gfs2: gfs2_setattr_size error path fix
authorAndreas Gruenbacher <agruenba@redhat.com>
Fri, 10 Dec 2021 13:43:36 +0000 (14:43 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 13 Apr 2022 19:00:54 +0000 (21:00 +0200)
[ Upstream commit 7336905a89f19173bf9301cd50a24421162f417c ]

When gfs2_setattr_size() fails, it calls gfs2_rs_delete(ip, NULL) to get
rid of any reservations the inode may have.  Instead, it should pass in
the inode's write count as the second parameter to allow
gfs2_rs_delete() to figure out if the inode has any writers left.

In a next step, there are two instances of gfs2_rs_delete(ip, NULL) left
where we know that there can be no other users of the inode.  Replace
those with gfs2_rs_deltree(&ip->i_res) to avoid the unnecessary write
count check.

With that, gfs2_rs_delete() is only called with the inode's actual write
count, so get rid of the second parameter.

Fixes: a097dc7e24cb ("GFS2: Make rgrp reservations part of the gfs2_inode structure")
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
fs/gfs2/bmap.c
fs/gfs2/file.c
fs/gfs2/inode.c
fs/gfs2/rgrp.c
fs/gfs2/rgrp.h
fs/gfs2/super.c

index b34c02985d9d2ea671f31afb6ebda29196f9fb0e..6c047570d6a948c3479b3cd52f6e78dbcb6941a4 100644 (file)
@@ -2200,7 +2200,7 @@ int gfs2_setattr_size(struct inode *inode, u64 newsize)
 
        ret = do_shrink(inode, newsize);
 out:
-       gfs2_rs_delete(ip, NULL);
+       gfs2_rs_delete(ip);
        gfs2_qa_put(ip);
        return ret;
 }
index 7bd7581aa6822fccf9d529eaf1278c96447f85f8..2e6f622ed4283ef7602accd3334446467cb18c5c 100644 (file)
@@ -718,7 +718,7 @@ static int gfs2_release(struct inode *inode, struct file *file)
 
        if (file->f_mode & FMODE_WRITE) {
                if (gfs2_rs_active(&ip->i_res))
-                       gfs2_rs_delete(ip, &inode->i_writecount);
+                       gfs2_rs_delete(ip);
                gfs2_qa_put(ip);
        }
        return 0;
index 65ae4fc28ede49a7354a18c6928141a09d5acbfc..74a6b0800e059d925ace05aba56b8c6499fefa82 100644 (file)
@@ -811,7 +811,7 @@ fail_free_inode:
                if (free_vfs_inode) /* else evict will do the put for us */
                        gfs2_glock_put(ip->i_gl);
        }
-       gfs2_rs_delete(ip, NULL);
+       gfs2_rs_deltree(&ip->i_res);
        gfs2_qa_put(ip);
 fail_free_acls:
        posix_acl_release(default_acl);
index eb775e93de97c336b14d84b17f59a78c2d91f4c4..dc55b029afaa4c3494b6e09770b53f7bbf97bde5 100644 (file)
@@ -664,13 +664,14 @@ void gfs2_rs_deltree(struct gfs2_blkreserv *rs)
 /**
  * gfs2_rs_delete - delete a multi-block reservation
  * @ip: The inode for this reservation
- * @wcount: The inode's write count, or NULL
  *
  */
-void gfs2_rs_delete(struct gfs2_inode *ip, atomic_t *wcount)
+void gfs2_rs_delete(struct gfs2_inode *ip)
 {
+       struct inode *inode = &ip->i_inode;
+
        down_write(&ip->i_rw_mutex);
-       if ((wcount == NULL) || (atomic_read(wcount) <= 1))
+       if (atomic_read(&inode->i_writecount) <= 1)
                gfs2_rs_deltree(&ip->i_res);
        up_write(&ip->i_rw_mutex);
 }
index 9a587ada51edaf2c16cc71af4367ab4fd0de5c7c..2d3c150c55bd5c8ecd8d7c58682d97ea5f4e9296 100644 (file)
@@ -45,7 +45,7 @@ extern int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *n,
                             bool dinode, u64 *generation);
 
 extern void gfs2_rs_deltree(struct gfs2_blkreserv *rs);
-extern void gfs2_rs_delete(struct gfs2_inode *ip, atomic_t *wcount);
+extern void gfs2_rs_delete(struct gfs2_inode *ip);
 extern void __gfs2_free_blocks(struct gfs2_inode *ip, struct gfs2_rgrpd *rgd,
                               u64 bstart, u32 blen, int meta);
 extern void gfs2_free_meta(struct gfs2_inode *ip, struct gfs2_rgrpd *rgd,
index d2b7ecbd1b1503a89b0116e66cd08986e0da258d..d14b98aa1c3ebeae654d669d736137908cce98c4 100644 (file)
@@ -1434,7 +1434,7 @@ out:
        truncate_inode_pages_final(&inode->i_data);
        if (ip->i_qadata)
                gfs2_assert_warn(sdp, ip->i_qadata->qa_ref == 0);
-       gfs2_rs_delete(ip, NULL);
+       gfs2_rs_deltree(&ip->i_res);
        gfs2_ordered_del_inode(ip);
        clear_inode(inode);
        gfs2_dir_hash_inval(ip);