aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2/rgrp.c
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2009-05-20 05:48:47 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2009-05-20 05:48:47 -0400
commit09010978345e8883003bf411bb99753710eb5a3a (patch)
treec3a7eaf3a775649d11ad01c2be5d3549e90f6581 /fs/gfs2/rgrp.c
parentef9e8b14a5c1d0afbaf12b4c3b271188ddfc52a4 (diff)
GFS2: Improve resource group error handling
This patch improves the error handling in the case where we discover that the summary information in the resource group doesn't match the bitmap information while in the process of allocating blocks. Originally this resulted in a kernel bug, but this patch changes that so that we return -EIO and print some messages explaining what went wrong, and how to fix it. We also remember locally not to try and allocate from the same rgrp again, so that a subsequent allocation in a different rgrp should succeed. Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2/rgrp.c')
-rw-r--r--fs/gfs2/rgrp.c58
1 files changed, 43 insertions, 15 deletions
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index 565038243fa2..fbacf09ee34e 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -701,10 +701,7 @@ static void gfs2_rgrp_in(struct gfs2_rgrpd *rgd, const void *buf)
701 u32 rg_flags; 701 u32 rg_flags;
702 702
703 rg_flags = be32_to_cpu(str->rg_flags); 703 rg_flags = be32_to_cpu(str->rg_flags);
704 if (rg_flags & GFS2_RGF_NOALLOC) 704 rg_flags &= ~GFS2_RDF_MASK;
705 rgd->rd_flags |= GFS2_RDF_NOALLOC;
706 else
707 rgd->rd_flags &= ~GFS2_RDF_NOALLOC;
708 rgd->rd_free = be32_to_cpu(str->rg_free); 705 rgd->rd_free = be32_to_cpu(str->rg_free);
709 rgd->rd_dinodes = be32_to_cpu(str->rg_dinodes); 706 rgd->rd_dinodes = be32_to_cpu(str->rg_dinodes);
710 rgd->rd_igeneration = be64_to_cpu(str->rg_igeneration); 707 rgd->rd_igeneration = be64_to_cpu(str->rg_igeneration);
@@ -713,11 +710,8 @@ static void gfs2_rgrp_in(struct gfs2_rgrpd *rgd, const void *buf)
713static void gfs2_rgrp_out(struct gfs2_rgrpd *rgd, void *buf) 710static void gfs2_rgrp_out(struct gfs2_rgrpd *rgd, void *buf)
714{ 711{
715 struct gfs2_rgrp *str = buf; 712 struct gfs2_rgrp *str = buf;
716 u32 rg_flags = 0;
717 713
718 if (rgd->rd_flags & GFS2_RDF_NOALLOC) 714 str->rg_flags = cpu_to_be32(rgd->rd_flags & ~GFS2_RDF_MASK);
719 rg_flags |= GFS2_RGF_NOALLOC;
720 str->rg_flags = cpu_to_be32(rg_flags);
721 str->rg_free = cpu_to_be32(rgd->rd_free); 715 str->rg_free = cpu_to_be32(rgd->rd_free);
722 str->rg_dinodes = cpu_to_be32(rgd->rd_dinodes); 716 str->rg_dinodes = cpu_to_be32(rgd->rd_dinodes);
723 str->__pad = cpu_to_be32(0); 717 str->__pad = cpu_to_be32(0);
@@ -942,7 +936,7 @@ static int try_rgrp_fit(struct gfs2_rgrpd *rgd, struct gfs2_alloc *al)
942 struct gfs2_sbd *sdp = rgd->rd_sbd; 936 struct gfs2_sbd *sdp = rgd->rd_sbd;
943 int ret = 0; 937 int ret = 0;
944 938
945 if (rgd->rd_flags & GFS2_RDF_NOALLOC) 939 if (rgd->rd_flags & (GFS2_RGF_NOALLOC | GFS2_RDF_ERROR))
946 return 0; 940 return 0;
947 941
948 spin_lock(&sdp->sd_rindex_spin); 942 spin_lock(&sdp->sd_rindex_spin);
@@ -1435,13 +1429,33 @@ static struct gfs2_rgrpd *rgblk_free(struct gfs2_sbd *sdp, u64 bstart,
1435} 1429}
1436 1430
1437/** 1431/**
1438 * gfs2_alloc_block - Allocate a block 1432 * gfs2_rgrp_dump - print out an rgrp
1433 * @seq: The iterator
1434 * @gl: The glock in question
1435 *
1436 */
1437
1438int gfs2_rgrp_dump(struct seq_file *seq, const struct gfs2_glock *gl)
1439{
1440 const struct gfs2_rgrpd *rgd = gl->gl_object;
1441 if (rgd == NULL)
1442 return 0;
1443 gfs2_print_dbg(seq, " R: n:%llu f:%02x b:%u/%u i:%u\n",
1444 (unsigned long long)rgd->rd_addr, rgd->rd_flags,
1445 rgd->rd_free, rgd->rd_free_clone, rgd->rd_dinodes);
1446 return 0;
1447}
1448
1449/**
1450 * gfs2_alloc_block - Allocate one or more blocks
1439 * @ip: the inode to allocate the block for 1451 * @ip: the inode to allocate the block for
1452 * @bn: Used to return the starting block number
1453 * @n: requested number of blocks/extent length (value/result)
1440 * 1454 *
1441 * Returns: the allocated block 1455 * Returns: 0 or error
1442 */ 1456 */
1443 1457
1444u64 gfs2_alloc_block(struct gfs2_inode *ip, unsigned int *n) 1458int gfs2_alloc_block(struct gfs2_inode *ip, u64 *bn, unsigned int *n)
1445{ 1459{
1446 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); 1460 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
1447 struct buffer_head *dibh; 1461 struct buffer_head *dibh;
@@ -1457,7 +1471,10 @@ u64 gfs2_alloc_block(struct gfs2_inode *ip, unsigned int *n)
1457 goal = rgd->rd_last_alloc; 1471 goal = rgd->rd_last_alloc;
1458 1472
1459 blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, GFS2_BLKST_USED, n); 1473 blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, GFS2_BLKST_USED, n);
1460 BUG_ON(blk == BFITNOENT); 1474
1475 /* Since all blocks are reserved in advance, this shouldn't happen */
1476 if (blk == BFITNOENT)
1477 goto rgrp_error;
1461 1478
1462 rgd->rd_last_alloc = blk; 1479 rgd->rd_last_alloc = blk;
1463 block = rgd->rd_data0 + blk; 1480 block = rgd->rd_data0 + blk;
@@ -1469,7 +1486,9 @@ u64 gfs2_alloc_block(struct gfs2_inode *ip, unsigned int *n)
1469 di->di_goal_meta = di->di_goal_data = cpu_to_be64(ip->i_goal); 1486 di->di_goal_meta = di->di_goal_data = cpu_to_be64(ip->i_goal);
1470 brelse(dibh); 1487 brelse(dibh);
1471 } 1488 }
1472 gfs2_assert_withdraw(sdp, rgd->rd_free >= *n); 1489 if (rgd->rd_free < *n)
1490 goto rgrp_error;
1491
1473 rgd->rd_free -= *n; 1492 rgd->rd_free -= *n;
1474 1493
1475 gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1); 1494 gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1);
@@ -1484,7 +1503,16 @@ u64 gfs2_alloc_block(struct gfs2_inode *ip, unsigned int *n)
1484 rgd->rd_free_clone -= *n; 1503 rgd->rd_free_clone -= *n;
1485 spin_unlock(&sdp->sd_rindex_spin); 1504 spin_unlock(&sdp->sd_rindex_spin);
1486 1505
1487 return block; 1506 *bn = block;
1507 return 0;
1508
1509rgrp_error:
1510 fs_warn(sdp, "rgrp %llu has an error, marking it readonly until umount\n",
1511 (unsigned long long)rgd->rd_addr);
1512 fs_warn(sdp, "umount on all nodes and run fsck.gfs2 to fix the error\n");
1513 gfs2_rgrp_dump(NULL, rgd->rd_gl);
1514 rgd->rd_flags |= GFS2_RDF_ERROR;
1515 return -EIO;
1488} 1516}
1489 1517
1490/** 1518/**