aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2/rgrp.c
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2008-02-06 05:11:15 -0500
committerSteven Whitehouse <swhiteho@redhat.com>2008-03-31 05:40:47 -0400
commitb45e41d7d56dfef1ae9e02e6c59990066ba82e5c (patch)
treec139447fa57beb3886def4e17449cc34bf40cf3c /fs/gfs2/rgrp.c
parent1639431a3f57b43da1e15e9268a1d691ac01ba26 (diff)
[GFS2] Add extent allocation to block allocator
Rather than having to allocate a single block at a time, this patch allows the block allocator to allocate an extent. Since there is no difference (so far as the block allocator is concerned) between data blocks and indirect blocks, it is posible to allocate a single extent and for the caller to unrevoke just the blocks required for indirect blocks. Currently the only bit of GFS2 to make use of this feature is the build height function. The intention is that gfs2_block_map will be changed to make use of this feature in future patches. Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2/rgrp.c')
-rw-r--r--fs/gfs2/rgrp.c100
1 files changed, 63 insertions, 37 deletions
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index 274a2df13f02..77eba0a38040 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -53,7 +53,8 @@ static const char valid_change[16] = {
53}; 53};
54 54
55static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal, 55static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal,
56 unsigned char old_state, unsigned char new_state); 56 unsigned char old_state, unsigned char new_state,
57 unsigned int *n);
57 58
58/** 59/**
59 * gfs2_setbit - Set a bit in the bitmaps 60 * gfs2_setbit - Set a bit in the bitmaps
@@ -64,26 +65,32 @@ static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal,
64 * 65 *
65 */ 66 */
66 67
67static void gfs2_setbit(struct gfs2_rgrpd *rgd, unsigned char *buffer, 68static inline void gfs2_setbit(struct gfs2_rgrpd *rgd, unsigned char *buf1,
68 unsigned int buflen, u32 block, 69 unsigned char *buf2, unsigned int offset,
69 unsigned char new_state) 70 unsigned int buflen, u32 block,
71 unsigned char new_state)
70{ 72{
71 unsigned char *byte, *end, cur_state; 73 unsigned char *byte1, *byte2, *end, cur_state;
72 unsigned int bit; 74 const unsigned int bit = (block % GFS2_NBBY) * GFS2_BIT_SIZE;
73 75
74 byte = buffer + (block / GFS2_NBBY); 76 byte1 = buf1 + offset + (block / GFS2_NBBY);
75 bit = (block % GFS2_NBBY) * GFS2_BIT_SIZE; 77 end = buf1 + offset + buflen;
76 end = buffer + buflen;
77 78
78 gfs2_assert(rgd->rd_sbd, byte < end); 79 BUG_ON(byte1 >= end);
79 80
80 cur_state = (*byte >> bit) & GFS2_BIT_MASK; 81 cur_state = (*byte1 >> bit) & GFS2_BIT_MASK;
81 82
82 if (valid_change[new_state * 4 + cur_state]) { 83 if (unlikely(!valid_change[new_state * 4 + cur_state])) {
83 *byte ^= cur_state << bit;
84 *byte |= new_state << bit;
85 } else
86 gfs2_consist_rgrpd(rgd); 84 gfs2_consist_rgrpd(rgd);
85 return;
86 }
87 *byte1 ^= (cur_state ^ new_state) << bit;
88
89 if (buf2) {
90 byte2 = buf2 + offset + (block / GFS2_NBBY);
91 cur_state = (*byte2 >> bit) & GFS2_BIT_MASK;
92 *byte2 ^= (cur_state ^ new_state) << bit;
93 }
87} 94}
88 95
89/** 96/**
@@ -94,10 +101,12 @@ static void gfs2_setbit(struct gfs2_rgrpd *rgd, unsigned char *buffer,
94 * 101 *
95 */ 102 */
96 103
97static unsigned char gfs2_testbit(struct gfs2_rgrpd *rgd, unsigned char *buffer, 104static inline unsigned char gfs2_testbit(struct gfs2_rgrpd *rgd,
98 unsigned int buflen, u32 block) 105 const unsigned char *buffer,
106 unsigned int buflen, u32 block)
99{ 107{
100 unsigned char *byte, *end, cur_state; 108 const unsigned char *byte, *end;
109 unsigned char cur_state;
101 unsigned int bit; 110 unsigned int bit;
102 111
103 byte = buffer + (block / GFS2_NBBY); 112 byte = buffer + (block / GFS2_NBBY);
@@ -877,13 +886,15 @@ static struct inode *try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked)
877 u32 goal = 0, block; 886 u32 goal = 0, block;
878 u64 no_addr; 887 u64 no_addr;
879 struct gfs2_sbd *sdp = rgd->rd_sbd; 888 struct gfs2_sbd *sdp = rgd->rd_sbd;
889 unsigned int n;
880 890
881 for(;;) { 891 for(;;) {
882 if (goal >= rgd->rd_data) 892 if (goal >= rgd->rd_data)
883 break; 893 break;
884 down_write(&sdp->sd_log_flush_lock); 894 down_write(&sdp->sd_log_flush_lock);
895 n = 1;
885 block = rgblk_search(rgd, goal, GFS2_BLKST_UNLINKED, 896 block = rgblk_search(rgd, goal, GFS2_BLKST_UNLINKED,
886 GFS2_BLKST_UNLINKED); 897 GFS2_BLKST_UNLINKED, &n);
887 up_write(&sdp->sd_log_flush_lock); 898 up_write(&sdp->sd_log_flush_lock);
888 if (block == BFITNOENT) 899 if (block == BFITNOENT)
889 break; 900 break;
@@ -1280,6 +1291,7 @@ unsigned char gfs2_get_block_type(struct gfs2_rgrpd *rgd, u64 block)
1280 * @goal: the goal block within the RG (start here to search for avail block) 1291 * @goal: the goal block within the RG (start here to search for avail block)
1281 * @old_state: GFS2_BLKST_XXX the before-allocation state to find 1292 * @old_state: GFS2_BLKST_XXX the before-allocation state to find
1282 * @new_state: GFS2_BLKST_XXX the after-allocation block state 1293 * @new_state: GFS2_BLKST_XXX the after-allocation block state
1294 * @n: The extent length
1283 * 1295 *
1284 * Walk rgrp's bitmap to find bits that represent a block in @old_state. 1296 * Walk rgrp's bitmap to find bits that represent a block in @old_state.
1285 * Add the found bitmap buffer to the transaction. 1297 * Add the found bitmap buffer to the transaction.
@@ -1295,13 +1307,17 @@ unsigned char gfs2_get_block_type(struct gfs2_rgrpd *rgd, u64 block)
1295 */ 1307 */
1296 1308
1297static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal, 1309static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal,
1298 unsigned char old_state, unsigned char new_state) 1310 unsigned char old_state, unsigned char new_state,
1311 unsigned int *n)
1299{ 1312{
1300 struct gfs2_bitmap *bi = NULL; 1313 struct gfs2_bitmap *bi = NULL;
1301 u32 length = rgd->rd_length; 1314 const u32 length = rgd->rd_length;
1302 u32 blk = 0; 1315 u32 blk = 0;
1303 unsigned int buf, x; 1316 unsigned int buf, x;
1317 const unsigned int elen = *n;
1318 const u8 *buffer;
1304 1319
1320 *n = 0;
1305 /* Find bitmap block that contains bits for goal block */ 1321 /* Find bitmap block that contains bits for goal block */
1306 for (buf = 0; buf < length; buf++) { 1322 for (buf = 0; buf < length; buf++) {
1307 bi = rgd->rd_bits + buf; 1323 bi = rgd->rd_bits + buf;
@@ -1322,7 +1338,7 @@ static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal,
1322 for (x = 0; x <= length; x++) { 1338 for (x = 0; x <= length; x++) {
1323 /* The GFS2_BLKST_UNLINKED state doesn't apply to the clone 1339 /* The GFS2_BLKST_UNLINKED state doesn't apply to the clone
1324 bitmaps, so we must search the originals for that. */ 1340 bitmaps, so we must search the originals for that. */
1325 const u8 *buffer = bi->bi_bh->b_data + bi->bi_offset; 1341 buffer = bi->bi_bh->b_data + bi->bi_offset;
1326 if (old_state != GFS2_BLKST_UNLINKED && bi->bi_clone) 1342 if (old_state != GFS2_BLKST_UNLINKED && bi->bi_clone)
1327 buffer = bi->bi_clone + bi->bi_offset; 1343 buffer = bi->bi_clone + bi->bi_offset;
1328 1344
@@ -1337,12 +1353,21 @@ static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal,
1337 } 1353 }
1338 1354
1339 if (blk != BFITNOENT && old_state != new_state) { 1355 if (blk != BFITNOENT && old_state != new_state) {
1356 *n = 1;
1340 gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1); 1357 gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1);
1341 gfs2_setbit(rgd, bi->bi_bh->b_data + bi->bi_offset, 1358 gfs2_setbit(rgd, bi->bi_bh->b_data, bi->bi_clone, bi->bi_offset,
1342 bi->bi_len, blk, new_state); 1359 bi->bi_len, blk, new_state);
1343 if (bi->bi_clone) 1360 while(*n < elen) {
1344 gfs2_setbit(rgd, bi->bi_clone + bi->bi_offset, 1361 goal++;
1345 bi->bi_len, blk, new_state); 1362 if (goal >= (bi->bi_len / GFS2_NBBY))
1363 break;
1364 if (gfs2_testbit(rgd, buffer, bi->bi_len, goal) !=
1365 GFS2_BLKST_FREE)
1366 break;
1367 (*n)++;
1368 gfs2_setbit(rgd, bi->bi_bh->b_data, bi->bi_clone,
1369 bi->bi_offset, bi->bi_len, blk, new_state);
1370 }
1346 } 1371 }
1347 1372
1348 return (blk == BFITNOENT) ? blk : (bi->bi_start * GFS2_NBBY) + blk; 1373 return (blk == BFITNOENT) ? blk : (bi->bi_start * GFS2_NBBY) + blk;
@@ -1397,7 +1422,7 @@ static struct gfs2_rgrpd *rgblk_free(struct gfs2_sbd *sdp, u64 bstart,
1397 bi->bi_len); 1422 bi->bi_len);
1398 } 1423 }
1399 gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1); 1424 gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1);
1400 gfs2_setbit(rgd, bi->bi_bh->b_data + bi->bi_offset, 1425 gfs2_setbit(rgd, bi->bi_bh->b_data, NULL, bi->bi_offset,
1401 bi->bi_len, buf_blk, new_state); 1426 bi->bi_len, buf_blk, new_state);
1402 } 1427 }
1403 1428
@@ -1411,7 +1436,7 @@ static struct gfs2_rgrpd *rgblk_free(struct gfs2_sbd *sdp, u64 bstart,
1411 * Returns: the allocated block 1436 * Returns: the allocated block
1412 */ 1437 */
1413 1438
1414u64 gfs2_alloc_block(struct gfs2_inode *ip) 1439u64 gfs2_alloc_block(struct gfs2_inode *ip, unsigned int *n)
1415{ 1440{
1416 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); 1441 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
1417 struct gfs2_alloc *al = ip->i_alloc; 1442 struct gfs2_alloc *al = ip->i_alloc;
@@ -1424,26 +1449,26 @@ u64 gfs2_alloc_block(struct gfs2_inode *ip)
1424 else 1449 else
1425 goal = rgd->rd_last_alloc; 1450 goal = rgd->rd_last_alloc;
1426 1451
1427 blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, GFS2_BLKST_USED); 1452 blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, GFS2_BLKST_USED, n);
1428 BUG_ON(blk == BFITNOENT); 1453 BUG_ON(blk == BFITNOENT);
1429 rgd->rd_last_alloc = blk;
1430 1454
1455 rgd->rd_last_alloc = blk;
1431 block = rgd->rd_data0 + blk; 1456 block = rgd->rd_data0 + blk;
1432 ip->i_goal = block; 1457 ip->i_goal = block;
1433 1458
1434 gfs2_assert_withdraw(sdp, rgd->rd_rg.rg_free); 1459 gfs2_assert_withdraw(sdp, rgd->rd_rg.rg_free >= *n);
1435 rgd->rd_rg.rg_free--; 1460 rgd->rd_rg.rg_free -= *n;
1436 1461
1437 gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1); 1462 gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1);
1438 gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data); 1463 gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data);
1439 1464
1440 al->al_alloced++; 1465 al->al_alloced += *n;
1441 1466
1442 gfs2_statfs_change(sdp, 0, -1, 0); 1467 gfs2_statfs_change(sdp, 0, -*n, 0);
1443 gfs2_quota_change(ip, +1, ip->i_inode.i_uid, ip->i_inode.i_gid); 1468 gfs2_quota_change(ip, *n, ip->i_inode.i_uid, ip->i_inode.i_gid);
1444 1469
1445 spin_lock(&sdp->sd_rindex_spin); 1470 spin_lock(&sdp->sd_rindex_spin);
1446 rgd->rd_free_clone--; 1471 rgd->rd_free_clone -= *n;
1447 spin_unlock(&sdp->sd_rindex_spin); 1472 spin_unlock(&sdp->sd_rindex_spin);
1448 1473
1449 return block; 1474 return block;
@@ -1463,9 +1488,10 @@ u64 gfs2_alloc_di(struct gfs2_inode *dip, u64 *generation)
1463 struct gfs2_rgrpd *rgd = al->al_rgd; 1488 struct gfs2_rgrpd *rgd = al->al_rgd;
1464 u32 blk; 1489 u32 blk;
1465 u64 block; 1490 u64 block;
1491 unsigned int n = 1;
1466 1492
1467 blk = rgblk_search(rgd, rgd->rd_last_alloc, 1493 blk = rgblk_search(rgd, rgd->rd_last_alloc,
1468 GFS2_BLKST_FREE, GFS2_BLKST_DINODE); 1494 GFS2_BLKST_FREE, GFS2_BLKST_DINODE, &n);
1469 BUG_ON(blk == BFITNOENT); 1495 BUG_ON(blk == BFITNOENT);
1470 1496
1471 rgd->rd_last_alloc = blk; 1497 rgd->rd_last_alloc = blk;