]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
smbd: Add file_has_read_lease()
authorVolker Lendecke <vl@samba.org>
Sun, 30 Jun 2019 06:54:20 +0000 (08:54 +0200)
committerRalph Boehme <slow@samba.org>
Thu, 4 Jul 2019 14:03:29 +0000 (14:03 +0000)
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>
source3/include/vfs.h
source3/locking/proto.h
source3/locking/share_mode_lock.c

index a7ac50f06d255313ed9a9fd7989c4018ea886609..4c778839880f2bffd07f9d63533667607b54e76d 100644 (file)
@@ -374,6 +374,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
index 604d66ebd3a9d390dd9df0ad9d0739e217132b97..a1c6529183ae69132d5fde4d484f2019635b9c0f 100644 (file)
@@ -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,
index 79a0580118f61a48499289a75a830ff77592a2f7..430d14fab4a1b89c22803d4ce56a688d9c1fd548 100644 (file)
@@ -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;