256ebe
From 76127f4f8f3c2bf415f66a335e7b37670cb9bd84 Mon Sep 17 00:00:00 2001
256ebe
From: Raghavendra G <rgowdapp@redhat.com>
256ebe
Date: Fri, 3 May 2019 10:14:48 +0530
256ebe
Subject: [PATCH 134/141] performance/write-behind: remove request from wip
256ebe
 list in wb_writev_cbk
256ebe
256ebe
There is a race in the way O_DIRECT writes are handled. Assume two
256ebe
overlapping write requests w1 and w2.
256ebe
256ebe
* w1 is issued and is in wb_inode->wip queue as the response is still
256ebe
  pending from bricks. Also wb_request_unref in wb_do_winds is not yet
256ebe
  invoked.
256ebe
256ebe
       list_for_each_entry_safe (req, tmp, tasks, winds) {
256ebe
		list_del_init (&req->winds);
256ebe
256ebe
                if (req->op_ret == -1) {
256ebe
			call_unwind_error_keep_stub (req->stub, req->op_ret,
256ebe
		                                     req->op_errno);
256ebe
                } else {
256ebe
                        call_resume_keep_stub (req->stub);
256ebe
		}
256ebe
256ebe
                wb_request_unref (req);
256ebe
        }
256ebe
256ebe
* w2 is issued and wb_process_queue is invoked. w2 is not picked up
256ebe
  for winding as w1 is still in wb_inode->wip. w1 is added to todo
256ebe
  list and wb_writev for w2 returns.
256ebe
256ebe
* response to w1 is received and invokes wb_request_unref. Assume
256ebe
  wb_request_unref in wb_do_winds (see point 1) is not invoked
256ebe
  yet. Since there is one more refcount, wb_request_unref in
256ebe
  wb_writev_cbk of w1 doesn't remove w1 from wip.
256ebe
256ebe
* wb_process_queue is invoked as part of wb_writev_cbk of w1. But, it
256ebe
  fails to wind w2 as w1 is still in wip.
256ebe
256ebe
* wb_requet_unref is invoked on w1 as part of wb_do_winds. w1 is
256ebe
  removed from all queues including w1.
256ebe
256ebe
* After this point there is no invocation of wb_process_queue unless
256ebe
  new request is issued from application causing w2 to be hung till
256ebe
  the next request.
256ebe
256ebe
This bug is similar to bz 1626780 and bz 1379655.
256ebe
256ebe
upstream patch: https://review.gluster.org/#/c/glusterfs/+/22654/
256ebe
BUG: 1702686
256ebe
Change-Id: Iaa47437613591699d4c8ad18bc0b32de6affcc31
256ebe
fixes: bz#1702686
256ebe
Signed-off-by: Raghavendra G <rgowdapp@redhat.com>
256ebe
Reviewed-on: https://code.engineering.redhat.com/gerrit/169552
256ebe
Tested-by: RHGS Build Bot <nigelb@redhat.com>
256ebe
Reviewed-by: Sunil Kumar Heggodu Gopala Acharya <sheggodu@redhat.com>
256ebe
---
256ebe
 xlators/performance/write-behind/src/write-behind.c | 6 ++++++
256ebe
 1 file changed, 6 insertions(+)
256ebe
256ebe
diff --git a/xlators/performance/write-behind/src/write-behind.c b/xlators/performance/write-behind/src/write-behind.c
256ebe
index cf302bd..70e281a 100644
256ebe
--- a/xlators/performance/write-behind/src/write-behind.c
256ebe
+++ b/xlators/performance/write-behind/src/write-behind.c
256ebe
@@ -1813,6 +1813,12 @@ wb_writev_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret,
256ebe
     frame->local = NULL;
256ebe
     wb_inode = req->wb_inode;
256ebe
 
256ebe
+    LOCK(&req->wb_inode->lock);
256ebe
+    {
256ebe
+        list_del_init(&req->wip);
256ebe
+    }
256ebe
+    UNLOCK(&req->wb_inode->lock);
256ebe
+
256ebe
     wb_request_unref(req);
256ebe
 
256ebe
     /* requests could be pending while this was in progress */
256ebe
-- 
256ebe
1.8.3.1
256ebe