aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2/rgrp.c
diff options
context:
space:
mode:
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;