#include "smbd/smbd.h"
#include "smbd/globals.h"
#include "lib/util/tevent_unix.h"
+#include "lib/util/sys_rw.h"
#include <sys/eventfd.h>
#include <libaio.h>
+#include "smbprofile.h"
static int event_fd = -1;
static io_context_t io_ctx;
static void aio_linux_done(struct tevent_context *event_ctx,
struct tevent_fd *event,
- uint16 flags, void *private_data);
+ uint16_t flags, void *private_data);
/************************************************************************
Housekeeping. Cleanup if no activity for 30 seconds.
goto fail;
}
- if (io_queue_init(aio_pending_size, &io_ctx)) {
+ if (io_queue_init(lp_aio_max_threads(), &io_ctx)) {
goto fail;
}
DEBUG(10,("init_aio_linux: initialized with up to %d events\n",
- aio_pending_size));
+ (int)lp_aio_max_threads()));
return true;
struct aio_linux_state {
struct iocb event_iocb;
ssize_t ret;
- int err;
+ struct vfs_aio_state vfs_aio_state;
+ struct timespec start;
};
static struct tevent_req *aio_linux_pread_send(
piocb = &state->event_iocb;
+ PROFILE_TIMESTAMP(&state->start);
ret = io_submit(io_ctx, 1, &piocb);
if (ret < 0) {
tevent_req_error(req, -ret);
piocb = &state->event_iocb;
+ PROFILE_TIMESTAMP(&state->start);
ret = io_submit(io_ctx, 1, &piocb);
if (ret < 0) {
tevent_req_error(req, -ret);
piocb = &state->event_iocb;
+ PROFILE_TIMESTAMP(&state->start);
ret = io_submit(io_ctx, 1, &piocb);
if (ret < 0) {
tevent_req_error(req, -ret);
static void aio_linux_done(struct tevent_context *event_ctx,
struct tevent_fd *event,
- uint16 flags, void *private_data)
+ uint16_t flags, void *private_data)
{
uint64_t num_events = 0;
+ struct timespec end;
DEBUG(10, ("aio_linux_done called with flags=%d\n",
(int)flags));
+ PROFILE_TIMESTAMP(&end);
+
/* Read the number of events available. */
if (sys_read(event_fd, &num_events, sizeof(num_events)) !=
sizeof(num_events)) {
if (finished.res < 0) {
state->ret = -1;
- state->err = -finished.res;
+ state->vfs_aio_state.error = -finished.res;
} else {
state->ret = finished.res;
- state->err = 0;
}
+ state->vfs_aio_state.duration = nsec_time_diff(&end, &state->start);
tevent_req_done(req);
num_events -= 1;
}
}
-static ssize_t aio_linux_recv(struct tevent_req *req, int *err)
+static ssize_t aio_linux_recv(struct tevent_req *req,
+ struct vfs_aio_state *vfs_aio_state)
{
struct aio_linux_state *state = tevent_req_data(
req, struct aio_linux_state);
- if (tevent_req_is_unix_error(req, err)) {
+ if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
return -1;
}
- if (state->ret == -1) {
- *err = state->err;
- }
+ *vfs_aio_state = state->vfs_aio_state;
return state->ret;
}
-static int aio_linux_int_recv(struct tevent_req *req, int *err)
+static int aio_linux_int_recv(struct tevent_req *req,
+ struct vfs_aio_state *vfs_aio_state)
{
/*
* Use implicit conversion ssize_t->int
*/
- return aio_linux_recv(req, err);
-}
-
-static int aio_linux_connect(vfs_handle_struct *handle, const char *service,
- const char *user)
-{
- /*********************************************************************
- * How many io_events to initialize ?
- * 128 per process seems insane as a default until you realize that
- * (a) Throttling is done in SMB2 via the crediting algorithm.
- * (b) 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_linux", "aio num events", 128);
- return SMB_VFS_NEXT_CONNECT(handle, service, user);
+ return aio_linux_recv(req, vfs_aio_state);
}
static struct vfs_fn_pointers vfs_aio_linux_fns = {
- .connect_fn = aio_linux_connect,
.pread_send_fn = aio_linux_pread_send,
.pread_recv_fn = aio_linux_recv,
.pwrite_send_fn = aio_linux_pwrite_send,
.fsync_recv_fn = aio_linux_int_recv,
};
-NTSTATUS vfs_aio_linux_init(void)
+static_decl_vfs;
+NTSTATUS vfs_aio_linux_init(TALLOC_CTX *ctx)
{
return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
"aio_linux", &vfs_aio_linux_fns);