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