drm/radeon: fix PM on non-vram cards.
[safe/jmp/linux-2.6] / fs / reiserfs / super.c
index 7adea74..9822fa1 100644 (file)
@@ -12,6 +12,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/time.h>
 #include <asm/uaccess.h>
@@ -157,6 +158,7 @@ static int finish_unfinished(struct super_block *s)
 #ifdef CONFIG_QUOTA
        int i;
        int ms_active_set;
+       int quota_enabled[MAXQUOTAS];
 #endif
 
        /* compose key to look for "save" links */
@@ -178,8 +180,15 @@ static int finish_unfinished(struct super_block *s)
        }
        /* Turn on quotas so that they are updated correctly */
        for (i = 0; i < MAXQUOTAS; i++) {
+               quota_enabled[i] = 1;
                if (REISERFS_SB(s)->s_qf_names[i]) {
-                       int ret = reiserfs_quota_on_mount(s, i);
+                       int ret;
+
+                       if (sb_has_quota_active(s, i)) {
+                               quota_enabled[i] = 0;
+                               continue;
+                       }
+                       ret = reiserfs_quota_on_mount(s, i);
                        if (ret < 0)
                                reiserfs_warning(s, "reiserfs-2500",
                                                 "cannot turn on journaled "
@@ -246,7 +255,7 @@ static int finish_unfinished(struct super_block *s)
                        retval = remove_save_link_only(s, &save_link_key, 0);
                        continue;
                }
-               vfs_dq_init(inode);
+               dquot_initialize(inode);
 
                if (truncate && S_ISDIR(inode->i_mode)) {
                        /* We got a truncate request for a dir which is impossible.
@@ -303,8 +312,8 @@ static int finish_unfinished(struct super_block *s)
 #ifdef CONFIG_QUOTA
        /* Turn quotas off */
        for (i = 0; i < MAXQUOTAS; i++) {
-               if (sb_dqopt(s)->files[i])
-                       vfs_quota_off(s, i, 0);
+               if (sb_dqopt(s)->files[i] && quota_enabled[i])
+                       dquot_quota_off(s, i);
        }
        if (ms_active_set)
                /* Restore the flag back */
@@ -465,7 +474,9 @@ static void reiserfs_put_super(struct super_block *s)
        struct reiserfs_transaction_handle th;
        th.t_trans_id = 0;
 
-       lock_kernel();
+       dquot_disable(s, -1, DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED);
+
+       reiserfs_write_lock(s);
 
        if (s->s_dirt)
                reiserfs_write_super(s);
@@ -499,10 +510,10 @@ static void reiserfs_put_super(struct super_block *s)
 
        reiserfs_proc_info_done(s);
 
+       reiserfs_write_unlock(s);
+       mutex_destroy(&REISERFS_SB(s)->lock);
        kfree(s->s_fs_info);
        s->s_fs_info = NULL;
-
-       unlock_kernel();
 }
 
 static struct kmem_cache *reiserfs_inode_cachep;
@@ -554,25 +565,33 @@ static void reiserfs_dirty_inode(struct inode *inode)
        struct reiserfs_transaction_handle th;
 
        int err = 0;
+       int lock_depth;
+
        if (inode->i_sb->s_flags & MS_RDONLY) {
                reiserfs_warning(inode->i_sb, "clm-6006",
                                 "writing inode %lu on readonly FS",
                                 inode->i_ino);
                return;
        }
-       reiserfs_write_lock(inode->i_sb);
+       lock_depth = reiserfs_write_lock_once(inode->i_sb);
 
        /* this is really only used for atime updates, so they don't have
         ** to be included in O_SYNC or fsync
         */
        err = journal_begin(&th, inode->i_sb, 1);
-       if (err) {
-               reiserfs_write_unlock(inode->i_sb);
-               return;
-       }
+       if (err)
+               goto out;
+
        reiserfs_update_sd(&th, inode);
        journal_end(&th, inode->i_sb, 1);
-       reiserfs_write_unlock(inode->i_sb);
+
+out:
+       reiserfs_write_unlock_once(inode->i_sb, lock_depth);
+}
+
+static void reiserfs_clear_inode(struct inode *inode)
+{
+       dquot_drop(inode);
 }
 
 #ifdef CONFIG_QUOTA
@@ -587,6 +606,7 @@ static const struct super_operations reiserfs_sops = {
        .destroy_inode = reiserfs_destroy_inode,
        .write_inode = reiserfs_write_inode,
        .dirty_inode = reiserfs_dirty_inode,
+       .clear_inode = reiserfs_clear_inode,
        .delete_inode = reiserfs_delete_inode,
        .put_super = reiserfs_put_super,
        .write_super = reiserfs_write_super,
@@ -610,16 +630,9 @@ static int reiserfs_acquire_dquot(struct dquot *);
 static int reiserfs_release_dquot(struct dquot *);
 static int reiserfs_mark_dquot_dirty(struct dquot *);
 static int reiserfs_write_info(struct super_block *, int);
-static int reiserfs_quota_on(struct super_block *, int, int, char *, int);
-
-static struct dquot_operations reiserfs_quota_operations = {
-       .initialize = dquot_initialize,
-       .drop = dquot_drop,
-       .alloc_space = dquot_alloc_space,
-       .alloc_inode = dquot_alloc_inode,
-       .free_space = dquot_free_space,
-       .free_inode = dquot_free_inode,
-       .transfer = dquot_transfer,
+static int reiserfs_quota_on(struct super_block *, int, int, char *);
+
+static const struct dquot_operations reiserfs_quota_operations = {
        .write_dquot = reiserfs_write_dquot,
        .acquire_dquot = reiserfs_acquire_dquot,
        .release_dquot = reiserfs_release_dquot,
@@ -629,14 +642,14 @@ static struct dquot_operations reiserfs_quota_operations = {
        .destroy_dquot  = dquot_destroy,
 };
 
-static struct quotactl_ops reiserfs_qctl_operations = {
+static const struct quotactl_ops reiserfs_qctl_operations = {
        .quota_on = reiserfs_quota_on,
-       .quota_off = vfs_quota_off,
-       .quota_sync = vfs_quota_sync,
-       .get_info = vfs_get_dqinfo,
-       .set_info = vfs_set_dqinfo,
-       .get_dqblk = vfs_get_dqblk,
-       .set_dqblk = vfs_set_dqblk,
+       .quota_off = dquot_quota_off,
+       .quota_sync = dquot_quota_sync,
+       .get_info = dquot_get_dqinfo,
+       .set_info = dquot_set_dqinfo,
+       .get_dqblk = dquot_get_dqblk,
+       .set_dqblk = dquot_set_dqblk,
 };
 #endif
 
@@ -1168,11 +1181,14 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
        unsigned int qfmt = 0;
 #ifdef CONFIG_QUOTA
        int i;
+#endif
+
+       reiserfs_write_lock(s);
 
+#ifdef CONFIG_QUOTA
        memcpy(qf_names, REISERFS_SB(s)->s_qf_names, sizeof(qf_names));
 #endif
 
-       lock_kernel();
        rs = SB_DISK_SUPER_BLOCK(s);
 
        if (!reiserfs_parse_options
@@ -1236,6 +1252,11 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
                if (s->s_flags & MS_RDONLY)
                        /* it is read-only already */
                        goto out_ok;
+
+               err = dquot_suspend(s, -1);
+               if (err < 0)
+                       goto out_err;
+
                /* try to remount file system with read-only permissions */
                if (sb_umount_state(rs) == REISERFS_VALID_FS
                    || REISERFS_SB(s)->s_mount_state != REISERFS_VALID_FS) {
@@ -1289,18 +1310,19 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
        s->s_dirt = 0;
 
        if (!(*mount_flags & MS_RDONLY)) {
+               dquot_resume(s, -1);
                finish_unfinished(s);
                reiserfs_xattr_init(s, *mount_flags);
        }
 
 out_ok:
        replace_mount_options(s, new_opts);
-       unlock_kernel();
+       reiserfs_write_unlock(s);
        return 0;
 
 out_err:
        kfree(new_opts);
-       unlock_kernel();
+       reiserfs_write_unlock(s);
        return err;
 }
 
@@ -1404,7 +1426,9 @@ static int read_super_block(struct super_block *s, int offset)
 static int reread_meta_blocks(struct super_block *s)
 {
        ll_rw_block(READ, 1, &(SB_BUFFER_WITH_SB(s)));
+       reiserfs_write_unlock(s);
        wait_on_buffer(SB_BUFFER_WITH_SB(s));
+       reiserfs_write_lock(s);
        if (!buffer_uptodate(SB_BUFFER_WITH_SB(s))) {
                reiserfs_warning(s, "reiserfs-2504", "error reading the super");
                return 1;
@@ -1611,10 +1635,8 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
        save_mount_options(s, data);
 
        sbi = kzalloc(sizeof(struct reiserfs_sb_info), GFP_KERNEL);
-       if (!sbi) {
-               errval = -ENOMEM;
-               goto error;
-       }
+       if (!sbi)
+               return -ENOMEM;
        s->s_fs_info = sbi;
        /* Set default values for options: non-aggressive tails, RO on errors */
        REISERFS_SB(s)->s_mount_opt |= (1 << REISERFS_SMALLTAIL);
@@ -1627,6 +1649,20 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
        /* setup default block allocator options */
        reiserfs_init_alloc_options(s);
 
+       mutex_init(&REISERFS_SB(s)->lock);
+       REISERFS_SB(s)->lock_depth = -1;
+
+       /*
+        * This function is called with the bkl, which also was the old
+        * locking used here.
+        * do_journal_begin() will soon check if we hold the lock (ie: was the
+        * bkl). This is likely because do_journal_begin() has several another
+        * callers because at this time, it doesn't seem to be necessary to
+        * protect against anything.
+        * Anyway, let's be conservative and lock for now.
+        */
+       reiserfs_write_lock(s);
+
        jdev_name = NULL;
        if (reiserfs_parse_options
            (s, (char *)data, &(sbi->s_mount_opt), &blocks, &jdev_name,
@@ -1852,6 +1888,8 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
        init_waitqueue_head(&(sbi->s_wait));
        spin_lock_init(&sbi->bitmap_lock);
 
+       reiserfs_write_unlock(s);
+
        return (0);
 
 error:
@@ -1859,6 +1897,8 @@ error:
                journal_release_error(NULL, s);
        }
 
+       reiserfs_write_unlock(s);
+
        reiserfs_free_bitmap_cache(s);
        if (SB_BUFFER_WITH_SB(s))
                brelse(SB_BUFFER_WITH_SB(s));
@@ -1998,15 +2038,15 @@ static int reiserfs_write_info(struct super_block *sb, int type)
  */
 static int reiserfs_quota_on_mount(struct super_block *sb, int type)
 {
-       return vfs_quota_on_mount(sb, REISERFS_SB(sb)->s_qf_names[type],
-                                 REISERFS_SB(sb)->s_jquota_fmt, type);
+       return dquot_quota_on_mount(sb, REISERFS_SB(sb)->s_qf_names[type],
+                                       REISERFS_SB(sb)->s_jquota_fmt, type);
 }
 
 /*
  * Standard function to be called on quota_on
  */
 static int reiserfs_quota_on(struct super_block *sb, int type, int format_id,
-                            char *name, int remount)
+                            char *name)
 {
        int err;
        struct path path;
@@ -2015,9 +2055,7 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id,
 
        if (!(REISERFS_SB(sb)->s_mount_opt & (1 << REISERFS_QUOTA)))
                return -EINVAL;
-       /* No more checks needed? Path and format_id are bogus anyway... */
-       if (remount)
-               return vfs_quota_on(sb, type, format_id, name, 1);
+
        err = kern_path(name, LOOKUP_FOLLOW, &path);
        if (err)
                return err;
@@ -2061,7 +2099,7 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id,
                if (err)
                        goto out;
        }
-       err = vfs_quota_on_path(sb, type, format_id, &path);
+       err = dquot_quota_on_path(sb, type, format_id, &path);
 out:
        path_put(&path);
        return err;
@@ -2196,8 +2234,6 @@ static int __init init_reiserfs_fs(void)
        }
 
        reiserfs_proc_info_global_init();
-       reiserfs_proc_register_global("version",
-                                     reiserfs_global_version_in_proc);
 
        ret = register_filesystem(&reiserfs_fs_type);
 
@@ -2205,7 +2241,6 @@ static int __init init_reiserfs_fs(void)
                return 0;
        }
 
-       reiserfs_proc_unregister_global("version");
        reiserfs_proc_info_global_done();
        destroy_inodecache();
 
@@ -2214,7 +2249,6 @@ static int __init init_reiserfs_fs(void)
 
 static void __exit exit_reiserfs_fs(void)
 {
-       reiserfs_proc_unregister_global("version");
        reiserfs_proc_info_global_done();
        unregister_filesystem(&reiserfs_fs_type);
        destroy_inodecache();