mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	nfs: count DIO good bytes correctly with mirroring
When resending to MDS, we might resend multiple mirroring requests to MDS. As a result, nfs_direct_good_bytes() ends up counting bytes multiple times, causing application to get wrong return results in read/write syscalls. Fix it by tracking start of a dreq and checking the range of pgio header. Cc: Weston Andros Adamson <dros@primarydata.com> Signed-off-by: Peng Tao <tao.peng@primarydata.com>
This commit is contained in:
		
							parent
							
								
									aa8a45ee97
								
							
						
					
					
						commit
						5fadeb47dc
					
				
					 1 changed files with 8 additions and 4 deletions
				
			
		| 
						 | 
					@ -88,6 +88,7 @@ struct nfs_direct_req {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ssize_t			count,		/* bytes actually processed */
 | 
						ssize_t			count,		/* bytes actually processed */
 | 
				
			||||||
				bytes_left,	/* bytes left to be sent */
 | 
									bytes_left,	/* bytes left to be sent */
 | 
				
			||||||
 | 
									io_start,	/* start of IO */
 | 
				
			||||||
				error;		/* any reported error */
 | 
									error;		/* any reported error */
 | 
				
			||||||
	struct completion	completion;	/* wait for i/o completion */
 | 
						struct completion	completion;	/* wait for i/o completion */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -130,10 +131,11 @@ nfs_direct_good_bytes(struct nfs_direct_req *dreq, struct nfs_pgio_header *hdr)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	WARN_ON_ONCE(hdr->pgio_mirror_idx >= dreq->mirror_count);
 | 
						WARN_ON_ONCE(hdr->pgio_mirror_idx >= dreq->mirror_count);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dreq->mirrors[hdr->pgio_mirror_idx].count += hdr->good_bytes;
 | 
						count = dreq->mirrors[hdr->pgio_mirror_idx].count;
 | 
				
			||||||
 | 
						if (count + dreq->io_start < hdr->io_start + hdr->good_bytes) {
 | 
				
			||||||
	if (hdr->pgio_mirror_idx == 0)
 | 
							count = hdr->io_start + hdr->good_bytes - dreq->io_start;
 | 
				
			||||||
		dreq->count += hdr->good_bytes;
 | 
							dreq->mirrors[hdr->pgio_mirror_idx].count = count;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* update the dreq->count by finding the minimum agreed count from all
 | 
						/* update the dreq->count by finding the minimum agreed count from all
 | 
				
			||||||
	 * mirrors */
 | 
						 * mirrors */
 | 
				
			||||||
| 
						 | 
					@ -594,6 +596,7 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, struct iov_iter *iter,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dreq->inode = inode;
 | 
						dreq->inode = inode;
 | 
				
			||||||
	dreq->bytes_left = count;
 | 
						dreq->bytes_left = count;
 | 
				
			||||||
 | 
						dreq->io_start = pos;
 | 
				
			||||||
	dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp));
 | 
						dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp));
 | 
				
			||||||
	l_ctx = nfs_get_lock_context(dreq->ctx);
 | 
						l_ctx = nfs_get_lock_context(dreq->ctx);
 | 
				
			||||||
	if (IS_ERR(l_ctx)) {
 | 
						if (IS_ERR(l_ctx)) {
 | 
				
			||||||
| 
						 | 
					@ -1002,6 +1005,7 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dreq->inode = inode;
 | 
						dreq->inode = inode;
 | 
				
			||||||
	dreq->bytes_left = count;
 | 
						dreq->bytes_left = count;
 | 
				
			||||||
 | 
						dreq->io_start = pos;
 | 
				
			||||||
	dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp));
 | 
						dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp));
 | 
				
			||||||
	l_ctx = nfs_get_lock_context(dreq->ctx);
 | 
						l_ctx = nfs_get_lock_context(dreq->ctx);
 | 
				
			||||||
	if (IS_ERR(l_ctx)) {
 | 
						if (IS_ERR(l_ctx)) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue