Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

NFS/localio: Stop further I/O upon hitting an error

If the call into the filesystem results in an I/O error, then the next
chunk of data won't be contiguous with the end of the last successful
chunk. So break out of the I/O loop and report the results.
Currently the localio code will do this for a short read/write, but not
for an error.

Fixes: 6a218b9c3183 ("nfs/localio: do not issue misaligned DIO out-of-order")
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Reviewed-by: Mike Snitzer <snitzer@kernel.org>

+14 -16
+14 -16
fs/nfs/localio.c
··· 618 618 struct nfs_local_kiocb *iocb = 619 619 container_of(work, struct nfs_local_kiocb, work); 620 620 struct file *filp = iocb->kiocb.ki_filp; 621 - bool force_done = false; 622 621 ssize_t status; 623 622 int n_iters; 624 623 ··· 636 637 scoped_with_creds(filp->f_cred) 637 638 status = filp->f_op->read_iter(&iocb->kiocb, &iocb->iters[i]); 638 639 639 - if (status != -EIOCBQUEUED) { 640 - if (unlikely(status >= 0 && status < iocb->iters[i].count)) 641 - force_done = true; /* Partial read */ 642 - if (nfs_local_pgio_done(iocb, status, force_done)) { 643 - nfs_local_read_iocb_done(iocb); 644 - break; 645 - } 640 + if (status == -EIOCBQUEUED) 641 + continue; 642 + /* Break on completion, errors, or short reads */ 643 + if (nfs_local_pgio_done(iocb, status, false) || status < 0 || 644 + (size_t)status < iov_iter_count(&iocb->iters[i])) { 645 + nfs_local_read_iocb_done(iocb); 646 + break; 646 647 } 647 648 } 648 649 } ··· 820 821 container_of(work, struct nfs_local_kiocb, work); 821 822 struct file *filp = iocb->kiocb.ki_filp; 822 823 unsigned long old_flags = current->flags; 823 - bool force_done = false; 824 824 ssize_t status; 825 825 int n_iters; 826 826 ··· 841 843 scoped_with_creds(filp->f_cred) 842 844 status = filp->f_op->write_iter(&iocb->kiocb, &iocb->iters[i]); 843 845 844 - if (status != -EIOCBQUEUED) { 845 - if (unlikely(status >= 0 && status < iocb->iters[i].count)) 846 - force_done = true; /* Partial write */ 847 - if (nfs_local_pgio_done(iocb, status, force_done)) { 848 - nfs_local_write_iocb_done(iocb); 849 - break; 850 - } 846 + if (status == -EIOCBQUEUED) 847 + continue; 848 + /* Break on completion, errors, or short writes */ 849 + if (nfs_local_pgio_done(iocb, status, false) || status < 0 || 850 + (size_t)status < iov_iter_count(&iocb->iters[i])) { 851 + nfs_local_write_iocb_done(iocb); 852 + break; 851 853 } 852 854 } 853 855 file_end_write(filp);