From: Volker Lendecke Date: Tue, 3 Nov 2020 12:25:57 +0000 (+0100) Subject: smbd: Move share_mode_cleanup_disonnected() to scavenger.c X-Git-Tag: samba-4.14.0rc1~670 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=13217e6eb9163abcbb9ff3bb4716fd1f453a2bf8;p=thirdparty%2Fsamba.git smbd: Move share_mode_cleanup_disonnected() to scavenger.c Reduce the complexity of share_mode_lock.c, scavenger.c is the only user of this routine. Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison --- diff --git a/source3/locking/share_mode_lock.c b/source3/locking/share_mode_lock.c index ad69ef7c6e2..f4f563ee37c 100644 --- a/source3/locking/share_mode_lock.c +++ b/source3/locking/share_mode_lock.c @@ -1572,224 +1572,6 @@ int share_entry_forall(int (*fn)(struct file_id fid, return share_mode_forall(share_entry_traverse_fn, &state); } -struct cleanup_disconnected_state { - struct share_mode_lock *lck; - uint64_t open_persistent_id; - size_t num_disconnected; - bool found_connected; -}; - -static bool cleanup_disconnected_lease(struct share_mode_entry *e, - void *private_data) -{ - struct cleanup_disconnected_state *state = private_data; - NTSTATUS status; - - status = leases_db_del( - &e->client_guid, &e->lease_key, &state->lck->data->id); - - if (!NT_STATUS_IS_OK(status)) { - DBG_DEBUG("leases_db_del failed: %s\n", - nt_errstr(status)); - } - - return false; -} - -static bool share_mode_find_connected_fn( - struct share_mode_entry *e, - bool *modified, - void *private_data) -{ - struct cleanup_disconnected_state *state = private_data; - struct share_mode_data *d = state->lck->data; - bool disconnected; - - disconnected = server_id_is_disconnected(&e->pid); - if (!disconnected) { - struct file_id_buf tmp1; - struct server_id_buf tmp2; - DBG_INFO("file (file-id='%s', servicepath='%s', " - "base_name='%s%s%s') " - "is used by server %s ==> do not cleanup\n", - file_id_str_buf(d->id, &tmp1), - d->servicepath, - d->base_name, - (d->stream_name == NULL) - ? "" : "', stream_name='", - (d->stream_name == NULL) - ? "" : d->stream_name, - server_id_str_buf(e->pid, &tmp2)); - state->found_connected = true; - return true; - } - - if (state->open_persistent_id != e->share_file_id) { - struct file_id_buf tmp; - DBG_INFO("entry for file " - "(file-id='%s', servicepath='%s', " - "base_name='%s%s%s') " - "has share_file_id %"PRIu64" but expected " - "%"PRIu64"==> do not cleanup\n", - file_id_str_buf(d->id, &tmp), - d->servicepath, - d->base_name, - (d->stream_name == NULL) - ? "" : "', stream_name='", - (d->stream_name == NULL) - ? "" : d->stream_name, - e->share_file_id, - state->open_persistent_id); - state->found_connected = true; - return true; - } - - state->num_disconnected += 1; - - return false; -} - -static bool cleanup_disconnected_share_mode_entry_fn( - struct share_mode_entry *e, - bool *modified, - void *private_data) -{ - struct cleanup_disconnected_state *state = private_data; - struct share_mode_data *d = state->lck->data; - - bool disconnected; - - disconnected = server_id_is_disconnected(&e->pid); - if (!disconnected) { - struct file_id_buf tmp1; - struct server_id_buf tmp2; - DBG_ERR("file (file-id='%s', servicepath='%s', " - "base_name='%s%s%s') " - "is used by server %s ==> internal error\n", - file_id_str_buf(d->id, &tmp1), - d->servicepath, - d->base_name, - (d->stream_name == NULL) - ? "" : "', stream_name='", - (d->stream_name == NULL) - ? "" : d->stream_name, - server_id_str_buf(e->pid, &tmp2)); - smb_panic(__location__); - } - - /* - * Setting e->stale = true is - * the indication to delete the entry. - */ - e->stale = true; - return false; -} - -bool share_mode_cleanup_disconnected(struct file_id fid, - uint64_t open_persistent_id) -{ - struct cleanup_disconnected_state state = { - .open_persistent_id = open_persistent_id - }; - struct share_mode_data *data; - bool ret = false; - TALLOC_CTX *frame = talloc_stackframe(); - struct file_id_buf idbuf; - bool ok; - - state.lck = get_existing_share_mode_lock(frame, fid); - if (state.lck == NULL) { - DBG_INFO("Could not fetch share mode entry for %s\n", - file_id_str_buf(fid, &idbuf)); - goto done; - } - data = state.lck->data; - - ok = share_mode_forall_entries( - state.lck, share_mode_find_connected_fn, &state); - if (!ok) { - DBG_DEBUG("share_mode_forall_entries failed\n"); - goto done; - } - if (state.found_connected) { - DBG_DEBUG("Found connected entry\n"); - goto done; - } - - ok = share_mode_forall_leases( - state.lck, cleanup_disconnected_lease, &state); - if (!ok) { - DBG_DEBUG("failed to clean up leases associated " - "with file (file-id='%s', servicepath='%s', " - "base_name='%s%s%s') and open_persistent_id %"PRIu64" " - "==> do not cleanup\n", - file_id_str_buf(fid, &idbuf), - data->servicepath, - data->base_name, - (data->stream_name == NULL) - ? "" : "', stream_name='", - (data->stream_name == NULL) - ? "" : data->stream_name, - open_persistent_id); - goto done; - } - - ok = brl_cleanup_disconnected(fid, open_persistent_id); - if (!ok) { - DBG_DEBUG("failed to clean up byte range locks associated " - "with file (file-id='%s', servicepath='%s', " - "base_name='%s%s%s') and open_persistent_id %"PRIu64" " - "==> do not cleanup\n", - file_id_str_buf(fid, &idbuf), - data->servicepath, - data->base_name, - (data->stream_name == NULL) - ? "" : "', stream_name='", - (data->stream_name == NULL) - ? "" : data->stream_name, - open_persistent_id); - goto done; - } - - DBG_DEBUG("cleaning up %zu entries for file " - "(file-id='%s', servicepath='%s', " - "base_name='%s%s%s') " - "from open_persistent_id %"PRIu64"\n", - state.num_disconnected, - file_id_str_buf(fid, &idbuf), - data->servicepath, - data->base_name, - (data->stream_name == NULL) - ? "" : "', stream_name='", - (data->stream_name == NULL) - ? "" : data->stream_name, - open_persistent_id); - - ok = share_mode_forall_entries( - state.lck, cleanup_disconnected_share_mode_entry_fn, &state); - if (!ok) { - DBG_DEBUG("failed to clean up %zu entries associated " - "with file (file-id='%s', servicepath='%s', " - "base_name='%s%s%s') and open_persistent_id %"PRIu64" " - "==> do not cleanup\n", - state.num_disconnected, - file_id_str_buf(fid, &idbuf), - data->servicepath, - data->base_name, - (data->stream_name == NULL) - ? "" : "', stream_name='", - (data->stream_name == NULL) - ? "" : data->stream_name, - open_persistent_id); - goto done; - } - - ret = true; -done: - talloc_free(frame); - return ret; -} - static int share_mode_entry_cmp( struct server_id pid1, uint64_t share_file_id1, diff --git a/source3/locking/share_mode_lock.h b/source3/locking/share_mode_lock.h index 644f2bda9e3..734db6fd6f4 100644 --- a/source3/locking/share_mode_lock.h +++ b/source3/locking/share_mode_lock.h @@ -71,9 +71,6 @@ int share_entry_forall( const struct share_mode_entry *entry, void *private_data), void *private_data); -bool share_mode_cleanup_disconnected( - struct file_id fid, - uint64_t open_persistent_id); NTSTATUS share_mode_count_entries(struct file_id fid, size_t *num_share_modes); NTSTATUS share_mode_do_locked( diff --git a/source3/smbd/scavenger.c b/source3/smbd/scavenger.c index a24a5d7ccb9..ef34cdc41f9 100644 --- a/source3/smbd/scavenger.c +++ b/source3/smbd/scavenger.c @@ -24,7 +24,9 @@ #include "smbd/globals.h" #include "smbd/scavenger.h" #include "locking/share_mode_lock.h" +#include "locking/leases_db.h" #include "locking/proto.h" +#include "librpc/gen_ndr/open_files.h" #include "lib/util/server_id.h" #include "lib/util/util_process.h" #include "lib/util/sys_rw_data.h" @@ -464,6 +466,224 @@ struct scavenger_timer_context { struct scavenger_message msg; }; +struct cleanup_disconnected_state { + struct share_mode_lock *lck; + uint64_t open_persistent_id; + size_t num_disconnected; + bool found_connected; +}; + +static bool cleanup_disconnected_lease(struct share_mode_entry *e, + void *private_data) +{ + struct cleanup_disconnected_state *state = private_data; + NTSTATUS status; + + status = leases_db_del( + &e->client_guid, &e->lease_key, &state->lck->data->id); + + if (!NT_STATUS_IS_OK(status)) { + DBG_DEBUG("leases_db_del failed: %s\n", + nt_errstr(status)); + } + + return false; +} + +static bool share_mode_find_connected_fn( + struct share_mode_entry *e, + bool *modified, + void *private_data) +{ + struct cleanup_disconnected_state *state = private_data; + struct share_mode_data *d = state->lck->data; + bool disconnected; + + disconnected = server_id_is_disconnected(&e->pid); + if (!disconnected) { + struct file_id_buf tmp1; + struct server_id_buf tmp2; + DBG_INFO("file (file-id='%s', servicepath='%s', " + "base_name='%s%s%s') " + "is used by server %s ==> do not cleanup\n", + file_id_str_buf(d->id, &tmp1), + d->servicepath, + d->base_name, + (d->stream_name == NULL) + ? "" : "', stream_name='", + (d->stream_name == NULL) + ? "" : d->stream_name, + server_id_str_buf(e->pid, &tmp2)); + state->found_connected = true; + return true; + } + + if (state->open_persistent_id != e->share_file_id) { + struct file_id_buf tmp; + DBG_INFO("entry for file " + "(file-id='%s', servicepath='%s', " + "base_name='%s%s%s') " + "has share_file_id %"PRIu64" but expected " + "%"PRIu64"==> do not cleanup\n", + file_id_str_buf(d->id, &tmp), + d->servicepath, + d->base_name, + (d->stream_name == NULL) + ? "" : "', stream_name='", + (d->stream_name == NULL) + ? "" : d->stream_name, + e->share_file_id, + state->open_persistent_id); + state->found_connected = true; + return true; + } + + state->num_disconnected += 1; + + return false; +} + +static bool cleanup_disconnected_share_mode_entry_fn( + struct share_mode_entry *e, + bool *modified, + void *private_data) +{ + struct cleanup_disconnected_state *state = private_data; + struct share_mode_data *d = state->lck->data; + + bool disconnected; + + disconnected = server_id_is_disconnected(&e->pid); + if (!disconnected) { + struct file_id_buf tmp1; + struct server_id_buf tmp2; + DBG_ERR("file (file-id='%s', servicepath='%s', " + "base_name='%s%s%s') " + "is used by server %s ==> internal error\n", + file_id_str_buf(d->id, &tmp1), + d->servicepath, + d->base_name, + (d->stream_name == NULL) + ? "" : "', stream_name='", + (d->stream_name == NULL) + ? "" : d->stream_name, + server_id_str_buf(e->pid, &tmp2)); + smb_panic(__location__); + } + + /* + * Setting e->stale = true is + * the indication to delete the entry. + */ + e->stale = true; + return false; +} + +static bool share_mode_cleanup_disconnected( + struct file_id fid, uint64_t open_persistent_id) +{ + struct cleanup_disconnected_state state = { + .open_persistent_id = open_persistent_id + }; + struct share_mode_data *data; + bool ret = false; + TALLOC_CTX *frame = talloc_stackframe(); + struct file_id_buf idbuf; + bool ok; + + state.lck = get_existing_share_mode_lock(frame, fid); + if (state.lck == NULL) { + DBG_INFO("Could not fetch share mode entry for %s\n", + file_id_str_buf(fid, &idbuf)); + goto done; + } + data = state.lck->data; + + ok = share_mode_forall_entries( + state.lck, share_mode_find_connected_fn, &state); + if (!ok) { + DBG_DEBUG("share_mode_forall_entries failed\n"); + goto done; + } + if (state.found_connected) { + DBG_DEBUG("Found connected entry\n"); + goto done; + } + + ok = share_mode_forall_leases( + state.lck, cleanup_disconnected_lease, &state); + if (!ok) { + DBG_DEBUG("failed to clean up leases associated " + "with file (file-id='%s', servicepath='%s', " + "base_name='%s%s%s') and open_persistent_id %"PRIu64" " + "==> do not cleanup\n", + file_id_str_buf(fid, &idbuf), + data->servicepath, + data->base_name, + (data->stream_name == NULL) + ? "" : "', stream_name='", + (data->stream_name == NULL) + ? "" : data->stream_name, + open_persistent_id); + goto done; + } + + ok = brl_cleanup_disconnected(fid, open_persistent_id); + if (!ok) { + DBG_DEBUG("failed to clean up byte range locks associated " + "with file (file-id='%s', servicepath='%s', " + "base_name='%s%s%s') and open_persistent_id %"PRIu64" " + "==> do not cleanup\n", + file_id_str_buf(fid, &idbuf), + data->servicepath, + data->base_name, + (data->stream_name == NULL) + ? "" : "', stream_name='", + (data->stream_name == NULL) + ? "" : data->stream_name, + open_persistent_id); + goto done; + } + + DBG_DEBUG("cleaning up %zu entries for file " + "(file-id='%s', servicepath='%s', " + "base_name='%s%s%s') " + "from open_persistent_id %"PRIu64"\n", + state.num_disconnected, + file_id_str_buf(fid, &idbuf), + data->servicepath, + data->base_name, + (data->stream_name == NULL) + ? "" : "', stream_name='", + (data->stream_name == NULL) + ? "" : data->stream_name, + open_persistent_id); + + ok = share_mode_forall_entries( + state.lck, cleanup_disconnected_share_mode_entry_fn, &state); + if (!ok) { + DBG_DEBUG("failed to clean up %zu entries associated " + "with file (file-id='%s', servicepath='%s', " + "base_name='%s%s%s') and open_persistent_id %"PRIu64" " + "==> do not cleanup\n", + state.num_disconnected, + file_id_str_buf(fid, &idbuf), + data->servicepath, + data->base_name, + (data->stream_name == NULL) + ? "" : "', stream_name='", + (data->stream_name == NULL) + ? "" : data->stream_name, + open_persistent_id); + goto done; + } + + ret = true; +done: + talloc_free(frame); + return ret; +} + static void scavenger_timer(struct tevent_context *ev, struct tevent_timer *te, struct timeval t, void *data)