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