diff options
author | Steven Whitehouse <swhiteho@redhat.com> | 2006-08-24 15:59:40 -0400 |
---|---|---|
committer | Steven Whitehouse <swhiteho@redhat.com> | 2006-08-24 15:59:40 -0400 |
commit | 166afccd71fbb7bd758ab9fc770eef4924081077 (patch) | |
tree | 05ba592267ca899e0f5b9313fc7a8d1415bc5f63 /fs/gfs2/ops_address.c | |
parent | 233e515f4062f99569c24f00ad7429a860b23db4 (diff) |
[GFS2] Tidy up error handling in gfs2_releasepage()
This should clarify the logic in gfs2_releasepage() relating to
error handling as well as making the response to errors a bit
more graceful.
Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2/ops_address.c')
-rw-r--r-- | fs/gfs2/ops_address.c | 29 |
1 files changed, 14 insertions, 15 deletions
diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c index 4c59cb110995..48720421c796 100644 --- a/fs/gfs2/ops_address.c +++ b/fs/gfs2/ops_address.c | |||
@@ -683,6 +683,10 @@ static void stuck_releasepage(struct buffer_head *bh) | |||
683 | struct gfs2_sbd *sdp = inode->i_sb->s_fs_info; | 683 | struct gfs2_sbd *sdp = inode->i_sb->s_fs_info; |
684 | struct gfs2_bufdata *bd = bh->b_private; | 684 | struct gfs2_bufdata *bd = bh->b_private; |
685 | struct gfs2_glock *gl; | 685 | struct gfs2_glock *gl; |
686 | static unsigned limit = 0; | ||
687 | |||
688 | if (limit++ > 3) | ||
689 | return; | ||
686 | 690 | ||
687 | fs_warn(sdp, "stuck in gfs2_releasepage() %p\n", inode); | 691 | fs_warn(sdp, "stuck in gfs2_releasepage() %p\n", inode); |
688 | fs_warn(sdp, "blkno = %llu, bh->b_count = %d\n", | 692 | fs_warn(sdp, "blkno = %llu, bh->b_count = %d\n", |
@@ -736,28 +740,24 @@ int gfs2_releasepage(struct page *page, gfp_t gfp_mask) | |||
736 | struct gfs2_sbd *sdp = aspace->i_sb->s_fs_info; | 740 | struct gfs2_sbd *sdp = aspace->i_sb->s_fs_info; |
737 | struct buffer_head *bh, *head; | 741 | struct buffer_head *bh, *head; |
738 | struct gfs2_bufdata *bd; | 742 | struct gfs2_bufdata *bd; |
739 | unsigned long t; | 743 | unsigned long t = jiffies + gfs2_tune_get(sdp, gt_stall_secs) * HZ; |
740 | 744 | ||
741 | if (!page_has_buffers(page)) | 745 | if (!page_has_buffers(page)) |
742 | goto out; | 746 | goto out; |
743 | 747 | ||
744 | head = bh = page_buffers(page); | 748 | head = bh = page_buffers(page); |
745 | do { | 749 | do { |
746 | t = jiffies; | ||
747 | |||
748 | while (atomic_read(&bh->b_count)) { | 750 | while (atomic_read(&bh->b_count)) { |
749 | if (atomic_read(&aspace->i_writecount)) { | 751 | if (!atomic_read(&aspace->i_writecount)) |
750 | if (time_after_eq(jiffies, t + | 752 | return 0; |
751 | gfs2_tune_get(sdp, gt_stall_secs) * HZ)) { | 753 | |
752 | stuck_releasepage(bh); | 754 | if (time_after_eq(jiffies, t)) { |
753 | t = jiffies; | 755 | stuck_releasepage(bh); |
754 | } | 756 | /* should we withdraw here? */ |
755 | 757 | return 0; | |
756 | yield(); | ||
757 | continue; | ||
758 | } | 758 | } |
759 | 759 | ||
760 | return 0; | 760 | yield(); |
761 | } | 761 | } |
762 | 762 | ||
763 | gfs2_assert_warn(sdp, !buffer_pinned(bh)); | 763 | gfs2_assert_warn(sdp, !buffer_pinned(bh)); |
@@ -773,8 +773,7 @@ int gfs2_releasepage(struct page *page, gfp_t gfp_mask) | |||
773 | } | 773 | } |
774 | 774 | ||
775 | bh = bh->b_this_page; | 775 | bh = bh->b_this_page; |
776 | } | 776 | } while (bh != head); |
777 | while (bh != head); | ||
778 | 777 | ||
779 | out: | 778 | out: |
780 | return try_to_free_buffers(page); | 779 | return try_to_free_buffers(page); |