mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	NFS: commit errors should be fatal
Fix the O_DIRECT code to avoid retries if the COMMIT fails with a fatal error. Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
This commit is contained in:
		
							parent
							
								
									18f4129696
								
							
						
					
					
						commit
						fb5f7f20cd
					
				
					 1 changed files with 30 additions and 2 deletions
				
			
		| 
						 | 
					@ -94,6 +94,7 @@ struct nfs_direct_req {
 | 
				
			||||||
#define NFS_ODIRECT_RESCHED_WRITES	(2)	/* write verification failed */
 | 
					#define NFS_ODIRECT_RESCHED_WRITES	(2)	/* write verification failed */
 | 
				
			||||||
	/* for read */
 | 
						/* for read */
 | 
				
			||||||
#define NFS_ODIRECT_SHOULD_DIRTY	(3)	/* dirty user-space page after read */
 | 
					#define NFS_ODIRECT_SHOULD_DIRTY	(3)	/* dirty user-space page after read */
 | 
				
			||||||
 | 
					#define NFS_ODIRECT_DONE		INT_MAX	/* write verification failed */
 | 
				
			||||||
	struct nfs_writeverf	verf;		/* unstable write verifier */
 | 
						struct nfs_writeverf	verf;		/* unstable write verifier */
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -678,8 +679,17 @@ static void nfs_direct_commit_complete(struct nfs_commit_data *data)
 | 
				
			||||||
	struct nfs_page *req;
 | 
						struct nfs_page *req;
 | 
				
			||||||
	int status = data->task.tk_status;
 | 
						int status = data->task.tk_status;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (status < 0) {
 | 
				
			||||||
 | 
							/* Errors in commit are fatal */
 | 
				
			||||||
 | 
							dreq->error = status;
 | 
				
			||||||
 | 
							dreq->max_count = 0;
 | 
				
			||||||
 | 
							dreq->count = 0;
 | 
				
			||||||
 | 
							dreq->flags = NFS_ODIRECT_DONE;
 | 
				
			||||||
 | 
						} else if (dreq->flags == NFS_ODIRECT_DONE)
 | 
				
			||||||
 | 
							status = dreq->error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	nfs_init_cinfo_from_dreq(&cinfo, dreq);
 | 
						nfs_init_cinfo_from_dreq(&cinfo, dreq);
 | 
				
			||||||
	if (status < 0 || nfs_direct_cmp_commit_data_verf(dreq, data))
 | 
						if (nfs_direct_cmp_commit_data_verf(dreq, data))
 | 
				
			||||||
		dreq->flags = NFS_ODIRECT_RESCHED_WRITES;
 | 
							dreq->flags = NFS_ODIRECT_RESCHED_WRITES;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	while (!list_empty(&data->pages)) {
 | 
						while (!list_empty(&data->pages)) {
 | 
				
			||||||
| 
						 | 
					@ -708,7 +718,8 @@ static void nfs_direct_resched_write(struct nfs_commit_info *cinfo,
 | 
				
			||||||
	struct nfs_direct_req *dreq = cinfo->dreq;
 | 
						struct nfs_direct_req *dreq = cinfo->dreq;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_lock(&dreq->lock);
 | 
						spin_lock(&dreq->lock);
 | 
				
			||||||
	dreq->flags = NFS_ODIRECT_RESCHED_WRITES;
 | 
						if (dreq->flags != NFS_ODIRECT_DONE)
 | 
				
			||||||
 | 
							dreq->flags = NFS_ODIRECT_RESCHED_WRITES;
 | 
				
			||||||
	spin_unlock(&dreq->lock);
 | 
						spin_unlock(&dreq->lock);
 | 
				
			||||||
	nfs_mark_request_commit(req, NULL, cinfo, 0);
 | 
						nfs_mark_request_commit(req, NULL, cinfo, 0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -731,6 +742,22 @@ static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq)
 | 
				
			||||||
		nfs_direct_write_reschedule(dreq);
 | 
							nfs_direct_write_reschedule(dreq);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void nfs_direct_write_clear_reqs(struct nfs_direct_req *dreq)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nfs_commit_info cinfo;
 | 
				
			||||||
 | 
						struct nfs_page *req;
 | 
				
			||||||
 | 
						LIST_HEAD(reqs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nfs_init_cinfo_from_dreq(&cinfo, dreq);
 | 
				
			||||||
 | 
						nfs_direct_write_scan_commit_list(dreq->inode, &reqs, &cinfo);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while (!list_empty(&reqs)) {
 | 
				
			||||||
 | 
							req = nfs_list_entry(reqs.next);
 | 
				
			||||||
 | 
							nfs_list_remove_request(req);
 | 
				
			||||||
 | 
							nfs_unlock_and_release_request(req);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void nfs_direct_write_schedule_work(struct work_struct *work)
 | 
					static void nfs_direct_write_schedule_work(struct work_struct *work)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct nfs_direct_req *dreq = container_of(work, struct nfs_direct_req, work);
 | 
						struct nfs_direct_req *dreq = container_of(work, struct nfs_direct_req, work);
 | 
				
			||||||
| 
						 | 
					@ -745,6 +772,7 @@ static void nfs_direct_write_schedule_work(struct work_struct *work)
 | 
				
			||||||
			nfs_direct_write_reschedule(dreq);
 | 
								nfs_direct_write_reschedule(dreq);
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
 | 
								nfs_direct_write_clear_reqs(dreq);
 | 
				
			||||||
			nfs_zap_mapping(dreq->inode, dreq->inode->i_mapping);
 | 
								nfs_zap_mapping(dreq->inode, dreq->inode->i_mapping);
 | 
				
			||||||
			nfs_direct_complete(dreq);
 | 
								nfs_direct_complete(dreq);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue