use kmalloc() to allocate fdmem if possible. vmalloc() is used as a fallback solution for fdmem allocation. Two members are added into the hole of the structure fdtable to indicate if vmalloc() is used or not. Signed-off-by: Changli Gao <xiaosuo@xxxxxxxxx> ---- fs/file.c | 33 ++++++++++++++++++++------------- include/linux/fdtable.h | 2 ++ 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/fs/file.c b/fs/file.c index 34bb7f7..f71dd85 100644 --- a/fs/file.c +++ b/fs/file.c @@ -39,28 +39,34 @@ int sysctl_nr_open_max = 1024 * 1024; /* raised later */ */ static DEFINE_PER_CPU(struct fdtable_defer, fdtable_defer_list); -static inline void * alloc_fdmem(unsigned int size) +static inline void *alloc_fdmem(unsigned int size, unsigned short *use_vmalloc) { - if (size <= PAGE_SIZE) - return kmalloc(size, GFP_KERNEL); - else - return vmalloc(size); + void *data; + + data = kmalloc(size, GFP_KERNEL); + if (data != NULL) { + *use_vmalloc = 0; + return data; + } + *use_vmalloc = 1; + + return vmalloc(size); } static inline void free_fdarr(struct fdtable *fdt) { - if (fdt->max_fds <= (PAGE_SIZE / sizeof(struct file *))) - kfree(fdt->fd); - else + if (fdt->fdarr_vmalloc) vfree(fdt->fd); + else + kfree(fdt->fd); } static inline void free_fdset(struct fdtable *fdt) { - if (fdt->max_fds <= (PAGE_SIZE * BITS_PER_BYTE / 2)) - kfree(fdt->open_fds); - else + if (fdt->fdset_vmalloc) vfree(fdt->open_fds); + else + kfree(fdt->open_fds); } static void free_fdtable_work(struct work_struct *work) @@ -167,12 +173,13 @@ static struct fdtable * alloc_fdtable(unsigned int nr) if (!fdt) goto out; fdt->max_fds = nr; - data = alloc_fdmem(nr * sizeof(struct file *)); + data = alloc_fdmem(nr * sizeof(struct file *), &fdt->fdarr_vmalloc); if (!data) goto out_fdt; fdt->fd = (struct file **)data; data = alloc_fdmem(max_t(unsigned int, - 2 * nr / BITS_PER_BYTE, L1_CACHE_BYTES)); + 2 * nr / BITS_PER_BYTE, L1_CACHE_BYTES), + &fdt->fdset_vmalloc); if (!data) goto out_arr; fdt->open_fds = (fd_set *)data; diff --git a/include/linux/fdtable.h b/include/linux/fdtable.h index 013dc52..1e730bc 100644 --- a/include/linux/fdtable.h +++ b/include/linux/fdtable.h @@ -30,6 +30,8 @@ struct embedded_fd_set { struct fdtable { unsigned int max_fds; + unsigned short fdarr_vmalloc; + unsigned short fdset_vmalloc; struct file ** fd; /* current fd array */ fd_set *close_on_exec; fd_set *open_fds; -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html