e7a346
From c1d83132c4b2d49eb922fb7fe42952856aeff83d Mon Sep 17 00:00:00 2001
e7a346
From: Raghavendra G <rgowdapp@redhat.com>
e7a346
Date: Sat, 8 Sep 2018 19:53:07 +0530
e7a346
Subject: [PATCH 371/385] performance/write-behind: remove the request from wip
e7a346
 queue in wb_fulfill_request
e7a346
e7a346
The bug is very similar to bz 1379655 and the fix too very similar to
e7a346
commit a8b2a981881221925bb5edfe7bb65b25ad855c04.
e7a346
e7a346
Before this patch, a request is removed from wip queue only when ref
e7a346
count of request hits 0. Though, wb_fulfill_request does an unref,
e7a346
it need not be the last unref and hence the request may survive in
e7a346
wip queue till the last unref. Let,
e7a346
e7a346
T1: the time at which wb_fulfill_request is invoked
e7a346
T2: the time at which last unref is done on request
e7a346
e7a346
Let's consider a case of T2 > T1. In the time window between T1 and
e7a346
T2, any other request (waiter) conflicting with request in liability
e7a346
queue (blocker - basically a write which has been lied) is blocked
e7a346
from winding. If T2 happens to be when wb_do_unwinds is invoked, no
e7a346
further processing of request list happens and "waiter" would get
e7a346
blocked forever. An example imaginary sequence of events is given
e7a346
below:
e7a346
e7a346
1. A write request w1 is picked up for winding in __wb_pick_winds
e7a346
   and w1 is moved to wip queue. Let's call this
e7a346
   invocation of wb_process_queue by wb_writev as PQ1. Note w1 is not
e7a346
   unwound.
e7a346
e7a346
2. A dependent write (w2) hits write-behind and is unwound followed by
e7a346
   a flush (f1) request. Since the liability queue
e7a346
   of inode is not empty, w2 and f1 are not picked for unwinding. Let's call
e7a346
   the invocation of wb_process_queue by wb_flush as PQ2. Note that
e7a346
   invocation of wb_process_queue by w2 doesn't wind w2 instead
e7a346
   unwinds it after which we hit PQ2
e7a346
e7a346
3. PQ2 continues and picks w1 for fulfilling and invokes
e7a346
   wb_fulfill. As part of successful wb_fulfill_cbk,
e7a346
   wb_fulfill_request (w1) is invoked. But, w1 is not freed (and hence
e7a346
   not removed from wip queue) as w1 is not unwound _yet_ and a
e7a346
   ref remains (PQ1 has not invoked wb_do_unwinds _yet_).
e7a346
e7a346
4. wb_fulfill_cbk (triggered by PQ2) invokes a wb_process_queue (let's
e7a346
   say PQ3). w2 is not picked up for winding in PQ3 as w1 is still in wip
e7a346
   queue. At this time, PQ2 and PQ3 are complete.
e7a346
e7a346
5. PQ1 continues, unwinds w1 and does last unref on w1 and w1 is freed
e7a346
   (and removed from wip queue). Since PQ1 didn't invoke
e7a346
   wb_fulfill on any other write requests, there won't be any future
e7a346
   codepaths that would invoke wb_process_queue and w2 is stuck
e7a346
   forever. This will prevent f2 too and hence close syscall is hung
e7a346
e7a346
With this fix, w1 is removed from liability queue in step 3 above and
e7a346
PQ3 winds w2 in step 4 (as there are no requests conflicting with w2
e7a346
in liability queue during execution of PQ3). Once w2 is complete, f1
e7a346
is resumed.
e7a346
e7a346
>Change-Id: Ia972fad0858dc4abccdc1227cb4d880f85b3b89b
e7a346
>Signed-off-by: Raghavendra G <rgowdapp@redhat.com>
e7a346
>Fixes: bz#1626787
e7a346
e7a346
Change-Id: Ia972fad0858dc4abccdc1227cb4d880f85b3b89b
e7a346
Signed-off-by: Raghavendra G <rgowdapp@redhat.com>
e7a346
BUG: 1626780
e7a346
upstream patch: https://review.gluster.org/21123
e7a346
Reviewed-on: https://code.engineering.redhat.com/gerrit/149775
e7a346
Tested-by: RHGS Build Bot <nigelb@redhat.com>
e7a346
Reviewed-by: Sunil Kumar Heggodu Gopala Acharya <sheggodu@redhat.com>
e7a346
---
e7a346
 xlators/performance/write-behind/src/write-behind.c | 1 +
e7a346
 1 file changed, 1 insertion(+)
e7a346
e7a346
diff --git a/xlators/performance/write-behind/src/write-behind.c b/xlators/performance/write-behind/src/write-behind.c
e7a346
index ca1cb63..478985a 100644
e7a346
--- a/xlators/performance/write-behind/src/write-behind.c
e7a346
+++ b/xlators/performance/write-behind/src/write-behind.c
e7a346
@@ -725,6 +725,7 @@ __wb_fulfill_request (wb_request_t *req)
e7a346
 		*/
e7a346
 	}
e7a346
 
e7a346
+        list_del_init (&req->wip);
e7a346
 	__wb_request_unref (req);
e7a346
 }
e7a346
 
e7a346
-- 
e7a346
1.8.3.1
e7a346