nfsd: use static memory for callback program and stats
[safe/jmp/linux-2.6] / fs / super.c
index ceaf2e3..4798350 100644 (file)
@@ -37,7 +37,9 @@
 #include <linux/idr.h>
 #include <linux/kobject.h>
 #include <linux/mutex.h>
+#include <linux/file.h>
 #include <asm/uaccess.h>
+#include "internal.h"
 
 
 LIST_HEAD(super_blocks);
@@ -105,6 +107,7 @@ static inline void destroy_super(struct super_block *s)
 {
        security_sb_free(s);
        kfree(s->s_subtype);
+       kfree(s->s_options);
        kfree(s);
 }
 
@@ -555,21 +558,40 @@ out:
 }
 
 /**
- *     mark_files_ro
+ *     mark_files_ro - mark all files read-only
  *     @sb: superblock in question
  *
- *     All files are marked read/only.  We don't care about pending
- *     delete files so this should be used in 'force' mode only
+ *     All files are marked read-only.  We don't care about pending
+ *     delete files so this should be used in 'force' mode only.
  */
 
 static void mark_files_ro(struct super_block *sb)
 {
        struct file *f;
 
+retry:
        file_list_lock();
        list_for_each_entry(f, &sb->s_files, f_u.fu_list) {
-               if (S_ISREG(f->f_path.dentry->d_inode->i_mode) && file_count(f))
-                       f->f_mode &= ~FMODE_WRITE;
+               struct vfsmount *mnt;
+               if (!S_ISREG(f->f_path.dentry->d_inode->i_mode))
+                      continue;
+               if (!file_count(f))
+                       continue;
+               if (!(f->f_mode & FMODE_WRITE))
+                       continue;
+               f->f_mode &= ~FMODE_WRITE;
+               if (file_check_writeable(f) != 0)
+                       continue;
+               file_release_write(f);
+               mnt = mntget(f->f_path.mnt);
+               file_list_unlock();
+               /*
+                * This can sleep, so we can't hold
+                * the file_list_lock() spinlock.
+                */
+               mnt_drop_write(mnt);
+               mntput(mnt);
+               goto retry;
        }
        file_list_unlock();
 }
@@ -603,6 +625,7 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force)
                        mark_files_ro(sb);
                else if (!fs_may_remount_ro(sb))
                        return -EBUSY;
+               DQUOT_OFF(sb);
        }
 
        if (sb->s_op->remount_fs) {
@@ -868,12 +891,12 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void
        if (!mnt)
                goto out;
 
-       if (data) {
+       if (data && !(type->fs_flags & FS_BINARY_MOUNTDATA)) {
                secdata = alloc_secdata();
                if (!secdata)
                        goto out_mnt;
 
-               error = security_sb_copy_data(type, data, secdata);
+               error = security_sb_copy_data(data, secdata);
                if (error)
                        goto out_free_secdata;
        }
@@ -943,6 +966,7 @@ do_kern_mount(const char *fstype, int flags, const char *name, void *data)
        put_filesystem(type);
        return mnt;
 }
+EXPORT_SYMBOL_GPL(do_kern_mount);
 
 struct vfsmount *kern_mount_data(struct file_system_type *type, void *data)
 {