s3:smbd: explain parameters in call to SMB_VFS_DURABLE_RECONNECT()
[obnox/samba/samba-obnox.git] / source3 / smbd / smb2_create.c
index 331ca49b1bac03486a809e469b45e0a7faa31fcf..6a43d274ff8b5c7cba9fd450b548cb7ed10e0535 100644 (file)
@@ -284,19 +284,6 @@ static void smbd_smb2_request_create_done(struct tevent_req *tsubreq)
        NTSTATUS status;
        NTSTATUS error; /* transport error */
 
-       if (smb2req->cancelled) {
-               uint64_t mid = get_mid_from_smb2req(smb2req);
-               DEBUG(10,("smbd_smb2_request_create_done: cancelled mid %llu\n",
-                       (unsigned long long)mid ));
-               error = smbd_smb2_request_error(smb2req, NT_STATUS_CANCELLED);
-               if (!NT_STATUS_IS_OK(error)) {
-                       smbd_server_connection_terminate(smb2req->sconn,
-                               nt_errstr(error));
-                       return;
-               }
-               return;
-       }
-
        status = smbd_smb2_create_recv(tsubreq,
                                       smb2req,
                                       &out_oplock_level,
@@ -390,7 +377,8 @@ static void smbd_smb2_request_create_done(struct tevent_req *tsubreq)
 struct smbd_smb2_create_state {
        struct smbd_smb2_request *smb2req;
        struct smb_request *smb1req;
-       struct timed_event *te;
+       bool open_was_deferred;
+       struct tevent_timer *te;
        struct tevent_immediate *im;
        struct timeval request_time;
        struct file_id id;
@@ -564,6 +552,7 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
                uint32_t durable_timeout_msec = 0;
                bool do_durable_reconnect = false;
                struct smb2_create_blob *dh2q = NULL;
+               uint64_t persistent_id = 0;
 
                exta = smb2_create_blob_find(&in_context_blobs,
                                             SMB2_CREATE_TAG_EXTA);
@@ -695,41 +684,13 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
                }
 
                if (dhnc) {
-                       NTTIME now = timeval_to_nttime(&smb2req->request_time);
-                       uint64_t persistent_id;
-
                        persistent_id = BVAL(dhnc->data.data, 0);
 
-                       status = smb2srv_open_recreate(smb2req->sconn->conn,
-                                               smb1req->conn->session_info,
-                                               persistent_id, create_guid,
-                                               now, &op);
-                       if (!NT_STATUS_IS_OK(status)) {
-                               DEBUG(3, ("smbd_smb2_create_send: "
-                                         "smb2srv_open_recreate v1 failed: %s\n",
-                                         nt_errstr(status)));
-                               tevent_req_nterror(req, status);
-                               return tevent_req_post(req, ev);
-                       }
-
-                       DEBUG(10, ("smb2_create_send: DHNC: %s recreate the "
-                                  "smb2srv_open struct for a durable handle.\n",
-                                  op->global->durable ? "did" : "could not"));
-
-                       if (!op->global->durable) {
-                               talloc_free(op);
-                               tevent_req_nterror(req,
-                                       NT_STATUS_OBJECT_NAME_NOT_FOUND);
-                               return tevent_req_post(req, ev);
-                       }
-
                        do_durable_reconnect = true;
                }
 
                if (dh2c) {
                        const uint8_t *p = dh2c->data.data;
-                       NTTIME now = timeval_to_nttime(&smb2req->request_time);
-                       uint64_t persistent_id;
                        DATA_BLOB create_guid_blob;
 
                        persistent_id = BVAL(p, 0);
@@ -741,29 +702,6 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
                                return tevent_req_post(req, ev);
                        }
 
-                       status = smb2srv_open_recreate(smb2req->sconn->conn,
-                                                      smb1req->conn->session_info,
-                                                      persistent_id, create_guid,
-                                                      now, &op);
-                       if (!NT_STATUS_IS_OK(status)) {
-                               DEBUG(3, ("smbd_smb2_create_send: "
-                                         "smb2srv_open_recreate v2 failed: %s\n",
-                                         nt_errstr(status)));
-                               tevent_req_nterror(req, status);
-                               return tevent_req_post(req, ev);
-                       }
-
-                       DEBUG(10, ("smb2_create_send: DH2C: %s recreate the "
-                                  "smb2srv_open struct for a durable handle.\n",
-                                  op->global->durable ? "did" : "could not"));
-
-                       if (!op->global->durable) {
-                               talloc_free(op);
-                               tevent_req_nterror(req,
-                                       NT_STATUS_OBJECT_NAME_NOT_FOUND);
-                               return tevent_req_post(req, ev);
-                       }
-
                        do_durable_reconnect = true;
                }
 
@@ -825,12 +763,37 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
                 */
                if (do_durable_reconnect) {
                        DATA_BLOB new_cookie = data_blob_null;
+                       NTTIME now = timeval_to_nttime(&smb2req->request_time);
+
+                       status = smb2srv_open_recreate(smb2req->sconn->conn,
+                                               smb1req->conn->session_info,
+                                               persistent_id, create_guid,
+                                               now, &op);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               DEBUG(3, ("smbd_smb2_create_send: "
+                                         "smb2srv_open_recreate failed: %s\n",
+                                         nt_errstr(status)));
+                               tevent_req_nterror(req, status);
+                               return tevent_req_post(req, ev);
+                       }
+
+                       DEBUG(10, ("smb2_create_send: %s to recreate the "
+                                  "smb2srv_open struct for a durable handle.\n",
+                                  op->global->durable ? "succeded" : "failed"));
+
+                       if (!op->global->durable) {
+                               talloc_free(op);
+                               tevent_req_nterror(req,
+                                       NT_STATUS_OBJECT_NAME_NOT_FOUND);
+                               return tevent_req_post(req, ev);
+                       }
 
                        status = SMB_VFS_DURABLE_RECONNECT(smb1req->conn,
                                                smb1req,
-                                               op,
+                                               op, /* smbXsrv_open input */
                                                op->global->backend_cookie,
-                                               op, &result, &new_cookie);
+                                               op, /* TALLOC_CTX */
+                                               &result, &new_cookie);
                        if (!NT_STATUS_IS_OK(status)) {
                                NTSTATUS return_status;
 
@@ -851,11 +814,10 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
                        op->status = NT_STATUS_OK;
                        op->global->disconnect_time = 0;
 
-                       status = smbXsrv_open_update(op);
-                       if (!NT_STATUS_IS_OK(status)) {
-                               tevent_req_nterror(req, status);
-                               return tevent_req_post(req, ev);
-                       }
+                       /* save the timout for later update */
+                       durable_timeout_msec = op->global->durable_timeout_msec;
+
+                       update_open = true;
 
                        info = FILE_WAS_OPENED;
                } else {
@@ -932,6 +894,7 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
 
                                status = smbd_calculate_access_mask(smb1req->conn,
                                                        result->fsp_name,
+                                                       false,
                                                        SEC_FLAG_MAXIMUM_ALLOWED,
                                                        &max_access_granted);
 
@@ -1144,9 +1107,6 @@ bool get_deferred_open_message_state_smb2(struct smbd_smb2_request *smb2req,
        if (!smb2req) {
                return false;
        }
-       if (smb2req->async_te == NULL) {
-               return false;
-       }
        req = smb2req->subreq;
        if (!req) {
                return false;
@@ -1155,6 +1115,9 @@ bool get_deferred_open_message_state_smb2(struct smbd_smb2_request *smb2req,
        if (!state) {
                return false;
        }
+       if (!state->open_was_deferred) {
+               return false;
+       }
        if (p_request_time) {
                *p_request_time = state->request_time;
        }
@@ -1216,7 +1179,7 @@ bool open_was_deferred_smb2(struct smbd_server_connection *sconn, uint64_t mid)
                return false;
        }
        /* It's not in progress if there's no timeout event. */
-       if (!state->te) {
+       if (!state->open_was_deferred) {
                return false;
        }
 
@@ -1247,6 +1210,7 @@ static void remove_deferred_open_message_smb2_internal(struct smbd_smb2_request
                "mid %llu\n",
                (unsigned long long)mid ));
 
+       state->open_was_deferred = false;
        /* Ensure we don't have any outstanding timer event. */
        TALLOC_FREE(state->te);
        /* Ensure we don't have any outstanding immediate event. */
@@ -1349,55 +1313,6 @@ bool schedule_deferred_open_message_smb2(
        return true;
 }
 
-/*********************************************************
- Re-process this call.
-*********************************************************/
-
-static void smb2_deferred_open_timer(struct event_context *ev,
-                                       struct timed_event *te,
-                                       struct timeval _tval,
-                                       void *private_data)
-{
-       NTSTATUS status;
-       struct smbd_smb2_create_state *state = NULL;
-       struct smbd_smb2_request *smb2req = talloc_get_type(private_data,
-                                               struct smbd_smb2_request);
-
-       DEBUG(10,("smb2_deferred_open_timer: [idx=%d], %s\n",
-               smb2req->current_idx,
-               tevent_req_default_print(smb2req->subreq, talloc_tos()) ));
-
-       state = tevent_req_data(smb2req->subreq,
-                       struct smbd_smb2_create_state);
-       if (!state) {
-               return;
-       }
-       /*
-        * Null this out, don't talloc_free. It will
-        * be talloc_free'd by the tevent library when
-        * this returns.
-        */
-       state->te = NULL;
-       /* Ensure we don't have any outstanding immediate event. */
-       TALLOC_FREE(state->im);
-
-       /*
-        * This is subtle. We must null out the callback
-        * before rescheduling, else the first call to
-        * tevent_req_nterror() causes the _receive()
-        * function to be called, this causing tevent_req_post()
-        * to crash.
-        */
-       tevent_req_set_callback(smb2req->subreq, NULL, NULL);
-
-       status = smbd_smb2_request_dispatch(smb2req);
-
-       if (!NT_STATUS_IS_OK(status)) {
-               smbd_server_connection_terminate(smb2req->sconn,
-                               nt_errstr(status));
-       }
-}
-
 static bool smbd_smb2_create_cancel(struct tevent_req *req)
 {
        struct smbd_smb2_request *smb2req = NULL;
@@ -1421,12 +1336,10 @@ static bool smbd_smb2_create_cancel(struct tevent_req *req)
                return false;
        }
 
-       remove_deferred_open_entry(state->id, mid,
-                                  messaging_server_id(smb2req->sconn->msg_ctx));
        remove_deferred_open_message_smb2_internal(smb2req, mid);
-       smb2req->cancelled = true;
 
-       tevent_req_done(req);
+       tevent_req_defer_callback(req, smb2req->sconn->ev_ctx);
+       tevent_req_nterror(req, NT_STATUS_CANCELLED);
        return true;
 }
 
@@ -1469,14 +1382,7 @@ bool push_deferred_open_message_smb2(struct smbd_smb2_request *smb2req,
                                &end_time,
                                true) ));
 
-       state->te = tevent_add_timer(smb2req->sconn->ev_ctx,
-                               state,
-                               end_time,
-                               smb2_deferred_open_timer,
-                               smb2req);
-        if (!state->te) {
-               return false;
-       }
+       state->open_was_deferred = true;
 
        /* allow this request to be canceled */
        tevent_req_set_cancel_fn(req, smbd_smb2_create_cancel);