[SCM] Samba Shared Repository - branch master updated
Jeremy Allison
jra at samba.org
Fri Mar 10 06:31:02 UTC 2017
The branch, master has been updated
via 2772fa4 talloc: fix doxygen of talloc_move
via 59b580f auth_ntdomain3: Correctly handle !authoritative
via 7d3c197 auth_winbind4: Correctly handle !authoritative
via 9abc80e auth_winbind3: Correctly handle !authoritative
via d3e2e41 s3/smbd: add my copyright to open.c
via fd03420 s4/torture: some tests for kernel oplocks
via 6e54d8d s3/selftest: adopt config.h check from source4
via b35a296 s3/smbd: fix deferred open with streams and kernel oplocks
via 1a6c82e s3/smbd: all callers of defer_open() pass a lck
via 7fa2f11 s3/smbd: remove async_open arg from defer_open()
via ad8c361 s3/smbd: fix schedule_async_open() timer
via beaba62 s3/smbd: add and use retry_open() instead of defer_open() in two places
via b17ff9b s3/smbd: simplify defer_open()
via 8580adc s3/smbd: req is already validated at the beginning of open_file_ntcreate()
via f5631f6 s3/smbd: add comments and some reformatting to open_file_ntcreate()
via 6924e72 s3/smbd: add const to get_lease_type() args
via fe473f8 s3/wscript: fix Linux kernel oplock detection
from 373e0bd winbindd: Remove an unused #define
https://git.samba.org/?p=samba.git;a=shortlog;h=master
- Log -----------------------------------------------------------------
commit 2772fa4fbff968106897ec02669d017b9e47979d
Author: Uri Simchoni <uri at samba.org>
Date: Thu Mar 9 14:40:54 2017 +0200
talloc: fix doxygen of talloc_move
talloc_move cannot fail.
Signed-off-by: Uri Simchoni <uri at samba.org>
Reviewed-by: Jeremy Allison <jra at samba.org>
Autobuild-User(master): Jeremy Allison <jra at samba.org>
Autobuild-Date(master): Fri Mar 10 07:30:40 CET 2017 on sn-devel-144
commit 59b580f6c72d4d296a22c95fc1ef572ed2c696b0
Author: Volker Lendecke <vl at samba.org>
Date: Sun Feb 12 19:20:07 2017 +0100
auth_ntdomain3: Correctly handle !authoritative
Signed-off-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
commit 7d3c197e6172535a069c5fce4dc737c1d152b2a1
Author: Volker Lendecke <vl at samba.org>
Date: Sat Feb 25 09:55:28 2017 +0000
auth_winbind4: Correctly handle !authoritative
Signed-off-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
commit 9abc80e0e4bc13f69e73b0a09ee09803b4dc985c
Author: Volker Lendecke <vl at samba.org>
Date: Sat Feb 11 10:25:44 2017 +0100
auth_winbind3: Correctly handle !authoritative
Signed-off-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
commit d3e2e41995c54128e7b761834c2dde3c7b052476
Author: Ralph Boehme <slow at samba.org>
Date: Tue Mar 7 19:24:45 2017 +0100
s3/smbd: add my copyright to open.c
Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Jeremy Allison <jra at samba.org>
commit fd03420c4f59d3248b80d07a302d1404ce78b09f
Author: Ralph Boehme <slow at samba.org>
Date: Wed Mar 1 18:13:35 2017 +0100
s4/torture: some tests for kernel oplocks
Bug: https://bugzilla.samba.org/show_bug.cgi?id=7537
Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Jeremy Allison <jra at samba.org>
commit 6e54d8d2bda2c9232676f8c08c626f22de50f52b
Author: Ralph Boehme <slow at samba.org>
Date: Wed Mar 8 07:18:36 2017 +0100
s3/selftest: adopt config.h check from source4
No change in behaviour.
Bug: https://bugzilla.samba.org/show_bug.cgi?id=7537
Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Jeremy Allison <jra at samba.org>
commit b35a296a27a0807c780f2a9e7af2f2e93feefaa8
Author: Ralph Boehme <slow at samba.org>
Date: Tue Mar 7 16:27:39 2017 +0100
s3/smbd: fix deferred open with streams and kernel oplocks
I noticed smbd can get stuck in an open() call with kernel oplocks
enabled and named streams (provided by vfs_streams_xattr):
- client opens a file and with an exclusive oplock
- client starts writing to the file
- client opens an existing stream of the file
- the smbd process gets stuck in an open()
What happens is:
we had setup a locking.tdb record watch in defer_open(), the watch was
triggered, we reattempted the open and got stuck in a blocking open
because the oplock holder (ourselves) hadn't given up the oplock yet.
Cf e576bf5310bc9de9686a71539e9a1b60b4fba5cc for the commit that added
the kernel oplock retry logic. tldr: with kernel oplocks the first open
is non-blocking, but the second one is blocking.
Detailed analysis follows.
When opening a named stream of a file, Samba internally opens the
underlying "base" file first. This internal open of the basefile suceeds
and does *not* trigger an oplock break (because it is an internal open
that doesn't call open() at all) but it is added as an entry to the
locking.tdb record of the file.
Next, the stream open ends up in streams_xattr where a non-blocking
open() on the base file is called. This open fails with EWOULDBLOCK
because we have another fd with a kernel oplock on the file.
So we call defer_open() which sets up a watch on the locking.tdb record.
In the subsequent error unwinding code in open_file_ntcreate() and
callers we close the internal open file handle of the basefile which
also removes the entry from the locking.tdb record and so *changes the
record*.
This fires the record watch and in the callback defer_open_done() we
don't check whether the condition (oplock gone) we're interested in is
actually met. The callback blindly reschedules the open request with
schedule_deferred_open_message_smb().
schedule_deferred_open_message_smb() schedules an immediate tevent event
which has precedence over the IPC fd events in messaging, so the open is
always (!) reattempted before processing the oplock break message.
As explained above, this second open will be a blocking one so we get
stuck in a blocking open.
It doesn't help to make all opens non-blocking, that would just result
in a busy loop failing the open, as we never process the oplock break
message (remember, schedule_deferred_open_message_smb() used immediate
tevent events).
To fix this we must add some logic to the record watch callback to check
whether the record watch was done for a kernel oplock file and if yes,
check if the oplock state changed. If not, simply reschedule the
deferred open and keep waiting.
This logic is only needed for kernel oplocks, not for Samba-level
oplocks, because there's no risk of deadlocking, the worst that can
happen is a rescheduled open that fails again in the oplock checks and
gets deferred again.
Bug: https://bugzilla.samba.org/show_bug.cgi?id=7537
Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Jeremy Allison <jra at samba.org>
commit 1a6c82e5d5a3462827ee3fe1edab01f535f831a9
Author: Ralph Boehme <slow at samba.org>
Date: Tue Mar 7 15:48:05 2017 +0100
s3/smbd: all callers of defer_open() pass a lck
No change in behaviour. Update the function comment explaining how it
works and relies on lck for a record watch.
Bug: https://bugzilla.samba.org/show_bug.cgi?id=7537
Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Jeremy Allison <jra at samba.org>
commit 7fa2f1159437c9f1aa47f51e65655b4d9afa5c0a
Author: Ralph Boehme <slow at samba.org>
Date: Tue Mar 7 19:11:20 2017 +0100
s3/smbd: remove async_open arg from defer_open()
All remaining callers pass false.
Bug: https://bugzilla.samba.org/show_bug.cgi?id=7537
Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Jeremy Allison <jra at samba.org>
commit ad8c36125f72e0d5f9ebfc94037a4ae9e7608aad
Author: Ralph Boehme <slow at samba.org>
Date: Tue Mar 7 15:33:55 2017 +0100
s3/smbd: fix schedule_async_open() timer
schedule_async_open() was calling defer_open with sharemode lock = NULL,
as a result there was never an active 20 s timeout.
This has been broken since the commits in
$ git log --reverse -p -10 8283fd0e0090ed12b0b12d5acb550642d621b026
Just roll our own deferred record instead of calling defer_open() and
also set up timer that, as a last resort, catches stuck opens and just
exits for now.
Bug: https://bugzilla.samba.org/show_bug.cgi?id=7537
Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Jeremy Allison <jra at samba.org>
commit beaba6222848fb4ff4392b2247c5be1094b1d65b
Author: Ralph Boehme <slow at samba.org>
Date: Tue Mar 7 15:03:12 2017 +0100
s3/smbd: add and use retry_open() instead of defer_open() in two places
Add a new function that does an immediate open rescheduling.
The first deferred open this commit changes was never scheduled, as the
scheduling relies on a timeout of the watch on the sharemode lock.
This has been broken since the commits in
$ git log --reverse -p -10 8283fd0e0090ed12b0b12d5acb550642d621b026
That patchset added the dbwrap watch record logic to defer_open() and
removed the timers.
I'm doing this mainly to untangle the defer_open() logic which is
complicated by the lck arg.
Bug: https://bugzilla.samba.org/show_bug.cgi?id=7537
Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Jeremy Allison <jra at samba.org>
commit b17ff9b181b7b9730d32534e720c45faabfa6799
Author: Ralph Boehme <slow at samba.org>
Date: Tue Mar 7 14:37:54 2017 +0100
s3/smbd: simplify defer_open()
Add a helper function deferred_open_record_create() that creates a
deferred_open_record and let all callers pass all needed arguments
individually.
While we're at it, enhance the debug message in defer_open() to print
all variables.
Bug: https://bugzilla.samba.org/show_bug.cgi?id=7537
Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Jeremy Allison <jra at samba.org>
commit 8580adc1d968304b69237f289d13950972394b48
Author: Ralph Boehme <slow at samba.org>
Date: Tue Mar 7 14:10:39 2017 +0100
s3/smbd: req is already validated at the beginning of open_file_ntcreate()
req can't be NULL because the if condition surrounding this code checks
!(oplock_request & INTERNAL_OPEN_ONLY).
Bug: https://bugzilla.samba.org/show_bug.cgi?id=7537
Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Jeremy Allison <jra at samba.org>
commit f5631f6b3520326d4c9a6bae5636fd8d53e66b29
Author: Ralph Boehme <slow at samba.org>
Date: Mon Mar 6 11:43:08 2017 +0100
s3/smbd: add comments and some reformatting to open_file_ntcreate()
No change in behaviour.
Bug: https://bugzilla.samba.org/show_bug.cgi?id=7537
Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Jeremy Allison <jra at samba.org>
commit 6924e72ade20e98ac470fcb6ba7120c61b06bb0f
Author: Ralph Boehme <slow at samba.org>
Date: Sat Mar 4 13:55:55 2017 +0100
s3/smbd: add const to get_lease_type() args
Bug: https://bugzilla.samba.org/show_bug.cgi?id=7537
Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Jeremy Allison <jra at samba.org>
commit fe473f805af885a23bb16046c9d26d756e164f30
Author: Ralph Boehme <slow at samba.org>
Date: Mon Mar 6 12:09:53 2017 +0100
s3/wscript: fix Linux kernel oplock detection
Fix a copy/paste error, the Linux kernel oplocks check was copied from
the change notify support check.
Bug: https://bugzilla.samba.org/show_bug.cgi?id=7537
Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Jeremy Allison <jra at samba.org>
-----------------------------------------------------------------------
Summary of changes:
lib/talloc/talloc.h | 7 +-
selftest/target/Samba3.pm | 5 +
source3/auth/auth_domain.c | 4 +
source3/auth/auth_winbind.c | 9 +
source3/selftest/tests.py | 37 ++--
source3/smbd/open.c | 392 ++++++++++++++++++++++++++++-----------
source3/smbd/oplock.c | 3 +-
source3/smbd/proto.h | 3 +-
source3/wscript | 6 +-
source4/auth/ntlm/auth_winbind.c | 5 +
source4/selftest/tests.py | 2 +-
source4/torture/smb2/oplock.c | 140 ++++++++++++++
source4/torture/smb2/smb2.c | 1 +
13 files changed, 485 insertions(+), 129 deletions(-)
Changeset truncated at 500 lines:
diff --git a/lib/talloc/talloc.h b/lib/talloc/talloc.h
index 227f745..618430a 100644
--- a/lib/talloc/talloc.h
+++ b/lib/talloc/talloc.h
@@ -407,10 +407,11 @@ const char *talloc_set_name(const void *ptr, const char *fmt, ...) PRINTF_ATTRIB
*
* @param[in] new_ctx The new parent context.
*
- * @param[in] pptr Pointer to the talloc chunk to move.
+ * @param[in] pptr Pointer to a pointer to the talloc chunk to move.
+ *
+ * @return The pointer to the talloc chunk that moved.
+ * It does not have any failure modes.
*
- * @return The pointer of the talloc chunk it has been moved to,
- * NULL on error.
*/
void *talloc_move(const void *new_ctx, void **pptr);
#else
diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm
index 775dc16..d754b5f 100755
--- a/selftest/target/Samba3.pm
+++ b/selftest/target/Samba3.pm
@@ -1860,6 +1860,11 @@ sub provision($$$$$$$$)
[mangle_illegal]
copy = tmp
mangled names = illegal
+
+[kernel_oplocks]
+ copy = tmp
+ kernel oplocks = yes
+ vfs objects = streams_xattr xattr_tdb
";
close(CONF);
diff --git a/source3/auth/auth_domain.c b/source3/auth/auth_domain.c
index d663923..b3ff518 100644
--- a/source3/auth/auth_domain.c
+++ b/source3/auth/auth_domain.c
@@ -229,6 +229,10 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx,
if (NT_STATUS_EQUAL(nt_status, NT_STATUS_UNSUCCESSFUL)) {
nt_status = NT_STATUS_NO_LOGON_SERVERS;
}
+ if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER) &&
+ (authoritative == 0)) {
+ nt_status = NT_STATUS_NOT_IMPLEMENTED;
+ }
} else {
nt_status = make_server_info_info3(mem_ctx,
user_info->client.account_name,
diff --git a/source3/auth/auth_winbind.c b/source3/auth/auth_winbind.c
index 2b5c84d..e6a6296 100644
--- a/source3/auth/auth_winbind.c
+++ b/source3/auth/auth_winbind.c
@@ -121,6 +121,15 @@ static NTSTATUS check_winbind_security(const struct auth_context *auth_context,
if (wbc_status == WBC_ERR_AUTH_ERROR) {
nt_status = NT_STATUS(err->nt_status);
+
+ if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER) &&
+ (err->authoritative == 0)) {
+ /*
+ * Trigger a fallback to local SAM
+ */
+ nt_status = NT_STATUS_NOT_IMPLEMENTED;
+ }
+
wbcFreeMemory(err);
return nt_status;
}
diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py
index f180710..e386b1f 100755
--- a/source3/selftest/tests.py
+++ b/source3/selftest/tests.py
@@ -36,6 +36,26 @@ def plansmbtorture4testsuite(name, env, options, description=''):
selftesthelpers.plansmbtorture4testsuite(
name, env, options, target='samba3', modname=modname)
+# find config.h
+try:
+ config_h = os.environ["CONFIG_H"]
+except KeyError:
+ samba4bindir = bindir()
+ config_h = os.path.join(samba4bindir, "default/include/config.h")
+
+# check available features
+config_hash = dict()
+f = open(config_h, 'r')
+try:
+ lines = f.readlines()
+ config_hash = dict((x[0], ' '.join(x[1:]))
+ for x in map(lambda line: line.strip().split(' ')[1:],
+ filter(lambda line: (line[0:7] == '#define') and (len(line.split(' ')) > 2), lines)))
+finally:
+ f.close()
+
+have_libarchive = ("HAVE_LIBARCHIVE" in config_hash)
+have_linux_kernel_oplocks = ("HAVE_KERNEL_OPLOCKS_LINUX" in config_hash)
plantestsuite("samba3.blackbox.success", "nt4_dc:local", [os.path.join(samba3srcdir, "script/tests/test_success.sh")])
plantestsuite("samba3.blackbox.failure", "nt4_dc:local", [os.path.join(samba3srcdir, "script/tests/test_failure.sh")])
@@ -213,20 +233,6 @@ for env in ["fileserver"]:
# tar command tests
#
- # find config.h
- try:
- config_h = os.environ["CONFIG_H"]
- except KeyError:
- samba4bindir = bindir()
- config_h = os.path.join(samba4bindir, "default/include/config.h")
-
- # see if libarchive is supported
- f = open(config_h, 'r')
- try:
- have_libarchive = ("HAVE_LIBARCHIVE 1" in f.read())
- finally:
- f.close()
-
# tar command enabled only if built with libarchive
if have_libarchive:
# Test smbclient/tarmode
@@ -436,6 +442,9 @@ for t in tests:
plansmbtorture4testsuite(t, "ad_dc", '//$SERVER/tmp -U$USERNAME%$PASSWORD --signing=required')
elif t == "smb2.dosmode":
plansmbtorture4testsuite(t, "simpleserver", '//$SERVER/dosmode -U$USERNAME%$PASSWORD')
+ elif t == "smb2.kernel-oplocks":
+ if have_linux_kernel_oplocks:
+ plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER/kernel_oplocks -U$USERNAME%$PASSWORD')
elif t == "vfs.acl_xattr":
plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/tmp -U$USERNAME%$PASSWORD')
else:
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index 7bd1086..603a01d 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -4,6 +4,7 @@
Copyright (C) Andrew Tridgell 1992-1998
Copyright (C) Jeremy Allison 2001-2004
Copyright (C) Volker Lendecke 2005
+ Copyright (C) Ralph Boehme 2017
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -45,6 +46,13 @@ struct deferred_open_record {
bool delayed_for_oplocks;
bool async_open;
struct file_id id;
+
+ /*
+ * Timer for async opens, needed because they don't use a watch on
+ * a locking.tdb record. This is currently only used for real async
+ * opens and just terminates smbd if the async open times out.
+ */
+ struct tevent_timer *te;
};
/****************************************************************************
@@ -1544,6 +1552,23 @@ static bool delay_for_oplock(files_struct *fsp,
return delay;
}
+/**
+ * Return lease or oplock state from a share mode
+ **/
+static uint32_t get_lease_type_from_share_mode(const struct share_mode_data *d)
+{
+ uint32_t e_lease_type = 0;
+ uint32_t i;
+
+ for (i=0; i < d->num_share_modes; i++) {
+ struct share_mode_entry *e = &d->share_modes[i];
+
+ e_lease_type |= get_lease_type(d, e);
+ }
+
+ return e_lease_type;
+}
+
static bool file_has_brlocks(files_struct *fsp)
{
struct byte_range_lock *br_lck;
@@ -1932,71 +1957,112 @@ static bool request_timed_out(struct timeval request_time,
return (timeval_compare(&end_time, &now) < 0);
}
+static struct deferred_open_record *deferred_open_record_create(
+ bool delayed_for_oplocks,
+ bool async_open,
+ struct file_id id)
+{
+ struct deferred_open_record *record = NULL;
+
+ record = talloc(NULL, struct deferred_open_record);
+ if (record == NULL) {
+ return NULL;
+ }
+
+ *record = (struct deferred_open_record) {
+ .delayed_for_oplocks = delayed_for_oplocks,
+ .async_open = async_open,
+ .id = id,
+ };
+
+ return record;
+}
+
struct defer_open_state {
struct smbXsrv_connection *xconn;
uint64_t mid;
+ struct file_id file_id;
+ struct timeval request_time;
+ struct timeval timeout;
+ bool kernel_oplock;
+ uint32_t lease_type;
};
static void defer_open_done(struct tevent_req *req);
-/****************************************************************************
- Handle the 1 second delay in returning a SHARING_VIOLATION error.
-****************************************************************************/
-
+/**
+ * Defer an open and watch a locking.tdb record
+ *
+ * This defers an open that gets rescheduled once the locking.tdb record watch
+ * is triggered by a change to the record.
+ *
+ * It is used to defer opens that triggered an oplock break and for the SMB1
+ * sharing violation delay.
+ **/
static void defer_open(struct share_mode_lock *lck,
struct timeval request_time,
struct timeval timeout,
struct smb_request *req,
- struct deferred_open_record *state)
+ bool delayed_for_oplocks,
+ bool kernel_oplock,
+ struct file_id id)
{
- struct deferred_open_record *open_rec;
+ struct deferred_open_record *open_rec = NULL;
+ struct timeval abs_timeout;
+ struct defer_open_state *watch_state;
+ struct tevent_req *watch_req;
+ bool ok;
+
+ abs_timeout = timeval_sum(&request_time, &timeout);
- DEBUG(10,("defer_open_sharing_error: time [%u.%06u] adding deferred "
- "open entry for mid %llu\n",
- (unsigned int)request_time.tv_sec,
- (unsigned int)request_time.tv_usec,
- (unsigned long long)req->mid));
+ DBG_DEBUG("request time [%s] timeout [%s] mid [%" PRIu64 "] "
+ "delayed_for_oplocks [%s] kernel_oplock [%s] file_id [%s]\n",
+ timeval_string(talloc_tos(), &request_time, false),
+ timeval_string(talloc_tos(), &abs_timeout, false),
+ req->mid,
+ delayed_for_oplocks ? "yes" : "no",
+ kernel_oplock ? "yes" : "no",
+ file_id_string_tos(&id));
- open_rec = talloc(NULL, struct deferred_open_record);
+ open_rec = deferred_open_record_create(delayed_for_oplocks,
+ false,
+ id);
if (open_rec == NULL) {
TALLOC_FREE(lck);
exit_server("talloc failed");
}
- *open_rec = *state;
-
- if (lck) {
- struct defer_open_state *watch_state;
- struct tevent_req *watch_req;
- bool ret;
-
- watch_state = talloc(open_rec, struct defer_open_state);
- if (watch_state == NULL) {
- exit_server("talloc failed");
- }
- watch_state->xconn = req->xconn;
- watch_state->mid = req->mid;
+ watch_state = talloc(open_rec, struct defer_open_state);
+ if (watch_state == NULL) {
+ exit_server("talloc failed");
+ }
+ watch_state->xconn = req->xconn;
+ watch_state->mid = req->mid;
+ watch_state->file_id = lck->data->id;
+ watch_state->request_time = request_time;
+ watch_state->timeout = timeout;
+ watch_state->kernel_oplock = kernel_oplock;
+ watch_state->lease_type = get_lease_type_from_share_mode(lck->data);
- DEBUG(10, ("defering mid %llu\n",
- (unsigned long long)req->mid));
+ DBG_DEBUG("defering mid %" PRIu64 "\n", req->mid);
- watch_req = dbwrap_watched_watch_send(
- watch_state, req->sconn->ev_ctx, lck->data->record,
- (struct server_id){0});
- if (watch_req == NULL) {
- exit_server("Could not watch share mode record");
- }
- tevent_req_set_callback(watch_req, defer_open_done,
- watch_state);
+ watch_req = dbwrap_watched_watch_send(watch_state,
+ req->sconn->ev_ctx,
+ lck->data->record,
+ (struct server_id){0});
+ if (watch_req == NULL) {
+ exit_server("Could not watch share mode record");
+ }
+ tevent_req_set_callback(watch_req, defer_open_done, watch_state);
- ret = tevent_req_set_endtime(
- watch_req, req->sconn->ev_ctx,
- timeval_sum(&request_time, &timeout));
- SMB_ASSERT(ret);
+ ok = tevent_req_set_endtime(watch_req, req->sconn->ev_ctx, abs_timeout);
+ if (!ok) {
+ exit_server("tevent_req_set_endtime failed");
}
- if (!push_deferred_open_message_smb(req, request_time, timeout,
- state->id, open_rec)) {
+ ok = push_deferred_open_message_smb(req, request_time, timeout,
+ open_rec->id, open_rec);
+ if (!ok) {
TALLOC_FREE(lck);
exit_server("push_deferred_open_message_smb failed");
}
@@ -2006,8 +2072,12 @@ static void defer_open_done(struct tevent_req *req)
{
struct defer_open_state *state = tevent_req_callback_data(
req, struct defer_open_state);
+ struct tevent_req *watch_req = NULL;
+ struct share_mode_lock *lck = NULL;
+ bool schedule_req = true;
+ struct timeval timeout;
NTSTATUS status;
- bool ret;
+ bool ok;
status = dbwrap_watched_watch_recv(req, talloc_tos(), NULL, NULL,
NULL);
@@ -2019,15 +2089,108 @@ static void defer_open_done(struct tevent_req *req)
* Even if it failed, retry anyway. TODO: We need a way to
* tell a re-scheduled open about that error.
*/
+ if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) &&
+ state->kernel_oplock)
+ {
+ /*
+ * If we reschedule but the kernel oplock is still hold
+ * we would block in the second open as that will be a
+ * blocking open attempt.
+ */
+ exit_server("Kernel oplock holder didn't "
+ "respond to break message");
+ }
+ }
+
+ if (state->kernel_oplock) {
+ lck = get_existing_share_mode_lock(talloc_tos(), state->file_id);
+ if (lck != NULL) {
+ uint32_t lease_type;
+
+ lease_type = get_lease_type_from_share_mode(lck->data);
+
+ if ((lease_type != 0) &&
+ (lease_type == state->lease_type))
+ {
+ DBG_DEBUG("Unchanged lease: %" PRIu32 "\n",
+ lease_type);
+ schedule_req = false;
+ }
+ }
+ }
+
+ if (schedule_req) {
+ DBG_DEBUG("scheduling mid %" PRIu64 "\n", state->mid);
+
+ ok = schedule_deferred_open_message_smb(state->xconn,
+ state->mid);
+ if (!ok) {
+ exit_server("schedule_deferred_open_message_smb failed");
+ }
+ TALLOC_FREE(lck);
+ TALLOC_FREE(state);
+ return;
}
- DEBUG(10, ("scheduling mid %llu\n", (unsigned long long)state->mid));
+ DBG_DEBUG("Keep waiting for oplock release for [%s/%s%s] "
+ "mid: %" PRIu64 "\n",
+ lck->data->servicepath,
+ lck->data->base_name,
+ lck->data->stream_name ? lck->data->stream_name : "",
+ state->mid);
- ret = schedule_deferred_open_message_smb(state->xconn, state->mid);
- SMB_ASSERT(ret);
- TALLOC_FREE(state);
+ watch_req = dbwrap_watched_watch_send(state,
+ state->xconn->ev_ctx,
+ lck->data->record,
+ (struct server_id){0});
+ if (watch_req == NULL) {
+ exit_server("Could not watch share mode record");
+ }
+ tevent_req_set_callback(watch_req, defer_open_done, state);
+
+ timeout = timeval_sum(&state->request_time, &state->timeout);
+ ok = tevent_req_set_endtime(watch_req, state->xconn->ev_ctx, timeout);
+ if (!ok) {
+ exit_server("tevent_req_set_endtime failed");
+ }
+
+ TALLOC_FREE(lck);
}
+/**
+ * Reschedule an open for immediate execution
+ **/
+static void retry_open(struct timeval request_time,
+ struct smb_request *req,
+ struct file_id id)
+{
+ struct deferred_open_record *open_rec = NULL;
+ bool ok;
+
+ DBG_DEBUG("request time [%s] mid [%" PRIu64 "] file_id [%s]\n",
+ timeval_string(talloc_tos(), &request_time, false),
+ req->mid,
+ file_id_string_tos(&id));
+
+ open_rec = deferred_open_record_create(false, false, id);
+ if (open_rec == NULL) {
+ exit_server("talloc failed");
+ }
+
+ ok = push_deferred_open_message_smb(req,
+ request_time,
+ timeval_set(0, 0),
+ id,
+ open_rec);
+ if (!ok) {
+ exit_server("push_deferred_open_message_smb failed");
+ }
+
+ ok = schedule_deferred_open_message_smb(req->xconn, req->mid);
+ if (!ok) {
+ exit_server("schedule_deferred_open_message_smb failed");
+ }
+}
/****************************************************************************
On overwrite open ensure that the attributes match.
@@ -2142,10 +2305,9 @@ static NTSTATUS fcb_or_dos_open(struct smb_request *req,
static void schedule_defer_open(struct share_mode_lock *lck,
struct file_id id,
struct timeval request_time,
- struct smb_request *req)
+ struct smb_request *req,
+ bool kernel_oplock)
{
- struct deferred_open_record state;
-
/* This is a relative time, added to the absolute
request_time value to get the absolute timeout time.
Note that if this is the second or greater time we enter
@@ -2164,38 +2326,54 @@ static void schedule_defer_open(struct share_mode_lock *lck,
timeout = timeval_set(OPLOCK_BREAK_TIMEOUT*2, 0);
- /* Nothing actually uses state.delayed_for_oplocks
- but it's handy to differentiate in debug messages
- between a 30 second delay due to oplock break, and
- a 1 second delay for share mode conflicts. */
-
- state.delayed_for_oplocks = True;
- state.async_open = false;
- state.id = id;
-
- if (!request_timed_out(request_time, timeout)) {
- defer_open(lck, request_time, timeout, req, &state);
+ if (request_timed_out(request_time, timeout)) {
+ return;
}
+
+ defer_open(lck, request_time, timeout, req, true, kernel_oplock, id);
}
/****************************************************************************
Reschedule an open call that went asynchronous.
--
Samba Shared Repository
More information about the samba-cvs
mailing list