summaryrefslogtreecommitdiff
path: root/source3/locking
diff options
context:
space:
mode:
authorVolker Lendecke <vl@samba.org>2019-08-13 22:07:47 +0200
committerJeremy Allison <jra@samba.org>2019-09-17 22:49:36 +0000
commitcc2e5b41646f6c18288ffb4b0ea16f4ea2cb4874 (patch)
tree1435330a00a0a40782e8f40d4de3987ce1aa2695 /source3/locking
parent8d63b622df42111b603d5f6fe2fa31490eb7cd98 (diff)
downloadsamba-cc2e5b41646f6c18288ffb4b0ea16f4ea2cb4874.tar.gz
smbd: Add quick leases_db_get_current_state()
Signed-off-by: Volker Lendecke <vl@samba.org> Reviewed-by: Jeremy Allison <jra@samba.org>
Diffstat (limited to 'source3/locking')
-rw-r--r--source3/locking/leases_db.c77
-rw-r--r--source3/locking/leases_db.h5
2 files changed, 81 insertions, 1 deletions
diff --git a/source3/locking/leases_db.c b/source3/locking/leases_db.c
index 17778050acc..b739d618c49 100644
--- a/source3/locking/leases_db.c
+++ b/source3/locking/leases_db.c
@@ -47,7 +47,10 @@ bool leases_db_init(bool read_only)
}
leases_db = db_open(NULL, db_path, 0,
- TDB_DEFAULT|TDB_VOLATILE|TDB_CLEAR_IF_FIRST|
+ TDB_DEFAULT|
+ TDB_VOLATILE|
+ TDB_CLEAR_IF_FIRST|
+ TDB_SEQNUM|
TDB_INCOMPATIBLE_HASH,
read_only ? O_RDONLY : O_RDWR|O_CREAT, 0644,
DBWRAP_LOCK_ORDER_2, DBWRAP_FLAG_NONE);
@@ -625,7 +628,79 @@ NTSTATUS leases_db_get(const struct GUID *client_guid,
return status;
}
return state.status;
+}
+
+struct leases_db_get_current_state_state {
+ int seqnum;
+ uint32_t current_state;
+ NTSTATUS status;
+};
+
+/*
+ * This function is an optimization that
+ * relies on the fact that the
+ * smb2_lease_state current_state
+ * (which is a uint32_t size)
+ * from struct leases_db_value is the first
+ * entry in the ndr-encoded struct leases_db_value.
+ * Read it without having to ndr decode all
+ * the values in struct leases_db_value.
+ */
+
+static void leases_db_get_current_state_fn(
+ TDB_DATA key, TDB_DATA data, void *private_data)
+{
+ struct leases_db_get_current_state_state *state = private_data;
+ struct ndr_pull ndr;
+ enum ndr_err_code ndr_err;
+
+ if (data.dsize < sizeof(uint32_t)) {
+ state->status = NT_STATUS_INTERNAL_DB_CORRUPTION;
+ return;
+ }
+
+ state->seqnum = dbwrap_get_seqnum(leases_db);
+
+ ndr = (struct ndr_pull) {
+ .data = data.dptr, .data_size = data.dsize,
+ };
+ ndr_err = ndr_pull_uint32(&ndr, NDR_SCALARS, &state->current_state);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ state->status = ndr_map_error2ntstatus(ndr_err);
+ }
+}
+NTSTATUS leases_db_get_current_state(
+ const struct GUID *client_guid,
+ const struct smb2_lease_key *lease_key,
+ int *database_seqnum,
+ uint32_t *current_state)
+{
+ struct leases_db_get_current_state_state state = { 0 };
+ struct leases_db_key_buf keybuf;
+ TDB_DATA db_key = { 0 };
+ NTSTATUS status;
+
+ if (!leases_db_init(true)) {
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+
+ state.seqnum = dbwrap_get_seqnum(leases_db);
+ if (*database_seqnum == state.seqnum) {
+ return NT_STATUS_OK;
+ }
+
+ db_key = leases_db_key(&keybuf, client_guid, lease_key);
+
+ status = dbwrap_parse_record(
+ leases_db, db_key, leases_db_get_current_state_fn, &state);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+ *database_seqnum = state.seqnum;
+ *current_state = state.current_state;
+
+ return NT_STATUS_OK;
}
NTSTATUS leases_db_copy_file_ids(TALLOC_CTX *mem_ctx,
diff --git a/source3/locking/leases_db.h b/source3/locking/leases_db.h
index 99a4a78315c..9c149c19f07 100644
--- a/source3/locking/leases_db.h
+++ b/source3/locking/leases_db.h
@@ -68,6 +68,11 @@ NTSTATUS leases_db_get(const struct GUID *client_guid,
uint32_t *breaking_to_required,
uint16_t *lease_version,
uint16_t *epoch);
+NTSTATUS leases_db_get_current_state(
+ const struct GUID *client_guid,
+ const struct smb2_lease_key *lease_key,
+ int *database_seqnum,
+ uint32_t *current_state);
NTSTATUS leases_db_copy_file_ids(TALLOC_CTX *mem_ctx,
uint32_t num_files,
const struct leases_db_file *files,