[SCM] Samba Shared Repository - branch master updated

Steven Danneman sdanneman at samba.org
Mon Dec 7 17:19:26 MST 2009


The branch, master has been updated
       via  47f5aac... s4/torture: add test for zero byte read contention with byte range locks
       via  995b480... s4/libcli: add define for exclusive lock mode
       via  b4c72e4... s4/torture: fix >80 column spacing issues
       via  0c42d65... s4/torture: add delete-on-close test for directories
      from  a246310... parent_sd can never be null in this function, so don't check for it.

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 47f5aac39d4a81f37ae0d8656ac75d985b24053b
Author: Steven Danneman <steven.danneman at isilon.com>
Date:   Thu Dec 3 18:50:33 2009 -0800

    s4/torture: add test for zero byte read contention with byte range locks

commit 995b4800f820a9d4415026e677aaad8de7668b92
Author: Steven Danneman <steven.danneman at isilon.com>
Date:   Thu Dec 3 18:32:56 2009 -0800

    s4/libcli: add define for exclusive lock mode

commit b4c72e44a83157768ae991e72d824f56a381eab6
Author: Steven Danneman <steven.danneman at isilon.com>
Date:   Thu Dec 3 19:32:53 2009 -0800

    s4/torture: fix >80 column spacing issues

commit 0c42d65d7cbc24b96f0e9ec700d32da860060174
Author: Aravind Srinivasan <aravind.srinivasan at isilon.com>
Date:   Tue Nov 17 12:28:34 2009 -0800

    s4/torture: add delete-on-close test for directories
    
    This test opens a directory with delete on close, opens it again,
    and checks to make sure that the second open returned with
    NT_STATUS_DELETE_PENDING.

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

Summary of changes:
 source4/libcli/raw/smb.h       |    1 +
 source4/selftest/knownfail     |    2 +
 source4/torture/basic/delete.c |   63 ++++++++++++++++
 source4/torture/raw/lock.c     |  162 +++++++++++++++++++++++++++++++++++++++-
 source4/torture/smb2/lock.c    |  132 +++++++++++++++++++++++++++++++--
 5 files changed, 350 insertions(+), 10 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source4/libcli/raw/smb.h b/source4/libcli/raw/smb.h
index 4fbf76f..349705d 100644
--- a/source4/libcli/raw/smb.h
+++ b/source4/libcli/raw/smb.h
@@ -559,6 +559,7 @@
 #define UID_FIELD_INVALID 0
 
 /* Lock types. */
+#define LOCKING_ANDX_EXCLUSIVE_LOCK  0x00
 #define LOCKING_ANDX_SHARED_LOCK     0x01
 #define LOCKING_ANDX_OPLOCK_RELEASE  0x02
 #define LOCKING_ANDX_CHANGE_LOCKTYPE 0x04
diff --git a/source4/selftest/knownfail b/source4/selftest/knownfail
index b9d40f2..ef3c10c 100644
--- a/source4/selftest/knownfail
+++ b/source4/selftest/knownfail
@@ -67,3 +67,5 @@ samba4.raw.lock.*.async # bug 6960
 samba4.smb2.lock.*.MULTIPLE-UNLOCK # bug 6959
 samba4.raw.sfileinfo.*.END-OF-FILE # bug 6962
 samba4.raw.oplock.*.BATCH22 # bug 6963
+samba4.raw.lock.*.zerobyteread # bug 6974
+samba4.smb2.lock.*.ZEROBYTEREAD # bug 6974
diff --git a/source4/torture/basic/delete.c b/source4/torture/basic/delete.c
index 0f7c939..22d9219 100644
--- a/source4/torture/basic/delete.c
+++ b/source4/torture/basic/delete.c
@@ -1515,9 +1515,71 @@ static bool deltest22(struct torture_context *tctx)
 
 	CHECK_STATUS(cli1, NT_STATUS_DELETE_PENDING);
 
+	smbcli_close(cli1->tree, dnum2);
+	CHECK_STATUS(cli1, NT_STATUS_OK);
+
 	return correct;
 }
 
+/* Test 23 - Second directory open fails when delete is pending. */
+static bool deltest23(struct torture_context *tctx,
+			struct smbcli_state *cli1,
+			struct smbcli_state *cli2)
+{
+	int dnum1 = -1;
+	int dnum2 = -1;
+	bool correct = true;
+	NTSTATUS status;
+
+	del_clean_area(cli1, cli2);
+
+	/* Test 23 -- Basic delete on close for directories. */
+
+	/* Open a directory */
+	dnum1 = smbcli_nt_create_full(cli1->tree, dname, 0,
+				      SEC_FILE_READ_DATA|
+				      SEC_FILE_WRITE_DATA|
+				      SEC_STD_DELETE,
+				      FILE_ATTRIBUTE_DIRECTORY,
+				      NTCREATEX_SHARE_ACCESS_READ|
+				      NTCREATEX_SHARE_ACCESS_WRITE|
+				      NTCREATEX_SHARE_ACCESS_DELETE,
+				      NTCREATEX_DISP_CREATE,
+				      NTCREATEX_OPTIONS_DIRECTORY, 0);
+
+	torture_assert(tctx, dnum1 != -1, talloc_asprintf(tctx,
+			   "open of %s failed: %s!",
+			   dname, smbcli_errstr(cli1->tree)));
+
+	correct &= check_delete_on_close(tctx, cli1, dnum1, dname, false,
+	    __location__);
+
+	/* Set delete on close */
+	status = smbcli_nt_delete_on_close(cli1->tree, dnum1, true);
+
+	/* Attempt opening the directory again.  It should fail. */
+	dnum2 = smbcli_nt_create_full(cli1->tree, dname, 0,
+				      SEC_FILE_READ_DATA|
+				      SEC_FILE_WRITE_DATA|
+				      SEC_STD_DELETE,
+				      FILE_ATTRIBUTE_DIRECTORY,
+				      NTCREATEX_SHARE_ACCESS_READ|
+				      NTCREATEX_SHARE_ACCESS_WRITE|
+				      NTCREATEX_SHARE_ACCESS_DELETE,
+				      NTCREATEX_DISP_OPEN,
+				      NTCREATEX_OPTIONS_DIRECTORY, 0);
+
+	torture_assert(tctx, dnum2 == -1, talloc_asprintf(tctx,
+			   "open of %s succeeded: %s. It should have failed "
+			   "with NT_STATUS_DELETE_PENDING",
+			   dname, smbcli_errstr(cli1->tree)));
+
+	torture_assert_ntstatus_equal(tctx, smbcli_nt_error(cli1->tree),
+	    NT_STATUS_DELETE_PENDING, "smbcli_open failed");
+
+	return true;
+}
+
 /*
   Test delete on close semantics.
  */
@@ -1551,6 +1613,7 @@ struct torture_suite *torture_test_delete(void)
 	torture_suite_add_2smb_test(suite, "deltest20b", deltest20b);
 	torture_suite_add_simple_test(suite, "deltest21", deltest21);
 	torture_suite_add_simple_test(suite, "deltest22", deltest22);
+	torture_suite_add_2smb_test(suite, "deltest23", deltest23);
 
 	return suite;
 }
diff --git a/source4/torture/raw/lock.c b/source4/torture/raw/lock.c
index 6871ed3..34b05b7 100644
--- a/source4/torture/raw/lock.c
+++ b/source4/torture/raw/lock.c
@@ -71,9 +71,10 @@
 
 #define TARGET_IS_W2K8(_tctx) (torture_setting_bool(_tctx, "w2k8", false))
 #define TARGET_IS_WIN7(_tctx) (torture_setting_bool(_tctx, "win7", false))
-#define TARGET_IS_WINDOWS(_tctx) ((torture_setting_bool(_tctx, "w2k8", false)) || \
-				  (torture_setting_bool(_tctx, "win7", false)) || \
-				  (torture_setting_bool(_tctx, "w2k3", false)))
+#define TARGET_IS_WINDOWS(_tctx) \
+	((torture_setting_bool(_tctx, "w2k3", false)) || \
+	 (torture_setting_bool(_tctx, "w2k8", false)) || \
+	 (torture_setting_bool(_tctx, "win7", false)))
 #define TARGET_IS_SAMBA3(_tctx) (torture_setting_bool(_tctx, "samba3", false))
 #define TARGET_IS_SAMBA4(_tctx) (torture_setting_bool(_tctx, "samba4", false))
 
@@ -1996,7 +1997,158 @@ done:
 	return ret;
 }
 
-/* 
+/**
+ * Test how 0-byte read requests contend with byte range locks
+ */
+static bool test_zerobyteread(struct torture_context *tctx,
+			      struct smbcli_state *cli)
+{
+	union smb_lock io;
+	union smb_read rd;
+	NTSTATUS status;
+	bool ret = true;
+	int fnum1, fnum2;
+	const char *fname = BASEDIR "\\zerobyteread.txt";
+	struct smb_lock_entry lock1;
+	uint8_t c = 1;
+
+	if (!torture_setup_dir(cli, BASEDIR)) {
+		return false;
+	}
+
+	io.generic.level = RAW_LOCK_LOCKX;
+
+	fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
+	torture_assert(tctx,(fnum1 != -1), talloc_asprintf(tctx,
+		       "Failed to create %s - %s\n",
+		       fname, smbcli_errstr(cli->tree)));
+
+	fnum2 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
+	torture_assert(tctx,(fnum2 != -1), talloc_asprintf(tctx,
+		       "Failed to create %s - %s\n",
+		       fname, smbcli_errstr(cli->tree)));
+
+	/* Setup initial parameters */
+	io.lockx.level = RAW_LOCK_LOCKX;
+	io.lockx.in.timeout = 0;
+
+	lock1.pid = cli->session->pid;
+	lock1.offset = 0;
+	lock1.count = 10;
+
+	ZERO_STRUCT(rd);
+	rd.readx.level = RAW_READ_READX;
+
+	torture_comment(tctx, "Testing zero byte read on lock range:\n");
+
+	/* Take an exclusive lock */
+	torture_comment(tctx, "  taking exclusive lock.\n");
+	io.lockx.in.ulock_cnt = 0;
+	io.lockx.in.lock_cnt = 1;
+	io.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
+	io.lockx.in.file.fnum = fnum1;
+	io.lockx.in.locks = &lock1;
+	status = smb_raw_lock(cli->tree, &io);
+	CHECK_STATUS(status, NT_STATUS_OK);
+
+	/* Try a zero byte read */
+	torture_comment(tctx, "  reading 0 bytes.\n");
+	rd.readx.in.file.fnum = fnum2;
+	rd.readx.in.offset    = 5;
+	rd.readx.in.mincnt    = 0;
+	rd.readx.in.maxcnt    = 0;
+	rd.readx.in.remaining = 0;
+	rd.readx.in.read_for_execute = false;
+	rd.readx.out.data     = &c;
+	status = smb_raw_read(cli->tree, &rd);
+	torture_assert_int_equal_goto(tctx, rd.readx.out.nread, 0, ret, done,
+				      "zero byte read did not return 0 bytes");
+	CHECK_STATUS(status, NT_STATUS_OK);
+
+	/* Unlock lock */
+	io.lockx.in.ulock_cnt = 1;
+	io.lockx.in.lock_cnt = 0;
+	io.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
+	io.lockx.in.file.fnum = fnum1;
+	io.lockx.in.locks = &lock1;
+	status = smb_raw_lock(cli->tree, &io);
+	CHECK_STATUS(status, NT_STATUS_OK);
+
+	torture_comment(tctx, "Testing zero byte read on zero byte lock "
+			      "range:\n");
+
+	/* Take an exclusive lock */
+	torture_comment(tctx, "  taking exclusive 0-byte lock.\n");
+	io.lockx.in.ulock_cnt = 0;
+	io.lockx.in.lock_cnt = 1;
+	io.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
+	io.lockx.in.file.fnum = fnum1;
+	io.lockx.in.locks = &lock1;
+	lock1.offset = 5;
+	lock1.count = 0;
+	status = smb_raw_lock(cli->tree, &io);
+	CHECK_STATUS(status, NT_STATUS_OK);
+
+	/* Try a zero byte read before the lock */
+	torture_comment(tctx, "  reading 0 bytes before the lock.\n");
+	rd.readx.in.file.fnum = fnum2;
+	rd.readx.in.offset    = 4;
+	rd.readx.in.mincnt    = 0;
+	rd.readx.in.maxcnt    = 0;
+	rd.readx.in.remaining = 0;
+	rd.readx.in.read_for_execute = false;
+	rd.readx.out.data     = &c;
+	status = smb_raw_read(cli->tree, &rd);
+	torture_assert_int_equal_goto(tctx, rd.readx.out.nread, 0, ret, done,
+				      "zero byte read did not return 0 bytes");
+	CHECK_STATUS(status, NT_STATUS_OK);
+
+	/* Try a zero byte read on the lock */
+	torture_comment(tctx, "  reading 0 bytes on the lock.\n");
+	rd.readx.in.file.fnum = fnum2;
+	rd.readx.in.offset    = 5;
+	rd.readx.in.mincnt    = 0;
+	rd.readx.in.maxcnt    = 0;
+	rd.readx.in.remaining = 0;
+	rd.readx.in.read_for_execute = false;
+	rd.readx.out.data     = &c;
+	status = smb_raw_read(cli->tree, &rd);
+	torture_assert_int_equal_goto(tctx, rd.readx.out.nread, 0, ret, done,
+				      "zero byte read did not return 0 bytes");
+	CHECK_STATUS(status, NT_STATUS_OK);
+
+	/* Try a zero byte read after the lock */
+	torture_comment(tctx, "  reading 0 bytes after the lock.\n");
+	rd.readx.in.file.fnum = fnum2;
+	rd.readx.in.offset    = 6;
+	rd.readx.in.mincnt    = 0;
+	rd.readx.in.maxcnt    = 0;
+	rd.readx.in.remaining = 0;
+	rd.readx.in.read_for_execute = false;
+	rd.readx.out.data     = &c;
+	status = smb_raw_read(cli->tree, &rd);
+	torture_assert_int_equal_goto(tctx, rd.readx.out.nread, 0, ret, done,
+				      "zero byte read did not return 0 bytes");
+	CHECK_STATUS(status, NT_STATUS_OK);
+
+	/* Unlock lock */
+	io.lockx.in.ulock_cnt = 1;
+	io.lockx.in.lock_cnt = 0;
+	io.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
+	io.lockx.in.file.fnum = fnum1;
+	io.lockx.in.locks = &lock1;
+	status = smb_raw_lock(cli->tree, &io);
+	CHECK_STATUS(status, NT_STATUS_OK);
+
+done:
+	smbcli_close(cli->tree, fnum1);
+	smbcli_close(cli->tree, fnum2);
+	smb_raw_exit(cli->session);
+	smbcli_deltree(cli->tree, BASEDIR);
+	return ret;
+}
+
+/*
    basic testing of lock calls
 */
 struct torture_suite *torture_raw_lock(TALLOC_CTX *mem_ctx)
@@ -2016,6 +2168,8 @@ struct torture_suite *torture_raw_lock(TALLOC_CTX *mem_ctx)
 	    test_multiple_unlock);
 	torture_suite_add_1smb_test(suite, "zerobytelocks",
 	    test_zerobytelocks);
+	torture_suite_add_1smb_test(suite, "zerobyteread",
+	    test_zerobyteread);
 
 	return suite;
 }
diff --git a/source4/torture/smb2/lock.c b/source4/torture/smb2/lock.c
index ba97a54..508358e 100644
--- a/source4/torture/smb2/lock.c
+++ b/source4/torture/smb2/lock.c
@@ -1453,6 +1453,124 @@ done:
 	return ret;
 }
 
+static bool test_zerobyteread(struct torture_context *torture,
+			      struct smb2_tree *tree)
+{
+	NTSTATUS status;
+	bool ret = true;
+	struct smb2_handle h, h2;
+	uint8_t buf[200];
+	struct smb2_lock lck;
+	struct smb2_lock_element el[1];
+	struct smb2_read rd;
+
+	const char *fname = BASEDIR "\\zerobyteread.txt";
+
+	status = torture_smb2_testdir(tree, BASEDIR, &h);
+	CHECK_STATUS(status, NT_STATUS_OK);
+	smb2_util_close(tree, h);
+
+	status = torture_smb2_testfile(tree, fname, &h);
+	CHECK_STATUS(status, NT_STATUS_OK);
+
+	ZERO_STRUCT(buf);
+	status = smb2_util_write(tree, h, buf, 0, ARRAY_SIZE(buf));
+	CHECK_STATUS(status, NT_STATUS_OK);
+
+	status = torture_smb2_testfile(tree, fname, &h2);
+	CHECK_STATUS(status, NT_STATUS_OK);
+
+	/* Setup initial parameters */
+	lck.in.locks		= el;
+	lck.in.lock_count	= 0x0001;
+	lck.in.lock_sequence	= 0x00000000;
+	lck.in.file.handle	= h;
+
+	ZERO_STRUCT(rd);
+	rd.in.file.handle = h2;
+
+	torture_comment(torture, "Testing zero byte read on lock range:\n");
+
+	/* Take an exclusive lock */
+	torture_comment(torture, "  taking exclusive lock.\n");
+	el[0].offset		= 0;
+	el[0].length		= 10;
+	el[0].reserved		= 0x00000000;
+	el[0].flags		= SMB2_LOCK_FLAG_EXCLUSIVE |
+				  SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
+	status = smb2_lock(tree, &lck);
+	CHECK_STATUS(status, NT_STATUS_OK);
+	CHECK_VALUE(lck.out.reserved, 0);
+
+	/* Try a zero byte read */
+	torture_comment(torture, "  reading 0 bytes.\n");
+	rd.in.offset      = 5;
+	rd.in.length      = 0;
+	status = smb2_read(tree, tree, &rd);
+	torture_assert_int_equal_goto(torture, rd.out.data.length, 0, ret, done,
+				      "zero byte read did not return 0 bytes");
+	CHECK_STATUS(status, NT_STATUS_OK);
+
+	/* Unlock lock */
+	el[0].flags		= SMB2_LOCK_FLAG_UNLOCK;
+	status = smb2_lock(tree, &lck);
+	CHECK_STATUS(status, NT_STATUS_OK);
+	CHECK_VALUE(lck.out.reserved, 0);
+
+	torture_comment(torture, "Testing zero byte read on zero byte lock "
+				 "range:\n");
+
+	/* Take an exclusive lock */
+	torture_comment(torture, "  taking exclusive 0-byte lock.\n");
+	el[0].offset		= 5;
+	el[0].length		= 0;
+	el[0].reserved		= 0x00000000;
+	el[0].flags		= SMB2_LOCK_FLAG_EXCLUSIVE |
+				  SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
+	status = smb2_lock(tree, &lck);
+	CHECK_STATUS(status, NT_STATUS_OK);
+	CHECK_VALUE(lck.out.reserved, 0);
+
+	/* Try a zero byte read before the lock */
+	torture_comment(torture, "  reading 0 bytes before the lock.\n");
+	rd.in.offset      = 4;
+	rd.in.length      = 0;
+	status = smb2_read(tree, tree, &rd);
+	torture_assert_int_equal_goto(torture, rd.out.data.length, 0, ret, done,
+				      "zero byte read did not return 0 bytes");
+	CHECK_STATUS(status, NT_STATUS_OK);
+
+	/* Try a zero byte read on the lock */
+	torture_comment(torture, "  reading 0 bytes on the lock.\n");
+	rd.in.offset      = 5;
+	rd.in.length      = 0;
+	status = smb2_read(tree, tree, &rd);
+	torture_assert_int_equal_goto(torture, rd.out.data.length, 0, ret, done,
+				      "zero byte read did not return 0 bytes");
+	CHECK_STATUS(status, NT_STATUS_OK);
+
+	/* Try a zero byte read after the lock */
+	torture_comment(torture, "  reading 0 bytes after the lock.\n");
+	rd.in.offset      = 6;
+	rd.in.length      = 0;
+	status = smb2_read(tree, tree, &rd);
+	torture_assert_int_equal_goto(torture, rd.out.data.length, 0, ret, done,
+				      "zero byte read did not return 0 bytes");
+	CHECK_STATUS(status, NT_STATUS_OK);
+
+	/* Unlock lock */
+	el[0].flags		= SMB2_LOCK_FLAG_UNLOCK;
+	status = smb2_lock(tree, &lck);
+	CHECK_STATUS(status, NT_STATUS_OK);
+	CHECK_VALUE(lck.out.reserved, 0);
+
+done:
+	smb2_util_close(tree, h2);
+	smb2_util_close(tree, h);
+	smb2_deltree(tree, BASEDIR);
+	return ret;
+}
+
 static bool test_unlock(struct torture_context *torture,
 		        struct smb2_tree *tree)
 {
@@ -2626,8 +2744,8 @@ static bool test_overlap(struct torture_context *torture,
 	      NT_STATUS_IS_OK(torture_smb2_testfile(tree, fname, &h)) &&
 	      NT_STATUS_IS_OK(smb2cli_lock(tree, h, 7, 1, true));
 	EXPECTED(ret, true);
-	torture_comment(torture, "the server %s have the NT byte range lock bug\n",
-				 !ret?"does":"doesn't");
+	torture_comment(torture, "the server %s have the NT byte range lock "
+				 "bug\n", !ret?"does":"doesn't");
 
 done:
 	smb2_util_close(tree2, h3);
@@ -2694,8 +2812,8 @@ static bool test_truncate(struct torture_context *torture,
 	CHECK_STATUS(status, NT_STATUS_OK);
 
 	/* On second handle open the file with OVERWRITE disposition */
-	torture_comment(torture, "  overwrite disposition is allowed on a locked "
-				 "file.\n");
+	torture_comment(torture, "  overwrite disposition is allowed on a "
+				 "locked file.\n");
 
 	io.in.create_disposition = NTCREATEX_DISP_OVERWRITE;
 	status = smb2_create(tree, tree, &io);
@@ -2704,8 +2822,8 @@ static bool test_truncate(struct torture_context *torture,
 	smb2_util_close(tree, h2);
 
 	/* On second handle open the file with SUPERSEDE disposition */
-	torture_comment(torture, "  supersede disposition is allowed on a locked "
-				 "file.\n");
+	torture_comment(torture, "  supersede disposition is allowed on a "
+				 "locked file.\n");
 
 	io.in.create_disposition = NTCREATEX_DISP_SUPERSEDE;
 	status = smb2_create(tree, tree, &io);
@@ -2750,6 +2868,8 @@ struct torture_suite *torture_smb2_lock_init(void)
 	torture_suite_add_1smb2_test(suite, "ERRORCODE", test_errorcode);
 	torture_suite_add_1smb2_test(suite, "ZEROBYTELENGTH",
 	    test_zerobytelength);
+	torture_suite_add_1smb2_test(suite, "ZEROBYTEREAD",
+	    test_zerobyteread);
 	torture_suite_add_1smb2_test(suite, "UNLOCK", test_unlock);
 	torture_suite_add_1smb2_test(suite, "MULTIPLE-UNLOCK",
 	    test_multiple_unlock);


-- 
Samba Shared Repository


More information about the samba-cvs mailing list