GFS2: Clean up reservation removal
The reservation for an inode should be cleared when it is truncated so that we can start again at a different offset for future allocations. We could try and do better than that, by resetting the search based on where the truncation started from, but this is only a first step. In addition, there are three callers of gfs2_rs_delete() but only one of those should really be testing the value of i_writecount. While we get away with that in the other cases currently, I think it would be better if we made that test specific to the one case which requires it. Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
This commit is contained in:
parent
5ca1db41ec
commit
af5c269799
|
@ -1279,6 +1279,7 @@ do_grow_qunlock:
|
|||
|
||||
int gfs2_setattr_size(struct inode *inode, u64 newsize)
|
||||
{
|
||||
struct gfs2_inode *ip = GFS2_I(inode);
|
||||
int ret;
|
||||
u64 oldsize;
|
||||
|
||||
|
@ -1294,7 +1295,7 @@ int gfs2_setattr_size(struct inode *inode, u64 newsize)
|
|||
|
||||
inode_dio_wait(inode);
|
||||
|
||||
ret = gfs2_rs_alloc(GFS2_I(inode));
|
||||
ret = gfs2_rs_alloc(ip);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
|
@ -1304,6 +1305,7 @@ int gfs2_setattr_size(struct inode *inode, u64 newsize)
|
|||
goto out;
|
||||
}
|
||||
|
||||
gfs2_rs_deltree(ip->i_res);
|
||||
ret = do_shrink(inode, oldsize, newsize);
|
||||
out:
|
||||
put_write_access(inode);
|
||||
|
|
|
@ -620,7 +620,7 @@ static int gfs2_release(struct inode *inode, struct file *file)
|
|||
if (!(file->f_mode & FMODE_WRITE))
|
||||
return 0;
|
||||
|
||||
gfs2_rs_delete(ip);
|
||||
gfs2_rs_delete(ip, &inode->i_writecount);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -711,7 +711,7 @@ fail_gunlock2:
|
|||
fail_free_inode:
|
||||
if (ip->i_gl)
|
||||
gfs2_glock_put(ip->i_gl);
|
||||
gfs2_rs_delete(ip);
|
||||
gfs2_rs_delete(ip, NULL);
|
||||
free_inode_nonrcu(inode);
|
||||
inode = NULL;
|
||||
fail_gunlock:
|
||||
|
|
|
@ -661,14 +661,13 @@ 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)
|
||||
void gfs2_rs_delete(struct gfs2_inode *ip, atomic_t *wcount)
|
||||
{
|
||||
struct inode *inode = &ip->i_inode;
|
||||
|
||||
down_write(&ip->i_rw_mutex);
|
||||
if (ip->i_res && atomic_read(&inode->i_writecount) <= 1) {
|
||||
if (ip->i_res && ((wcount == NULL) || (atomic_read(wcount) <= 1))) {
|
||||
gfs2_rs_deltree(ip->i_res);
|
||||
BUG_ON(ip->i_res->rs_free);
|
||||
kmem_cache_free(gfs2_rsrv_cachep, ip->i_res);
|
||||
|
|
|
@ -48,7 +48,7 @@ extern int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *n,
|
|||
|
||||
extern int gfs2_rs_alloc(struct gfs2_inode *ip);
|
||||
extern void gfs2_rs_deltree(struct gfs2_blkreserv *rs);
|
||||
extern void gfs2_rs_delete(struct gfs2_inode *ip);
|
||||
extern void gfs2_rs_delete(struct gfs2_inode *ip, atomic_t *wcount);
|
||||
extern void __gfs2_free_blocks(struct gfs2_inode *ip, u64 bstart, u32 blen, int meta);
|
||||
extern void gfs2_free_meta(struct gfs2_inode *ip, u64 bstart, u32 blen);
|
||||
extern void gfs2_free_di(struct gfs2_rgrpd *rgd, struct gfs2_inode *ip);
|
||||
|
|
|
@ -1526,7 +1526,7 @@ out_unlock:
|
|||
out:
|
||||
/* Case 3 starts here */
|
||||
truncate_inode_pages(&inode->i_data, 0);
|
||||
gfs2_rs_delete(ip);
|
||||
gfs2_rs_delete(ip, NULL);
|
||||
gfs2_ordered_del_inode(ip);
|
||||
clear_inode(inode);
|
||||
gfs2_dir_hash_inval(ip);
|
||||
|
|
Loading…
Reference in a new issue