diff options
Diffstat (limited to 'fs/gfs2/rgrp.c')
-rw-r--r-- | fs/gfs2/rgrp.c | 82 |
1 files changed, 70 insertions, 12 deletions
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index fba795798d3a..18d3a28554ac 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c | |||
@@ -1256,7 +1256,7 @@ void gfs2_inplace_release(struct gfs2_inode *ip) | |||
1256 | * Returns: The block type (GFS2_BLKST_*) | 1256 | * Returns: The block type (GFS2_BLKST_*) |
1257 | */ | 1257 | */ |
1258 | 1258 | ||
1259 | unsigned char gfs2_get_block_type(struct gfs2_rgrpd *rgd, u64 block) | 1259 | static unsigned char gfs2_get_block_type(struct gfs2_rgrpd *rgd, u64 block) |
1260 | { | 1260 | { |
1261 | struct gfs2_bitmap *bi = NULL; | 1261 | struct gfs2_bitmap *bi = NULL; |
1262 | u32 length, rgrp_block, buf_block; | 1262 | u32 length, rgrp_block, buf_block; |
@@ -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,16 +1554,21 @@ 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; |
1564 | if (rgd->rd_free == 0) | ||
1565 | goto rgrp_error; | ||
1554 | 1566 | ||
1555 | gfs2_assert_withdraw(sdp, rgd->rd_free); | ||
1556 | rgd->rd_free--; | 1567 | rgd->rd_free--; |
1557 | rgd->rd_dinodes++; | 1568 | rgd->rd_dinodes++; |
1558 | *generation = rgd->rd_igeneration++; | 1569 | *generation = rgd->rd_igeneration++; |
1570 | if (*generation == 0) | ||
1571 | *generation = rgd->rd_igeneration++; | ||
1559 | gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1); | 1572 | gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1); |
1560 | gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data); | 1573 | gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data); |
1561 | 1574 | ||
@@ -1568,7 +1581,12 @@ u64 gfs2_alloc_di(struct gfs2_inode *dip, u64 *generation) | |||
1568 | rgd->rd_free_clone--; | 1581 | rgd->rd_free_clone--; |
1569 | spin_unlock(&sdp->sd_rindex_spin); | 1582 | spin_unlock(&sdp->sd_rindex_spin); |
1570 | trace_gfs2_block_alloc(dip, block, 1, GFS2_BLKST_DINODE); | 1583 | trace_gfs2_block_alloc(dip, block, 1, GFS2_BLKST_DINODE); |
1571 | return block; | 1584 | *bn = block; |
1585 | return 0; | ||
1586 | |||
1587 | rgrp_error: | ||
1588 | gfs2_rgrp_error(rgd); | ||
1589 | return -EIO; | ||
1572 | } | 1590 | } |
1573 | 1591 | ||
1574 | /** | 1592 | /** |
@@ -1676,6 +1694,46 @@ void gfs2_free_di(struct gfs2_rgrpd *rgd, struct gfs2_inode *ip) | |||
1676 | } | 1694 | } |
1677 | 1695 | ||
1678 | /** | 1696 | /** |
1697 | * gfs2_check_blk_type - Check the type of a block | ||
1698 | * @sdp: The superblock | ||
1699 | * @no_addr: The block number to check | ||
1700 | * @type: The block type we are looking for | ||
1701 | * | ||
1702 | * Returns: 0 if the block type matches the expected type | ||
1703 | * -ESTALE if it doesn't match | ||
1704 | * or -ve errno if something went wrong while checking | ||
1705 | */ | ||
1706 | |||
1707 | int gfs2_check_blk_type(struct gfs2_sbd *sdp, u64 no_addr, unsigned int type) | ||
1708 | { | ||
1709 | struct gfs2_rgrpd *rgd; | ||
1710 | struct gfs2_holder ri_gh, rgd_gh; | ||
1711 | int error; | ||
1712 | |||
1713 | error = gfs2_rindex_hold(sdp, &ri_gh); | ||
1714 | if (error) | ||
1715 | goto fail; | ||
1716 | |||
1717 | error = -EINVAL; | ||
1718 | rgd = gfs2_blk2rgrpd(sdp, no_addr); | ||
1719 | if (!rgd) | ||
1720 | goto fail_rindex; | ||
1721 | |||
1722 | error = gfs2_glock_nq_init(rgd->rd_gl, LM_ST_SHARED, 0, &rgd_gh); | ||
1723 | if (error) | ||
1724 | goto fail_rindex; | ||
1725 | |||
1726 | if (gfs2_get_block_type(rgd, no_addr) != type) | ||
1727 | error = -ESTALE; | ||
1728 | |||
1729 | gfs2_glock_dq_uninit(&rgd_gh); | ||
1730 | fail_rindex: | ||
1731 | gfs2_glock_dq_uninit(&ri_gh); | ||
1732 | fail: | ||
1733 | return error; | ||
1734 | } | ||
1735 | |||
1736 | /** | ||
1679 | * gfs2_rlist_add - add a RG to a list of RGs | 1737 | * gfs2_rlist_add - add a RG to a list of RGs |
1680 | * @sdp: the filesystem | 1738 | * @sdp: the filesystem |
1681 | * @rlist: the list of resource groups | 1739 | * @rlist: the list of resource groups |