diff options
-rw-r--r-- | source3/modules/vfs_aio_pthread.c | 160 | ||||
-rw-r--r-- | source3/modules/vfs_default.c | 208 | ||||
-rw-r--r-- | source3/modules/wscript_build | 2 | ||||
-rw-r--r-- | source3/smbd/globals.h | 6 | ||||
-rwxr-xr-x | source3/wscript_build | 1 |
5 files changed, 146 insertions, 231 deletions
diff --git a/source3/modules/vfs_aio_pthread.c b/source3/modules/vfs_aio_pthread.c index 06ac8b8667..6edb12d95e 100644 --- a/source3/modules/vfs_aio_pthread.c +++ b/source3/modules/vfs_aio_pthread.c @@ -27,125 +27,10 @@ #include "smbd/smbd.h" #include "smbd/globals.h" #include "lib/pthreadpool/pthreadpool.h" -#include "lib/asys/asys.h" -#include "lib/util/tevent_unix.h" #ifdef HAVE_LINUX_FALLOC_H #include <linux/falloc.h> #endif -static struct asys_context *asys_ctx; -struct tevent_fd *asys_fde; - -struct aio_pthread_state { - struct tevent_req *req; - ssize_t ret; - int err; -}; - -static int aio_pthread_state_destructor(struct aio_pthread_state *s) -{ - asys_cancel(asys_ctx, s->req); - return 0; -} - -static struct tevent_req *aio_pthread_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 aio_pthread_state *state; - int ret; - - req = tevent_req_create(mem_ctx, &state, struct aio_pthread_state); - if (req == NULL) { - return NULL; - } - state->req = req; - - ret = asys_pread(asys_ctx, fsp->fh->fd, data, n, offset, req); - if (ret != 0) { - tevent_req_error(req, ret); - return tevent_req_post(req, ev); - } - talloc_set_destructor(state, aio_pthread_state_destructor); - - return req; -} - -static struct tevent_req *aio_pthread_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 aio_pthread_state *state; - int ret; - - req = tevent_req_create(mem_ctx, &state, struct aio_pthread_state); - if (req == NULL) { - return NULL; - } - state->req = req; - - ret = asys_pwrite(asys_ctx, fsp->fh->fd, data, n, offset, req); - if (ret != 0) { - tevent_req_error(req, ret); - return tevent_req_post(req, ev); - } - talloc_set_destructor(state, aio_pthread_state_destructor); - - return req; -} - -static void aio_pthread_finished(struct tevent_context *ev, - struct tevent_fd *fde, - uint16_t flags, void *p) -{ - struct tevent_req *req; - struct aio_pthread_state *state; - int res; - ssize_t ret; - int err; - void *private_data; - - if ((flags & TEVENT_FD_READ) == 0) { - return; - } - - res = asys_result(asys_ctx, &ret, &err, &private_data); - if (res == ECANCELED) { - return; - } - - if (res != 0) { - DEBUG(1, ("asys_result returned %s\n", strerror(res))); - return; - } - - req = talloc_get_type_abort(private_data, struct tevent_req); - state = tevent_req_data(req, struct aio_pthread_state); - - talloc_set_destructor(state, NULL); - - state->ret = ret; - state->err = err; - tevent_req_done(req); -} - -static ssize_t aio_pthread_recv(struct tevent_req *req, int *err) -{ - struct aio_pthread_state *state = tevent_req_data( - req, struct aio_pthread_state); - - if (tevent_req_is_unix_error(req, err)) { - return -1; - } - *err = state->err; - return state->ret; -} - - #if defined(HAVE_OPENAT) && defined(USE_LINUX_THREAD_CREDENTIALS) /************************************************************************ @@ -597,55 +482,10 @@ static int aio_pthread_open_fn(vfs_handle_struct *handle, } #endif -static int aio_pthread_connect(vfs_handle_struct *handle, const char *service, - const char *user) -{ - /********************************************************************* - * How many threads to initialize ? - * 100 per process seems insane as a default until you realize that - * (a) Threads terminate after 1 second when idle. - * (b) Throttling is done in SMB2 via the crediting algorithm. - * (c) SMB1 clients are limited to max_mux (50) outstanding - * requests and Windows clients don't use this anyway. - * Essentially we want this to be unlimited unless smb.conf - * says different. - *********************************************************************/ - aio_pending_size = lp_parm_int( - SNUM(handle->conn), "aio_pthread", "aio num threads", 100); - - if (asys_ctx == NULL) { - int ret; - - ret = asys_context_init(&asys_ctx, aio_pending_size); - if (ret != 0) { - DEBUG(1, ("asys_context_init failed: %s\n", - strerror(ret))); - return -1; - } - - asys_fde = tevent_add_fd(handle->conn->sconn->ev_ctx, NULL, - asys_signalfd(asys_ctx), - TEVENT_FD_READ, aio_pthread_finished, - NULL); - if (asys_fde == NULL) { - DEBUG(1, ("tevent_add_fd failed\n")); - asys_context_destroy(asys_ctx); - asys_ctx = NULL; - return -1; - } - } - return SMB_VFS_NEXT_CONNECT(handle, service, user); -} - static struct vfs_fn_pointers vfs_aio_pthread_fns = { - .connect_fn = aio_pthread_connect, #if defined(HAVE_OPENAT) && defined(USE_LINUX_THREAD_CREDENTIALS) .open_fn = aio_pthread_open_fn, #endif - .pread_send_fn = aio_pthread_pread_send, - .pread_recv_fn = aio_pthread_recv, - .pwrite_send_fn = aio_pthread_pwrite_send, - .pwrite_recv_fn = aio_pthread_recv, }; NTSTATUS vfs_aio_pthread_init(void); diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c index c9d32389c7..c79eed0b97 100644 --- a/source3/modules/vfs_default.c +++ b/source3/modules/vfs_default.c @@ -30,6 +30,7 @@ #include "source3/include/msdfs.h" #include "librpc/gen_ndr/ndr_dfsblobs.h" #include "lib/util/tevent_unix.h" +#include "lib/asys/asys.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_VFS @@ -580,49 +581,6 @@ 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; @@ -672,49 +630,159 @@ static ssize_t vfswrap_pwrite(vfs_handle_struct *handle, files_struct *fsp, cons return result; } -struct vfswrap_pwrite_state { - ssize_t retval; +static void vfswrap_asys_finished(struct tevent_context *ev, + struct tevent_fd *fde, + uint16_t flags, void *p); + +static bool vfswrap_init_asys_ctx(struct smbXsrv_connection *conn) +{ + int ret; + + if (conn->asys_ctx != NULL) { + return true; + } + ret = asys_context_init(&conn->asys_ctx, aio_pending_size); + if (ret != 0) { + DEBUG(1, ("asys_context_init failed: %s\n", strerror(ret))); + return false; + } + conn->asys_fde = tevent_add_fd(conn->ev_ctx, conn, + asys_signalfd(conn->asys_ctx), + TEVENT_FD_READ, + vfswrap_asys_finished, + conn->asys_ctx); + if (conn->asys_fde == NULL) { + DEBUG(1, ("tevent_add_fd failed\n")); + asys_context_destroy(conn->asys_ctx); + conn->asys_ctx = NULL; + return false; + } + return true; +} + +struct vfswrap_asys_state { + struct asys_context *asys_ctx; + struct tevent_req *req; + ssize_t ret; + int err; }; -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) +static int vfswrap_asys_state_destructor(struct vfswrap_asys_state *s) +{ + asys_cancel(s->asys_ctx, s->req); + return 0; +} + +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_pwrite_state *state; - int saved_errno; + struct vfswrap_asys_state *state; + int ret; - req = tevent_req_create(mem_ctx, &state, - struct vfswrap_pwrite_state); + req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state); if (req == NULL) { return NULL; } + if (!vfswrap_init_asys_ctx(handle->conn->sconn->conn)) { + tevent_req_oom(req); + return tevent_req_post(req, ev); + } + state->asys_ctx = handle->conn->sconn->conn->asys_ctx; + state->req = req; - START_PROFILE_BYTES(syscall_pwrite, n); - state->retval = sys_pwrite(fsp->fh->fd, data, n, offset); - saved_errno = errno; - END_PROFILE(syscall_pwrite); + ret = asys_pread(state->asys_ctx, fsp->fh->fd, data, n, offset, req); + if (ret != 0) { + tevent_req_error(req, ret); + return tevent_req_post(req, ev); + } + talloc_set_destructor(state, vfswrap_asys_state_destructor); - if (state->retval == -1) { - tevent_req_error(req, saved_errno); - } else { - tevent_req_done(req); + return req; +} + +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_asys_state *state; + int ret; + + req = tevent_req_create(mem_ctx, &state, struct vfswrap_asys_state); + if (req == NULL) { + return NULL; } - return tevent_req_post(req, ev); + if (!vfswrap_init_asys_ctx(handle->conn->sconn->conn)) { + tevent_req_oom(req); + return tevent_req_post(req, ev); + } + state->asys_ctx = handle->conn->sconn->conn->asys_ctx; + state->req = req; + + ret = asys_pwrite(state->asys_ctx, fsp->fh->fd, data, n, offset, req); + if (ret != 0) { + tevent_req_error(req, ret); + return tevent_req_post(req, ev); + } + talloc_set_destructor(state, vfswrap_asys_state_destructor); + + return req; } -static ssize_t vfswrap_pwrite_recv(struct tevent_req *req, int *perrno) +static void vfswrap_asys_finished(struct tevent_context *ev, + struct tevent_fd *fde, + uint16_t flags, void *p) { - struct vfswrap_pwrite_state *state = tevent_req_data( - req, struct vfswrap_pwrite_state); + struct asys_context *asys_ctx = (struct asys_context *)p; + struct tevent_req *req; + struct vfswrap_asys_state *state; + int res; + ssize_t ret; int err; + void *private_data; + + if ((flags & TEVENT_FD_READ) == 0) { + return; + } + + res = asys_result(asys_ctx, &ret, &err, &private_data); + if (res == ECANCELED) { + return; + } + + if (res != 0) { + DEBUG(1, ("asys_result returned %s\n", strerror(res))); + return; + } + + req = talloc_get_type_abort(private_data, struct tevent_req); + state = tevent_req_data(req, struct vfswrap_asys_state); + + talloc_set_destructor(state, NULL); + + state->ret = ret; + state->err = err; + tevent_req_done(req); +} + +static ssize_t vfswrap_asys_ssize_t_recv(struct tevent_req *req, int *err) +{ + struct vfswrap_asys_state *state = tevent_req_data( + req, struct vfswrap_asys_state); - if (tevent_req_is_unix_error(req, &err)) { - *perrno = err; + if (tevent_req_is_unix_error(req, err)) { return -1; } - return state->retval; + *err = state->err; + return state->ret; } static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence) @@ -2236,11 +2304,11 @@ static struct vfs_fn_pointers vfs_default_fns = { .read_fn = vfswrap_read, .pread_fn = vfswrap_pread, .pread_send_fn = vfswrap_pread_send, - .pread_recv_fn = vfswrap_pread_recv, + .pread_recv_fn = vfswrap_asys_ssize_t_recv, .write_fn = vfswrap_write, .pwrite_fn = vfswrap_pwrite, .pwrite_send_fn = vfswrap_pwrite_send, - .pwrite_recv_fn = vfswrap_pwrite_recv, + .pwrite_recv_fn = vfswrap_asys_ssize_t_recv, .lseek_fn = vfswrap_lseek, .sendfile_fn = vfswrap_sendfile, .recvfile_fn = vfswrap_recvfile, diff --git a/source3/modules/wscript_build b/source3/modules/wscript_build index 2f5088ad24..aaefd98727 100644 --- a/source3/modules/wscript_build +++ b/source3/modules/wscript_build @@ -358,7 +358,7 @@ bld.SAMBA3_MODULE('vfs_aio_fork', bld.SAMBA3_MODULE('vfs_aio_pthread', subsystem='vfs', source=VFS_AIO_PTHREAD_SRC, - deps='samba-util tevent LIBASYS', + deps='samba-util tevent', init_function='', internal_module=bld.SAMBA3_IS_STATIC_MODULE('vfs_aio_pthread'), enabled=bld.SAMBA3_IS_ENABLED_MODULE('vfs_aio_pthread'), diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index 80612eb716..c400181130 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -347,6 +347,12 @@ struct smbXsrv_connection { struct msg_state *msg_state; + /* + * Link into libasys for asynchronous operations + */ + struct asys_context *asys_ctx; + struct tevent_fd *asys_fde; + uint64_t smbd_idle_profstamp; /* diff --git a/source3/wscript_build b/source3/wscript_build index 672129dbcc..3b3bdeac9f 100755 --- a/source3/wscript_build +++ b/source3/wscript_build @@ -935,6 +935,7 @@ bld.SAMBA3_LIBRARY('smbd_base', LIBAFS_SETTOKEN RPC_SERVER NDR_SMBXSRV + LIBASYS ccan-hash ''', private_library=True, |