aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/gfs2/bmap.c26
-rw-r--r--fs/gfs2/dir.c3
-rw-r--r--fs/gfs2/eattr.c10
-rw-r--r--fs/gfs2/rgrp.c100
-rw-r--r--fs/gfs2/rgrp.h2
5 files changed, 87 insertions, 54 deletions
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index e3a75a27cee7..1fda731c074b 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -136,8 +136,9 @@ int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page)
136 /* Get a free block, fill it with the stuffed data, 136 /* Get a free block, fill it with the stuffed data,
137 and write it out to disk */ 137 and write it out to disk */
138 138
139 unsigned int n = 1;
140 block = gfs2_alloc_block(ip, &n);
139 if (isdir) { 141 if (isdir) {
140 block = gfs2_alloc_block(ip);
141 gfs2_trans_add_unrevoke(GFS2_SB(&ip->i_inode), block, 1); 142 gfs2_trans_add_unrevoke(GFS2_SB(&ip->i_inode), block, 1);
142 error = gfs2_dir_get_new_buffer(ip, block, &bh); 143 error = gfs2_dir_get_new_buffer(ip, block, &bh);
143 if (error) 144 if (error)
@@ -146,8 +147,6 @@ int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page)
146 dibh, sizeof(struct gfs2_dinode)); 147 dibh, sizeof(struct gfs2_dinode));
147 brelse(bh); 148 brelse(bh);
148 } else { 149 } else {
149 block = gfs2_alloc_block(ip);
150
151 error = gfs2_unstuffer_page(ip, dibh, block, page); 150 error = gfs2_unstuffer_page(ip, dibh, block, page);
152 if (error) 151 if (error)
153 goto out_brelse; 152 goto out_brelse;
@@ -195,7 +194,7 @@ static int build_height(struct inode *inode, struct metapath *mp, unsigned heigh
195 int error; 194 int error;
196 __be64 *bp; 195 __be64 *bp;
197 u64 bn; 196 u64 bn;
198 unsigned n; 197 unsigned n, i = 0;
199 198
200 if (height <= ip->i_height) 199 if (height <= ip->i_height)
201 return 0; 200 return 0;
@@ -204,12 +203,16 @@ static int build_height(struct inode *inode, struct metapath *mp, unsigned heigh
204 if (error) 203 if (error)
205 return error; 204 return error;
206 205
207 for(n = 0; n < new_height; n++) { 206 do {
208 bn = gfs2_alloc_block(ip); 207 n = new_height - i;
209 gfs2_trans_add_unrevoke(GFS2_SB(inode), bn, 1); 208 bn = gfs2_alloc_block(ip, &n);
210 mp->mp_bh[n] = gfs2_meta_new(ip->i_gl, bn); 209 gfs2_trans_add_unrevoke(GFS2_SB(inode), bn, n);
211 gfs2_trans_add_bh(ip->i_gl, mp->mp_bh[n], 1); 210 do {
212 } 211 mp->mp_bh[i] = gfs2_meta_new(ip->i_gl, bn++);
212 gfs2_trans_add_bh(ip->i_gl, mp->mp_bh[i], 1);
213 i++;
214 } while(i < n);
215 } while(i < new_height);
213 216
214 n = 0; 217 n = 0;
215 bn = mp->mp_bh[0]->b_blocknr; 218 bn = mp->mp_bh[0]->b_blocknr;
@@ -358,6 +361,7 @@ static int lookup_block(struct gfs2_inode *ip, unsigned int height,
358{ 361{
359 int boundary; 362 int boundary;
360 __be64 *ptr = metapointer(&boundary, height, mp); 363 __be64 *ptr = metapointer(&boundary, height, mp);
364 unsigned int n = 1;
361 365
362 if (*ptr) { 366 if (*ptr) {
363 *block = be64_to_cpu(*ptr); 367 *block = be64_to_cpu(*ptr);
@@ -369,7 +373,7 @@ static int lookup_block(struct gfs2_inode *ip, unsigned int height,
369 if (!create) 373 if (!create)
370 return 0; 374 return 0;
371 375
372 *block = gfs2_alloc_block(ip); 376 *block = gfs2_alloc_block(ip, &n);
373 if (height != ip->i_height - 1 || gfs2_is_dir(ip)) 377 if (height != ip->i_height - 1 || gfs2_is_dir(ip))
374 gfs2_trans_add_unrevoke(GFS2_SB(&ip->i_inode), *block, 1); 378 gfs2_trans_add_unrevoke(GFS2_SB(&ip->i_inode), *block, 1);
375 379
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c
index fbdf31957cb5..93a2e6afbd81 100644
--- a/fs/gfs2/dir.c
+++ b/fs/gfs2/dir.c
@@ -803,7 +803,8 @@ got_dent:
803static struct gfs2_leaf *new_leaf(struct inode *inode, struct buffer_head **pbh, u16 depth) 803static struct gfs2_leaf *new_leaf(struct inode *inode, struct buffer_head **pbh, u16 depth)
804{ 804{
805 struct gfs2_inode *ip = GFS2_I(inode); 805 struct gfs2_inode *ip = GFS2_I(inode);
806 u64 bn = gfs2_alloc_block(ip); 806 unsigned int n = 1;
807 u64 bn = gfs2_alloc_block(ip, &n);
807 struct buffer_head *bh = gfs2_meta_new(ip->i_gl, bn); 808 struct buffer_head *bh = gfs2_meta_new(ip->i_gl, bn);
808 struct gfs2_leaf *leaf; 809 struct gfs2_leaf *leaf;
809 struct gfs2_dirent *dent; 810 struct gfs2_dirent *dent;
diff --git a/fs/gfs2/eattr.c b/fs/gfs2/eattr.c
index f9f63bc21cd2..0e79cd543496 100644
--- a/fs/gfs2/eattr.c
+++ b/fs/gfs2/eattr.c
@@ -582,9 +582,10 @@ static int ea_alloc_blk(struct gfs2_inode *ip, struct buffer_head **bhp)
582{ 582{
583 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); 583 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
584 struct gfs2_ea_header *ea; 584 struct gfs2_ea_header *ea;
585 unsigned int n = 1;
585 u64 block; 586 u64 block;
586 587
587 block = gfs2_alloc_block(ip); 588 block = gfs2_alloc_block(ip, &n);
588 gfs2_trans_add_unrevoke(sdp, block, 1); 589 gfs2_trans_add_unrevoke(sdp, block, 1);
589 *bhp = gfs2_meta_new(ip->i_gl, block); 590 *bhp = gfs2_meta_new(ip->i_gl, block);
590 gfs2_trans_add_bh(ip->i_gl, *bhp, 1); 591 gfs2_trans_add_bh(ip->i_gl, *bhp, 1);
@@ -642,8 +643,9 @@ static int ea_write(struct gfs2_inode *ip, struct gfs2_ea_header *ea,
642 struct buffer_head *bh; 643 struct buffer_head *bh;
643 u64 block; 644 u64 block;
644 int mh_size = sizeof(struct gfs2_meta_header); 645 int mh_size = sizeof(struct gfs2_meta_header);
646 unsigned int n = 1;
645 647
646 block = gfs2_alloc_block(ip); 648 block = gfs2_alloc_block(ip, &n);
647 gfs2_trans_add_unrevoke(sdp, block, 1); 649 gfs2_trans_add_unrevoke(sdp, block, 1);
648 bh = gfs2_meta_new(ip->i_gl, block); 650 bh = gfs2_meta_new(ip->i_gl, block);
649 gfs2_trans_add_bh(ip->i_gl, bh, 1); 651 gfs2_trans_add_bh(ip->i_gl, bh, 1);
@@ -966,8 +968,8 @@ static int ea_set_block(struct gfs2_inode *ip, struct gfs2_ea_request *er,
966 gfs2_trans_add_bh(ip->i_gl, indbh, 1); 968 gfs2_trans_add_bh(ip->i_gl, indbh, 1);
967 } else { 969 } else {
968 u64 blk; 970 u64 blk;
969 971 unsigned int n = 1;
970 blk = gfs2_alloc_block(ip); 972 blk = gfs2_alloc_block(ip, &n);
971 gfs2_trans_add_unrevoke(sdp, blk, 1); 973 gfs2_trans_add_unrevoke(sdp, blk, 1);
972 indbh = gfs2_meta_new(ip->i_gl, blk); 974 indbh = gfs2_meta_new(ip->i_gl, blk);
973 gfs2_trans_add_bh(ip->i_gl, indbh, 1); 975 gfs2_trans_add_bh(ip->i_gl, indbh, 1);
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;
diff --git a/fs/gfs2/rgrp.h b/fs/gfs2/rgrp.h
index 5e66613b33db..3181c7e624bf 100644
--- a/fs/gfs2/rgrp.h
+++ b/fs/gfs2/rgrp.h
@@ -46,7 +46,7 @@ void gfs2_inplace_release(struct gfs2_inode *ip);
46 46
47unsigned char gfs2_get_block_type(struct gfs2_rgrpd *rgd, u64 block); 47unsigned char gfs2_get_block_type(struct gfs2_rgrpd *rgd, u64 block);
48 48
49u64 gfs2_alloc_block(struct gfs2_inode *ip); 49u64 gfs2_alloc_block(struct gfs2_inode *ip, unsigned int *n);
50u64 gfs2_alloc_di(struct gfs2_inode *ip, u64 *generation); 50u64 gfs2_alloc_di(struct gfs2_inode *ip, u64 *generation);
51 51
52void gfs2_free_data(struct gfs2_inode *ip, u64 bstart, u32 blen); 52void gfs2_free_data(struct gfs2_inode *ip, u64 bstart, u32 blen);