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) {
        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;
 
        *nbytesp = nbytes;
 
-       return 0;
+       return ret;
 }
 
 static inline int fuse_iter_npages(const struct iov_iter *ii_p)
        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));
                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);
                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;
        if (res > 0)
                *ppos = pos;
 
-       return res;
+       return res > 0 ? res : err;
 }
 EXPORT_SYMBOL_GPL(fuse_direct_io);