diff options
author | Bob Peterson <rpeterso@redhat.com> | 2011-11-14 11:17:08 -0500 |
---|---|---|
committer | Steven Whitehouse <swhiteho@redhat.com> | 2011-11-15 10:25:03 -0500 |
commit | 3c5d785acfda7dffa63477951bb6864c6a49ed2e (patch) | |
tree | aa387498361ad753777363322a35b8feb80e5f85 /fs/gfs2 | |
parent | c688b8b334d20acbc79b0383af2816ecf7365741 (diff) |
GFS2: combine gfs2_alloc_block and gfs2_alloc_di
GFS2 functions gfs2_alloc_block and gfs2_alloc_di do basically
the same things, with a few exceptions. This patch combines
the two functions into a slightly more generic gfs2_alloc_block.
Having one centralized block allocation function will reduce
code redundancy and make it easier to implement multi-block
reservations to reduce file fragmentation in the future.
Signed-off-by: Bob Peterson <rpeterso@redhat.com>
Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2')
-rw-r--r-- | fs/gfs2/bmap.c | 4 | ||||
-rw-r--r-- | fs/gfs2/dir.c | 2 | ||||
-rw-r--r-- | fs/gfs2/inode.c | 2 | ||||
-rw-r--r-- | fs/gfs2/rgrp.c | 104 | ||||
-rw-r--r-- | fs/gfs2/rgrp.h | 4 | ||||
-rw-r--r-- | fs/gfs2/xattr.c | 6 |
6 files changed, 45 insertions, 77 deletions
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c index f6be14f9ec14..b69235ba2251 100644 --- a/fs/gfs2/bmap.c +++ b/fs/gfs2/bmap.c | |||
@@ -133,7 +133,7 @@ int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page) | |||
133 | and write it out to disk */ | 133 | and write it out to disk */ |
134 | 134 | ||
135 | unsigned int n = 1; | 135 | unsigned int n = 1; |
136 | error = gfs2_alloc_block(ip, &block, &n); | 136 | error = gfs2_alloc_block(ip, &block, &n, 0, NULL); |
137 | if (error) | 137 | if (error) |
138 | goto out_brelse; | 138 | goto out_brelse; |
139 | if (isdir) { | 139 | if (isdir) { |
@@ -503,7 +503,7 @@ static int gfs2_bmap_alloc(struct inode *inode, const sector_t lblock, | |||
503 | do { | 503 | do { |
504 | int error; | 504 | int error; |
505 | n = blks - alloced; | 505 | n = blks - alloced; |
506 | error = gfs2_alloc_block(ip, &bn, &n); | 506 | error = gfs2_alloc_block(ip, &bn, &n, 0, NULL); |
507 | if (error) | 507 | if (error) |
508 | return error; | 508 | return error; |
509 | alloced += n; | 509 | alloced += n; |
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c index 946b6f88939e..ae75319b65e8 100644 --- a/fs/gfs2/dir.c +++ b/fs/gfs2/dir.c | |||
@@ -823,7 +823,7 @@ static struct gfs2_leaf *new_leaf(struct inode *inode, struct buffer_head **pbh, | |||
823 | struct gfs2_dirent *dent; | 823 | struct gfs2_dirent *dent; |
824 | struct qstr name = { .name = "", .len = 0, .hash = 0 }; | 824 | struct qstr name = { .name = "", .len = 0, .hash = 0 }; |
825 | 825 | ||
826 | error = gfs2_alloc_block(ip, &bn, &n); | 826 | error = gfs2_alloc_block(ip, &bn, &n, 0, NULL); |
827 | if (error) | 827 | if (error) |
828 | return NULL; | 828 | return NULL; |
829 | bh = gfs2_meta_new(ip->i_gl, bn); | 829 | bh = gfs2_meta_new(ip->i_gl, bn); |
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 377920d3c430..de2668f5c974 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c | |||
@@ -402,7 +402,7 @@ static int alloc_dinode(struct gfs2_inode *dip, u64 *no_addr, u64 *generation) | |||
402 | if (error) | 402 | if (error) |
403 | goto out_ipreserv; | 403 | goto out_ipreserv; |
404 | 404 | ||
405 | error = gfs2_alloc_di(dip, no_addr, generation); | 405 | error = gfs2_alloc_block(dip, no_addr, NULL, 1, generation); |
406 | 406 | ||
407 | gfs2_trans_end(sdp); | 407 | gfs2_trans_end(sdp); |
408 | 408 | ||
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index a1a815b691cd..995f4e674489 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c | |||
@@ -1304,19 +1304,24 @@ static void gfs2_rgrp_error(struct gfs2_rgrpd *rgd) | |||
1304 | * @ip: the inode to allocate the block for | 1304 | * @ip: the inode to allocate the block for |
1305 | * @bn: Used to return the starting block number | 1305 | * @bn: Used to return the starting block number |
1306 | * @n: requested number of blocks/extent length (value/result) | 1306 | * @n: requested number of blocks/extent length (value/result) |
1307 | * dinode: 1 if we're allocating a dinode, 0 if it's a data block | ||
1308 | * @generation: the generation number of the inode | ||
1307 | * | 1309 | * |
1308 | * Returns: 0 or error | 1310 | * Returns: 0 or error |
1309 | */ | 1311 | */ |
1310 | 1312 | ||
1311 | int gfs2_alloc_block(struct gfs2_inode *ip, u64 *bn, unsigned int *n) | 1313 | int gfs2_alloc_block(struct gfs2_inode *ip, u64 *bn, unsigned int *n, |
1314 | int dinode, u64 *generation) | ||
1312 | { | 1315 | { |
1313 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | 1316 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); |
1314 | struct buffer_head *dibh; | 1317 | struct buffer_head *dibh; |
1315 | struct gfs2_alloc *al = ip->i_alloc; | 1318 | struct gfs2_alloc *al = ip->i_alloc; |
1316 | struct gfs2_rgrpd *rgd; | 1319 | struct gfs2_rgrpd *rgd; |
1317 | u32 goal, blk; | 1320 | u32 goal, blk; /* block, within the rgrp scope */ |
1318 | u64 block; | 1321 | u64 block; /* block, within the file system scope */ |
1322 | unsigned int extn = 1; | ||
1319 | int error; | 1323 | int error; |
1324 | unsigned char blk_type = dinode ? GFS2_BLKST_DINODE : GFS2_BLKST_USED; | ||
1320 | 1325 | ||
1321 | /* Only happens if there is a bug in gfs2, return something distinctive | 1326 | /* Only happens if there is a bug in gfs2, return something distinctive |
1322 | * to ensure that it is noticed. | 1327 | * to ensure that it is noticed. |
@@ -1324,14 +1329,16 @@ int gfs2_alloc_block(struct gfs2_inode *ip, u64 *bn, unsigned int *n) | |||
1324 | if (al == NULL) | 1329 | if (al == NULL) |
1325 | return -ECANCELED; | 1330 | return -ECANCELED; |
1326 | 1331 | ||
1332 | if (n == NULL) | ||
1333 | n = &extn; | ||
1327 | rgd = ip->i_rgd; | 1334 | rgd = ip->i_rgd; |
1328 | 1335 | ||
1329 | if (rgrp_contains_block(rgd, ip->i_goal)) | 1336 | if (!dinode && rgrp_contains_block(rgd, ip->i_goal)) |
1330 | goal = ip->i_goal - rgd->rd_data0; | 1337 | goal = ip->i_goal - rgd->rd_data0; |
1331 | else | 1338 | else |
1332 | goal = rgd->rd_last_alloc; | 1339 | goal = rgd->rd_last_alloc; |
1333 | 1340 | ||
1334 | blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, GFS2_BLKST_USED, n); | 1341 | blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, blk_type, n); |
1335 | 1342 | ||
1336 | /* Since all blocks are reserved in advance, this shouldn't happen */ | 1343 | /* Since all blocks are reserved in advance, this shouldn't happen */ |
1337 | if (blk == BFITNOENT) | 1344 | if (blk == BFITNOENT) |
@@ -1339,82 +1346,43 @@ int gfs2_alloc_block(struct gfs2_inode *ip, u64 *bn, unsigned int *n) | |||
1339 | 1346 | ||
1340 | rgd->rd_last_alloc = blk; | 1347 | rgd->rd_last_alloc = blk; |
1341 | block = rgd->rd_data0 + blk; | 1348 | block = rgd->rd_data0 + blk; |
1342 | ip->i_goal = block + *n - 1; | 1349 | if (!dinode) { |
1343 | error = gfs2_meta_inode_buffer(ip, &dibh); | 1350 | ip->i_goal = block + *n - 1; |
1344 | if (error == 0) { | 1351 | error = gfs2_meta_inode_buffer(ip, &dibh); |
1345 | struct gfs2_dinode *di = (struct gfs2_dinode *)dibh->b_data; | 1352 | if (error == 0) { |
1346 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); | 1353 | struct gfs2_dinode *di = |
1347 | di->di_goal_meta = di->di_goal_data = cpu_to_be64(ip->i_goal); | 1354 | (struct gfs2_dinode *)dibh->b_data; |
1348 | brelse(dibh); | 1355 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); |
1356 | di->di_goal_meta = di->di_goal_data = | ||
1357 | cpu_to_be64(ip->i_goal); | ||
1358 | brelse(dibh); | ||
1359 | } | ||
1349 | } | 1360 | } |
1350 | if (rgd->rd_free < *n) | 1361 | if (rgd->rd_free < *n) |
1351 | goto rgrp_error; | 1362 | goto rgrp_error; |
1352 | 1363 | ||
1353 | rgd->rd_free -= *n; | 1364 | rgd->rd_free -= *n; |
1365 | if (dinode) { | ||
1366 | rgd->rd_dinodes++; | ||
1367 | *generation = rgd->rd_igeneration++; | ||
1368 | if (*generation == 0) | ||
1369 | *generation = rgd->rd_igeneration++; | ||
1370 | } | ||
1354 | 1371 | ||
1355 | gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1); | 1372 | gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1); |
1356 | gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data); | 1373 | gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data); |
1357 | 1374 | ||
1358 | al->al_alloced += *n; | 1375 | al->al_alloced += *n; |
1359 | 1376 | ||
1360 | gfs2_statfs_change(sdp, 0, -(s64)*n, 0); | 1377 | gfs2_statfs_change(sdp, 0, -(s64)*n, dinode ? 1 : 0); |
1361 | gfs2_quota_change(ip, *n, ip->i_inode.i_uid, ip->i_inode.i_gid); | 1378 | if (dinode) |
1379 | gfs2_trans_add_unrevoke(sdp, block, 1); | ||
1380 | else | ||
1381 | gfs2_quota_change(ip, *n, ip->i_inode.i_uid, | ||
1382 | ip->i_inode.i_gid); | ||
1362 | 1383 | ||
1363 | rgd->rd_free_clone -= *n; | 1384 | rgd->rd_free_clone -= *n; |
1364 | trace_gfs2_block_alloc(ip, block, *n, GFS2_BLKST_USED); | 1385 | trace_gfs2_block_alloc(ip, block, *n, blk_type); |
1365 | *bn = block; | ||
1366 | return 0; | ||
1367 | |||
1368 | rgrp_error: | ||
1369 | gfs2_rgrp_error(rgd); | ||
1370 | return -EIO; | ||
1371 | } | ||
1372 | |||
1373 | /** | ||
1374 | * gfs2_alloc_di - Allocate a dinode | ||
1375 | * @dip: the directory that the inode is going in | ||
1376 | * @bn: the block number which is allocated | ||
1377 | * @generation: the generation number of the inode | ||
1378 | * | ||
1379 | * Returns: 0 on success or error | ||
1380 | */ | ||
1381 | |||
1382 | int gfs2_alloc_di(struct gfs2_inode *dip, u64 *bn, u64 *generation) | ||
1383 | { | ||
1384 | struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); | ||
1385 | struct gfs2_alloc *al = dip->i_alloc; | ||
1386 | struct gfs2_rgrpd *rgd = dip->i_rgd; | ||
1387 | u32 blk; | ||
1388 | u64 block; | ||
1389 | unsigned int n = 1; | ||
1390 | |||
1391 | blk = rgblk_search(rgd, rgd->rd_last_alloc, | ||
1392 | GFS2_BLKST_FREE, GFS2_BLKST_DINODE, &n); | ||
1393 | |||
1394 | /* Since all blocks are reserved in advance, this shouldn't happen */ | ||
1395 | if (blk == BFITNOENT) | ||
1396 | goto rgrp_error; | ||
1397 | |||
1398 | rgd->rd_last_alloc = blk; | ||
1399 | block = rgd->rd_data0 + blk; | ||
1400 | if (rgd->rd_free == 0) | ||
1401 | goto rgrp_error; | ||
1402 | |||
1403 | rgd->rd_free--; | ||
1404 | rgd->rd_dinodes++; | ||
1405 | *generation = rgd->rd_igeneration++; | ||
1406 | if (*generation == 0) | ||
1407 | *generation = rgd->rd_igeneration++; | ||
1408 | gfs2_trans_add_bh(rgd->rd_gl, rgd->rd_bits[0].bi_bh, 1); | ||
1409 | gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data); | ||
1410 | |||
1411 | al->al_alloced++; | ||
1412 | |||
1413 | gfs2_statfs_change(sdp, 0, -1, +1); | ||
1414 | gfs2_trans_add_unrevoke(sdp, block, 1); | ||
1415 | |||
1416 | rgd->rd_free_clone--; | ||
1417 | trace_gfs2_block_alloc(dip, block, 1, GFS2_BLKST_DINODE); | ||
1418 | *bn = block; | 1386 | *bn = block; |
1419 | return 0; | 1387 | return 0; |
1420 | 1388 | ||
diff --git a/fs/gfs2/rgrp.h b/fs/gfs2/rgrp.h index cf5c50180192..4cb560813973 100644 --- a/fs/gfs2/rgrp.h +++ b/fs/gfs2/rgrp.h | |||
@@ -39,8 +39,8 @@ static inline void gfs2_alloc_put(struct gfs2_inode *ip) | |||
39 | extern int gfs2_inplace_reserve(struct gfs2_inode *ip); | 39 | extern int gfs2_inplace_reserve(struct gfs2_inode *ip); |
40 | extern void gfs2_inplace_release(struct gfs2_inode *ip); | 40 | extern void gfs2_inplace_release(struct gfs2_inode *ip); |
41 | 41 | ||
42 | extern int gfs2_alloc_block(struct gfs2_inode *ip, u64 *bn, unsigned int *n); | 42 | extern int gfs2_alloc_block(struct gfs2_inode *ip, u64 *bn, unsigned int *n, |
43 | extern int gfs2_alloc_di(struct gfs2_inode *ip, u64 *bn, u64 *generation); | 43 | int dinode, u64 *generation); |
44 | 44 | ||
45 | extern void __gfs2_free_blocks(struct gfs2_inode *ip, u64 bstart, u32 blen, int meta); | 45 | extern void __gfs2_free_blocks(struct gfs2_inode *ip, u64 bstart, u32 blen, int meta); |
46 | extern void gfs2_free_meta(struct gfs2_inode *ip, u64 bstart, u32 blen); | 46 | extern void gfs2_free_meta(struct gfs2_inode *ip, u64 bstart, u32 blen); |
diff --git a/fs/gfs2/xattr.c b/fs/gfs2/xattr.c index a201a1d57a6d..e4794a5b0a16 100644 --- a/fs/gfs2/xattr.c +++ b/fs/gfs2/xattr.c | |||
@@ -610,7 +610,7 @@ static int ea_alloc_blk(struct gfs2_inode *ip, struct buffer_head **bhp) | |||
610 | u64 block; | 610 | u64 block; |
611 | int error; | 611 | int error; |
612 | 612 | ||
613 | error = gfs2_alloc_block(ip, &block, &n); | 613 | error = gfs2_alloc_block(ip, &block, &n, 0, NULL); |
614 | if (error) | 614 | if (error) |
615 | return error; | 615 | return error; |
616 | gfs2_trans_add_unrevoke(sdp, block, 1); | 616 | gfs2_trans_add_unrevoke(sdp, block, 1); |
@@ -672,7 +672,7 @@ static int ea_write(struct gfs2_inode *ip, struct gfs2_ea_header *ea, | |||
672 | int mh_size = sizeof(struct gfs2_meta_header); | 672 | int mh_size = sizeof(struct gfs2_meta_header); |
673 | unsigned int n = 1; | 673 | unsigned int n = 1; |
674 | 674 | ||
675 | error = gfs2_alloc_block(ip, &block, &n); | 675 | error = gfs2_alloc_block(ip, &block, &n, 0, NULL); |
676 | if (error) | 676 | if (error) |
677 | return error; | 677 | return error; |
678 | gfs2_trans_add_unrevoke(sdp, block, 1); | 678 | gfs2_trans_add_unrevoke(sdp, block, 1); |
@@ -992,7 +992,7 @@ static int ea_set_block(struct gfs2_inode *ip, struct gfs2_ea_request *er, | |||
992 | } else { | 992 | } else { |
993 | u64 blk; | 993 | u64 blk; |
994 | unsigned int n = 1; | 994 | unsigned int n = 1; |
995 | error = gfs2_alloc_block(ip, &blk, &n); | 995 | error = gfs2_alloc_block(ip, &blk, &n, 0, NULL); |
996 | if (error) | 996 | if (error) |
997 | return error; | 997 | return error; |
998 | gfs2_trans_add_unrevoke(sdp, blk, 1); | 998 | gfs2_trans_add_unrevoke(sdp, blk, 1); |