lkml.org 
[lkml]   [1998]   [Feb]   [26]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
Subjectpatch for 2.1.88 files_struct fd array
I've attached a preliminary patch to provide separate allocation of the fd array
in the files_struct, as suggested by Mark Hemment a while back. The eventual
goal is to use a variable-sized array with dynamic expansion, but the present
kernel still has many places that assume the fd array has a fixed NR_OPEN slots.
The current patch allocates the fd array using get_free_page() provided that the
array size (NR_OPEN*sizeof struct file *) is PAGE_SIZE; otherwise it uses
kmalloc.

We had a discussion on the kernel-list a while back on the importance of
revising the current files_struct, as its size is extremely awkward for memory
allocation, requiring high page orders for the slab. Most of the memory space is
wasted as well, since only a few processes ever need anything approaching
NR_OPEN files. The present patch doesn't fix the wasted space problem, but once
the remaining accesses to the fd array are suitably wrapped it won't be too hard
to make the fd array dynamic.

The patch includes changes for all the architectures, but only i386 has been
tested. Suggestions and comments welcome ...

Regards,
Bill--- linux-2.1.88/include/linux/sched.h.old Wed Feb 25 10:20:57 1998
+++ linux-2.1.88/include/linux/sched.h Thu Feb 26 12:38:33 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 {
--- linux-2.1.88/kernel/fork.c.old Sat Jan 24 10:13:19 1998
+++ linux-2.1.88/kernel/fork.c Thu Feb 26 15:16:41 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.88/kernel/exit.c.old Tue Jan 13 10:38:36 1998
+++ linux-2.1.88/kernel/exit.c Thu Feb 26 13:30:56 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.88/arch/i386/kernel/init_task.c.old Mon Dec 1 23:56:55 1997
+++ linux-2.1.88/arch/i386/kernel/init_task.c Thu Feb 26 00:09:21 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.88/arch/mips/kernel/init_task.c.old Thu Jun 26 15:33:37 1997
+++ linux-2.1.88/arch/mips/kernel/init_task.c Thu Feb 26 15:45:22 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.88/arch/arm/kernel/init_task.c.old Tue Jan 20 23:55:24 1998
+++ linux-2.1.88/arch/arm/kernel/init_task.c Thu Feb 26 15:47:41 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.88/arch/sparc/kernel/init_task.c.old Wed May 14 01:41:03 1997
+++ linux-2.1.88/arch/sparc/kernel/init_task.c Thu Feb 26 15:46:13 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.88/arch/sparc64/kernel/init_task.c.old Thu May 15 19:48:02 1997
+++ linux-2.1.88/arch/sparc64/kernel/init_task.c Thu Feb 26 15:46:54 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.88/arch/alpha/kernel/process.c.old Tue Jan 13 10:38:14 1998
+++ linux-2.1.88/arch/alpha/kernel/process.c Thu Feb 26 15:43:01 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.88/arch/ppc/kernel/process.c.old Sat Feb 21 09:24:51 1998
+++ linux-2.1.88/arch/ppc/kernel/process.c Thu Feb 26 15:44:08 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.88/arch/m68k/kernel/process.c.old Tue Feb 17 10:34:24 1998
+++ linux-2.1.88/arch/m68k/kernel/process.c Thu Feb 26 15:51:05 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;
\
 
 \ /
  Last update: 2005-03-22 13:41    [W:0.343 / U:1.304 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site