]> bbs.cooldavid.org Git - net-next-2.6.git/commitdiff
GFS2: Improve error handling in inode allocation
authorSteven Whitehouse <swhiteho@redhat.com>
Fri, 31 Jul 2009 15:19:40 +0000 (16:19 +0100)
committerSteven Whitehouse <swhiteho@redhat.com>
Mon, 17 Aug 2009 10:05:31 +0000 (11:05 +0100)
A little while back, block allocation was given some improved
error handling which meant that -EIO was returned in the case
of there being a problem in the resource group data. In addition
a message is printed explaning what went wrong and how to fix it.
This extends that error handling so that it also covers inode
allocation too.

Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
fs/gfs2/inode.c
fs/gfs2/rgrp.c
fs/gfs2/rgrp.h

index 2f94bd723698a24723bbe1a84153f979169816ef..f9b4fe88654030ffb67d6e1bfbcb8b2011f727c0 100644 (file)
@@ -731,7 +731,7 @@ static int alloc_dinode(struct gfs2_inode *dip, u64 *no_addr, u64 *generation)
        if (error)
                goto out_ipreserv;
 
-       *no_addr = gfs2_alloc_di(dip, generation);
+       error = gfs2_alloc_di(dip, no_addr, generation);
 
        gfs2_trans_end(sdp);
 
index fba795798d3a1b63f1ea10aab5342d5f044b7f21..3d0193af19c3c43f9cf7f8c39b6ef7fe9402c5dc 100644 (file)
@@ -1459,6 +1459,16 @@ int gfs2_rgrp_dump(struct seq_file *seq, const struct gfs2_glock *gl)
        return 0;
 }
 
+static void gfs2_rgrp_error(struct gfs2_rgrpd *rgd)
+{
+       struct gfs2_sbd *sdp = rgd->rd_sbd;
+       fs_warn(sdp, "rgrp %llu has an error, marking it readonly until umount\n",
+               (unsigned long long)rgd->rd_addr);
+       fs_warn(sdp, "umount on all nodes and run fsck.gfs2 to fix the error\n");
+       gfs2_rgrp_dump(NULL, rgd->rd_gl);
+       rgd->rd_flags |= GFS2_RDF_ERROR;
+}
+
 /**
  * gfs2_alloc_block - Allocate one or more blocks
  * @ip: the inode to allocate the block for
@@ -1520,22 +1530,20 @@ int gfs2_alloc_block(struct gfs2_inode *ip, u64 *bn, unsigned int *n)
        return 0;
 
 rgrp_error:
-       fs_warn(sdp, "rgrp %llu has an error, marking it readonly until umount\n",
-               (unsigned long long)rgd->rd_addr);
-       fs_warn(sdp, "umount on all nodes and run fsck.gfs2 to fix the error\n");
-       gfs2_rgrp_dump(NULL, rgd->rd_gl);
-       rgd->rd_flags |= GFS2_RDF_ERROR;
+       gfs2_rgrp_error(rgd);
        return -EIO;
 }
 
 /**
  * gfs2_alloc_di - Allocate a dinode
  * @dip: the directory that the inode is going in
+ * @bn: the block number which is allocated
+ * @generation: the generation number of the inode
  *
- * Returns: the block allocated
+ * Returns: 0 on success or error
  */
 
-u64 gfs2_alloc_di(struct gfs2_inode *dip, u64 *generation)
+int gfs2_alloc_di(struct gfs2_inode *dip, u64 *bn, u64 *generation)
 {
        struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
        struct gfs2_alloc *al = dip->i_alloc;
@@ -1546,12 +1554,13 @@ u64 gfs2_alloc_di(struct gfs2_inode *dip, u64 *generation)
 
        blk = rgblk_search(rgd, rgd->rd_last_alloc,
                           GFS2_BLKST_FREE, GFS2_BLKST_DINODE, &n);
-       BUG_ON(blk == BFITNOENT);
 
-       rgd->rd_last_alloc = blk;
+       /* Since all blocks are reserved in advance, this shouldn't happen */
+       if (blk == BFITNOENT)
+               goto rgrp_error;
 
+       rgd->rd_last_alloc = blk;
        block = rgd->rd_data0 + blk;
-
        gfs2_assert_withdraw(sdp, rgd->rd_free);
        rgd->rd_free--;
        rgd->rd_dinodes++;
@@ -1568,7 +1577,12 @@ u64 gfs2_alloc_di(struct gfs2_inode *dip, u64 *generation)
        rgd->rd_free_clone--;
        spin_unlock(&sdp->sd_rindex_spin);
        trace_gfs2_block_alloc(dip, block, 1, GFS2_BLKST_DINODE);
-       return block;
+       *bn = block;
+       return 0;
+
+rgrp_error:
+       gfs2_rgrp_error(rgd);
+       return -EIO;
 }
 
 /**
index 1e76ff0f3e00cf24328dbb169b0b38bdff14d25c..a8dedd78245b80199f7c3fb9084f35787ad4a122 100644 (file)
@@ -47,7 +47,7 @@ extern void gfs2_inplace_release(struct gfs2_inode *ip);
 extern unsigned char gfs2_get_block_type(struct gfs2_rgrpd *rgd, u64 block);
 
 extern int gfs2_alloc_block(struct gfs2_inode *ip, u64 *bn, unsigned int *n);
-extern u64 gfs2_alloc_di(struct gfs2_inode *ip, u64 *generation);
+extern int gfs2_alloc_di(struct gfs2_inode *ip, u64 *bn, u64 *generation);
 
 extern void gfs2_free_data(struct gfs2_inode *ip, u64 bstart, u32 blen);
 extern void gfs2_free_meta(struct gfs2_inode *ip, u64 bstart, u32 blen);