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