GFS2: Check rs_free with rd_rsspin protection
authorBob Peterson <rpeterso@redhat.com>
Wed, 6 Jul 2016 15:36:43 +0000 (10:36 -0500)
committerBob Peterson <rpeterso@redhat.com>
Tue, 12 Jul 2016 16:48:22 +0000 (11:48 -0500)
For the last process to close a file opened for write, function
gfs2_rsqa_delete was deleting the file's inode's block reservation
out of the rgrp reservations tree. Then it was checking to make sure
rs_free was 0, but it was performing the check outside the protection
of rd_rsspin spin_lock. The rd_rsspin spin_lock protection is needed
to prevent a race between the process freeing the reservation and
another who is allocating a new set of blocks inside the same rgrp
for the same inode, thus changing its value.

Signed-off-by: Bob Peterson <rpeterso@redhat.com>
fs/gfs2/rgrp.c

index fba38ca94135681fb596f2d27f9481947d6539ad..86ccc01593937d93b7e5901ec26ed30bd5a4ab32 100644 (file)
@@ -658,6 +658,7 @@ void gfs2_rs_deltree(struct gfs2_blkreserv *rs)
        if (rgd) {
                spin_lock(&rgd->rd_rsspin);
                __rs_deltree(rs);
+               BUG_ON(rs->rs_free);
                spin_unlock(&rgd->rd_rsspin);
        }
 }
@@ -671,10 +672,8 @@ void gfs2_rs_deltree(struct gfs2_blkreserv *rs)
 void gfs2_rsqa_delete(struct gfs2_inode *ip, atomic_t *wcount)
 {
        down_write(&ip->i_rw_mutex);
-       if ((wcount == NULL) || (atomic_read(wcount) <= 1)) {
+       if ((wcount == NULL) || (atomic_read(wcount) <= 1))
                gfs2_rs_deltree(&ip->i_res);
-               BUG_ON(ip->i_res.rs_free);
-       }
        up_write(&ip->i_rw_mutex);
        gfs2_qa_delete(ip, wcount);
 }