[SCM] Samba Shared Repository - branch v4-0-test updated

Karolin Seeger kseeger at samba.org
Sun Jul 13 15:36:03 MDT 2014


The branch, v4-0-test has been updated
       via  cfbd1da torture4: Make raw.lock.multilock fail after 20 seconds
       via  d06fad8 torture4: Adapt comment to code
       via  90ca1fd s4: smbtorture: Add multi-lock test. Regression test for bug #10684.
       via  6207d7f s3: smbd: Locking - re-add pending lock records if we fail to acquire a lock (and the lock hasn't timed out).
       via  b1be3eb s3: smbd: Locking - treat lock timeout the same as any other error.
       via  9df5a51 s3: smbd: Locking - add and use utility function lock_timed_out().
       via  18fc716 s3: smbd: Locking - convert to using utility macro used elsewhere.
       via  f0cf96d net/doc: make clear that net vampire is for NT4 domains only
       via  09e777f selftest/subunithelper.py: correctly pass testsuite-uxsuccess to end_testsuite()
       via  c9a2f59 selftest/subunithelper.py: correctly handle fail_immediately in end_testsuite of FilterOps
       via  eef4181 selftest/subunithelper.py: correctly handle unexpected success in FilterOps
       via  78b755d script/autobuild: use --force-rebase option
      from  a064b7c torture3: Fix bug 10687

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=v4-0-test


- Log -----------------------------------------------------------------
commit cfbd1da69faceb75eb67bca0398f4fa1fb97941c
Author: Volker Lendecke <vl at samba.org>
Date:   Thu Jul 3 10:05:55 2014 +0000

    torture4: Make raw.lock.multilock fail after 20 seconds
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>
    
    Autobuild-User(master): Jeremy Allison <jra at samba.org>
    Autobuild-Date(master): Fri Jul  4 00:04:10 CEST 2014 on sn-devel-104
    
    (cherry picked from commit 0c97b7eb5359b95c0d51a3b5524e82e34243d2d1)
    
    The last 7 patches address bug #10684 - SMB1 blocking locks can fail
    notification on unlock, causing client timeout.
    
    Autobuild-User(v4-0-test): Karolin Seeger <kseeger at samba.org>
    Autobuild-Date(v4-0-test): Sun Jul 13 23:35:54 CEST 2014 on sn-devel-104

commit d06fad8bb8cd2e24eeb7cff48da2ed1c287bcafa
Author: Volker Lendecke <vl at samba.org>
Date:   Thu Jul 3 10:05:39 2014 +0000

    torture4: Adapt comment to code
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>
    (cherry picked from commit 4205463ef1815d6e86e1d1f1f57651ca30407469)

commit 90ca1fd13a3e1ee538502ffeac4a33033859d45b
Author: Jeremy Allison <jra at samba.org>
Date:   Tue Jul 1 12:05:07 2014 -0700

    s4: smbtorture: Add multi-lock test. Regression test for bug #10684.
    
    Bug #10684 - SMB1 blocking locks can fail notification on unlock, causing client timeout.
    
    https://bugzilla.samba.org/show_bug.cgi?id=10684
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Volker Lendecke <Volker.Lendecke at SerNet.DE>
    (cherry picked from commit 64346a134dac2bd023f7473202ca38d35ffd3c89)

commit 6207d7f17c5d8d2c32e096d7383770f147d1776a
Author: Jeremy Allison <jra at samba.org>
Date:   Wed Jul 2 20:51:24 2014 -0700

    s3: smbd: Locking - re-add pending lock records if we fail to acquire a lock (and the lock hasn't timed out).
    
    Keep the blocking lock record and the pending lock records consistent
    if we are dealing with multiple blocking lock requests in one SMB1 LockingX
    request.
    
    Ensure we re-add the records under the record lock, to avoid race
    conditions.
    
    Bug #10684 - SMB1 blocking locks can fail notification on unlock, causing client timeout.
    
    https://bugzilla.samba.org/show_bug.cgi?id=10684
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Volker Lendecke <Volker.Lendecke at SerNet.DE>
    (cherry picked from commit 954401f8b2b16b3e2ef9655e8ce94d657becce36)

commit b1be3eb040647e756eef4722d39e6d32e0f90c5f
Author: Jeremy Allison <jra at samba.org>
Date:   Wed Jul 2 20:40:49 2014 -0700

    s3: smbd: Locking - treat lock timeout the same as any other error.
    
    Allows the special case in process_blocking_lock_queue()
    that talks back to the client to be removed.
    
    Bug #10684 - SMB1 blocking locks can fail notification on unlock, causing client timeout.
    
    https://bugzilla.samba.org/show_bug.cgi?id=10684
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Volker Lendecke <Volker.Lendecke at SerNet.DE>
    (cherry picked from commit cc9de6eb091159a84228b988c49261c46c301233)

commit 9df5a516d3f11da70506695c4a50b57e92824328
Author: Jeremy Allison <jra at samba.org>
Date:   Wed Jul 2 20:18:42 2014 -0700

    s3: smbd: Locking - add and use utility function lock_timed_out().
    
    Bug #10684 - SMB1 blocking locks can fail notification on unlock, causing client timeout.
    
    https://bugzilla.samba.org/show_bug.cgi?id=10684
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Volker Lendecke <Volker.Lendecke at SerNet.DE>
    (cherry picked from commit 12be57ef3b2d1b670be7a83f29cd580938030015)

commit 18fc7166f0ab0615e9c3e29f0e33015abb2d5a4c
Author: Jeremy Allison <jra at samba.org>
Date:   Wed Jul 2 17:25:22 2014 -0700

    s3: smbd: Locking - convert to using utility macro used elsewhere.
    
    Bug #10684 - SMB1 blocking locks can fail notification on unlock, causing client timeout.
    
    https://bugzilla.samba.org/show_bug.cgi?id=10684
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Volker Lendecke <Volker.Lendecke at SerNet.DE>
    (cherry picked from commit 517fa80bd385c6adcfee03ea6b25599013ad88f5)

commit f0cf96dbebe10a9c131fd001ee854f205fef989c
Author: Björn Jacke <bj at sernet.de>
Date:   Fri Jun 13 14:14:41 2014 +0200

    net/doc: make clear that net vampire is for NT4 domains only
    
    https://bugzilla.samba.org/show_bug.cgi?id=3263
    
    Signed-off-by: Bjoern Jacke <bj at sernet.de>

commit 09e777f9a5d5583eb5c03ab8975a7c954aa7c828
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Mar 12 15:12:42 2014 +0100

    selftest/subunithelper.py: correctly pass testsuite-uxsuccess to end_testsuite()
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>
    
    Autobuild-User(master): Jeremy Allison <jra at samba.org>
    Autobuild-Date(master): Thu Mar 13 23:49:36 CET 2014 on sn-devel-104
    
    (cherry picked from commit 3632c59e250396b3974bccf7ad74cbe5c84fdba3)
    
    The last 4 patches address bug #10696 - backport autobuild/selftest fixes from
    master.

commit c9a2f59a7905cca663d15a755bb045017d7b0b83
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Mar 12 15:12:42 2014 +0100

    selftest/subunithelper.py: correctly handle fail_immediately in end_testsuite of FilterOps
    
    This way --fail-immediately also works if a command segfaults.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>
    (cherry picked from commit fee156f5b9235b5f766cb773433ddb7d0ccd98a1)

commit eef4181723a2f83b5dde049ae6c518eee163a8d4
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Mar 12 15:12:42 2014 +0100

    selftest/subunithelper.py: correctly handle unexpected success in FilterOps
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>
    (cherry picked from commit 14246953b2e91578e5f51faedfdf31926a5b1950)

commit 78b755db4e9bb8f724877d35fb25aec4f2a775c3
Author: Stefan Metzmacher <metze at samba.org>
Date:   Mon Feb 17 09:15:30 2014 +0100

    script/autobuild: use --force-rebase option
    
    This makes sure the current user will be the committer.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>
    (cherry picked from commit ab9f02193188af8e482052ee6b55c30aac2c8340)

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

Summary of changes:
 docs-xml/manpages/net.8.xml |    2 +
 script/autobuild.py         |    4 +-
 selftest/subunithelper.py   |   25 +++++-
 source3/smbd/blocking.c     |  195 ++++++++++++++++++++++++++++--------------
 source4/torture/raw/lock.c  |   97 +++++++++++++++++++++
 5 files changed, 254 insertions(+), 69 deletions(-)


Changeset truncated at 500 lines:

diff --git a/docs-xml/manpages/net.8.xml b/docs-xml/manpages/net.8.xml
index 3765af9..bd46cff 100644
--- a/docs-xml/manpages/net.8.xml
+++ b/docs-xml/manpages/net.8.xml
@@ -981,6 +981,8 @@ to run this against the PDC, from a Samba machine joined as a BDC. </para>
 
 <para>Export users, aliases and groups from remote server to 
 local server.  You need to run this against the PDC, from a Samba machine joined as a BDC. 
+This vampire command cannot be used against an Active Directory, only
+against an NT4 Domain Controller.
 </para>
 </refsect2>
 
diff --git a/script/autobuild.py b/script/autobuild.py
index 76e777c..a54cb15 100755
--- a/script/autobuild.py
+++ b/script/autobuild.py
@@ -417,11 +417,11 @@ def rebase_tree(rebase_url, rebase_branch = "master"):
             show=True, dir=test_master)
     run_cmd("git fetch %s" % rebase_remote, show=True, dir=test_master)
     if options.fix_whitespace:
-        run_cmd("git rebase --whitespace=fix %s/%s" %
+        run_cmd("git rebase --force-rebase --whitespace=fix %s/%s" %
                 (rebase_remote, rebase_branch),
                 show=True, dir=test_master)
     else:
-        run_cmd("git rebase %s/%s" %
+        run_cmd("git rebase --force-rebase %s/%s" %
                 (rebase_remote, rebase_branch),
                 show=True, dir=test_master)
     diff = run_cmd("git --no-pager diff HEAD %s/%s" %
diff --git a/selftest/subunithelper.py b/selftest/subunithelper.py
index 057e139..6f1fdce 100644
--- a/selftest/subunithelper.py
+++ b/selftest/subunithelper.py
@@ -24,7 +24,7 @@ import subunit.iso8601
 import testtools
 from testtools import content, content_type
 
-VALID_RESULTS = ['success', 'successful', 'failure', 'fail', 'skip', 'knownfail', 'error', 'xfail', 'skip-testsuite', 'testsuite-failure', 'testsuite-xfail', 'testsuite-success', 'testsuite-error', 'uxsuccess']
+VALID_RESULTS = ['success', 'successful', 'failure', 'fail', 'skip', 'knownfail', 'error', 'xfail', 'skip-testsuite', 'testsuite-failure', 'testsuite-xfail', 'testsuite-success', 'testsuite-error', 'uxsuccess', 'testsuite-uxsuccess']
 
 class TestsuiteEnabledTestResult(testtools.testresult.TestResult):
 
@@ -158,6 +158,9 @@ def parse_results(msg_ops, statistics, fh):
                 exitcode = 1
             elif result == "testsuite-xfail":
                 msg_ops.end_testsuite(testname, "xfail", reason)
+            elif result == "testsuite-uxsuccess":
+                msg_ops.end_testsuite(testname, "uxsuccess", reason)
+                exitcode = 1
             elif result == "testsuite-error":
                 msg_ops.end_testsuite(testname, "error", reason)
                 exitcode = 1
@@ -301,8 +304,14 @@ class FilterOps(testtools.testresult.TestResult):
 
     def addUnexpectedSuccess(self, test, details=None):
         test = self._add_prefix(test)
+        self.uxsuccess_added+=1
+        self.total_uxsuccess+=1
         self._ops.addUnexpectedSuccess(test, details)
+        if self.output:
+            self._ops.output_msg(self.output)
         self.output = None
+        if self.fail_immediately:
+            raise ImmediateFail()
 
     def addFailure(self, test, details=None):
         test = self._add_prefix(test)
@@ -362,12 +371,18 @@ class FilterOps(testtools.testresult.TestResult):
 
         if self.xfail_added > 0:
             xfail = True
-        if self.fail_added > 0 or self.error_added > 0:
+        if self.fail_added > 0 or self.error_added > 0 or self.uxsuccess_added > 0:
             xfail = False
 
         if xfail and result in ("fail", "failure"):
             result = "xfail"
 
+        if self.uxsuccess_added > 0 and result != "uxsuccess":
+            result = "uxsuccess"
+            if reason is None:
+                reason = "Subunit/Filter Reason"
+            reason += "\n uxsuccess[%d]" % self.uxsuccess_added
+
         if self.fail_added > 0 and result != "failure":
             result = "failure"
             if reason is None:
@@ -381,6 +396,12 @@ class FilterOps(testtools.testresult.TestResult):
             reason += "\n errors[%d]" % self.error_added
 
         self._ops.end_testsuite(name, result, reason)
+        if result not in ("success", "xfail"):
+            if self.output:
+                self._ops.output_msg(self.output)
+            if self.fail_immediately:
+                raise ImmediateFail()
+        self.output = None
 
     def __init__(self, out, prefix=None, suffix=None, expected_failures=None,
                  strip_ok_output=False, fail_immediately=False,
diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c
index 100944c..7132084 100644
--- a/source3/smbd/blocking.c
+++ b/source3/smbd/blocking.c
@@ -430,6 +430,25 @@ static void blocking_lock_reply_error(struct blocking_lock_record *blr, NTSTATUS
 }
 
 /****************************************************************************
+ Utility function that returns true if a lock timed out.
+*****************************************************************************/
+
+static bool lock_timed_out(const struct blocking_lock_record *blr)
+{
+	struct timeval tv_curr;
+
+	if (timeval_is_zero(&blr->expire_time)) {
+		return false; /* Never times out. */
+	}
+
+	tv_curr = timeval_current();
+	if (timeval_compare(&blr->expire_time, &tv_curr) <= 0) {
+		return true;
+	}
+	return false;
+}
+
+/****************************************************************************
  Attempt to finish off getting all pending blocking locks for a lockingX call.
  Returns True if we want to be removed from the list.
 *****************************************************************************/
@@ -440,11 +459,10 @@ static bool process_lockingX(struct blocking_lock_record *blr)
 	files_struct *fsp = blr->fsp;
 	uint16 num_ulocks = SVAL(blr->req->vwv+6, 0);
 	uint16 num_locks = SVAL(blr->req->vwv+7, 0);
-	uint64_t count = (uint64_t)0, offset = (uint64_t)0;
-	uint64_t smblctx;
 	bool large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES);
 	uint8_t *data;
 	NTSTATUS status = NT_STATUS_OK;
+	bool lock_timeout = lock_timed_out(blr);
 
 	data = discard_const_p(uint8_t, blr->req->buf)
 		+ ((large_file_format ? 20 : 10)*num_ulocks);
@@ -458,9 +476,14 @@ static bool process_lockingX(struct blocking_lock_record *blr)
 		struct byte_range_lock *br_lck = NULL;
 		bool err;
 
-		smblctx = get_lock_pid( data, blr->lock_num, large_file_format);
-		count = get_lock_count( data, blr->lock_num, large_file_format);
-		offset = get_lock_offset( data, blr->lock_num, large_file_format, &err);
+		/*
+		 * Ensure the blr record gets updated with
+		 * any lock we might end up blocked on.
+		 */
+
+		blr->smblctx = get_lock_pid( data, blr->lock_num, large_file_format);
+		blr->count = get_lock_count( data, blr->lock_num, large_file_format);
+		blr->offset = get_lock_offset( data, blr->lock_num, large_file_format, &err);
 
 		/*
 		 * We know err cannot be set as if it was the lock
@@ -469,9 +492,9 @@ static bool process_lockingX(struct blocking_lock_record *blr)
 		errno = 0;
 		br_lck = do_lock(fsp->conn->sconn->msg_ctx,
 				fsp,
-				smblctx,
-				count,
-				offset,
+				blr->smblctx,
+				blr->count,
+				blr->offset,
 				((locktype & LOCKING_ANDX_SHARED_LOCK) ?
 					READ_LOCK : WRITE_LOCK),
 				WINDOWS_LOCK,
@@ -480,6 +503,34 @@ static bool process_lockingX(struct blocking_lock_record *blr)
 				&blr->blocking_smblctx,
 				blr);
 
+		if (ERROR_WAS_LOCK_DENIED(status) && !lock_timeout) {
+			/*
+			 * If we didn't timeout, but still need to wait,
+			 * re-add the pending lock entry whilst holding
+			 * the brlock db lock.
+			 */
+			NTSTATUS status1 =
+				brl_lock(blr->fsp->conn->sconn->msg_ctx,
+					br_lck,
+					blr->smblctx,
+					messaging_server_id(
+						blr->fsp->conn->sconn->msg_ctx),
+					blr->offset,
+					blr->count,
+					blr->lock_type == READ_LOCK ?
+						PENDING_READ_LOCK :
+						PENDING_WRITE_LOCK,
+						blr->lock_flav,
+					true, /* Blocking lock. */
+					NULL,
+					blr);
+
+			if (!NT_STATUS_IS_OK(status1)) {
+				DEBUG(0,("failed to add PENDING_LOCK "
+					"record.\n"));
+			}
+		}
+
 		TALLOC_FREE(br_lck);
 
 		if (NT_STATUS_IS_ERR(status)) {
@@ -500,8 +551,7 @@ static bool process_lockingX(struct blocking_lock_record *blr)
 		return True;
 	}
 
-	if (!NT_STATUS_EQUAL(status,NT_STATUS_LOCK_NOT_GRANTED) &&
-	    !NT_STATUS_EQUAL(status,NT_STATUS_FILE_LOCK_CONFLICT)) {
+	if (!ERROR_WAS_LOCK_DENIED(status)) {
 		/*
 		 * We have other than a "can't get lock"
 		 * error. Free any locks we had and return an error.
@@ -512,6 +562,14 @@ static bool process_lockingX(struct blocking_lock_record *blr)
 	}
 
 	/*
+	 * Return an error to the client if we timed out.
+	 */
+	if (lock_timeout) {
+		blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT);
+		return true;
+	}
+
+	/*
 	 * Still can't get all the locks - keep waiting.
 	 */
 
@@ -532,6 +590,8 @@ static bool process_trans2(struct blocking_lock_record *blr)
 {
 	char params[2];
 	NTSTATUS status;
+	bool lock_timeout = lock_timed_out(blr);
+
 	struct byte_range_lock *br_lck = do_lock(
 						blr->fsp->conn->sconn->msg_ctx,
 						blr->fsp,
@@ -544,10 +604,46 @@ static bool process_trans2(struct blocking_lock_record *blr)
 						&status,
 						&blr->blocking_smblctx,
 						blr);
+	if (ERROR_WAS_LOCK_DENIED(status) && !lock_timeout) {
+		/*
+		 * If we didn't timeout, but still need to wait,
+		 * re-add the pending lock entry whilst holding
+		 * the brlock db lock.
+		 */
+		NTSTATUS status1 =
+			brl_lock(blr->fsp->conn->sconn->msg_ctx,
+				br_lck,
+				blr->smblctx,
+				messaging_server_id(
+					blr->fsp->conn->sconn->msg_ctx),
+				blr->offset,
+				blr->count,
+				blr->lock_type == READ_LOCK ?
+					PENDING_READ_LOCK :
+					PENDING_WRITE_LOCK,
+				blr->lock_flav,
+				true, /* Blocking lock. */
+				NULL,
+				blr);
+
+		if (!NT_STATUS_IS_OK(status1)) {
+			DEBUG(0,("failed to add PENDING_LOCK record.\n"));
+		}
+	}
+
 	TALLOC_FREE(br_lck);
 
 	if (!NT_STATUS_IS_OK(status)) {
 		if (ERROR_WAS_LOCK_DENIED(status)) {
+			if (lock_timeout) {
+				/*
+				 * Return an error if we timed out
+				 * and return true to get dequeued.
+				 */
+				blocking_lock_reply_error(blr,
+					NT_STATUS_FILE_LOCK_CONFLICT);
+				return true;
+			}
 			/* Still can't get the lock, just keep waiting. */
 			return False;
 		}	
@@ -735,11 +831,10 @@ static void received_unlock_msg(struct messaging_context *msg,
 
 void process_blocking_lock_queue(struct smbd_server_connection *sconn)
 {
-	struct timeval tv_curr = timeval_current();
 	struct blocking_lock_record *blr, *next = NULL;
 
 	if (sconn->using_smb2) {
-		process_blocking_lock_queue_smb2(sconn, tv_curr);
+		process_blocking_lock_queue_smb2(sconn, timeval_current());
 		return;
 	}
 
@@ -748,6 +843,7 @@ void process_blocking_lock_queue(struct smbd_server_connection *sconn)
 	 */
 
 	for (blr = sconn->smb1.locks.blocking_lock_queue; blr; blr = next) {
+		struct byte_range_lock *br_lck = NULL;
 
 		next = blr->next;
 
@@ -767,65 +863,34 @@ void process_blocking_lock_queue(struct smbd_server_connection *sconn)
 				SVAL(blr->req->inbuf,smb_flg),
 				false);
 
-		if(blocking_lock_record_process(blr)) {
-			struct byte_range_lock *br_lck = brl_get_locks(
-				talloc_tos(), blr->fsp);
-
-			DEBUG(10, ("BLR_process returned true: cancelling and "
-			    "removing lock. BLR = %p\n", blr));
-
-			if (br_lck) {
-				brl_lock_cancel(br_lck,
-					blr->smblctx,
-					messaging_server_id(sconn->msg_ctx),
-					blr->offset,
-					blr->count,
-					blr->lock_flav,
-					blr);
-				TALLOC_FREE(br_lck);
-			}
-
-			DLIST_REMOVE(sconn->smb1.locks.blocking_lock_queue, blr);
-			TALLOC_FREE(blr);
-			continue;
-		}
-
 		/*
-		 * We couldn't get the locks for this record on the list.
-		 * If the time has expired, return a lock error.
+		 * Remove the pending lock we're waiting on.
+		 * If we need to keep waiting blocking_lock_record_process()
+		 * will re-add it.
 		 */
 
-		if (!timeval_is_zero(&blr->expire_time) && timeval_compare(&blr->expire_time, &tv_curr) <= 0) {
-			struct byte_range_lock *br_lck = brl_get_locks(
-				talloc_tos(), blr->fsp);
-
-			DEBUG(10, ("Lock timed out! BLR = %p\n", blr));
-
-			/*
-			 * Lock expired - throw away all previously
-			 * obtained locks and return lock error.
-			 */
+		br_lck = brl_get_locks(talloc_tos(), blr->fsp);
+		if (br_lck) {
+			brl_lock_cancel(br_lck,
+				blr->smblctx,
+				messaging_server_id(sconn->msg_ctx),
+				blr->offset,
+				blr->count,
+				blr->lock_flav,
+				blr);
+		}
+		TALLOC_FREE(br_lck);
 
-			if (br_lck) {
-				DEBUG(5,("process_blocking_lock_queue: "
-					 "pending lock for %s, file %s "
-					 "timed out.\n", fsp_fnum_dbg(blr->fsp),
-					 fsp_str_dbg(blr->fsp)));
+		if(!blocking_lock_record_process(blr)) {
+			DEBUG(10, ("still waiting for lock. BLR = %p\n", blr));
+			continue;
+		}
 
-				brl_lock_cancel(br_lck,
-					blr->smblctx,
-					messaging_server_id(sconn->msg_ctx),
-					blr->offset,
-					blr->count,
-					blr->lock_flav,
-					blr);
-				TALLOC_FREE(br_lck);
-			}
+		DEBUG(10, ("BLR_process returned true: removing BLR = %p\n",
+			blr));
 
-			blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT);
-			DLIST_REMOVE(sconn->smb1.locks.blocking_lock_queue, blr);
-			TALLOC_FREE(blr);
-		}
+		DLIST_REMOVE(sconn->smb1.locks.blocking_lock_queue, blr);
+		TALLOC_FREE(blr);
 	}
 
 	recalc_brl_timeout(sconn);
diff --git a/source4/torture/raw/lock.c b/source4/torture/raw/lock.c
index a31a4d0..e131e27 100644
--- a/source4/torture/raw/lock.c
+++ b/source4/torture/raw/lock.c
@@ -2262,6 +2262,102 @@ done:
 	smbcli_deltree(cli->tree, BASEDIR);
 	return ret;
 }
+/*
+  test multi Locking&X operation
+*/
+static bool test_multilock(struct torture_context *tctx,
+					   struct smbcli_state *cli)
+{
+	union smb_lock io;
+	struct smb_lock_entry lock[2];
+	NTSTATUS status;
+	bool ret = true;
+	int fnum;
+	const char *fname = BASEDIR "\\multilock_test.txt";
+	time_t t;
+	struct smbcli_request *req;
+	struct smbcli_session_options options;
+
+	torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
+
+	lpcfg_smbcli_session_options(tctx->lp_ctx, &options);
+
+	torture_comment(tctx, "Testing LOCKING_ANDX multi-lock\n");
+	io.generic.level = RAW_LOCK_LOCKX;
+
+	/* Create the test file. */
+	fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
+	torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
+		       "Failed to create %s - %s\n",
+		       fname, smbcli_errstr(cli->tree)));
+
+	/*
+	 * Lock regions 100->109, 120->129 as
+	 * two separate write locks in one request.
+	 */
+	io.lockx.level = RAW_LOCK_LOCKX;
+	io.lockx.in.file.fnum = fnum;
+	io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
+	io.lockx.in.timeout = 0;
+	io.lockx.in.ulock_cnt = 0;
+	io.lockx.in.lock_cnt = 2;
+	io.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
+	lock[0].pid = cli->session->pid;
+	lock[0].offset = 100;
+	lock[0].count = 10;
+	lock[1].pid = cli->session->pid;
+	lock[1].offset = 120;
+	lock[1].count = 10;
+	io.lockx.in.locks = &lock[0];
+	status = smb_raw_lock(cli->tree, &io);
+	CHECK_STATUS(status, NT_STATUS_OK);
+
+	/*
+	 * Now request the same locks on a different
+	 * context as blocking locks with infinite timeout.
+	 */
+
+	io.lockx.in.timeout = 20000;
+	lock[0].pid = cli->session->pid+1;
+	lock[1].pid = cli->session->pid+1;
+	req = smb_raw_lock_send(cli->tree, &io);
+	torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
+		       "Failed to setup timed locks (%s)\n", __location__));
+
+	/* Unlock lock[0] */
+	io.lockx.in.timeout = 0;
+	io.lockx.in.ulock_cnt = 1;
+	io.lockx.in.lock_cnt = 0;
+	io.lockx.in.locks = &lock[0];
+	lock[0].pid = cli->session->pid;
+	status = smb_raw_lock(cli->tree, &io);
+	CHECK_STATUS(status, NT_STATUS_OK);
+
+	/* Start the clock. */
+	t = time_mono(NULL);
+
+	/* Unlock lock[1] */
+	io.lockx.in.timeout = 0;
+	io.lockx.in.ulock_cnt = 1;
+	io.lockx.in.lock_cnt = 0;
+	io.lockx.in.locks = &lock[1];
+	lock[1].pid = cli->session->pid;
+	status = smb_raw_lock(cli->tree, &io);
+	CHECK_STATUS(status, NT_STATUS_OK);
+
+	/* receive the successful blocked lock requests */
+	status = smbcli_request_simple_recv(req);
+	CHECK_STATUS(status, NT_STATUS_OK);
+
+	/* Fail if this took more than 2 seconds. */
+	torture_assert(tctx,!(time_mono(NULL) > t+2), talloc_asprintf(tctx,
+		       "Blocking locks were not granted immediately (%s)\n",
+		       __location__));


-- 
Samba Shared Repository


More information about the samba-cvs mailing list