]> Git Repo - linux.git/commitdiff
Merge tag 'gfs2-v6.1-rc7-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <[email protected]>
Sat, 17 Dec 2022 14:18:04 +0000 (08:18 -0600)
committerLinus Torvalds <[email protected]>
Sat, 17 Dec 2022 14:18:04 +0000 (08:18 -0600)
Pull gfs2 updtaes from Andreas Gruenbacher:

 - Revert a change to delete_work_func() that has gone wrong in commit
   c412a97cf6c5 ("gfs2: Use TRY lock in gfs2_inode_lookup for UNLINKED
   inodes").

 - Avoid dequeuing GL_ASYNC glock holders twice by first checking if the
   holder is still queued.

 - gfs2: Always check the inode size of inline inodes when reading in
   inodes to prevent corrupt filesystem images from causing weid errors.

 - Properly handle a race between gfs2_create_inode() and
   gfs2_inode_lookup() that causes insert_inode_locked4() to return
   -EBUSY.

 - Fix and clean up the interaction between gfs2_create_inode() and
   gfs2_evict_inode() by completely handling the inode deallocation and
   destruction in gfs2_evict_inode().

 - Remove support for glock holder auto-demotion as we have no current
   plans of using this feature again.

 - And a few more minor cleanups and clarifications.

* tag 'gfs2-v6.1-rc7-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2:
  gfs2: Remove support for glock holder auto-demotion (2)
  gfs2: Remove support for glock holder auto-demotion
  gfs2: Minor gfs2_try_evict cleanup
  gfs2: Partially revert gfs2_inode_lookup change
  gfs2: Add gfs2_inode_lookup comment
  gfs2: Uninline and improve glock_{set,clear}_object
  gfs2: Simply dequeue iopen glock in gfs2_evict_inode
  gfs2: Clean up after gfs2_create_inode rework
  gfs2: Avoid dequeuing GL_ASYNC glock holders twice
  gfs2: Make gfs2_glock_hold return its glock argument
  gfs2: Always check inode size of inline inodes
  gfs2: Cosmetic gfs2_dinode_{in,out} cleanup
  gfs2: Handle -EBUSY result of insert_inode_locked4
  gfs2: Fix and clean up create / evict interaction
  gfs2: Clean up initialization of "ip" in gfs2_create_inode
  gfs2: Get rid of ghs[] in gfs2_create_inode
  gfs2: Add extra error check in alloc_dinode

1  2 
fs/gfs2/inode.c

diff --combined fs/gfs2/inode.c
index 1371e067d2a7cd3a43f52111d105640123c60d1d,8d4c4b5c4c0dab55263c78529b914a90c493a73a..614db3055c024f36eec6d06f87a7036eff7efe44
@@@ -142,6 -142,11 +142,11 @@@ struct inode *gfs2_inode_lookup(struct 
                if (unlikely(error))
                        goto fail;
  
+               /*
+                * The only caller that sets @blktype to GFS2_BLKST_UNLINKED is
+                * delete_work_func().  Make sure not to cancel the delete work
+                * from within itself here.
+                */
                if (blktype == GFS2_BLKST_UNLINKED)
                        extra_flags |= LM_FLAG_TRY;
                else
@@@ -403,12 -408,17 +408,17 @@@ static int alloc_dinode(struct gfs2_ino
                goto out_ipreserv;
  
        error = gfs2_alloc_blocks(ip, &ip->i_no_addr, dblocks, 1, &ip->i_generation);
+       if (error)
+               goto out_trans_end;
        ip->i_no_formal_ino = ip->i_generation;
        ip->i_inode.i_ino = ip->i_no_addr;
        ip->i_goal = ip->i_no_addr;
+       if (*dblocks > 1)
+               ip->i_eattr = ip->i_no_addr + 1;
  
+ out_trans_end:
        gfs2_trans_end(sdp);
  out_ipreserv:
        gfs2_inplace_release(ip);
  out_quota:
@@@ -586,6 -596,12 +596,12 @@@ static int gfs2_initxattrs(struct inod
   * @size: The initial size of the inode (ignored for directories)
   * @excl: Force fail if inode exists
   *
+  * FIXME: Change to allocate the disk blocks and write them out in the same
+  * transaction.  That way, we can no longer end up in a situation in which an
+  * inode is allocated, the node crashes, and the block looks like a valid
+  * inode.  (With atomic creates in place, we will also no longer need to zero
+  * the link count and dirty the inode here on failure.)
+  *
   * Returns: 0 on success, or error code
   */
  
@@@ -596,12 -612,12 +612,12 @@@ static int gfs2_create_inode(struct ino
  {
        const struct qstr *name = &dentry->d_name;
        struct posix_acl *default_acl, *acl;
-       struct gfs2_holder ghs[2];
+       struct gfs2_holder d_gh, gh;
        struct inode *inode = NULL;
        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 = 1;
+       int error;
        u32 aflags = 0;
        unsigned blocks = 1;
        struct gfs2_diradd da = { .bh = NULL, .save_loc = 1, };
        if (error)
                goto fail;
  
-       error = gfs2_glock_nq_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs);
+       error = gfs2_glock_nq_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, &d_gh);
        if (error)
                goto fail;
-       gfs2_holder_mark_uninitialized(ghs + 1);
+       gfs2_holder_mark_uninitialized(&gh);
  
        error = create_ok(dip, name, mode);
        if (error)
                        else
                                error = finish_no_open(file, NULL);
                }
-               gfs2_glock_dq_uninit(ghs);
+               gfs2_glock_dq_uninit(&d_gh);
                goto fail;
        } else if (error != -ENOENT) {
                goto fail_gunlock;
        error = -ENOMEM;
        if (!inode)
                goto fail_gunlock;
+       ip = GFS2_I(inode);
  
        error = posix_acl_create(dir, &mode, &default_acl, &acl);
        if (error)
                goto fail_gunlock;
  
-       ip = GFS2_I(inode);
        error = gfs2_qa_get(ip);
        if (error)
                goto fail_free_acls;
                goto fail_free_inode;
        gfs2_cancel_delete_work(io_gl);
  
+ retry:
        error = insert_inode_locked4(inode, ip->i_no_addr, iget_test, &ip->i_no_addr);
-       BUG_ON(error);
+       if (error == -EBUSY)
+               goto retry;
+       if (error)
+               goto fail_gunlock2;
  
        error = gfs2_glock_nq_init(io_gl, LM_ST_SHARED, GL_EXACT | GL_NOPID,
                                   &ip->i_iopen_gh);
        if (error)
                goto fail_gunlock2;
  
-       error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_SKIP, ghs + 1);
+       error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_SKIP, &gh);
        if (error)
                goto fail_gunlock3;
  
        if (error)
                goto fail_gunlock3;
  
-       if (blocks > 1) {
-               ip->i_eattr = ip->i_no_addr + 1;
+       if (blocks > 1)
                gfs2_init_xattr(ip);
-       }
        init_dinode(dip, ip, symname);
        gfs2_trans_end(sdp);
  
        glock_set_object(io_gl, ip);
        gfs2_set_iop(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);
                if (error)
                file->f_mode |= FMODE_CREATED;
                error = finish_open(file, dentry, gfs2_open_common);
        }
-       gfs2_glock_dq_uninit(ghs);
+       gfs2_glock_dq_uninit(&d_gh);
        gfs2_qa_put(ip);
-       gfs2_glock_dq_uninit(ghs + 1);
+       gfs2_glock_dq_uninit(&gh);
        gfs2_glock_put(io_gl);
        gfs2_qa_put(dip);
        unlock_new_inode(inode);
@@@ -801,10 -816,6 +816,6 @@@ fail_gunlock3
  fail_gunlock2:
        gfs2_glock_put(io_gl);
  fail_free_inode:
-       if (ip->i_gl) {
-               if (free_vfs_inode) /* else evict will do the put for us */
-                       gfs2_glock_put(ip->i_gl);
-       }
        gfs2_rs_deltree(&ip->i_res);
        gfs2_qa_put(ip);
  fail_free_acls:
        posix_acl_release(acl);
  fail_gunlock:
        gfs2_dir_no_add(&da);
-       gfs2_glock_dq_uninit(ghs);
+       gfs2_glock_dq_uninit(&d_gh);
        if (!IS_ERR_OR_NULL(inode)) {
+               set_bit(GIF_ALLOC_FAILED, &ip->i_flags);
                clear_nlink(inode);
-               if (!free_vfs_inode)
+               if (ip->i_no_addr)
                        mark_inode_dirty(inode);
-               set_bit(free_vfs_inode ? GIF_FREE_VFS_INODE : GIF_ALLOC_FAILED,
-                       &GFS2_I(inode)->i_flags);
                if (inode->i_state & I_NEW)
                        iget_failed(inode);
                else
                        iput(inode);
        }
-       if (gfs2_holder_initialized(ghs + 1))
-               gfs2_glock_dq_uninit(ghs + 1);
+       if (gfs2_holder_initialized(&gh))
+               gfs2_glock_dq_uninit(&gh);
  fail:
        gfs2_qa_put(dip);
        return error;
@@@ -1997,7 -2007,7 +2007,7 @@@ static int gfs2_setattr(struct user_nam
        else {
                error = gfs2_setattr_simple(inode, attr);
                if (!error && attr->ia_valid & ATTR_MODE)
 -                      error = posix_acl_chmod(&init_user_ns, inode,
 +                      error = posix_acl_chmod(&init_user_ns, dentry,
                                                inode->i_mode);
        }
  
@@@ -2149,7 -2159,7 +2159,7 @@@ static const struct inode_operations gf
        .getattr = gfs2_getattr,
        .listxattr = gfs2_listxattr,
        .fiemap = gfs2_fiemap,
 -      .get_acl = gfs2_get_acl,
 +      .get_inode_acl = gfs2_get_acl,
        .set_acl = gfs2_set_acl,
        .update_time = gfs2_update_time,
        .fileattr_get = gfs2_fileattr_get,
@@@ -2171,7 -2181,7 +2181,7 @@@ static const struct inode_operations gf
        .getattr = gfs2_getattr,
        .listxattr = gfs2_listxattr,
        .fiemap = gfs2_fiemap,
 -      .get_acl = gfs2_get_acl,
 +      .get_inode_acl = gfs2_get_acl,
        .set_acl = gfs2_set_acl,
        .update_time = gfs2_update_time,
        .atomic_open = gfs2_atomic_open,
This page took 0.070677 seconds and 4 git commands to generate.