aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2011-08-02 08:17:27 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2011-10-21 07:39:23 -0400
commit40ac218f52aa5cac7dc8082f28b61c8b2b29373c (patch)
tree34e86173a2554b738f0141a1c38ffc3191d2f228
parent1d4ec642d9f00d4c531b1a4ae0613091ec1f8e9b (diff)
GFS2: Fix inode allocation error path
If we have got far enough through the inode allocation code path that an inode has already been allocated, then we must call iput to dispose of it, if an error occurs during a later part of the process. This will always be the final iput since there will be no other references to the inode. Unlike when the inode has been unlinked, its block state will be GFS2_BLKST_INODE rather than GFS2_BLKST_UNLINKED so we need to skip the test in ->evict_inode() for this one case in order to ensure that it will be deallocated correctly. This patch adds a new flag in order to ensure that this will happen correctly. Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
-rw-r--r--fs/gfs2/incore.h1
-rw-r--r--fs/gfs2/inode.c6
-rw-r--r--fs/gfs2/super.c12
3 files changed, 14 insertions, 5 deletions
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index 892ac37de8ae..be5801a75406 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -267,6 +267,7 @@ struct gfs2_alloc {
267enum { 267enum {
268 GIF_INVALID = 0, 268 GIF_INVALID = 0,
269 GIF_QD_LOCKED = 1, 269 GIF_QD_LOCKED = 1,
270 GIF_ALLOC_FAILED = 2,
270 GIF_SW_PAGED = 3, 271 GIF_SW_PAGED = 3,
271}; 272};
272 273
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index 900cf986aadc..044efe273b97 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -736,10 +736,12 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
736 736
737fail_gunlock2: 737fail_gunlock2:
738 gfs2_glock_dq_uninit(ghs + 1); 738 gfs2_glock_dq_uninit(ghs + 1);
739 if (inode && !IS_ERR(inode))
740 iput(inode);
741fail_gunlock: 739fail_gunlock:
742 gfs2_glock_dq_uninit(ghs); 740 gfs2_glock_dq_uninit(ghs);
741 if (inode && !IS_ERR(inode)) {
742 set_bit(GIF_ALLOC_FAILED, &GFS2_I(inode)->i_flags);
743 iput(inode);
744 }
743fail: 745fail:
744 if (bh) 746 if (bh)
745 brelse(bh); 747 brelse(bh);
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c
index afb87615c014..9961de702d1b 100644
--- a/fs/gfs2/super.c
+++ b/fs/gfs2/super.c
@@ -1471,9 +1471,11 @@ static void gfs2_evict_inode(struct inode *inode)
1471 goto out; 1471 goto out;
1472 } 1472 }
1473 1473
1474 error = gfs2_check_blk_type(sdp, ip->i_no_addr, GFS2_BLKST_UNLINKED); 1474 if (!test_bit(GIF_ALLOC_FAILED, &ip->i_flags)) {
1475 if (error) 1475 error = gfs2_check_blk_type(sdp, ip->i_no_addr, GFS2_BLKST_UNLINKED);
1476 goto out_truncate; 1476 if (error)
1477 goto out_truncate;
1478 }
1477 1479
1478 if (test_bit(GIF_INVALID, &ip->i_flags)) { 1480 if (test_bit(GIF_INVALID, &ip->i_flags)) {
1479 error = gfs2_inode_refresh(ip); 1481 error = gfs2_inode_refresh(ip);
@@ -1513,6 +1515,10 @@ static void gfs2_evict_inode(struct inode *inode)
1513 goto out_unlock; 1515 goto out_unlock;
1514 1516
1515out_truncate: 1517out_truncate:
1518 gfs2_log_flush(sdp, ip->i_gl);
1519 write_inode_now(inode, 1);
1520 gfs2_ail_flush(ip->i_gl);
1521
1516 /* Case 2 starts here */ 1522 /* Case 2 starts here */
1517 error = gfs2_trans_begin(sdp, 0, sdp->sd_jdesc->jd_blocks); 1523 error = gfs2_trans_begin(sdp, 0, sdp->sd_jdesc->jd_blocks);
1518 if (error) 1524 if (error)