The branch, master has been updated via 8a05d2b074d smbd: Move lease type detection in delay_for_oplock() via 9a11f361cc1 smbd: Merge grant_fsp_oplock_type() into delay_for_oplock() via 7a6fa34130e smbd: Move delay_for_oplock() down via a4192bc70d7 smbd: Make delay_for_oplock() return NTSTATUS via 10679b67d13 smbd: Slightly simplify grant_fsp_oplock_type() via d1cb71fa500 smbd: Slightly simplify delay_for_oplock() via 385a7fb196f smbd: Introduce handle_share_mode_lease() via d4e98b8ae5f smbd: Move set_share_mode() out of grant_fsp_oplock_type() via 5c6163d3e66 smbd: Move grant_fsp_oplock_type() close to delay_for_oplock() via 3ecfa36e777 smbd: Slightly simplify open_file_ntcreate() via 3bd7b119e68 smbd: Remove a late ref to "file_existed" in open_file_ntcreate() via f8fe0116c11 smbd: Move resetting "oplock_request" to before delay_for_oplock() via 002c6d0efb7 smbd: For kernel-oplocked files don't call delay_for_oplock() via 706f0af2e4b smbd: Optionally wait for a share mode record in setup_poll_open() via 4d6f89c9883 smbd: Simplify has_other_nonposix_opens() via 6be8057317a smbd: Align integer types via 28868d24576 smbd: Simplify delay_for_oplock() via 021e2d01e68 smbd: Move is_same_lease() up in the file via 71c9fd73d42 smbd: Simplify is_same_lease() via 9034cb39d7c smbd: Optimize delay_for_oplock() via 38463a91aaf lib: Remove a duplicate function prototype via aeb4265ec2f smbd: Remove a misleading comment via d09bd5f8fd4 smbd: Merge two DEBUGs into one via 13fb42ac400 smbd: Avoid casts in share_conflict() via a0b0ea8f356 smbd: Save two lines in find_share_mode_entry via 58b5bfba11a lib: Micro-optimization for db_tdb_do_locked() from 7d96ed63226 third_party: Remove historical tombstone about zlib divergance
https://git.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 8a05d2b074d588a481aa372f2923f55cfb3e3a23 Author: Volker Lendecke <v...@samba.org> Date: Tue Aug 13 16:56:58 2019 +0200 smbd: Move lease type detection in delay_for_oplock() Walk the share_modes array only once. Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> Autobuild-User(master): Jeremy Allison <j...@samba.org> Autobuild-Date(master): Tue Aug 20 00:33:12 UTC 2019 on sn-devel-184 commit 9a11f361cc19d3b8da3469424697486d0fd8dd6d Author: Volker Lendecke <v...@samba.org> Date: Sat Aug 10 21:23:24 2019 +0200 smbd: Merge grant_fsp_oplock_type() into delay_for_oplock() This is a preparation for the next commit: Only walk the share_modes[] array once when handling oplocks and leases. Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit 7a6fa34130e8e6bea4672d08637af49097654119 Author: Volker Lendecke <v...@samba.org> Date: Sat Aug 10 21:17:05 2019 +0200 smbd: Move delay_for_oplock() down We'll merge grant_fsp_oplock_type() into this function. This makes the next commit smaller, and the newly extended delay_for_oplocks will for example reference static file_has_brlocks() above. Make forward declarations unnecessary. Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit a4192bc70d7717a5072ccdd8e53b7dda7e6d9c98 Author: Volker Lendecke <v...@samba.org> Date: Sat Aug 10 21:15:22 2019 +0200 smbd: Make delay_for_oplock() return NTSTATUS A further commit will merge grant_fsp_oplock_type (returning NTSTATUS) into delay_for_oplock(). Make that commit smaller. Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit 10679b67d1372bde37a1cdd639bebcc5f79a9c1b Author: Volker Lendecke <v...@samba.org> Date: Fri Aug 9 13:39:34 2019 +0200 smbd: Slightly simplify grant_fsp_oplock_type() This is never called with INTERNAL_OPENs anymore Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit d1cb71fa500ede015600ace58411c857b051794e Author: Volker Lendecke <v...@samba.org> Date: Fri Aug 9 13:38:40 2019 +0200 smbd: Slightly simplify delay_for_oplock() This is never called for INTERNAL_OPENs anymore, see handle_share_mode_lease() Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit 385a7fb196f7a6bdcdeb74b6e8553da7c810c1ca Author: Volker Lendecke <v...@samba.org> Date: Wed Aug 7 12:15:45 2019 +0200 smbd: Introduce handle_share_mode_lease() This consolidates the core share_mode_lock access of open_file_ntcreate into one routine. Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit d4e98b8ae5f08d6e332b15d868e7bf85995974f3 Author: Volker Lendecke <v...@samba.org> Date: Tue Aug 6 16:28:29 2019 +0200 smbd: Move set_share_mode() out of grant_fsp_oplock_type() This shows that "req", "share_access" and "access_mask" are not needed for the core logic of grant_fsp_oplock_type() and it separates concerns a bit: open_directory() also does the set_share_mode() in the main open routine, not in a helper like grant_fsp_oplock_type() Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit 5c6163d3e664c20034fb41969e886372e3c88aa6 Author: Volker Lendecke <v...@samba.org> Date: Thu Jul 25 16:31:17 2019 +0200 smbd: Move grant_fsp_oplock_type() close to delay_for_oplock() Note that this is not a cut&paste: Instead of fsp->access_mask we use the access_mask the client requested. At the new code location fsp->access_mask (a.k.a. open_access_mask) might have FILE_WRITE_DATA from O_TRUNC (a.k.a. FILE_OVERWRITE). Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit 3ecfa36e777cf377a4ae06644b0880fef4867452 Author: Volker Lendecke <v...@samba.org> Date: Fri Aug 2 15:24:16 2019 +0200 smbd: Slightly simplify open_file_ntcreate() There is no reference to "file_existed" after this point anymore Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit 3bd7b119e6882aee04badc92f2ddbcbc1964c115 Author: Volker Lendecke <v...@samba.org> Date: Fri Aug 2 15:21:49 2019 +0200 smbd: Remove a late ref to "file_existed" in open_file_ntcreate() If you follow "existing_dos_attributes" through the routine, this can only ever be !=0 if SMB_VFS_GET_DOS_ATTRIBUTES() was successful. This can only have been successful if the file existed. Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit f8fe0116c1158d8fdf0401ca46e8f12b84c04738 Author: Volker Lendecke <v...@samba.org> Date: Thu Jul 25 11:52:21 2019 +0200 smbd: Move resetting "oplock_request" to before delay_for_oplock() It seems to make little sense to me to do the oplock break with one setting and then later on grant_fsp_oplock_type with another one. Survives tests, I can't think of any scenario where this (to me) simplification would break anything Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit 002c6d0efb7bb41c158fc9056a176c5cce72f393 Author: Volker Lendecke <v...@samba.org> Date: Sun Aug 18 08:57:38 2019 +0200 smbd: For kernel-oplocked files don't call delay_for_oplock() The kernel has already sent the signal. We don't have to send another message. Instead, just directly wait for the downgrade to happen via the watch on the share mode lock assuming it's there. Also setup the polling interval: I could imagine that in some race situation the file has already been closed and re-opened by a nonsamba process while we were waiting. Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit 706f0af2e4b5012644da742c94fc12eb756054fd Author: Volker Lendecke <v...@samba.org> Date: Sun Aug 18 08:55:14 2019 +0200 smbd: Optionally wait for a share mode record in setup_poll_open() This will be used when waiting for a oplock break that has been signalled via a kernel oplock break. Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit 4d6f89c9883abaf7e9152887b7fa13449579c09c Author: Volker Lendecke <v...@samba.org> Date: Wed Aug 14 21:27:53 2019 +0200 smbd: Simplify has_other_nonposix_opens() We pick quite some information from "fsp" already, so from an API design perspecitve it's only fair to only use its implicit server_id. This is what all the callers did anyway. Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Ralph Böhme <s...@samba.org> commit 6be8057317a05b247169b8a30f968d1d2c085562 Author: Volker Lendecke <v...@samba.org> Date: Wed Aug 14 21:39:50 2019 +0200 smbd: Align integer types Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Ralph Böhme <s...@samba.org> commit 28868d24576dbd437329b7a59104cb7c15ee4624 Author: Volker Lendecke <v...@samba.org> Date: Sat Aug 10 15:01:24 2019 +0200 smbd: Simplify delay_for_oplock() Use is_same_lease() Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Ralph Böhme <s...@samba.org> commit 021e2d01e68714556bd811ff2bc2a04c71a6c1fd Author: Volker Lendecke <v...@samba.org> Date: Sat Aug 10 15:01:00 2019 +0200 smbd: Move is_same_lease() up in the file The next commit will need it there Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Ralph Böhme <s...@samba.org> commit 71c9fd73d42e092cf65de25fb7773fc1395ff601 Author: Volker Lendecke <v...@samba.org> Date: Sat Aug 10 14:28:51 2019 +0200 smbd: Simplify is_same_lease() It does not use "struct share_mode_data" Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Ralph Böhme <s...@samba.org> commit 9034cb39d7c0d8d6387f4977f894349db187d6b5 Author: Volker Lendecke <v...@samba.org> Date: Sat Aug 10 14:44:08 2019 +0200 smbd: Optimize delay_for_oplock() get_lease_type() can involve a database access. Do that only if necessary, and that is at most once in this loop. Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Ralph Böhme <s...@samba.org> commit 38463a91aafa2643551b4e4508c3e575d9e914a1 Author: Volker Lendecke <v...@samba.org> Date: Sat Aug 10 16:45:30 2019 +0200 lib: Remove a duplicate function prototype Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Ralph Böhme <s...@samba.org> commit aeb4265ec2f5d75250b1bc4d884628426df28dca Author: Volker Lendecke <v...@samba.org> Date: Fri Aug 9 13:48:53 2019 +0200 smbd: Remove a misleading comment open_mode_check() is done before the oplock breaks. Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Ralph Böhme <s...@samba.org> commit d09bd5f8fd4b2de28efcefc5839bd69bb088b88f Author: Volker Lendecke <v...@samba.org> Date: Mon Aug 12 12:12:48 2019 +0200 smbd: Merge two DEBUGs into one This looks easier to understand to me, less lines in logfiles Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Ralph Böhme <s...@samba.org> commit 13fb42ac40067d1b335511e48354169ee15f29b3 Author: Volker Lendecke <v...@samba.org> Date: Mon Aug 12 11:44:39 2019 +0200 smbd: Avoid casts in share_conflict() Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Ralph Böhme <s...@samba.org> commit a0b0ea8f356ac3a788d7b33d249ed6ec3eecc4bb Author: Volker Lendecke <v...@samba.org> Date: Sat Aug 10 22:15:05 2019 +0200 smbd: Save two lines in find_share_mode_entry Directly initialized variables give compilers less reason to complain Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Ralph Böhme <s...@samba.org> commit 58b5bfba11a66d250267efe901dfba76f82005f8 Author: Volker Lendecke <v...@samba.org> Date: Tue Aug 13 14:43:08 2019 +0200 lib: Micro-optimization for db_tdb_do_locked() We don't need the tdb lock for the talloc_free(buf) anymore Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Ralph Böhme <s...@samba.org> ----------------------------------------------------------------------- Summary of changes: lib/dbwrap/dbwrap_tdb.c | 4 +- lib/util/idtree.h | 5 - source3/locking/locking.c | 4 +- source3/smbd/close.c | 12 +- source3/smbd/open.c | 654 ++++++++++++++++++++++++---------------------- source3/smbd/proto.h | 3 +- source3/smbd/trans2.c | 3 +- 7 files changed, 346 insertions(+), 339 deletions(-) Changeset truncated at 500 lines: diff --git a/lib/dbwrap/dbwrap_tdb.c b/lib/dbwrap/dbwrap_tdb.c index 00d283c66e6..eb08a01a161 100644 --- a/lib/dbwrap/dbwrap_tdb.c +++ b/lib/dbwrap/dbwrap_tdb.c @@ -218,10 +218,10 @@ static NTSTATUS db_tdb_do_locked(struct db_context *db, TDB_DATA key, fn(&rec, private_data); - talloc_free(buf); - tdb_chainunlock(ctx->wtdb->tdb, key); + talloc_free(buf); + return NT_STATUS_OK; } diff --git a/lib/util/idtree.h b/lib/util/idtree.h index e7864a86968..79d2d8cd260 100644 --- a/lib/util/idtree.h +++ b/lib/util/idtree.h @@ -50,11 +50,6 @@ int idr_get_new(struct idr_context *idp, void *ptr, int limit); */ int idr_get_new_above(struct idr_context *idp, void *ptr, int starting_id, int limit); -/** - allocate a new id randomly in the given range -*/ -int idr_get_new_random(struct idr_context *idp, void *ptr, int limit); - /** find a pointer value previously set with idr_get_new given an id */ diff --git a/source3/locking/locking.c b/source3/locking/locking.c index c19b899e468..113f63476e4 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -836,11 +836,9 @@ static struct share_mode_entry *find_share_mode_entry( struct share_mode_lock *lck, files_struct *fsp) { struct share_mode_data *d = lck->data; - struct server_id pid; + struct server_id pid = messaging_server_id(fsp->conn->sconn->msg_ctx); uint32_t i; - pid = messaging_server_id(fsp->conn->sconn->msg_ctx); - for (i=0; i<d->num_share_modes; i++) { struct share_mode_entry *e = &d->share_modes[i]; diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 04c19cf32c0..12d7f8c9a95 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -166,7 +166,7 @@ NTSTATUS delete_all_streams(connection_struct *conn, const struct smb_filename *smb_fname) { struct stream_struct *stream_info = NULL; - int i; + unsigned int i; unsigned int num_streams = 0; TALLOC_CTX *frame = talloc_stackframe(); NTSTATUS status; @@ -234,10 +234,10 @@ NTSTATUS delete_all_streams(connection_struct *conn, } bool has_other_nonposix_opens(struct share_mode_lock *lck, - struct files_struct *fsp, - struct server_id self) + struct files_struct *fsp) { struct share_mode_data *data = lck->data; + struct server_id self = messaging_server_id(fsp->conn->sconn->msg_ctx); uint32_t i; for (i=0; i<data->num_share_modes; i++) { @@ -274,7 +274,6 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, enum file_close_type close_type) { connection_struct *conn = fsp->conn; - struct server_id self = messaging_server_id(conn->sconn->msg_ctx); bool delete_file = false; bool changed_user = false; struct share_mode_lock *lck = NULL; @@ -353,7 +352,7 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, delete_file = is_delete_on_close_set(lck, fsp->name_hash); - delete_file &= !has_other_nonposix_opens(lck, fsp, self); + delete_file &= !has_other_nonposix_opens(lck, fsp); /* * NT can set delete_on_close of the last open @@ -1081,7 +1080,6 @@ static NTSTATUS rmdir_internals(TALLOC_CTX *ctx, files_struct *fsp) static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp, enum file_close_type close_type) { - struct server_id self = messaging_server_id(fsp->conn->sconn->msg_ctx); struct share_mode_lock *lck = NULL; bool delete_dir = False; NTSTATUS status = NT_STATUS_OK; @@ -1160,7 +1158,7 @@ static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp, delete_dir = get_delete_on_close_token(lck, fsp->name_hash, &del_nt_token, &del_token); - delete_dir &= !has_other_nonposix_opens(lck, fsp, self); + delete_dir &= !has_other_nonposix_opens(lck, fsp); if ((close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE) && delete_dir) { diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 13a7d7237c7..b654b3ceb9c 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -56,6 +56,16 @@ struct deferred_open_record { * opens and just terminates smbd if the async open times out. */ struct tevent_timer *te; + + /* + * For the samba kernel oplock case we use both a timeout and + * a watch on locking.tdb. This way in case it's smbd holding + * the kernel oplock we get directly notified for the retry + * once the kernel oplock is properly broken. Store the req + * here so that it can be timely discarded once the timer + * above fires. + */ + struct tevent_req *watch_req; }; /**************************************************************************** @@ -1461,28 +1471,29 @@ static bool share_conflict(struct share_mode_entry *entry, uint32_t access_mask, uint32_t share_access) { - DEBUG(10,("share_conflict: entry->access_mask = 0x%x, " - "entry->share_access = 0x%x, " - "entry->private_options = 0x%x\n", - (unsigned int)entry->access_mask, - (unsigned int)entry->share_access, - (unsigned int)entry->private_options)); + DBG_DEBUG("entry->access_mask = 0x%"PRIx32", " + "entry->share_access = 0x%"PRIx32", " + "entry->private_options = 0x%"PRIx32", " + "access_mask = 0x%"PRIx32", " + "share_access = 0x%"PRIx32"\n", + entry->access_mask, + entry->share_access, + entry->private_options, + access_mask, + share_access); if (server_id_is_disconnected(&entry->pid)) { return false; } - DEBUG(10,("share_conflict: access_mask = 0x%x, share_access = 0x%x\n", - (unsigned int)access_mask, (unsigned int)share_access)); - if ((entry->access_mask & (FILE_WRITE_DATA| FILE_APPEND_DATA| FILE_READ_DATA| FILE_EXECUTE| DELETE_ACCESS)) == 0) { - DEBUG(10,("share_conflict: No conflict due to " - "entry->access_mask = 0x%x\n", - (unsigned int)entry->access_mask )); + DBG_DEBUG("No conflict due to " + "entry->access_mask = 0x%"PRIx32"\n", + entry->access_mask); return False; } @@ -1491,9 +1502,8 @@ static bool share_conflict(struct share_mode_entry *entry, FILE_READ_DATA| FILE_EXECUTE| DELETE_ACCESS)) == 0) { - DEBUG(10,("share_conflict: No conflict due to " - "access_mask = 0x%x\n", - (unsigned int)access_mask )); + DBG_DEBUG("No conflict due to access_mask = 0x%"PRIx32"\n", + access_mask); return False; } @@ -1655,7 +1665,6 @@ static NTSTATUS open_mode_check(connection_struct *conn, } #endif - /* Now we check the share modes, after any oplock breaks. */ for(i = 0; i < lck->data->num_share_modes; i++) { if (!is_valid_share_mode_entry(&lck->data->share_modes[i])) { @@ -1830,122 +1839,21 @@ static bool validate_oplock_types(struct share_mode_lock *lck) return true; } -static bool delay_for_oplock(files_struct *fsp, - int oplock_request, - const struct smb2_lease *lease, - struct share_mode_lock *lck, - bool have_sharing_violation, - uint32_t create_disposition, - bool first_open_attempt) +static bool is_same_lease(const files_struct *fsp, + const struct share_mode_entry *e, + const struct smb2_lease *lease) { - struct share_mode_data *d = lck->data; - uint32_t i; - bool delay = false; - bool will_overwrite; - const uint32_t delay_mask = have_sharing_violation ? - SMB2_LEASE_HANDLE : SMB2_LEASE_WRITE; - - if ((oplock_request & INTERNAL_OPEN_ONLY) || - is_stat_open(fsp->access_mask)) { + if (e->op_type != LEASE_OPLOCK) { return false; } - - switch (create_disposition) { - case FILE_SUPERSEDE: - case FILE_OVERWRITE: - case FILE_OVERWRITE_IF: - will_overwrite = true; - break; - default: - will_overwrite = false; - break; + if (lease == NULL) { + return false; } - for (i=0; i<d->num_share_modes; i++) { - struct share_mode_entry *e = &d->share_modes[i]; - bool e_is_lease = (e->op_type == LEASE_OPLOCK); - uint32_t e_lease_type = get_lease_type(d, e); - uint32_t break_to; - bool lease_is_breaking = false; - - if (e_is_lease) { - NTSTATUS status; - - if (lease != NULL) { - bool our_lease = smb2_lease_equal( - fsp_client_guid(fsp), - &lease->lease_key, - &e->client_guid, - &e->lease_key); - if (our_lease) { - DBG_DEBUG("Ignoring our own lease\n"); - continue; - } - } - - status = leases_db_get( + return smb2_lease_equal(fsp_client_guid(fsp), + &lease->lease_key, &e->client_guid, - &e->lease_key, - &fsp->file_id, - NULL, /* current_state */ - &lease_is_breaking, - NULL, /* breaking_to_requested */ - NULL, /* breaking_to_required */ - NULL, /* lease_version */ - NULL); /* epoch */ - SMB_ASSERT(NT_STATUS_IS_OK(status)); - } - - break_to = e_lease_type & ~delay_mask; - - if (will_overwrite) { - break_to &= ~(SMB2_LEASE_HANDLE|SMB2_LEASE_READ); - } - - DEBUG(10, ("entry %u: e_lease_type %u, will_overwrite: %u\n", - (unsigned)i, (unsigned)e_lease_type, - (unsigned)will_overwrite)); - - if ((e_lease_type & ~break_to) == 0) { - if (lease_is_breaking) { - delay = true; - } - continue; - } - - if (share_mode_stale_pid(d, i)) { - continue; - } - - if (will_overwrite) { - /* - * If we break anyway break to NONE directly. - * Otherwise vfs_set_filelen() will trigger the - * break. - */ - break_to &= ~(SMB2_LEASE_READ|SMB2_LEASE_WRITE); - } - - if (!e_is_lease) { - /* - * Oplocks only support breaking to R or NONE. - */ - break_to &= ~(SMB2_LEASE_HANDLE|SMB2_LEASE_WRITE); - } - - DEBUG(10, ("breaking from %d to %d\n", - (int)e_lease_type, (int)break_to)); - send_break_message(fsp->conn->sconn->msg_ctx, &fsp->file_id, - e, break_to); - if (e_lease_type & delay_mask) { - delay = true; - } - if (lease_is_breaking && !first_open_attempt) { - delay = true; - } - } - - return delay; + &e->lease_key); } static bool file_has_brlocks(files_struct *fsp) @@ -2165,24 +2073,6 @@ static NTSTATUS grant_fsp_lease(struct files_struct *fsp, return status; } -static bool is_same_lease(const files_struct *fsp, - const struct share_mode_data *d, - const struct share_mode_entry *e, - const struct smb2_lease *lease) -{ - if (e->op_type != LEASE_OPLOCK) { - return false; - } - if (lease == NULL) { - return false; - } - - return smb2_lease_equal(fsp_client_guid(fsp), - &lease->lease_key, - &e->client_guid, - &e->lease_key); -} - static int map_lease_type_to_oplock(uint32_t lease_type) { int result = NO_OPLOCK; @@ -2203,27 +2093,144 @@ static int map_lease_type_to_oplock(uint32_t lease_type) return result; } -static NTSTATUS grant_fsp_oplock_type(struct smb_request *req, - struct files_struct *fsp, - struct share_mode_lock *lck, - int oplock_request, - const struct smb2_lease *lease, - uint32_t share_access, - uint32_t access_mask) +static NTSTATUS delay_for_oplock(files_struct *fsp, + int oplock_request, + const struct smb2_lease *lease, + struct share_mode_lock *lck, + bool have_sharing_violation, + uint32_t create_disposition, + bool first_open_attempt) { struct share_mode_data *d = lck->data; + uint32_t i; + bool delay = false; + bool will_overwrite; + const uint32_t delay_mask = have_sharing_violation ? + SMB2_LEASE_HANDLE : SMB2_LEASE_WRITE; bool got_handle_lease = false; bool got_oplock = false; - uint32_t i; + bool have_other_lease = false; uint32_t granted; - bool ok; NTSTATUS status; - if (oplock_request & INTERNAL_OPEN_ONLY) { - /* No oplocks on internal open. */ - oplock_request = NO_OPLOCK; - DEBUG(10,("grant_fsp_oplock_type: oplock type 0x%x on file %s\n", - fsp->oplock_type, fsp_str_dbg(fsp))); + if (is_stat_open(fsp->access_mask)) { + goto grant; + } + + switch (create_disposition) { + case FILE_SUPERSEDE: + case FILE_OVERWRITE: + case FILE_OVERWRITE_IF: + will_overwrite = true; + break; + default: + will_overwrite = false; + break; + } + + for (i=0; i<d->num_share_modes; i++) { + struct share_mode_entry *e = &d->share_modes[i]; + bool e_is_lease = (e->op_type == LEASE_OPLOCK); + uint32_t e_lease_type = get_lease_type(d, e); + uint32_t break_to; + bool lease_is_breaking = false; + + if (e_is_lease) { + if (lease != NULL) { + bool our_lease = is_same_lease(fsp, e, lease); + if (our_lease) { + DBG_DEBUG("Ignoring our own lease\n"); + continue; + } + } + + status = leases_db_get( + &e->client_guid, + &e->lease_key, + &fsp->file_id, + NULL, /* current_state */ + &lease_is_breaking, + NULL, /* breaking_to_requested */ + NULL, /* breaking_to_required */ + NULL, /* lease_version */ + NULL); /* epoch */ + SMB_ASSERT(NT_STATUS_IS_OK(status)); + } + + if (!got_handle_lease && + ((e_lease_type & SMB2_LEASE_HANDLE) != 0) && + !share_mode_stale_pid(d, i)) { + got_handle_lease = true; + } + + if (!got_oplock && + (e->op_type != LEASE_OPLOCK) && + !share_mode_stale_pid(d, i)) { + got_oplock = true; + } + + if (!have_other_lease && + !is_same_lease(fsp, e, lease) && + !share_mode_stale_pid(d, i)) { + have_other_lease = true; + } + + break_to = e_lease_type & ~delay_mask; + + if (will_overwrite) { + break_to &= ~(SMB2_LEASE_HANDLE|SMB2_LEASE_READ); + } + + DEBUG(10, ("entry %u: e_lease_type %u, will_overwrite: %u\n", + (unsigned)i, (unsigned)e_lease_type, + (unsigned)will_overwrite)); + + if ((e_lease_type & ~break_to) == 0) { + if (lease_is_breaking) { + delay = true; + } + continue; + } + + if (share_mode_stale_pid(d, i)) { + continue; + } + + if (will_overwrite) { + /* + * If we break anyway break to NONE directly. + * Otherwise vfs_set_filelen() will trigger the + * break. + */ + break_to &= ~(SMB2_LEASE_READ|SMB2_LEASE_WRITE); + } + + if (!e_is_lease) { + /* + * Oplocks only support breaking to R or NONE. + */ + break_to &= ~(SMB2_LEASE_HANDLE|SMB2_LEASE_WRITE); + } + + DEBUG(10, ("breaking from %d to %d\n", + (int)e_lease_type, (int)break_to)); + send_break_message(fsp->conn->sconn->msg_ctx, &fsp->file_id, + e, break_to); + if (e_lease_type & delay_mask) { + delay = true; + } + if (lease_is_breaking && !first_open_attempt) { + delay = true; + } + } + + if (delay) { -- Samba Shared Repository