diff options
Diffstat (limited to 'fs/gfs2/bmap.c')
-rw-r--r-- | fs/gfs2/bmap.c | 57 |
1 files changed, 36 insertions, 21 deletions
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c index e84e3845a394..08d1be492ef7 100644 --- a/fs/gfs2/bmap.c +++ b/fs/gfs2/bmap.c | |||
@@ -384,6 +384,35 @@ static int lookup_block(struct gfs2_inode *ip, struct buffer_head *bh, | |||
384 | return 0; | 384 | return 0; |
385 | } | 385 | } |
386 | 386 | ||
387 | static int lookup_metapath(struct inode *inode, struct metapath *mp, | ||
388 | int create, int *new, u64 *dblock, | ||
389 | struct buffer_head **dibh, struct buffer_head **bh) | ||
390 | { | ||
391 | struct gfs2_inode *ip = GFS2_I(inode); | ||
392 | unsigned int end_of_metadata = ip->i_height - 1; | ||
393 | unsigned int x; | ||
394 | int ret = gfs2_meta_inode_buffer(ip, bh); | ||
395 | if (ret) | ||
396 | return ret; | ||
397 | |||
398 | *dibh = *bh; | ||
399 | get_bh(*dibh); | ||
400 | |||
401 | for (x = 0; x < end_of_metadata; x++) { | ||
402 | lookup_block(ip, *bh, x, mp, create, new, dblock); | ||
403 | brelse(*bh); | ||
404 | *bh = NULL; | ||
405 | if (!dblock) | ||
406 | return 0; | ||
407 | |||
408 | ret = gfs2_meta_indirect_buffer(ip, x+1, *dblock, *new, bh); | ||
409 | if (ret) | ||
410 | return ret; | ||
411 | } | ||
412 | |||
413 | return lookup_block(ip, *bh, end_of_metadata, mp, create, new, dblock); | ||
414 | } | ||
415 | |||
387 | static inline void bmap_lock(struct inode *inode, int create) | 416 | static inline void bmap_lock(struct inode *inode, int create) |
388 | { | 417 | { |
389 | struct gfs2_inode *ip = GFS2_I(inode); | 418 | struct gfs2_inode *ip = GFS2_I(inode); |
@@ -419,10 +448,8 @@ int gfs2_block_map(struct inode *inode, sector_t lblock, | |||
419 | { | 448 | { |
420 | struct gfs2_inode *ip = GFS2_I(inode); | 449 | struct gfs2_inode *ip = GFS2_I(inode); |
421 | struct gfs2_sbd *sdp = GFS2_SB(inode); | 450 | struct gfs2_sbd *sdp = GFS2_SB(inode); |
422 | struct buffer_head *bh; | ||
423 | unsigned int bsize = sdp->sd_sb.sb_bsize; | 451 | unsigned int bsize = sdp->sd_sb.sb_bsize; |
424 | unsigned int end_of_metadata; | 452 | struct buffer_head *bh = NULL; |
425 | unsigned int x; | ||
426 | int error = 0; | 453 | int error = 0; |
427 | int new = 0; | 454 | int new = 0; |
428 | u64 dblock = 0; | 455 | u64 dblock = 0; |
@@ -459,25 +486,11 @@ int gfs2_block_map(struct inode *inode, sector_t lblock, | |||
459 | } | 486 | } |
460 | 487 | ||
461 | find_metapath(ip, lblock, &mp); | 488 | find_metapath(ip, lblock, &mp); |
462 | end_of_metadata = ip->i_height - 1; | 489 | error = lookup_metapath(inode, &mp, create, &new, &dblock, &dibh, &bh); |
463 | error = gfs2_meta_inode_buffer(ip, &bh); | 490 | if (error < 0) |
464 | if (error) | ||
465 | goto out_fail; | 491 | goto out_fail; |
466 | dibh = bh; | 492 | boundary = error; |
467 | get_bh(dibh); | ||
468 | |||
469 | for (x = 0; x < end_of_metadata; x++) { | ||
470 | lookup_block(ip, bh, x, &mp, create, &new, &dblock); | ||
471 | brelse(bh); | ||
472 | if (!dblock) | ||
473 | goto out_ok; | ||
474 | 493 | ||
475 | error = gfs2_meta_indirect_buffer(ip, x+1, dblock, new, &bh); | ||
476 | if (error) | ||
477 | goto out_fail; | ||
478 | } | ||
479 | |||
480 | boundary = lookup_block(ip, bh, end_of_metadata, &mp, create, &new, &dblock); | ||
481 | if (dblock) { | 494 | if (dblock) { |
482 | map_bh(bh_map, inode->i_sb, dblock); | 495 | map_bh(bh_map, inode->i_sb, dblock); |
483 | if (boundary) | 496 | if (boundary) |
@@ -489,6 +502,7 @@ int gfs2_block_map(struct inode *inode, sector_t lblock, | |||
489 | goto out_brelse; | 502 | goto out_brelse; |
490 | } | 503 | } |
491 | while(--maxlen && !buffer_boundary(bh_map)) { | 504 | while(--maxlen && !buffer_boundary(bh_map)) { |
505 | unsigned int end_of_metadata = ip->i_height - 1; | ||
492 | u64 eblock; | 506 | u64 eblock; |
493 | 507 | ||
494 | mp.mp_list[end_of_metadata]++; | 508 | mp.mp_list[end_of_metadata]++; |
@@ -501,7 +515,8 @@ int gfs2_block_map(struct inode *inode, sector_t lblock, | |||
501 | } | 515 | } |
502 | } | 516 | } |
503 | out_brelse: | 517 | out_brelse: |
504 | brelse(bh); | 518 | if (bh) |
519 | brelse(bh); | ||
505 | out_ok: | 520 | out_ok: |
506 | error = 0; | 521 | error = 0; |
507 | out_fail: | 522 | out_fail: |