]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - fs/reiserfs/super.c
[XFS] s/XFS_PURGE_INODE/IRELE/g s/VN_HOLD(XFS_ITOV())/IHOLD()/
[linux-2.6-omap-h63xx.git] / fs / reiserfs / super.c
index 1d40f2bd197081284dce1ff34c6d1f828082304f..879e54d35c2d49400a48b3d748a69c92934acb7a 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/blkdev.h>
 #include <linux/buffer_head.h>
 #include <linux/exportfs.h>
+#include <linux/quotaops.h>
 #include <linux/vfs.h>
 #include <linux/mnt_namespace.h>
 #include <linux/mount.h>
@@ -182,7 +183,7 @@ static int finish_unfinished(struct super_block *s)
                        int ret = reiserfs_quota_on_mount(s, i);
                        if (ret < 0)
                                reiserfs_warning(s,
-                                                "reiserfs: cannot turn on journalled quota: error %d",
+                                                "reiserfs: cannot turn on journaled quota: error %d",
                                                 ret);
                }
        }
@@ -520,7 +521,7 @@ static void reiserfs_destroy_inode(struct inode *inode)
        kmem_cache_free(reiserfs_inode_cachep, REISERFS_I(inode));
 }
 
-static void init_once(struct kmem_cache * cachep, void *foo)
+static void init_once(void *foo)
 {
        struct reiserfs_inode_info *ei = (struct reiserfs_inode_info *)foo;
 
@@ -876,7 +877,9 @@ static int reiserfs_parse_options(struct super_block *s, char *options,     /* strin
                                     mount options were selected. */
                                  unsigned long *blocks,        /* strtol-ed from NNN of resize=NNN */
                                  char **jdev_name,
-                                 unsigned int *commit_max_age)
+                                 unsigned int *commit_max_age,
+                                 char **qf_names,
+                                 unsigned int *qfmt)
 {
        int c;
        char *arg = NULL;
@@ -992,9 +995,11 @@ static int reiserfs_parse_options(struct super_block *s, char *options,    /* strin
                if (c == 'u' || c == 'g') {
                        int qtype = c == 'u' ? USRQUOTA : GRPQUOTA;
 
-                       if (sb_any_quota_enabled(s)) {
+                       if ((sb_any_quota_enabled(s) ||
+                            sb_any_quota_suspended(s)) &&
+                           (!*arg != !REISERFS_SB(s)->s_qf_names[qtype])) {
                                reiserfs_warning(s,
-                                                "reiserfs_parse_options: cannot change journalled quota options when quota turned on.");
+                                                "reiserfs_parse_options: cannot change journaled quota options when quota turned on.");
                                return 0;
                        }
                        if (*arg) {     /* Some filename specified? */
@@ -1011,46 +1016,54 @@ static int reiserfs_parse_options(struct super_block *s, char *options, /* strin
                                                         "reiserfs_parse_options: quotafile must be on filesystem root.");
                                        return 0;
                                }
-                               REISERFS_SB(s)->s_qf_names[qtype] =
+                               qf_names[qtype] =
                                    kmalloc(strlen(arg) + 1, GFP_KERNEL);
-                               if (!REISERFS_SB(s)->s_qf_names[qtype]) {
+                               if (!qf_names[qtype]) {
                                        reiserfs_warning(s,
                                                         "reiserfs_parse_options: not enough memory for storing quotafile name.");
                                        return 0;
                                }
-                               strcpy(REISERFS_SB(s)->s_qf_names[qtype], arg);
+                               strcpy(qf_names[qtype], arg);
                                *mount_options |= 1 << REISERFS_QUOTA;
                        } else {
-                               kfree(REISERFS_SB(s)->s_qf_names[qtype]);
-                               REISERFS_SB(s)->s_qf_names[qtype] = NULL;
+                               if (qf_names[qtype] !=
+                                   REISERFS_SB(s)->s_qf_names[qtype])
+                                       kfree(qf_names[qtype]);
+                               qf_names[qtype] = NULL;
                        }
                }
                if (c == 'f') {
                        if (!strcmp(arg, "vfsold"))
-                               REISERFS_SB(s)->s_jquota_fmt = QFMT_VFS_OLD;
+                               *qfmt = QFMT_VFS_OLD;
                        else if (!strcmp(arg, "vfsv0"))
-                               REISERFS_SB(s)->s_jquota_fmt = QFMT_VFS_V0;
+                               *qfmt = QFMT_VFS_V0;
                        else {
                                reiserfs_warning(s,
                                                 "reiserfs_parse_options: unknown quota format specified.");
                                return 0;
                        }
+                       if ((sb_any_quota_enabled(s) ||
+                            sb_any_quota_suspended(s)) &&
+                           *qfmt != REISERFS_SB(s)->s_jquota_fmt) {
+                               reiserfs_warning(s,
+                                                "reiserfs_parse_options: cannot change journaled quota options when quota turned on.");
+                               return 0;
+                       }
                }
 #else
                if (c == 'u' || c == 'g' || c == 'f') {
                        reiserfs_warning(s,
-                                        "reiserfs_parse_options: journalled quota options not supported.");
+                                        "reiserfs_parse_options: journaled quota options not supported.");
                        return 0;
                }
 #endif
        }
 
 #ifdef CONFIG_QUOTA
-       if (!REISERFS_SB(s)->s_jquota_fmt
-           && (REISERFS_SB(s)->s_qf_names[USRQUOTA]
-               || REISERFS_SB(s)->s_qf_names[GRPQUOTA])) {
+       if (!REISERFS_SB(s)->s_jquota_fmt && !*qfmt
+           && (qf_names[USRQUOTA] || qf_names[GRPQUOTA])) {
                reiserfs_warning(s,
-                                "reiserfs_parse_options: journalled quota format not specified.");
+                                "reiserfs_parse_options: journaled quota format not specified.");
                return 0;
        }
        /* This checking is not precise wrt the quota type but for our purposes it is sufficient */
@@ -1130,6 +1143,21 @@ static void handle_attrs(struct super_block *s)
        }
 }
 
+#ifdef CONFIG_QUOTA
+static void handle_quota_files(struct super_block *s, char **qf_names,
+                              unsigned int *qfmt)
+{
+       int i;
+
+       for (i = 0; i < MAXQUOTAS; i++) {
+               if (qf_names[i] != REISERFS_SB(s)->s_qf_names[i])
+                       kfree(REISERFS_SB(s)->s_qf_names[i]);
+               REISERFS_SB(s)->s_qf_names[i] = qf_names[i];
+       }
+       REISERFS_SB(s)->s_jquota_fmt = *qfmt;
+}
+#endif
+
 static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
 {
        struct reiserfs_super_block *rs;
@@ -1141,23 +1169,30 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
        struct reiserfs_journal *journal = SB_JOURNAL(s);
        char *new_opts = kstrdup(arg, GFP_KERNEL);
        int err;
+       char *qf_names[MAXQUOTAS];
+       unsigned int qfmt = 0;
 #ifdef CONFIG_QUOTA
        int i;
+
+       memcpy(qf_names, REISERFS_SB(s)->s_qf_names, sizeof(qf_names));
 #endif
 
        rs = SB_DISK_SUPER_BLOCK(s);
 
        if (!reiserfs_parse_options
-           (s, arg, &mount_options, &blocks, NULL, &commit_max_age)) {
+           (s, arg, &mount_options, &blocks, NULL, &commit_max_age,
+           qf_names, &qfmt)) {
 #ifdef CONFIG_QUOTA
-               for (i = 0; i < MAXQUOTAS; i++) {
-                       kfree(REISERFS_SB(s)->s_qf_names[i]);
-                       REISERFS_SB(s)->s_qf_names[i] = NULL;
-               }
+               for (i = 0; i < MAXQUOTAS; i++)
+                       if (qf_names[i] != REISERFS_SB(s)->s_qf_names[i])
+                               kfree(qf_names[i]);
 #endif
                err = -EINVAL;
                goto out_err;
        }
+#ifdef CONFIG_QUOTA
+       handle_quota_files(s, qf_names, &qfmt);
+#endif
 
        handle_attrs(s);
 
@@ -1570,6 +1605,8 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
        char *jdev_name;
        struct reiserfs_sb_info *sbi;
        int errval = -EINVAL;
+       char *qf_names[MAXQUOTAS] = {};
+       unsigned int qfmt = 0;
 
        save_mount_options(s, data);
 
@@ -1597,9 +1634,12 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
        jdev_name = NULL;
        if (reiserfs_parse_options
            (s, (char *)data, &(sbi->s_mount_opt), &blocks, &jdev_name,
-            &commit_max_age) == 0) {
+            &commit_max_age, qf_names, &qfmt) == 0) {
                goto error;
        }
+#ifdef CONFIG_QUOTA
+       handle_quota_files(s, qf_names, &qfmt);
+#endif
 
        if (blocks) {
                SWARN(silent, s, "jmacd-7: reiserfs_fill_super: resize option "
@@ -1819,7 +1859,7 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
 
        return (0);
 
-      error:
+error:
        if (jinit_done) {       /* kill the commit thread, free journal ram */
                journal_release_error(NULL, s);
        }
@@ -1830,10 +1870,8 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
 #ifdef CONFIG_QUOTA
        {
                int j;
-               for (j = 0; j < MAXQUOTAS; j++) {
-                       kfree(sbi->s_qf_names[j]);
-                       sbi->s_qf_names[j] = NULL;
-               }
+               for (j = 0; j < MAXQUOTAS; j++)
+                       kfree(qf_names[j]);
        }
 #endif
        kfree(sbi);
@@ -1980,7 +2018,7 @@ static int reiserfs_release_dquot(struct dquot *dquot)
 
 static int reiserfs_mark_dquot_dirty(struct dquot *dquot)
 {
-       /* Are we journalling quotas? */
+       /* Are we journaling quotas? */
        if (REISERFS_SB(dquot->dq_sb)->s_qf_names[USRQUOTA] ||
            REISERFS_SB(dquot->dq_sb)->s_qf_names[GRPQUOTA]) {
                dquot_mark_dquot_dirty(dquot);
@@ -2026,6 +2064,7 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id,
        int err;
        struct nameidata nd;
        struct inode *inode;
+       struct reiserfs_transaction_handle th;
 
        if (!(REISERFS_SB(sb)->s_mount_opt & (1 << REISERFS_QUOTA)))
                return -EINVAL;
@@ -2053,17 +2092,28 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id,
                }
                mark_inode_dirty(inode);
        }
-       /* Not journalling quota? No more tests needed... */
-       if (!REISERFS_SB(sb)->s_qf_names[USRQUOTA] &&
-           !REISERFS_SB(sb)->s_qf_names[GRPQUOTA]) {
-               path_put(&nd.path);
-               return vfs_quota_on(sb, type, format_id, path, 0);
-       }
-       /* Quotafile not of fs root? */
-       if (nd.path.dentry->d_parent->d_inode != sb->s_root->d_inode)
-               reiserfs_warning(sb,
+       /* Journaling quota? */
+       if (REISERFS_SB(sb)->s_qf_names[type]) {
+               /* Quotafile not of fs root? */
+               if (nd.path.dentry->d_parent->d_inode != sb->s_root->d_inode)
+                       reiserfs_warning(sb,
                                 "reiserfs: Quota file not on filesystem root. "
                                 "Journalled quota will not work.");
+       }
+
+       /*
+        * When we journal data on quota file, we have to flush journal to see
+        * all updates to the file when we bypass pagecache...
+        */
+       if (reiserfs_file_data_log(inode)) {
+               /* Just start temporary transaction and finish it */
+               err = journal_begin(&th, sb, 1);
+               if (err)
+                       return err;
+               err = journal_end_sync(&th, sb, 1);
+               if (err)
+                       return err;
+       }
        path_put(&nd.path);
        return vfs_quota_on(sb, type, format_id, path, 0);
 }