Commit af5c2697 authored by Steven Whitehouse's avatar Steven Whitehouse

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: default avatarSteven Whitehouse <swhiteho@redhat.com>
parent 5ca1db41
...@@ -1279,6 +1279,7 @@ static int do_grow(struct inode *inode, u64 size) ...@@ -1279,6 +1279,7 @@ static int do_grow(struct inode *inode, u64 size)
int gfs2_setattr_size(struct inode *inode, u64 newsize) int gfs2_setattr_size(struct inode *inode, u64 newsize)
{ {
struct gfs2_inode *ip = GFS2_I(inode);
int ret; int ret;
u64 oldsize; u64 oldsize;
...@@ -1294,7 +1295,7 @@ int gfs2_setattr_size(struct inode *inode, u64 newsize) ...@@ -1294,7 +1295,7 @@ int gfs2_setattr_size(struct inode *inode, u64 newsize)
inode_dio_wait(inode); inode_dio_wait(inode);
ret = gfs2_rs_alloc(GFS2_I(inode)); ret = gfs2_rs_alloc(ip);
if (ret) if (ret)
goto out; goto out;
...@@ -1304,6 +1305,7 @@ int gfs2_setattr_size(struct inode *inode, u64 newsize) ...@@ -1304,6 +1305,7 @@ int gfs2_setattr_size(struct inode *inode, u64 newsize)
goto out; goto out;
} }
gfs2_rs_deltree(ip->i_res);
ret = do_shrink(inode, oldsize, newsize); ret = do_shrink(inode, oldsize, newsize);
out: out:
put_write_access(inode); put_write_access(inode);
......
...@@ -620,7 +620,7 @@ static int gfs2_release(struct inode *inode, struct file *file) ...@@ -620,7 +620,7 @@ static int gfs2_release(struct inode *inode, struct file *file)
if (!(file->f_mode & FMODE_WRITE)) if (!(file->f_mode & FMODE_WRITE))
return 0; return 0;
gfs2_rs_delete(ip); gfs2_rs_delete(ip, &inode->i_writecount);
return 0; return 0;
} }
......
...@@ -711,7 +711,7 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, ...@@ -711,7 +711,7 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
fail_free_inode: fail_free_inode:
if (ip->i_gl) if (ip->i_gl)
gfs2_glock_put(ip->i_gl); gfs2_glock_put(ip->i_gl);
gfs2_rs_delete(ip); gfs2_rs_delete(ip, NULL);
free_inode_nonrcu(inode); free_inode_nonrcu(inode);
inode = NULL; inode = NULL;
fail_gunlock: fail_gunlock:
......
...@@ -661,14 +661,13 @@ void gfs2_rs_deltree(struct gfs2_blkreserv *rs) ...@@ -661,14 +661,13 @@ 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) void gfs2_rs_delete(struct gfs2_inode *ip, atomic_t *wcount)
{ {
struct inode *inode = &ip->i_inode;
down_write(&ip->i_rw_mutex); 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); gfs2_rs_deltree(ip->i_res);
BUG_ON(ip->i_res->rs_free); BUG_ON(ip->i_res->rs_free);
kmem_cache_free(gfs2_rsrv_cachep, ip->i_res); 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, ...@@ -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 int gfs2_rs_alloc(struct gfs2_inode *ip);
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); 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_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_meta(struct gfs2_inode *ip, u64 bstart, u32 blen);
extern void gfs2_free_di(struct gfs2_rgrpd *rgd, struct gfs2_inode *ip); extern void gfs2_free_di(struct gfs2_rgrpd *rgd, struct gfs2_inode *ip);
......
...@@ -1526,7 +1526,7 @@ static void gfs2_evict_inode(struct inode *inode) ...@@ -1526,7 +1526,7 @@ static void gfs2_evict_inode(struct inode *inode)
out: out:
/* Case 3 starts here */ /* Case 3 starts here */
truncate_inode_pages(&inode->i_data, 0); truncate_inode_pages(&inode->i_data, 0);
gfs2_rs_delete(ip); gfs2_rs_delete(ip, NULL);
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