GFS2: Wipe directory hash table metadata when deallocating a directory
authorSteven Whitehouse <swhiteho@redhat.com>
Sat, 21 May 2011 13:05:58 +0000 (14:05 +0100)
committerSteven Whitehouse <swhiteho@redhat.com>
Sat, 21 May 2011 13:05:58 +0000 (14:05 +0100)
The deallocation code for directories in GFS2 is largely divided into
two parts. The first part deallocates any directory leaf blocks and
marks the directory as being a regular file when that is complete. The
second stage was identical to deallocating regular files.

Regular files have their data blocks in a different
address space to directories, and thus what would have been normal data
blocks in a regular file (the hash table in a GFS2 directory) were
deallocated correctly. However, a reference to these blocks was left in the
journal (assuming of course that some previous activity had resulted in
those blocks being in the journal or ail list).

This patch uses the i_depth as a test of whether the inode is an
exhash directory (we cannot test the inode type as that has already
been changed to a regular file at this stage in deallocation)

The original issue was reported by Chris Hertel as an issue he encountered
running bonnie++

Reported-by: Christopher R. Hertel <crh@samba.org>
Cc: Abhijith Das <adas@redhat.com>
Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
fs/gfs2/bmap.c
fs/gfs2/rgrp.c

index 74add2ddcc3fbf05a8a4210e13589f34e1dfc49e..e65493a8ac002ad91a68433bf76dbe2243ff08e1 100644 (file)
@@ -780,6 +780,8 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
        metadata = (height != ip->i_height - 1);
        if (metadata)
                revokes = (height) ? sdp->sd_inptrs : sdp->sd_diptrs;
+       else if (ip->i_depth)
+               revokes = sdp->sd_inptrs;
 
        if (ip != GFS2_I(sdp->sd_rindex))
                error = gfs2_rindex_hold(sdp, &ip->i_alloc->al_ri_gh);
index 7273ad3c85ba4d41d6ef339648444e5fc4d3cc4f..9b780df3fd5476c7014d1db3cf76f1b1a97399fb 100644 (file)
@@ -1629,6 +1629,10 @@ void __gfs2_free_data(struct gfs2_inode *ip, u64 bstart, u32 blen)
        gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data);
 
        gfs2_trans_add_rg(rgd);
+
+       /* Directories keep their data in the metadata address space */
+       if (ip->i_depth)
+               gfs2_meta_wipe(ip, bstart, blen);
 }
 
 /**