]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
smbd: rework async rename check for handle lease breaks
authorRalph Boehme <slow@samba.org>
Mon, 16 Sep 2024 00:36:00 +0000 (02:36 +0200)
committerRalph Boehme <slow@samba.org>
Tue, 5 Nov 2024 14:39:30 +0000 (14:39 +0000)
Add a version of delay_rename_for_lease_break() that is usable in other places
where we have to check for handle lease breaks. No change in behaviour.

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

Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
source3/smbd/proto.h
source3/smbd/smb2_oplock.c
source3/smbd/smb2_setinfo.c

index 15262d07fab92ff3c35db6620f3739e5c92f7a19..8ff937a8e4fa7c8189cc571827618f4f8246cfd9 100644 (file)
@@ -1204,4 +1204,15 @@ void smb3_file_posix_information_init(
        uint32_t dos_attributes,
        struct smb3_file_posix_information *dst);
 
+struct tevent_req *delay_for_handle_lease_break_send(
+       TALLOC_CTX *mem_ctx,
+       struct tevent_context *ev,
+       struct timeval timeout,
+       struct files_struct *fsp,
+       struct share_mode_lock **lck);
+
+NTSTATUS delay_for_handle_lease_break_recv(struct tevent_req *req,
+                                          TALLOC_CTX *mem_ctx,
+                                          struct share_mode_lock **lck);
+
 #endif /* _SMBD_PROTO_H_ */
index bdc0cc96cc61a7102f54b414414dbe01d28457f4..f3155ff0c45c74986a7fb6b566b0916a668ef036 100644 (file)
@@ -28,6 +28,7 @@
 #include "messages.h"
 #include "locking/leases_db.h"
 #include "../librpc/gen_ndr/ndr_open_files.h"
+#include "lib/util/tevent_ntstatus.h"
 
 /*
  * helper function used by the kernel oplock backends to post the break message
@@ -1368,3 +1369,232 @@ void init_kernel_oplocks(struct smbd_server_connection *sconn)
                sconn->oplocks.kernel_ops = koplocks;
        }
 }
+
+struct delay_for_handle_lease_break_state {
+       TALLOC_CTX *mem_ctx;
+       struct tevent_context *ev;
+       struct timeval timeout;
+       struct files_struct *fsp;
+       struct share_mode_lock *lck;
+       bool delay;
+};
+
+static void delay_for_handle_lease_break_cleanup(struct tevent_req *req,
+                                                enum tevent_req_state req_state)
+{
+       struct delay_for_handle_lease_break_state *state =
+               tevent_req_data(req, struct delay_for_handle_lease_break_state);
+
+       if (req_state == TEVENT_REQ_DONE) {
+               return;
+       }
+       TALLOC_FREE(state->lck);
+}
+
+static void delay_for_handle_lease_break_check(struct tevent_req *req);
+
+struct tevent_req *delay_for_handle_lease_break_send(
+       TALLOC_CTX *mem_ctx,
+       struct tevent_context *ev,
+       struct timeval timeout,
+       struct files_struct *fsp,
+       struct share_mode_lock **lck)
+{
+       struct tevent_req *req = NULL;
+       struct delay_for_handle_lease_break_state *state = NULL;
+
+       req = tevent_req_create(
+               mem_ctx, &state, struct delay_for_handle_lease_break_state);
+       if (req == NULL) {
+               return NULL;
+       }
+
+       tevent_req_set_cleanup_fn(req, delay_for_handle_lease_break_cleanup);
+
+       *state = (struct delay_for_handle_lease_break_state) {
+               .mem_ctx = mem_ctx,
+               .ev = ev,
+               .timeout = timeout,
+               .fsp = fsp,
+               .lck = talloc_move(state, lck),
+       };
+
+       delay_for_handle_lease_break_check(req);
+       if (!tevent_req_is_in_progress(req)) {
+               return tevent_req_post(req, ev);
+       }
+
+       /* Ensure we can't be closed in flight. */
+       if (!aio_add_req_to_fsp(fsp, req)) {
+               tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
+               return tevent_req_post(req, ev);
+       }
+
+       return req;
+}
+
+static bool delay_for_handle_lease_break_fn(struct share_mode_entry *e,
+                                           void *private_data)
+{
+       struct delay_for_handle_lease_break_state *state = talloc_get_type_abort(
+               private_data, struct delay_for_handle_lease_break_state);
+       struct files_struct *fsp = state->fsp;
+       struct server_id_buf buf;
+       uint32_t lease_type;
+       bool ours, stale;
+
+       if (fsp->lease != NULL) {
+               ours = smb2_lease_equal(fsp_client_guid(fsp),
+                                       &fsp->lease->lease.lease_key,
+                                       &e->client_guid,
+                                       &e->lease_key);
+               if (ours) {
+                       return false;
+               }
+       }
+
+       lease_type = get_lease_type(e, fsp->file_id);
+       if ((lease_type & SMB2_LEASE_HANDLE) == 0) {
+               return false;
+       }
+
+       stale = share_entry_stale_pid(e);
+       if (stale) {
+               return false;
+       }
+
+       state->delay = true;
+
+       DBG_DEBUG("Breaking h-lease on [%s] pid [%s]\n",
+                 fsp_str_dbg(fsp),
+                 server_id_str_buf(e->pid, &buf));
+
+       send_break_message(fsp->conn->sconn->msg_ctx,
+                          &fsp->file_id,
+                          e,
+                          lease_type & ~SMB2_LEASE_HANDLE);
+
+       return false;
+}
+
+static void delay_for_handle_lease_break_fsp_done(struct tevent_req *subreq);
+
+static void delay_for_handle_lease_break_fsp_check(struct tevent_req *req)
+{
+       struct delay_for_handle_lease_break_state *state = tevent_req_data(
+               req, struct delay_for_handle_lease_break_state);
+       struct tevent_req *subreq = NULL;
+       bool ok;
+
+       DBG_DEBUG("fsp [%s]\n", fsp_str_dbg(state->fsp));
+
+       ok = share_mode_forall_leases(state->lck,
+                                     delay_for_handle_lease_break_fn,
+                                     state);
+       if (!ok) {
+               tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
+               return;
+       }
+       if (state->delay) {
+               DBG_DEBUG("Delaying fsp [%s]\n", fsp_str_dbg(state->fsp));
+
+               subreq = share_mode_watch_send(state,
+                                              state->ev,
+                                              state->lck,
+                                              (struct server_id){0});
+               if (tevent_req_nomem(subreq, req)) {
+                       return;
+               }
+
+               tevent_req_set_callback(subreq,
+                                       delay_for_handle_lease_break_fsp_done,
+                                       req);
+
+               if (!tevent_req_set_endtime(subreq, state->ev, state->timeout)) {
+                       tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
+                       return;
+               }
+               return;
+       }
+}
+
+static void delay_for_handle_lease_break_fsp_done(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(
+               subreq, struct tevent_req);
+       struct delay_for_handle_lease_break_state *state = tevent_req_data(
+               req, struct delay_for_handle_lease_break_state);
+       NTSTATUS status;
+
+       DBG_DEBUG("Watch returned for fsp [%s]\n", fsp_str_dbg(state->fsp));
+
+       status = share_mode_watch_recv(subreq, NULL, NULL);
+       TALLOC_FREE(subreq);
+       if (!NT_STATUS_IS_OK(status)) {
+               DBG_ERR("share_mode_watch_recv returned %s\n",
+                       nt_errstr(status));
+               if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
+                       /*
+                        * The sharemode-watch timer fired because a client
+                        * didn't respond to the lease break.
+                        */
+                       status = NT_STATUS_ACCESS_DENIED;
+               }
+               tevent_req_nterror(req, status);
+               return;
+       }
+
+       state->lck = get_existing_share_mode_lock(state, state->fsp->file_id);
+       if (state->lck == NULL) {
+               tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
+               return;
+       }
+
+       /*
+        * This could potentially end up looping for some if a client
+        * aggressively reaquires H-leases on the file, but we have a
+        * timeout on the tevent req as upper bound.
+        */
+       delay_for_handle_lease_break_check(req);
+}
+
+static void delay_for_handle_lease_break_check(struct tevent_req *req)
+{
+       struct delay_for_handle_lease_break_state *state = tevent_req_data(
+               req, struct delay_for_handle_lease_break_state);
+
+       state->delay = false;
+
+       DBG_DEBUG("fsp [%s]\n", fsp_str_dbg(state->fsp));
+
+       delay_for_handle_lease_break_fsp_check(req);
+       if (!tevent_req_is_in_progress(req)) {
+               return;
+       }
+       if (state->delay) {
+               DBG_DEBUG("Delaying fsp [%s]\n", fsp_str_dbg(state->fsp));
+               TALLOC_FREE(state->lck);
+               return;
+       }
+
+       tevent_req_done(req);
+}
+
+NTSTATUS delay_for_handle_lease_break_recv(struct tevent_req *req,
+                                          TALLOC_CTX *mem_ctx,
+                                          struct share_mode_lock **lck)
+{
+       NTSTATUS status;
+
+       struct delay_for_handle_lease_break_state *state =
+               tevent_req_data(req, struct delay_for_handle_lease_break_state);
+
+       if (tevent_req_is_nterror(req, &status)) {
+               tevent_req_received(req);
+               return status;
+       }
+
+       *lck = talloc_move(mem_ctx, &state->lck);
+       tevent_req_received(req);
+       return NT_STATUS_OK;
+}
index df4ecbf61d5a0cbf7361230d17eb96007a876794..db6ca6d12046c8a0cfb2f09ff8e43c52095454a0 100644 (file)
@@ -168,188 +168,30 @@ static void smbd_smb2_request_setinfo_done(struct tevent_req *subreq)
        }
 }
 
-struct defer_rename_state {
-       struct tevent_req *req;
-       struct smbd_smb2_request *smb2req;
+struct smbd_smb2_setinfo_state {
        struct tevent_context *ev;
+       struct smbd_smb2_request *smb2req;
        struct files_struct *fsp;
+       struct share_mode_lock *lck;
+       uint16_t file_info_level;
        DATA_BLOB data;
-};
-
-static void defer_rename_done(struct tevent_req *subreq);
-
-struct delay_rename_lease_break_state {
-       struct files_struct *fsp;
        bool delay;
 };
 
-static bool delay_rename_lease_break_fn(
-       struct share_mode_entry *e,
-       void *private_data)
-{
-       struct delay_rename_lease_break_state *state = private_data;
-       struct files_struct *fsp = state->fsp;
-       uint32_t e_lease_type, break_to;
-       bool ours, stale;
-
-       ours = smb2_lease_equal(fsp_client_guid(fsp),
-                               &fsp->lease->lease.lease_key,
-                               &e->client_guid,
-                               &e->lease_key);
-       if (ours) {
-               return false;
-       }
-
-       e_lease_type = get_lease_type(e, fsp->file_id);
-
-       if ((e_lease_type & SMB2_LEASE_HANDLE) == 0) {
-               return false;
-       }
-
-       stale = share_entry_stale_pid(e);
-       if (stale) {
-               return false;
-       }
-
-       state->delay = true;
-       break_to = (e_lease_type & ~SMB2_LEASE_HANDLE);
+static void smbd_smb2_setinfo_lease_break_check(struct tevent_req *req);
 
-       send_break_message(
-               fsp->conn->sconn->msg_ctx, &fsp->file_id, e, break_to);
-
-       return false;
-}
-
-static struct tevent_req *delay_rename_for_lease_break(struct tevent_req *req,
-                               struct smbd_smb2_request *smb2req,
-                               struct tevent_context *ev,
-                               struct files_struct *fsp,
-                               struct share_mode_lock *lck,
-                               DATA_BLOB *data)
+static void smbd_smb2_setinfo_cleanup(struct tevent_req *req,
+                                     enum tevent_req_state req_state)
 {
-       struct tevent_req *subreq;
-       struct defer_rename_state *rename_state;
-       struct delay_rename_lease_break_state state = { .fsp = fsp };
-       struct timeval timeout;
-       bool ok;
-
-       ok = share_mode_forall_leases(
-               lck, delay_rename_lease_break_fn, &state);
-       if (!ok) {
-               return NULL;
-       }
-
-       if (!state.delay) {
-               return NULL;
-       }
-
-       /* Setup a watch on this record. */
-       rename_state = talloc_zero(req, struct defer_rename_state);
-       if (rename_state == NULL) {
-               return NULL;
-       }
+       struct smbd_smb2_setinfo_state *state = tevent_req_data(
+               req, struct smbd_smb2_setinfo_state);
 
-       rename_state->req = req;
-       rename_state->smb2req = smb2req;
-       rename_state->ev = ev;
-       rename_state->fsp = fsp;
-       rename_state->data = *data;
-
-       subreq = share_mode_watch_send(
-                               rename_state,
-                               ev,
-                               lck,
-                               (struct server_id){0});
-
-       if (subreq == NULL) {
-               exit_server("Could not watch share mode record for rename\n");
-       }
-
-       tevent_req_set_callback(subreq, defer_rename_done, rename_state);
-
-       timeout = tevent_timeval_set(OPLOCK_BREAK_TIMEOUT * 2, 0);
-       if (!tevent_req_set_endtime(subreq,
-                       ev,
-                       timeval_sum(&smb2req->request_time, &timeout))) {
-               exit_server("Could not set rename timeout\n");
-       }
-
-       return subreq;
-}
-
-static void defer_rename_done(struct tevent_req *subreq)
-{
-       struct defer_rename_state *state = tevent_req_callback_data(
-               subreq, struct defer_rename_state);
-       NTSTATUS status;
-       struct share_mode_lock *lck;
-       int ret_size = 0;
-       bool ok;
-
-       status = share_mode_watch_recv(subreq, NULL, NULL);
-       TALLOC_FREE(subreq);
-       if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(5, ("dbwrap_record_watch_recv returned %s\n",
-                       nt_errstr(status)));
-               tevent_req_nterror(state->req, status);
-               return;
-       }
-
-       /*
-        * Make sure we run as the user again
-        */
-       ok = change_to_user_and_service(
-               state->smb2req->tcon->compat,
-               state->smb2req->session->global->session_wire_id);
-       if (!ok) {
-               tevent_req_nterror(state->req, NT_STATUS_ACCESS_DENIED);
-               return;
-       }
-
-       /* Do we still need to wait ? */
-       lck = get_existing_share_mode_lock(state->req, state->fsp->file_id);
-       if (lck == NULL) {
-               tevent_req_nterror(state->req, NT_STATUS_UNSUCCESSFUL);
-               return;
-       }
-       subreq = delay_rename_for_lease_break(state->req,
-                               state->smb2req,
-                               state->ev,
-                               state->fsp,
-                               lck,
-                               &state->data);
-       if (subreq) {
-               /* Yep - keep waiting. */
-               TALLOC_FREE(state);
-               TALLOC_FREE(lck);
+       if (req_state == TEVENT_REQ_DONE) {
                return;
        }
-
-       /* Do the rename under the lock. */
-       status = smbd_do_setfilepathinfo(state->fsp->conn,
-                               state->smb2req->smb1req,
-                               state,
-                               SMB2_FILE_RENAME_INFORMATION_INTERNAL,
-                               state->fsp,
-                               state->fsp->fsp_name,
-                               (char *)state->data.data,
-                               state->data.length,
-                               &ret_size);
-
-       TALLOC_FREE(lck);
-
-       if (!NT_STATUS_IS_OK(status)) {
-               tevent_req_nterror(state->req, status);
-               return;
-       }
-
-       tevent_req_done(state->req);
+       TALLOC_FREE(state->lck);
 }
 
-struct smbd_smb2_setinfo_state {
-       struct smbd_smb2_request *smb2req;
-};
-
 static struct tevent_req *smbd_smb2_setinfo_send(TALLOC_CTX *mem_ctx,
                                                 struct tevent_context *ev,
                                                 struct smbd_smb2_request *smb2req,
@@ -363,7 +205,6 @@ static struct tevent_req *smbd_smb2_setinfo_send(TALLOC_CTX *mem_ctx,
        struct smbd_smb2_setinfo_state *state = NULL;
        struct smb_request *smbreq = NULL;
        connection_struct *conn = smb2req->tcon->compat;
-       struct share_mode_lock *lck = NULL;
        NTSTATUS status;
        int ret;
 
@@ -372,7 +213,12 @@ static struct tevent_req *smbd_smb2_setinfo_send(TALLOC_CTX *mem_ctx,
        if (req == NULL) {
                return NULL;
        }
+       state->ev = ev;
        state->smb2req = smb2req;
+       state->fsp = fsp;
+       state->data = in_input_buffer;
+
+       tevent_req_set_cleanup_fn(req, smbd_smb2_setinfo_cleanup);
 
        DEBUG(10,("smbd_smb2_setinfo_send: %s - %s\n",
                  fsp_str_dbg(fsp), fsp_fnum_dbg(fsp)));
@@ -391,13 +237,13 @@ static struct tevent_req *smbd_smb2_setinfo_send(TALLOC_CTX *mem_ctx,
        case SMB2_0_INFO_FILE:
        {
                uint16_t file_info_level;
-               int ret_size = 0;
 
                file_info_level = in_file_info_class + 1000;
                if (file_info_level == SMB_FILE_RENAME_INFORMATION) {
                        /* SMB2_FILE_RENAME_INFORMATION_INTERNAL == 0xFF00 + in_file_info_class */
                        file_info_level = SMB2_FILE_RENAME_INFORMATION_INTERNAL;
                }
+               state->file_info_level = file_info_level;
 
                if (fsp_get_pathref_fd(fsp) == -1) {
                        /*
@@ -448,54 +294,12 @@ static struct tevent_req *smbd_smb2_setinfo_send(TALLOC_CTX *mem_ctx,
                        }
                }
 
-               if (file_info_level == SMB2_FILE_RENAME_INFORMATION_INTERNAL) {
-                       struct tevent_req *subreq;
-
-                       lck = get_existing_share_mode_lock(mem_ctx,
-                                                       fsp->file_id);
-                       if (lck == NULL) {
-                               tevent_req_nterror(req,
-                                       NT_STATUS_UNSUCCESSFUL);
-                               return tevent_req_post(req, ev);
-                       }
-
-                       subreq = delay_rename_for_lease_break(req,
-                                                       smb2req,
-                                                       ev,
-                                                       fsp,
-                                                       lck,
-                                                       &in_input_buffer);
-                       if (subreq) {
-                               /* Wait for lease break response. */
-
-                               /* Ensure we can't be closed in flight. */
-                               if (!aio_add_req_to_fsp(fsp, req)) {
-                                       TALLOC_FREE(lck);
-                                       tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
-                                       return tevent_req_post(req, ev);
-                               }
-
-                               TALLOC_FREE(lck);
-                               return req;
-                       }
-               }
-
-               status = smbd_do_setfilepathinfo(conn, smbreq, state,
-                                                file_info_level,
-                                                fsp,
-                                                fsp->fsp_name,
-                                                (char *)in_input_buffer.data,
-                                                in_input_buffer.length,
-                                                &ret_size);
-               TALLOC_FREE(lck);
-               if (!NT_STATUS_IS_OK(status)) {
-                       if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_LEVEL)) {
-                               status = NT_STATUS_INVALID_INFO_CLASS;
-                       }
-                       tevent_req_nterror(req, status);
+               smbd_smb2_setinfo_lease_break_check(req);
+               if (!tevent_req_is_in_progress(req)) {
                        return tevent_req_post(req, ev);
                }
-               break;
+               SMB_ASSERT(state->delay);
+               return req;
        }
 
        case SMB2_0_INFO_FILESYSTEM:
@@ -583,6 +387,144 @@ static struct tevent_req *smbd_smb2_setinfo_send(TALLOC_CTX *mem_ctx,
        return tevent_req_post(req, ev);
 }
 
+static void smbd_smb2_setinfo_lease_break_fsp_check(struct tevent_req *req);
+static void smbd_smb2_setinfo_lease_break_fsp_done(struct tevent_req *subreq);
+
+static void smbd_smb2_setinfo_lease_break_check(struct tevent_req *req)
+{
+       struct smbd_smb2_setinfo_state *state = tevent_req_data(
+               req, struct smbd_smb2_setinfo_state);
+       int ret_size;
+       NTSTATUS status;
+
+       state->delay = false;
+
+       smbd_smb2_setinfo_lease_break_fsp_check(req);
+       if (!tevent_req_is_in_progress(req)) {
+               return;
+       }
+       if (state->delay) {
+               TALLOC_FREE(state->lck);
+               DBG_DEBUG("Waiting for h-lease breaks on fsp [%s]\n",
+                         fsp_str_dbg(state->fsp));
+               return;
+       }
+
+       status = smbd_do_setfilepathinfo(state->fsp->conn,
+                                        state->smb2req->smb1req,
+                                        state,
+                                        state->file_info_level,
+                                        state->fsp,
+                                        state->fsp->fsp_name,
+                                        (char *)state->data.data,
+                                        state->data.length,
+                                        &ret_size);
+       TALLOC_FREE(state->lck);
+       if (!NT_STATUS_IS_OK(status)) {
+               if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_LEVEL)) {
+                       status = NT_STATUS_INVALID_INFO_CLASS;
+               }
+               tevent_req_nterror(req, status);
+               return;
+       }
+
+       tevent_req_done(req);
+}
+
+static void smbd_smb2_setinfo_lease_break_fsp_check(struct tevent_req *req)
+{
+       struct smbd_smb2_setinfo_state *state = tevent_req_data(
+               req, struct smbd_smb2_setinfo_state);
+       struct smbd_smb2_request *smb2req = state->smb2req;
+       struct files_struct *fsp = state->fsp;
+       uint16_t file_info_level = state->file_info_level;
+       struct tevent_req *subreq = NULL;
+       struct timeval timeout;
+       bool rename;
+       NTSTATUS status;
+
+       rename = (file_info_level == SMB2_FILE_RENAME_INFORMATION_INTERNAL);
+       if (!rename) {
+               return;
+       }
+
+       state->lck = get_existing_share_mode_lock(state, fsp->file_id);
+       if (state->lck == NULL) {
+               tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
+               return;
+       }
+
+       timeout = tevent_timeval_set(OPLOCK_BREAK_TIMEOUT, 0);
+       timeout = timeval_sum(&smb2req->request_time, &timeout);
+
+       subreq = delay_for_handle_lease_break_send(state,
+                                                  state->ev,
+                                                  timeout,
+                                                  fsp,
+                                                  &state->lck);
+       if (tevent_req_nomem(subreq, req)) {
+               return;
+       }
+       if (tevent_req_is_in_progress(subreq)) {
+               state->delay = true;
+               tevent_req_set_callback(subreq,
+                                       smbd_smb2_setinfo_lease_break_fsp_done,
+                                       req);
+               return;
+       }
+
+       status = delay_for_handle_lease_break_recv(subreq, state, &state->lck);
+       TALLOC_FREE(subreq);
+       if (tevent_req_nterror(req, status)) {
+               return;
+       }
+}
+
+static void smbd_smb2_setinfo_lease_break_fsp_done(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(
+               subreq, struct tevent_req);
+       struct smbd_smb2_setinfo_state *state = tevent_req_data(
+               req, struct smbd_smb2_setinfo_state);
+       int ret_size;
+       NTSTATUS status;
+       bool ok;
+
+       status = delay_for_handle_lease_break_recv(subreq, state, &state->lck);
+       TALLOC_FREE(subreq);
+       if (tevent_req_nterror(req, status)) {
+               return;
+       }
+
+       /*
+        * Make sure we run as the user again
+        */
+       ok = change_to_user_and_service(
+               state->smb2req->tcon->compat,
+               state->smb2req->session->global->session_wire_id);
+       if (!ok) {
+               tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
+               return;
+       }
+
+       /* Do the rename under the lock. */
+       status = smbd_do_setfilepathinfo(state->fsp->conn,
+                               state->smb2req->smb1req,
+                               state,
+                               state->file_info_level,
+                               state->fsp,
+                               state->fsp->fsp_name,
+                               (char *)state->data.data,
+                               state->data.length,
+                               &ret_size);
+       TALLOC_FREE(state->lck);
+       if (tevent_req_nterror(req, status)) {
+               return;
+       }
+
+       tevent_req_done(req);
+}
+
 static NTSTATUS smbd_smb2_setinfo_recv(struct tevent_req *req)
 {
        NTSTATUS status;