diff options
Diffstat (limited to 'fs/gfs2/rgrp.c')
-rw-r--r-- | fs/gfs2/rgrp.c | 88 |
1 files changed, 74 insertions, 14 deletions
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index fba795798d3a..28c590b7c9da 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c | |||
@@ -857,7 +857,8 @@ static void gfs2_rgrp_send_discards(struct gfs2_sbd *sdp, u64 offset, | |||
857 | goto start_new_extent; | 857 | goto start_new_extent; |
858 | if ((start + nr_sects) != blk) { | 858 | if ((start + nr_sects) != blk) { |
859 | rv = blkdev_issue_discard(bdev, start, | 859 | rv = blkdev_issue_discard(bdev, start, |
860 | nr_sects, GFP_NOFS); | 860 | nr_sects, GFP_NOFS, |
861 | DISCARD_FL_BARRIER); | ||
861 | if (rv) | 862 | if (rv) |
862 | goto fail; | 863 | goto fail; |
863 | nr_sects = 0; | 864 | nr_sects = 0; |
@@ -871,7 +872,8 @@ start_new_extent: | |||
871 | } | 872 | } |
872 | } | 873 | } |
873 | if (nr_sects) { | 874 | if (nr_sects) { |
874 | rv = blkdev_issue_discard(bdev, start, nr_sects, GFP_NOFS); | 875 | rv = blkdev_issue_discard(bdev, start, nr_sects, GFP_NOFS, |
876 | DISCARD_FL_BARRIER); | ||
875 | if (rv) | 877 | if (rv) |
876 | goto fail; | 878 | goto fail; |
877 | } | 879 | } |
@@ -1256,7 +1258,7 @@ void gfs2_inplace_release(struct gfs2_inode *ip) | |||
1256 | * Returns: The block type (GFS2_BLKST_*) | 1258 | * Returns: The block type (GFS2_BLKST_*) |
1257 | */ | 1259 | */ |
1258 | 1260 | ||
1259 | unsigned char gfs2_get_block_type(struct gfs2_rgrpd *rgd, u64 block) | 1261 | static unsigned char gfs2_get_block_type(struct gfs2_rgrpd *rgd, u64 block) |
1260 | { | 1262 | { |
1261 | struct gfs2_bitmap *bi = NULL; | 1263 | struct gfs2_bitmap *bi = NULL; |
1262 | u32 length, rgrp_block, buf_block; | 1264 | u32 length, rgrp_block, buf_block; |
@@ -1459,6 +1461,16 @@ int gfs2_rgrp_dump(struct seq_file *seq, const struct gfs2_glock *gl) | |||
1459 | return 0; | 1461 | return 0; |
1460 | } | 1462 | } |
1461 | 1463 | ||
1464 | static void gfs2_rgrp_error(struct gfs2_rgrpd *rgd) | ||
1465 | { | ||
1466 | struct gfs2_sbd *sdp = rgd->rd_sbd; | ||
1467 | fs_warn(sdp, "rgrp %llu has an error, marking it readonly until umount\n", | ||
1468 | (unsigned long long)rgd->rd_addr); | ||
1469 | fs_warn(sdp, "umount on all nodes and run fsck.gfs2 to fix the error\n"); | ||
1470 | gfs2_rgrp_dump(NULL, rgd->rd_gl); | ||
1471 | rgd->rd_flags |= GFS2_RDF_ERROR; | ||
1472 | } | ||
1473 | |||
1462 | /** | 1474 | /** |
1463 | * gfs2_alloc_block - Allocate one or more blocks | 1475 | * gfs2_alloc_block - Allocate one or more blocks |
1464 | * @ip: the inode to allocate the block for | 1476 | * @ip: the inode to allocate the block for |
@@ -1520,22 +1532,20 @@ int gfs2_alloc_block(struct gfs2_inode *ip, u64 *bn, unsigned int *n) | |||
1520 | return 0; | 1532 | return 0; |
1521 | 1533 | ||
1522 | rgrp_error: | 1534 | rgrp_error: |
1523 | fs_warn(sdp, "rgrp %llu has an error, marking it readonly until umount\n", | 1535 | 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; | 1536 | return -EIO; |
1529 | } | 1537 | } |
1530 | 1538 | ||
1531 | /** | 1539 | /** |
1532 | * gfs2_alloc_di - Allocate a dinode | 1540 | * gfs2_alloc_di - Allocate a dinode |
1533 | * @dip: the directory that the inode is going in | 1541 | * @dip: the directory that the inode is going in |
1542 | * @bn: the block number which is allocated | ||
1543 | * @generation: the generation number of the inode | ||
1534 | * | 1544 | * |
1535 | * Returns: the block allocated | 1545 | * Returns: 0 on success or error |
1536 | */ | 1546 | */ |
1537 | 1547 | ||
1538 | u64 gfs2_alloc_di(struct gfs2_inode *dip, u64 *generation) | 1548 | int gfs2_alloc_di(struct gfs2_inode *dip, u64 *bn, u64 *generation) |
1539 | { | 1549 | { |
1540 | struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); | 1550 | struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); |
1541 | struct gfs2_alloc *al = dip->i_alloc; | 1551 | struct gfs2_alloc *al = dip->i_alloc; |
@@ -1546,16 +1556,21 @@ u64 gfs2_alloc_di(struct gfs2_inode *dip, u64 *generation) | |||
1546 | 1556 | ||
1547 | blk = rgblk_search(rgd, rgd->rd_last_alloc, | 1557 | blk = rgblk_search(rgd, rgd->rd_last_alloc, |
1548 | GFS2_BLKST_FREE, GFS2_BLKST_DINODE, &n); | 1558 | GFS2_BLKST_FREE, GFS2_BLKST_DINODE, &n); |
1549 | BUG_ON(blk == BFITNOENT); | ||
1550 | 1559 | ||
1551 | rgd->rd_last_alloc = blk; | 1560 | /* Since all blocks are reserved in advance, this shouldn't happen */ |
1561 | if (blk == BFITNOENT) | ||
1562 | goto rgrp_error; | ||
1552 | 1563 | ||
1564 | rgd->rd_last_alloc = blk; | ||
1553 | block = rgd->rd_data0 + blk; | 1565 | block = rgd->rd_data0 + blk; |
1566 | if (rgd->rd_free == 0) | ||
1567 | goto rgrp_error; | ||
1554 | 1568 | ||
1555 | gfs2_assert_withdraw(sdp, rgd->rd_free); | ||
1556 | rgd->rd_free--; | 1569 | rgd->rd_free--; |
1557 | rgd->rd_dinodes++; | 1570 | rgd->rd_dinodes++; |
1558 | *generation = rgd->rd_igeneration++; | 1571 | *generation = rgd->rd_igeneration++; |
1572 | if (*generation == 0) | ||
1573 | *generation = rgd->rd_igeneration++; | ||
1559 | gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1); | 1574 | 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); | 1575 | gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data); |
1561 | 1576 | ||
@@ -1568,7 +1583,12 @@ u64 gfs2_alloc_di(struct gfs2_inode *dip, u64 *generation) | |||
1568 | rgd->rd_free_clone--; | 1583 | rgd->rd_free_clone--; |
1569 | spin_unlock(&sdp->sd_rindex_spin); | 1584 | spin_unlock(&sdp->sd_rindex_spin); |
1570 | trace_gfs2_block_alloc(dip, block, 1, GFS2_BLKST_DINODE); | 1585 | trace_gfs2_block_alloc(dip, block, 1, GFS2_BLKST_DINODE); |
1571 | return block; | 1586 | *bn = block; |
1587 | return 0; | ||
1588 | |||
1589 | rgrp_error: | ||
1590 | gfs2_rgrp_error(rgd); | ||
1591 | return -EIO; | ||
1572 | } | 1592 | } |
1573 | 1593 | ||
1574 | /** | 1594 | /** |
@@ -1676,6 +1696,46 @@ void gfs2_free_di(struct gfs2_rgrpd *rgd, struct gfs2_inode *ip) | |||
1676 | } | 1696 | } |
1677 | 1697 | ||
1678 | /** | 1698 | /** |
1699 | * gfs2_check_blk_type - Check the type of a block | ||
1700 | * @sdp: The superblock | ||
1701 | * @no_addr: The block number to check | ||
1702 | * @type: The block type we are looking for | ||
1703 | * | ||
1704 | * Returns: 0 if the block type matches the expected type | ||
1705 | * -ESTALE if it doesn't match | ||
1706 | * or -ve errno if something went wrong while checking | ||
1707 | */ | ||
1708 | |||
1709 | int gfs2_check_blk_type(struct gfs2_sbd *sdp, u64 no_addr, unsigned int type) | ||
1710 | { | ||
1711 | struct gfs2_rgrpd *rgd; | ||
1712 | struct gfs2_holder ri_gh, rgd_gh; | ||
1713 | int error; | ||
1714 | |||
1715 | error = gfs2_rindex_hold(sdp, &ri_gh); | ||
1716 | if (error) | ||
1717 | goto fail; | ||
1718 | |||
1719 | error = -EINVAL; | ||
1720 | rgd = gfs2_blk2rgrpd(sdp, no_addr); | ||
1721 | if (!rgd) | ||
1722 | goto fail_rindex; | ||
1723 | |||
1724 | error = gfs2_glock_nq_init(rgd->rd_gl, LM_ST_SHARED, 0, &rgd_gh); | ||
1725 | if (error) | ||
1726 | goto fail_rindex; | ||
1727 | |||
1728 | if (gfs2_get_block_type(rgd, no_addr) != type) | ||
1729 | error = -ESTALE; | ||
1730 | |||
1731 | gfs2_glock_dq_uninit(&rgd_gh); | ||
1732 | fail_rindex: | ||
1733 | gfs2_glock_dq_uninit(&ri_gh); | ||
1734 | fail: | ||
1735 | return error; | ||
1736 | } | ||
1737 | |||
1738 | /** | ||
1679 | * gfs2_rlist_add - add a RG to a list of RGs | 1739 | * gfs2_rlist_add - add a RG to a list of RGs |
1680 | * @sdp: the filesystem | 1740 | * @sdp: the filesystem |
1681 | * @rlist: the list of resource groups | 1741 | * @rlist: the list of resource groups |