Trim the list in gfs2_ordered_write() as we run through it
to write out inodes.
Also attempt to remove an inode from the list after it is
fsync'ed.
Finally, call gfs2_ordered_write() in case we were not able
to shrink the list in gfs2_ordered_shrink() in the hopes that
it will eventually cause the list to shrink.
---
 fs/gfs2/file.c   |  3 +++
 fs/gfs2/incore.h |  1 +
 fs/gfs2/log.c    | 13 +++++++++++--
 fs/gfs2/log.h    |  4 +++-
 fs/gfs2/quota.c  |  4 ++--
 5 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c
index 757ec66..75f9ac0 100644
--- a/fs/gfs2/file.c
+++ b/fs/gfs2/file.c
@@ -697,6 +697,9 @@ static int gfs2_fsync(struct file *file, loff_t start, 
loff_t end,
        if (mapping->nrpages)
                ret = filemap_fdatawait_range(mapping, start, end);
 
+       if (!ret && !ret1)
+               gfs2_ordered_del_inode(ip, ORD_WHENCE_FSYNC);
+
        return ret ? ret : ret1;
 }
 
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index 6fcad2a..93da360 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -661,6 +661,7 @@ struct ord_stats {
        unsigned long os_rm_trunc;
        unsigned long os_rm_evict;
        unsigned long os_rm_wait;
+       unsigned long os_rm_fsync;
        unsigned long os_rm_syncfs;
        unsigned long os_rm_write;
        unsigned long os_rm_setflags;
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c
index 6d618a1..4cfef47 100644
--- a/fs/gfs2/log.c
+++ b/fs/gfs2/log.c
@@ -507,9 +507,13 @@ static void gfs2_ordered_write(struct gfs2_sbd *sdp)
        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);
-               list_move(&ip->i_ordered, &written);
-               if (ip->i_inode.i_mapping->nrpages == 0)
+               if (ip->i_inode.i_mapping->nrpages == 0) {
+                       test_and_clear_bit(GIF_ORDERED, &ip->i_flags);
+                       list_del(&ip->i_ordered);
+                       ord_stats_adjust(sdp, -1, ORD_WHENCE_ORD_WRITE);
                        continue;
+               }
+               list_move(&ip->i_ordered, &written);
                spin_unlock(&sdp->sd_ordered_lock);
                filemap_fdatawrite(ip->i_inode.i_mapping);
                spin_lock(&sdp->sd_ordered_lock);
@@ -540,17 +544,22 @@ static void gfs2_ordered_wait(struct gfs2_sbd *sdp)
 void gfs2_ordered_shrink(struct gfs2_sbd *sdp, int whence)
 {
        struct gfs2_inode *ip, *tmp;
+       bool removed;
 
        spin_lock(&sdp->sd_ordered_lock);
        list_for_each_entry_safe(ip, tmp, &sdp->sd_log_le_ordered, i_ordered) {
                if (ip->i_inode.i_mapping->nrpages != 0)
                        continue;
                if (test_and_clear_bit(GIF_ORDERED, &ip->i_flags)) {
+                       removed = true;
                        list_del(&ip->i_ordered);
                        ord_stats_adjust(sdp, -1, whence);
                }
        }
        spin_unlock(&sdp->sd_ordered_lock);
+
+       if (!removed)
+               gfs2_ordered_write(sdp);
 }
 
 void gfs2_ordered_del_inode(struct gfs2_inode *ip, int whence)
diff --git a/fs/gfs2/log.h b/fs/gfs2/log.h
index 80c8861..0bc3620 100644
--- a/fs/gfs2/log.h
+++ b/fs/gfs2/log.h
@@ -55,7 +55,8 @@ enum {
        ORD_WHENCE_SYNCFS       = 3,
        ORD_WHENCE_ORD_WRITE    = 4,
        ORD_WHENCE_SETFLAGS     = 5,
-       ORD_WHENCE_ADD          = 6,
+       ORD_WHENCE_FSYNC        = 6,
+       ORD_WHENCE_ADD          = 7,
 };
 
 static inline void ord_stats_adjust(struct gfs2_sbd *sdp, int count, int 
whence)
@@ -70,6 +71,7 @@ static inline void ord_stats_adjust(struct gfs2_sbd *sdp, int 
count, int whence)
        case ORD_WHENCE_SYNCFS:     os->os_rm_syncfs += -(count); break;
        case ORD_WHENCE_ORD_WRITE:  os->os_rm_write += -(count); break;
        case ORD_WHENCE_SETFLAGS:   os->os_rm_setflags += -(count); break;
+       case ORD_WHENCE_FSYNC:      os->os_rm_fsync += -(count); break;
 
        case ORD_WHENCE_ADD:        os->os_add += count; break;
        default: break;
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
index 66c5126..63e3afa 100644
--- a/fs/gfs2/quota.c
+++ b/fs/gfs2/quota.c
@@ -1575,11 +1575,11 @@ int gfs2_quotad(void *data)
 
                printk(KERN_WARNING "Ord list Size:%lu +[add_inode:%lu] "
                       "-[trunc:%lu evict:%lu wait:%lu syncfs:%lu ord_write:%lu"
-                      " setflags:%lu]\n", sdp->sd_ord_stats.os_ct,
+                      " setflags:%lu fsync:%lu]\n", sdp->sd_ord_stats.os_ct,
                       sdp->sd_ord_stats.os_add, sdp->sd_ord_stats.os_rm_trunc,
                       sdp->sd_ord_stats.os_rm_evict, 
sdp->sd_ord_stats.os_rm_wait,
                       sdp->sd_ord_stats.os_rm_syncfs, 
sdp->sd_ord_stats.os_rm_write,
-                      sdp->sd_ord_stats.os_rm_setflags);
+                      sdp->sd_ord_stats.os_rm_setflags, 
sdp->sd_ord_stats.os_rm_fsync);
        }
 
        return 0;
-- 
2.4.11

Reply via email to