GFS2: Clean up reservation removal
authorSteven Whitehouse <swhiteho@redhat.com>
Fri, 27 Sep 2013 11:49:33 +0000 (12:49 +0100)
committerSteven Whitehouse <swhiteho@redhat.com>
Fri, 27 Sep 2013 11:49:33 +0000 (12:49 +0100)
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>
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 62a65fc..21ad0f1 100644 (file)
@@ -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);
index 0621b46..9ad20ed 100644 (file)
@@ -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;
 }
 
index cd58611..4b79c19 100644 (file)
@@ -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:
index 285dd36..d4d10fa 100644 (file)
@@ -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);
index 5b3f4a8..57ea16b 100644 (file)
@@ -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);
index e5639de..35da5b1 100644 (file)
@@ -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);