aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2/rgrp.c
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2009-09-08 13:00:30 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2009-09-08 13:00:30 -0400
commitacf7e2444acfaf4c8540603b76d71010eea3fc24 (patch)
tree7c31957ffbbb4008f368b8640c289f72657330a5 /fs/gfs2/rgrp.c
parent8d8291ae93ecb4a246e87e452d55cca412373300 (diff)
GFS2: Be extra careful about deallocating inodes
There is a potential race in the inode deallocation code if two nodes try to deallocate the same inode at the same time. Most of the issue is solved by the iopen locking. There is still a small window which is not covered by the iopen lock. This patches fixes that and also makes the deallocation code more robust in the face of any errors in the rgrp bitmaps, or erroneous iopen callbacks from other nodes. This does introduce one extra disk read, but that is generally not an issue since its the same block that must be written to later in the deallocation process. The total disk accesses therefore stay the same, Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2/rgrp.c')
-rw-r--r--fs/gfs2/rgrp.c42
1 files changed, 41 insertions, 1 deletions
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index 388a61d12fc8..caaa665d4033 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -1256,7 +1256,7 @@ void gfs2_inplace_release(struct gfs2_inode *ip)
1256 * Returns: The block type (GFS2_BLKST_*) 1256 * Returns: The block type (GFS2_BLKST_*)
1257 */ 1257 */
1258 1258
1259unsigned char gfs2_get_block_type(struct gfs2_rgrpd *rgd, u64 block) 1259static unsigned char gfs2_get_block_type(struct gfs2_rgrpd *rgd, u64 block)
1260{ 1260{
1261 struct gfs2_bitmap *bi = NULL; 1261 struct gfs2_bitmap *bi = NULL;
1262 u32 length, rgrp_block, buf_block; 1262 u32 length, rgrp_block, buf_block;
@@ -1694,6 +1694,46 @@ void gfs2_free_di(struct gfs2_rgrpd *rgd, struct gfs2_inode *ip)
1694} 1694}
1695 1695
1696/** 1696/**
1697 * gfs2_check_blk_type - Check the type of a block
1698 * @sdp: The superblock
1699 * @no_addr: The block number to check
1700 * @type: The block type we are looking for
1701 *
1702 * Returns: 0 if the block type matches the expected type
1703 * -ESTALE if it doesn't match
1704 * or -ve errno if something went wrong while checking
1705 */
1706
1707int gfs2_check_blk_type(struct gfs2_sbd *sdp, u64 no_addr, unsigned int type)
1708{
1709 struct gfs2_rgrpd *rgd;
1710 struct gfs2_holder ri_gh, rgd_gh;
1711 int error;
1712
1713 error = gfs2_rindex_hold(sdp, &ri_gh);
1714 if (error)
1715 goto fail;
1716
1717 error = -EINVAL;
1718 rgd = gfs2_blk2rgrpd(sdp, no_addr);
1719 if (!rgd)
1720 goto fail_rindex;
1721
1722 error = gfs2_glock_nq_init(rgd->rd_gl, LM_ST_SHARED, 0, &rgd_gh);
1723 if (error)
1724 goto fail_rindex;
1725
1726 if (gfs2_get_block_type(rgd, no_addr) != type)
1727 error = -ESTALE;
1728
1729 gfs2_glock_dq_uninit(&rgd_gh);
1730fail_rindex:
1731 gfs2_glock_dq_uninit(&ri_gh);
1732fail:
1733 return error;
1734}
1735
1736/**
1697 * gfs2_rlist_add - add a RG to a list of RGs 1737 * gfs2_rlist_add - add a RG to a list of RGs
1698 * @sdp: the filesystem 1738 * @sdp: the filesystem
1699 * @rlist: the list of resource groups 1739 * @rlist: the list of resource groups