s3: VFS: fruit. Implement fsync_send()/fsync_recv().
authorJeremy Allison <jra@samba.org>
Tue, 20 Sep 2022 20:25:22 +0000 (13:25 -0700)
committerJeremy Allison <jra@samba.org>
Thu, 6 Oct 2022 22:03:35 +0000 (22:03 +0000)
For type == ADOUBLE_META, fio->fake_fd is true so
writes are already synchronous, just call tevent_req_post().

For type == ADOUBLE_RSRC we know we are configured
with FRUIT_RSRC_ADFILE (because fruit_must_handle_aio_stream()
returned true), so we can just call SMB_VFS_NEXT_FSYNC_SEND()
after replacing fsp with fio->ad_fsp.

Remove knownfail.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15182

Signed-off-by: Jeremy Allison <jra@samba.org>
Reviewed-by: Ralph Böhme <slow@samba.org>
selftest/knownfail.d/fruit_fsync [deleted file]
source3/modules/vfs_fruit.c

diff --git a/selftest/knownfail.d/fruit_fsync b/selftest/knownfail.d/fruit_fsync
deleted file mode 100644 (file)
index 15745bd..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-^samba3.vfs.fruit\ metadata_stream.fsync_resource_fork.nt4_dc
-^samba3.vfs.fruit\ metadata_netatalk.fsync_resource_fork.nt4_dc
-^samba3.vfs.fruit\ fruit_delete_empty_adfiles.fsync_resource_fork.nt4_dc
index 13033096dc92161fd6be5f615e086c03971325bb..3b657f92b3df6fc46211fcbaaeeca817cc7db684 100644 (file)
@@ -3071,6 +3071,106 @@ static ssize_t fruit_pwrite_recv(struct tevent_req *req,
        return state->nwritten;
 }
 
+struct fruit_fsync_state {
+       int ret;
+       struct vfs_aio_state vfs_aio_state;
+};
+
+static void fruit_fsync_done(struct tevent_req *subreq);
+
+static struct tevent_req *fruit_fsync_send(
+       struct vfs_handle_struct *handle,
+       TALLOC_CTX *mem_ctx,
+       struct tevent_context *ev,
+       struct files_struct *fsp)
+{
+       struct tevent_req *req = NULL;
+       struct tevent_req *subreq = NULL;
+       struct fruit_fsync_state *state = NULL;
+       struct fio *fio = fruit_get_complete_fio(handle, fsp);
+
+       req = tevent_req_create(mem_ctx, &state,
+                               struct fruit_fsync_state);
+       if (req == NULL) {
+               return NULL;
+       }
+
+       if (fruit_must_handle_aio_stream(fio)) {
+               struct adouble *ad = NULL;
+
+               if (fio->type == ADOUBLE_META) {
+                       /*
+                        * We must never pass a fake_fd
+                        * to lower level fsync calls.
+                        * Everything is already done
+                        * synchronously, so just return
+                        * true.
+                        */
+                       SMB_ASSERT(fio->fake_fd);
+                       tevent_req_done(req);
+                       return tevent_req_post(req, ev);
+               }
+
+               /*
+                * We know the following must be true,
+                * as it's the condition for fruit_must_handle_aio_stream()
+                * to return true if fio->type == ADOUBLE_RSRC.
+                */
+               SMB_ASSERT(fio->config->rsrc == FRUIT_RSRC_ADFILE);
+               if (fio->ad_fsp == NULL) {
+                       tevent_req_error(req, EBADF);
+                       return tevent_req_post(req, ev);
+               }
+               ad = ad_fget(talloc_tos(), handle, fio->ad_fsp, ADOUBLE_RSRC);
+               if (ad == NULL) {
+                       tevent_req_error(req, ENOMEM);
+                       return tevent_req_post(req, ev);
+               }
+               fsp = fio->ad_fsp;
+       }
+
+       subreq = SMB_VFS_NEXT_FSYNC_SEND(state, ev, handle, fsp);
+       if (tevent_req_nomem(req, subreq)) {
+               return tevent_req_post(req, ev);
+       }
+       tevent_req_set_callback(subreq, fruit_fsync_done, req);
+       return req;
+}
+
+static void fruit_fsync_done(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(
+               subreq, struct tevent_req);
+       struct fruit_fsync_state *state = tevent_req_data(
+               req, struct fruit_fsync_state);
+
+       state->ret = SMB_VFS_FSYNC_RECV(subreq, &state->vfs_aio_state);
+       TALLOC_FREE(subreq);
+       if (state->ret != 0) {
+               tevent_req_error(req, errno);
+               return;
+       }
+       tevent_req_done(req);
+}
+
+static int fruit_fsync_recv(struct tevent_req *req,
+                                       struct vfs_aio_state *vfs_aio_state)
+{
+       struct fruit_fsync_state *state = tevent_req_data(
+               req, struct fruit_fsync_state);
+       int retval = -1;
+
+       if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
+               tevent_req_received(req);
+               return -1;
+       }
+
+       *vfs_aio_state = state->vfs_aio_state;
+       retval = state->ret;
+       tevent_req_received(req);
+       return retval;
+}
+
 /**
  * Helper to stat/lstat the base file of an smb_fname.
  */
@@ -5305,6 +5405,8 @@ static struct vfs_fn_pointers vfs_fruit_fns = {
        .pread_recv_fn = fruit_pread_recv,
        .pwrite_send_fn = fruit_pwrite_send,
        .pwrite_recv_fn = fruit_pwrite_recv,
+       .fsync_send_fn = fruit_fsync_send,
+       .fsync_recv_fn = fruit_fsync_recv,
        .stat_fn = fruit_stat,
        .lstat_fn = fruit_lstat,
        .fstat_fn = fruit_fstat,