The Samba-Bugzilla – Attachment 13050 Details for
Bug 7537
streams_xattr and kernel oplocks results in NT_STATUS_NETWORK_BUSY
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch for 4.4 backported from master
bug7537-v44.patch (text/plain), 46.66 KB, created by
Ralph Böhme
on 2017-03-13 14:23:40 UTC
(
hide
)
Description:
Patch for 4.4 backported from master
Filename:
MIME Type:
Creator:
Ralph Böhme
Created:
2017-03-13 14:23:40 UTC
Size:
46.66 KB
patch
obsolete
>From 18703dceb2d112b75f0c75cfc74937066d0948f6 Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Mon, 6 Mar 2017 12:09:53 +0100 >Subject: [PATCH 01/12] 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@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit fe473f805af885a23bb16046c9d26d756e164f30) >--- > source3/wscript | 6 +++--- > 1 file changed, 3 insertions(+), 3 deletions(-) > >diff --git a/source3/wscript b/source3/wscript >index cd63f74..a345d3e 100644 >--- a/source3/wscript >+++ b/source3/wscript >@@ -159,11 +159,11 @@ main() { > #include <sys/types.h> > #include <fcntl.h> > #include <signal.h> >-#ifndef F_NOTIFY >-#define F_NOTIFY 1026 >+#ifndef F_GETLEASE >+#define F_GETLEASE 1025 > #endif > main() { >- exit(fcntl(open("/tmp", O_RDONLY), F_NOTIFY, 0) == -1 ? 1 : 0); >+ exit(fcntl(open("/tmp", O_RDONLY), F_GETLEASE, 0) == -1 ? 1 : 0); > }''', 'HAVE_KERNEL_OPLOCKS_LINUX', addmain=False, execute=True, > msg="Checking for Linux kernel oplocks") > >-- >2.9.3 > > >From 5b38619f043cda2f2f5d54d6459ff6fc6adf39e9 Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Sat, 4 Mar 2017 13:55:55 +0100 >Subject: [PATCH 02/12] 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@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 6924e72ade20e98ac470fcb6ba7120c61b06bb0f) >--- > source3/smbd/oplock.c | 3 ++- > source3/smbd/proto.h | 3 ++- > 2 files changed, 4 insertions(+), 2 deletions(-) > >diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c >index b94bc36..56b4499 100644 >--- a/source3/smbd/oplock.c >+++ b/source3/smbd/oplock.c >@@ -171,7 +171,8 @@ uint32_t map_oplock_to_lease_type(uint16_t op_type) > return ret; > } > >-uint32_t get_lease_type(struct share_mode_data *d, struct share_mode_entry *e) >+uint32_t get_lease_type(const struct share_mode_data *d, >+ const struct share_mode_entry *e) > { > if (e->op_type == LEASE_OPLOCK) { > return d->leases[e->lease_idx].current_state; >diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h >index 4ba7316..77a3b21 100644 >--- a/source3/smbd/proto.h >+++ b/source3/smbd/proto.h >@@ -679,7 +679,8 @@ NTSTATUS get_relative_fid_filename(connection_struct *conn, > /* The following definitions come from smbd/oplock.c */ > > uint32_t map_oplock_to_lease_type(uint16_t op_type); >-uint32_t get_lease_type(struct share_mode_data *d, struct share_mode_entry *e); >+uint32_t get_lease_type(const struct share_mode_data *d, >+ const struct share_mode_entry *e); > bool update_num_read_oplocks(files_struct *fsp, struct share_mode_lock *lck); > > void break_kernel_oplock(struct messaging_context *msg_ctx, files_struct *fsp); >-- >2.9.3 > > >From 188cd1ed0cda820c51409f8a867ea80065719e9a Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Mon, 6 Mar 2017 11:43:08 +0100 >Subject: [PATCH 03/12] 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@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit f5631f6b3520326d4c9a6bae5636fd8d53e66b29) >--- > source3/smbd/open.c | 45 +++++++++++++++++++++++++++++++++------------ > 1 file changed, 33 insertions(+), 12 deletions(-) > >diff --git a/source3/smbd/open.c b/source3/smbd/open.c >index 25cf417..9817569 100644 >--- a/source3/smbd/open.c >+++ b/source3/smbd/open.c >@@ -2779,9 +2779,16 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, > > if (NT_STATUS_EQUAL(fsp_open, NT_STATUS_NETWORK_BUSY)) { > struct deferred_open_record state; >+ bool delay; > > /* >- * EWOULDBLOCK/EAGAIN maps to NETWORK_BUSY. >+ * This handles the kernel oplock case: >+ * >+ * the file has an active kernel oplock and the open() returned >+ * EWOULDBLOCK/EAGAIN which maps to NETWORK_BUSY. >+ * >+ * "Samba locking.tdb oplocks" are handled below after acquiring >+ * the sharemode lock with get_share_mode_lock(). > */ > if (file_existed && S_ISFIFO(fsp->fsp_name->st.st_ex_mode)) { > DEBUG(10, ("FIFO busy\n")); >@@ -2812,8 +2819,10 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, > smb_panic("validate_oplock_types failed"); > } > >- if (delay_for_oplock(fsp, 0, lease, lck, false, >- create_disposition, first_open_attempt)) { >+ delay = delay_for_oplock(fsp, 0, lease, lck, false, >+ create_disposition, >+ first_open_attempt); >+ if (delay) { > schedule_defer_open(lck, fsp->file_id, request_time, > req); > TALLOC_FREE(lck); >@@ -2934,15 +2943,27 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, > file_existed = true; > } > >- if ((req != NULL) && >- delay_for_oplock( >- fsp, oplock_request, lease, lck, >- NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION), >- create_disposition, first_open_attempt)) { >- schedule_defer_open(lck, fsp->file_id, request_time, req); >- TALLOC_FREE(lck); >- fd_close(fsp); >- return NT_STATUS_SHARING_VIOLATION; >+ if (req != NULL) { >+ /* >+ * Handle oplocks, deferring the request if delay_for_oplock() >+ * triggered a break message and we have to wait for the break >+ * response. >+ */ >+ bool delay; >+ bool sharing_violation = NT_STATUS_EQUAL( >+ status, NT_STATUS_SHARING_VIOLATION); >+ >+ delay = delay_for_oplock(fsp, oplock_request, lease, lck, >+ sharing_violation, >+ create_disposition, >+ first_open_attempt); >+ if (delay) { >+ schedule_defer_open(lck, fsp->file_id, >+ request_time, req); >+ TALLOC_FREE(lck); >+ fd_close(fsp); >+ return NT_STATUS_SHARING_VIOLATION; >+ } > } > > if (!NT_STATUS_IS_OK(status)) { >-- >2.9.3 > > >From 423c9149fab7305c56397b61dca43ba89b1bf45f Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Tue, 7 Mar 2017 14:10:39 +0100 >Subject: [PATCH 04/12] 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@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 8580adc1d968304b69237f289d13950972394b48) >--- > source3/smbd/open.c | 4 +--- > 1 file changed, 1 insertion(+), 3 deletions(-) > >diff --git a/source3/smbd/open.c b/source3/smbd/open.c >index 9817569..2afe601 100644 >--- a/source3/smbd/open.c >+++ b/source3/smbd/open.c >@@ -3071,9 +3071,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, > state.async_open = false; > state.id = id; > >- if ((req != NULL) >- && !request_timed_out(request_time, >- timeout)) { >+ if (!request_timed_out(request_time, timeout)) { > defer_open(lck, request_time, timeout, > req, &state); > } >-- >2.9.3 > > >From 41349f0cb5d24825a4544d7bca28c0ccc0134822 Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Tue, 7 Mar 2017 14:37:54 +0100 >Subject: [PATCH 05/12] 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@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit b17ff9b181b7b9730d32534e720c45faabfa6799) >--- > source3/smbd/open.c | 113 +++++++++++++++++++++++++++------------------------- > 1 file changed, 58 insertions(+), 55 deletions(-) > >diff --git a/source3/smbd/open.c b/source3/smbd/open.c >index 2afe601..070e228 100644 >--- a/source3/smbd/open.c >+++ b/source3/smbd/open.c >@@ -1913,6 +1913,27 @@ 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; >@@ -1928,24 +1949,32 @@ 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 async_open, >+ struct file_id id) > { >- struct deferred_open_record *open_rec; >- >- 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)); >- >- open_rec = talloc(NULL, struct deferred_open_record); >+ struct deferred_open_record *open_rec = NULL; >+ struct timeval abs_timeout; >+ >+ abs_timeout = timeval_sum(&request_time, &timeout); >+ >+ DBG_DEBUG("request time [%s] timeout [%s] mid [%" PRIu64 "] " >+ "delayed_for_oplocks [%s] async_open [%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", >+ async_open ? "yes" : "no", >+ file_id_string_tos(&id)); >+ >+ open_rec = deferred_open_record_create(delayed_for_oplocks, >+ async_open, >+ 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; >@@ -1972,12 +2001,12 @@ static void defer_open(struct share_mode_lock *lck, > > ret = tevent_req_set_endtime( > watch_req, req->sconn->ev_ctx, >- timeval_sum(&request_time, &timeout)); >+ abs_timeout); > SMB_ASSERT(ret); > } > > if (!push_deferred_open_message_smb(req, request_time, timeout, >- state->id, open_rec)) { >+ open_rec->id, open_rec)) { > TALLOC_FREE(lck); > exit_server("push_deferred_open_message_smb failed"); > } >@@ -2124,8 +2153,6 @@ static void schedule_defer_open(struct share_mode_lock *lck, > struct timeval request_time, > struct smb_request *req) > { >- 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 >@@ -2144,18 +2171,11 @@ 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, false, id); > } > > /**************************************************************************** >@@ -2165,18 +2185,16 @@ static void schedule_defer_open(struct share_mode_lock *lck, > static void schedule_async_open(struct timeval request_time, > struct smb_request *req) > { >- struct deferred_open_record state; > struct timeval timeout; > > timeout = timeval_set(20, 0); > >- ZERO_STRUCT(state); >- state.delayed_for_oplocks = false; >- state.async_open = true; >- >- if (!request_timed_out(request_time, timeout)) { >- defer_open(NULL, request_time, timeout, req, &state); >+ if (request_timed_out(request_time, timeout)) { >+ return; > } >+ >+ defer_open(NULL, request_time, timeout, req, >+ false, true, (struct file_id){0}); > } > > /**************************************************************************** >@@ -2778,7 +2796,6 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, > open_access_mask, &new_file_created); > > if (NT_STATUS_EQUAL(fsp_open, NT_STATUS_NETWORK_BUSY)) { >- struct deferred_open_record state; > bool delay; > > /* >@@ -2805,11 +2822,8 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, > > lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id); > if (lck == NULL) { >- state.delayed_for_oplocks = false; >- state.async_open = false; >- state.id = fsp->file_id; > defer_open(NULL, request_time, timeval_set(0, 0), >- req, &state); >+ req, false, false, fsp->file_id); > DEBUG(10, ("No share mode lock found after " > "EWOULDBLOCK, retrying sync\n")); > return NT_STATUS_SHARING_VIOLATION; >@@ -2835,10 +2849,9 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, > * No oplock from Samba around. Immediately retry with > * a blocking open. > */ >- state.delayed_for_oplocks = false; >- state.async_open = false; >- state.id = fsp->file_id; >- defer_open(lck, request_time, timeval_set(0, 0), req, &state); >+ defer_open(lck, request_time, timeval_set(0, 0), req, >+ false, false, fsp->file_id); >+ > TALLOC_FREE(lck); > DEBUG(10, ("No Samba oplock around after EWOULDBLOCK. " > "Retrying sync\n")); >@@ -3043,7 +3056,6 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, > !conn->sconn->using_smb2 && > lp_defer_sharing_violations()) { > struct timeval timeout; >- struct deferred_open_record state; > int timeout_usecs; > > /* this is a hack to speed up torture tests >@@ -3062,18 +3074,9 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, > > timeout = timeval_set(0, timeout_usecs); > >- /* 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 = False; >- state.async_open = false; >- state.id = id; >- > if (!request_timed_out(request_time, timeout)) { >- defer_open(lck, request_time, timeout, >- req, &state); >+ defer_open(lck, request_time, timeout, req, >+ false, false, id); > } > } > >-- >2.9.3 > > >From 7b56f791843a7f593d5c7bb93f884a10543d2c6f Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Tue, 7 Mar 2017 15:03:12 +0100 >Subject: [PATCH 06/12] 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@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit beaba6222848fb4ff4392b2247c5be1094b1d65b) >--- > source3/smbd/open.c | 40 ++++++++++++++++++++++++++++++++++++---- > 1 file changed, 36 insertions(+), 4 deletions(-) > >diff --git a/source3/smbd/open.c b/source3/smbd/open.c >index 070e228..9ffae48 100644 >--- a/source3/smbd/open.c >+++ b/source3/smbd/open.c >@@ -2037,6 +2037,40 @@ static void defer_open_done(struct tevent_req *req) > TALLOC_FREE(state); > } > >+/** >+ * 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. >@@ -2822,8 +2856,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, > > lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id); > if (lck == NULL) { >- defer_open(NULL, request_time, timeval_set(0, 0), >- req, false, false, fsp->file_id); >+ retry_open(request_time, req, fsp->file_id); > DEBUG(10, ("No share mode lock found after " > "EWOULDBLOCK, retrying sync\n")); > return NT_STATUS_SHARING_VIOLATION; >@@ -2849,8 +2882,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, > * No oplock from Samba around. Immediately retry with > * a blocking open. > */ >- defer_open(lck, request_time, timeval_set(0, 0), req, >- false, false, fsp->file_id); >+ retry_open(request_time, req, fsp->file_id); > > TALLOC_FREE(lck); > DEBUG(10, ("No Samba oplock around after EWOULDBLOCK. " >-- >2.9.3 > > >From af42193e1e7638768a0c4d75720d25938f72c71f Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Tue, 7 Mar 2017 15:33:55 +0100 >Subject: [PATCH 07/12] 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@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit ad8c36125f72e0d5f9ebfc94037a4ae9e7608aad) >--- > source3/smbd/open.c | 42 +++++++++++++++++++++++++++++++++++++----- > 1 file changed, 37 insertions(+), 5 deletions(-) > >diff --git a/source3/smbd/open.c b/source3/smbd/open.c >index 9ffae48..e76395d 100644 >--- a/source3/smbd/open.c >+++ b/source3/smbd/open.c >@@ -44,6 +44,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; > }; > > /**************************************************************************** >@@ -2216,19 +2223,44 @@ static void schedule_defer_open(struct share_mode_lock *lck, > Reschedule an open call that went asynchronous. > ****************************************************************************/ > >+static void schedule_async_open_timer(struct tevent_context *ev, >+ struct tevent_timer *te, >+ struct timeval current_time, >+ void *private_data) >+{ >+ exit_server("async open timeout"); >+} >+ > static void schedule_async_open(struct timeval request_time, > struct smb_request *req) > { >- struct timeval timeout; >- >- timeout = timeval_set(20, 0); >+ struct deferred_open_record *open_rec = NULL; >+ struct timeval timeout = timeval_set(20, 0); >+ bool ok; > > if (request_timed_out(request_time, timeout)) { > return; > } > >- defer_open(NULL, request_time, timeout, req, >- false, true, (struct file_id){0}); >+ open_rec = deferred_open_record_create(false, true, (struct file_id){0}); >+ if (open_rec == NULL) { >+ exit_server("deferred_open_record_create failed"); >+ } >+ >+ ok = push_deferred_open_message_smb(req, request_time, timeout, >+ (struct file_id){0}, open_rec); >+ if (!ok) { >+ exit_server("push_deferred_open_message_smb failed"); >+ } >+ >+ open_rec->te = tevent_add_timer(req->sconn->ev_ctx, >+ req, >+ timeval_current_ofs(20, 0), >+ schedule_async_open_timer, >+ open_rec); >+ if (open_rec->te == NULL) { >+ exit_server("tevent_add_timer failed"); >+ } > } > > /**************************************************************************** >-- >2.9.3 > > >From 6253bd95b017080940ffc3c82f8d05f72c37e446 Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Tue, 7 Mar 2017 19:11:20 +0100 >Subject: [PATCH 08/12] 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@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(cherry picked from commit 7fa2f1159437c9f1aa47f51e65655b4d9afa5c0a) >--- > source3/smbd/open.c | 10 ++++------ > 1 file changed, 4 insertions(+), 6 deletions(-) > >diff --git a/source3/smbd/open.c b/source3/smbd/open.c >index e76395d..cfe9135 100644 >--- a/source3/smbd/open.c >+++ b/source3/smbd/open.c >@@ -1957,7 +1957,6 @@ static void defer_open(struct share_mode_lock *lck, > struct timeval timeout, > struct smb_request *req, > bool delayed_for_oplocks, >- bool async_open, > struct file_id id) > { > struct deferred_open_record *open_rec = NULL; >@@ -1966,16 +1965,15 @@ static void defer_open(struct share_mode_lock *lck, > abs_timeout = timeval_sum(&request_time, &timeout); > > DBG_DEBUG("request time [%s] timeout [%s] mid [%" PRIu64 "] " >- "delayed_for_oplocks [%s] async_open [%s] file_id [%s]\n", >+ "delayed_for_oplocks [%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", >- async_open ? "yes" : "no", > file_id_string_tos(&id)); > > open_rec = deferred_open_record_create(delayed_for_oplocks, >- async_open, >+ false, > id); > if (open_rec == NULL) { > TALLOC_FREE(lck); >@@ -2216,7 +2214,7 @@ static void schedule_defer_open(struct share_mode_lock *lck, > return; > } > >- defer_open(lck, request_time, timeout, req, true, false, id); >+ defer_open(lck, request_time, timeout, req, true, id); > } > > /**************************************************************************** >@@ -3140,7 +3138,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, > > if (!request_timed_out(request_time, timeout)) { > defer_open(lck, request_time, timeout, req, >- false, false, id); >+ false, id); > } > } > >-- >2.9.3 > > >From a8db5a1f48a1cd7c2ca52585a9539724f114d84b Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Tue, 7 Mar 2017 15:48:05 +0100 >Subject: [PATCH 09/12] 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@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(backported from commit 1a6c82e5d5a3462827ee3fe1edab01f535f831a9) >--- > source3/smbd/open.c | 64 +++++++++++++++++++++++++++-------------------------- > 1 file changed, 33 insertions(+), 31 deletions(-) > >diff --git a/source3/smbd/open.c b/source3/smbd/open.c >index cfe9135..a2fda6d 100644 >--- a/source3/smbd/open.c >+++ b/source3/smbd/open.c >@@ -1948,10 +1948,15 @@ struct defer_open_state { > > 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, >@@ -1961,6 +1966,9 @@ static void defer_open(struct share_mode_lock *lck, > { > 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); > >@@ -1980,38 +1988,32 @@ static void defer_open(struct share_mode_lock *lck, > exit_server("talloc failed"); > } > >- 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; > >- DEBUG(10, ("defering mid %llu\n", >- (unsigned long long)req->mid)); >+ DBG_DEBUG("defering mid %" PRIu64 "\n", req->mid); > >- watch_req = dbwrap_record_watch_send( >- watch_state, req->sconn->ev_ctx, lck->data->record, >- req->sconn->msg_ctx); >- 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_record_watch_send( >+ watch_state, req->sconn->ev_ctx, lck->data->record, >+ req->sconn->msg_ctx); >+ 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, >- abs_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, >- open_rec->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"); > } >-- >2.9.3 > > >From 772dacb27314fa38898468e73129285a5ef504bd Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Tue, 7 Mar 2017 16:27:39 +0100 >Subject: [PATCH 10/12] 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@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(backported from commit b35a296a27a0807c780f2a9e7af2f2e93feefaa8) >--- > source3/smbd/open.c | 114 +++++++++++++++++++++++++++++++++++++++++++++++----- > 1 file changed, 103 insertions(+), 11 deletions(-) > >diff --git a/source3/smbd/open.c b/source3/smbd/open.c >index a2fda6d..1c67684 100644 >--- a/source3/smbd/open.c >+++ b/source3/smbd/open.c >@@ -1532,6 +1532,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; >@@ -1944,6 +1961,11 @@ static struct deferred_open_record *deferred_open_record_create( > 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); >@@ -1962,6 +1984,7 @@ static void defer_open(struct share_mode_lock *lck, > struct timeval timeout, > struct smb_request *req, > bool delayed_for_oplocks, >+ bool kernel_oplock, > struct file_id id) > { > struct deferred_open_record *open_rec = NULL; >@@ -1973,11 +1996,12 @@ static void defer_open(struct share_mode_lock *lck, > abs_timeout = timeval_sum(&request_time, &timeout); > > DBG_DEBUG("request time [%s] timeout [%s] mid [%" PRIu64 "] " >- "delayed_for_oplocks [%s] file_id [%s]\n", >+ "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 = deferred_open_record_create(delayed_for_oplocks, >@@ -1994,6 +2018,11 @@ static void defer_open(struct share_mode_lock *lck, > } > 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); > > DBG_DEBUG("defering mid %" PRIu64 "\n", req->mid); > >@@ -2023,8 +2052,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_record_watch_recv(req, talloc_tos(), NULL); > TALLOC_FREE(req); >@@ -2035,13 +2068,71 @@ 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; >+ } >+ } > } > >- DEBUG(10, ("scheduling mid %llu\n", (unsigned long long)state->mid)); >+ if (schedule_req) { >+ DBG_DEBUG("scheduling mid %" PRIu64 "\n", state->mid); > >- ret = schedule_deferred_open_message_smb(state->xconn, state->mid); >- SMB_ASSERT(ret); >- TALLOC_FREE(state); >+ 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; >+ } >+ >+ 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); >+ >+ watch_req = dbwrap_record_watch_send( >+ state, state->xconn->ev_ctx, lck->data->record, >+ state->xconn->msg_ctx); >+ 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); > } > > /** >@@ -2192,7 +2283,8 @@ 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) > { > /* This is a relative time, added to the absolute > request_time value to get the absolute timeout time. >@@ -2216,7 +2308,7 @@ static void schedule_defer_open(struct share_mode_lock *lck, > return; > } > >- defer_open(lck, request_time, timeout, req, true, id); >+ defer_open(lck, request_time, timeout, req, true, kernel_oplock, id); > } > > /**************************************************************************** >@@ -2903,7 +2995,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, > first_open_attempt); > if (delay) { > schedule_defer_open(lck, fsp->file_id, request_time, >- req); >+ req, true); > TALLOC_FREE(lck); > DEBUG(10, ("Sent oplock break request to kernel " > "oplock holder\n")); >@@ -3036,7 +3128,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, > first_open_attempt); > if (delay) { > schedule_defer_open(lck, fsp->file_id, >- request_time, req); >+ request_time, req, false); > TALLOC_FREE(lck); > fd_close(fsp); > return NT_STATUS_SHARING_VIOLATION; >@@ -3140,7 +3232,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, > > if (!request_timed_out(request_time, timeout)) { > defer_open(lck, request_time, timeout, req, >- false, id); >+ false, false, id); > } > } > >-- >2.9.3 > > >From 751e5fef0e28ce592b2f6adcc8b9b17c46196c07 Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Wed, 8 Mar 2017 07:18:36 +0100 >Subject: [PATCH 11/12] 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@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(backported from commit 6e54d8d2bda2c9232676f8c08c626f22de50f52b) >--- > source3/selftest/tests.py | 32 +++++++++++++++++++------------- > 1 file changed, 19 insertions(+), 13 deletions(-) > >diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py >index fd4f615..4ad8aa9 100755 >--- a/source3/selftest/tests.py >+++ b/source3/selftest/tests.py >@@ -36,6 +36,25 @@ 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) > > 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")]) >@@ -194,19 +213,6 @@ for env in ["fileserver"]: > # tar command tests > # > >- # find config.h >- try: >- config_h = os.environ["CONFIG_H"] >- except KeyError: >- 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 >-- >2.9.3 > > >From c18263b55ad43dddf57ee7a534d271c9a55e5249 Mon Sep 17 00:00:00 2001 >From: Ralph Boehme <slow@samba.org> >Date: Wed, 1 Mar 2017 18:13:35 +0100 >Subject: [PATCH 12/12] s4/torture: some tests for kernel oplocks > >Bug: https://bugzilla.samba.org/show_bug.cgi?id=7537 > >Signed-off-by: Ralph Boehme <slow@samba.org> >Reviewed-by: Jeremy Allison <jra@samba.org> >(backported from commit fd03420c4f59d3248b80d07a302d1404ce78b09f) >--- > selftest/target/Samba3.pm | 4 ++ > source3/selftest/tests.py | 4 ++ > source4/selftest/tests.py | 2 +- > source4/torture/smb2/oplock.c | 140 ++++++++++++++++++++++++++++++++++++++++++ > source4/torture/smb2/smb2.c | 1 + > 5 files changed, 150 insertions(+), 1 deletion(-) > >diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm >index 4596a0a..619ae1e 100755 >--- a/selftest/target/Samba3.pm >+++ b/selftest/target/Samba3.pm >@@ -1717,6 +1717,10 @@ sub provision($$$$$$$$) > copy = tmp > acl_xattr:ignore system acls = yes > acl_xattr:default acl style = windows >+[kernel_oplocks] >+ copy = tmp >+ kernel oplocks = yes >+ vfs objects = streams_xattr xattr_tdb > "; > close(CONF); > >diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py >index 4ad8aa9..9915fb6 100755 >--- a/source3/selftest/tests.py >+++ b/source3/selftest/tests.py >@@ -55,6 +55,7 @@ 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")]) >@@ -418,6 +419,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/source4/selftest/tests.py b/source4/selftest/tests.py >index 7eb4e46..073ff0a 100755 >--- a/source4/selftest/tests.py >+++ b/source4/selftest/tests.py >@@ -301,7 +301,7 @@ for t in nbt_tests: > ntvfsargs = ["--option=torture:sharedelay=100000", "--option=torture:oplocktimeout=3", "--option=torture:writetimeupdatedelay=500000"] > > # Filter smb2 tests that should not run against ad_dc_ntvfs >-smb2_s3only = ["smb2.change_notify_disabled", "smb2.dosmode"] >+smb2_s3only = ["smb2.change_notify_disabled", "smb2.dosmode", "smb2.kernel-oplocks"] > smb2 = [x for x in smbtorture4_testsuites("smb2.") if x not in smb2_s3only] > > #The QFILEINFO-IPC test needs to be on ipc$ >diff --git a/source4/torture/smb2/oplock.c b/source4/torture/smb2/oplock.c >index fdd29c3..11e1bdc 100644 >--- a/source4/torture/smb2/oplock.c >+++ b/source4/torture/smb2/oplock.c >@@ -4197,3 +4197,143 @@ bool test_smb2_hold_oplock(struct torture_context *tctx, > talloc_free(mem_ctx); > return true; > } >+ >+ >+static bool test_smb2_kernel_oplocks1(struct torture_context *tctx, >+ struct smb2_tree *tree) >+{ >+ const char *fname = "test_kernel_oplock1.dat"; >+ NTSTATUS status; >+ bool ret = true; >+ struct smb2_create create; >+ struct smb2_handle h1 = {{0}}, h2 = {{0}}; >+ >+ smb2_util_unlink(tree, fname); >+ >+ tree->session->transport->oplock.handler = torture_oplock_handler; >+ tree->session->transport->oplock.private_data = tree; >+ ZERO_STRUCT(break_info); >+ >+ ZERO_STRUCT(create); >+ create.in.desired_access = SEC_RIGHTS_FILE_ALL; >+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL; >+ create.in.share_access = NTCREATEX_SHARE_ACCESS_NONE; >+ create.in.create_disposition = NTCREATEX_DISP_OPEN_IF; >+ create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS; >+ create.in.fname = fname; >+ create.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE; >+ >+ status = smb2_create(tree, tctx, &create); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n"); >+ h1 = create.out.file.handle; >+ >+ torture_assert_goto(tctx, create.out.oplock_level == SMB2_OPLOCK_LEVEL_EXCLUSIVE, ret, done, >+ "Oplock level is not SMB2_OPLOCK_LEVEL_EXCLUSIVE\n"); >+ >+ ZERO_STRUCT(create); >+ create.in.desired_access = SEC_RIGHTS_FILE_ALL; >+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL; >+ create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK; >+ create.in.create_disposition = NTCREATEX_DISP_OPEN_IF; >+ create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS; >+ create.in.fname = fname; >+ >+ status = smb2_create(tree, tctx, &create); >+ torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_SHARING_VIOLATION, ret, done, >+ "Open didn't return NT_STATUS_SHARING_VIOLATION\n"); >+ h2 = create.out.file.handle; >+ >+ torture_wait_for_oplock_break(tctx); >+ if (break_info.count != 0) { >+ torture_warning(tctx, "Open caused oplock break\n"); >+ } >+ >+ smb2_util_close(tree, h1); >+ smb2_util_close(tree, h2); >+ >+done: >+ if (!smb2_util_handle_empty(h1)) { >+ smb2_util_close(tree, h1); >+ } >+ if (!smb2_util_handle_empty(h2)) { >+ smb2_util_close(tree, h2); >+ } >+ smb2_util_unlink(tree, fname); >+ return ret; >+} >+ >+static bool test_smb2_kernel_oplocks2(struct torture_context *tctx, >+ struct smb2_tree *tree) >+{ >+ const char *fname = "test_kernel_oplock2.dat"; >+ const char *sname = "test_kernel_oplock2.dat:foo"; >+ NTSTATUS status; >+ bool ret = true; >+ struct smb2_create create; >+ struct smb2_handle h1 = {{0}}, h2 = {{0}}; >+ >+ smb2_util_unlink(tree, fname); >+ >+ tree->session->transport->oplock.handler = torture_oplock_handler; >+ tree->session->transport->oplock.private_data = tree; >+ ZERO_STRUCT(break_info); >+ >+ ZERO_STRUCT(create); >+ create.in.desired_access = SEC_RIGHTS_FILE_ALL; >+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL; >+ create.in.share_access = NTCREATEX_SHARE_ACCESS_NONE; >+ create.in.create_disposition = NTCREATEX_DISP_OPEN_IF; >+ create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS; >+ create.in.fname = fname; >+ create.in.oplock_level = SMB2_OPLOCK_LEVEL_EXCLUSIVE; >+ >+ status = smb2_create(tree, tctx, &create); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n"); >+ h1 = create.out.file.handle; >+ >+ torture_assert_goto(tctx, create.out.oplock_level == SMB2_OPLOCK_LEVEL_EXCLUSIVE, ret, done, >+ "Oplock level is not SMB2_OPLOCK_LEVEL_EXCLUSIVE\n"); >+ >+ ZERO_STRUCT(create); >+ create.in.desired_access = SEC_RIGHTS_FILE_ALL; >+ create.in.file_attributes = FILE_ATTRIBUTE_NORMAL; >+ create.in.share_access = NTCREATEX_SHARE_ACCESS_MASK; >+ create.in.create_disposition = NTCREATEX_DISP_OPEN_IF; >+ create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS; >+ create.in.fname = sname; >+ >+ status = smb2_create(tree, tctx, &create); >+ torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "Error opening the file\n"); >+ h2 = create.out.file.handle; >+ >+ torture_wait_for_oplock_break(tctx); >+ if (break_info.count != 0) { >+ torture_warning(tctx, "Stream open caused oplock break\n"); >+ } >+ >+ smb2_util_close(tree, h1); >+ smb2_util_close(tree, h2); >+ >+done: >+ if (!smb2_util_handle_empty(h1)) { >+ smb2_util_close(tree, h1); >+ } >+ if (!smb2_util_handle_empty(h2)) { >+ smb2_util_close(tree, h2); >+ } >+ smb2_util_unlink(tree, fname); >+ return ret; >+} >+ >+struct torture_suite *torture_smb2_kernel_oplocks_init(void) >+{ >+ struct torture_suite *suite = >+ torture_suite_create(talloc_autofree_context(), "kernel-oplocks"); >+ >+ torture_suite_add_1smb2_test(suite, "kernel_oplocks1", test_smb2_kernel_oplocks1); >+ torture_suite_add_1smb2_test(suite, "kernel_oplocks2", test_smb2_kernel_oplocks2); >+ >+ suite->description = talloc_strdup(suite, "SMB2-KERNEL-OPLOCK tests"); >+ >+ return suite; >+} >diff --git a/source4/torture/smb2/smb2.c b/source4/torture/smb2/smb2.c >index be632cc..9f2f757 100644 >--- a/source4/torture/smb2/smb2.c >+++ b/source4/torture/smb2/smb2.c >@@ -163,6 +163,7 @@ NTSTATUS torture_smb2_init(void) > torture_suite_add_suite(suite, torture_smb2_lease_init()); > torture_suite_add_suite(suite, torture_smb2_compound_init()); > torture_suite_add_suite(suite, torture_smb2_oplocks_init()); >+ torture_suite_add_suite(suite, torture_smb2_kernel_oplocks_init()); > torture_suite_add_suite(suite, torture_smb2_streams_init()); > torture_suite_add_suite(suite, torture_smb2_ioctl_init()); > torture_suite_add_suite(suite, torture_smb2_rename_init()); >-- >2.9.3 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Flags:
jra
:
review+
Actions:
View
Attachments on
bug 7537
:
5824
|
13018
|
13048
|
13049
| 13050