]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge remote-tracking branch 'gfs2/master'
authorStephen Rothwell <sfr@canb.auug.org.au>
Tue, 24 Jul 2012 23:55:58 +0000 (09:55 +1000)
committerStephen Rothwell <sfr@canb.auug.org.au>
Tue, 24 Jul 2012 23:55:58 +0000 (09:55 +1000)
1  2 
fs/gfs2/inode.c
fs/gfs2/ops_fstype.c
fs/gfs2/quota.c
fs/gfs2/super.c
fs/gfs2/sys.c

diff --combined fs/gfs2/inode.c
index 867674785fcf04909ae03cd5d6f95752fcaeee6d,c53c67e30bd45b339216892c07f5957c820508fc..4ce22e54730806e02ed0ba70f7e7fc847d513142
@@@ -521,12 -521,13 +521,13 @@@ static int make_dinode(struct gfs2_inod
        int error;
  
        munge_mode_uid_gid(dip, &mode, &uid, &gid);
-       if (!gfs2_qadata_get(dip))
-               return -ENOMEM;
+       error = gfs2_rindex_update(sdp);
+       if (error)
+               return error;
  
        error = gfs2_quota_lock(dip, uid, gid);
        if (error)
-               goto out;
+               return error;
  
        error = gfs2_quota_check(dip, uid, gid);
        if (error)
  
  out_quota:
        gfs2_quota_unlock(dip);
- out:
-       gfs2_qadata_put(dip);
        return error;
  }
  
@@@ -551,14 -550,13 +550,13 @@@ static int link_dinode(struct gfs2_inod
                       struct gfs2_inode *ip)
  {
        struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
-       struct gfs2_qadata *qa;
        int alloc_required;
        struct buffer_head *dibh;
        int error;
  
-       qa = gfs2_qadata_get(dip);
-       if (!qa)
-               return -ENOMEM;
+       error = gfs2_rindex_update(sdp);
+       if (error)
+               return error;
  
        error = gfs2_quota_lock(dip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
        if (error)
@@@ -605,13 -603,13 +603,13 @@@ fail_end_trans
        gfs2_trans_end(sdp);
  
  fail_ipreserv:
-       gfs2_inplace_release(dip);
+       if (alloc_required)
+               gfs2_inplace_release(dip);
  
  fail_quota_locks:
        gfs2_quota_unlock(dip);
  
  fail:
-       gfs2_qadata_put(dip);
        return error;
  }
  
@@@ -657,7 -655,7 +655,7 @@@ static int gfs2_create_inode(struct ino
        const struct qstr *name = &dentry->d_name;
        struct gfs2_holder ghs[2];
        struct inode *inode = NULL;
-       struct gfs2_inode *dip = GFS2_I(dir);
+       struct gfs2_inode *dip = GFS2_I(dir), *ip;
        struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
        struct gfs2_inum_host inum = { .no_addr = 0, .no_formal_ino = 0 };
        int error;
        if (!name->len || name->len > GFS2_FNAMESIZE)
                return -ENAMETOOLONG;
  
+       /* We need a reservation to allocate the new dinode block. The
+          directory ip temporarily points to the reservation, but this is
+          being done to get a set of contiguous blocks for the new dinode.
+          Since this is a create, we don't have a sizehint yet, so it will
+          have to use the minimum reservation size. */
+       error = gfs2_rs_alloc(dip);
+       if (error)
+               return error;
        error = gfs2_glock_nq_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs);
        if (error)
                goto fail;
        if (IS_ERR(inode))
                goto fail_gunlock2;
  
-       error = gfs2_inode_refresh(GFS2_I(inode));
+       ip = GFS2_I(inode);
+       error = gfs2_inode_refresh(ip);
        if (error)
                goto fail_gunlock2;
  
+       /* The newly created inode needs a reservation so it can allocate
+          xattrs. At the same time, we want new blocks allocated to the new
+          dinode to be as contiguous as possible. Since we allocated the
+          dinode block under the directory's reservation, we transfer
+          ownership of that reservation to the new inode. The directory
+          doesn't need a reservation unless it needs a new allocation. */
+       ip->i_res = dip->i_res;
+       dip->i_res = NULL;
        error = gfs2_acl_create(dip, inode);
        if (error)
                goto fail_gunlock2;
  
-       error = gfs2_security_init(dip, GFS2_I(inode), name);
+       error = gfs2_security_init(dip, ip, name);
        if (error)
                goto fail_gunlock2;
  
-       error = link_dinode(dip, name, GFS2_I(inode));
+       error = link_dinode(dip, name, ip);
        if (error)
                goto fail_gunlock2;
  
        gfs2_trans_end(sdp);
        /* Check if we reserved space in the rgrp. Function link_dinode may
           not, depending on whether alloc is required. */
-       if (dip->i_res)
+       if (gfs2_mb_reserved(dip))
                gfs2_inplace_release(dip);
        gfs2_quota_unlock(dip);
-       gfs2_qadata_put(dip);
        mark_inode_dirty(inode);
        gfs2_glock_dq_uninit_m(2, ghs);
        d_instantiate(dentry, inode);
@@@ -740,6 -756,7 +756,7 @@@ fail_gunlock
                iput(inode);
        }
  fail:
+       gfs2_rs_delete(dip);
        if (bh)
                brelse(bh);
        return error;
   */
  
  static int gfs2_create(struct inode *dir, struct dentry *dentry,
 -                     umode_t mode, struct nameidata *nd)
 +                     umode_t mode, bool excl)
  {
 -      int excl = 0;
 -      if (nd && (nd->flags & LOOKUP_EXCL))
 -              excl = 1;
        return gfs2_create_inode(dir, dentry, S_IFREG | mode, 0, NULL, 0, excl);
  }
  
   */
  
  static struct dentry *gfs2_lookup(struct inode *dir, struct dentry *dentry,
 -                                struct nameidata *nd)
 +                                unsigned int flags)
  {
        struct inode *inode = gfs2_lookupi(dir, &dentry->d_name, 0);
        if (inode && !IS_ERR(inode)) {
@@@ -816,6 -836,10 +833,10 @@@ static int gfs2_link(struct dentry *old
        if (S_ISDIR(inode->i_mode))
                return -EPERM;
  
+       error = gfs2_rs_alloc(dip);
+       if (error)
+               return error;
        gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs);
        gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + 1);
  
        error = 0;
  
        if (alloc_required) {
-               struct gfs2_qadata *qa = gfs2_qadata_get(dip);
-               if (!qa) {
-                       error = -ENOMEM;
-                       goto out_gunlock;
-               }
                error = gfs2_quota_lock_check(dip);
                if (error)
-                       goto out_alloc;
+                       goto out_gunlock;
  
                error = gfs2_inplace_reserve(dip, sdp->sd_max_dirres);
                if (error)
@@@ -919,9 -936,6 +933,6 @@@ out_ipres
  out_gunlock_q:
        if (alloc_required)
                gfs2_quota_unlock(dip);
- out_alloc:
-       if (alloc_required)
-               gfs2_qadata_put(dip);
  out_gunlock:
        gfs2_glock_dq(ghs + 1);
  out_child:
@@@ -1231,6 -1245,10 +1242,10 @@@ static int gfs2_rename(struct inode *od
        if (error)
                return error;
  
+       error = gfs2_rs_alloc(ndip);
+       if (error)
+               return error;
        if (odip != ndip) {
                error = gfs2_glock_nq_init(sdp->sd_rename_gl, LM_ST_EXCLUSIVE,
                                           0, &r_gh);
                goto out_gunlock;
  
        if (alloc_required) {
-               struct gfs2_qadata *qa = gfs2_qadata_get(ndip);
-               if (!qa) {
-                       error = -ENOMEM;
-                       goto out_gunlock;
-               }
                error = gfs2_quota_lock_check(ndip);
                if (error)
-                       goto out_alloc;
+                       goto out_gunlock;
  
                error = gfs2_inplace_reserve(ndip, sdp->sd_max_dirres);
                if (error)
@@@ -1424,9 -1435,6 +1432,6 @@@ out_ipreserv
  out_gunlock_q:
        if (alloc_required)
                gfs2_quota_unlock(ndip);
- out_alloc:
-       if (alloc_required)
-               gfs2_qadata_put(ndip);
  out_gunlock:
        while (x--) {
                gfs2_glock_dq(ghs + x);
@@@ -1587,12 -1595,9 +1592,9 @@@ static int setattr_chown(struct inode *
        if (!(attr->ia_valid & ATTR_GID) || ogid == ngid)
                ogid = ngid = NO_QUOTA_CHANGE;
  
-       if (!gfs2_qadata_get(ip))
-               return -ENOMEM;
        error = gfs2_quota_lock(ip, nuid, ngid);
        if (error)
-               goto out_alloc;
+               return error;
  
        if (ouid != NO_QUOTA_CHANGE || ogid != NO_QUOTA_CHANGE) {
                error = gfs2_quota_check(ip, nuid, ngid);
@@@ -1618,8 -1623,6 +1620,6 @@@ out_end_trans
        gfs2_trans_end(sdp);
  out_gunlock_q:
        gfs2_quota_unlock(ip);
- out_alloc:
-       gfs2_qadata_put(ip);
        return error;
  }
  
@@@ -1641,6 -1644,10 +1641,10 @@@ static int gfs2_setattr(struct dentry *
        struct gfs2_holder i_gh;
        int error;
  
+       error = gfs2_rs_alloc(ip);
+       if (error)
+               return error;
        error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &i_gh);
        if (error)
                return error;
diff --combined fs/gfs2/ops_fstype.c
index 6c906078f657024c6f17c663b413a97de643e8b0,9b2389756acd6ab4e8c23d51192144bb9f18761c..e5af9dc420ef0c3f1d9a40034b7a63b5791c04f0
@@@ -1118,20 -1118,33 +1118,33 @@@ static int fill_super(struct super_bloc
        }
  
        error = init_names(sdp, silent);
-       if (error)
-               goto fail;
+       if (error) {
+               /* In this case, we haven't initialized sysfs, so we have to
+                  manually free the sdp. */
+               free_percpu(sdp->sd_lkstats);
+               kfree(sdp);
+               sb->s_fs_info = NULL;
+               return error;
+       }
  
        snprintf(sdp->sd_fsname, GFS2_FSNAME_LEN, "%s", sdp->sd_table_name);
  
-       gfs2_create_debugfs_file(sdp);
        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)
-               goto fail;
+               return error;
+       gfs2_create_debugfs_file(sdp);
  
        error = gfs2_lm_mount(sdp, silent);
        if (error)
-               goto fail_sys;
+               goto fail_debug;
  
        error = init_locking(sdp, &mount_gh, DO);
        if (error)
@@@ -1215,12 -1228,12 +1228,12 @@@ fail_locking
  fail_lm:
        gfs2_gl_hash_clear(sdp);
        gfs2_lm_unmount(sdp);
- fail_sys:
-       gfs2_sys_fs_del(sdp);
- fail:
+ fail_debug:
        gfs2_delete_debugfs_file(sdp);
        free_percpu(sdp->sd_lkstats);
-       kfree(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);
        sb->s_fs_info = NULL;
        return error;
  }
@@@ -1286,7 -1299,7 +1299,7 @@@ static struct dentry *gfs2_mount(struc
                error = -EBUSY;
                goto error_bdev;
        }
 -      s = sget(fs_type, test_gfs2_super, set_gfs2_super, bdev);
 +      s = sget(fs_type, test_gfs2_super, set_gfs2_super, flags, bdev);
        mutex_unlock(&bdev->bd_fsfreeze_mutex);
        error = PTR_ERR(s);
        if (IS_ERR(s))
        } else {
                char b[BDEVNAME_SIZE];
  
 -              s->s_flags = flags;
                s->s_mode = mode;
                strlcpy(s->s_id, bdevname(bdev, b), sizeof(s->s_id));
                sb_set_blocksize(s, block_size(bdev));
@@@ -1359,7 -1373,7 +1372,7 @@@ static struct dentry *gfs2_mount_meta(s
                       dev_name, error);
                return ERR_PTR(error);
        }
 -      s = sget(&gfs2_fs_type, test_gfs2_super, set_meta_super,
 +      s = sget(&gfs2_fs_type, test_gfs2_super, set_meta_super, flags,
                 path.dentry->d_inode->i_sb->s_bdev);
        path_put(&path);
        if (IS_ERR(s)) {
@@@ -1389,10 -1403,9 +1402,9 @@@ static void gfs2_kill_sb(struct super_b
        sdp->sd_root_dir = NULL;
        sdp->sd_master_dir = NULL;
        shrink_dcache_sb(sb);
-       kill_block_super(sb);
        gfs2_delete_debugfs_file(sdp);
        free_percpu(sdp->sd_lkstats);
-       kfree(sdp);
+       kill_block_super(sb);
  }
  
  struct file_system_type gfs2_fs_type = {
diff --combined fs/gfs2/quota.c
index 27b5cc7d688166d4e9a74525d6e1ad00133fe94f,7d1ede7b66fc5258d22570178ff716ebff613c38..a3bde91645c29489fce1097456955235f2a63a12
@@@ -494,11 -494,15 +494,15 @@@ static void qdsb_put(struct gfs2_quota_
  int gfs2_quota_hold(struct gfs2_inode *ip, u32 uid, u32 gid)
  {
        struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
-       struct gfs2_qadata *qa = ip->i_qadata;
-       struct gfs2_quota_data **qd = qa->qa_qd;
+       struct gfs2_quota_data **qd;
        int error;
  
-       if (gfs2_assert_warn(sdp, !qa->qa_qd_num) ||
+       if (ip->i_res == NULL)
+               gfs2_rs_alloc(ip);
+       qd = ip->i_res->rs_qa_qd;
+       if (gfs2_assert_warn(sdp, !ip->i_res->rs_qa_qd_num) ||
            gfs2_assert_warn(sdp, !test_bit(GIF_QD_LOCKED, &ip->i_flags)))
                return -EIO;
  
        error = qdsb_get(sdp, QUOTA_USER, ip->i_inode.i_uid, qd);
        if (error)
                goto out;
-       qa->qa_qd_num++;
+       ip->i_res->rs_qa_qd_num++;
        qd++;
  
        error = qdsb_get(sdp, QUOTA_GROUP, ip->i_inode.i_gid, qd);
        if (error)
                goto out;
-       qa->qa_qd_num++;
+       ip->i_res->rs_qa_qd_num++;
        qd++;
  
        if (uid != NO_QUOTA_CHANGE && uid != ip->i_inode.i_uid) {
                error = qdsb_get(sdp, QUOTA_USER, uid, qd);
                if (error)
                        goto out;
-               qa->qa_qd_num++;
+               ip->i_res->rs_qa_qd_num++;
                qd++;
        }
  
                error = qdsb_get(sdp, QUOTA_GROUP, gid, qd);
                if (error)
                        goto out;
-               qa->qa_qd_num++;
+               ip->i_res->rs_qa_qd_num++;
                qd++;
        }
  
@@@ -542,16 -546,17 +546,17 @@@ out
  void gfs2_quota_unhold(struct gfs2_inode *ip)
  {
        struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
-       struct gfs2_qadata *qa = ip->i_qadata;
        unsigned int x;
  
+       if (ip->i_res == NULL)
+               return;
        gfs2_assert_warn(sdp, !test_bit(GIF_QD_LOCKED, &ip->i_flags));
  
-       for (x = 0; x < qa->qa_qd_num; x++) {
-               qdsb_put(qa->qa_qd[x]);
-               qa->qa_qd[x] = NULL;
+       for (x = 0; x < ip->i_res->rs_qa_qd_num; x++) {
+               qdsb_put(ip->i_res->rs_qa_qd[x]);
+               ip->i_res->rs_qa_qd[x] = NULL;
        }
-       qa->qa_qd_num = 0;
+       ip->i_res->rs_qa_qd_num = 0;
  }
  
  static int sort_qd(const void *a, const void *b)
@@@ -764,6 -769,10 +769,10 @@@ static int do_sync(unsigned int num_qd
        unsigned int nalloc = 0, blocks;
        int error;
  
+       error = gfs2_rs_alloc(ip);
+       if (error)
+               return error;
        gfs2_write_calc_reserv(ip, sizeof(struct gfs2_quota),
                              &data_blocks, &ind_blocks);
  
@@@ -915,7 -924,6 +924,6 @@@ fail
  int gfs2_quota_lock(struct gfs2_inode *ip, u32 uid, u32 gid)
  {
        struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
-       struct gfs2_qadata *qa = ip->i_qadata;
        struct gfs2_quota_data *qd;
        unsigned int x;
        int error = 0;
            sdp->sd_args.ar_quota != GFS2_QUOTA_ON)
                return 0;
  
-       sort(qa->qa_qd, qa->qa_qd_num, sizeof(struct gfs2_quota_data *),
-            sort_qd, NULL);
+       sort(ip->i_res->rs_qa_qd, ip->i_res->rs_qa_qd_num,
+            sizeof(struct gfs2_quota_data *), sort_qd, NULL);
  
-       for (x = 0; x < qa->qa_qd_num; x++) {
+       for (x = 0; x < ip->i_res->rs_qa_qd_num; x++) {
                int force = NO_FORCE;
-               qd = qa->qa_qd[x];
+               qd = ip->i_res->rs_qa_qd[x];
                if (test_and_clear_bit(QDF_REFRESH, &qd->qd_flags))
                        force = FORCE;
-               error = do_glock(qd, force, &qa->qa_qd_ghs[x]);
+               error = do_glock(qd, force, &ip->i_res->rs_qa_qd_ghs[x]);
                if (error)
                        break;
        }
                set_bit(GIF_QD_LOCKED, &ip->i_flags);
        else {
                while (x--)
-                       gfs2_glock_dq_uninit(&qa->qa_qd_ghs[x]);
+                       gfs2_glock_dq_uninit(&ip->i_res->rs_qa_qd_ghs[x]);
                gfs2_quota_unhold(ip);
        }
  
@@@ -990,7 -998,6 +998,6 @@@ static int need_sync(struct gfs2_quota_
  
  void gfs2_quota_unlock(struct gfs2_inode *ip)
  {
-       struct gfs2_qadata *qa = ip->i_qadata;
        struct gfs2_quota_data *qda[4];
        unsigned int count = 0;
        unsigned int x;
        if (!test_and_clear_bit(GIF_QD_LOCKED, &ip->i_flags))
                goto out;
  
-       for (x = 0; x < qa->qa_qd_num; x++) {
+       for (x = 0; x < ip->i_res->rs_qa_qd_num; x++) {
                struct gfs2_quota_data *qd;
                int sync;
  
-               qd = qa->qa_qd[x];
+               qd = ip->i_res->rs_qa_qd[x];
                sync = need_sync(qd);
  
-               gfs2_glock_dq_uninit(&qa->qa_qd_ghs[x]);
+               gfs2_glock_dq_uninit(&ip->i_res->rs_qa_qd_ghs[x]);
  
                if (sync && qd_trylock(qd))
                        qda[count++] = qd;
@@@ -1038,7 -1045,6 +1045,6 @@@ static int print_message(struct gfs2_qu
  int gfs2_quota_check(struct gfs2_inode *ip, u32 uid, u32 gid)
  {
        struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
-       struct gfs2_qadata *qa = ip->i_qadata;
        struct gfs2_quota_data *qd;
        s64 value;
        unsigned int x;
          if (sdp->sd_args.ar_quota != GFS2_QUOTA_ON)
                  return 0;
  
-       for (x = 0; x < qa->qa_qd_num; x++) {
-               qd = qa->qa_qd[x];
+       for (x = 0; x < ip->i_res->rs_qa_qd_num; x++) {
+               qd = ip->i_res->rs_qa_qd[x];
  
                if (!((qd->qd_id == uid && test_bit(QDF_USER, &qd->qd_flags)) ||
                      (qd->qd_id == gid && !test_bit(QDF_USER, &qd->qd_flags))))
  void gfs2_quota_change(struct gfs2_inode *ip, s64 change,
                       u32 uid, u32 gid)
  {
-       struct gfs2_qadata *qa = ip->i_qadata;
        struct gfs2_quota_data *qd;
        unsigned int x;
  
        if (ip->i_diskflags & GFS2_DIF_SYSTEM)
                return;
  
-       for (x = 0; x < qa->qa_qd_num; x++) {
-               qd = qa->qa_qd[x];
+       for (x = 0; x < ip->i_res->rs_qa_qd_num; x++) {
+               qd = ip->i_res->rs_qa_qd[x];
  
                if ((qd->qd_id == uid && test_bit(QDF_USER, &qd->qd_flags)) ||
                    (qd->qd_id == gid && !test_bit(QDF_USER, &qd->qd_flags))) {
        }
  }
  
 -int gfs2_quota_sync(struct super_block *sb, int type, int wait)
 +int gfs2_quota_sync(struct super_block *sb, int type)
  {
        struct gfs2_sbd *sdp = sb->s_fs_info;
        struct gfs2_quota_data **qda;
  
  static int gfs2_quota_sync_timeo(struct super_block *sb, int type)
  {
 -      return gfs2_quota_sync(sb, type, 0);
 +      return gfs2_quota_sync(sb, type);
  }
  
  int gfs2_quota_refresh(struct gfs2_sbd *sdp, int user, u32 id)
@@@ -1549,10 -1554,14 +1554,14 @@@ static int gfs2_set_dqblk(struct super_
        if (error)
                return error;
  
+       error = gfs2_rs_alloc(ip);
+       if (error)
+               goto out_put;
        mutex_lock(&ip->i_inode.i_mutex);
        error = gfs2_glock_nq_init(qd->qd_gl, LM_ST_EXCLUSIVE, 0, &q_gh);
        if (error)
-               goto out_put;
+               goto out_unlockput;
        error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &i_gh);
        if (error)
                goto out_q;
@@@ -1609,8 -1618,9 +1618,9 @@@ out_i
        gfs2_glock_dq_uninit(&i_gh);
  out_q:
        gfs2_glock_dq_uninit(&q_gh);
- out_put:
+ out_unlockput:
        mutex_unlock(&ip->i_inode.i_mutex);
+ out_put:
        qd_put(qd);
        return error;
  }
diff --combined fs/gfs2/super.c
index f3d6bbfb32c5308e9893fe6c689bf1935af2bc50,b1502c4bc60d822eabce44e9ff455777f02ff97a..fc3168f47a146a978b733a2dd106aaf50706aeb7
@@@ -78,6 -78,8 +78,8 @@@ enum 
        Opt_quota_quantum,
        Opt_barrier,
        Opt_nobarrier,
+       Opt_rgrplvb,
+       Opt_norgrplvb,
        Opt_error,
  };
  
@@@ -115,6 -117,8 +117,8 @@@ static const match_table_t tokens = 
        {Opt_quota_quantum, "quota_quantum=%d"},
        {Opt_barrier, "barrier"},
        {Opt_nobarrier, "nobarrier"},
+       {Opt_rgrplvb, "rgrplvb"},
+       {Opt_norgrplvb, "norgrplvb"},
        {Opt_error, NULL}
  };
  
@@@ -267,6 -271,12 +271,12 @@@ int gfs2_mount_args(struct gfs2_args *a
                case Opt_nobarrier:
                        args->ar_nobarrier = 1;
                        break;
+               case Opt_rgrplvb:
+                       args->ar_rgrplvb = 1;
+                       break;
+               case Opt_norgrplvb:
+                       args->ar_rgrplvb = 0;
+                       break;
                case Opt_error:
                default:
                        printk(KERN_WARNING "GFS2: invalid mount option: %s\n", o);
@@@ -838,7 -848,7 +848,7 @@@ static int gfs2_make_fs_ro(struct gfs2_
        int error;
  
        flush_workqueue(gfs2_delete_workqueue);
 -      gfs2_quota_sync(sdp->sd_vfs, 0, 1);
 +      gfs2_quota_sync(sdp->sd_vfs, 0);
        gfs2_statfs_sync(sdp->sd_vfs, 0);
  
        error = gfs2_glock_nq_init(sdp->sd_trans_gl, LM_ST_SHARED, GL_NOCACHE,
@@@ -952,8 -962,6 +962,8 @@@ restart
  static int gfs2_sync_fs(struct super_block *sb, int wait)
  {
        struct gfs2_sbd *sdp = sb->s_fs_info;
 +
 +      gfs2_quota_sync(sb, -1);
        if (wait && sdp)
                gfs2_log_flush(sdp, NULL);
        return 0;
@@@ -1381,6 -1389,8 +1391,8 @@@ static int gfs2_show_options(struct seq
                seq_printf(s, ",nobarrier");
        if (test_bit(SDF_DEMOTE, &sdp->sd_flags))
                seq_printf(s, ",demote_interface_used");
+       if (args->ar_rgrplvb)
+               seq_printf(s, ",rgrplvb");
        return 0;
  }
  
@@@ -1401,7 -1411,6 +1413,6 @@@ static void gfs2_final_release_pages(st
  static int gfs2_dinode_dealloc(struct gfs2_inode *ip)
  {
        struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
-       struct gfs2_qadata *qa;
        struct gfs2_rgrpd *rgd;
        struct gfs2_holder gh;
        int error;
                return -EIO;
        }
  
-       qa = gfs2_qadata_get(ip);
-       if (!qa)
-               return -ENOMEM;
+       error = gfs2_rindex_update(sdp);
+       if (error)
+               return error;
  
        error = gfs2_quota_hold(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE);
        if (error)
-               goto out;
+               return error;
  
        rgd = gfs2_blk2rgrpd(sdp, ip->i_no_addr, 1);
        if (!rgd) {
@@@ -1445,8 -1454,6 +1456,6 @@@ out_rg_gunlock
        gfs2_glock_dq_uninit(&gh);
  out_qs:
        gfs2_quota_unhold(ip);
- out:
-       gfs2_qadata_put(ip);
        return error;
  }
  
@@@ -1547,6 -1554,9 +1556,9 @@@ out_truncate
  
  out_unlock:
        /* Error path for case 1 */
+       if (gfs2_rs_active(ip->i_res))
+               gfs2_rs_deltree(ip->i_res);
        if (test_bit(HIF_HOLDER, &ip->i_iopen_gh.gh_iflags))
                gfs2_glock_dq(&ip->i_iopen_gh);
        gfs2_holder_uninit(&ip->i_iopen_gh);
  out:
        /* Case 3 starts here */
        truncate_inode_pages(&inode->i_data, 0);
+       gfs2_rs_delete(ip);
        clear_inode(inode);
        gfs2_dir_hash_inval(ip);
        ip->i_gl->gl_object = NULL;
@@@ -1578,6 -1589,7 +1591,7 @@@ static struct inode *gfs2_alloc_inode(s
                ip->i_flags = 0;
                ip->i_gl = NULL;
                ip->i_rgd = NULL;
+               ip->i_res = NULL;
        }
        return &ip->i_inode;
  }
diff --combined fs/gfs2/sys.c
index 73ecc34c434280ec0c7343ca0f801ea08c784f6e,e4bee4bebbf69153e9333633bc9754bf71a6fcaf..8056b7b7238e9ee7770b21fd7cd5e77835c3062c
@@@ -168,7 -168,7 +168,7 @@@ static ssize_t quota_sync_store(struct 
        if (simple_strtol(buf, NULL, 0) != 1)
                return -EINVAL;
  
 -      gfs2_quota_sync(sdp->sd_vfs, 0, 1);
 +      gfs2_quota_sync(sdp->sd_vfs, 0);
        return len;
  }
  
@@@ -276,7 -276,15 +276,15 @@@ static struct attribute *gfs2_attrs[] 
        NULL,
  };
  
+ static void gfs2_sbd_release(struct kobject *kobj)
+ {
+       struct gfs2_sbd *sdp = container_of(kobj, struct gfs2_sbd, sd_kobj);
+       kfree(sdp);
+ }
  static struct kobj_type gfs2_ktype = {
+       .release = gfs2_sbd_release,
        .default_attrs = gfs2_attrs,
        .sysfs_ops     = &gfs2_attr_ops,
  };
@@@ -583,6 -591,7 +591,7 @@@ int gfs2_sys_fs_add(struct gfs2_sbd *sd
        char ro[20];
        char spectator[20];
        char *envp[] = { ro, spectator, NULL };
+       int sysfs_frees_sdp = 0;
  
        sprintf(ro, "RDONLY=%d", (sb->s_flags & MS_RDONLY) ? 1 : 0);
        sprintf(spectator, "SPECTATOR=%d", sdp->sd_args.ar_spectator ? 1 : 0);
        error = kobject_init_and_add(&sdp->sd_kobj, &gfs2_ktype, NULL,
                                     "%s", sdp->sd_table_name);
        if (error)
-               goto fail;
+               goto fail_reg;
  
+       sysfs_frees_sdp = 1; /* Freeing sdp is now done by sysfs calling
+                               function gfs2_sbd_release. */
        error = sysfs_create_group(&sdp->sd_kobj, &tune_group);
        if (error)
                goto fail_reg;
@@@ -615,9 -626,13 +626,13 @@@ fail_lock_module
  fail_tune:
        sysfs_remove_group(&sdp->sd_kobj, &tune_group);
  fail_reg:
-       kobject_put(&sdp->sd_kobj);
- fail:
+       free_percpu(sdp->sd_lkstats);
        fs_err(sdp, "error %d adding sysfs files", error);
+       if (sysfs_frees_sdp)
+               kobject_put(&sdp->sd_kobj);
+       else
+               kfree(sdp);
+       sb->s_fs_info = NULL;
        return error;
  }