diff options
Diffstat (limited to 'fs/gfs2/meta_io.c')
-rw-r--r-- | fs/gfs2/meta_io.c | 173 |
1 files changed, 76 insertions, 97 deletions
diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c index 6b52aacb0736..d3708af0a4d1 100644 --- a/fs/gfs2/meta_io.c +++ b/fs/gfs2/meta_io.c | |||
@@ -273,19 +273,16 @@ void gfs2_meta_inval(struct gfs2_glock *gl) | |||
273 | /** | 273 | /** |
274 | * gfs2_meta_sync - Sync all buffers associated with a glock | 274 | * gfs2_meta_sync - Sync all buffers associated with a glock |
275 | * @gl: The glock | 275 | * @gl: The glock |
276 | * @flags: DIO_START | DIO_WAIT | ||
277 | * | 276 | * |
278 | */ | 277 | */ |
279 | 278 | ||
280 | void gfs2_meta_sync(struct gfs2_glock *gl, int flags) | 279 | void gfs2_meta_sync(struct gfs2_glock *gl) |
281 | { | 280 | { |
282 | struct address_space *mapping = gl->gl_aspace->i_mapping; | 281 | struct address_space *mapping = gl->gl_aspace->i_mapping; |
283 | int error = 0; | 282 | int error; |
284 | 283 | ||
285 | if (flags & DIO_START) | 284 | filemap_fdatawrite(mapping); |
286 | filemap_fdatawrite(mapping); | 285 | error = filemap_fdatawait(mapping); |
287 | if (!error && (flags & DIO_WAIT)) | ||
288 | error = filemap_fdatawait(mapping); | ||
289 | 286 | ||
290 | if (error) | 287 | if (error) |
291 | gfs2_io_error(gl->gl_sbd); | 288 | gfs2_io_error(gl->gl_sbd); |
@@ -377,7 +374,7 @@ struct buffer_head *gfs2_meta_new(struct gfs2_glock *gl, u64 blkno) | |||
377 | * gfs2_meta_read - Read a block from disk | 374 | * gfs2_meta_read - Read a block from disk |
378 | * @gl: The glock covering the block | 375 | * @gl: The glock covering the block |
379 | * @blkno: The block number | 376 | * @blkno: The block number |
380 | * @flags: flags to gfs2_dreread() | 377 | * @flags: flags |
381 | * @bhp: the place where the buffer is returned (NULL on failure) | 378 | * @bhp: the place where the buffer is returned (NULL on failure) |
382 | * | 379 | * |
383 | * Returns: errno | 380 | * Returns: errno |
@@ -386,45 +383,43 @@ struct buffer_head *gfs2_meta_new(struct gfs2_glock *gl, u64 blkno) | |||
386 | int gfs2_meta_read(struct gfs2_glock *gl, u64 blkno, int flags, | 383 | int gfs2_meta_read(struct gfs2_glock *gl, u64 blkno, int flags, |
387 | struct buffer_head **bhp) | 384 | struct buffer_head **bhp) |
388 | { | 385 | { |
389 | int error; | ||
390 | |||
391 | *bhp = getbuf(gl->gl_sbd, gl->gl_aspace, blkno, CREATE); | 386 | *bhp = getbuf(gl->gl_sbd, gl->gl_aspace, blkno, CREATE); |
392 | error = gfs2_meta_reread(gl->gl_sbd, *bhp, flags); | 387 | if (!buffer_uptodate(*bhp)) |
393 | if (error) | 388 | ll_rw_block(READ, 1, bhp); |
394 | brelse(*bhp); | 389 | if (flags & DIO_WAIT) { |
390 | int error = gfs2_meta_wait(gl->gl_sbd, *bhp); | ||
391 | if (error) { | ||
392 | brelse(*bhp); | ||
393 | return error; | ||
394 | } | ||
395 | } | ||
395 | 396 | ||
396 | return error; | 397 | return 0; |
397 | } | 398 | } |
398 | 399 | ||
399 | /** | 400 | /** |
400 | * gfs2_meta_reread - Reread a block from disk | 401 | * gfs2_meta_wait - Reread a block from disk |
401 | * @sdp: the filesystem | 402 | * @sdp: the filesystem |
402 | * @bh: The block to read | 403 | * @bh: The block to wait for |
403 | * @flags: Flags that control the read | ||
404 | * | 404 | * |
405 | * Returns: errno | 405 | * Returns: errno |
406 | */ | 406 | */ |
407 | 407 | ||
408 | int gfs2_meta_reread(struct gfs2_sbd *sdp, struct buffer_head *bh, int flags) | 408 | int gfs2_meta_wait(struct gfs2_sbd *sdp, struct buffer_head *bh) |
409 | { | 409 | { |
410 | if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) | 410 | if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) |
411 | return -EIO; | 411 | return -EIO; |
412 | 412 | ||
413 | if ((flags & DIO_START) && !buffer_uptodate(bh)) | 413 | wait_on_buffer(bh); |
414 | ll_rw_block(READ, 1, &bh); | ||
415 | |||
416 | if (flags & DIO_WAIT) { | ||
417 | wait_on_buffer(bh); | ||
418 | 414 | ||
419 | if (!buffer_uptodate(bh)) { | 415 | if (!buffer_uptodate(bh)) { |
420 | struct gfs2_trans *tr = current->journal_info; | 416 | struct gfs2_trans *tr = current->journal_info; |
421 | if (tr && tr->tr_touched) | 417 | if (tr && tr->tr_touched) |
422 | gfs2_io_error_bh(sdp, bh); | 418 | gfs2_io_error_bh(sdp, bh); |
423 | return -EIO; | 419 | return -EIO; |
424 | } | ||
425 | if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) | ||
426 | return -EIO; | ||
427 | } | 420 | } |
421 | if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) | ||
422 | return -EIO; | ||
428 | 423 | ||
429 | return 0; | 424 | return 0; |
430 | } | 425 | } |
@@ -635,67 +630,57 @@ void gfs2_meta_cache_flush(struct gfs2_inode *ip) | |||
635 | int gfs2_meta_indirect_buffer(struct gfs2_inode *ip, int height, u64 num, | 630 | int gfs2_meta_indirect_buffer(struct gfs2_inode *ip, int height, u64 num, |
636 | int new, struct buffer_head **bhp) | 631 | int new, struct buffer_head **bhp) |
637 | { | 632 | { |
638 | struct buffer_head *bh, **bh_slot = ip->i_cache + height; | 633 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); |
639 | int error; | 634 | struct gfs2_glock *gl = ip->i_gl; |
635 | struct buffer_head *bh = NULL, **bh_slot = ip->i_cache + height; | ||
636 | int in_cache = 0; | ||
640 | 637 | ||
641 | spin_lock(&ip->i_spin); | 638 | spin_lock(&ip->i_spin); |
642 | bh = *bh_slot; | 639 | if (*bh_slot && (*bh_slot)->b_blocknr == num) { |
643 | if (bh) { | 640 | bh = *bh_slot; |
644 | if (bh->b_blocknr == num) | 641 | get_bh(bh); |
645 | get_bh(bh); | 642 | in_cache = 1; |
646 | else | ||
647 | bh = NULL; | ||
648 | } | 643 | } |
649 | spin_unlock(&ip->i_spin); | 644 | spin_unlock(&ip->i_spin); |
650 | 645 | ||
651 | if (bh) { | 646 | if (!bh) |
652 | if (new) | 647 | bh = getbuf(gl->gl_sbd, gl->gl_aspace, num, CREATE); |
653 | meta_prep_new(bh); | ||
654 | else { | ||
655 | error = gfs2_meta_reread(GFS2_SB(&ip->i_inode), bh, | ||
656 | DIO_START | DIO_WAIT); | ||
657 | if (error) { | ||
658 | brelse(bh); | ||
659 | return error; | ||
660 | } | ||
661 | } | ||
662 | } else { | ||
663 | if (new) | ||
664 | bh = gfs2_meta_new(ip->i_gl, num); | ||
665 | else { | ||
666 | error = gfs2_meta_read(ip->i_gl, num, | ||
667 | DIO_START | DIO_WAIT, &bh); | ||
668 | if (error) | ||
669 | return error; | ||
670 | } | ||
671 | 648 | ||
672 | spin_lock(&ip->i_spin); | 649 | if (!bh) |
673 | if (*bh_slot != bh) { | 650 | return -ENOBUFS; |
674 | brelse(*bh_slot); | ||
675 | *bh_slot = bh; | ||
676 | get_bh(bh); | ||
677 | } | ||
678 | spin_unlock(&ip->i_spin); | ||
679 | } | ||
680 | 651 | ||
681 | if (new) { | 652 | if (new) { |
682 | if (gfs2_assert_warn(GFS2_SB(&ip->i_inode), height)) { | 653 | if (gfs2_assert_warn(sdp, height)) |
683 | brelse(bh); | 654 | goto err; |
684 | return -EIO; | 655 | meta_prep_new(bh); |
685 | } | ||
686 | gfs2_trans_add_bh(ip->i_gl, bh, 1); | 656 | gfs2_trans_add_bh(ip->i_gl, bh, 1); |
687 | gfs2_metatype_set(bh, GFS2_METATYPE_IN, GFS2_FORMAT_IN); | 657 | gfs2_metatype_set(bh, GFS2_METATYPE_IN, GFS2_FORMAT_IN); |
688 | gfs2_buffer_clear_tail(bh, sizeof(struct gfs2_meta_header)); | 658 | gfs2_buffer_clear_tail(bh, sizeof(struct gfs2_meta_header)); |
659 | } else { | ||
660 | u32 mtype = height ? GFS2_METATYPE_IN : GFS2_METATYPE_DI; | ||
661 | if (!buffer_uptodate(bh)) { | ||
662 | ll_rw_block(READ, 1, &bh); | ||
663 | if (gfs2_meta_wait(sdp, bh)) | ||
664 | goto err; | ||
665 | } | ||
666 | if (gfs2_metatype_check(sdp, bh, mtype)) | ||
667 | goto err; | ||
668 | } | ||
689 | 669 | ||
690 | } else if (gfs2_metatype_check(GFS2_SB(&ip->i_inode), bh, | 670 | if (!in_cache) { |
691 | (height) ? GFS2_METATYPE_IN : GFS2_METATYPE_DI)) { | 671 | spin_lock(&ip->i_spin); |
692 | brelse(bh); | 672 | if (*bh_slot) |
693 | return -EIO; | 673 | brelse(*bh_slot); |
674 | *bh_slot = bh; | ||
675 | get_bh(bh); | ||
676 | spin_unlock(&ip->i_spin); | ||
694 | } | 677 | } |
695 | 678 | ||
696 | *bhp = bh; | 679 | *bhp = bh; |
697 | |||
698 | return 0; | 680 | return 0; |
681 | err: | ||
682 | brelse(bh); | ||
683 | return -EIO; | ||
699 | } | 684 | } |
700 | 685 | ||
701 | /** | 686 | /** |
@@ -704,19 +689,21 @@ int gfs2_meta_indirect_buffer(struct gfs2_inode *ip, int height, u64 num, | |||
704 | * @dblock: the starting disk block | 689 | * @dblock: the starting disk block |
705 | * @extlen: the number of blocks in the extent | 690 | * @extlen: the number of blocks in the extent |
706 | * | 691 | * |
692 | * returns: the first buffer in the extent | ||
707 | */ | 693 | */ |
708 | 694 | ||
709 | void gfs2_meta_ra(struct gfs2_glock *gl, u64 dblock, u32 extlen) | 695 | struct buffer_head *gfs2_meta_ra(struct gfs2_glock *gl, u64 dblock, u32 extlen) |
710 | { | 696 | { |
711 | struct gfs2_sbd *sdp = gl->gl_sbd; | 697 | struct gfs2_sbd *sdp = gl->gl_sbd; |
712 | struct inode *aspace = gl->gl_aspace; | 698 | struct inode *aspace = gl->gl_aspace; |
713 | struct buffer_head *first_bh, *bh; | 699 | struct buffer_head *first_bh, *bh; |
714 | u32 max_ra = gfs2_tune_get(sdp, gt_max_readahead) >> | 700 | u32 max_ra = gfs2_tune_get(sdp, gt_max_readahead) >> |
715 | sdp->sd_sb.sb_bsize_shift; | 701 | sdp->sd_sb.sb_bsize_shift; |
716 | int error; | ||
717 | 702 | ||
718 | if (!extlen || !max_ra) | 703 | BUG_ON(!extlen); |
719 | return; | 704 | |
705 | if (max_ra < 1) | ||
706 | max_ra = 1; | ||
720 | if (extlen > max_ra) | 707 | if (extlen > max_ra) |
721 | extlen = max_ra; | 708 | extlen = max_ra; |
722 | 709 | ||
@@ -724,11 +711,8 @@ void gfs2_meta_ra(struct gfs2_glock *gl, u64 dblock, u32 extlen) | |||
724 | 711 | ||
725 | if (buffer_uptodate(first_bh)) | 712 | if (buffer_uptodate(first_bh)) |
726 | goto out; | 713 | goto out; |
727 | if (!buffer_locked(first_bh)) { | 714 | if (!buffer_locked(first_bh)) |
728 | error = gfs2_meta_reread(sdp, first_bh, DIO_START); | 715 | ll_rw_block(READ, 1, &first_bh); |
729 | if (error) | ||
730 | goto out; | ||
731 | } | ||
732 | 716 | ||
733 | dblock++; | 717 | dblock++; |
734 | extlen--; | 718 | extlen--; |
@@ -736,23 +720,18 @@ void gfs2_meta_ra(struct gfs2_glock *gl, u64 dblock, u32 extlen) | |||
736 | while (extlen) { | 720 | while (extlen) { |
737 | bh = getbuf(sdp, aspace, dblock, CREATE); | 721 | bh = getbuf(sdp, aspace, dblock, CREATE); |
738 | 722 | ||
739 | if (!buffer_uptodate(bh) && !buffer_locked(bh)) { | 723 | if (!buffer_uptodate(bh) && !buffer_locked(bh)) |
740 | error = gfs2_meta_reread(sdp, bh, DIO_START); | 724 | ll_rw_block(READA, 1, &bh); |
741 | brelse(bh); | 725 | brelse(bh); |
742 | if (error) | ||
743 | goto out; | ||
744 | } else | ||
745 | brelse(bh); | ||
746 | |||
747 | dblock++; | 726 | dblock++; |
748 | extlen--; | 727 | extlen--; |
749 | 728 | if (!buffer_locked(first_bh) && buffer_uptodate(first_bh)) | |
750 | if (buffer_uptodate(first_bh)) | 729 | goto out; |
751 | break; | ||
752 | } | 730 | } |
753 | 731 | ||
732 | wait_on_buffer(first_bh); | ||
754 | out: | 733 | out: |
755 | brelse(first_bh); | 734 | return first_bh; |
756 | } | 735 | } |
757 | 736 | ||
758 | /** | 737 | /** |