diff options
| author | Raghavendra G <rgowdapp@redhat.com> | 2013-07-29 23:43:51 +0530 | 
|---|---|---|
| committer | Vijay Bellur <vbellur@redhat.com> | 2013-09-10 01:22:49 -0700 | 
| commit | 8641a8641c4efec9cc7ac20108f2461a0300d01c (patch) | |
| tree | 84c04b882a3f549b158b90ea99d752d6ec072ca7 /xlators/performance/write-behind/src/write-behind.c | |
| parent | 77a7ae0fbf5bf1a0eaa2d18a31bd0c6ef1913ef8 (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/5883
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Diffstat (limited to 'xlators/performance/write-behind/src/write-behind.c')
| -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 1e769008955..a3a1af36bbd 100644 --- a/xlators/performance/write-behind/src/write-behind.c +++ b/xlators/performance/write-behind/src/write-behind.c @@ -749,7 +749,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]; @@ -799,22 +799,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;				\ @@ -823,7 +824,7 @@ err:  	} while (0) -void +int  wb_fulfill (wb_inode_t *wb_inode, list_head_t *liabilities)  {  	wb_request_t  *req     = NULL; @@ -833,6 +834,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; @@ -876,8 +878,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;  } @@ -1162,27 +1165,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;  } @@ -1408,7 +1419,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;  | 
