summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/modules/vfs_aio_fork.c113
1 files changed, 112 insertions, 1 deletions
diff --git a/source3/modules/vfs_aio_fork.c b/source3/modules/vfs_aio_fork.c
index 210fde1b31..c8a1fdc0f3 100644
--- a/source3/modules/vfs_aio_fork.c
+++ b/source3/modules/vfs_aio_fork.c
@@ -81,7 +81,8 @@ fail:
enum cmd_type {
READ_CMD,
- WRITE_CMD
+ WRITE_CMD,
+ FSYNC_CMD
};
static const char *cmd_type_str(enum cmd_type cmd)
@@ -95,6 +96,9 @@ static const char *cmd_type_str(enum cmd_type cmd)
case WRITE_CMD:
result = "WRITE";
break;
+ case FSYNC_CMD:
+ result = "FSYNC";
+ break;
default:
result = "<UNKNOWN>";
break;
@@ -388,6 +392,9 @@ static void aio_child_loop(int sockfd, struct mmap_area *map)
fd, (void *)map->ptr, cmd_struct.n,
cmd_struct.offset);
break;
+ case FSYNC_CMD:
+ ret_struct.size = fsync(fd);
+ break;
default:
ret_struct.size = -1;
errno = EINVAL;
@@ -782,6 +789,108 @@ static ssize_t aio_fork_pwrite_recv(struct tevent_req *req, int *err)
return state->ret;
}
+struct aio_fork_fsync_state {
+ struct aio_child *child;
+ ssize_t ret;
+ int err;
+};
+
+static void aio_fork_fsync_done(struct tevent_req *subreq);
+
+static struct tevent_req *aio_fork_fsync_send(
+ struct vfs_handle_struct *handle, TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev, struct files_struct *fsp)
+{
+ struct tevent_req *req, *subreq;
+ struct aio_fork_fsync_state *state;
+ struct rw_cmd cmd;
+ ssize_t written;
+ int err;
+
+ req = tevent_req_create(mem_ctx, &state, struct aio_fork_fsync_state);
+ if (req == NULL) {
+ return NULL;
+ }
+
+ err = get_idle_child(handle, &state->child);
+ if (err != 0) {
+ tevent_req_error(req, err);
+ return tevent_req_post(req, ev);
+ }
+
+ ZERO_STRUCT(cmd);
+ cmd.cmd = FSYNC_CMD;
+
+ DEBUG(10, ("sending fd %d to child %d\n", fsp->fh->fd,
+ (int)state->child->pid));
+
+ /*
+ * Not making this async. We're writing into an empty unix
+ * domain socket. This should never block.
+ */
+ written = write_fd(state->child->sockfd, &cmd, sizeof(cmd),
+ fsp->fh->fd);
+ if (written == -1) {
+ err = errno;
+
+ TALLOC_FREE(state->child);
+
+ DEBUG(10, ("write_fd failed: %s\n", strerror(err)));
+ tevent_req_error(req, err);
+ return tevent_req_post(req, ev);
+ }
+
+ subreq = read_packet_send(state, ev, state->child->sockfd,
+ sizeof(struct rw_ret), NULL, NULL);
+ if (tevent_req_nomem(subreq, req)) {
+ TALLOC_FREE(state->child); /* we sent sth down */
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, aio_fork_fsync_done, req);
+ return req;
+}
+
+static void aio_fork_fsync_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct aio_fork_fsync_state *state = tevent_req_data(
+ req, struct aio_fork_fsync_state);
+ ssize_t nread;
+ uint8_t *buf;
+ int err;
+ struct rw_ret *retbuf;
+
+ nread = read_packet_recv(subreq, talloc_tos(), &buf, &err);
+ TALLOC_FREE(subreq);
+ if (nread == -1) {
+ TALLOC_FREE(state->child);
+ tevent_req_error(req, err);
+ return;
+ }
+
+ state->child->busy = false;
+
+ retbuf = (struct rw_ret *)buf;
+ state->ret = retbuf->size;
+ state->err = retbuf->ret_errno;
+ tevent_req_done(req);
+}
+
+static int aio_fork_fsync_recv(struct tevent_req *req, int *err)
+{
+ struct aio_fork_fsync_state *state = tevent_req_data(
+ req, struct aio_fork_fsync_state);
+
+ if (tevent_req_is_unix_error(req, err)) {
+ return -1;
+ }
+ if (state->ret == -1) {
+ *err = state->err;
+ }
+ return state->ret;
+}
+
static int aio_fork_connect(vfs_handle_struct *handle, const char *service,
const char *user)
{
@@ -805,6 +914,8 @@ static struct vfs_fn_pointers vfs_aio_fork_fns = {
.pread_recv_fn = aio_fork_pread_recv,
.pwrite_send_fn = aio_fork_pwrite_send,
.pwrite_recv_fn = aio_fork_pwrite_recv,
+ .fsync_send_fn = aio_fork_fsync_send,
+ .fsync_recv_fn = aio_fork_fsync_recv,
};
NTSTATUS vfs_aio_fork_init(void);