diff options
author | Raghavendra G <rgowdapp@redhat.com> | 2013-07-29 23:43:51 +0530 |
---|---|---|
committer | Anand Avati <avati@redhat.com> | 2013-08-14 02:11:58 -0700 |
commit | 1e49b3ac9b1019c742236be8db0ca8ec00750ae7 (patch) | |
tree | 027d6cd702aae990555c931d95f4806db846566e | |
parent | 8360037701788d49471cc0228fa873aa18382023 (diff) |
performance/write-behind: invoke request queue processing if
we find fd marked bad while trying to fulfill lies.
* flush was queued behind some unfulfilled write.
* A previously wound write returned an error and hence fd was marked
bad with corresponding error.
* wb_fulfill_head (invocation probably rooted in wb_flush), before
winding checks for failures of previous writes and since there was a
failure, calls wb_head_done without even winding one request in head.
* wb_head_done unrefs all the requests in list "head".
* since flush was last operation on fd (and most likely last operation
on inode itself), no one invokes wb_process_queue and flush is stuck
in request queue for eternity.
Change-Id: I3b5b114a1c401d477dd7ff64fb6119b43fda2d18
BUG: 988642
Signed-off-by: Raghavendra G <rgowdapp@redhat.com>
Reviewed-on: http://review.gluster.org/5398
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Anand Avati <avati@redhat.com>
-rw-r--r-- | xlators/performance/write-behind/src/write-behind.c | 49 |
1 files changed, 30 insertions, 19 deletions
diff --git a/xlators/performance/write-behind/src/write-behind.c b/xlators/performance/write-behind/src/write-behind.c index e01a227f30e..95c5921c6bd 100644 --- a/xlators/performance/write-behind/src/write-behind.c +++ b/xlators/performance/write-behind/src/write-behind.c @@ -745,7 +745,7 @@ wb_fulfill_cbk (call_frame_t *frame, void *cookie, xlator_t *this, } while (0) -void +int wb_fulfill_head (wb_inode_t *wb_inode, wb_request_t *head) { struct iovec vector[MAX_VECTOR_COUNT]; @@ -795,22 +795,23 @@ wb_fulfill_head (wb_inode_t *wb_inode, wb_request_t *head) head->stub->args.flags, head->stub->args.iobref, NULL); - return; + return 0; err: if (!fderr) { /* frame creation failure */ - wb_fulfill_err (head, ENOMEM); + fderr = ENOMEM; + wb_fulfill_err (head, fderr); } wb_head_done (head); - return; + return fderr; } #define NEXT_HEAD(head, req) do { \ if (head) \ - wb_fulfill_head (wb_inode, head); \ + ret |= wb_fulfill_head (wb_inode, head); \ head = req; \ expected_offset = req->stub->args.offset + \ req->write_size; \ @@ -819,7 +820,7 @@ err: } while (0) -void +int wb_fulfill (wb_inode_t *wb_inode, list_head_t *liabilities) { wb_request_t *req = NULL; @@ -829,6 +830,7 @@ wb_fulfill (wb_inode_t *wb_inode, list_head_t *liabilities) off_t expected_offset = 0; size_t curr_aggregate = 0; size_t vector_count = 0; + int ret = 0; conf = wb_inode->this->private; @@ -872,8 +874,9 @@ wb_fulfill (wb_inode_t *wb_inode, list_head_t *liabilities) } if (head) - wb_fulfill_head (wb_inode, head); - return; + ret |= wb_fulfill_head (wb_inode, head); + + return ret; } @@ -1158,27 +1161,35 @@ wb_process_queue (wb_inode_t *wb_inode) list_head_t tasks = {0, }; list_head_t lies = {0, }; list_head_t liabilities = {0, }; + int retry = 0; INIT_LIST_HEAD (&tasks); INIT_LIST_HEAD (&lies); INIT_LIST_HEAD (&liabilities); - LOCK (&wb_inode->lock); - { - __wb_preprocess_winds (wb_inode); + do { + LOCK (&wb_inode->lock); + { + __wb_preprocess_winds (wb_inode); - __wb_pick_winds (wb_inode, &tasks, &liabilities); + __wb_pick_winds (wb_inode, &tasks, &liabilities); - __wb_pick_unwinds (wb_inode, &lies); + __wb_pick_unwinds (wb_inode, &lies); - } - UNLOCK (&wb_inode->lock); + } + UNLOCK (&wb_inode->lock); - wb_do_unwinds (wb_inode, &lies); + wb_do_unwinds (wb_inode, &lies); - wb_do_winds (wb_inode, &tasks); + wb_do_winds (wb_inode, &tasks); - wb_fulfill (wb_inode, &liabilities); + /* fd might've been marked bad due to previous errors. + * Since, caller of wb_process_queue might be the last fop on + * inode, make sure we keep processing request queue, till there + * are no requests left. + */ + retry = wb_fulfill (wb_inode, &liabilities); + } while (retry); return; } @@ -1409,7 +1420,7 @@ wb_flush (call_frame_t *frame, xlator_t *this, fd_t *fd, dict_t *xdata) if (!wb_enqueue (wb_inode, stub)) goto unwind; - wb_process_queue (wb_inode); + wb_process_queue (wb_inode); return 0; |