summaryrefslogtreecommitdiff
path: root/fs/gfs2/ops_address.c
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2007-09-02 09:48:13 (GMT)
committerSteven Whitehouse <swhiteho@redhat.com>2007-10-10 07:56:03 (GMT)
commitd7b616e252b125f12b007c392f7644053bb6f140 (patch)
tree0794272905a1876ef74144a993f7a76400893813 /fs/gfs2/ops_address.c
parent9b9107a5a8b190e6cf09bbdf893869c6a9c482cc (diff)
downloadlinux-d7b616e252b125f12b007c392f7644053bb6f140.tar.xz
[GFS2] Clean up ordered write code
The following patch removes the ordered write processing from databuf_lo_before_commit() and moves it to log.c. This has the effect of greatly simplyfying databuf_lo_before_commit() and well as potentially making the ordered write code more efficient. As a side effect of this, its now possible to remove ordered buffers from the ordered buffer list at any time, so we now make use of this in invalidatepage and releasepage to ensure timely release of these buffers. Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2/ops_address.c')
-rw-r--r--fs/gfs2/ops_address.c50
1 files changed, 46 insertions, 4 deletions
diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c
index 8407d1d..dd1ea49 100644
--- a/fs/gfs2/ops_address.c
+++ b/fs/gfs2/ops_address.c
@@ -616,13 +616,50 @@ static sector_t gfs2_bmap(struct address_space *mapping, sector_t lblock)
return dblock;
}
+static void gfs2_discard(struct gfs2_sbd *sdp, struct buffer_head *bh)
+{
+ struct gfs2_bufdata *bd;
+
+ lock_buffer(bh);
+ gfs2_log_lock(sdp);
+ clear_buffer_dirty(bh);
+ bd = bh->b_private;
+ if (bd) {
+ if (!list_empty(&bd->bd_le.le_list)) {
+ if (!buffer_pinned(bh))
+ list_del_init(&bd->bd_le.le_list);
+ }
+ }
+ bh->b_bdev = NULL;
+ clear_buffer_mapped(bh);
+ clear_buffer_req(bh);
+ clear_buffer_new(bh);
+ gfs2_log_unlock(sdp);
+ unlock_buffer(bh);
+}
+
static void gfs2_invalidatepage(struct page *page, unsigned long offset)
{
+ struct gfs2_sbd *sdp = GFS2_SB(page->mapping->host);
+ struct buffer_head *bh, *head;
+ unsigned long pos = 0;
+
BUG_ON(!PageLocked(page));
if (offset == 0)
ClearPageChecked(page);
+ if (!page_has_buffers(page))
+ goto out;
- block_invalidatepage(page, offset);
+ bh = head = page_buffers(page);
+ do {
+ if (offset <= pos)
+ gfs2_discard(sdp, bh);
+ pos += bh->b_size;
+ bh = bh->b_this_page;
+ } while (bh != head);
+out:
+ if (offset == 0)
+ try_to_release_page(page, 0);
}
/**
@@ -732,9 +769,14 @@ int gfs2_releasepage(struct page *page, gfp_t gfp_mask)
if (bd) {
gfs2_assert_warn(sdp, bd->bd_bh == bh);
gfs2_assert_warn(sdp, list_empty(&bd->bd_list_tr));
- bd->bd_bh = NULL;
- if (!list_empty(&bd->bd_le.le_list))
- bd = NULL;
+ if (!list_empty(&bd->bd_le.le_list)) {
+ if (!buffer_pinned(bh))
+ list_del_init(&bd->bd_le.le_list);
+ else
+ bd = NULL;
+ }
+ if (bd)
+ bd->bd_bh = NULL;
bh->b_private = NULL;
}
gfs2_log_unlock(sdp);