s3-vfs: async pwrite
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 20:49:21 +0000 (13:49 -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 6508707f75efbc20a17f682cde7159cc861e3d28..2a466de0b4572791665885b93b8e13a7eac87ccc 100644 (file)
@@ -517,6 +517,13 @@ struct vfs_fn_pointers {
        ssize_t (*pread_fn)(struct vfs_handle_struct *handle, struct files_struct *fsp, void *data, size_t n, off_t offset);
        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,
+                                            TALLOC_CTX *mem_ctx,
+                                            struct tevent_context *ev,
+                                            struct files_struct *fsp,
+                                            const void *data,
+                                            size_t n, off_t offset);
+       ssize_t (*pwrite_recv_fn)(struct tevent_req *req, int *err);
        off_t (*lseek_fn)(struct vfs_handle_struct *handle, struct files_struct *fsp, off_t offset, int whence);
        ssize_t (*sendfile_fn)(struct vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *header, off_t offset, size_t count);
        ssize_t (*recvfile_fn)(struct vfs_handle_struct *handle, int fromfd, files_struct *tofsp, off_t offset, size_t count);
@@ -884,6 +891,14 @@ ssize_t smb_vfs_call_write(struct vfs_handle_struct *handle,
 ssize_t smb_vfs_call_pwrite(struct vfs_handle_struct *handle,
                            struct files_struct *fsp, const void *data,
                            size_t n, off_t offset);
+struct tevent_req *smb_vfs_call_pwrite_send(struct vfs_handle_struct *handle,
+                                           TALLOC_CTX *mem_ctx,
+                                           struct tevent_context *ev,
+                                           struct files_struct *fsp,
+                                           const void *data,
+                                           size_t n, off_t offset);
+ssize_t SMB_VFS_PWRITE_RECV(struct tevent_req *req, int *perrno);
+
 off_t smb_vfs_call_lseek(struct vfs_handle_struct *handle,
                             struct files_struct *fsp, off_t offset,
                             int whence);
index 3c2256bfeeadcc39008f951c62bfce74bfd3131a..24add0b92695a69a970ddc4fcb12da3296e48ca4 100644 (file)
 #define SMB_VFS_NEXT_PWRITE(handle, fsp, data, n, off) \
        smb_vfs_call_pwrite((handle)->next, (fsp), (data), (n), (off))
 
+#define SMB_VFS_PWRITE_SEND(mem_ctx, ev, fsp, data, n, off) \
+       smb_vfs_call_pwrite_send((fsp)->conn->vfs_handles, (mem_ctx), (ev), \
+                               (fsp), (data), (n), (off))
+#define SMB_VFS_NEXT_PWRITE_SEND(mem_ctx, ev, handle, fsp, data, n, off) \
+       smb_vfs_call_pwrite_send((handle)->next, (mem_ctx), (ev), (fsp), \
+                               (data), (n), (off))
+
 #define SMB_VFS_LSEEK(fsp, offset, whence) \
        smb_vfs_call_lseek((fsp)->conn->vfs_handles, (fsp), (offset), (whence))
 #define SMB_VFS_NEXT_LSEEK(handle, fsp, offset, whence) \
index f8c5b75977e0ac31e263cf3d137e418ae6803096..2235ef98a9fc8d6fddcb96d1ee1d91ab367f68ac 100644 (file)
@@ -29,6 +29,7 @@
 #include "passdb/lookup_sid.h"
 #include "source3/include/msdfs.h"
 #include "librpc/gen_ndr/ndr_dfsblobs.h"
+#include "lib/util/tevent_unix.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_VFS
@@ -628,6 +629,51 @@ static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, cons
        return result;
 }
 
+struct vfswrap_pwrite_state {
+       ssize_t retval;
+};
+
+static struct tevent_req *vfswrap_pwrite_send(
+       struct vfs_handle_struct *handle,
+       TALLOC_CTX *mem_ctx, struct tevent_context *ev,
+       struct files_struct *fsp, const void *data, size_t n, off_t offset)
+{
+       struct tevent_req *req;
+       struct vfswrap_pwrite_state *state;
+       int saved_errno;
+
+       req = tevent_req_create(mem_ctx, &state,
+                               struct vfswrap_pwrite_state);
+       if (req == NULL) {
+               return NULL;
+       }
+
+       START_PROFILE_BYTES(syscall_pwrite, n);
+       state->retval = sys_pwrite(fsp->fh->fd, data, n, offset);
+       saved_errno = errno;
+       END_PROFILE(syscall_pwrite);
+
+       if (state->retval == -1) {
+               tevent_req_error(req, saved_errno);
+       } else {
+               tevent_req_done(req);
+       }
+       return tevent_req_post(req, ev);
+}
+
+static ssize_t vfswrap_pwrite_recv(struct tevent_req *req, int *perrno)
+{
+       struct vfswrap_pwrite_state *state = tevent_req_data(
+               req, struct vfswrap_pwrite_state);
+       int err;
+
+       if (tevent_req_is_unix_error(req, &err)) {
+               *perrno = err;
+               return -1;
+       }
+       return state->retval;
+}
+
 static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
 {
        off_t result = 0;
@@ -2211,6 +2257,8 @@ static struct vfs_fn_pointers vfs_default_fns = {
        .pread_fn = vfswrap_pread,
        .write_fn = vfswrap_write,
        .pwrite_fn = vfswrap_pwrite,
+       .pwrite_send_fn = vfswrap_pwrite_send,
+       .pwrite_recv_fn = vfswrap_pwrite_recv,
        .lseek_fn = vfswrap_lseek,
        .sendfile_fn = vfswrap_sendfile,
        .recvfile_fn = vfswrap_recvfile,
index 32e3472efe8fd8eb00edc730072def0961377e41..9b666e0bf628d18a08d68ffdeec04900d4567f8e 100644 (file)
@@ -30,6 +30,7 @@
 #include "memcache.h"
 #include "transfer_file.h"
 #include "ntioctl.h"
+#include "lib/util/tevent_unix.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_VFS
@@ -1556,6 +1557,70 @@ ssize_t smb_vfs_call_pwrite(struct vfs_handle_struct *handle,
        return handle->fns->pwrite_fn(handle, fsp, data, n, offset);
 }
 
+struct smb_vfs_call_pwrite_state {
+       ssize_t (*recv_fn)(struct tevent_req *req, int *err);
+       ssize_t retval;
+};
+
+static void smb_vfs_call_pwrite_done(struct tevent_req *subreq);
+
+struct tevent_req *smb_vfs_call_pwrite_send(struct vfs_handle_struct *handle,
+                                           TALLOC_CTX *mem_ctx,
+                                           struct tevent_context *ev,
+                                           struct files_struct *fsp,
+                                           const void *data,
+                                           size_t n, off_t offset)
+{
+       struct tevent_req *req, *subreq;
+       struct smb_vfs_call_pwrite_state *state;
+
+       req = tevent_req_create(mem_ctx, &state,
+                               struct smb_vfs_call_pwrite_state);
+       if (req == NULL) {
+               return NULL;
+       }
+       VFS_FIND(pwrite_send);
+       state->recv_fn = handle->fns->pwrite_recv_fn;
+
+       subreq = handle->fns->pwrite_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_pwrite_done, req);
+       return req;
+}
+
+static void smb_vfs_call_pwrite_done(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(
+               subreq, struct tevent_req);
+       struct smb_vfs_call_pwrite_state *state = tevent_req_data(
+               req, struct smb_vfs_call_pwrite_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_PWRITE_RECV(struct tevent_req *req, int *perrno)
+{
+       struct smb_vfs_call_pwrite_state *state = tevent_req_data(
+               req, struct smb_vfs_call_pwrite_state);
+       int err;
+
+       if (tevent_req_is_unix_error(req, &err)) {
+               *perrno = err;
+               return -1;
+       }
+       return state->retval;
+}
+
 off_t smb_vfs_call_lseek(struct vfs_handle_struct *handle,
                             struct files_struct *fsp, off_t offset,
                             int whence)