]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - fs/ext3/super.c
[PATCH] sem2mutex: quota
[net-next-2.6.git] / fs / ext3 / super.c
index 9e24ceb019fe2cea7ba9dec689006fe2cfc7d390..efa832059143a119bb49c11047c43836e00b0547 100644 (file)
 #include <linux/namei.h>
 #include <linux/quotaops.h>
 #include <linux/seq_file.h>
+
 #include <asm/uaccess.h>
+
 #include "xattr.h"
 #include "acl.h"
+#include "namei.h"
 
-static int ext3_load_journal(struct super_block *, struct ext3_super_block *);
+static int ext3_load_journal(struct super_block *, struct ext3_super_block *,
+                            unsigned long journal_devnum);
 static int ext3_create_journal(struct super_block *, struct ext3_super_block *,
                               int);
 static void ext3_commit_super (struct super_block * sb,
@@ -510,19 +514,11 @@ static void ext3_clear_inode(struct inode *inode)
        kfree(rsv);
 }
 
-static int ext3_show_options(struct seq_file *seq, struct vfsmount *vfs)
+static inline void ext3_show_quota_options(struct seq_file *seq, struct super_block *sb)
 {
-       struct super_block *sb = vfs->mnt_sb;
+#if defined(CONFIG_QUOTA)
        struct ext3_sb_info *sbi = EXT3_SB(sb);
 
-       if (test_opt(sb, DATA_FLAGS) == EXT3_MOUNT_JOURNAL_DATA)
-               seq_puts(seq, ",data=journal");
-       else if (test_opt(sb, DATA_FLAGS) == EXT3_MOUNT_ORDERED_DATA)
-               seq_puts(seq, ",data=ordered");
-       else if (test_opt(sb, DATA_FLAGS) == EXT3_MOUNT_WRITEBACK_DATA)
-               seq_puts(seq, ",data=writeback");
-
-#if defined(CONFIG_QUOTA)
        if (sbi->s_jquota_fmt)
                seq_printf(seq, ",jqfmt=%s",
                (sbi->s_jquota_fmt == QFMT_VFS_OLD) ? "vfsold": "vfsv0");
@@ -539,6 +535,20 @@ static int ext3_show_options(struct seq_file *seq, struct vfsmount *vfs)
        if (sbi->s_mount_opt & EXT3_MOUNT_GRPQUOTA)
                seq_puts(seq, ",grpquota");
 #endif
+}
+
+static int ext3_show_options(struct seq_file *seq, struct vfsmount *vfs)
+{
+       struct super_block *sb = vfs->mnt_sb;
+
+       if (test_opt(sb, DATA_FLAGS) == EXT3_MOUNT_JOURNAL_DATA)
+               seq_puts(seq, ",data=journal");
+       else if (test_opt(sb, DATA_FLAGS) == EXT3_MOUNT_ORDERED_DATA)
+               seq_puts(seq, ",data=ordered");
+       else if (test_opt(sb, DATA_FLAGS) == EXT3_MOUNT_WRITEBACK_DATA)
+               seq_puts(seq, ",data=writeback");
+
+       ext3_show_quota_options(seq, sb);
 
        return 0;
 }
@@ -609,7 +619,6 @@ static struct super_operations ext3_sops = {
 #endif
 };
 
-struct dentry *ext3_get_parent(struct dentry *child);
 static struct export_operations ext3_export_ops = {
        .get_parent = ext3_get_parent,
 };
@@ -617,10 +626,10 @@ static struct export_operations ext3_export_ops = {
 enum {
        Opt_bsd_df, Opt_minix_df, Opt_grpid, Opt_nogrpid,
        Opt_resgid, Opt_resuid, Opt_sb, Opt_err_cont, Opt_err_panic, Opt_err_ro,
-       Opt_nouid32, Opt_check, Opt_nocheck, Opt_debug, Opt_oldalloc, Opt_orlov,
+       Opt_nouid32, Opt_nocheck, Opt_debug, Opt_oldalloc, Opt_orlov,
        Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl,
        Opt_reservation, Opt_noreservation, Opt_noload, Opt_nobh,
-       Opt_commit, Opt_journal_update, Opt_journal_inum,
+       Opt_commit, Opt_journal_update, Opt_journal_inum, Opt_journal_dev,
        Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback,
        Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
        Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota,
@@ -644,7 +653,6 @@ static match_table_t tokens = {
        {Opt_nouid32, "nouid32"},
        {Opt_nocheck, "nocheck"},
        {Opt_nocheck, "check=none"},
-       {Opt_check, "check"},
        {Opt_debug, "debug"},
        {Opt_oldalloc, "oldalloc"},
        {Opt_orlov, "orlov"},
@@ -659,6 +667,7 @@ static match_table_t tokens = {
        {Opt_commit, "commit=%u"},
        {Opt_journal_update, "journal=update"},
        {Opt_journal_inum, "journal=%u"},
+       {Opt_journal_dev, "journal_dev=%u"},
        {Opt_abort, "abort"},
        {Opt_data_journal, "data=journal"},
        {Opt_data_ordered, "data=ordered"},
@@ -698,8 +707,9 @@ static unsigned long get_sb_block(void **data)
        return sb_block;
 }
 
-static int parse_options (char * options, struct super_block *sb,
-                         unsigned long * inum, unsigned long *n_blocks_count, int is_remount)
+static int parse_options (char *options, struct super_block *sb,
+                         unsigned long *inum, unsigned long *journal_devnum,
+                         unsigned long *n_blocks_count, int is_remount)
 {
        struct ext3_sb_info *sbi = EXT3_SB(sb);
        char * p;
@@ -765,14 +775,6 @@ static int parse_options (char * options, struct super_block *sb,
                case Opt_nouid32:
                        set_opt (sbi->s_mount_opt, NO_UID32);
                        break;
-               case Opt_check:
-#ifdef CONFIG_EXT3_CHECK
-                       set_opt (sbi->s_mount_opt, CHECK);
-#else
-                       printk(KERN_ERR
-                              "EXT3 Check option not supported\n");
-#endif
-                       break;
                case Opt_nocheck:
                        clear_opt (sbi->s_mount_opt, CHECK);
                        break;
@@ -840,6 +842,16 @@ static int parse_options (char * options, struct super_block *sb,
                                return 0;
                        *inum = option;
                        break;
+               case Opt_journal_dev:
+                       if (is_remount) {
+                               printk(KERN_ERR "EXT3-fs: cannot specify "
+                                      "journal on remount\n");
+                               return 0;
+                       }
+                       if (match_int(&args[0], &option))
+                               return 0;
+                       *journal_devnum = option;
+                       break;
                case Opt_noload:
                        set_opt (sbi->s_mount_opt, NOLOAD);
                        break;
@@ -1107,12 +1119,6 @@ static int ext3_setup_super(struct super_block *sb, struct ext3_super_block *es,
        } else {
                printk("internal journal\n");
        }
-#ifdef CONFIG_EXT3_CHECK
-       if (test_opt (sb, CHECK)) {
-               ext3_check_blocks_bitmap (sb);
-               ext3_check_inodes_bitmap (sb);
-       }
-#endif
        return res;
 }
 
@@ -1338,6 +1344,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
        unsigned long logic_sb_block;
        unsigned long offset = 0;
        unsigned long journal_inum = 0;
+       unsigned long journal_devnum = 0;
        unsigned long def_mount_opts;
        struct inode *root;
        int blocksize;
@@ -1418,7 +1425,8 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
 
        set_opt(sbi->s_mount_opt, RESERVATION);
 
-       if (!parse_options ((char *) data, sb, &journal_inum, NULL, 0))
+       if (!parse_options ((char *) data, sb, &journal_inum, &journal_devnum,
+                           NULL, 0))
                goto failed_mount;
 
        sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
@@ -1629,7 +1637,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
         */
        if (!test_opt(sb, NOLOAD) &&
            EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
-               if (ext3_load_journal(sb, es))
+               if (ext3_load_journal(sb, es, journal_devnum))
                        goto failed_mount2;
        } else if (journal_inum) {
                if (ext3_create_journal(sb, es, journal_inum))
@@ -1909,15 +1917,24 @@ out_bdev:
        return NULL;
 }
 
-static int ext3_load_journal(struct super_block * sb,
-                            struct ext3_super_block * es)
+static int ext3_load_journal(struct super_block *sb,
+                            struct ext3_super_block *es,
+                            unsigned long journal_devnum)
 {
        journal_t *journal;
        int journal_inum = le32_to_cpu(es->s_journal_inum);
-       dev_t journal_dev = new_decode_dev(le32_to_cpu(es->s_journal_dev));
+       dev_t journal_dev;
        int err = 0;
        int really_read_only;
 
+       if (journal_devnum &&
+           journal_devnum != le32_to_cpu(es->s_journal_dev)) {
+               printk(KERN_INFO "EXT3-fs: external journal device major/minor "
+                       "numbers have changed\n");
+               journal_dev = new_decode_dev(journal_devnum);
+       } else
+               journal_dev = new_decode_dev(le32_to_cpu(es->s_journal_dev));
+
        really_read_only = bdev_read_only(sb->s_bdev);
 
        /*
@@ -1976,6 +1993,16 @@ static int ext3_load_journal(struct super_block * sb,
 
        EXT3_SB(sb)->s_journal = journal;
        ext3_clear_journal_err(sb, es);
+
+       if (journal_devnum &&
+           journal_devnum != le32_to_cpu(es->s_journal_dev)) {
+               es->s_journal_dev = cpu_to_le32(journal_devnum);
+               sb->s_dirt = 1;
+
+               /* Make sure we flush the recovery flag to disk. */
+               ext3_commit_super(sb, es, 1);
+       }
+
        return 0;
 }
 
@@ -2123,7 +2150,7 @@ int ext3_force_commit(struct super_block *sb)
 
 static void ext3_write_super (struct super_block * sb)
 {
-       if (down_trylock(&sb->s_lock) == 0)
+       if (mutex_trylock(&sb->s_lock) != 0)
                BUG();
        sb->s_dirt = 0;
 }
@@ -2204,7 +2231,7 @@ static int ext3_remount (struct super_block * sb, int * flags, char * data)
        /*
         * Allow the "check" option to be passed as a remount option.
         */
-       if (!parse_options(data, sb, NULL, &n_blocks_count, 1)) {
+       if (!parse_options(data, sb, NULL, NULL, &n_blocks_count, 1)) {
                err = -EINVAL;
                goto restore_opts;
        }
@@ -2355,8 +2382,8 @@ static int ext3_statfs (struct super_block * sb, struct kstatfs * buf)
  * Process 1                         Process 2
  * ext3_create()                     quota_sync()
  *   journal_start()                   write_dquot()
- *   DQUOT_INIT()                        down(dqio_sem)
- *     down(dqio_sem)                    journal_start()
+ *   DQUOT_INIT()                        down(dqio_mutex)
+ *     down(dqio_mutex)                    journal_start()
  *
  */
 
@@ -2574,7 +2601,7 @@ static ssize_t ext3_quota_write(struct super_block *sb, int type,
        struct buffer_head *bh;
        handle_t *handle = journal_current_handle();
 
-       down(&inode->i_sem);
+       mutex_lock(&inode->i_mutex);
        while (towrite > 0) {
                tocopy = sb->s_blocksize - offset < towrite ?
                                sb->s_blocksize - offset : towrite;
@@ -2617,7 +2644,7 @@ out:
        inode->i_version++;
        inode->i_mtime = inode->i_ctime = CURRENT_TIME;
        ext3_mark_inode_dirty(handle, inode);
-       up(&inode->i_sem);
+       mutex_unlock(&inode->i_mutex);
        return len - towrite;
 }