diff options
author | Steven Whitehouse <swhiteho@redhat.com> | 2009-05-21 07:23:12 -0400 |
---|---|---|
committer | Steven Whitehouse <swhiteho@redhat.com> | 2009-05-21 07:23:12 -0400 |
commit | 60a0b8f93664621a07b93273fc8ebc29590c62f5 (patch) | |
tree | 6e819ce13d40aef078f3af45867b8af2e9c6ec85 | |
parent | 09010978345e8883003bf411bb99753710eb5a3a (diff) |
GFS2: Add a rgrp bitmap full flag
During block allocation, it is useful to know if sections of disk
are full on a finer grained basis than a single resource group.
This can make a performance difference when resource groups have
larger numbers of bitmap blocks, since we no longer have to search
them all block by block in each individual bitmap.
The full flag is set on a per-bitmap basis when it has been
searched and found to have no free space. It is then skipped in
subsequent searches until the flag is reset. The resetting
occurs if we have to drop the glock on the resource group for any
reason, or if we deallocate some blocks within that resource
group and thus free up some space.
Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
-rw-r--r-- | fs/gfs2/incore.h | 3 | ||||
-rw-r--r-- | fs/gfs2/rgrp.c | 77 |
2 files changed, 50 insertions, 30 deletions
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index de50d86fec12..dd87379b61e6 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h | |||
@@ -64,9 +64,12 @@ struct gfs2_log_element { | |||
64 | const struct gfs2_log_operations *le_ops; | 64 | const struct gfs2_log_operations *le_ops; |
65 | }; | 65 | }; |
66 | 66 | ||
67 | #define GBF_FULL 1 | ||
68 | |||
67 | struct gfs2_bitmap { | 69 | struct gfs2_bitmap { |
68 | struct buffer_head *bi_bh; | 70 | struct buffer_head *bi_bh; |
69 | char *bi_clone; | 71 | char *bi_clone; |
72 | unsigned long bi_flags; | ||
70 | u32 bi_offset; | 73 | u32 bi_offset; |
71 | u32 bi_start; | 74 | u32 bi_start; |
72 | u32 bi_len; | 75 | u32 bi_len; |
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index fbacf09ee34e..23637b9d1c73 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c | |||
@@ -442,6 +442,7 @@ static int compute_bitstructs(struct gfs2_rgrpd *rgd) | |||
442 | for (x = 0; x < length; x++) { | 442 | for (x = 0; x < length; x++) { |
443 | bi = rgd->rd_bits + x; | 443 | bi = rgd->rd_bits + x; |
444 | 444 | ||
445 | bi->bi_flags = 0; | ||
445 | /* small rgrp; bitmap stored completely in header block */ | 446 | /* small rgrp; bitmap stored completely in header block */ |
446 | if (length == 1) { | 447 | if (length == 1) { |
447 | bytes = bytes_left; | 448 | bytes = bytes_left; |
@@ -769,6 +770,8 @@ int gfs2_rgrp_bh_get(struct gfs2_rgrpd *rgd) | |||
769 | } | 770 | } |
770 | 771 | ||
771 | 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); | ||
772 | 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); |
773 | rgd->rd_flags |= GFS2_RDF_UPTODATE; | 776 | rgd->rd_flags |= GFS2_RDF_UPTODATE; |
774 | } | 777 | } |
@@ -897,6 +900,7 @@ void gfs2_rgrp_repolish_clones(struct gfs2_rgrpd *rgd) | |||
897 | continue; | 900 | continue; |
898 | if (sdp->sd_args.ar_discard) | 901 | if (sdp->sd_args.ar_discard) |
899 | 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); | ||
900 | memcpy(bi->bi_clone + bi->bi_offset, | 904 | memcpy(bi->bi_clone + bi->bi_offset, |
901 | bi->bi_bh->b_data + bi->bi_offset, bi->bi_len); | 905 | bi->bi_bh->b_data + bi->bi_offset, bi->bi_len); |
902 | } | 906 | } |
@@ -1309,30 +1313,37 @@ static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal, | |||
1309 | { | 1313 | { |
1310 | struct gfs2_bitmap *bi = NULL; | 1314 | struct gfs2_bitmap *bi = NULL; |
1311 | const u32 length = rgd->rd_length; | 1315 | const u32 length = rgd->rd_length; |
1312 | u32 blk = 0; | 1316 | u32 blk = BFITNOENT; |
1313 | unsigned int buf, x; | 1317 | unsigned int buf, x; |
1314 | const unsigned int elen = *n; | 1318 | const unsigned int elen = *n; |
1315 | const u8 *buffer; | 1319 | const u8 *buffer = NULL; |
1316 | 1320 | ||
1317 | *n = 0; | 1321 | *n = 0; |
1318 | /* Find bitmap block that contains bits for goal block */ | 1322 | /* Find bitmap block that contains bits for goal block */ |
1319 | for (buf = 0; buf < length; buf++) { | 1323 | for (buf = 0; buf < length; buf++) { |
1320 | bi = rgd->rd_bits + buf; | 1324 | bi = rgd->rd_bits + buf; |
1321 | if (goal < (bi->bi_start + bi->bi_len) * GFS2_NBBY) | 1325 | /* Convert scope of "goal" from rgrp-wide to within found bit block */ |
1322 | break; | 1326 | if (goal < (bi->bi_start + bi->bi_len) * GFS2_NBBY) { |
1327 | goal -= bi->bi_start * GFS2_NBBY; | ||
1328 | goto do_search; | ||
1329 | } | ||
1323 | } | 1330 | } |
1331 | buf = 0; | ||
1332 | goal = 0; | ||
1324 | 1333 | ||
1325 | gfs2_assert(rgd->rd_sbd, buf < length); | 1334 | do_search: |
1326 | |||
1327 | /* Convert scope of "goal" from rgrp-wide to within found bit block */ | ||
1328 | goal -= bi->bi_start * GFS2_NBBY; | ||
1329 | |||
1330 | /* Search (up to entire) bitmap in this rgrp for allocatable block. | 1335 | /* Search (up to entire) bitmap in this rgrp for allocatable block. |
1331 | "x <= length", instead of "x < length", because we typically start | 1336 | "x <= length", instead of "x < length", because we typically start |
1332 | 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 |
1333 | 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 |
1334 | search in the first part of our first-searched bit block. */ | 1339 | search in the first part of our first-searched bit block. */ |
1335 | 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 | |||
1336 | /* The GFS2_BLKST_UNLINKED state doesn't apply to the clone | 1347 | /* The GFS2_BLKST_UNLINKED state doesn't apply to the clone |
1337 | bitmaps, so we must search the originals for that. */ | 1348 | bitmaps, so we must search the originals for that. */ |
1338 | buffer = bi->bi_bh->b_data + bi->bi_offset; | 1349 | buffer = bi->bi_bh->b_data + bi->bi_offset; |
@@ -1343,33 +1354,39 @@ static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal, | |||
1343 | if (blk != BFITNOENT) | 1354 | if (blk != BFITNOENT) |
1344 | break; | 1355 | break; |
1345 | 1356 | ||
1357 | if ((goal == 0) && (old_state == GFS2_BLKST_FREE)) | ||
1358 | set_bit(GBF_FULL, &bi->bi_flags); | ||
1359 | |||
1346 | /* 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) */ |
1347 | buf = (buf + 1) % length; | 1361 | skip: |
1348 | bi = rgd->rd_bits + buf; | 1362 | buf++; |
1363 | buf %= length; | ||
1349 | goal = 0; | 1364 | goal = 0; |
1350 | } | 1365 | } |
1351 | 1366 | ||
1352 | if (blk != BFITNOENT && old_state != new_state) { | 1367 | if (blk == BFITNOENT) |
1353 | *n = 1; | 1368 | return blk; |
1354 | 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; | ||
1355 | 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, |
1356 | bi->bi_len, blk, new_state); | 1385 | bi->bi_len, goal, new_state); |
1357 | goal = blk; | 1386 | (*n)++; |
1358 | while (*n < elen) { | ||
1359 | goal++; | ||
1360 | if (goal >= (bi->bi_len * GFS2_NBBY)) | ||
1361 | break; | ||
1362 | if (gfs2_testbit(rgd, buffer, bi->bi_len, goal) != | ||
1363 | GFS2_BLKST_FREE) | ||
1364 | break; | ||
1365 | gfs2_setbit(rgd, bi->bi_bh->b_data, bi->bi_clone, | ||
1366 | bi->bi_offset, bi->bi_len, goal, | ||
1367 | new_state); | ||
1368 | (*n)++; | ||
1369 | } | ||
1370 | } | 1387 | } |
1371 | 1388 | out: | |
1372 | return (blk == BFITNOENT) ? blk : (bi->bi_start * GFS2_NBBY) + blk; | 1389 | return (bi->bi_start * GFS2_NBBY) + blk; |
1373 | } | 1390 | } |
1374 | 1391 | ||
1375 | /** | 1392 | /** |