Merge tag 'gfs2-merge-window' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2...
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 13 Jan 2016 02:09:35 +0000 (18:09 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 13 Jan 2016 02:09:35 +0000 (18:09 -0800)
Pull GFS2 updates from Bob Peterson:
 "Here is a list of patches we've accumulated for GFS2 for the current
  upstream merge window.  Last window's set was short, but I warned that
  this one would be bigger, and so it is.  We've got 19 patches:

   - A patch from Abhi Das to propagate the GFS2_DIF_SYSTEM bit so that
     newly added journals don't get flagged, deleted, and recreated by
     fsck.gfs2.

   - Two patches from Andreas Gruenbacher to improve GFS2 performance
     where extended attributes are involved.

   - A patch from Andy Price to fix a suspicious rcu dereference error.

   - Two patches from Ben Marzinski that rework how GFS2's NFS cookies
     are managed.  This fixes readdir problems with nfs-over-gfs2.

   - A patch from Ben Marzinski that fixes a race in unmounting GFS2.

   - A set of four patches from me to move the resource group
     reservations inside the gfs2 inode to improve performance and fix a
     bug whereby get_write_access improperly prevented some operations
     like chown.

   - A patch from me to spinlock-protect the setting of system statfs
     file data.  This was causing small discrepancies between df and du.

   - A patch from me to reintroduce a timeout while clearing glocks
     which was accidentally dropped some time ago.

   - A patch from me to wait for iopen glock dequeues in order to
     improve deleting of files that were unlinked from a different
     cluster node.

   - A patch from me to ensure metadata address spaces get truncated
     when an inode is evicted.

   - A patch from me to fix a bug in which a memory leak could occur in
     some error cases when inodes were trying to be created.

   - A patch to consistently use iopen glocks to transition from the
     unlinked state to the deleted state.

   - A patch to fix a glock reference count error when inode creation
     fails.

   - A patch from Junxiao Bi to fix an flock panic.

   - A patch from Markus Elfring that removes an unnecessary if"

* tag 'gfs2-merge-window' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2:
  gfs2: fix flock panic issue
  GFS2: Don't do glock put on when inode creation fails
  GFS2: Always use iopen glock for gl_deletes
  GFS2: Release iopen glock in gfs2_create_inode error cases
  GFS2: Truncate address space mapping when deleting an inode
  GFS2: Wait for iopen glock dequeues
  gfs2: clear journal live bit in gfs2_log_flush
  gfs2: change gfs2 readdir cookie
  gfs2: keep offset when splitting dir leaf blocks
  GFS2: Reintroduce a timeout in function gfs2_gl_hash_clear
  GFS2: Update master statfs buffer with sd_statfs_spin locked
  GFS2: Reduce size of incore inode
  GFS2: Make rgrp reservations part of the gfs2_inode structure
  GFS2: Extract quota data from reservations structure (revert 5407e24)
  gfs2: Extended attribute readahead optimization
  gfs2: Extended attribute readahead
  GFS2: Use rht_for_each_entry_rcu in glock_hash_walk
  GFS2: Delete an unnecessary check before the function call "iput"
  gfs2: Automatically set GFS2_DIF_SYSTEM flag on system files

1  2 
fs/gfs2/inode.c
fs/gfs2/ops_fstype.c
fs/gfs2/xattr.c

diff --combined fs/gfs2/inode.c
@@@ -191,13 -191,13 +191,13 @@@ struct inode *gfs2_inode_lookup(struct 
  fail_refresh:
        ip->i_iopen_gh.gh_flags |= GL_NOCACHE;
        ip->i_iopen_gh.gh_gl->gl_object = NULL;
-       gfs2_glock_dq_uninit(&ip->i_iopen_gh);
+       gfs2_glock_dq_wait(&ip->i_iopen_gh);
+       gfs2_holder_uninit(&ip->i_iopen_gh);
  fail_iopen:
        if (io_gl)
                gfs2_glock_put(io_gl);
  fail_put:
        ip->i_gl->gl_object = NULL;
-       gfs2_glock_put(ip->i_gl);
  fail:
        iget_failed(inode);
        return ERR_PTR(error);
@@@ -593,7 -593,7 +593,7 @@@ static int gfs2_create_inode(struct ino
        struct gfs2_inode *dip = GFS2_I(dir), *ip;
        struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
        struct gfs2_glock *io_gl;
-       int error, free_vfs_inode = 0;
+       int error, free_vfs_inode = 1;
        u32 aflags = 0;
        unsigned blocks = 1;
        struct gfs2_diradd da = { .bh = NULL, .save_loc = 1, };
        if (!name->len || name->len > GFS2_FNAMESIZE)
                return -ENAMETOOLONG;
  
-       error = gfs2_rs_alloc(dip);
+       error = gfs2_rsqa_alloc(dip);
        if (error)
                return error;
  
  
        error = posix_acl_create(dir, &mode, &default_acl, &acl);
        if (error)
-               goto fail_free_vfs_inode;
+               goto fail_gunlock;
  
        ip = GFS2_I(inode);
-       error = gfs2_rs_alloc(ip);
+       error = gfs2_rsqa_alloc(ip);
        if (error)
                goto fail_free_acls;
  
                ip->i_entries = 2;
                break;
        }
+       /* Force SYSTEM flag on all files and subdirs of a SYSTEM directory */
+       if (dip->i_diskflags & GFS2_DIF_SYSTEM)
+               ip->i_diskflags |= GFS2_DIF_SYSTEM;
        gfs2_set_inode_flags(inode);
  
        if ((GFS2_I(d_inode(sdp->sd_root_dir)) == dip) ||
        gfs2_set_iop(inode);
        insert_inode_hash(inode);
  
+       free_vfs_inode = 0; /* After this point, the inode is no longer
+                              considered free. Any failures need to undo
+                              the gfs2 structures. */
        if (default_acl) {
                error = gfs2_set_acl(inode, default_acl, ACL_TYPE_DEFAULT);
                posix_acl_release(default_acl);
        return error;
  
  fail_gunlock3:
-       gfs2_glock_dq_uninit(ghs + 1);
-       if (ip->i_gl)
-               gfs2_glock_put(ip->i_gl);
-       goto fail_gunlock;
+       gfs2_glock_dq_uninit(&ip->i_iopen_gh);
+       gfs2_glock_put(io_gl);
  fail_gunlock2:
        gfs2_glock_dq_uninit(ghs + 1);
  fail_free_inode:
        if (ip->i_gl)
                gfs2_glock_put(ip->i_gl);
-       gfs2_rs_delete(ip, NULL);
+       gfs2_rsqa_delete(ip, NULL);
  fail_free_acls:
        if (default_acl)
                posix_acl_release(default_acl);
        if (acl)
                posix_acl_release(acl);
- fail_free_vfs_inode:
-       free_vfs_inode = 1;
  fail_gunlock:
        gfs2_dir_no_add(&da);
        gfs2_glock_dq_uninit(ghs);
@@@ -898,7 -901,7 +901,7 @@@ static int gfs2_link(struct dentry *old
        if (S_ISDIR(inode->i_mode))
                return -EPERM;
  
-       error = gfs2_rs_alloc(dip);
+       error = gfs2_rsqa_alloc(dip);
        if (error)
                return error;
  
@@@ -1371,7 -1374,7 +1374,7 @@@ static int gfs2_rename(struct inode *od
        if (error)
                return error;
  
-       error = gfs2_rs_alloc(ndip);
+       error = gfs2_rsqa_alloc(ndip);
        if (error)
                return error;
  
@@@ -1712,30 -1715,24 +1715,30 @@@ static int gfs2_rename2(struct inode *o
  }
  
  /**
 - * gfs2_follow_link - Follow a symbolic link
 + * gfs2_get_link - Follow a symbolic link
   * @dentry: The dentry of the link
 - * @nd: Data that we pass to vfs_follow_link()
 + * @inode: The inode of the link
 + * @done: destructor for return value
   *
   * This can handle symlinks of any size.
   *
   * Returns: 0 on success or error code
   */
  
 -static const char *gfs2_follow_link(struct dentry *dentry, void **cookie)
 +static const char *gfs2_get_link(struct dentry *dentry,
 +                               struct inode *inode,
 +                               struct delayed_call *done)
  {
 -      struct gfs2_inode *ip = GFS2_I(d_inode(dentry));
 +      struct gfs2_inode *ip = GFS2_I(inode);
        struct gfs2_holder i_gh;
        struct buffer_head *dibh;
        unsigned int size;
        char *buf;
        int error;
  
 +      if (!dentry)
 +              return ERR_PTR(-ECHILD);
 +
        gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &i_gh);
        error = gfs2_glock_nq(&i_gh);
        if (error) {
  out:
        gfs2_glock_dq_uninit(&i_gh);
        if (!IS_ERR(buf))
 -              *cookie = buf;
 +              set_delayed_call(done, kfree_link, buf);
        return buf;
  }
  
@@@ -1860,11 -1857,7 +1863,7 @@@ static int setattr_chown(struct inode *
        if (!(attr->ia_valid & ATTR_GID) || gid_eq(ogid, ngid))
                ogid = ngid = NO_GID_QUOTA_CHANGE;
  
-       error = get_write_access(inode);
-       if (error)
-               return error;
-       error = gfs2_rs_alloc(ip);
+       error = gfs2_rsqa_alloc(ip);
        if (error)
                goto out;
  
@@@ -1904,7 -1897,6 +1903,6 @@@ out_end_trans
  out_gunlock_q:
        gfs2_quota_unlock(ip);
  out:
-       put_write_access(inode);
        return error;
  }
  
@@@ -1926,7 -1918,7 +1924,7 @@@ static int gfs2_setattr(struct dentry *
        struct gfs2_holder i_gh;
        int error;
  
-       error = gfs2_rs_alloc(ip);
+       error = gfs2_rsqa_alloc(ip);
        if (error)
                return error;
  
@@@ -2008,7 -2000,7 +2006,7 @@@ static int gfs2_setxattr(struct dentry 
        gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
        ret = gfs2_glock_nq(&gh);
        if (ret == 0) {
-               ret = gfs2_rs_alloc(ip);
+               ret = gfs2_rsqa_alloc(ip);
                if (ret == 0)
                        ret = generic_setxattr(dentry, name, data, size, flags);
                gfs2_glock_dq(&gh);
@@@ -2049,7 -2041,7 +2047,7 @@@ static int gfs2_removexattr(struct dent
        gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
        ret = gfs2_glock_nq(&gh);
        if (ret == 0) {
-               ret = gfs2_rs_alloc(ip);
+               ret = gfs2_rsqa_alloc(ip);
                if (ret == 0)
                        ret = generic_removexattr(dentry, name);
                gfs2_glock_dq(&gh);
@@@ -2138,7 -2130,8 +2136,7 @@@ const struct inode_operations gfs2_dir_
  
  const struct inode_operations gfs2_symlink_iops = {
        .readlink = generic_readlink,
 -      .follow_link = gfs2_follow_link,
 -      .put_link = kfree_put_link,
 +      .get_link = gfs2_get_link,
        .permission = gfs2_permission,
        .setattr = gfs2_setattr,
        .getattr = gfs2_getattr,
diff --combined fs/gfs2/ops_fstype.c
@@@ -352,6 -352,9 +352,9 @@@ static int gfs2_read_sb(struct gfs2_sb
        sdp->sd_jheightsize[x] = ~0;
        gfs2_assert(sdp, sdp->sd_max_jheight <= GFS2_MAX_META_HEIGHT);
  
+       sdp->sd_max_dents_per_leaf = (sdp->sd_sb.sb_bsize -
+                                     sizeof(struct gfs2_leaf)) /
+                                    GFS2_MIN_DIRENT_SIZE;
        return 0;
  }
  
@@@ -910,8 -913,7 +913,7 @@@ fail_qc_i
  fail_ut_i:
        iput(sdp->sd_sc_inode);
  fail:
-       if (pn)
-               iput(pn);
+       iput(pn);
        return error;
  }
  
@@@ -1315,7 -1317,9 +1317,7 @@@ static struct dentry *gfs2_mount(struc
                if ((flags ^ s->s_flags) & MS_RDONLY)
                        goto error_super;
        } else {
 -              char b[BDEVNAME_SIZE];
 -
 -              strlcpy(s->s_id, bdevname(bdev, b), sizeof(s->s_id));
 +              snprintf(s->s_id, sizeof(s->s_id), "%pg", bdev);
                sb_set_blocksize(s, block_size(bdev));
                error = fill_super(s, &args, flags & MS_SILENT ? 1 : 0);
                if (error)
diff --combined fs/gfs2/xattr.c
@@@ -119,7 -119,7 +119,7 @@@ static int ea_foreach(struct gfs2_inod
        __be64 *eablk, *end;
        int error;
  
-       error = gfs2_meta_read(ip->i_gl, ip->i_eattr, DIO_WAIT, &bh);
+       error = gfs2_meta_read(ip->i_gl, ip->i_eattr, DIO_WAIT, 0, &bh);
        if (error)
                return error;
  
                        break;
                bn = be64_to_cpu(*eablk);
  
-               error = gfs2_meta_read(ip->i_gl, bn, DIO_WAIT, &eabh);
+               error = gfs2_meta_read(ip->i_gl, bn, DIO_WAIT, 0, &eabh);
                if (error)
                        break;
                error = ea_foreach_i(ip, eabh, ea_call, data);
@@@ -477,7 -477,7 +477,7 @@@ static int gfs2_iter_unstuffed(struct g
                return -ENOMEM;
  
        for (x = 0; x < nptrs; x++) {
-               error = gfs2_meta_read(ip->i_gl, be64_to_cpu(*dataptrs), 0,
+               error = gfs2_meta_read(ip->i_gl, be64_to_cpu(*dataptrs), 0, 0,
                                       bh + x);
                if (error) {
                        while (x--)
@@@ -583,13 -583,11 +583,13 @@@ out
   *
   * Returns: actual size of data on success, -errno on error
   */
 -static int gfs2_xattr_get(struct dentry *dentry, const char *name,
 -              void *buffer, size_t size, int type)
 +static int gfs2_xattr_get(const struct xattr_handler *handler,
 +                        struct dentry *dentry, const char *name,
 +                        void *buffer, size_t size)
  {
        struct gfs2_inode *ip = GFS2_I(d_inode(dentry));
        struct gfs2_ea_location el;
 +      int type = handler->flags;
        int error;
  
        if (!ip->i_eattr)
@@@ -979,7 -977,7 +979,7 @@@ static int ea_set_block(struct gfs2_ino
        if (ip->i_diskflags & GFS2_DIF_EA_INDIRECT) {
                __be64 *end;
  
-               error = gfs2_meta_read(ip->i_gl, ip->i_eattr, DIO_WAIT,
+               error = gfs2_meta_read(ip->i_gl, ip->i_eattr, DIO_WAIT, 0,
                                       &indbh);
                if (error)
                        return error;
@@@ -1229,12 -1227,61 +1229,12 @@@ int __gfs2_xattr_set(struct inode *inod
        return error;
  }
  
 -static int gfs2_xattr_set(struct dentry *dentry, const char *name,
 -              const void *value, size_t size, int flags, int type)
 +static int gfs2_xattr_set(const struct xattr_handler *handler,
 +                        struct dentry *dentry, const char *name,
 +                        const void *value, size_t size, int flags)
  {
        return __gfs2_xattr_set(d_inode(dentry), name, value,
 -                              size, flags, type);
 -}
 -
 -
 -static int ea_acl_chmod_unstuffed(struct gfs2_inode *ip,
 -                                struct gfs2_ea_header *ea, char *data)
 -{
 -      struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
 -      unsigned int amount = GFS2_EA_DATA_LEN(ea);
 -      unsigned int nptrs = DIV_ROUND_UP(amount, sdp->sd_jbsize);
 -      int ret;
 -
 -      ret = gfs2_trans_begin(sdp, nptrs + RES_DINODE, 0);
 -      if (ret)
 -              return ret;
 -
 -      ret = gfs2_iter_unstuffed(ip, ea, data, NULL);
 -      gfs2_trans_end(sdp);
 -
 -      return ret;
 -}
 -
 -int gfs2_xattr_acl_chmod(struct gfs2_inode *ip, struct iattr *attr, char *data)
 -{
 -      struct inode *inode = &ip->i_inode;
 -      struct gfs2_sbd *sdp = GFS2_SB(inode);
 -      struct gfs2_ea_location el;
 -      int error;
 -
 -      error = gfs2_ea_find(ip, GFS2_EATYPE_SYS, GFS2_POSIX_ACL_ACCESS, &el);
 -      if (error)
 -              return error;
 -
 -      if (GFS2_EA_IS_STUFFED(el.el_ea)) {
 -              error = gfs2_trans_begin(sdp, RES_DINODE + RES_EATTR, 0);
 -              if (error == 0) {
 -                      gfs2_trans_add_meta(ip->i_gl, el.el_bh);
 -                      memcpy(GFS2_EA2DATA(el.el_ea), data,
 -                             GFS2_EA_DATA_LEN(el.el_ea));
 -              }
 -      } else {
 -              error = ea_acl_chmod_unstuffed(ip, el.el_ea, data);
 -      }
 -
 -      brelse(el.el_bh);
 -      if (error)
 -              return error;
 -
 -      error = gfs2_setattr_simple(inode, attr);
 -      gfs2_trans_end(sdp);
 -      return error;
 +                              size, flags, handler->flags);
  }
  
  static int ea_dealloc_indirect(struct gfs2_inode *ip)
  
        memset(&rlist, 0, sizeof(struct gfs2_rgrp_list));
  
-       error = gfs2_meta_read(ip->i_gl, ip->i_eattr, DIO_WAIT, &indbh);
+       error = gfs2_meta_read(ip->i_gl, ip->i_eattr, DIO_WAIT, 0, &indbh);
        if (error)
                return error;