]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
GFS2: Fix inode allocation error path
authorSteven Whitehouse <swhiteho@redhat.com>
Tue, 2 Aug 2011 12:17:27 +0000 (13:17 +0100)
committerSteven Whitehouse <swhiteho@redhat.com>
Thu, 27 Oct 2011 08:08:00 +0000 (09:08 +0100)
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>
fs/gfs2/incore.h
fs/gfs2/inode.c
fs/gfs2/super.c

index 892ac37de8aed8e272e491354c62352df93e690e..be5801a754060246ff9fca238797f3d30a9a59a2 100644 (file)
@@ -267,6 +267,7 @@ struct gfs2_alloc {
 enum {
        GIF_INVALID             = 0,
        GIF_QD_LOCKED           = 1,
+       GIF_ALLOC_FAILED        = 2,
        GIF_SW_PAGED            = 3,
 };
 
index 6525b804d5ecb6c8a917aeed577272458183af65..c9d634e7067af39af131b41224496166b2ea779d 100644 (file)
@@ -734,10 +734,12 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
 
 fail_gunlock2:
        gfs2_glock_dq_uninit(ghs + 1);
-       if (inode && !IS_ERR(inode))
-               iput(inode);
 fail_gunlock:
        gfs2_glock_dq_uninit(ghs);
+       if (inode && !IS_ERR(inode)) {
+               set_bit(GIF_ALLOC_FAILED, &GFS2_I(inode)->i_flags);
+               iput(inode);
+       }
 fail:
        if (bh)
                brelse(bh);
index afb87615c014be7570131c1e35bceca2b9bea93d..9961de702d1babc25b5923ae6813260fbfd31fa0 100644 (file)
@@ -1471,9 +1471,11 @@ static void gfs2_evict_inode(struct inode *inode)
                goto out;
        }
 
-       error = gfs2_check_blk_type(sdp, ip->i_no_addr, GFS2_BLKST_UNLINKED);
-       if (error)
-               goto out_truncate;
+       if (!test_bit(GIF_ALLOC_FAILED, &ip->i_flags)) {
+               error = gfs2_check_blk_type(sdp, ip->i_no_addr, GFS2_BLKST_UNLINKED);
+               if (error)
+                       goto out_truncate;
+       }
 
        if (test_bit(GIF_INVALID, &ip->i_flags)) {
                error = gfs2_inode_refresh(ip);
@@ -1513,6 +1515,10 @@ static void gfs2_evict_inode(struct inode *inode)
        goto out_unlock;
 
 out_truncate:
+       gfs2_log_flush(sdp, ip->i_gl);
+       write_inode_now(inode, 1);
+       gfs2_ail_flush(ip->i_gl);
+
        /* Case 2 starts here */
        error = gfs2_trans_begin(sdp, 0, sdp->sd_jdesc->jd_blocks);
        if (error)