Messages in this thread Patch in this message | | | Date | Sat, 07 Mar 1998 15:37:06 -0500 | From | Bill Hawes <> | Subject | patch for 2.1.89 file_struct |
| |
The attached patch splits the allocation of the files_struct into two parts and adds a max_fds field, in preparation for a variable-length fd[] array. Breaking the structure into two parts will help ease memory allocation problems on busy systems.
As soon as the remaining direct references to current->files->fd[] are suitably wrapped, I'll add the changes for a variable-length array.
I've been running the patch on my system for a while now with no problems.
Regards, Bill--- linux-2.1.89/include/linux/sched.h.old Sat Mar 7 11:40:57 1998 +++ linux-2.1.89/include/linux/sched.h Sat Mar 7 15:02:59 1998 @@ -113,19 +113,24 @@ asmlinkage void schedule(void); -/* Open file table structure */ + +/* + * Open file table structure + */ struct files_struct { int count; + int max_fds; + struct file ** fd; /* current fd array */ fd_set close_on_exec; fd_set open_fds; - struct file * fd[NR_OPEN]; }; #define INIT_FILES { \ 1, \ + NR_OPEN, \ + &init_fd_array[0], \ { { 0, } }, \ - { { 0, } }, \ - { NULL, } \ + { { 0, } } \ } struct fs_struct { @@ -571,19 +576,6 @@ extern int do_execve(char *, char **, char **, struct pt_regs *); extern int do_fork(unsigned long, unsigned long, struct pt_regs *); -/* See if we have a valid user level fd. - * If it makes sense, return the file structure it references. - * Otherwise return NULL. - */ -extern inline struct file *file_from_fd(const unsigned int fd) -{ - - if (fd >= NR_OPEN) - return NULL; - /* either valid or null */ - return current->files->fd[fd]; -} - /* * The wait-queues are circular lists, and you have to be *very* sure * to keep them correct. Use only these two functions to add/remove --- linux-2.1.89/kernel/fork.c.old Sat Mar 7 11:32:19 1998 +++ linux-2.1.89/kernel/fork.c Sat Mar 7 15:02:59 1998 @@ -375,44 +375,66 @@ return __copy_fdset(dst->fds_bits, src->fds_bits); } -static inline int copy_files(unsigned long clone_flags, struct task_struct * tsk) +static int copy_files(unsigned long clone_flags, struct task_struct * tsk) { - int i; struct files_struct *oldf, *newf; struct file **old_fds, **new_fds; + int size, i, error = 0; /* * A background process may not have any files ... */ oldf = current->files; if (!oldf) - return 0; + goto out; if (clone_flags & CLONE_FILES) { oldf->count++; - return 0; + goto out; } + tsk->files = NULL; + error = -ENOMEM; newf = kmem_cache_alloc(files_cachep, SLAB_KERNEL); - tsk->files = newf; if (!newf) - return -1; + goto out; + + /* + * Allocate the fd array, using get_free_page() if possible. + * Eventually we want to make the array size variable ... + */ + size = NR_OPEN * sizeof(struct file *); + if (size == PAGE_SIZE) + new_fds = (struct file **) __get_free_page(GFP_KERNEL); + else + new_fds = (struct file **) kmalloc(size, GFP_KERNEL); + if (!new_fds) + goto out_release; + memset((void *) new_fds, 0, size); newf->count = 1; + newf->max_fds = NR_OPEN; + newf->fd = new_fds; newf->close_on_exec = oldf->close_on_exec; - i = copy_fdset(&newf->open_fds,&oldf->open_fds); + i = copy_fdset(&newf->open_fds, &oldf->open_fds); old_fds = oldf->fd; - new_fds = newf->fd; for (; i != 0; i--) { struct file * f = *old_fds; old_fds++; *new_fds = f; - new_fds++; if (f) f->f_count++; + new_fds++; } - return 0; + tsk->files = newf; + error = 0; +out: + return error; + +out_release: + kmem_cache_free(files_cachep, newf); + goto out; } static inline int copy_sighand(unsigned long clone_flags, struct task_struct * tsk) --- linux-2.1.89/kernel/exit.c.old Sat Mar 7 11:32:19 1998 +++ linux-2.1.89/kernel/exit.c Sat Mar 7 15:02:59 1998 @@ -157,7 +157,7 @@ unsigned long set = files->open_fds.fds_bits[j]; i = j * __NFDBITS; j++; - if (i >= NR_OPEN) + if (i >= files->max_fds) break; while (set) { if (set & 1) { @@ -183,6 +183,13 @@ tsk->files = NULL; if (!--files->count) { close_files(files); + /* + * Free the fd array as appropriate ... + */ + if (NR_OPEN * sizeof(struct file *) == PAGE_SIZE) + free_page((unsigned long) files->fd); + else + kfree(files->fd); kmem_cache_free(files_cachep, files); } } --- linux-2.1.89/arch/i386/kernel/init_task.c.old Mon Dec 1 23:56:55 1997 +++ linux-2.1.89/arch/i386/kernel/init_task.c Sat Mar 7 15:02:59 1998 @@ -6,6 +6,7 @@ static struct vm_area_struct init_mmap = INIT_MMAP; static struct fs_struct init_fs = INIT_FS; +static struct files * init_fd_array[NR_OPEN] = { NULL, }; static struct files_struct init_files = INIT_FILES; static struct signal_struct init_signals = INIT_SIGNALS; struct mm_struct init_mm = INIT_MM; --- linux-2.1.89/arch/mips/kernel/init_task.c.old Thu Jun 26 15:33:37 1997 +++ linux-2.1.89/arch/mips/kernel/init_task.c Sat Mar 7 15:02:59 1998 @@ -5,6 +5,7 @@ static struct vm_area_struct init_mmap = INIT_MMAP; static struct fs_struct init_fs = INIT_FS; +static struct files * init_fd_array[NR_OPEN] = { NULL, }; static struct files_struct init_files = INIT_FILES; static struct signal_struct init_signals = INIT_SIGNALS; struct mm_struct init_mm = INIT_MM; --- linux-2.1.89/arch/arm/kernel/init_task.c.old Tue Jan 20 23:55:24 1998 +++ linux-2.1.89/arch/arm/kernel/init_task.c Sat Mar 7 15:02:59 1998 @@ -6,6 +6,7 @@ static struct vm_area_struct init_mmap = INIT_MMAP; static struct fs_struct init_fs = INIT_FS; +static struct files * init_fd_array[NR_OPEN] = { NULL, }; static struct files_struct init_files = INIT_FILES; static struct signal_struct init_signals = INIT_SIGNALS; struct mm_struct init_mm = INIT_MM; --- linux-2.1.89/arch/sparc/kernel/init_task.c.old Wed May 14 01:41:03 1997 +++ linux-2.1.89/arch/sparc/kernel/init_task.c Sat Mar 7 15:02:59 1998 @@ -6,6 +6,7 @@ static struct vm_area_struct init_mmap = INIT_MMAP; static struct fs_struct init_fs = INIT_FS; +static struct files * init_fd_array[NR_OPEN] = { NULL, }; static struct files_struct init_files = INIT_FILES; static struct signal_struct init_signals = INIT_SIGNALS; struct mm_struct init_mm = INIT_MM; --- linux-2.1.89/arch/sparc64/kernel/init_task.c.old Thu May 15 19:48:02 1997 +++ linux-2.1.89/arch/sparc64/kernel/init_task.c Sat Mar 7 15:02:59 1998 @@ -6,6 +6,7 @@ static struct vm_area_struct init_mmap = INIT_MMAP; static struct fs_struct init_fs = INIT_FS; +static struct files * init_fd_array[NR_OPEN] = { NULL, }; static struct files_struct init_files = INIT_FILES; static struct signal_struct init_signals = INIT_SIGNALS; struct mm_struct init_mm = INIT_MM; --- linux-2.1.89/arch/alpha/kernel/process.c.old Tue Jan 13 10:38:14 1998 +++ linux-2.1.89/arch/alpha/kernel/process.c Sat Mar 7 15:03:00 1998 @@ -50,6 +50,7 @@ unsigned long init_user_stack[1024] = { STACK_MAGIC, }; static struct vm_area_struct init_mmap = INIT_MMAP; static struct fs_struct init_fs = INIT_FS; +static struct files * init_fd_array[NR_OPEN] = { NULL, }; static struct files_struct init_files = INIT_FILES; static struct signal_struct init_signals = INIT_SIGNALS; struct mm_struct init_mm = INIT_MM; --- linux-2.1.89/arch/ppc/kernel/process.c.old Sat Feb 21 09:24:51 1998 +++ linux-2.1.89/arch/ppc/kernel/process.c Sat Mar 7 15:03:00 1998 @@ -64,6 +64,7 @@ static struct vm_area_struct init_mmap = INIT_MMAP; static struct fs_struct init_fs = INIT_FS; +static struct files * init_fd_array[NR_OPEN] = { NULL, }; static struct files_struct init_files = INIT_FILES; static struct signal_struct init_signals = INIT_SIGNALS; --- linux-2.1.89/arch/m68k/kernel/process.c.old Tue Feb 17 10:34:24 1998 +++ linux-2.1.89/arch/m68k/kernel/process.c Sat Mar 7 15:03:00 1998 @@ -40,6 +40,7 @@ */ static struct vm_area_struct init_mmap = INIT_MMAP; static struct fs_struct init_fs = INIT_FS; +static struct files * init_fd_array[NR_OPEN] = { NULL, }; static struct files_struct init_files = INIT_FILES; static struct signal_struct init_signals = INIT_SIGNALS; struct mm_struct init_mm = INIT_MM; | |