aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2/meta_io.c
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2006-09-21 17:05:23 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2006-09-21 17:05:23 -0400
commit7276b3b0c77101f8b3f4e45e89a29cf9045e831a (patch)
tree3dd0a981218e490ddf47f925ba20c254e491ce98 /fs/gfs2/meta_io.c
parent91fa47964165a42401fbc1f41caa63ab78564305 (diff)
[GFS2] Tidy up meta_io code
Fix a bug in the directory reading code, where we might have dereferenced a NULL pointer in case of OOM. Updated the directory code to use the new & improved version of gfs2_meta_ra() which now returns the first block that was being read. Previously it was releasing it requiring following code to grab the block again at each point it was called. Also turned off readahead on directory lookups since we are reading a hash table, and therefore reading the entries in order is very unlikely. Readahead is still used for all other calls to the directory reading function (e.g. when growing the hash table). Removed the DIO_START constant. Everywhere this was used, it was used to unconditionally start i/o aside from a couple of places, so I've removed it and made the couple of exceptions to this rule into separate functions. Also hunted through the other DIO flags and removed them as arguments from functions which were always called with the same combination of arguments. Updated gfs2_meta_indirect_buffer to be a bit more efficient and hopefully also be a bit easier to read. Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2/meta_io.c')
-rw-r--r--fs/gfs2/meta_io.c173
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
280void gfs2_meta_sync(struct gfs2_glock *gl, int flags) 279void 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)
386int gfs2_meta_read(struct gfs2_glock *gl, u64 blkno, int flags, 383int 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
408int gfs2_meta_reread(struct gfs2_sbd *sdp, struct buffer_head *bh, int flags) 408int 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)
635int gfs2_meta_indirect_buffer(struct gfs2_inode *ip, int height, u64 num, 630int 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;
681err:
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
709void gfs2_meta_ra(struct gfs2_glock *gl, u64 dblock, u32 extlen) 695struct 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);
754out: 733out:
755 brelse(first_bh); 734 return first_bh;
756} 735}
757 736
758/** 737/**