return true;
}
+static bool durable_reconnect_fn(
+ struct share_mode_entry *e,
+ bool *modified,
+ void *private_data)
+{
+ struct share_mode_entry *dst_e = private_data;
+
+ if (dst_e->pid.pid != 0) {
+ DBG_INFO("Found more than one entry, invalidating previous\n");
+ dst_e->pid.pid = 0;
+ return true; /* end the loop through share mode entries */
+ }
+ *dst_e = *e;
+ return false; /* Look at potential other entries */
+}
+
NTSTATUS vfs_default_durable_reconnect(struct connection_struct *conn,
struct smb_request *smb1req,
struct smbXsrv_open *op,
DATA_BLOB *new_cookie)
{
struct share_mode_lock *lck;
- struct share_mode_entry *e;
+ struct share_mode_entry e;
struct files_struct *fsp = NULL;
NTSTATUS status;
bool ok;
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
- if (lck->data->num_share_modes == 0) {
- DEBUG(1, ("vfs_default_durable_reconnect: Error: no share-mode "
- "entry in existing share mode lock\n"));
+ e = (struct share_mode_entry) { .pid.pid = 0 };
+
+ ok = share_mode_forall_entries(lck, durable_reconnect_fn, &e);
+ if (!ok) {
+ DBG_WARNING("share_mode_forall_entries failed\n");
TALLOC_FREE(lck);
return NT_STATUS_INTERNAL_DB_ERROR;
}
- if (lck->data->num_share_modes > 1) {
- /*
- * It can't be durable if there is more than one handle
- * on the file.
- */
- DEBUG(5, ("vfs_default_durable_reconnect: more than one "
- "share-mode entry - can not be durable\n"));
+ if (e.pid.pid == 0) {
+ DBG_WARNING("Did not find a unique valid share mode entry\n");
TALLOC_FREE(lck);
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
- e = &lck->data->share_modes[0];
-
- if (!server_id_is_disconnected(&e->pid)) {
+ if (!server_id_is_disconnected(&e.pid)) {
DEBUG(5, ("vfs_default_durable_reconnect: denying durable "
"reconnect for handle that was not marked "
"disconnected (e.g. smbd or cluster node died)\n"));
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
- if (e->share_file_id != op->global->open_persistent_id) {
+ if (e.share_file_id != op->global->open_persistent_id) {
DBG_INFO("denying durable "
"share_file_id changed %"PRIu64" != %"PRIu64" "
"(e.g. another client had opened the file)\n",
- e->share_file_id,
+ e.share_file_id,
op->global->open_persistent_id);
TALLOC_FREE(lck);
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
- if ((e->access_mask & (FILE_WRITE_DATA|FILE_APPEND_DATA)) &&
+ if ((e.access_mask & (FILE_WRITE_DATA|FILE_APPEND_DATA)) &&
!CAN_WRITE(conn))
{
DEBUG(5, ("vfs_default_durable_reconnect: denying durable "
return status;
}
- fsp->fh->private_options = e->private_options;
+ fsp->fh->private_options = e.private_options;
fsp->file_id = file_id;
fsp->file_pid = smb1req->smbpid;
fsp->vuid = smb1req->vuid;
- fsp->open_time = e->time;
- fsp->access_mask = e->access_mask;
+ fsp->open_time = e.time;
+ fsp->access_mask = e.access_mask;
fsp->can_read = ((fsp->access_mask & (FILE_READ_DATA)) != 0);
fsp->can_write = ((fsp->access_mask & (FILE_WRITE_DATA|FILE_APPEND_DATA)) != 0);
fsp->fnum = op->local_id;
* We do not support aio write behind for smb2
*/
fsp->aio_write_behind = false;
- fsp->oplock_type = e->op_type;
+ fsp->oplock_type = e.op_type;
if (fsp->oplock_type == LEASE_OPLOCK) {
uint32_t current_state;
* stored one in the share_mode_entry.
*/
if (!GUID_equal(fsp_client_guid(fsp),
- &e->client_guid)) {
+ &e.client_guid)) {
TALLOC_FREE(lck);
fsp_free(fsp);
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
status = leases_db_get(
- &e->client_guid,
- &e->lease_key,
+ &e.client_guid,
+ &e.lease_key,
&file_id,
¤t_state, /* current_state */
NULL, /* breaking */
fsp->lease = find_fsp_lease(
fsp,
- &e->lease_key,
+ &e.lease_key,
current_state,
lease_version,
epoch);
op->compat = fsp;
fsp->op = op;
- e->pid = messaging_server_id(conn->sconn->msg_ctx);
- e->op_mid = smb1req->mid;
- e->share_file_id = fsp->fh->gen_id;
+ ok = reset_share_mode_entry(
+ lck,
+ e.pid,
+ e.share_file_id,
+ messaging_server_id(conn->sconn->msg_ctx),
+ smb1req->mid,
+ fsp->fh->gen_id);
+ if (!ok) {
+ DBG_DEBUG("Could not set new share_mode_entry values\n");
+ TALLOC_FREE(lck);
+ op->compat = NULL;
+ fsp_free(fsp);
+ return NT_STATUS_INTERNAL_ERROR;
+ }
ok = brl_reconnect_disconnected(fsp);
if (!ok) {