- Remove the private freelist.  There's no point in special-casing file
  structure allocations in this way.

- Hence the freeing of files can be moved outside file_list_lock()

- Replace euid test with capable(CAP_SYS_ADMIN).

- Tidy various other things up.


 fs/file_table.c |   68 ++++++++++++++++++++------------------------------------
 1 files changed, 25 insertions(+), 43 deletions(-)

diff -puN fs/file_table.c~file_list-remove-free_list fs/file_table.c
--- 25/fs/file_table.c~file_list-remove-free_list	2003-03-09 23:17:11.000000000 -0800
+++ 25-akpm/fs/file_table.c	2003-03-09 23:18:52.000000000 -0800
@@ -22,8 +22,6 @@ struct files_stat_struct files_stat = {
 	.max_files = NR_FILE
 };
 
-/* list of free filps for root */
-static LIST_HEAD(free_list);
 /* public *and* exported. Not pretty! */
 spinlock_t __cacheline_aligned_in_smp files_lock = SPIN_LOCK_UNLOCKED;
 
@@ -52,41 +50,34 @@ void filp_dtor(void * objp, struct kmem_
 	spin_unlock_irqrestore(&filp_count_lock, flags);
 }
 
-static inline void file_free(struct file* f)
+static inline void file_free(struct file *f)
 {
-	if (files_stat.nr_free_files <= NR_RESERVED_FILES) {
-		list_add(&f->f_list, &free_list);
-		files_stat.nr_free_files++;
-	} else {
-		kmem_cache_free(filp_cachep, f);
-	}
+	kmem_cache_free(filp_cachep, f);
 }
 
 /* Find an unused file structure and return a pointer to it.
  * Returns NULL, if there are no more free file structures or
  * we run out of memory.
- *
- * SMP-safe.
  */
-struct file * get_empty_filp(void)
+struct file *get_empty_filp(void)
 {
 static int old_max = 0;
 	struct file * f;
 
-	if (likely(files_stat.nr_files < files_stat.max_files)) {
+	/*
+	 * Privileged users can go above max_files
+	 */
+	if (files_stat.nr_files < files_stat.max_files ||
+				capable(CAP_SYS_ADMIN)) {
 		f = kmem_cache_alloc(filp_cachep, GFP_KERNEL);
 		if (f) {
-got_one:
 			memset(f, 0, sizeof(*f));
 			if (security_file_alloc(f)) {
-				file_list_lock();
 				file_free(f);
-				file_list_unlock();
-
-				return NULL;
+				goto fail;
 			}
 			eventpoll_init_file(f);
-			atomic_set(&f->f_count,1);
+			atomic_set(&f->f_count, 1);
 			f->f_uid = current->fsuid;
 			f->f_gid = current->fsgid;
 			f->f_owner.lock = RW_LOCK_UNLOCKED;
@@ -95,24 +86,17 @@ got_one:
 			return f;
 		}
 	}
-	/* Use a reserved one if we're the superuser */
-	file_list_lock();
-	if (files_stat.nr_free_files && !current->euid) {
-		f = list_entry(free_list.next, struct file, f_list);
-		list_del(&f->f_list);
-		files_stat.nr_free_files--;
-		file_list_unlock();
-		goto got_one;
-	}
-	file_list_unlock();
+
 	/* Ran out of filps - report that */
-	if (files_stat.max_files > old_max) {
-		printk(KERN_INFO "VFS: file-max limit %d reached\n", files_stat.max_files);
+	if (files_stat.max_files >= old_max) {
+		printk(KERN_INFO "VFS: file-max limit %d reached\n",
+					files_stat.max_files);
 		old_max = files_stat.max_files;
 	} else {
 		/* Big problems... */
 		printk(KERN_WARNING "VFS: filp allocation failed\n");
 	}
+fail:
 	return NULL;
 }
 
@@ -147,11 +131,11 @@ void fput(struct file * file)
 /* __fput is called from task context when aio completion releases the last
  * last use of a struct file *.  Do not use otherwise.
  */
-void __fput(struct file * file)
+void __fput(struct file *file)
 {
-	struct dentry * dentry = file->f_dentry;
-	struct vfsmount * mnt = file->f_vfsmnt;
-	struct inode * inode = dentry->d_inode;
+	struct dentry *dentry = file->f_dentry;
+	struct vfsmount *mnt = file->f_vfsmnt;
+	struct inode *inode = dentry->d_inode;
 
 	/*
 	 * The function eventpoll_release() should be the first called
@@ -170,15 +154,15 @@ void __fput(struct file * file)
 	file->f_dentry = NULL;
 	file->f_vfsmnt = NULL;
 	list_del(&file->f_list);
-	file_free(file);
 	file_list_unlock();
+	file_free(file);
 	dput(dentry);
 	mntput(mnt);
 }
 
-struct file * fget(unsigned int fd)
+struct file *fget(unsigned int fd)
 {
-	struct file * file;
+	struct file *file;
 	struct files_struct *files = current->files;
 
 	read_lock(&files->file_lock);
@@ -189,16 +173,14 @@ struct file * fget(unsigned int fd)
 	return file;
 }
 
-/* Here. put_filp() is SMP-safe now. */
-
 void put_filp(struct file *file)
 {
-	if(atomic_dec_and_test(&file->f_count)) {
+	if (atomic_dec_and_test(&file->f_count)) {
 		security_file_free(file);
 		file_list_lock();
 		list_del(&file->f_list);
-		file_free(file);
 		file_list_unlock();
+		file_free(file);
 	}
 }
 
@@ -232,7 +214,7 @@ int fs_may_remount_ro(struct super_block
 		if (inode->i_nlink == 0)
 			goto too_bad;
 
-		/* Writable file? */
+		/* Writeable file? */
 		if (S_ISREG(inode->i_mode) && (file->f_mode & FMODE_WRITE))
 			goto too_bad;
 	}

_