switch open-coded instances of d_make_root() to new helper
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / fs / reiserfs / super.c
index 14363b96b6afafa74a80c2c66553c8d914064268..208dfd14440980e1c4e6c0866ddd34c694656046 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/mount.h>
 #include <linux/namei.h>
 #include <linux/crc32.h>
+#include <linux/seq_file.h>
 
 struct file_system_type reiserfs_fs_type;
 
@@ -61,6 +62,7 @@ static int is_any_reiserfs_magic_string(struct reiserfs_super_block *rs)
 
 static int reiserfs_remount(struct super_block *s, int *flags, char *data);
 static int reiserfs_statfs(struct dentry *dentry, struct kstatfs *buf);
+void show_alloc_options(struct seq_file *seq, struct super_block *s);
 
 static int reiserfs_sync_fs(struct super_block *s, int wait)
 {
@@ -453,16 +455,20 @@ int remove_save_link(struct inode *inode, int truncate)
 static void reiserfs_kill_sb(struct super_block *s)
 {
        if (REISERFS_SB(s)) {
-               if (REISERFS_SB(s)->xattr_root) {
-                       d_invalidate(REISERFS_SB(s)->xattr_root);
-                       dput(REISERFS_SB(s)->xattr_root);
-                       REISERFS_SB(s)->xattr_root = NULL;
-               }
-               if (REISERFS_SB(s)->priv_root) {
-                       d_invalidate(REISERFS_SB(s)->priv_root);
-                       dput(REISERFS_SB(s)->priv_root);
-                       REISERFS_SB(s)->priv_root = NULL;
-               }
+               /*
+                * Force any pending inode evictions to occur now. Any
+                * inodes to be removed that have extended attributes
+                * associated with them need to clean them up before
+                * we can release the extended attribute root dentries.
+                * shrink_dcache_for_umount will BUG if we don't release
+                * those before it's called so ->put_super is too late.
+                */
+               shrink_dcache_sb(s);
+
+               dput(REISERFS_SB(s)->xattr_root);
+               REISERFS_SB(s)->xattr_root = NULL;
+               dput(REISERFS_SB(s)->priv_root);
+               REISERFS_SB(s)->priv_root = NULL;
        }
 
        kill_block_super(s);
@@ -532,7 +538,6 @@ static struct inode *reiserfs_alloc_inode(struct super_block *sb)
 static void reiserfs_i_callback(struct rcu_head *head)
 {
        struct inode *inode = container_of(head, struct inode, i_rcu);
-       INIT_LIST_HEAD(&inode->i_dentry);
        kmem_cache_free(reiserfs_inode_cachep, REISERFS_I(inode));
 }
 
@@ -597,6 +602,82 @@ out:
        reiserfs_write_unlock_once(inode->i_sb, lock_depth);
 }
 
+static int reiserfs_show_options(struct seq_file *seq, struct dentry *root)
+{
+       struct super_block *s = root->d_sb;
+       struct reiserfs_journal *journal = SB_JOURNAL(s);
+       long opts = REISERFS_SB(s)->s_mount_opt;
+
+       if (opts & (1 << REISERFS_LARGETAIL))
+               seq_puts(seq, ",tails=on");
+       else if (!(opts & (1 << REISERFS_SMALLTAIL)))
+               seq_puts(seq, ",notail");
+       /* tails=small is default so we don't show it */
+
+       if (!(opts & (1 << REISERFS_BARRIER_FLUSH)))
+               seq_puts(seq, ",barrier=none");
+       /* barrier=flush is default so we don't show it */
+
+       if (opts & (1 << REISERFS_ERROR_CONTINUE))
+               seq_puts(seq, ",errors=continue");
+       else if (opts & (1 << REISERFS_ERROR_PANIC))
+               seq_puts(seq, ",errors=panic");
+       /* errors=ro is default so we don't show it */
+
+       if (opts & (1 << REISERFS_DATA_LOG))
+               seq_puts(seq, ",data=journal");
+       else if (opts & (1 << REISERFS_DATA_WRITEBACK))
+               seq_puts(seq, ",data=writeback");
+       /* data=ordered is default so we don't show it */
+
+       if (opts & (1 << REISERFS_ATTRS))
+               seq_puts(seq, ",attrs");
+
+       if (opts & (1 << REISERFS_XATTRS_USER))
+               seq_puts(seq, ",user_xattr");
+
+       if (opts & (1 << REISERFS_EXPOSE_PRIVROOT))
+               seq_puts(seq, ",expose_privroot");
+
+       if (opts & (1 << REISERFS_POSIXACL))
+               seq_puts(seq, ",acl");
+
+       if (REISERFS_SB(s)->s_jdev)
+               seq_printf(seq, ",jdev=%s", REISERFS_SB(s)->s_jdev);
+
+       if (journal->j_max_commit_age != journal->j_default_max_commit_age)
+               seq_printf(seq, ",commit=%d", journal->j_max_commit_age);
+
+#ifdef CONFIG_QUOTA
+       if (REISERFS_SB(s)->s_qf_names[USRQUOTA])
+               seq_printf(seq, ",usrjquota=%s", REISERFS_SB(s)->s_qf_names[USRQUOTA]);
+       else if (opts & (1 << REISERFS_USRQUOTA))
+               seq_puts(seq, ",usrquota");
+       if (REISERFS_SB(s)->s_qf_names[GRPQUOTA])
+               seq_printf(seq, ",grpjquota=%s", REISERFS_SB(s)->s_qf_names[GRPQUOTA]);
+       else if (opts & (1 << REISERFS_GRPQUOTA))
+               seq_puts(seq, ",grpquota");
+       if (REISERFS_SB(s)->s_jquota_fmt) {
+               if (REISERFS_SB(s)->s_jquota_fmt == QFMT_VFS_OLD)
+                       seq_puts(seq, ",jqfmt=vfsold");
+               else if (REISERFS_SB(s)->s_jquota_fmt == QFMT_VFS_V0)
+                       seq_puts(seq, ",jqfmt=vfsv0");
+       }
+#endif
+
+       /* Block allocator options */
+       if (opts & (1 << REISERFS_NO_BORDER))
+               seq_puts(seq, ",block-allocator=noborder");
+       if (opts & (1 << REISERFS_NO_UNHASHED_RELOCATION))
+               seq_puts(seq, ",block-allocator=no_unhashed_relocation");
+       if (opts & (1 << REISERFS_HASHED_RELOCATION))
+               seq_puts(seq, ",block-allocator=hashed_relocation");
+       if (opts & (1 << REISERFS_TEST4))
+               seq_puts(seq, ",block-allocator=test4");
+       show_alloc_options(seq, s);
+       return 0;
+}
+
 #ifdef CONFIG_QUOTA
 static ssize_t reiserfs_quota_write(struct super_block *, int, const char *,
                                    size_t, loff_t);
@@ -617,7 +698,7 @@ static const struct super_operations reiserfs_sops = {
        .unfreeze_fs = reiserfs_unfreeze,
        .statfs = reiserfs_statfs,
        .remount_fs = reiserfs_remount,
-       .show_options = generic_show_options,
+       .show_options = reiserfs_show_options,
 #ifdef CONFIG_QUOTA
        .quota_read = reiserfs_quota_read,
        .quota_write = reiserfs_quota_write,
@@ -915,9 +996,9 @@ static int reiserfs_parse_options(struct super_block *s, char *options,     /* strin
                {"jdev",.arg_required = 'j',.values = NULL},
                {"nolargeio",.arg_required = 'w',.values = NULL},
                {"commit",.arg_required = 'c',.values = NULL},
-               {"usrquota",.setmask = 1 << REISERFS_QUOTA},
-               {"grpquota",.setmask = 1 << REISERFS_QUOTA},
-               {"noquota",.clrmask = 1 << REISERFS_QUOTA},
+               {"usrquota",.setmask = 1 << REISERFS_USRQUOTA},
+               {"grpquota",.setmask = 1 << REISERFS_GRPQUOTA},
+               {"noquota",.clrmask = 1 << REISERFS_USRQUOTA | 1 << REISERFS_GRPQUOTA},
                {"errors",.arg_required = 'e',.values = error_actions},
                {"usrjquota",.arg_required =
                 'u' | (1 << REISERFS_OPT_ALLOWEMPTY),.values = NULL},
@@ -1031,12 +1112,19 @@ static int reiserfs_parse_options(struct super_block *s, char *options, /* strin
                                        return 0;
                                }
                                strcpy(qf_names[qtype], arg);
-                               *mount_options |= 1 << REISERFS_QUOTA;
+                               if (qtype == USRQUOTA)
+                                       *mount_options |= 1 << REISERFS_USRQUOTA;
+                               else
+                                       *mount_options |= 1 << REISERFS_GRPQUOTA;
                        } else {
                                if (qf_names[qtype] !=
                                    REISERFS_SB(s)->s_qf_names[qtype])
                                        kfree(qf_names[qtype]);
                                qf_names[qtype] = NULL;
+                               if (qtype == USRQUOTA)
+                                       *mount_options &= ~(1 << REISERFS_USRQUOTA);
+                               else
+                                       *mount_options &= ~(1 << REISERFS_GRPQUOTA);
                        }
                }
                if (c == 'f') {
@@ -1075,9 +1163,10 @@ static int reiserfs_parse_options(struct super_block *s, char *options,  /* strin
                                 "journaled quota format not specified.");
                return 0;
        }
-       /* This checking is not precise wrt the quota type but for our purposes it is sufficient */
-       if (!(*mount_options & (1 << REISERFS_QUOTA))
-           && sb_any_quota_loaded(s)) {
+       if ((!(*mount_options & (1 << REISERFS_USRQUOTA)) &&
+              sb_has_quota_loaded(s, USRQUOTA)) ||
+           (!(*mount_options & (1 << REISERFS_GRPQUOTA)) &&
+              sb_has_quota_loaded(s, GRPQUOTA))) {
                reiserfs_warning(s, "super-6516", "quota options must "
                                 "be present when quota is turned on.");
                return 0;
@@ -1164,7 +1253,8 @@ static void handle_quota_files(struct super_block *s, char **qf_names,
                        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;
+       if (*qfmt)
+               REISERFS_SB(s)->s_jquota_fmt = *qfmt;
 }
 #endif
 
@@ -1225,7 +1315,8 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
        safe_mask |= 1 << REISERFS_ERROR_RO;
        safe_mask |= 1 << REISERFS_ERROR_CONTINUE;
        safe_mask |= 1 << REISERFS_ERROR_PANIC;
-       safe_mask |= 1 << REISERFS_QUOTA;
+       safe_mask |= 1 << REISERFS_USRQUOTA;
+       safe_mask |= 1 << REISERFS_GRPQUOTA;
 
        /* Update the bitmask, taking care to keep
         * the bits we're not allowed to change here */
@@ -1428,9 +1519,7 @@ 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;
@@ -1655,22 +1744,19 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
        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,
             &commit_max_age, qf_names, &qfmt) == 0) {
-               goto error;
+               goto error_unlocked;
+       }
+       if (jdev_name && jdev_name[0]) {
+               REISERFS_SB(s)->s_jdev = kstrdup(jdev_name, GFP_KERNEL);
+               if (!REISERFS_SB(s)->s_jdev) {
+                       SWARN(silent, s, "", "Cannot allocate memory for "
+                               "journal device name");
+                       goto error;
+               }
        }
 #ifdef CONFIG_QUOTA
        handle_quota_files(s, qf_names, &qfmt);
@@ -1678,7 +1764,7 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
 
        if (blocks) {
                SWARN(silent, s, "jmacd-7", "resize option for remount only");
-               goto error;
+               goto error_unlocked;
        }
 
        /* try old format (undistributed bitmap, super block in 8-th 1k block of a device) */
@@ -1688,7 +1774,7 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
        else if (read_super_block(s, REISERFS_DISK_OFFSET_IN_BYTES)) {
                SWARN(silent, s, "sh-2021", "can not find reiserfs on %s",
                      reiserfs_bdevname(s));
-               goto error;
+               goto error_unlocked;
        }
 
        rs = SB_DISK_SUPER_BLOCK(s);
@@ -1704,7 +1790,7 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
                      "or increase size of your LVM partition");
                SWARN(silent, s, "", "Or may be you forgot to "
                      "reboot after fdisk when it told you to");
-               goto error;
+               goto error_unlocked;
        }
 
        sbi->s_mount_state = SB_REISERFS_STATE(s);
@@ -1712,8 +1798,9 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
 
        if ((errval = reiserfs_init_bitmap_cache(s))) {
                SWARN(silent, s, "jmacd-8", "unable to read bitmap");
-               goto error;
+               goto error_unlocked;
        }
+
        errval = -EINVAL;
 #ifdef CONFIG_REISERFS_CHECK
        SWARN(silent, s, "", "CONFIG_REISERFS_CHECK is set ON");
@@ -1736,24 +1823,26 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
        if (reiserfs_barrier_flush(s)) {
                printk("reiserfs: using flush barriers\n");
        }
+
        // set_device_ro(s->s_dev, 1) ;
        if (journal_init(s, jdev_name, old_format, commit_max_age)) {
                SWARN(silent, s, "sh-2022",
                      "unable to initialize journal space");
-               goto error;
+               goto error_unlocked;
        } else {
                jinit_done = 1; /* once this is set, journal_release must be called
                                 ** if we error out of the mount
                                 */
        }
+
        if (reread_meta_blocks(s)) {
                SWARN(silent, s, "jmacd-9",
                      "unable to reread meta blocks after journal init");
-               goto error;
+               goto error_unlocked;
        }
 
        if (replay_only(s))
-               goto error;
+               goto error_unlocked;
 
        if (bdev_read_only(s->s_bdev) && !(s->s_flags & MS_RDONLY)) {
                SWARN(silent, s, "clm-7000",
@@ -1767,19 +1856,27 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
                         reiserfs_init_locked_inode, (void *)(&args));
        if (!root_inode) {
                SWARN(silent, s, "jmacd-10", "get root inode failed");
-               goto error;
+               goto error_unlocked;
        }
 
+       /*
+        * This path assumed to be called with the BKL in the old times.
+        * Now we have inherited the big reiserfs lock from it and many
+        * reiserfs helpers called in the mount path and elsewhere require
+        * this lock to be held even if it's not always necessary. Let's be
+        * conservative and hold it early. The window can be reduced after
+        * careful review of the code.
+        */
+       reiserfs_write_lock(s);
+
        if (root_inode->i_state & I_NEW) {
                reiserfs_read_locked_inode(root_inode, &args);
                unlock_new_inode(root_inode);
        }
 
-       s->s_root = d_alloc_root(root_inode);
-       if (!s->s_root) {
-               iput(root_inode);
+       s->s_root = d_make_root(root_inode);
+       if (!s->s_root)
                goto error;
-       }
        // define and initialize hash function
        sbi->s_hash_function = hash_function(s);
        if (sbi->s_hash_function == NULL) {
@@ -1896,12 +1993,16 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
        return (0);
 
 error:
-       if (jinit_done) {       /* kill the commit thread, free journal ram */
+       reiserfs_write_unlock(s);
+
+error_unlocked:
+       /* kill the commit thread, free journal ram */
+       if (jinit_done) {
+               reiserfs_write_lock(s);
                journal_release_error(NULL, s);
+               reiserfs_write_unlock(s);
        }
 
-       reiserfs_write_unlock(s);
-
        reiserfs_free_bitmap_cache(s);
        if (SB_BUFFER_WITH_SB(s))
                brelse(SB_BUFFER_WITH_SB(s));
@@ -2054,12 +2155,13 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id,
        int err;
        struct inode *inode;
        struct reiserfs_transaction_handle th;
+       int opt = type == USRQUOTA ? REISERFS_USRQUOTA : REISERFS_GRPQUOTA;
 
-       if (!(REISERFS_SB(sb)->s_mount_opt & (1 << REISERFS_QUOTA)))
+       if (!(REISERFS_SB(sb)->s_mount_opt & (1 << opt)))
                return -EINVAL;
 
        /* Quotafile not on the same filesystem? */
-       if (path->mnt->mnt_sb != sb) {
+       if (path->dentry->d_sb != sb) {
                err = -EXDEV;
                goto out;
        }