#include "messages.h"
#include "util_tdb.h"
#include "../librpc/gen_ndr/ndr_open_files.h"
+#include "source3/lib/dbwrap/dbwrap_watch.h"
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_LOCKING
if (!posix_locking_init(read_only))
return False;
+ dbwrap_watch_db(lock_db, server_messaging_context());
+
return True;
}
Form a static locking key for a dev/inode pair.
******************************************************************/
-static TDB_DATA locking_key(const struct file_id *id, struct file_id *tmp)
+static TDB_DATA locking_key(const struct file_id *id)
{
- *tmp = *id;
- return make_tdb_data((const uint8_t *)tmp, sizeof(*tmp));
+ return make_tdb_data((const uint8_t *)id, sizeof(*id));
}
/*******************************************************************
const TDB_DATA dbuf)
{
struct share_mode_data *d;
- int i;
- struct server_id *pids;
- bool *pid_exists;
enum ndr_err_code ndr_err;
+ uint32_t i;
DATA_BLOB blob;
d = talloc(mem_ctx, struct share_mode_data);
ndr_err = ndr_pull_struct_blob(
&blob, d, d, (ndr_pull_flags_fn_t)ndr_pull_share_mode_data);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
- DEBUG(1, ("ndr_pull_share_mode_lock failed\n"));
+ DEBUG(1, ("ndr_pull_share_mode_lock failed: %s\n",
+ ndr_errstr(ndr_err)));
goto fail;
}
+ /*
+ * Initialize the values that are [skip] in the idl. The NDR code does
+ * not initialize them.
+ */
+
+ for (i=0; i<d->num_share_modes; i++) {
+ d->share_modes[i].stale = false;
+ }
d->modified = false;
d->fresh = false;
NDR_PRINT_DEBUG(share_mode_data, d);
}
- /*
- * Ensure that each entry has a real process attached.
- */
-
- pids = talloc_array(talloc_tos(), struct server_id,
- d->num_share_modes);
- if (pids == NULL) {
- DEBUG(0, ("talloc failed\n"));
- goto fail;
- }
- pid_exists = talloc_array(talloc_tos(), bool, d->num_share_modes);
- if (pid_exists == NULL) {
- DEBUG(0, ("talloc failed\n"));
- goto fail;
- }
-
- for (i=0; i<d->num_share_modes; i++) {
- pids[i] = d->share_modes[i].pid;
- }
- if (!serverids_exist(pids, d->num_share_modes, pid_exists)) {
- DEBUG(0, ("serverid_exists failed\n"));
- goto fail;
- }
-
- i = 0;
- while (i < d->num_share_modes) {
- struct share_mode_entry *e = &d->share_modes[i];
- if (!pid_exists[i]) {
- DEBUG(10, ("wipe non-existent pid %s\n",
- procid_str_static(&e->pid)));
- *e = d->share_modes[d->num_share_modes-1];
- d->num_share_modes -= 1;
- d->modified = True;
- continue;
- }
- i += 1;
- }
- TALLOC_FREE(pid_exists);
- TALLOC_FREE(pids);
return d;
fail:
TALLOC_FREE(d);
NDR_PRINT_DEBUG(share_mode_data, d);
}
+ remove_stale_share_mode_entries(d);
+
if (d->num_share_modes == 0) {
DEBUG(10, ("No used share mode found\n"));
return make_tdb_data(NULL, 0);
********************************************************************/
static struct share_mode_lock *get_share_mode_lock_internal(
- TALLOC_CTX *mem_ctx, const struct file_id id,
+ TALLOC_CTX *mem_ctx, struct file_id id,
const char *servicepath, const struct smb_filename *smb_fname,
const struct timespec *old_write_time)
{
struct share_mode_lock *lck;
struct share_mode_data *d;
- struct file_id tmp;
struct db_record *rec;
- TDB_DATA key = locking_key(&id, &tmp);
+ TDB_DATA key = locking_key(&id);
TDB_DATA value;
rec = dbwrap_fetch_locked(lock_db, mem_ctx, key);
}
if (d == NULL) {
- DEBUG(1, ("Could not get share mode lock\n"));
+ DEBUG(5, ("get_share_mode_lock_internal: "
+ "Could not get share mode lock\n"));
TALLOC_FREE(rec);
return NULL;
}
}
/*******************************************************************
- Get a share_mode_lock, Reference counted to allow nexted calls.
+ Get a share_mode_lock, Reference counted to allow nested calls.
********************************************************************/
struct share_mode_lock *get_share_mode_lock(
TALLOC_CTX *mem_ctx,
- const struct file_id id,
+ struct file_id id,
const char *servicepath,
const struct smb_filename *smb_fname,
const struct timespec *old_write_time)
return NULL;
}
+static void fetch_share_mode_unlocked_parser(
+ TDB_DATA key, TDB_DATA data, void *private_data)
+{
+ struct share_mode_lock *lck = talloc_get_type_abort(
+ private_data, struct share_mode_lock);
+
+ lck->data = parse_share_modes(lck, data);
+}
+
/*******************************************************************
Get a share_mode_lock without locking the database or reference
counting. Used by smbstatus to display existing share modes.
********************************************************************/
struct share_mode_lock *fetch_share_mode_unlocked(TALLOC_CTX *mem_ctx,
- const struct file_id id)
+ struct file_id id)
{
struct share_mode_lock *lck;
- struct file_id tmp;
- TDB_DATA key = locking_key(&id, &tmp);
- TDB_DATA data;
+ TDB_DATA key = locking_key(&id);
NTSTATUS status;
- status = dbwrap_fetch(lock_db, talloc_tos(), key, &data);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(3, ("Could not fetch share entry\n"));
- return NULL;
- }
- if (data.dptr == NULL) {
- return NULL;
- }
lck = talloc(mem_ctx, struct share_mode_lock);
if (lck == NULL) {
- TALLOC_FREE(data.dptr);
+ DEBUG(0, ("talloc failed\n"));
return NULL;
}
- lck->data = parse_share_modes(lck, data);
- TALLOC_FREE(data.dptr);
- if (lck->data == NULL) {
+ status = dbwrap_parse_record(
+ lock_db, key, fetch_share_mode_unlocked_parser, lck);
+ if (!NT_STATUS_IS_OK(status) ||
+ (lck->data == NULL)) {
TALLOC_FREE(lck);
return NULL;
}
DEBUG(1, ("ndr_pull_share_mode_lock failed\n"));
return 0;
}
+ if (DEBUGLEVEL > 10) {
+ DEBUG(11, ("parse_share_modes:\n"));
+ NDR_PRINT_DEBUG(share_mode_data, d);
+ }
for (i=0; i<d->num_share_modes; i++) {
state->fn(&d->share_modes[i],
d->servicepath, d->base_name,
return count;
}
}
+
+bool share_mode_cleanup_disconnected(struct file_id fid,
+ uint64_t open_persistent_id)
+{
+ bool ret = false;
+ TALLOC_CTX *frame = talloc_stackframe();
+ unsigned n;
+ struct share_mode_data *data;
+ struct share_mode_lock *lck;
+ bool ok;
+
+ lck = get_existing_share_mode_lock(frame, fid);
+ if (lck == NULL) {
+ DEBUG(5, ("share_mode_cleanup_disconnected: "
+ "Could not fetch share mode entry for %s\n",
+ file_id_string(frame, &fid)));
+ goto done;
+ }
+ data = lck->data;
+
+ for (n=0; n < data->num_share_modes; n++) {
+ struct share_mode_entry *entry = &data->share_modes[n];
+
+ if (!server_id_is_disconnected(&entry->pid)) {
+ DEBUG(5, ("share_mode_cleanup_disconnected: "
+ "file (file-id='%s', servicepath='%s', "
+ "base_name='%s%s%s') "
+ "is used by server %s ==> do not cleanup\n",
+ file_id_string(frame, &fid),
+ data->servicepath,
+ data->base_name,
+ (data->stream_name == NULL)
+ ? "" : "', stream_name='",
+ (data->stream_name == NULL)
+ ? "" : data->stream_name,
+ server_id_str(frame, &entry->pid)));
+ goto done;
+ }
+ if (open_persistent_id != entry->share_file_id) {
+ DEBUG(5, ("share_mode_cleanup_disconnected: "
+ "entry for file "
+ "(file-id='%s', servicepath='%s', "
+ "base_name='%s%s%s') "
+ "has share_file_id %llu but expected %llu"
+ "==> do not cleanup\n",
+ file_id_string(frame, &fid),
+ data->servicepath,
+ data->base_name,
+ (data->stream_name == NULL)
+ ? "" : "', stream_name='",
+ (data->stream_name == NULL)
+ ? "" : data->stream_name,
+ (unsigned long long)entry->share_file_id,
+ (unsigned long long)open_persistent_id));
+ goto done;
+ }
+ }
+
+ ok = brl_cleanup_disconnected(fid, open_persistent_id);
+ if (!ok) {
+ DEBUG(10, ("share_mode_cleanup_disconnected: "
+ "failed to clean up byte range locks associated "
+ "with file (file-id='%s', servicepath='%s', "
+ "base_name='%s%s%s') and open_persistent_id %llu "
+ "==> do not cleanup\n",
+ file_id_string(frame, &fid),
+ data->servicepath,
+ data->base_name,
+ (data->stream_name == NULL)
+ ? "" : "', stream_name='",
+ (data->stream_name == NULL)
+ ? "" : data->stream_name,
+ (unsigned long long)open_persistent_id));
+ goto done;
+ }
+
+ DEBUG(10, ("share_mode_cleanup_disconnected: "
+ "cleaning up %u entries for file "
+ "(file-id='%s', servicepath='%s', "
+ "base_name='%s%s%s') "
+ "from open_persistent_id %llu\n",
+ data->num_share_modes,
+ file_id_string(frame, &fid),
+ data->servicepath,
+ data->base_name,
+ (data->stream_name == NULL)
+ ? "" : "', stream_name='",
+ (data->stream_name == NULL)
+ ? "" : data->stream_name,
+ (unsigned long long)open_persistent_id));
+
+ data->num_share_modes = 0;
+ data->modified = true;
+
+ ret = true;
+done:
+ talloc_free(frame);
+ return ret;
+}