From 946ed969262f7227681788b75f84d872aa3e04f9 Mon Sep 17 00:00:00 2001 From: buxiasen Date: Fri, 14 Jun 2024 11:56:13 +0800 Subject: [PATCH] fs: add fs_heap, support shm/tmpfs/pseudofile with indepent heap For some case, need large files from tmpfs or shmfs, will lead to high pressure on memory fragments, add an optional fs_heap with independent heap will benifit for memory fragments issue. Signed-off-by: buxiasen --- fs/CMakeLists.txt | 2 +- fs/Kconfig | 8 +++++ fs/Makefile | 2 +- fs/fs_heap.c | 66 ++++++++++++++++++++++++++++++++++++++++++ fs/fs_heap.h | 50 ++++++++++++++++++++++++++++++++ fs/fs_initialize.c | 3 ++ fs/shm/shmfs_alloc.c | 5 ++-- fs/tmpfs/fs_tmpfs.c | 55 ++++++++++++++++++----------------- fs/vfs/fs_pseudofile.c | 17 ++++++----- 9 files changed, 169 insertions(+), 39 deletions(-) create mode 100644 fs/fs_heap.c create mode 100644 fs/fs_heap.h diff --git a/fs/CMakeLists.txt b/fs/CMakeLists.txt index cc876d4c17..ef2401dbec 100644 --- a/fs/CMakeLists.txt +++ b/fs/CMakeLists.txt @@ -17,7 +17,7 @@ # the License. # # ############################################################################## -nuttx_add_kernel_library(fs fs_initialize.c) +nuttx_add_kernel_library(fs fs_initialize.c fs_heap.c) nuttx_add_subdirectory() target_include_directories(fs PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${NUTTX_DIR}/sched) diff --git a/fs/Kconfig b/fs/Kconfig index 3485a1878d..b34ffa4325 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -111,6 +111,14 @@ config SENDFILE_BUFSIZE ---help--- Size of the I/O buffer to allocate in sendfile(). Default: 512b +config FS_HEAPSIZE + int "Independent heap bytes used by shm/tmpfs/pseudofile" + default 0 + depends on FS_SHMFS || FS_TMPFS || PSEUDOFS_FILE + ---help--- + Support for shm/tmpfs/fs_pseudofile.c ram based fs memory. + default 0 to use kmm directly. independent heap disabled + source "fs/vfs/Kconfig" source "fs/aio/Kconfig" source "fs/semaphore/Kconfig" diff --git a/fs/Makefile b/fs/Makefile index d18a339973..050ec8d743 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -20,7 +20,7 @@ include $(TOPDIR)/Make.defs -CSRCS = fs_initialize.c +CSRCS = fs_initialize.c fs_heap.c include inode/Make.defs include vfs/Make.defs diff --git a/fs/fs_heap.c b/fs/fs_heap.c new file mode 100644 index 0000000000..1de10e3fb1 --- /dev/null +++ b/fs/fs_heap.c @@ -0,0 +1,66 @@ +/**************************************************************************** + * fs/fs_heap.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "fs_heap.h" + +#if defined(CONFIG_FS_HEAPSIZE) && CONFIG_FS_HEAPSIZE > 0 + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static FAR struct mm_heap_s *g_fs_heap; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +void fs_heap_initialize(void) +{ + FAR void *buf = kmm_malloc(CONFIG_FS_HEAPSIZE); + DEBUGASSERT(buf != NULL); + g_fs_heap = mm_initialize("heapfs", buf, CONFIG_FS_HEAPSIZE); +} + +FAR void *fs_heap_zalloc(size_t size) +{ + return mm_zalloc(g_fs_heap, size); +} + +size_t fs_heap_malloc_size(FAR void *mem) +{ + return mm_malloc_size(g_fs_heap, mem); +} + +FAR void *fs_heap_realloc(FAR void *oldmem, size_t size) +{ + return mm_realloc(g_fs_heap, oldmem, size); +} + +void fs_heap_free(FAR void *mem) +{ + mm_free(g_fs_heap, mem); +} + +#endif diff --git a/fs/fs_heap.h b/fs/fs_heap.h new file mode 100644 index 0000000000..2ed359b1ba --- /dev/null +++ b/fs/fs_heap.h @@ -0,0 +1,50 @@ +/**************************************************************************** + * fs/fs_heap.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __FS_FS_HEAP_H +#define __FS_FS_HEAP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#if defined(CONFIG_FS_HEAPSIZE) && CONFIG_FS_HEAPSIZE > 0 +void fs_heap_initialize(void); +FAR void *fs_heap_zalloc(size_t size); +size_t fs_heap_malloc_size(FAR void *mem); +FAR void *fs_heap_realloc(FAR void *oldmem, size_t size); +void fs_heap_free(FAR void *mem); +#else +# define fs_heap_initialize() +# define fs_heap_zalloc kmm_zalloc +# define fs_heap_malloc_size kmm_malloc_size +# define fs_heap_realloc kmm_realloc +# define fs_heap_free kmm_free +#endif + +#endif diff --git a/fs/fs_initialize.c b/fs/fs_initialize.c index 4424711196..d82753920b 100644 --- a/fs/fs_initialize.c +++ b/fs/fs_initialize.c @@ -31,6 +31,7 @@ #include "inode/inode.h" #include "aio/aio.h" #include "vfs/lock.h" +#include "fs_heap.h" /**************************************************************************** * Private Functions @@ -81,6 +82,8 @@ void fs_initialize(void) { fs_trace_begin(); + fs_heap_initialize(); + /* Initial inode, file, and VFS data structures */ inode_initialize(); diff --git a/fs/shm/shmfs_alloc.c b/fs/shm/shmfs_alloc.c index 05a0f540b1..971f96831e 100644 --- a/fs/shm/shmfs_alloc.c +++ b/fs/shm/shmfs_alloc.c @@ -31,6 +31,7 @@ #include #include "shm/shmfs.h" +#include "fs_heap.h" /**************************************************************************** * Public Functions @@ -54,7 +55,7 @@ FAR struct shmfs_object_s *shmfs_alloc_object(size_t length) return NULL; } - object = kmm_zalloc(alloc_size); + object = fs_heap_zalloc(alloc_size); if (object) { object->paddr = (FAR char *)(object + 1); @@ -156,6 +157,6 @@ void shmfs_free_object(FAR struct shmfs_object_s *object) * (and the shared memory in case of FLAT build) */ - kmm_free(object); + fs_heap_free(object); } } diff --git a/fs/tmpfs/fs_tmpfs.c b/fs/tmpfs/fs_tmpfs.c index 83d73425a0..2e4dc5a91d 100644 --- a/fs/tmpfs/fs_tmpfs.c +++ b/fs/tmpfs/fs_tmpfs.c @@ -39,6 +39,7 @@ #include "inode/inode.h" #include "fs_tmpfs.h" +#include "fs_heap.h" #ifndef CONFIG_DISABLE_MOUNTPOINT @@ -245,7 +246,7 @@ static int tmpfs_realloc_directory(FAR struct tmpfs_directory_s *tdo, /* Realloc the directory object */ - newentry = kmm_realloc(tdo->tdo_entry, objsize); + newentry = fs_heap_realloc(tdo->tdo_entry, objsize); if (newentry == NULL) { return -ENOMEM; @@ -285,7 +286,7 @@ static int tmpfs_realloc_file(FAR struct tmpfs_file_s *tfo, { /* Free the file object */ - kmm_free(tfo->tfo_data); + fs_heap_free(tfo->tfo_data); tfo->tfo_data = NULL; tfo->tfo_alloc = 0; tfo->tfo_size = 0; @@ -326,7 +327,7 @@ static int tmpfs_realloc_file(FAR struct tmpfs_file_s *tfo, /* Realloc the file object */ - newdata = kmm_realloc(tfo->tfo_data, allocsize); + newdata = fs_heap_realloc(tfo->tfo_data, allocsize); if (newdata == NULL) { return -ENOMEM; @@ -377,8 +378,8 @@ static void tmpfs_release_lockedfile(FAR struct tmpfs_file_s *tfo) { tmpfs_unlock_file(tfo); nxrmutex_destroy(&tfo->tfo_lock); - kmm_free(tfo->tfo_data); - kmm_free(tfo); + fs_heap_free(tfo->tfo_data); + fs_heap_free(tfo); } /* Otherwise, just decrement the reference count on the file object */ @@ -470,7 +471,7 @@ static int tmpfs_remove_dirent(FAR struct tmpfs_directory_s *tdo, if (tdo->tdo_entry[index].tde_name != NULL) { - kmm_free(tdo->tdo_entry[index].tde_name); + lib_free(tdo->tdo_entry[index].tde_name); } /* Remove by replacing this entry with the final directory entry */ @@ -535,7 +536,7 @@ static int tmpfs_add_dirent(FAR struct tmpfs_directory_s *tdo, index = tmpfs_realloc_directory(tdo, nentries); if (index < 0) { - kmm_free(newname); + fs_heap_free(newname); return index; } @@ -560,7 +561,7 @@ tmpfs_alloc_file(FAR struct tmpfs_directory_s *parent) /* Create a new zero length file object */ - tfo = kmm_malloc(sizeof(*tfo)); + tfo = fs_heap_zalloc(sizeof(*tfo)); if (tfo == NULL) { return NULL; @@ -693,7 +694,7 @@ static int tmpfs_create_file(FAR struct tmpfs_s *fs, errout_with_file: nxrmutex_destroy(&newtfo->tfo_lock); - kmm_free(newtfo); + fs_heap_free(newtfo); errout_with_parent: parent->tdo_refs--; @@ -712,7 +713,7 @@ tmpfs_alloc_directory(FAR struct tmpfs_directory_s *parent) /* Create a new zero length directory object */ - tdo = kmm_malloc(sizeof(*tdo)); + tdo = fs_heap_zalloc(sizeof(*tdo)); if (tdo == NULL) { return NULL; @@ -846,7 +847,7 @@ static int tmpfs_create_directory(FAR struct tmpfs_s *fs, errout_with_directory: nxrmutex_destroy(&newtdo->tdo_lock); - kmm_free(newtdo); + fs_heap_free(newtdo); errout_with_parent: parent->tdo_refs--; @@ -1215,7 +1216,7 @@ static int tmpfs_free_callout(FAR struct tmpfs_directory_s *tdo, if (tdo->tdo_entry[index].tde_name != NULL) { - kmm_free(tdo->tdo_entry[index].tde_name); + lib_free(tdo->tdo_entry[index].tde_name); } /* Remove by replacing this entry with the final directory entry */ @@ -1251,19 +1252,19 @@ static int tmpfs_free_callout(FAR struct tmpfs_directory_s *tdo, return TMPFS_UNLINKED; } - kmm_free(tfo->tfo_data); + fs_heap_free(tfo->tfo_data); } else /* if (to->to_type == TMPFS_DIRECTORY) */ { tdo = (FAR struct tmpfs_directory_s *)to; - kmm_free(tdo->tdo_entry); + fs_heap_free(tdo->tdo_entry); } /* Free the object now */ nxrmutex_destroy(&to->to_lock); - kmm_free(to); + fs_heap_free(to); return TMPFS_DELETED; } @@ -1995,7 +1996,7 @@ static int tmpfs_opendir(FAR struct inode *mountpt, FAR const char *relpath, fs = mountpt->i_private; DEBUGASSERT(fs != NULL && fs->tfs_root.tde_object != NULL); - tdir = kmm_zalloc(sizeof(*tdir)); + tdir = fs_heap_zalloc(sizeof(*tdir)); if (tdir == NULL) { return -ENOMEM; @@ -2006,7 +2007,7 @@ static int tmpfs_opendir(FAR struct inode *mountpt, FAR const char *relpath, ret = tmpfs_lock(fs); if (ret < 0) { - kmm_free(tdir); + fs_heap_free(tdir); return ret; } @@ -2059,7 +2060,7 @@ static int tmpfs_closedir(FAR struct inode *mountpt, tmpfs_lock_directory(tdo); tdo->tdo_refs--; tmpfs_unlock_directory(tdo); - kmm_free(dir); + fs_heap_free(dir); return OK; } @@ -2177,7 +2178,7 @@ static int tmpfs_bind(FAR struct inode *blkdriver, FAR const void *data, /* Create an instance of the tmpfs file system */ - fs = kmm_zalloc(sizeof(struct tmpfs_s)); + fs = fs_heap_zalloc(sizeof(struct tmpfs_s)); if (fs == NULL) { return -ENOMEM; @@ -2190,7 +2191,7 @@ static int tmpfs_bind(FAR struct inode *blkdriver, FAR const void *data, tdo = tmpfs_alloc_directory(NULL); if (tdo == NULL) { - kmm_free(fs); + fs_heap_free(fs); return -ENOMEM; } @@ -2238,11 +2239,11 @@ static int tmpfs_unbind(FAR void *handle, FAR struct inode **blkdriver, /* Now we can destroy the root file system and the file system itself. */ nxrmutex_destroy(&tdo->tdo_lock); - kmm_free(tdo->tdo_entry); - kmm_free(tdo); + fs_heap_free(tdo->tdo_entry); + fs_heap_free(tdo); nxrmutex_destroy(&fs->tfs_lock); - kmm_free(fs); + fs_heap_free(fs); return ret; } @@ -2405,8 +2406,8 @@ static int tmpfs_unlink(FAR struct inode *mountpt, FAR const char *relpath) else { nxrmutex_destroy(&tfo->tfo_lock); - kmm_free(tfo->tfo_data); - kmm_free(tfo); + fs_heap_free(tfo->tfo_data); + fs_heap_free(tfo); } /* Release the reference and lock on the parent directory */ @@ -2547,8 +2548,8 @@ static int tmpfs_rmdir(FAR struct inode *mountpt, FAR const char *relpath) /* Free the directory object */ nxrmutex_destroy(&tdo->tdo_lock); - kmm_free(tdo->tdo_entry); - kmm_free(tdo); + fs_heap_free(tdo->tdo_entry); + fs_heap_free(tdo); /* Release the reference and lock on the parent directory */ diff --git a/fs/vfs/fs_pseudofile.c b/fs/vfs/fs_pseudofile.c index a45d2875a8..23890ef0bf 100644 --- a/fs/vfs/fs_pseudofile.c +++ b/fs/vfs/fs_pseudofile.c @@ -38,6 +38,7 @@ #include "inode/inode.h" #include "notify/notify.h" +#include "fs_heap.h" /**************************************************************************** * Private Types @@ -133,8 +134,8 @@ static void pseudofile_remove(FAR struct fs_pseudofile_s *pf) { nxmutex_unlock(&pf->lock); nxmutex_destroy(&pf->lock); - kmm_free(pf->content); - kmm_free(pf); + fs_heap_free(pf->content); + fs_heap_free(pf); } static int pseudofile_close(FAR struct file *filep) @@ -170,13 +171,13 @@ static int pseudofile_expand(FAR struct inode *node, FAR struct fs_pseudofile_s *pf = node->i_private; FAR void *tmp; - if (pf->content && kmm_malloc_size(pf->content) >= size) + if (pf->content && fs_heap_malloc_size(pf->content) >= size) { node->i_size = size; return 0; } - tmp = kmm_realloc(pf->content, 1 << LOG2_CEIL(size)); + tmp = fs_heap_realloc(pf->content, 1 << LOG2_CEIL(size)); if (tmp == NULL) { return -ENOMEM; @@ -362,7 +363,7 @@ static int pseudofile_munmap(FAR struct task_group_s *group, if (inode->i_private) { - kmm_free(inode->i_private); + fs_heap_free(inode->i_private); } inode->i_private = NULL; @@ -402,7 +403,7 @@ static int pseudofile_truncate(FAR struct file *filep, off_t length) { FAR void *tmp; - tmp = kmm_realloc(pf->content, length); + tmp = fs_heap_realloc(pf->content, length); if (tmp == NULL) { ret = -ENOMEM; @@ -480,7 +481,7 @@ int pseudofile_create(FAR struct inode **node, FAR const char *path, return -EINVAL; } - pf = kmm_zalloc(sizeof(struct fs_pseudofile_s)); + pf = fs_heap_zalloc(sizeof(struct fs_pseudofile_s)); if (pf == NULL) { return -ENOMEM; @@ -515,7 +516,7 @@ reserve_err: inode_unlock(); lock_err: nxmutex_destroy(&pf->lock); - kmm_free(pf); + fs_heap_free(pf); return ret; }