Merge branches 'rgrp-glock-sharing' and 'gfs2-revoke' from https://git.kernel.org...
[linux-2.6-microblaze.git] / fs / gfs2 / ops_fstype.c
index 6d18d2c..74c7d01 100644 (file)
@@ -110,6 +110,8 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb)
        spin_lock_init(&sdp->sd_trunc_lock);
        spin_lock_init(&sdp->sd_bitmap_lock);
 
+       INIT_LIST_HEAD(&sdp->sd_sc_inodes_list);
+
        mapping = &sdp->sd_aspace;
 
        address_space_init_once(mapping);
@@ -134,8 +136,6 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb)
 
        init_rwsem(&sdp->sd_log_flush_lock);
        atomic_set(&sdp->sd_log_in_flight, 0);
-       atomic_set(&sdp->sd_reserving_log, 0);
-       init_waitqueue_head(&sdp->sd_reserving_log_wait);
        init_waitqueue_head(&sdp->sd_log_flush_wait);
        atomic_set(&sdp->sd_freeze_state, SFS_UNFROZEN);
        mutex_init(&sdp->sd_freeze_mutex);
@@ -169,15 +169,20 @@ static int gfs2_check_sb(struct gfs2_sbd *sdp, int silent)
                return -EINVAL;
        }
 
-       /*  If format numbers match exactly, we're done.  */
-
-       if (sb->sb_fs_format == GFS2_FORMAT_FS &&
-           sb->sb_multihost_format == GFS2_FORMAT_MULTI)
-               return 0;
+       if (sb->sb_fs_format < GFS2_FS_FORMAT_MIN ||
+           sb->sb_fs_format > GFS2_FS_FORMAT_MAX ||
+           sb->sb_multihost_format != GFS2_FORMAT_MULTI) {
+               fs_warn(sdp, "Unknown on-disk format, unable to mount\n");
+               return -EINVAL;
+       }
 
-       fs_warn(sdp, "Unknown on-disk format, unable to mount\n");
+       if (sb->sb_bsize < 512 || sb->sb_bsize > PAGE_SIZE ||
+           (sb->sb_bsize & (sb->sb_bsize - 1))) {
+               pr_warn("Invalid block size\n");
+               return -EINVAL;
+       }
 
-       return -EINVAL;
+       return 0;
 }
 
 static void end_bio_io_page(struct bio *bio)
@@ -311,6 +316,13 @@ static int gfs2_read_sb(struct gfs2_sbd *sdp, int silent)
                                     sizeof(struct gfs2_meta_header))
                * GFS2_NBBY; /* not the rgrp bitmap, subsequent bitmaps only */
 
+       /*
+        * We always keep at least one block reserved for revokes in
+        * transactions.  This greatly simplifies allocating additional
+        * revoke blocks.
+        */
+       atomic_set(&sdp->sd_log_revokes_available, sdp->sd_ldptrs);
+
        /* Compute maximum reservation required to add a entry to a directory */
 
        hash_blocks = DIV_ROUND_UP(sizeof(u64) * BIT(GFS2_DIR_MAX_DEPTH),
@@ -482,6 +494,19 @@ static int init_sb(struct gfs2_sbd *sdp, int silent)
                goto out;
        }
 
+       switch(sdp->sd_sb.sb_fs_format) {
+       case GFS2_FS_FORMAT_MAX:
+               sb->s_xattr = gfs2_xattr_handlers_max;
+               break;
+
+       case GFS2_FS_FORMAT_MIN:
+               sb->s_xattr = gfs2_xattr_handlers_min;
+               break;
+
+       default:
+               BUG();
+       }
+
        /* Set up the buffer cache and SB for real */
        if (sdp->sd_sb.sb_bsize < bdev_logical_block_size(sb->s_bdev)) {
                ret = -EINVAL;
@@ -604,6 +629,94 @@ static int gfs2_jindex_hold(struct gfs2_sbd *sdp, struct gfs2_holder *ji_gh)
        return error;
 }
 
+/**
+ * init_statfs - look up and initialize master and local (per node) statfs inodes
+ * @sdp: The GFS2 superblock
+ *
+ * This should be called after the jindex is initialized in init_journal() and
+ * before gfs2_journal_recovery() is called because we need to be able to write
+ * to these inodes during recovery.
+ *
+ * Returns: errno
+ */
+static int init_statfs(struct gfs2_sbd *sdp)
+{
+       int error = 0;
+       struct inode *master = d_inode(sdp->sd_master_dir);
+       struct inode *pn = NULL;
+       char buf[30];
+       struct gfs2_jdesc *jd;
+       struct gfs2_inode *ip;
+
+       sdp->sd_statfs_inode = gfs2_lookup_simple(master, "statfs");
+       if (IS_ERR(sdp->sd_statfs_inode)) {
+               error = PTR_ERR(sdp->sd_statfs_inode);
+               fs_err(sdp, "can't read in statfs inode: %d\n", error);
+               goto out;
+       }
+       if (sdp->sd_args.ar_spectator)
+               goto out;
+
+       pn = gfs2_lookup_simple(master, "per_node");
+       if (IS_ERR(pn)) {
+               error = PTR_ERR(pn);
+               fs_err(sdp, "can't find per_node directory: %d\n", error);
+               goto put_statfs;
+       }
+
+       /* For each jid, lookup the corresponding local statfs inode in the
+        * per_node metafs directory and save it in the sdp->sd_sc_inodes_list. */
+       list_for_each_entry(jd, &sdp->sd_jindex_list, jd_list) {
+               struct local_statfs_inode *lsi =
+                       kmalloc(sizeof(struct local_statfs_inode), GFP_NOFS);
+               if (!lsi) {
+                       error = -ENOMEM;
+                       goto free_local;
+               }
+               sprintf(buf, "statfs_change%u", jd->jd_jid);
+               lsi->si_sc_inode = gfs2_lookup_simple(pn, buf);
+               if (IS_ERR(lsi->si_sc_inode)) {
+                       error = PTR_ERR(lsi->si_sc_inode);
+                       fs_err(sdp, "can't find local \"sc\" file#%u: %d\n",
+                              jd->jd_jid, error);
+                       goto free_local;
+               }
+               lsi->si_jid = jd->jd_jid;
+               if (jd->jd_jid == sdp->sd_jdesc->jd_jid)
+                       sdp->sd_sc_inode = lsi->si_sc_inode;
+
+               list_add_tail(&lsi->si_list, &sdp->sd_sc_inodes_list);
+       }
+
+       iput(pn);
+       ip = GFS2_I(sdp->sd_sc_inode);
+       error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0,
+                                  &sdp->sd_sc_gh);
+       if (error) {
+               fs_err(sdp, "can't lock local \"sc\" file: %d\n", error);
+               goto free_local;
+       }
+       return 0;
+
+free_local:
+       free_local_statfs_inodes(sdp);
+       iput(pn);
+put_statfs:
+       iput(sdp->sd_statfs_inode);
+out:
+       return error;
+}
+
+/* Uninitialize and free up memory used by the list of statfs inodes */
+static void uninit_statfs(struct gfs2_sbd *sdp)
+{
+       if (!sdp->sd_args.ar_spectator) {
+               gfs2_glock_dq_uninit(&sdp->sd_sc_gh);
+               free_local_statfs_inodes(sdp);
+       }
+       iput(sdp->sd_statfs_inode);
+}
+
 static int init_journal(struct gfs2_sbd *sdp, int undo)
 {
        struct inode *master = d_inode(sdp->sd_master_dir);
@@ -614,7 +727,7 @@ static int init_journal(struct gfs2_sbd *sdp, int undo)
 
        if (undo) {
                jindex = 0;
-               goto fail_jinode_gh;
+               goto fail_statfs;
        }
 
        sdp->sd_jindex = gfs2_lookup_simple(master, "jindex");
@@ -690,6 +803,11 @@ static int init_journal(struct gfs2_sbd *sdp, int undo)
        }
        trace_gfs2_log_blocks(sdp, atomic_read(&sdp->sd_log_blks_free));
 
+       /* Lookup statfs inodes here so journal recovery can use them. */
+       error = init_statfs(sdp);
+       if (error)
+               goto fail_jinode_gh;
+
        if (sdp->sd_lockstruct.ls_first) {
                unsigned int x;
                for (x = 0; x < sdp->sd_journals; x++) {
@@ -698,14 +816,14 @@ static int init_journal(struct gfs2_sbd *sdp, int undo)
                        if (sdp->sd_args.ar_spectator) {
                                error = check_journal_clean(sdp, jd, true);
                                if (error)
-                                       goto fail_jinode_gh;
+                                       goto fail_statfs;
                                continue;
                        }
                        error = gfs2_recover_journal(jd, true);
                        if (error) {
                                fs_err(sdp, "error recovering journal %u: %d\n",
                                       x, error);
-                               goto fail_jinode_gh;
+                               goto fail_statfs;
                        }
                }
 
@@ -714,7 +832,7 @@ static int init_journal(struct gfs2_sbd *sdp, int undo)
                error = gfs2_recover_journal(sdp->sd_jdesc, true);
                if (error) {
                        fs_err(sdp, "error recovering my journal: %d\n", error);
-                       goto fail_jinode_gh;
+                       goto fail_statfs;
                }
        }
 
@@ -725,6 +843,8 @@ static int init_journal(struct gfs2_sbd *sdp, int undo)
        INIT_WORK(&sdp->sd_freeze_work, gfs2_freeze_func);
        return 0;
 
+fail_statfs:
+       uninit_statfs(sdp);
 fail_jinode_gh:
        /* A withdraw may have done dq/uninit so now we need to check it */
        if (!sdp->sd_args.ar_spectator &&
@@ -758,20 +878,12 @@ static int init_inodes(struct gfs2_sbd *sdp, int undo)
        if (error)
                goto fail;
 
-       /* Read in the master statfs inode */
-       sdp->sd_statfs_inode = gfs2_lookup_simple(master, "statfs");
-       if (IS_ERR(sdp->sd_statfs_inode)) {
-               error = PTR_ERR(sdp->sd_statfs_inode);
-               fs_err(sdp, "can't read in statfs inode: %d\n", error);
-               goto fail_journal;
-       }
-
        /* Read in the resource index inode */
        sdp->sd_rindex = gfs2_lookup_simple(master, "rindex");
        if (IS_ERR(sdp->sd_rindex)) {
                error = PTR_ERR(sdp->sd_rindex);
                fs_err(sdp, "can't get resource index inode: %d\n", error);
-               goto fail_statfs;
+               goto fail_journal;
        }
        sdp->sd_rindex_uptodate = 0;
 
@@ -800,8 +912,6 @@ fail_qinode:
 fail_rindex:
        gfs2_clear_rgrpd(sdp);
        iput(sdp->sd_rindex);
-fail_statfs:
-       iput(sdp->sd_statfs_inode);
 fail_journal:
        init_journal(sdp, UNDO);
 fail:
@@ -829,14 +939,6 @@ static int init_per_node(struct gfs2_sbd *sdp, int undo)
                return error;
        }
 
-       sprintf(buf, "statfs_change%u", sdp->sd_jdesc->jd_jid);
-       sdp->sd_sc_inode = gfs2_lookup_simple(pn, buf);
-       if (IS_ERR(sdp->sd_sc_inode)) {
-               error = PTR_ERR(sdp->sd_sc_inode);
-               fs_err(sdp, "can't find local \"sc\" file: %d\n", error);
-               goto fail;
-       }
-
        sprintf(buf, "quota_change%u", sdp->sd_jdesc->jd_jid);
        sdp->sd_qc_inode = gfs2_lookup_simple(pn, buf);
        if (IS_ERR(sdp->sd_qc_inode)) {
@@ -848,33 +950,21 @@ static int init_per_node(struct gfs2_sbd *sdp, int undo)
        iput(pn);
        pn = NULL;
 
-       ip = GFS2_I(sdp->sd_sc_inode);
-       error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0,
-                                  &sdp->sd_sc_gh);
-       if (error) {
-               fs_err(sdp, "can't lock local \"sc\" file: %d\n", error);
-               goto fail_qc_i;
-       }
-
        ip = GFS2_I(sdp->sd_qc_inode);
        error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0,
                                   &sdp->sd_qc_gh);
        if (error) {
                fs_err(sdp, "can't lock local \"qc\" file: %d\n", error);
-               goto fail_ut_gh;
+               goto fail_qc_i;
        }
 
        return 0;
 
 fail_qc_gh:
        gfs2_glock_dq_uninit(&sdp->sd_qc_gh);
-fail_ut_gh:
-       gfs2_glock_dq_uninit(&sdp->sd_sc_gh);
 fail_qc_i:
        iput(sdp->sd_qc_inode);
 fail_ut_i:
-       iput(sdp->sd_sc_inode);
-fail:
        iput(pn);
        return error;
 }
@@ -961,13 +1051,14 @@ hostdata_error:
        }
 
        if (lm->lm_mount == NULL) {
-               fs_info(sdp, "Now mounting FS...\n");
+               fs_info(sdp, "Now mounting FS (format %u)...\n", sdp->sd_sb.sb_fs_format);
                complete_all(&sdp->sd_locking_init);
                return 0;
        }
        ret = lm->lm_mount(sdp, table);
        if (ret == 0)
-               fs_info(sdp, "Joined cluster. Now mounting FS...\n");
+               fs_info(sdp, "Joined cluster. Now mounting FS (format %u)...\n",
+                       sdp->sd_sb.sb_fs_format);
        complete_all(&sdp->sd_locking_init);
        return ret;
 }
@@ -1013,6 +1104,7 @@ static int gfs2_fill_super(struct super_block *sb, struct fs_context *fc)
        int silent = fc->sb_flags & SB_SILENT;
        struct gfs2_sbd *sdp;
        struct gfs2_holder mount_gh;
+       struct gfs2_holder freeze_gh;
        int error;
 
        sdp = init_sbd(sb);
@@ -1036,7 +1128,6 @@ static int gfs2_fill_super(struct super_block *sb, struct fs_context *fc)
        sb->s_op = &gfs2_super_ops;
        sb->s_d_op = &gfs2_dops;
        sb->s_export_op = &gfs2_export_ops;
-       sb->s_xattr = gfs2_xattr_handlers;
        sb->s_qcop = &gfs2_quotactl_ops;
        sb->s_quota_types = QTYPE_MASK_USR | QTYPE_MASK_GRP;
        sb_dqopt(sb)->flags |= DQUOT_QUOTA_SYS_FILE;
@@ -1062,26 +1153,14 @@ static int gfs2_fill_super(struct super_block *sb, struct fs_context *fc)
        }
 
        error = init_names(sdp, silent);
-       if (error) {
-               /* In this case, we haven't initialized sysfs, so we have to
-                  manually free the sdp. */
-               free_sbd(sdp);
-               sb->s_fs_info = NULL;
-               return error;
-       }
+       if (error)
+               goto fail_free;
 
        snprintf(sdp->sd_fsname, sizeof(sdp->sd_fsname), "%s", sdp->sd_table_name);
 
        error = gfs2_sys_fs_add(sdp);
-       /*
-        * If we hit an error here, gfs2_sys_fs_add will have called function
-        * kobject_put which causes the sysfs usage count to go to zero, which
-        * causes sysfs to call function gfs2_sbd_release, which frees sdp.
-        * Subsequent error paths here will call gfs2_sys_fs_del, which also
-        * kobject_put to free sdp.
-        */
        if (error)
-               return error;
+               goto fail_free;
 
        gfs2_create_debugfs_file(sdp);
 
@@ -1097,6 +1176,10 @@ static int gfs2_fill_super(struct super_block *sb, struct fs_context *fc)
        if (error)
                goto fail_locking;
 
+       /* Turn rgrplvb on by default if fs format is recent enough */
+       if (!sdp->sd_args.ar_got_rgrplvb && sdp->sd_sb.sb_fs_format > 1801)
+               sdp->sd_args.ar_rgrplvb = 1;
+
        error = wait_on_journal(sdp);
        if (error)
                goto fail_sb;
@@ -1136,25 +1219,18 @@ static int gfs2_fill_super(struct super_block *sb, struct fs_context *fc)
                goto fail_per_node;
        }
 
-       if (sb_rdonly(sb)) {
-               struct gfs2_holder freeze_gh;
+       error = gfs2_freeze_lock(sdp, &freeze_gh, 0);
+       if (error)
+               goto fail_per_node;
 
-               error = gfs2_glock_nq_init(sdp->sd_freeze_gl, LM_ST_SHARED,
-                                          LM_FLAG_NOEXP | GL_EXACT,
-                                          &freeze_gh);
-               if (error) {
-                       fs_err(sdp, "can't make FS RO: %d\n", error);
-                       goto fail_per_node;
-               }
-               gfs2_glock_dq_uninit(&freeze_gh);
-       } else {
+       if (!sb_rdonly(sb))
                error = gfs2_make_fs_rw(sdp);
-               if (error) {
-                       fs_err(sdp, "can't make FS RW: %d\n", error);
-                       goto fail_per_node;
-               }
-       }
 
+       gfs2_freeze_unlock(&freeze_gh);
+       if (error) {
+               fs_err(sdp, "can't make FS RW: %d\n", error);
+               goto fail_per_node;
+       }
        gfs2_glock_dq_uninit(&mount_gh);
        gfs2_online_uevent(sdp);
        return 0;
@@ -1179,9 +1255,9 @@ fail_lm:
        gfs2_lm_unmount(sdp);
 fail_debug:
        gfs2_delete_debugfs_file(sdp);
-       /* gfs2_sys_fs_del must be the last thing we do, since it causes
-        * sysfs to call function gfs2_sbd_release, which frees sdp. */
        gfs2_sys_fs_del(sdp);
+fail_free:
+       free_sbd(sdp);
        sb->s_fs_info = NULL;
        return error;
 }
@@ -1397,6 +1473,7 @@ static int gfs2_parse_param(struct fs_context *fc, struct fs_parameter *param)
                break;
        case Opt_rgrplvb:
                args->ar_rgrplvb = result.boolean;
+               args->ar_got_rgrplvb = 1;
                break;
        case Opt_loccookie:
                args->ar_loccookie = result.boolean;
@@ -1455,6 +1532,12 @@ static int gfs2_reconfigure(struct fs_context *fc)
                fc->sb_flags |= SB_RDONLY;
 
        if ((sb->s_flags ^ fc->sb_flags) & SB_RDONLY) {
+               struct gfs2_holder freeze_gh;
+
+               error = gfs2_freeze_lock(sdp, &freeze_gh, 0);
+               if (error)
+                       return -EINVAL;
+
                if (fc->sb_flags & SB_RDONLY) {
                        error = gfs2_make_fs_ro(sdp);
                        if (error)
@@ -1464,6 +1547,7 @@ static int gfs2_reconfigure(struct fs_context *fc)
                        if (error)
                                errorfc(fc, "unable to remount read-write");
                }
+               gfs2_freeze_unlock(&freeze_gh);
        }
        sdp->sd_args = *newargs;