[SCM] Samba Shared Repository - branch master updated

Ralph Böhme slow at samba.org
Thu Jul 4 15:41:02 UTC 2019


The branch, master has been updated
       via  4a9d46dafb3 s3: smbd: SMB1 add range checks to reply_fclose().
       via  522fe236124 s3: smbd: SMB1 add range checks to reply_search().
       via  173923c41ae vfs_nfs4acl_xattr: fix setting of permissions via NFS
       via  8bae5d82e2a smbd: Don't store num_read_oplocks in brlock.tdb
       via  2d7efba0d9d smbd: Use share_mode's flags in contend_level2_oplocks
       via  0e34096caea smbd: Set SHARE_MODE_HAS_READ_LEASE when downgrading an oplock
       via  ffd098d8bbd smbd: Set SHARE_MODE_HAS_READ_LEASE when granting a read lease
       via  0d4c4e045ec smbd: Add file_has_read_lease()
       via  01428c55dd0 smbd: Add flags to the beginning of share_mode_data
       via  c5659f7b052 smbd: Send do_lock() through share_mode_do_locked()
       via  44a77e6a5f9 smbd: Add share_mode_do_locked()
       via  0be81cda567 smbd: Introduce static_share_mode_record
       via  aabc97ebc92 smbd: Simplify share_mode_lock.c
       via  3b7b979ee98 dbwrap: Add publically available dbwrap_watch_wakeup()
       via  1920ebfda82 dbwrap: Rename dbwrap_watched_wakeup()
      from  eaebd8759b9 WHATSNEW: add news the sad passing of python2 support

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 4a9d46dafb32b02099e0d790c583876f412ac1c1
Author: Jeremy Allison <jra at samba.org>
Date:   Wed Jul 3 12:15:56 2019 -0700

    s3: smbd: SMB1 add range checks to reply_fclose().
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>
    
    Autobuild-User(master): Ralph Böhme <slow at samba.org>
    Autobuild-Date(master): Thu Jul  4 15:40:31 UTC 2019 on sn-devel-184

commit 522fe23612487995039cc1379caacdec001a5332
Author: Jeremy Allison <jra at samba.org>
Date:   Wed Jul 3 12:13:59 2019 -0700

    s3: smbd: SMB1 add range checks to reply_search().
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 173923c41aee6533532024ece8cd0fb62b06d316
Author: Bjoern Jacke <bjacke at samba.org>
Date:   Fri Jun 28 16:36:43 2019 +0200

    vfs_nfs4acl_xattr: fix setting of permissions via NFS
    
    via NFS root may not be priviledged user, so we should not call become_root()
    here. The normal NFS4 permissions already handle permission modify right, no
    need to do more magic things for Samba here.
    
    Signed-off-by: Bjoern Jacke <bjacke at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 8bae5d82e2a101d37f5572e1d174b37816576840
Author: Volker Lendecke <vl at samba.org>
Date:   Sun Jun 30 19:51:13 2019 +0200

    smbd: Don't store num_read_oplocks in brlock.tdb
    
    This removes a kludgy implementation that worked around a locking
    hierarchy problem: Setting a byte range lock had to contend the level2
    oplocks, which are stored in locking.tdb/leases.tdb. We could not
    access locking.tdb in the brlock.tdb code, as brlock.tdb might have
    been locked first without locking.tdb, violating the locking hierarchy
    locking.tdb->brlock.tdb. Now that that problem is gone (see the commit
    wrapping do_lock() in share_mode_do_locked()), we can remove this
    kludge.
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 2d7efba0d9dd212df127ffd697ff72fb30b72861
Author: Volker Lendecke <vl at samba.org>
Date:   Sun Jun 30 09:50:46 2019 +0200

    smbd: Use share_mode's flags in contend_level2_oplocks
    
    Here we traverse the oplocks and leases when breaking read leases. We
    find out here whether any of those are still left.
    
    As it's the receivers of the messages that downgrade the database
    entries, we might do that more than once. Possible future
    optimization?
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 0e34096caea40ef2d17aa229b5344818aa5a4baf
Author: Volker Lendecke <vl at samba.org>
Date:   Sun Jun 30 19:57:39 2019 +0200

    smbd: Set SHARE_MODE_HAS_READ_LEASE when downgrading an oplock
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit ffd098d8bbdcbcc6109aaa939c67bc6e9b306e42
Author: Volker Lendecke <vl at samba.org>
Date:   Sun Jun 30 09:15:48 2019 +0200

    smbd: Set SHARE_MODE_HAS_READ_LEASE when granting a read lease
    
    Lazy update of the flag: Whenever we add a read lease, we have to set
    the flag. Nobody except contend_level2_oplocks_begin will remove that
    flag again, as this would mean a full lease traverse when removing
    one. And contend_level2_oplocks_begin traverses the leases anyway
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 0d4c4e045ec8a56289cb18b229b9a40104113608
Author: Volker Lendecke <vl at samba.org>
Date:   Sun Jun 30 08:54:20 2019 +0200

    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 at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 01428c55dd0440976a0a319823cf7bc6113f508a
Author: Volker Lendecke <vl at samba.org>
Date:   Fri Jun 28 07:48:45 2019 +0200

    smbd: Add flags to the beginning of share_mode_data
    
    They are put at the beginning for easy parsing without reading the
    full struct. First step to remove the number of read oplocks/leases
    from brlock.tdb, where it does not belong.
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit c5659f7b05289d23efe0288702157c6b5442ed3d
Author: Volker Lendecke <vl at samba.org>
Date:   Mon Jul 1 15:56:27 2019 +0200

    smbd: Send do_lock() through share_mode_do_locked()
    
    We need to maintain the locking hierarchy locking.tdb->brlock.tdb at
    all times. vfs_fruit directly calls do_lock(), which might fail to
    maintain the locking hierarchy: In brlock.c we call
    contend_level2_oplocks_begin(), which will soon look at the
    locking.tdb record.
    
    For the SMB1 and SMB2 callers we already have the share mode locked,
    we might want to watch that record for unlocks. For those callers
    share_mode_do_locked() is practically free to call, we share the
    underlying db_record.
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 44a77e6a5f9cb8c051648eb8f6759aadf3596544
Author: Volker Lendecke <vl at samba.org>
Date:   Thu Jun 27 17:23:07 2019 +0200

    smbd: Add share_mode_do_locked()
    
    This is made for efficient locking of share mode records in
    locking.tdb. Right now we already need that when accessing leases.tdb,
    and soon it will be required for brlock.tdb as well. It does not give
    direct access to the parsed share mode entry, but the record is
    available for dbwrap_watched_wakeup() within downgrade_lease().
    
    It can be freely nested with get_share_mode_lock calls, the record
    will be shared and proper nesting should be checked.
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 0be81cda56788864f4a08aaa7e99746a6f61b1f1
Author: Volker Lendecke <vl at samba.org>
Date:   Thu Jun 27 16:58:54 2019 +0200

    smbd: Introduce static_share_mode_record
    
    The next commit will introduce share_mode_do_locked(), which allocates
    a share mode record on the stack. We have to expect nested
    get_share_mode_lock() calls from within share_mode_do_locked() for
    which we need to share a db_record.
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit aabc97ebc92f6b0977910a3125182e44ac4fdec9
Author: Volker Lendecke <vl at samba.org>
Date:   Thu Jun 27 14:40:08 2019 +0200

    smbd: Simplify share_mode_lock.c
    
    Do explicit refcounting instead of talloc_reference(). A later patch
    will introduce a share_mode_do_locked() routine that can be nested
    arbitrarily with get_share_mode_lock(). To do sanity checks for proper
    nesting, share_mode_do_locked needs to be aware of the reference
    counts for "static_share_mode_lock".
    
    Why is share_mode_memcache_delete() gone? In parse_share_modes() we
    already move the data out of the cache, share_mode_lock_destructor()
    we don't even bother re-adding the share_mode_data to the cache if
    it does not have share entries, because the next opener will invent a
    new seqnum anyway.
    
    Also: Less talloc_reference(), less lines of code.
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 3b7b979ee987e3561caec35b277abe74c996fa9c
Author: Volker Lendecke <vl at samba.org>
Date:   Fri May 24 15:00:45 2019 +0200

    dbwrap: Add publically available dbwrap_watch_wakeup()
    
    Without this, to notify watchers you need to actually store data. This
    might be a waste of resources. locking.tdb waiters might actually wait
    for leases.tdb or brlock.tdb changes, and locking.tdb records can be
    large.
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 1920ebfda82f12c4d77c21885084c36b40a4404f
Author: Volker Lendecke <vl at samba.org>
Date:   Fri May 24 14:49:47 2019 +0200

    dbwrap: Rename dbwrap_watched_wakeup()
    
    In the next step I want to make dbwrap_watched_wakeup() publically
    available under that canonical name.
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

-----------------------------------------------------------------------

Summary of changes:
 source3/include/vfs.h               |   6 +
 source3/lib/dbwrap/dbwrap_watch.c   |  29 ++-
 source3/lib/dbwrap/dbwrap_watch.h   |   8 +
 source3/librpc/idl/open_files.idl   |   5 +
 source3/locking/brlock.c            |  44 +---
 source3/locking/locking.c           |  82 ++++--
 source3/locking/proto.h             |  14 +-
 source3/locking/share_mode_lock.c   | 492 ++++++++++++++++++++++++------------
 source3/modules/vfs_nfs4acl_xattr.c |  31 ---
 source3/smbd/open.c                 |   6 +-
 source3/smbd/oplock.c               | 269 +++++---------------
 source3/smbd/proto.h                |   1 -
 source3/smbd/reply.c                |  23 ++
 13 files changed, 543 insertions(+), 467 deletions(-)


Changeset truncated at 500 lines:

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
@@ -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
diff --git a/source3/lib/dbwrap/dbwrap_watch.c b/source3/lib/dbwrap/dbwrap_watch.c
index c367efdd130..9bf3d372621 100644
--- a/source3/lib/dbwrap/dbwrap_watch.c
+++ b/source3/lib/dbwrap/dbwrap_watch.c
@@ -207,8 +207,8 @@ static NTSTATUS dbwrap_watched_storev(struct db_record *rec,
 				      const TDB_DATA *dbufs, int num_dbufs,
 				      int flags);
 static NTSTATUS dbwrap_watched_delete(struct db_record *rec);
-static void dbwrap_watched_wakeup(struct db_record *rec,
-				  struct dbwrap_watch_rec *wrec);
+static void dbwrap_watched_subrec_wakeup(
+	struct db_record *rec, struct db_watched_subrec *subrec);
 static NTSTATUS dbwrap_watched_save(struct db_record *rec,
 				    struct dbwrap_watch_rec *wrec,
 				    struct server_id *addwatch,
@@ -347,9 +347,10 @@ static NTSTATUS dbwrap_watched_do_locked(struct db_context *db, TDB_DATA key,
 	return state.status;
 }
 
-static void dbwrap_watched_wakeup(struct db_record *rec,
-				  struct dbwrap_watch_rec *wrec)
+static void dbwrap_watched_subrec_wakeup(
+	struct db_record *rec, struct db_watched_subrec *subrec)
 {
+	struct dbwrap_watch_rec *wrec = &subrec->wrec;
 	struct db_context *db = rec->db;
 	struct db_watched_ctx *ctx = talloc_get_type_abort(
 		db->private_data, struct db_watched_ctx);
@@ -451,7 +452,7 @@ static NTSTATUS dbwrap_watched_subrec_storev(
 {
 	NTSTATUS status;
 
-	dbwrap_watched_wakeup(rec, &subrec->wrec);
+	dbwrap_watched_subrec_wakeup(rec, subrec);
 
 	subrec->wrec.deleted = false;
 
@@ -478,7 +479,7 @@ static NTSTATUS dbwrap_watched_subrec_delete(
 {
 	NTSTATUS status;
 
-	dbwrap_watched_wakeup(rec, &subrec->wrec);
+	dbwrap_watched_subrec_wakeup(rec, subrec);
 
 	if (subrec->wrec.num_watchers == 0) {
 		return dbwrap_record_delete(subrec->subrec);
@@ -738,6 +739,22 @@ static size_t dbwrap_watched_id(struct db_context *db, uint8_t *id,
 	return dbwrap_db_id(ctx->backend, id, idlen);
 }
 
+void dbwrap_watched_wakeup(struct db_record *rec)
+{
+	struct db_watched_subrec *subrec = NULL;
+
+	if (rec->storev == dbwrap_watched_do_locked_storev) {
+		struct dbwrap_watched_do_locked_state *state =
+			rec->private_data;
+		subrec = &state->subrec;
+	} else {
+		subrec = talloc_get_type_abort(
+			rec->private_data, struct db_watched_subrec);
+	}
+
+	dbwrap_watched_subrec_wakeup(rec, subrec);
+}
+
 struct db_context *db_open_watched(TALLOC_CTX *mem_ctx,
 				   struct db_context **backend,
 				   struct messaging_context *msg)
diff --git a/source3/lib/dbwrap/dbwrap_watch.h b/source3/lib/dbwrap/dbwrap_watch.h
index a836ca48e8a..c380c434c85 100644
--- a/source3/lib/dbwrap/dbwrap_watch.h
+++ b/source3/lib/dbwrap/dbwrap_watch.h
@@ -35,4 +35,12 @@ NTSTATUS dbwrap_watched_watch_recv(struct tevent_req *req,
 				   bool *blockerdead,
 				   struct server_id *blocker);
 
+/*
+ * Wake up watchers without having modified the record value. One
+ * usecase at the time of this commit is: We have lease break waiters
+ * waiting on a locking.tdb record. They should be woken up when a
+ * lease is broken, which does not modify the locking.tdb record.
+ */
+void dbwrap_watched_wakeup(struct db_record *rec);
+
 #endif /* __DBWRAP_WATCH_H__ */
diff --git a/source3/librpc/idl/open_files.idl b/source3/librpc/idl/open_files.idl
index 04305e24164..bf832821b89 100644
--- a/source3/librpc/idl/open_files.idl
+++ b/source3/librpc/idl/open_files.idl
@@ -40,8 +40,13 @@ interface open_files
 		security_unix_token *delete_token;
 	} delete_token;
 
+	typedef [public,bitmap8bit] bitmap {
+		SHARE_MODE_HAS_READ_LEASE	= 0x01
+	} share_mode_flags;
+
 	typedef [public] struct {
 		hyper sequence_number;
+		share_mode_flags flags;
 		[string,charset(UTF8)] char *servicepath;
 		[string,charset(UTF8)] char *base_name;
 		[string,charset(UTF8)] char *stream_name;
diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c
index 75c020f57a6..cdfd09ceff1 100644
--- a/source3/locking/brlock.c
+++ b/source3/locking/brlock.c
@@ -48,7 +48,6 @@ struct byte_range_lock {
 	struct files_struct *fsp;
 	unsigned int num_locks;
 	bool modified;
-	uint32_t num_read_oplocks;
 	struct lock_struct *lock_data;
 	struct db_record *record;
 };
@@ -85,21 +84,6 @@ struct files_struct *brl_fsp(struct byte_range_lock *brl)
 	return brl->fsp;
 }
 
-uint32_t brl_num_read_oplocks(const struct byte_range_lock *brl)
-{
-	return brl->num_read_oplocks;
-}
-
-void brl_set_num_read_oplocks(struct byte_range_lock *brl,
-			      uint32_t num_read_oplocks)
-{
-	DEBUG(10, ("Setting num_read_oplocks to %"PRIu32"\n",
-		   num_read_oplocks));
-	SMB_ASSERT(brl->record != NULL); /* otherwise we're readonly */
-	brl->num_read_oplocks = num_read_oplocks;
-	brl->modified = true;
-}
-
 /****************************************************************************
  See if two locking contexts are equal.
 ****************************************************************************/
@@ -1652,7 +1636,7 @@ static void byte_range_lock_flush(struct byte_range_lock *br_lck)
 		}
 	}
 
-	if ((br_lck->num_locks == 0) && (br_lck->num_read_oplocks == 0)) {
+	if (br_lck->num_locks == 0) {
 		/* No locks - delete this entry. */
 		NTSTATUS status = dbwrap_record_delete(br_lck->record);
 		if (!NT_STATUS_IS_OK(status)) {
@@ -1661,25 +1645,13 @@ static void byte_range_lock_flush(struct byte_range_lock *br_lck)
 			smb_panic("Could not delete byte range lock entry");
 		}
 	} else {
-		size_t lock_len, data_len;
-		TDB_DATA data;
+		TDB_DATA data = {
+			.dsize = br_lck->num_locks * sizeof(struct lock_struct),
+			.dptr = (uint8_t *)br_lck->lock_data,
+		};
 		NTSTATUS status;
 
-		lock_len = br_lck->num_locks * sizeof(struct lock_struct);
-		data_len = lock_len + sizeof(br_lck->num_read_oplocks);
-
-		data.dsize = data_len;
-		data.dptr = talloc_array(talloc_tos(), uint8_t, data_len);
-		SMB_ASSERT(data.dptr != NULL);
-
-		if (lock_len > 0) {
-			memcpy(data.dptr, br_lck->lock_data, lock_len);
-		}
-		memcpy(data.dptr + lock_len, &br_lck->num_read_oplocks,
-		       sizeof(br_lck->num_read_oplocks));
-
 		status = dbwrap_record_store(br_lck->record, data, TDB_REPLACE);
-		TALLOC_FREE(data.dptr);
 		if (!NT_STATUS_IS_OK(status)) {
 			DEBUG(0, ("store returned %s\n", nt_errstr(status)));
 			smb_panic("Could not store byte range mode entry");
@@ -1706,8 +1678,7 @@ static bool brl_parse_data(struct byte_range_lock *br_lck, TDB_DATA data)
 	if (data.dsize == 0) {
 		return true;
 	}
-	if (data.dsize % sizeof(struct lock_struct) !=
-	    sizeof(br_lck->num_read_oplocks)) {
+	if (data.dsize % sizeof(struct lock_struct) != 0) {
 		DEBUG(1, ("Invalid data size: %u\n", (unsigned)data.dsize));
 		return false;
 	}
@@ -1720,8 +1691,6 @@ static bool brl_parse_data(struct byte_range_lock *br_lck, TDB_DATA data)
 		DEBUG(1, ("talloc_memdup failed\n"));
 		return false;
 	}
-	memcpy(&br_lck->num_read_oplocks, data.dptr + data_len,
-	       sizeof(br_lck->num_read_oplocks));
 	return true;
 }
 
@@ -1843,7 +1812,6 @@ struct byte_range_lock *brl_get_locks_readonly(files_struct *fsp)
 			return NULL;
 		}
 
-		br_lock->num_read_oplocks = 0;
 		br_lock->num_locks = 0;
 		br_lock->lock_data = NULL;
 
diff --git a/source3/locking/locking.c b/source3/locking/locking.c
index 6c69b0055dc..e173034165c 100644
--- a/source3/locking/locking.c
+++ b/source3/locking/locking.c
@@ -230,6 +230,47 @@ static void decrement_current_lock_count(files_struct *fsp,
  Utility function called by locking requests.
 ****************************************************************************/
 
+struct do_lock_state {
+	struct files_struct *fsp;
+	uint64_t smblctx;
+	uint64_t count;
+	uint64_t offset;
+	enum brl_type lock_type;
+	enum brl_flavour lock_flav;
+
+	struct server_id blocker_pid;
+	uint64_t blocker_smblctx;
+	NTSTATUS status;
+};
+
+static void do_lock_fn(
+	struct db_record *rec,
+	bool *modified_dependent,
+	void *private_data)
+{
+	struct do_lock_state *state = private_data;
+	struct byte_range_lock *br_lck = NULL;
+
+	br_lck = brl_get_locks(talloc_tos(), state->fsp);
+	if (br_lck == NULL) {
+		state->status = NT_STATUS_NO_MEMORY;
+		return;
+	}
+
+	state->status = brl_lock(
+		br_lck,
+		state->smblctx,
+		messaging_server_id(state->fsp->conn->sconn->msg_ctx),
+		state->offset,
+		state->count,
+		state->lock_type,
+		state->lock_flav,
+		&state->blocker_pid,
+		&state->blocker_smblctx);
+
+	TALLOC_FREE(br_lck);
+}
+
 NTSTATUS do_lock(files_struct *fsp,
 		 uint64_t smblctx,
 		 uint64_t count,
@@ -239,9 +280,14 @@ NTSTATUS do_lock(files_struct *fsp,
 		 struct server_id *pblocker_pid,
 		 uint64_t *psmblctx)
 {
-	struct byte_range_lock *br_lck = NULL;
-	struct server_id blocker_pid = { 0 };
-	uint64_t blocker_smblctx = 0;
+	struct do_lock_state state = {
+		.fsp = fsp,
+		.smblctx = smblctx,
+		.count = count,
+		.offset = offset,
+		.lock_type = lock_type,
+		.lock_flav = lock_flav,
+	};
 	NTSTATUS status;
 
 	/* silently return ok on print files as we don't do locking there */
@@ -271,36 +317,25 @@ NTSTATUS do_lock(files_struct *fsp,
 		  fsp_fnum_dbg(fsp),
 		  fsp_str_dbg(fsp));
 
-	br_lck = brl_get_locks(talloc_tos(), fsp);
-	if (!br_lck) {
-		return NT_STATUS_NO_MEMORY;
+	status = share_mode_do_locked(fsp->file_id, do_lock_fn, &state);
+	if (!NT_STATUS_IS_OK(status)) {
+		DBG_DEBUG("share_mode_do_locked returned %s\n",
+			  nt_errstr(status));
+		return status;
 	}
 
-	status = brl_lock(
-		br_lck,
-		smblctx,
-		messaging_server_id(fsp->conn->sconn->msg_ctx),
-		offset,
-		count,
-		lock_type,
-		lock_flav,
-		&blocker_pid,
-		&blocker_smblctx);
-
-	TALLOC_FREE(br_lck);
-
 	if (psmblctx != NULL) {
-		*psmblctx = blocker_smblctx;
+		*psmblctx = state.blocker_smblctx;
 	}
 	if (pblocker_pid != NULL) {
-		*pblocker_pid = blocker_pid;
+		*pblocker_pid = state.blocker_pid;
 	}
 
-	DBG_DEBUG("returning status=%s\n", nt_errstr(status));
+	DBG_DEBUG("returning status=%s\n", nt_errstr(state.status));
 
 	increment_current_lock_count(fsp, lock_flav);
 
-	return status;
+	return state.status;
 }
 
 /****************************************************************************
@@ -912,6 +947,7 @@ bool downgrade_share_oplock(struct share_mode_lock *lck, files_struct *fsp)
 	}
 
 	e->op_type = LEVEL_II_OPLOCK;
+	lck->data->flags |= SHARE_MODE_HAS_READ_LEASE;
 	lck->data->modified = True;
 	return True;
 }
diff --git a/source3/locking/proto.h b/source3/locking/proto.h
index 15826a9d4af..08d3f2c7ab8 100644
--- a/source3/locking/proto.h
+++ b/source3/locking/proto.h
@@ -30,9 +30,6 @@ void brl_shutdown(void);
 
 unsigned int brl_num_locks(const struct byte_range_lock *brl);
 struct files_struct *brl_fsp(struct byte_range_lock *brl);
-uint32_t brl_num_read_oplocks(const struct byte_range_lock *brl);
-void brl_set_num_read_oplocks(struct byte_range_lock *brl,
-			      uint32_t num_read_oplocks);
 
 NTSTATUS brl_lock_windows_default(struct byte_range_lock *br_lck,
 				  struct lock_struct *plock);
@@ -125,6 +122,17 @@ struct share_mode_lock *get_share_mode_lock(
 	const char *servicepath,
 	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,
+	void (*fn)(struct db_record *rec,
+		   bool *modified_dependent,
+		   void *private_data),
+	void *private_data);
+
 struct share_mode_lock *fetch_share_mode_unlocked(TALLOC_CTX *mem_ctx,
 						  struct file_id id);
 struct tevent_req *fetch_share_mode_send(TALLOC_CTX *mem_ctx,
diff --git a/source3/locking/share_mode_lock.c b/source3/locking/share_mode_lock.c
index 92902af3fe7..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);
@@ -147,20 +151,6 @@ static DATA_BLOB memcache_key(const struct file_id *id)
 	return data_blob_const((const void *)id, sizeof(*id));
 }
 
-static void share_mode_memcache_delete(struct share_mode_data *d)
-{
-	const DATA_BLOB key = memcache_key(&d->id);
-
-	DBG_DEBUG("deleting entry for file %s seq %"PRIx64" key %s\n",
-		  d->base_name,
-		  d->sequence_number,
-		  file_id_string(talloc_tos(), &d->id));
-
-	memcache_delete(NULL,
-			SHARE_MODE_LOCK_CACHE,
-			key);
-}
-
 static void share_mode_memcache_store(struct share_mode_data *d)
 {
 	const DATA_BLOB key = memcache_key(&d->id);
@@ -177,7 +167,8 @@ static void share_mode_memcache_store(struct share_mode_data *d)
 	/*
 	 * Ensure the memory going into the cache
 	 * doesn't have a destructor so it can be
-	 * cleanly freed by share_mode_memcache_delete().
+	 * cleanly evicted by the memcache LRU
+	 * mechanism.
 	 */
 	talloc_set_destructor(d, NULL);
 
@@ -192,17 +183,78 @@ static void share_mode_memcache_store(struct share_mode_data *d)
  * NB. We use ndr_pull_hyper on a stack-created
  * struct ndr_pull with no talloc allowed, as we
  * need this to be really fast as an ndr-peek into
- * the first 8 bytes of the blob.
+ * the first 9 bytes of the blob.
  */
 
-static enum ndr_err_code get_blob_sequence_number(DATA_BLOB *blob,
-						uint64_t *pseq)
+static enum ndr_err_code get_share_mode_blob_header(
+	DATA_BLOB *blob, uint64_t *pseq, uint8_t *pflags)
 {
 	struct ndr_pull ndr = {.data = blob->data, .data_size = blob->length};
 	NDR_CHECK(ndr_pull_hyper(&ndr, NDR_SCALARS, pseq));
+	NDR_CHECK(ndr_pull_uint8(&ndr, NDR_SCALARS, pflags));
 	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;
+	}


-- 
Samba Shared Repository



More information about the samba-cvs mailing list