patch-2.1.58 linux/fs/file_table.c

Next file: linux/fs/lockd/clntproc.c
Previous file: linux/fs/dcache.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.57/linux/fs/file_table.c linux/fs/file_table.c
@@ -18,8 +18,9 @@
 static kmem_cache_t *filp_cache;
 
 /* sysctl tunables... */
-int nr_files = 0;
-int max_files = NR_FILE;
+int nr_files = 0;	/* read only */
+int nr_free_files = 0;	/* read only */
+int max_files = NR_FILE;/* tunable */
 
 /* Free list management, if you are here you must have f_count == 0 */
 static struct file * free_filps = NULL;
@@ -30,6 +31,7 @@
 		free_filps->f_pprev = &file->f_next;
 	free_filps = file;
 	file->f_pprev = &free_filps;
+	nr_free_files++;
 }
 
 /* The list of in-use filp's must be exported (ugh...) */
@@ -43,6 +45,7 @@
 	file->f_pprev = &inuse_filps;
 }
 
+/* N.B. This should be an __initfunc ... */
 void file_table_init(void)
 {
 	filp_cache = kmem_cache_create("filp", sizeof(struct file),
@@ -50,6 +53,11 @@
 				       SLAB_HWCACHE_ALIGN, NULL, NULL);
 	if(!filp_cache)
 		panic("VFS: Cannot alloc filp SLAB cache.");
+	/*
+	 * We could allocate the reserved files here, but really
+	 * shouldn't need to: the normal boot process will create
+	 * plenty of free files.
+	 */
 }
 
 /* Find an unused file structure and return a pointer to it.
@@ -61,24 +69,31 @@
 	static int old_max = 0;
 	struct file * f;
 
-	f = free_filps;
-	if (!f) 
-		goto get_more;
-	remove_filp(f);
-got_one:
-	memset(f, 0, sizeof(*f));
-	f->f_count = 1;
-	f->f_version = ++event;
-	put_inuse(f);
-	return f;
-
-get_more:
-	/* Reserve a few files for the super-user.. */
-	if (nr_files < (current->euid ? max_files - 10 : max_files)) {
+	if (nr_free_files > NR_RESERVED_FILES) {
+	used_one:
+		f = free_filps;
+		remove_filp(f);
+		nr_free_files--;
+	new_one:
+		memset(f, 0, sizeof(*f));
+		f->f_count = 1;
+		f->f_version = ++event;
+		put_inuse(f);
+		return f;
+	}
+	/*
+	 * Use a reserved one if we're the superuser
+	 */
+	if (nr_free_files && !current->euid)
+		goto used_one;
+	/*
+	 * Allocate a new one if we're below the limit.
+	 */
+	if (nr_files < max_files) {
 		f = kmem_cache_alloc(filp_cache, SLAB_KERNEL);
 		if (f) {
 			nr_files++;
-			goto got_one;
+			goto new_one;
 		}
 		/* Big problems... */
 		printk("VFS: filp allocation failed\n");

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov