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