summaryrefslogtreecommitdiffstats
path: root/fs/gfs2/trans.c
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2013-01-28 09:30:07 +0000
committerSteven Whitehouse <swhiteho@redhat.com>2013-01-29 10:29:17 +0000
commit4513899092b3254b3539f92a65d2839afa1d50f6 (patch)
tree1080b7adfac648dacd2d4aa70643a6a456284492 /fs/gfs2/trans.c
parentd564053f074634e7a966359dc97d26900fa5f52d (diff)
downloadlinux-4513899092b3254b3539f92a65d2839afa1d50f6.tar.bz2
GFS2: Use ->writepages for ordered writes
Instead of using a list of buffers to write ahead of the journal flush, this now uses a list of inodes and calls ->writepages via filemap_fdatawrite() in order to achieve the same thing. For most use cases this results in a shorter ordered write list, as well as much larger i/os being issued. The ordered write list is sorted by inode number before writing in order to retain the disk block ordering between inodes as per the previous code. The previous ordered write code used to conflict in its assumptions about how to write out the disk blocks with mpage_writepages() so that with this updated version we can also use mpage_writepages() for GFS2's ordered write, writepages implementation. So we will also send larger i/os from writeback too. Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2/trans.c')
-rw-r--r--fs/gfs2/trans.c41
1 files changed, 18 insertions, 23 deletions
diff --git a/fs/gfs2/trans.c b/fs/gfs2/trans.c
index 14dbf6d3cdc0..88162fae27a5 100644
--- a/fs/gfs2/trans.c
+++ b/fs/gfs2/trans.c
@@ -159,7 +159,9 @@ static struct gfs2_bufdata *gfs2_alloc_bufdata(struct gfs2_glock *gl,
}
/**
- * databuf_lo_add - Add a databuf to the transaction.
+ * gfs2_trans_add_data - Add a databuf to the transaction.
+ * @gl: The inode glock associated with the buffer
+ * @bh: The buffer to add
*
* This is used in two distinct cases:
* i) In ordered write mode
@@ -174,33 +176,18 @@ static struct gfs2_bufdata *gfs2_alloc_bufdata(struct gfs2_glock *gl,
* blocks, which isn't an enormous overhead but twice as much as
* for normal metadata blocks.
*/
-static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)
+void gfs2_trans_add_data(struct gfs2_glock *gl, struct buffer_head *bh)
{
struct gfs2_trans *tr = current->journal_info;
- struct address_space *mapping = bd->bd_bh->b_page->mapping;
+ struct gfs2_sbd *sdp = gl->gl_sbd;
+ struct address_space *mapping = bh->b_page->mapping;
struct gfs2_inode *ip = GFS2_I(mapping->host);
+ struct gfs2_bufdata *bd;
- if (tr)
- tr->tr_touched = 1;
- if (!list_empty(&bd->bd_list))
+ if (!gfs2_is_jdata(ip)) {
+ gfs2_ordered_add_inode(ip);
return;
- set_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags);
- set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags);
- if (gfs2_is_jdata(ip)) {
- gfs2_pin(sdp, bd->bd_bh);
- tr->tr_num_databuf_new++;
- sdp->sd_log_num_databuf++;
- list_add_tail(&bd->bd_list, &sdp->sd_log_le_databuf);
- } else {
- list_add_tail(&bd->bd_list, &sdp->sd_log_le_ordered);
}
-}
-
-void gfs2_trans_add_data(struct gfs2_glock *gl, struct buffer_head *bh)
-{
-
- struct gfs2_sbd *sdp = gl->gl_sbd;
- struct gfs2_bufdata *bd;
lock_buffer(bh);
gfs2_log_lock(sdp);
@@ -214,7 +201,15 @@ void gfs2_trans_add_data(struct gfs2_glock *gl, struct buffer_head *bh)
gfs2_log_lock(sdp);
}
gfs2_assert(sdp, bd->bd_gl == gl);
- databuf_lo_add(sdp, bd);
+ tr->tr_touched = 1;
+ if (list_empty(&bd->bd_list)) {
+ set_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags);
+ set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags);
+ gfs2_pin(sdp, bd->bd_bh);
+ tr->tr_num_databuf_new++;
+ sdp->sd_log_num_databuf++;
+ list_add_tail(&bd->bd_list, &sdp->sd_log_le_databuf);
+ }
gfs2_log_unlock(sdp);
unlock_buffer(bh);
}