Hi,

Function gfs2_ail_empty_gl is part of the sync process (go_sync) for
a glock. The go_sync glop is called to sync the metadata for a glock
so we can, in good conscience, tell dlm to release the lock to another
node. Its goal is not only to sync the metadata for the glock, but
also to ensure all the glock's revokes are written properly as well.

The sync is accomplished by first calling a log_flush. Then it calls
function gfs2_ail_empty_gl to make sure all the revokes are written
for the glock.

Before this patch, function gfs2_ail_empty_gl was not doing that
correctly. It was checking for NEW items that needed to be revoked
(gl_ail_count) and if there weren't any, it was exiting. But the
log flush could have introduced new items on the sdp revokes list,
so they're still pending, but still accounted for in gl->gl_revokes.

This patch rearranges function gfs2_ail_empty_gl so that it first
processes new revokes for its ail list, then follows through with
its second log flush (for revokes both new and old) and then calls
log_flush_wait to make sure the revokes are written back.

Signed-off-by: Bob Peterson <rpete...@redhat.com>
---
 fs/gfs2/glops.c | 68 +++++++++++++++++++++------------------------------------
 1 file changed, 25 insertions(+), 43 deletions(-)

diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
index 9406e46c31fc..cdd48f52d6b3 100644
--- a/fs/gfs2/glops.c
+++ b/fs/gfs2/glops.c
@@ -90,56 +90,38 @@ static int gfs2_ail_empty_gl(struct gfs2_glock *gl)
        struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
        struct gfs2_trans tr;
        int ret;
+       bool need_flush = false;
 
        memset(&tr, 0, sizeof(tr));
        INIT_LIST_HEAD(&tr.tr_buf);
        INIT_LIST_HEAD(&tr.tr_databuf);
        tr.tr_revokes = atomic_read(&gl->gl_ail_count);
 
-       if (!tr.tr_revokes) {
-               bool have_revokes;
-               bool log_in_flight;
-
-               /*
-                * We have nothing on the ail, but there could be revokes on
-                * the sdp revoke queue, in which case, we still want to flush
-                * the log and wait for it to finish.
-                *
-                * If the sdp revoke list is empty too, we might still have an
-                * io outstanding for writing revokes, so we should wait for
-                * it before returning.
-                *
-                * If none of these conditions are true, our revokes are all
-                * flushed and we can return.
-                */
-               gfs2_log_lock(sdp);
-               have_revokes = !list_empty(&sdp->sd_log_revokes);
-               log_in_flight = atomic_read(&sdp->sd_log_in_flight);
-               gfs2_log_unlock(sdp);
-               if (have_revokes)
-                       goto flush;
-               if (log_in_flight)
-                       log_flush_wait(sdp);
-               return 0;
+       if (tr.tr_revokes) {
+               /* A shortened, inline version of gfs2_trans_begin()
+                * tr->alloced is not set since the transaction structure is
+                * on the stack */
+               tr.tr_reserved = 1 + gfs2_struct2blk(sdp, tr.tr_revokes,
+                                                    sizeof(u64));
+               tr.tr_ip = _RET_IP_;
+               ret = gfs2_log_reserve(sdp, tr.tr_reserved);
+               if (ret < 0)
+                       return ret;
+               WARN_ON_ONCE(current->journal_info);
+               current->journal_info = &tr;
+
+               __gfs2_ail_flush(gl, 0, tr.tr_revokes);
+
+               gfs2_trans_end(sdp);
+               need_flush = true;
+       } else if (atomic_read(&gl->gl_revokes)) {
+               need_flush = true;
+       }
+       if (need_flush) {
+               gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL |
+                              GFS2_LFC_AIL_EMPTY_GL);
+               log_flush_wait(sdp);
        }
-
-       /* A shortened, inline version of gfs2_trans_begin()
-         * tr->alloced is not set since the transaction structure is
-         * on the stack */
-       tr.tr_reserved = 1 + gfs2_struct2blk(sdp, tr.tr_revokes, sizeof(u64));
-       tr.tr_ip = _RET_IP_;
-       ret = gfs2_log_reserve(sdp, tr.tr_reserved);
-       if (ret < 0)
-               return ret;
-       WARN_ON_ONCE(current->journal_info);
-       current->journal_info = &tr;
-
-       __gfs2_ail_flush(gl, 0, tr.tr_revokes);
-
-       gfs2_trans_end(sdp);
-flush:
-       gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL |
-                      GFS2_LFC_AIL_EMPTY_GL);
        return 0;
 }
 

Reply via email to