diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-06-11 13:36:12 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-06-11 13:36:12 -0400 |
commit | 0a33f80a8373eca7f4bea3961d1346c3815fa5ed (patch) | |
tree | 16b0c0364340416f1e27bebdd4042ffe0e6fef8f /fs/gfs2/rgrp.c | |
parent | c29f5ec022451546be1e0b24c330a0368e63e4a7 (diff) | |
parent | 003dec8913d6bebb4ecc989ec04a235cf38f5ea9 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-nmw
* git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-nmw: (25 commits)
GFS2: Merge gfs2_get_sb into gfs2_get_sb_meta
GFS2: Fix cache coherency between truncate and O_DIRECT read
GFS2: Fix locking issue mounting gfs2meta fs
GFS2: Remove unused variable
GFS2: smbd proccess hangs with flock() call.
GFS2: Remove args subdir from gfs2 sysfs files
GFS2: Remove lockstruct subdir from gfs2 sysfs files
GFS2: Move gfs2_unlink_ok into ops_inode.c
GFS2: Move gfs2_readlinki into ops_inode.c
GFS2: Move gfs2_rmdiri into ops_inode.c
GFS2: Merge mount.c and ops_super.c into super.c
GFS2: Clean up some file names
GFS2: Be more aggressive in reclaiming unlinked inodes
GFS2: Add a rgrp bitmap full flag
GFS2: Improve resource group error handling
GFS2: Don't warn when delete inode fails on ro filesystem
GFS2: Update docs
GFS2: Umount recovery race fix
GFS2: Remove a couple of unused sysfs entries
GFS2: Add commit= mount option
...
Diffstat (limited to 'fs/gfs2/rgrp.c')
-rw-r--r-- | fs/gfs2/rgrp.c | 141 |
1 files changed, 93 insertions, 48 deletions
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index 565038243fa2..6122c7ee3648 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c | |||
@@ -29,7 +29,6 @@ | |||
29 | #include "util.h" | 29 | #include "util.h" |
30 | #include "log.h" | 30 | #include "log.h" |
31 | #include "inode.h" | 31 | #include "inode.h" |
32 | #include "ops_address.h" | ||
33 | 32 | ||
34 | #define BFITNOENT ((u32)~0) | 33 | #define BFITNOENT ((u32)~0) |
35 | #define NO_BLOCK ((u64)~0) | 34 | #define NO_BLOCK ((u64)~0) |
@@ -442,6 +441,7 @@ static int compute_bitstructs(struct gfs2_rgrpd *rgd) | |||
442 | for (x = 0; x < length; x++) { | 441 | for (x = 0; x < length; x++) { |
443 | bi = rgd->rd_bits + x; | 442 | bi = rgd->rd_bits + x; |
444 | 443 | ||
444 | bi->bi_flags = 0; | ||
445 | /* small rgrp; bitmap stored completely in header block */ | 445 | /* small rgrp; bitmap stored completely in header block */ |
446 | if (length == 1) { | 446 | if (length == 1) { |
447 | bytes = bytes_left; | 447 | bytes = bytes_left; |
@@ -580,7 +580,6 @@ static int read_rindex_entry(struct gfs2_inode *ip, | |||
580 | 580 | ||
581 | rgd->rd_gl->gl_object = rgd; | 581 | rgd->rd_gl->gl_object = rgd; |
582 | rgd->rd_flags &= ~GFS2_RDF_UPTODATE; | 582 | rgd->rd_flags &= ~GFS2_RDF_UPTODATE; |
583 | rgd->rd_flags |= GFS2_RDF_CHECK; | ||
584 | return error; | 583 | return error; |
585 | } | 584 | } |
586 | 585 | ||
@@ -701,10 +700,9 @@ static void gfs2_rgrp_in(struct gfs2_rgrpd *rgd, const void *buf) | |||
701 | u32 rg_flags; | 700 | u32 rg_flags; |
702 | 701 | ||
703 | rg_flags = be32_to_cpu(str->rg_flags); | 702 | rg_flags = be32_to_cpu(str->rg_flags); |
704 | if (rg_flags & GFS2_RGF_NOALLOC) | 703 | rg_flags &= ~GFS2_RDF_MASK; |
705 | rgd->rd_flags |= GFS2_RDF_NOALLOC; | 704 | rgd->rd_flags &= GFS2_RDF_MASK; |
706 | else | 705 | rgd->rd_flags |= rg_flags; |
707 | rgd->rd_flags &= ~GFS2_RDF_NOALLOC; | ||
708 | rgd->rd_free = be32_to_cpu(str->rg_free); | 706 | rgd->rd_free = be32_to_cpu(str->rg_free); |
709 | rgd->rd_dinodes = be32_to_cpu(str->rg_dinodes); | 707 | rgd->rd_dinodes = be32_to_cpu(str->rg_dinodes); |
710 | rgd->rd_igeneration = be64_to_cpu(str->rg_igeneration); | 708 | rgd->rd_igeneration = be64_to_cpu(str->rg_igeneration); |
@@ -713,11 +711,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) | 711 | static void gfs2_rgrp_out(struct gfs2_rgrpd *rgd, void *buf) |
714 | { | 712 | { |
715 | struct gfs2_rgrp *str = buf; | 713 | struct gfs2_rgrp *str = buf; |
716 | u32 rg_flags = 0; | ||
717 | 714 | ||
718 | if (rgd->rd_flags & GFS2_RDF_NOALLOC) | 715 | 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); | 716 | str->rg_free = cpu_to_be32(rgd->rd_free); |
722 | str->rg_dinodes = cpu_to_be32(rgd->rd_dinodes); | 717 | str->rg_dinodes = cpu_to_be32(rgd->rd_dinodes); |
723 | str->__pad = cpu_to_be32(0); | 718 | str->__pad = cpu_to_be32(0); |
@@ -775,8 +770,10 @@ int gfs2_rgrp_bh_get(struct gfs2_rgrpd *rgd) | |||
775 | } | 770 | } |
776 | 771 | ||
777 | if (!(rgd->rd_flags & GFS2_RDF_UPTODATE)) { | 772 | if (!(rgd->rd_flags & GFS2_RDF_UPTODATE)) { |
773 | for (x = 0; x < length; x++) | ||
774 | clear_bit(GBF_FULL, &rgd->rd_bits[x].bi_flags); | ||
778 | gfs2_rgrp_in(rgd, (rgd->rd_bits[0].bi_bh)->b_data); | 775 | gfs2_rgrp_in(rgd, (rgd->rd_bits[0].bi_bh)->b_data); |
779 | rgd->rd_flags |= GFS2_RDF_UPTODATE; | 776 | rgd->rd_flags |= (GFS2_RDF_UPTODATE | GFS2_RDF_CHECK); |
780 | } | 777 | } |
781 | 778 | ||
782 | spin_lock(&sdp->sd_rindex_spin); | 779 | spin_lock(&sdp->sd_rindex_spin); |
@@ -903,6 +900,7 @@ void gfs2_rgrp_repolish_clones(struct gfs2_rgrpd *rgd) | |||
903 | continue; | 900 | continue; |
904 | if (sdp->sd_args.ar_discard) | 901 | if (sdp->sd_args.ar_discard) |
905 | gfs2_rgrp_send_discards(sdp, rgd->rd_data0, bi); | 902 | gfs2_rgrp_send_discards(sdp, rgd->rd_data0, bi); |
903 | clear_bit(GBF_FULL, &bi->bi_flags); | ||
906 | memcpy(bi->bi_clone + bi->bi_offset, | 904 | memcpy(bi->bi_clone + bi->bi_offset, |
907 | bi->bi_bh->b_data + bi->bi_offset, bi->bi_len); | 905 | bi->bi_bh->b_data + bi->bi_offset, bi->bi_len); |
908 | } | 906 | } |
@@ -942,7 +940,7 @@ static int try_rgrp_fit(struct gfs2_rgrpd *rgd, struct gfs2_alloc *al) | |||
942 | struct gfs2_sbd *sdp = rgd->rd_sbd; | 940 | struct gfs2_sbd *sdp = rgd->rd_sbd; |
943 | int ret = 0; | 941 | int ret = 0; |
944 | 942 | ||
945 | if (rgd->rd_flags & GFS2_RDF_NOALLOC) | 943 | if (rgd->rd_flags & (GFS2_RGF_NOALLOC | GFS2_RDF_ERROR)) |
946 | return 0; | 944 | return 0; |
947 | 945 | ||
948 | spin_lock(&sdp->sd_rindex_spin); | 946 | spin_lock(&sdp->sd_rindex_spin); |
@@ -1315,30 +1313,37 @@ static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal, | |||
1315 | { | 1313 | { |
1316 | struct gfs2_bitmap *bi = NULL; | 1314 | struct gfs2_bitmap *bi = NULL; |
1317 | const u32 length = rgd->rd_length; | 1315 | const u32 length = rgd->rd_length; |
1318 | u32 blk = 0; | 1316 | u32 blk = BFITNOENT; |
1319 | unsigned int buf, x; | 1317 | unsigned int buf, x; |
1320 | const unsigned int elen = *n; | 1318 | const unsigned int elen = *n; |
1321 | const u8 *buffer; | 1319 | const u8 *buffer = NULL; |
1322 | 1320 | ||
1323 | *n = 0; | 1321 | *n = 0; |
1324 | /* Find bitmap block that contains bits for goal block */ | 1322 | /* Find bitmap block that contains bits for goal block */ |
1325 | for (buf = 0; buf < length; buf++) { | 1323 | for (buf = 0; buf < length; buf++) { |
1326 | bi = rgd->rd_bits + buf; | 1324 | bi = rgd->rd_bits + buf; |
1327 | if (goal < (bi->bi_start + bi->bi_len) * GFS2_NBBY) | 1325 | /* Convert scope of "goal" from rgrp-wide to within found bit block */ |
1328 | break; | 1326 | if (goal < (bi->bi_start + bi->bi_len) * GFS2_NBBY) { |
1327 | goal -= bi->bi_start * GFS2_NBBY; | ||
1328 | goto do_search; | ||
1329 | } | ||
1329 | } | 1330 | } |
1331 | buf = 0; | ||
1332 | goal = 0; | ||
1330 | 1333 | ||
1331 | gfs2_assert(rgd->rd_sbd, buf < length); | 1334 | do_search: |
1332 | |||
1333 | /* Convert scope of "goal" from rgrp-wide to within found bit block */ | ||
1334 | goal -= bi->bi_start * GFS2_NBBY; | ||
1335 | |||
1336 | /* Search (up to entire) bitmap in this rgrp for allocatable block. | 1335 | /* Search (up to entire) bitmap in this rgrp for allocatable block. |
1337 | "x <= length", instead of "x < length", because we typically start | 1336 | "x <= length", instead of "x < length", because we typically start |
1338 | the search in the middle of a bit block, but if we can't find an | 1337 | the search in the middle of a bit block, but if we can't find an |
1339 | allocatable block anywhere else, we want to be able wrap around and | 1338 | allocatable block anywhere else, we want to be able wrap around and |
1340 | search in the first part of our first-searched bit block. */ | 1339 | search in the first part of our first-searched bit block. */ |
1341 | for (x = 0; x <= length; x++) { | 1340 | for (x = 0; x <= length; x++) { |
1341 | bi = rgd->rd_bits + buf; | ||
1342 | |||
1343 | if (test_bit(GBF_FULL, &bi->bi_flags) && | ||
1344 | (old_state == GFS2_BLKST_FREE)) | ||
1345 | goto skip; | ||
1346 | |||
1342 | /* The GFS2_BLKST_UNLINKED state doesn't apply to the clone | 1347 | /* The GFS2_BLKST_UNLINKED state doesn't apply to the clone |
1343 | bitmaps, so we must search the originals for that. */ | 1348 | bitmaps, so we must search the originals for that. */ |
1344 | buffer = bi->bi_bh->b_data + bi->bi_offset; | 1349 | buffer = bi->bi_bh->b_data + bi->bi_offset; |
@@ -1349,33 +1354,39 @@ static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal, | |||
1349 | if (blk != BFITNOENT) | 1354 | if (blk != BFITNOENT) |
1350 | break; | 1355 | break; |
1351 | 1356 | ||
1357 | if ((goal == 0) && (old_state == GFS2_BLKST_FREE)) | ||
1358 | set_bit(GBF_FULL, &bi->bi_flags); | ||
1359 | |||
1352 | /* Try next bitmap block (wrap back to rgrp header if at end) */ | 1360 | /* Try next bitmap block (wrap back to rgrp header if at end) */ |
1353 | buf = (buf + 1) % length; | 1361 | skip: |
1354 | bi = rgd->rd_bits + buf; | 1362 | buf++; |
1363 | buf %= length; | ||
1355 | goal = 0; | 1364 | goal = 0; |
1356 | } | 1365 | } |
1357 | 1366 | ||
1358 | if (blk != BFITNOENT && old_state != new_state) { | 1367 | if (blk == BFITNOENT) |
1359 | *n = 1; | 1368 | return blk; |
1360 | gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1); | 1369 | *n = 1; |
1370 | if (old_state == new_state) | ||
1371 | goto out; | ||
1372 | |||
1373 | gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1); | ||
1374 | gfs2_setbit(rgd, bi->bi_bh->b_data, bi->bi_clone, bi->bi_offset, | ||
1375 | bi->bi_len, blk, new_state); | ||
1376 | goal = blk; | ||
1377 | while (*n < elen) { | ||
1378 | goal++; | ||
1379 | if (goal >= (bi->bi_len * GFS2_NBBY)) | ||
1380 | break; | ||
1381 | if (gfs2_testbit(rgd, buffer, bi->bi_len, goal) != | ||
1382 | GFS2_BLKST_FREE) | ||
1383 | break; | ||
1361 | gfs2_setbit(rgd, bi->bi_bh->b_data, bi->bi_clone, bi->bi_offset, | 1384 | gfs2_setbit(rgd, bi->bi_bh->b_data, bi->bi_clone, bi->bi_offset, |
1362 | bi->bi_len, blk, new_state); | 1385 | bi->bi_len, goal, new_state); |
1363 | goal = blk; | 1386 | (*n)++; |
1364 | while (*n < elen) { | ||
1365 | goal++; | ||
1366 | if (goal >= (bi->bi_len * GFS2_NBBY)) | ||
1367 | break; | ||
1368 | if (gfs2_testbit(rgd, buffer, bi->bi_len, goal) != | ||
1369 | GFS2_BLKST_FREE) | ||
1370 | break; | ||
1371 | gfs2_setbit(rgd, bi->bi_bh->b_data, bi->bi_clone, | ||
1372 | bi->bi_offset, bi->bi_len, goal, | ||
1373 | new_state); | ||
1374 | (*n)++; | ||
1375 | } | ||
1376 | } | 1387 | } |
1377 | 1388 | out: | |
1378 | return (blk == BFITNOENT) ? blk : (bi->bi_start * GFS2_NBBY) + blk; | 1389 | return (bi->bi_start * GFS2_NBBY) + blk; |
1379 | } | 1390 | } |
1380 | 1391 | ||
1381 | /** | 1392 | /** |
@@ -1435,13 +1446,33 @@ static struct gfs2_rgrpd *rgblk_free(struct gfs2_sbd *sdp, u64 bstart, | |||
1435 | } | 1446 | } |
1436 | 1447 | ||
1437 | /** | 1448 | /** |
1438 | * gfs2_alloc_block - Allocate a block | 1449 | * gfs2_rgrp_dump - print out an rgrp |
1450 | * @seq: The iterator | ||
1451 | * @gl: The glock in question | ||
1452 | * | ||
1453 | */ | ||
1454 | |||
1455 | int gfs2_rgrp_dump(struct seq_file *seq, const struct gfs2_glock *gl) | ||
1456 | { | ||
1457 | const struct gfs2_rgrpd *rgd = gl->gl_object; | ||
1458 | if (rgd == NULL) | ||
1459 | return 0; | ||
1460 | gfs2_print_dbg(seq, " R: n:%llu f:%02x b:%u/%u i:%u\n", | ||
1461 | (unsigned long long)rgd->rd_addr, rgd->rd_flags, | ||
1462 | rgd->rd_free, rgd->rd_free_clone, rgd->rd_dinodes); | ||
1463 | return 0; | ||
1464 | } | ||
1465 | |||
1466 | /** | ||
1467 | * gfs2_alloc_block - Allocate one or more blocks | ||
1439 | * @ip: the inode to allocate the block for | 1468 | * @ip: the inode to allocate the block for |
1469 | * @bn: Used to return the starting block number | ||
1470 | * @n: requested number of blocks/extent length (value/result) | ||
1440 | * | 1471 | * |
1441 | * Returns: the allocated block | 1472 | * Returns: 0 or error |
1442 | */ | 1473 | */ |
1443 | 1474 | ||
1444 | u64 gfs2_alloc_block(struct gfs2_inode *ip, unsigned int *n) | 1475 | int gfs2_alloc_block(struct gfs2_inode *ip, u64 *bn, unsigned int *n) |
1445 | { | 1476 | { |
1446 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | 1477 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); |
1447 | struct buffer_head *dibh; | 1478 | struct buffer_head *dibh; |
@@ -1457,7 +1488,10 @@ u64 gfs2_alloc_block(struct gfs2_inode *ip, unsigned int *n) | |||
1457 | goal = rgd->rd_last_alloc; | 1488 | goal = rgd->rd_last_alloc; |
1458 | 1489 | ||
1459 | blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, GFS2_BLKST_USED, n); | 1490 | blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, GFS2_BLKST_USED, n); |
1460 | BUG_ON(blk == BFITNOENT); | 1491 | |
1492 | /* Since all blocks are reserved in advance, this shouldn't happen */ | ||
1493 | if (blk == BFITNOENT) | ||
1494 | goto rgrp_error; | ||
1461 | 1495 | ||
1462 | rgd->rd_last_alloc = blk; | 1496 | rgd->rd_last_alloc = blk; |
1463 | block = rgd->rd_data0 + blk; | 1497 | block = rgd->rd_data0 + blk; |
@@ -1469,7 +1503,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); | 1503 | di->di_goal_meta = di->di_goal_data = cpu_to_be64(ip->i_goal); |
1470 | brelse(dibh); | 1504 | brelse(dibh); |
1471 | } | 1505 | } |
1472 | gfs2_assert_withdraw(sdp, rgd->rd_free >= *n); | 1506 | if (rgd->rd_free < *n) |
1507 | goto rgrp_error; | ||
1508 | |||
1473 | rgd->rd_free -= *n; | 1509 | rgd->rd_free -= *n; |
1474 | 1510 | ||
1475 | gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1); | 1511 | gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1); |
@@ -1484,7 +1520,16 @@ u64 gfs2_alloc_block(struct gfs2_inode *ip, unsigned int *n) | |||
1484 | rgd->rd_free_clone -= *n; | 1520 | rgd->rd_free_clone -= *n; |
1485 | spin_unlock(&sdp->sd_rindex_spin); | 1521 | spin_unlock(&sdp->sd_rindex_spin); |
1486 | 1522 | ||
1487 | return block; | 1523 | *bn = block; |
1524 | return 0; | ||
1525 | |||
1526 | rgrp_error: | ||
1527 | fs_warn(sdp, "rgrp %llu has an error, marking it readonly until umount\n", | ||
1528 | (unsigned long long)rgd->rd_addr); | ||
1529 | fs_warn(sdp, "umount on all nodes and run fsck.gfs2 to fix the error\n"); | ||
1530 | gfs2_rgrp_dump(NULL, rgd->rd_gl); | ||
1531 | rgd->rd_flags |= GFS2_RDF_ERROR; | ||
1532 | return -EIO; | ||
1488 | } | 1533 | } |
1489 | 1534 | ||
1490 | /** | 1535 | /** |