diff options
author | Volker Lendecke <vl@samba.org> | 2019-06-30 08:54:20 +0200 |
---|---|---|
committer | Ralph Boehme <slow@samba.org> | 2019-07-04 14:03:29 +0000 |
commit | 0d4c4e045ec8a56289cb18b229b9a40104113608 (patch) | |
tree | b9a13a9c358ecf1481d991a04291022bda9d4ff7 | |
parent | 01428c55dd0440976a0a319823cf7bc6113f508a (diff) | |
download | samba-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.h | 6 | ||||
-rw-r--r-- | source3/locking/proto.h | 2 | ||||
-rw-r--r-- | source3/locking/share_mode_lock.c | 66 |
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; |