mirror of
https://github.com/samba-team/samba.git
synced 2024-12-22 13:34:15 +03:00
smbd: add handle lease breaking when deleting files at session shutdown time
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>
This commit is contained in:
parent
bb940c5bb6
commit
644fab6c2a
@ -1,3 +1,2 @@
|
||||
^samba3.smb2.lease.initial_delete_disconnect\(fileserver\)
|
||||
^samba3.smb2.lease.initial_delete_logoff\(fileserver\)
|
||||
^samba3.smb2.lease.initial_delete_tdis\(fileserver\)
|
||||
|
@ -1739,6 +1739,19 @@ struct smb2srv_session_shutdown_state {
|
||||
|
||||
static void smb2srv_session_shutdown_wait_done(struct tevent_req *subreq);
|
||||
|
||||
struct check_for_lease_break_fsp_cmp_state {
|
||||
struct smbXsrv_session *session;
|
||||
};
|
||||
|
||||
static bool check_for_lease_break_fsp_cmp_fn(struct files_struct *fsp,
|
||||
void *private_data)
|
||||
{
|
||||
struct check_for_lease_break_fsp_cmp_state *state =
|
||||
(struct check_for_lease_break_fsp_cmp_state *)private_data;
|
||||
|
||||
return (fsp->vuid == state->session->global->session_wire_id);
|
||||
}
|
||||
|
||||
struct tevent_req *smb2srv_session_shutdown_send(TALLOC_CTX *mem_ctx,
|
||||
struct tevent_context *ev,
|
||||
struct smbXsrv_session *session,
|
||||
@ -1748,6 +1761,7 @@ struct tevent_req *smb2srv_session_shutdown_send(TALLOC_CTX *mem_ctx,
|
||||
struct smb2srv_session_shutdown_state *state = NULL;
|
||||
struct tevent_req *subreq = NULL;
|
||||
struct smbXsrv_connection *xconn = NULL;
|
||||
struct check_for_lease_break_fsp_cmp_state fsp_cmp_state;
|
||||
size_t len = 0;
|
||||
|
||||
/*
|
||||
@ -1797,6 +1811,21 @@ struct tevent_req *smb2srv_session_shutdown_send(TALLOC_CTX *mem_ctx,
|
||||
}
|
||||
}
|
||||
|
||||
fsp_cmp_state = (struct check_for_lease_break_fsp_cmp_state) {
|
||||
.session = session,
|
||||
};
|
||||
|
||||
smbXsrv_wait_for_handle_lease_break(
|
||||
req,
|
||||
ev,
|
||||
session->client,
|
||||
state->wait_queue,
|
||||
check_for_lease_break_fsp_cmp_fn,
|
||||
&fsp_cmp_state);
|
||||
if (!tevent_req_is_in_progress(req)) {
|
||||
return tevent_req_post(req, ev);
|
||||
}
|
||||
|
||||
len = tevent_queue_length(state->wait_queue);
|
||||
if (len == 0) {
|
||||
tevent_req_done(req);
|
||||
@ -2517,3 +2546,132 @@ NTSTATUS smbXsrv_session_global_traverse(
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static struct files_struct *smbXsrv_wait_for_handle_lease_break_fn(
|
||||
struct files_struct *fsp,
|
||||
void *private_data);
|
||||
static void smbXsrv_wait_for_handle_lease_break_done(
|
||||
struct tevent_req *subreq);
|
||||
|
||||
struct delay_for_handle_lease_break_state {
|
||||
struct tevent_req *req;
|
||||
struct tevent_context *ev;
|
||||
struct smbXsrv_client *client;
|
||||
struct tevent_queue *wait_queue;
|
||||
bool (*fsp_cmp_fn)(struct files_struct *fsp,
|
||||
void *private_data);
|
||||
void *fsp_cmp_private_data;
|
||||
};
|
||||
|
||||
void smbXsrv_wait_for_handle_lease_break(
|
||||
struct tevent_req *req,
|
||||
struct tevent_context *ev,
|
||||
struct smbXsrv_client *client,
|
||||
struct tevent_queue *wait_queue,
|
||||
bool (*fsp_cmp_fn)(struct files_struct *fsp,
|
||||
void *private_data),
|
||||
void *fsp_cmp_private_data)
|
||||
{
|
||||
struct delay_for_handle_lease_break_state state;
|
||||
|
||||
state = (struct delay_for_handle_lease_break_state) {
|
||||
.req = req,
|
||||
.ev = ev,
|
||||
.client = client,
|
||||
.wait_queue = wait_queue,
|
||||
.fsp_cmp_fn = fsp_cmp_fn,
|
||||
.fsp_cmp_private_data = fsp_cmp_private_data,
|
||||
};
|
||||
|
||||
files_forall(client->sconn,
|
||||
smbXsrv_wait_for_handle_lease_break_fn,
|
||||
&state);
|
||||
}
|
||||
|
||||
static struct files_struct *smbXsrv_wait_for_handle_lease_break_fn(
|
||||
struct files_struct *fsp,
|
||||
void *private_data)
|
||||
{
|
||||
struct delay_for_handle_lease_break_state *state = private_data;
|
||||
struct tevent_req *subreq = NULL;
|
||||
struct share_mode_lock *lck = NULL;
|
||||
struct timeval timeout = timeval_current_ofs(OPLOCK_BREAK_TIMEOUT, 0);
|
||||
bool match;
|
||||
NTSTATUS status;
|
||||
|
||||
match = state->fsp_cmp_fn(fsp, state->fsp_cmp_private_data);
|
||||
if (!match) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!fsp->fsp_flags.initial_delete_on_close) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lck = get_existing_share_mode_lock(fsp, fsp->file_id);
|
||||
if (lck == NULL) {
|
||||
/* No opens on this file */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
subreq = delay_for_handle_lease_break_send(fsp,
|
||||
state->ev,
|
||||
timeout,
|
||||
fsp,
|
||||
&lck);
|
||||
if (tevent_req_nomem(subreq, state->req)) {
|
||||
TALLOC_FREE(lck);
|
||||
/* Reminder: returning != NULL means STOP traverse */
|
||||
return fsp;
|
||||
}
|
||||
if (tevent_req_is_in_progress(subreq)) {
|
||||
struct tevent_req *wait_subreq = NULL;
|
||||
|
||||
tevent_req_set_callback(
|
||||
subreq,
|
||||
smbXsrv_wait_for_handle_lease_break_done,
|
||||
state->req);
|
||||
|
||||
/*
|
||||
* This just adds a blocker that unblocks when subreq is
|
||||
* completed and goes away.
|
||||
*/
|
||||
wait_subreq = tevent_queue_wait_send(subreq,
|
||||
state->ev,
|
||||
state->wait_queue);
|
||||
if (wait_subreq == NULL) {
|
||||
exit_server("tevent_queue_wait_send failed");
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
status = delay_for_handle_lease_break_recv(subreq, state->req, &lck);
|
||||
TALLOC_FREE(subreq);
|
||||
TALLOC_FREE(lck);
|
||||
if (tevent_req_nterror(state->req, status)) {
|
||||
DBG_ERR("delay_for_handle_lease_break_recv failed %s\n",
|
||||
nt_errstr(status));
|
||||
return fsp;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void smbXsrv_wait_for_handle_lease_break_done(
|
||||
struct tevent_req *subreq)
|
||||
{
|
||||
struct tevent_req *req = tevent_req_callback_data(
|
||||
subreq, struct tevent_req);
|
||||
struct share_mode_lock *lck = NULL;
|
||||
NTSTATUS status;
|
||||
|
||||
status = delay_for_handle_lease_break_recv(subreq,
|
||||
req,
|
||||
&lck);
|
||||
TALLOC_FREE(subreq);
|
||||
TALLOC_FREE(lck);
|
||||
if (tevent_req_nterror(req, status)) {
|
||||
DBG_ERR("delay_for_handle_lease_break_recv failed %s\n",
|
||||
nt_errstr(status));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -107,4 +107,13 @@ struct tevent_req *smb2srv_session_close_previous_send(
|
||||
uint64_t current_session_id);
|
||||
NTSTATUS smb2srv_session_close_previous_recv(struct tevent_req *req);
|
||||
|
||||
void smbXsrv_wait_for_handle_lease_break(
|
||||
struct tevent_req *req,
|
||||
struct tevent_context *ev,
|
||||
struct smbXsrv_client *client,
|
||||
struct tevent_queue *wait_queue,
|
||||
bool (*fsp_cmp_fn)(struct files_struct *fsp,
|
||||
void *private_data),
|
||||
void *fsp_cmp_private_data);
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user