Before this patch, the ordered_write function would submit all
the ordered writes with filemap_fdatawrite, which waited for each
one to complete before moving on to the next. This patch allows it
to submit them all, then wait for them after they're submitted.

Signed-off-by: Bob Peterson <[email protected]>
---
 fs/gfs2/log.c | 34 ++++++++++++++++++++++++----------
 1 file changed, 24 insertions(+), 10 deletions(-)

diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c
index bedd1c056ca2..b05d0fbc3d05 100644
--- a/fs/gfs2/log.c
+++ b/fs/gfs2/log.c
@@ -22,6 +22,7 @@
 #include <linux/blkdev.h>
 #include <linux/writeback.h>
 #include <linux/list_sort.h>
+#include <linux/fs.h>
 
 #include "gfs2.h"
 #include "incore.h"
@@ -530,15 +531,20 @@ static int ip_cmp(void *priv, struct list_head *a, struct 
list_head *b)
        return 0;
 }
 
-static void gfs2_ordered_wait(struct gfs2_sbd *sdp)
+static void gfs2_ordered_wait(struct gfs2_sbd *sdp, struct list_head *src,
+                             struct list_head *dst)
 {
        struct gfs2_inode *ip;
 
        spin_lock(&sdp->sd_ordered_lock);
-       while (!list_empty(&sdp->sd_log_le_ordered)) {
-               ip = list_entry(sdp->sd_log_le_ordered.next, struct gfs2_inode, 
i_ordered);
-               list_del(&ip->i_ordered);
-               WARN_ON(!test_and_clear_bit(GIF_ORDERED, &ip->i_flags));
+       while (!list_empty(src)) {
+               ip = list_entry(src->next, struct gfs2_inode, i_ordered);
+               if (dst)
+                       list_move_tail(&ip->i_ordered, dst);
+               else {
+                       list_del(&ip->i_ordered);
+                       WARN_ON(!test_and_clear_bit(GIF_ORDERED, &ip->i_flags));
+               }
                if (ip->i_inode.i_mapping->nrpages == 0)
                        continue;
                spin_unlock(&sdp->sd_ordered_lock);
@@ -551,24 +557,32 @@ static void gfs2_ordered_wait(struct gfs2_sbd *sdp)
 static void gfs2_ordered_write(struct gfs2_sbd *sdp)
 {
        struct gfs2_inode *ip;
+       struct address_space *mapping;
        LIST_HEAD(written);
+       struct writeback_control wbc = {
+               .sync_mode = WB_SYNC_NONE,
+               .nr_to_write = LONG_MAX,
+               .range_start = 0,
+               .range_end = LLONG_MAX,
+       };
 
        spin_lock(&sdp->sd_ordered_lock);
        list_sort(NULL, &sdp->sd_log_le_ordered, &ip_cmp);
        while (!list_empty(&sdp->sd_log_le_ordered)) {
                ip = list_entry(sdp->sd_log_le_ordered.next, struct gfs2_inode, 
i_ordered);
-               if (ip->i_inode.i_mapping->nrpages == 0) {
+               mapping = ip->i_inode.i_mapping;
+               if (mapping->nrpages == 0) {
                        test_and_clear_bit(GIF_ORDERED, &ip->i_flags);
                        list_del(&ip->i_ordered);
                        continue;
                }
-               list_move(&ip->i_ordered, &written);
+               list_move_tail(&ip->i_ordered, &written);
                spin_unlock(&sdp->sd_ordered_lock);
-               filemap_fdatawrite(ip->i_inode.i_mapping);
+               mapping->a_ops->writepages(mapping, &wbc);
                spin_lock(&sdp->sd_ordered_lock);
        }
-       list_splice(&written, &sdp->sd_log_le_ordered);
        spin_unlock(&sdp->sd_ordered_lock);
+       gfs2_ordered_wait(sdp, &written, &sdp->sd_log_le_ordered);
 }
 
 void gfs2_ordered_del_inode(struct gfs2_inode *ip)
@@ -741,7 +755,7 @@ static void log_write_header(struct gfs2_sbd *sdp, u32 
flags)
        tail = current_tail(sdp);
 
        if (test_bit(SDF_NOBARRIERS, &sdp->sd_flags)) {
-               gfs2_ordered_wait(sdp);
+               gfs2_ordered_wait(sdp, &sdp->sd_log_le_ordered, NULL);
                log_flush_wait(sdp);
                op_flags = REQ_SYNC | REQ_META | REQ_PRIO;
        }
-- 
2.17.0

Reply via email to