vfs_io_uring: retry after a short read in vfs_io_uring_pread_completion()
authorStefan Metzmacher <metze@samba.org>
Fri, 8 May 2020 11:30:17 +0000 (13:30 +0200)
committerJeremy Allison <jra@samba.org>
Tue, 12 May 2020 19:53:45 +0000 (19:53 +0000)
We need to be prepared for short reads from the kernel depending on
the state of the page cache. Windows and Mac clients don't
expect short reads for files, so we need to retry ourself.

For the future we may be able to play with some io_uring flags
in order to avoid the retries in userspace, but for now we just fix
the data corruption bug...

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14361

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
source3/modules/vfs_io_uring.c

index 0b1583f962a76b52d36ba0f457b0f0b96b5ec5c2..f16c9ae56d335a3d88e67b05fc43ad425fb54076 100644 (file)
@@ -489,6 +489,14 @@ static void vfs_io_uring_pread_completion(struct vfs_io_uring_request *cur,
                return;
        }
 
+       if (cur->cqe.res == 0) {
+               /*
+                * We reached EOF, we're done
+                */
+               tevent_req_done(cur->req);
+               return;
+       }
+
        ok = iov_advance(&iov, &num_iov, cur->cqe.res);
        if (!ok) {
                /* This is not expected! */
@@ -499,8 +507,20 @@ static void vfs_io_uring_pread_completion(struct vfs_io_uring_request *cur,
                return;
        }
 
-       state->nread = state->ur.cqe.res;
-       tevent_req_done(cur->req);
+       /* sys_valid_io_range() already checked the boundaries */
+       state->nread += state->ur.cqe.res;
+       if (num_iov == 0) {
+               /* We're done */
+               tevent_req_done(cur->req);
+               return;
+       }
+
+       /*
+        * sys_valid_io_range() already checked the boundaries
+        * now try to get the rest.
+        */
+       state->offset += state->ur.cqe.res;
+       vfs_io_uring_pread_submit(state);
 }
 
 static ssize_t vfs_io_uring_pread_recv(struct tevent_req *req,