diff options
Diffstat (limited to 'fs/netfs/misc.c')
| -rw-r--r-- | fs/netfs/misc.c | 50 | 
1 files changed, 31 insertions, 19 deletions
diff --git a/fs/netfs/misc.c b/fs/netfs/misc.c index 43b67a28a8fa..20748bcfbf59 100644 --- a/fs/netfs/misc.c +++ b/fs/netfs/misc.c @@ -356,22 +356,22 @@ void netfs_wait_for_in_progress_stream(struct netfs_io_request *rreq,  	DEFINE_WAIT(myself);  	list_for_each_entry(subreq, &stream->subrequests, rreq_link) { -		if (!test_bit(NETFS_SREQ_IN_PROGRESS, &subreq->flags)) +		if (!netfs_check_subreq_in_progress(subreq))  			continue; -		trace_netfs_rreq(rreq, netfs_rreq_trace_wait_queue); +		trace_netfs_rreq(rreq, netfs_rreq_trace_wait_quiesce);  		for (;;) {  			prepare_to_wait(&rreq->waitq, &myself, TASK_UNINTERRUPTIBLE); -			if (!test_bit(NETFS_SREQ_IN_PROGRESS, &subreq->flags)) +			if (!netfs_check_subreq_in_progress(subreq))  				break;  			trace_netfs_sreq(subreq, netfs_sreq_trace_wait_for);  			schedule(); -			trace_netfs_rreq(rreq, netfs_rreq_trace_woke_queue);  		}  	} +	trace_netfs_rreq(rreq, netfs_rreq_trace_waited_quiesce);  	finish_wait(&rreq->waitq, &myself);  } @@ -381,7 +381,12 @@ void netfs_wait_for_in_progress_stream(struct netfs_io_request *rreq,  static int netfs_collect_in_app(struct netfs_io_request *rreq,  				bool (*collector)(struct netfs_io_request *rreq))  { -	bool need_collect = false, inactive = true; +	bool need_collect = false, inactive = true, done = true; + +	if (!netfs_check_rreq_in_progress(rreq)) { +		trace_netfs_rreq(rreq, netfs_rreq_trace_recollect); +		return 1; /* Done */ +	}  	for (int i = 0; i < NR_IO_STREAMS; i++) {  		struct netfs_io_subrequest *subreq; @@ -395,14 +400,16 @@ static int netfs_collect_in_app(struct netfs_io_request *rreq,  						  struct netfs_io_subrequest,  						  rreq_link);  		if (subreq && -		    (!test_bit(NETFS_SREQ_IN_PROGRESS, &subreq->flags) || +		    (!netfs_check_subreq_in_progress(subreq) ||  		     test_bit(NETFS_SREQ_MADE_PROGRESS, &subreq->flags))) {  			need_collect = true;  			break;  		} +		if (subreq || !test_bit(NETFS_RREQ_ALL_QUEUED, &rreq->flags)) +			done = false;  	} -	if (!need_collect && !inactive) +	if (!need_collect && !inactive && !done)  		return 0; /* Sleep */  	__set_current_state(TASK_RUNNING); @@ -423,14 +430,13 @@ static int netfs_collect_in_app(struct netfs_io_request *rreq,  /*   * Wait for a request to complete, successfully or otherwise.   */ -static ssize_t netfs_wait_for_request(struct netfs_io_request *rreq, -				      bool (*collector)(struct netfs_io_request *rreq)) +static ssize_t netfs_wait_for_in_progress(struct netfs_io_request *rreq, +					  bool (*collector)(struct netfs_io_request *rreq))  {  	DEFINE_WAIT(myself);  	ssize_t ret;  	for (;;) { -		trace_netfs_rreq(rreq, netfs_rreq_trace_wait_queue);  		prepare_to_wait(&rreq->waitq, &myself, TASK_UNINTERRUPTIBLE);  		if (!test_bit(NETFS_RREQ_OFFLOAD_COLLECTION, &rreq->flags)) { @@ -440,18 +446,22 @@ static ssize_t netfs_wait_for_request(struct netfs_io_request *rreq,  			case 1:  				goto all_collected;  			case 2: +				if (!netfs_check_rreq_in_progress(rreq)) +					break; +				cond_resched();  				continue;  			}  		} -		if (!test_bit(NETFS_RREQ_IN_PROGRESS, &rreq->flags)) +		if (!netfs_check_rreq_in_progress(rreq))  			break; +		trace_netfs_rreq(rreq, netfs_rreq_trace_wait_ip);  		schedule(); -		trace_netfs_rreq(rreq, netfs_rreq_trace_woke_queue);  	}  all_collected: +	trace_netfs_rreq(rreq, netfs_rreq_trace_waited_ip);  	finish_wait(&rreq->waitq, &myself);  	ret = rreq->error; @@ -478,12 +488,12 @@ all_collected:  ssize_t netfs_wait_for_read(struct netfs_io_request *rreq)  { -	return netfs_wait_for_request(rreq, netfs_read_collection); +	return netfs_wait_for_in_progress(rreq, netfs_read_collection);  }  ssize_t netfs_wait_for_write(struct netfs_io_request *rreq)  { -	return netfs_wait_for_request(rreq, netfs_write_collection); +	return netfs_wait_for_in_progress(rreq, netfs_write_collection);  }  /* @@ -494,10 +504,8 @@ static void netfs_wait_for_pause(struct netfs_io_request *rreq,  {  	DEFINE_WAIT(myself); -	trace_netfs_rreq(rreq, netfs_rreq_trace_wait_pause); -  	for (;;) { -		trace_netfs_rreq(rreq, netfs_rreq_trace_wait_queue); +		trace_netfs_rreq(rreq, netfs_rreq_trace_wait_pause);  		prepare_to_wait(&rreq->waitq, &myself, TASK_UNINTERRUPTIBLE);  		if (!test_bit(NETFS_RREQ_OFFLOAD_COLLECTION, &rreq->flags)) { @@ -507,19 +515,23 @@ static void netfs_wait_for_pause(struct netfs_io_request *rreq,  			case 1:  				goto all_collected;  			case 2: +				if (!netfs_check_rreq_in_progress(rreq) || +				    !test_bit(NETFS_RREQ_PAUSE, &rreq->flags)) +					break; +				cond_resched();  				continue;  			}  		} -		if (!test_bit(NETFS_RREQ_IN_PROGRESS, &rreq->flags) || +		if (!netfs_check_rreq_in_progress(rreq) ||  		    !test_bit(NETFS_RREQ_PAUSE, &rreq->flags))  			break;  		schedule(); -		trace_netfs_rreq(rreq, netfs_rreq_trace_woke_queue);  	}  all_collected: +	trace_netfs_rreq(rreq, netfs_rreq_trace_waited_pause);  	finish_wait(&rreq->waitq, &myself);  }  | 
