Commit 7336905a authored by Andreas Gruenbacher's avatar Andreas Gruenbacher

gfs2: gfs2_setattr_size error path fix

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: a097dc7e ("GFS2: Make rgrp reservations part of the gfs2_inode structure")
Signed-off-by: default avatarAndreas Gruenbacher <agruenba@redhat.com>
parent 428f651c
...@@ -2146,7 +2146,7 @@ int gfs2_setattr_size(struct inode *inode, u64 newsize) ...@@ -2146,7 +2146,7 @@ int gfs2_setattr_size(struct inode *inode, u64 newsize)
ret = do_shrink(inode, newsize); ret = do_shrink(inode, newsize);
out: out:
gfs2_rs_delete(ip, NULL); gfs2_rs_delete(ip);
gfs2_qa_put(ip); gfs2_qa_put(ip);
return ret; return ret;
} }
......
...@@ -706,7 +706,7 @@ static int gfs2_release(struct inode *inode, struct file *file) ...@@ -706,7 +706,7 @@ static int gfs2_release(struct inode *inode, struct file *file)
if (file->f_mode & FMODE_WRITE) { if (file->f_mode & FMODE_WRITE) {
if (gfs2_rs_active(&ip->i_res)) if (gfs2_rs_active(&ip->i_res))
gfs2_rs_delete(ip, &inode->i_writecount); gfs2_rs_delete(ip);
gfs2_qa_put(ip); gfs2_qa_put(ip);
} }
return 0; return 0;
......
...@@ -793,7 +793,7 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, ...@@ -793,7 +793,7 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
if (free_vfs_inode) /* else evict will do the put for us */ if (free_vfs_inode) /* else evict will do the put for us */
gfs2_glock_put(ip->i_gl); gfs2_glock_put(ip->i_gl);
} }
gfs2_rs_delete(ip, NULL); gfs2_rs_deltree(&ip->i_res);
gfs2_qa_put(ip); gfs2_qa_put(ip);
fail_free_acls: fail_free_acls:
posix_acl_release(default_acl); posix_acl_release(default_acl);
......
...@@ -680,13 +680,14 @@ void gfs2_rs_deltree(struct gfs2_blkreserv *rs) ...@@ -680,13 +680,14 @@ void gfs2_rs_deltree(struct gfs2_blkreserv *rs)
/** /**
* gfs2_rs_delete - delete a multi-block reservation * gfs2_rs_delete - delete a multi-block reservation
* @ip: The inode for this 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); 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); gfs2_rs_deltree(&ip->i_res);
up_write(&ip->i_rw_mutex); up_write(&ip->i_rw_mutex);
} }
......
...@@ -45,7 +45,7 @@ extern int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *n, ...@@ -45,7 +45,7 @@ extern int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *n,
bool dinode, u64 *generation); bool dinode, u64 *generation);
extern void gfs2_rs_deltree(struct gfs2_blkreserv *rs); 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, extern void __gfs2_free_blocks(struct gfs2_inode *ip, struct gfs2_rgrpd *rgd,
u64 bstart, u32 blen, int meta); u64 bstart, u32 blen, int meta);
extern void gfs2_free_meta(struct gfs2_inode *ip, struct gfs2_rgrpd *rgd, extern void gfs2_free_meta(struct gfs2_inode *ip, struct gfs2_rgrpd *rgd,
......
...@@ -1396,7 +1396,7 @@ static void gfs2_evict_inode(struct inode *inode) ...@@ -1396,7 +1396,7 @@ static void gfs2_evict_inode(struct inode *inode)
truncate_inode_pages_final(&inode->i_data); truncate_inode_pages_final(&inode->i_data);
if (ip->i_qadata) if (ip->i_qadata)
gfs2_assert_warn(sdp, ip->i_qadata->qa_ref == 0); 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); gfs2_ordered_del_inode(ip);
clear_inode(inode); clear_inode(inode);
gfs2_dir_hash_inval(ip); gfs2_dir_hash_inval(ip);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment