Skip to content

Commit 001945a

Browse files
author
Trond Myklebust
committed
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: 6a218b9 ("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>
1 parent df56ddd commit 001945a

1 file changed

Lines changed: 14 additions & 16 deletions

File tree

fs/nfs/localio.c

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -618,7 +618,6 @@ static void nfs_local_call_read(struct work_struct *work)
618618
struct nfs_local_kiocb *iocb =
619619
container_of(work, struct nfs_local_kiocb, work);
620620
struct file *filp = iocb->kiocb.ki_filp;
621-
bool force_done = false;
622621
ssize_t status;
623622
int n_iters;
624623

@@ -637,13 +636,13 @@ static void nfs_local_call_read(struct work_struct *work)
637636
scoped_with_creds(filp->f_cred)
638637
status = filp->f_op->read_iter(&iocb->kiocb, &iocb->iters[i]);
639638

640-
if (status != -EIOCBQUEUED) {
641-
if (unlikely(status >= 0 && status < iocb->iters[i].count))
642-
force_done = true; /* Partial read */
643-
if (nfs_local_pgio_done(iocb, status, force_done)) {
644-
nfs_local_read_iocb_done(iocb);
645-
break;
646-
}
639+
if (status == -EIOCBQUEUED)
640+
continue;
641+
/* Break on completion, errors, or short reads */
642+
if (nfs_local_pgio_done(iocb, status, false) || status < 0 ||
643+
(size_t)status < iov_iter_count(&iocb->iters[i])) {
644+
nfs_local_read_iocb_done(iocb);
645+
break;
647646
}
648647
}
649648
}
@@ -821,7 +820,6 @@ static void nfs_local_call_write(struct work_struct *work)
821820
container_of(work, struct nfs_local_kiocb, work);
822821
struct file *filp = iocb->kiocb.ki_filp;
823822
unsigned long old_flags = current->flags;
824-
bool force_done = false;
825823
ssize_t status;
826824
int n_iters;
827825

@@ -843,13 +841,13 @@ static void nfs_local_call_write(struct work_struct *work)
843841
scoped_with_creds(filp->f_cred)
844842
status = filp->f_op->write_iter(&iocb->kiocb, &iocb->iters[i]);
845843

846-
if (status != -EIOCBQUEUED) {
847-
if (unlikely(status >= 0 && status < iocb->iters[i].count))
848-
force_done = true; /* Partial write */
849-
if (nfs_local_pgio_done(iocb, status, force_done)) {
850-
nfs_local_write_iocb_done(iocb);
851-
break;
852-
}
844+
if (status == -EIOCBQUEUED)
845+
continue;
846+
/* Break on completion, errors, or short writes */
847+
if (nfs_local_pgio_done(iocb, status, false) || status < 0 ||
848+
(size_t)status < iov_iter_count(&iocb->iters[i])) {
849+
nfs_local_write_iocb_done(iocb);
850+
break;
853851
}
854852
}
855853
file_end_write(filp);

0 commit comments

Comments
 (0)