diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 416108b424128c0c2a23fce93e982bbc57a4c341..9dde38f12c07bfec48255b99ee49d02539e52dec 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -1247,6 +1247,7 @@ static int fuse_get_user_pages(struct fuse_req *req, struct iov_iter *ii,
 			       size_t *nbytesp, int write)
 {
 	size_t nbytes = 0;  /* # bytes already packed in req */
+	ssize_t ret = 0;
 
 	/* Special case for kernel I/O: can copy directly into the buffer */
 	if (ii->type & ITER_KVEC) {
@@ -1266,13 +1267,12 @@ static int fuse_get_user_pages(struct fuse_req *req, struct iov_iter *ii,
 	while (nbytes < *nbytesp && req->num_pages < req->max_pages) {
 		unsigned npages;
 		size_t start;
-		ssize_t ret = iov_iter_get_pages(ii,
-					&req->pages[req->num_pages],
+		ret = iov_iter_get_pages(ii, &req->pages[req->num_pages],
 					*nbytesp - nbytes,
 					req->max_pages - req->num_pages,
 					&start);
 		if (ret < 0)
-			return ret;
+			break;
 
 		iov_iter_advance(ii, ret);
 		nbytes += ret;
@@ -1295,7 +1295,7 @@ static int fuse_get_user_pages(struct fuse_req *req, struct iov_iter *ii,
 
 	*nbytesp = nbytes;
 
-	return 0;
+	return ret;
 }
 
 static inline int fuse_iter_npages(const struct iov_iter *ii_p)
@@ -1319,6 +1319,7 @@ ssize_t fuse_direct_io(struct fuse_io_priv *io, struct iov_iter *iter,
 	pgoff_t idx_to = (pos + count - 1) >> PAGE_CACHE_SHIFT;
 	ssize_t res = 0;
 	struct fuse_req *req;
+	int err = 0;
 
 	if (io->async)
 		req = fuse_get_req_for_background(fc, fuse_iter_npages(iter));
@@ -1339,11 +1340,9 @@ ssize_t fuse_direct_io(struct fuse_io_priv *io, struct iov_iter *iter,
 		size_t nres;
 		fl_owner_t owner = current->files;
 		size_t nbytes = min(count, nmax);
-		int err = fuse_get_user_pages(req, iter, &nbytes, write);
-		if (err) {
-			res = err;
+		err = fuse_get_user_pages(req, iter, &nbytes, write);
+		if (err && !nbytes)
 			break;
-		}
 
 		if (write)
 			nres = fuse_send_write(req, io, pos, nbytes, owner);
@@ -1353,11 +1352,11 @@ ssize_t fuse_direct_io(struct fuse_io_priv *io, struct iov_iter *iter,
 		if (!io->async)
 			fuse_release_user_pages(req, !write);
 		if (req->out.h.error) {
-			if (!res)
-				res = req->out.h.error;
+			err = req->out.h.error;
 			break;
 		} else if (nres > nbytes) {
-			res = -EIO;
+			res = 0;
+			err = -EIO;
 			break;
 		}
 		count -= nres;
@@ -1381,7 +1380,7 @@ ssize_t fuse_direct_io(struct fuse_io_priv *io, struct iov_iter *iter,
 	if (res > 0)
 		*ppos = pos;
 
-	return res;
+	return res > 0 ? res : err;
 }
 EXPORT_SYMBOL_GPL(fuse_direct_io);