aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2009-07-31 11:19:40 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2009-08-17 06:05:31 -0400
commit6050b9c74f24513191fc6b5e4b3583e38d146bf5 (patch)
treeff77010d008e55f6091df69519182e9f88a78215
parent440d6da207e9eef2b576331cfedd5ecae9068663 (diff)
GFS2: Improve error handling in inode allocation
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>
-rw-r--r--fs/gfs2/inode.c2
-rw-r--r--fs/gfs2/rgrp.c36
-rw-r--r--fs/gfs2/rgrp.h2
3 files changed, 27 insertions, 13 deletions
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index 2f94bd723698..f9b4fe886540 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -731,7 +731,7 @@ static int alloc_dinode(struct gfs2_inode *dip, u64 *no_addr, u64 *generation)
731 if (error) 731 if (error)
732 goto out_ipreserv; 732 goto out_ipreserv;
733 733
734 *no_addr = gfs2_alloc_di(dip, generation); 734 error = gfs2_alloc_di(dip, no_addr, generation);
735 735
736 gfs2_trans_end(sdp); 736 gfs2_trans_end(sdp);
737 737
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index fba795798d3a..3d0193af19c3 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -1459,6 +1459,16 @@ int gfs2_rgrp_dump(struct seq_file *seq, const struct gfs2_glock *gl)
1459 return 0; 1459 return 0;
1460} 1460}
1461 1461
1462static void gfs2_rgrp_error(struct gfs2_rgrpd *rgd)
1463{
1464 struct gfs2_sbd *sdp = rgd->rd_sbd;
1465 fs_warn(sdp, "rgrp %llu has an error, marking it readonly until umount\n",
1466 (unsigned long long)rgd->rd_addr);
1467 fs_warn(sdp, "umount on all nodes and run fsck.gfs2 to fix the error\n");
1468 gfs2_rgrp_dump(NULL, rgd->rd_gl);
1469 rgd->rd_flags |= GFS2_RDF_ERROR;
1470}
1471
1462/** 1472/**
1463 * gfs2_alloc_block - Allocate one or more blocks 1473 * gfs2_alloc_block - Allocate one or more blocks
1464 * @ip: the inode to allocate the block for 1474 * @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)
1520 return 0; 1530 return 0;
1521 1531
1522rgrp_error: 1532rgrp_error:
1523 fs_warn(sdp, "rgrp %llu has an error, marking it readonly until umount\n", 1533 gfs2_rgrp_error(rgd);
1524 (unsigned long long)rgd->rd_addr);
1525 fs_warn(sdp, "umount on all nodes and run fsck.gfs2 to fix the error\n");
1526 gfs2_rgrp_dump(NULL, rgd->rd_gl);
1527 rgd->rd_flags |= GFS2_RDF_ERROR;
1528 return -EIO; 1534 return -EIO;
1529} 1535}
1530 1536
1531/** 1537/**
1532 * gfs2_alloc_di - Allocate a dinode 1538 * gfs2_alloc_di - Allocate a dinode
1533 * @dip: the directory that the inode is going in 1539 * @dip: the directory that the inode is going in
1540 * @bn: the block number which is allocated
1541 * @generation: the generation number of the inode
1534 * 1542 *
1535 * Returns: the block allocated 1543 * Returns: 0 on success or error
1536 */ 1544 */
1537 1545
1538u64 gfs2_alloc_di(struct gfs2_inode *dip, u64 *generation) 1546int gfs2_alloc_di(struct gfs2_inode *dip, u64 *bn, u64 *generation)
1539{ 1547{
1540 struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); 1548 struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
1541 struct gfs2_alloc *al = dip->i_alloc; 1549 struct gfs2_alloc *al = dip->i_alloc;
@@ -1546,12 +1554,13 @@ u64 gfs2_alloc_di(struct gfs2_inode *dip, u64 *generation)
1546 1554
1547 blk = rgblk_search(rgd, rgd->rd_last_alloc, 1555 blk = rgblk_search(rgd, rgd->rd_last_alloc,
1548 GFS2_BLKST_FREE, GFS2_BLKST_DINODE, &n); 1556 GFS2_BLKST_FREE, GFS2_BLKST_DINODE, &n);
1549 BUG_ON(blk == BFITNOENT);
1550 1557
1551 rgd->rd_last_alloc = blk; 1558 /* Since all blocks are reserved in advance, this shouldn't happen */
1559 if (blk == BFITNOENT)
1560 goto rgrp_error;
1552 1561
1562 rgd->rd_last_alloc = blk;
1553 block = rgd->rd_data0 + blk; 1563 block = rgd->rd_data0 + blk;
1554
1555 gfs2_assert_withdraw(sdp, rgd->rd_free); 1564 gfs2_assert_withdraw(sdp, rgd->rd_free);
1556 rgd->rd_free--; 1565 rgd->rd_free--;
1557 rgd->rd_dinodes++; 1566 rgd->rd_dinodes++;
@@ -1568,7 +1577,12 @@ u64 gfs2_alloc_di(struct gfs2_inode *dip, u64 *generation)
1568 rgd->rd_free_clone--; 1577 rgd->rd_free_clone--;
1569 spin_unlock(&sdp->sd_rindex_spin); 1578 spin_unlock(&sdp->sd_rindex_spin);
1570 trace_gfs2_block_alloc(dip, block, 1, GFS2_BLKST_DINODE); 1579 trace_gfs2_block_alloc(dip, block, 1, GFS2_BLKST_DINODE);
1571 return block; 1580 *bn = block;
1581 return 0;
1582
1583rgrp_error:
1584 gfs2_rgrp_error(rgd);
1585 return -EIO;
1572} 1586}
1573 1587
1574/** 1588/**
diff --git a/fs/gfs2/rgrp.h b/fs/gfs2/rgrp.h
index 1e76ff0f3e00..a8dedd78245b 100644
--- a/fs/gfs2/rgrp.h
+++ b/fs/gfs2/rgrp.h
@@ -47,7 +47,7 @@ extern void gfs2_inplace_release(struct gfs2_inode *ip);
47extern unsigned char gfs2_get_block_type(struct gfs2_rgrpd *rgd, u64 block); 47extern unsigned char gfs2_get_block_type(struct gfs2_rgrpd *rgd, u64 block);
48 48
49extern int gfs2_alloc_block(struct gfs2_inode *ip, u64 *bn, unsigned int *n); 49extern int gfs2_alloc_block(struct gfs2_inode *ip, u64 *bn, unsigned int *n);
50extern u64 gfs2_alloc_di(struct gfs2_inode *ip, u64 *generation); 50extern int gfs2_alloc_di(struct gfs2_inode *ip, u64 *bn, u64 *generation);
51 51
52extern void gfs2_free_data(struct gfs2_inode *ip, u64 bstart, u32 blen); 52extern void gfs2_free_data(struct gfs2_inode *ip, u64 bstart, u32 blen);
53extern void gfs2_free_meta(struct gfs2_inode *ip, u64 bstart, u32 blen); 53extern void gfs2_free_meta(struct gfs2_inode *ip, u64 bstart, u32 blen);