+++ /dev/null
-^samba3.smb2.replay.durable-reconnect-replay1\(nt4_dc\)
-^samba3.smb2.replay.durable-reconnect-replay3\(nt4_dc\)
-^samba3.smb2.replay.replay-twice-durable\(nt4_dc\)
struct deferred_open_record *open_rec;
files_struct *result;
bool replay_operation;
+ bool replay_reconnect;
uint8_t in_oplock_level;
uint32_t in_create_disposition;
uint32_t in_create_options;
* there is nothing else to do), durable_reconnect or
* new open.
*/
- if (state->replay_operation) {
+ if (state->replay_operation && !state->replay_reconnect) {
+ SMB_ASSERT(state->op != NULL);
state->result = state->op->compat;
state->result->op = state->op;
state->update_open = false;
return req;
}
- if (state->do_durable_reconnect) {
+ if (state->do_durable_reconnect || state->replay_reconnect) {
DATA_BLOB new_cookie = data_blob_null;
NTTIME now = timeval_to_nttime(&smb2req->request_time);
const struct smb2_lease_key *lease_key = NULL;
+ /*
+ * Assert a replay on a multichannel connection doesn't end up
+ * here.
+ */
+ SMB_ASSERT(state->op == NULL);
+
if (state->lease_ptr != NULL) {
lease_key = &state->lease_ptr->lease_key;
}
state->update_open = true;
- state->info = FILE_WAS_OPENED;
+ if (!state->replay_reconnect) {
+ state->info = FILE_WAS_OPENED;
+ } else {
+ state->info = state->op->global->create_action;
+ }
smbd_smb2_create_after_exec(req);
if (!tevent_req_is_in_progress(req)) {
*state->create_guid,
state->fname,
now,
+ &state->persistent_id,
&state->op);
if (NT_STATUS_EQUAL(status, NT_STATUS_FWP_RESERVED)) {
/*
} else if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_NOT_AVAILABLE)) {
tevent_req_nterror(req, status);
return;
+ } else if (NT_STATUS_EQUAL(status, NT_STATUS_HANDLE_NO_LONGER_VALID)) {
+ state->replay_reconnect = true;
} else if (tevent_req_nterror(req, status)) {
DBG_WARNING("smb2srv_open_lookup_replay_cache "
"failed: %s\n", nt_errstr(status));
* established open carries a lease with the
* same lease key.
*/
- if (state->replay_operation) {
+ if (state->replay_operation && !state->replay_reconnect) {
struct smb2_lease *op_ls =
&state->op->compat->lease->lease;
int op_oplock = state->op->compat->oplock_type;
struct smbXsrv_open_table {
struct {
struct idr_context *idr;
- struct db_context *replay_cache_db_ctx;
uint32_t lowest_id;
uint32_t highest_id;
uint32_t max_opens;
TALLOC_FREE(table);
return NT_STATUS_NO_MEMORY;
}
- table->local.replay_cache_db_ctx = db_open_rbt(table);
- if (table->local.replay_cache_db_ctx == NULL) {
- TALLOC_FREE(table);
- return NT_STATUS_NO_MEMORY;
- }
table->local.lowest_id = lowest_id;
table->local.highest_id = highest_id;
table->local.max_opens = max_opens;
static NTSTATUS smbXsrv_open_set_replay_cache(struct smbXsrv_open *op)
{
struct GUID_txt_buf buf;
- struct db_context *db = op->table->local.replay_cache_db_ctx;
+ struct db_context *db = op->table->global.db_ctx;
struct smbXsrv_open_global_key_buf open_key_buf;
NTSTATUS status;
struct smbXsrv_open_replay_cache_key_buf key_buf;
create_guid,
&key_buf);
- status = dbwrap_purge(client->open_table->local.replay_cache_db_ctx, key);
+ status = dbwrap_purge(client->open_table->global.db_ctx, key);
return status;
}
return NT_STATUS_OK;
}
- db = op->table->local.replay_cache_db_ctx;
+ db = op->table->global.db_ctx;
if (!(op->flags & SMBXSRV_OPEN_HAVE_REPLAY_CACHE)) {
return NT_STATUS_OK;
global->open_global_id, &key_buf);
int ret;
- error = smbXsrv_open_clear_replay_cache(op);
- if (!NT_STATUS_IS_OK(error)) {
- DBG_ERR("smbXsrv_open_clear_replay_cache failed: %s\n",
- nt_errstr(error));
- }
-
if (op->table == NULL) {
return error;
}
error = state.status;
}
+ if (!op->global->durable) {
+ /*
+ * If this is not a Durable Handle, remove the Replay-Cache entry.
+ */
+ error = smbXsrv_open_clear_replay_cache(op);
+ if (!NT_STATUS_IS_OK(error)) {
+ DBG_ERR("smbXsrv_open_clear_replay_cache failed: %s\n",
+ nt_errstr(error));
+ }
+ }
+
ret = idr_remove(table->local.idr, op->local_id);
SMB_ASSERT(ret == 0);
struct GUID create_guid,
const char *name,
NTTIME now,
+ uint64_t *persistent_id,
struct smbXsrv_open **_open)
{
TALLOC_CTX *frame = talloc_stackframe();
NTSTATUS status;
struct smbXsrv_open_table *table = conn->client->open_table;
- struct db_context *db = table->local.replay_cache_db_ctx;
+ struct db_context *db = table->global.db_ctx;
struct GUID_txt_buf _create_guid_buf;
const char *create_guid_str = GUID_buf_string(&create_guid, &_create_guid_buf);
struct db_record *db_rec = NULL;
return NT_STATUS_OK;
}
- DBG_DEBUG("No local open\n");
+ DBG_DEBUG("No local open, triggering reconnect\n");
+ *persistent_id = open_global_id;
TALLOC_FREE(frame);
- return status;
+ return NT_STATUS_HANDLE_NO_LONGER_VALID;
}
struct smb2srv_open_recreate_state {
struct GUID create_guid,
const char *name,
NTTIME now,
+ uint64_t *persistent_id,
struct smbXsrv_open **_open);
struct smb2_lease_key;
NTSTATUS smb2srv_open_recreate(struct smbXsrv_connection *conn,