aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2009-05-21 07:23:12 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2009-05-21 07:23:12 -0400
commit60a0b8f93664621a07b93273fc8ebc29590c62f5 (patch)
tree6e819ce13d40aef078f3af45867b8af2e9c6ec85
parent09010978345e8883003bf411bb99753710eb5a3a (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.h3
-rw-r--r--fs/gfs2/rgrp.c77
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
67struct gfs2_bitmap { 69struct 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); 1334do_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; 1361skip:
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 1388out:
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/**