diff options
author | Steven Whitehouse <swhiteho@redhat.com> | 2009-07-31 11:19:40 -0400 |
---|---|---|
committer | Steven Whitehouse <swhiteho@redhat.com> | 2009-08-17 06:05:31 -0400 |
commit | 6050b9c74f24513191fc6b5e4b3583e38d146bf5 (patch) | |
tree | ff77010d008e55f6091df69519182e9f88a78215 | |
parent | 440d6da207e9eef2b576331cfedd5ecae9068663 (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.c | 2 | ||||
-rw-r--r-- | fs/gfs2/rgrp.c | 36 | ||||
-rw-r--r-- | fs/gfs2/rgrp.h | 2 |
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 | ||
1462 | static 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 | ||
1522 | rgrp_error: | 1532 | rgrp_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 | ||
1538 | u64 gfs2_alloc_di(struct gfs2_inode *dip, u64 *generation) | 1546 | int 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 | |||
1583 | rgrp_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); | |||
47 | extern unsigned char gfs2_get_block_type(struct gfs2_rgrpd *rgd, u64 block); | 47 | extern unsigned char gfs2_get_block_type(struct gfs2_rgrpd *rgd, u64 block); |
48 | 48 | ||
49 | extern int gfs2_alloc_block(struct gfs2_inode *ip, u64 *bn, unsigned int *n); | 49 | extern int gfs2_alloc_block(struct gfs2_inode *ip, u64 *bn, unsigned int *n); |
50 | extern u64 gfs2_alloc_di(struct gfs2_inode *ip, u64 *generation); | 50 | extern int gfs2_alloc_di(struct gfs2_inode *ip, u64 *bn, u64 *generation); |
51 | 51 | ||
52 | extern void gfs2_free_data(struct gfs2_inode *ip, u64 bstart, u32 blen); | 52 | extern void gfs2_free_data(struct gfs2_inode *ip, u64 bstart, u32 blen); |
53 | extern void gfs2_free_meta(struct gfs2_inode *ip, u64 bstart, u32 blen); | 53 | extern void gfs2_free_meta(struct gfs2_inode *ip, u64 bstart, u32 blen); |