Re: Kernel profile

Johnny Stenback (jst@uwasa.fi)
Fri, 2 Aug 1996 04:14:13 +0300 (EET DST)


Hi!

Here's a patch I made that changes the get_empty_filp function to walk
the file table list in both directions while it searches for an empty
structure. This patch is otherwise the same as the patch posted a few
days ago by Michael O'Reilly (ie uses a static pointer so that a
search starts where the last ended...). The fact that it walks the
list in both directions of-course makes the walk a bit slower
(even-though it only walks half the way) but IMO it might give better
over all performance (I don't know because I newer got my home
computer to uses get_empty_filp intensively, when I turned on
profiling I saw that it is much faster than the original search but I
don't know if it's faster or slower than Michaels patch, anyone know
how to stress-test this or anyone wants test this on a computer that
has shown to use much time in get_empty_filp and show us some
results...).

This is the first patch I've ever made to the linux kernel so I hope
it doesn't do something stupid, I know that it works for me (in 2
computers) but that doesn't say much...

PS. This patch also makes a few changes in other functions but they
shouldn't affect what the function does at all, it only makes them
easier to read and understand IMO.

--- linux/fs/file_table.c.jst Wed Jul 31 16:43:13 1996
+++ linux/fs/file_table.c Fri Aug 2 03:22:11 1996
@@ -26,7 +26,7 @@
file->f_count = 0;
file->f_next = first_file;
file->f_prev = first_file->f_prev;
- file->f_next->f_prev = file;
+ first_file->f_prev = file;
file->f_prev->f_next = file;
first_file = file;
}
@@ -51,7 +51,7 @@
file->f_prev = first_file->f_prev;
file->f_prev->f_next = file;
file->f_next = first_file;
- file->f_next->f_prev = file;
+ first_file->f_prev = file;
}

/*
@@ -100,9 +100,8 @@
*/
struct file * get_empty_filp(void)
{
- int i;
- int max = max_files;
- struct file * f;
+ static struct file *f;
+ int i, max = max_files;

/*
* Reserve a few files for the super-user..
@@ -111,19 +110,33 @@
max -= 10;

/* if the return is taken, we are in deep trouble */
- if (!first_file && !grow_files())
- return NULL;
+ if (!first_file) {
+ if (!grow_files())
+ return NULL;
+ f = first_file;
+ }

do {
- for (f = first_file, i=0; i < nr_files; i++, f = f->f_next)
- if (!f->f_count) {
- remove_file_free(f);
- memset(f,0,sizeof(*f));
- put_last_free(f);
+ struct file *g = f->f_prev;
+
+ for (i = 0; i <= (nr_files >> 1); i++) {
+ if (!f->f_count || (!g->f_count && (f = g))) {
+ f->f_mode = f->f_pos = f->f_flags =
+ f->f_reada = f->f_ramax = f->f_raend =
+ f->f_ralen = f->f_rawin = f->f_owner = 0;
+
+ f->private_data = NULL;
+ f->f_op = NULL;
+ f->f_inode = NULL;
+
f->f_count = 1;
f->f_version = ++event;
+
return f;
}
+ f = f->f_next;
+ g = g->f_prev;
+ }
} while (nr_files < max && grow_files());

return NULL;
@@ -133,30 +146,30 @@

void add_dquot_ref(kdev_t dev, short type)
{
- struct file *filp;
+ struct file *f;
int cnt;

- for (filp = first_file, cnt = 0; cnt < nr_files; cnt++, filp = filp->f_next) {
- if (!filp->f_count || !filp->f_inode || filp->f_inode->i_dev != dev)
+ for (f = first_file, cnt = 0; cnt < nr_files; cnt++, f = f->f_next) {
+ if (!f->f_count || !f->f_inode || f->f_inode->i_dev != dev)
continue;
- if (filp->f_mode & FMODE_WRITE && filp->f_inode->i_sb->dq_op) {
- filp->f_inode->i_sb->dq_op->initialize(filp->f_inode, type);
- filp->f_inode->i_flags |= S_WRITE;
+ if (f->f_mode & FMODE_WRITE && f->f_inode->i_sb->dq_op) {
+ f->f_inode->i_sb->dq_op->initialize(f->f_inode, type);
+ f->f_inode->i_flags |= S_WRITE;
}
}
}

void reset_dquot_ptrs(kdev_t dev, short type)
{
- struct file *filp;
+ struct file *f;
int cnt;

- for (filp = first_file, cnt = 0; cnt < nr_files; cnt++, filp = filp->f_next) {
- if (!filp->f_count || !filp->f_inode || filp->f_inode->i_dev != dev)
+ for (f = first_file, cnt = 0; cnt < nr_files; cnt++, f = f->f_next) {
+ if (!f->f_count || !f->f_inode || f->f_inode->i_dev != dev)
continue;
- if (IS_WRITABLE(filp->f_inode)) {
- filp->f_inode->i_dquot[type] = NODQUOT;
- filp->f_inode->i_flags &= ~S_WRITE;
+ if (IS_WRITABLE(f->f_inode)) {
+ f->f_inode->i_dquot[type] = NODQUOT;
+ f->f_inode->i_flags &= ~S_WRITE;
}
}
}

--
Johnny Stenback, programmer / University of Vaasa, Computer Centre 
E-Mail jst@uwasa.fi, Phone +358 61 3248 387, +358 50 5575 094