diff options
Diffstat (limited to 'fs/gfs2/rgrp.c')
-rw-r--r-- | fs/gfs2/rgrp.c | 58 |
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) | |||
713 | static void gfs2_rgrp_out(struct gfs2_rgrpd *rgd, void *buf) | 710 | static 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 | |||
1438 | int 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 | ||
1444 | u64 gfs2_alloc_block(struct gfs2_inode *ip, unsigned int *n) | 1458 | int 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 | |||
1509 | rgrp_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 | /** |