Linux Headquarters
[ Register ]
[ About us ] [ Home Page ]

Advertisement
[ Kernel ] [ Documentation ] [ Links ] [ Books ]

Advertisement

Kernel v2.6.26-rc1 /fs/file_table.c

Filename:/fs/file_table.c
Lines Added:41
Lines Deleted:2
Also changed in: (Previous) 2.6.25-git20  2.6.25-git19  2.6.25-git18  2.6.25-git17  2.6.25-git16  2.6.25-git15 
(Following) 2.6.26-rc2  2.6.26-rc3  2.6.26-rc4  2.6.26-rc5  2.6.26-rc6  2.6.26-rc7 

Location
[  2.6.26-rc1
  [  fs
     o  file_table.c

Patch

diff --git a/fs/file_table.c b/fs/file_table.c
index 986ff4e..8308422 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -8,6 +8,7 @@
 #include <linux/string.h>
 #include <linux/slab.h>
 #include <linux/file.h>
+#include <linux/fdtable.h>
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/fs.h>
@@ -42,6 +43,7 @@ static inline void file_free_rcu(struct rcu_head *head)
 static inline void file_free(struct file *f)
 {
    percpu_counter_dec(&nr_files);
+   file_check_state(f);
    call_rcu(&f->f_u.fu_rcuhead, file_free_rcu);
 }
 
@@ -199,6 +201,18 @@ int init_file(struct file *file, struct vfsmount *mnt, struct dentry *dentry,
    file->f_mapping = dentry->d_inode->i_mapping;
    file->f_mode = mode;
    file->f_op = fop;
+
+   /*
+    * These mounts don't really matter in practice
+    * for r/o bind mounts.  They aren't userspace-
+    * visible.  We do this for consistency, and so
+    * that we can do debugging checks at __fput()
+    */
+   if ((mode & FMODE_WRITE) && !special_file(dentry->d_inode->i_mode)) {
+      file_take_write(file);
+      error = mnt_want_write(mnt);
+      WARN_ON(error);
+   }
    return error;
 }
 EXPORT_SYMBOL(init_file);
@@ -211,6 +225,31 @@ void fput(struct file *file)
 
 EXPORT_SYMBOL(fput);
 
+/**
+ * drop_file_write_access - give up ability to write to a file
+ * @file: the file to which we will stop writing
+ *
+ * This is a central place which will give up the ability
+ * to write to @file, along with access to write through
+ * its vfsmount.
+ */
+void drop_file_write_access(struct file *file)
+{
+   struct vfsmount *mnt = file->f_path.mnt;
+   struct dentry *dentry = file->f_path.dentry;
+   struct inode *inode = dentry->d_inode;
+
+   put_write_access(inode);
+
+   if (special_file(inode->i_mode))
+      return;
+   if (file_check_writeable(file) != 0)
+      return;
+   mnt_drop_write(mnt);
+   file_release_write(file);
+}
+EXPORT_SYMBOL_GPL(drop_file_write_access);
+
 /* __fput is called from task context when aio completion releases the last
  * last use of a struct file *.  Do not use otherwise.
  */
@@ -236,10 +275,10 @@ void __fput(struct file *file)
    if (unlikely(S_ISCHR(inode->i_mode) && inode->i_cdev != NULL))
       cdev_put(inode->i_cdev);
    fops_put(file->f_op);
-   if (file->f_mode & FMODE_WRITE)
-      put_write_access(inode);
    put_pid(file->f_owner.pid);
    file_kill(file);
+   if (file->f_mode & FMODE_WRITE)
+      drop_file_write_access(file);
    file->f_path.dentry = NULL;
    file->f_path.mnt = NULL;
    file_free(file);


Comments: webmaster (at) linuxhq.com.
Advertising: banners (at) linuxhq.com.
Compilation ©1998-2008 Linux Headquarters, Inc.