s3:locking: add share_mode_entry_prepare_{lock,unlock}() infrastructure
When adding or deleting share mode entries elements, we typically
have a pattern like this:
1. get the g_lock via get_[existing_]share_mode_lock()
2. do some checking of the existing record
3. add/delete a share_mode_entry to the record
4. do some vfs operations still protected by the g_lock
5. (optional) cleanup of the record on failure
6. release the g_lock
We can optimize this to:
- Run 1-3. under a tdb chainlock
- Only protect vfs operations with the g_lock
if a new file was created/will be deleted
- Regrab the g_lock for a cleanup.
The new share_mode_entry_prepare_lock()
allows the caller to run a function within a tdb chainlock
similar to share_mode_do_locked_vfs_denied() where vfs calls are denied
and the execution is done within a tdb chainlock.
But the callback function is allowed to decide if it wants to
keep the lock at the g_lock layer on return.
The decision is kept in struct share_mode_entry_prepare_state,
which is then passed to share_mode_entry_prepare_unlock()
with an optional callback to do some cleanup under the
still existing g_lock or a regrabed g_lock.
In the ideal case the callback function passed to
share_mode_entry_prepare_lock() is able to decide that
it can drop the g_lock and the share_mode_entry_prepare_unlock().
gets a NULL callback as there's nothing to cleanup.
In this case share_mode_entry_prepare_unlock() is a noop.
This will allow us to avoid fallbacks to the dbwrap_watch based
waiting for the g_lock in the SMB2 Create and Close code paths.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15125
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>