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;  | 
