s3-vfs: async pread
authorVolker Lendecke <vl@samba.org>
Tue, 26 Jun 2012 12:30:59 +0000 (14:30 +0200)
committerJeremy Allison <jra@samba.org>
Wed, 18 Jul 2012 22:11:56 +0000 (15:11 -0700)
Signed-off-by: Jeremy Allison <jra@samba.org>
source3/include/vfs.h
source3/include/vfs_macros.h
source3/modules/vfs_default.c
source3/smbd/vfs.c

index 2a466de0b4572791665885b93b8e13a7eac87ccc..5355d7a83699f640ec6f04c58d5f0c7ef55e5fb6 100644 (file)
@@ -515,6 +515,13 @@ struct vfs_fn_pointers {
        int (*close_fn)(struct vfs_handle_struct *handle, struct files_struct *fsp);
        ssize_t (*read_fn)(struct vfs_handle_struct *handle, struct files_struct *fsp, void *data, size_t n);
        ssize_t (*pread_fn)(struct vfs_handle_struct *handle, struct files_struct *fsp, void *data, size_t n, off_t offset);
+       struct tevent_req *(*pread_send_fn)(struct vfs_handle_struct *handle,
+                                           TALLOC_CTX *mem_ctx,
+                                           struct tevent_context *ev,
+                                           struct files_struct *fsp,
+                                           void *data,
+                                           size_t n, off_t offset);
+       ssize_t (*pread_recv_fn)(struct tevent_req *req, int *err);
        ssize_t (*write_fn)(struct vfs_handle_struct *handle, struct files_struct *fsp, const void *data, size_t n);
        ssize_t (*pwrite_fn)(struct vfs_handle_struct *handle, struct files_struct *fsp, const void *data, size_t n, off_t offset);
        struct tevent_req *(*pwrite_send_fn)(struct vfs_handle_struct *handle,
@@ -885,6 +892,14 @@ ssize_t smb_vfs_call_read(struct vfs_handle_struct *handle,
 ssize_t smb_vfs_call_pread(struct vfs_handle_struct *handle,
                           struct files_struct *fsp, void *data, size_t n,
                           off_t offset);
+struct tevent_req *smb_vfs_call_pread_send(struct vfs_handle_struct *handle,
+                                          TALLOC_CTX *mem_ctx,
+                                          struct tevent_context *ev,
+                                          struct files_struct *fsp,
+                                          void *data,
+                                          size_t n, off_t offset);
+ssize_t SMB_VFS_PREAD_RECV(struct tevent_req *req, int *perrno);
+
 ssize_t smb_vfs_call_write(struct vfs_handle_struct *handle,
                           struct files_struct *fsp, const void *data,
                           size_t n);
index 24add0b92695a69a970ddc4fcb12da3296e48ca4..80b375e6e0f74f8a56d0423062a812c210e1282e 100644 (file)
 #define SMB_VFS_NEXT_PREAD(handle, fsp, data, n, off) \
        smb_vfs_call_pread((handle)->next, (fsp), (data), (n), (off))
 
+#define SMB_VFS_PREAD_SEND(mem_ctx, ev, fsp, data, n, off) \
+       smb_vfs_call_pread_send((fsp)->conn->vfs_handles, (mem_ctx), (ev), \
+                               (fsp), (data), (n), (off))
+#define SMB_VFS_NEXT_PREAD_SEND(mem_ctx, ev, handle, fsp, data, n, off)        \
+       smb_vfs_call_pread_send((handle)->next, (mem_ctx), (ev), (fsp), \
+                               (data), (n), (off))
+
 #define SMB_VFS_WRITE(fsp, data, n) \
        smb_vfs_call_write((fsp)->conn->vfs_handles, (fsp), (data), (n))
 #define SMB_VFS_NEXT_WRITE(handle, fsp, data, n) \
index 2235ef98a9fc8d6fddcb96d1ee1d91ab367f68ac..aa38a50b8098bb5e6dd7bd90a8204ae32effda76 100644 (file)
@@ -580,6 +580,49 @@ static ssize_t vfswrap_pread(vfs_handle_struct *handle, files_struct *fsp, void
        return result;
 }
 
+struct vfswrap_pread_state {
+       ssize_t ret;
+};
+
+static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
+                                            TALLOC_CTX *mem_ctx,
+                                            struct tevent_context *ev,
+                                            struct files_struct *fsp,
+                                            void *data,
+                                            size_t n, off_t offset)
+{
+       struct tevent_req *req;
+       struct vfswrap_pread_state *state;
+       int saved_errno;
+
+       req = tevent_req_create(req, &state, struct vfswrap_pread_state);
+       if (req == NULL) {
+               return NULL;
+       }
+       START_PROFILE_BYTES(syscall_pread, n);
+       state->ret = sys_pread(fsp->fh->fd, data, n, offset);
+       saved_errno = errno;
+       END_PROFILE(syscall_pread);
+
+       if (state->ret == -1) {
+               tevent_req_error(req, saved_errno);
+               return tevent_req_post(req, ev);
+       }
+       tevent_req_done(req);
+       return tevent_req_post(req, ev);
+}
+
+static ssize_t vfswrap_pread_recv(struct tevent_req *req, int *err)
+{
+       struct vfswrap_pread_state *state = tevent_req_data(
+               req, struct vfswrap_pread_state);
+
+       if (tevent_req_is_unix_error(req, err)) {
+               return -1;
+       }
+       return state->ret;
+}
+
 static ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, const void *data, size_t n)
 {
        ssize_t result;
@@ -2255,6 +2298,8 @@ static struct vfs_fn_pointers vfs_default_fns = {
        .close_fn = vfswrap_close,
        .read_fn = vfswrap_read,
        .pread_fn = vfswrap_pread,
+       .pread_send_fn = vfswrap_pread_send,
+       .pread_recv_fn = vfswrap_pread_recv,
        .write_fn = vfswrap_write,
        .pwrite_fn = vfswrap_pwrite,
        .pwrite_send_fn = vfswrap_pwrite_send,
index 9b666e0bf628d18a08d68ffdeec04900d4567f8e..0414332073fd2641d6c546d66631f66f26ca4c5a 100644 (file)
@@ -1541,6 +1541,70 @@ ssize_t smb_vfs_call_pread(struct vfs_handle_struct *handle,
        return handle->fns->pread_fn(handle, fsp, data, n, offset);
 }
 
+struct smb_vfs_call_pread_state {
+       ssize_t (*recv_fn)(struct tevent_req *req, int *err);
+       ssize_t retval;
+};
+
+static void smb_vfs_call_pread_done(struct tevent_req *subreq);
+
+struct tevent_req *smb_vfs_call_pread_send(struct vfs_handle_struct *handle,
+                                          TALLOC_CTX *mem_ctx,
+                                          struct tevent_context *ev,
+                                          struct files_struct *fsp,
+                                          void *data,
+                                          size_t n, off_t offset)
+{
+       struct tevent_req *req, *subreq;
+       struct smb_vfs_call_pread_state *state;
+
+       req = tevent_req_create(mem_ctx, &state,
+                               struct smb_vfs_call_pread_state);
+       if (req == NULL) {
+               return NULL;
+       }
+       VFS_FIND(pread_send);
+       state->recv_fn = handle->fns->pread_recv_fn;
+
+       subreq = handle->fns->pread_send_fn(handle, state, ev, fsp, data, n,
+                                           offset);
+       if (tevent_req_nomem(subreq, req)) {
+               return tevent_req_post(req, ev);
+       }
+       tevent_req_set_callback(subreq, smb_vfs_call_pread_done, req);
+       return req;
+}
+
+static void smb_vfs_call_pread_done(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(
+               subreq, struct tevent_req);
+       struct smb_vfs_call_pread_state *state = tevent_req_data(
+               req, struct smb_vfs_call_pread_state);
+       int err;
+
+       state->retval = state->recv_fn(subreq, &err);
+       TALLOC_FREE(subreq);
+       if (state->retval == -1) {
+               tevent_req_error(req, err);
+               return;
+       }
+       tevent_req_done(req);
+}
+
+ssize_t SMB_VFS_PREAD_RECV(struct tevent_req *req, int *perrno)
+{
+       struct smb_vfs_call_pread_state *state = tevent_req_data(
+               req, struct smb_vfs_call_pread_state);
+       int err;
+
+       if (tevent_req_is_unix_error(req, &err)) {
+               *perrno = err;
+               return -1;
+       }
+       return state->retval;
+}
+
 ssize_t smb_vfs_call_write(struct vfs_handle_struct *handle,
                           struct files_struct *fsp, const void *data,
                           size_t n)