summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVolker Lendecke <vl@samba.org>2019-06-30 08:54:20 +0200
committerRalph Boehme <slow@samba.org>2019-07-04 14:03:29 +0000
commit0d4c4e045ec8a56289cb18b229b9a40104113608 (patch)
treeb9a13a9c358ecf1481d991a04291022bda9d4ff7
parent01428c55dd0440976a0a319823cf7bc6113f508a (diff)
downloadsamba-0d4c4e045ec8a56289cb18b229b9a40104113608.tar.gz
smbd: Add file_has_read_lease()
This caches share_mode_data->flags in the fsp, cache flush happening on tdb_seqnum change. Signed-off-by: Volker Lendecke <vl@samba.org> Reviewed-by: Ralph Boehme <slow@samba.org>
-rw-r--r--source3/include/vfs.h6
-rw-r--r--source3/locking/proto.h2
-rw-r--r--source3/locking/share_mode_lock.c66
3 files changed, 73 insertions, 1 deletions
diff --git a/source3/include/vfs.h b/source3/include/vfs.h
index a7ac50f06d2..4c778839880 100644
--- a/source3/include/vfs.h
+++ b/source3/include/vfs.h
@@ -375,6 +375,12 @@ typedef struct files_struct {
struct files_struct *base_fsp; /* placeholder for delete on close */
/*
+ * Cache of share_mode_data->flags
+ */
+ int share_mode_flags_seqnum;
+ uint8_t share_mode_flags;
+
+ /*
* Read-only cached brlock record, thrown away when the
* brlock.tdb seqnum changes. This avoids fetching data from
* the brlock.tdb on every read/write call.
diff --git a/source3/locking/proto.h b/source3/locking/proto.h
index 604d66ebd3a..a1c6529183a 100644
--- a/source3/locking/proto.h
+++ b/source3/locking/proto.h
@@ -126,6 +126,8 @@ struct share_mode_lock *get_share_mode_lock(
const struct smb_filename *smb_fname,
const struct timespec *old_write_time);
+bool file_has_read_lease(struct files_struct *fsp);
+
struct db_record;
NTSTATUS share_mode_do_locked(
struct file_id id,
diff --git a/source3/locking/share_mode_lock.c b/source3/locking/share_mode_lock.c
index 79a0580118f..430d14fab4a 100644
--- a/source3/locking/share_mode_lock.c
+++ b/source3/locking/share_mode_lock.c
@@ -77,7 +77,11 @@ static bool locking_init_internal(bool read_only)
backend = db_open(NULL, db_path,
SMB_OPEN_DATABASE_TDB_HASH_SIZE,
- TDB_DEFAULT|TDB_VOLATILE|TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH,
+ TDB_DEFAULT|
+ TDB_VOLATILE|
+ TDB_CLEAR_IF_FIRST|
+ TDB_INCOMPATIBLE_HASH|
+ TDB_SEQNUM,
read_only?O_RDONLY:O_RDWR|O_CREAT, 0644,
DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE);
TALLOC_FREE(db_path);
@@ -191,6 +195,66 @@ static enum ndr_err_code get_share_mode_blob_header(
return NDR_ERR_SUCCESS;
}
+struct fsp_update_share_mode_flags_state {
+ enum ndr_err_code ndr_err;
+ uint8_t share_mode_flags;
+};
+
+static void fsp_update_share_mode_flags_fn(
+ struct db_record *rec, bool *modified_dependent, void *private_data)
+{
+ struct fsp_update_share_mode_flags_state *state = private_data;
+ TDB_DATA value = dbwrap_record_get_value(rec);
+ DATA_BLOB blob = { .data = value.dptr, .length = value.dsize };
+ uint64_t seq;
+
+ state->ndr_err = get_share_mode_blob_header(
+ &blob, &seq, &state->share_mode_flags);
+}
+
+static NTSTATUS fsp_update_share_mode_flags(struct files_struct *fsp)
+{
+ struct fsp_update_share_mode_flags_state state = {0};
+ int seqnum = dbwrap_get_seqnum(lock_db);
+ NTSTATUS status;
+
+ if (seqnum == fsp->share_mode_flags_seqnum) {
+ return NT_STATUS_OK;
+ }
+
+ status = share_mode_do_locked(
+ fsp->file_id, fsp_update_share_mode_flags_fn, &state);
+ if (!NT_STATUS_IS_OK(status)) {
+ DBG_DEBUG("share_mode_do_locked returned %s\n",
+ nt_errstr(status));
+ return status;
+ }
+
+ if (!NDR_ERR_CODE_IS_SUCCESS(state.ndr_err)) {
+ DBG_DEBUG("get_share_mode_blob_header returned %s\n",
+ ndr_errstr(state.ndr_err));
+ return ndr_map_error2ntstatus(state.ndr_err);
+ }
+
+ fsp->share_mode_flags_seqnum = seqnum;
+ fsp->share_mode_flags = state.share_mode_flags;
+
+ return NT_STATUS_OK;
+}
+
+bool file_has_read_lease(struct files_struct *fsp)
+{
+ NTSTATUS status;
+
+ status = fsp_update_share_mode_flags(fsp);
+ if (!NT_STATUS_IS_OK(status)) {
+ /* Safe default for leases */
+ return true;
+ }
+
+ return (fsp->share_mode_flags & SHARE_MODE_HAS_READ_LEASE) != 0;
+}
+
static int share_mode_data_nofree_destructor(struct share_mode_data *d)
{
return -1;