[PATCH] Test for bug 12903

Ralph Böhme slow at samba.org
Fri Aug 25 14:46:04 UTC 2017


Hi!

Attached is a testcase that prooves that bug 12903 "File change notification for
renames not working" got fixed by a bunch of messaging patches from Volker
(5eccc2fd0072409f166c63e6876266f926411423~10..5eccc2fd0072409f166c63e6876266f926411423).

The fixes are in master and 4.7, but we need backports for 4.6 and 4.5. The
patches apply cleanly and work for 4.6 as well, still have to check 4.5.

Please review & push if ok. Once this patces are in, I'll roll up backports of
the fix alongside the testcase.

Cheerio!
-slow
-------------- next part --------------
From 1bc4bb4794ed39bb9ecd8a9e24b2e722a73e663d Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Thu, 13 Jul 2017 16:01:53 +0200
Subject: [PATCH 1/3] selftest: enable kernel change notifications in the
 fileserver environment

This environment is currently not used for any test in the smb2
testsuite, so this change doesn't affect any existing test.

A subsequent commit will add a test for change notifications with kernel
change notify enabled. It verifies a bug (this one) that only crops up
in such a setup and causes rename events to get lost.

Bug: https://bugzilla.samba.org/show_bug.cgi?id=12903

Signed-off-by: Ralph Boehme <slow at samba.org>
---
 selftest/target/Samba3.pm | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm
index 54da52b..45c00ba 100755
--- a/selftest/target/Samba3.pm
+++ b/selftest/target/Samba3.pm
@@ -884,6 +884,8 @@ sub setup_fileserver($$)
 	push(@dirs,$usershare_sharedir);
 
 	my $fileserver_options = "
+	kernel change notify = yes
+
 	usershare path = $usershare_dir
 	usershare max shares = 10
 	usershare allow guests = yes
-- 
2.9.4


From dc4750110994047bc5657c0bc1dc95542923f4a0 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Thu, 13 Jul 2017 16:04:50 +0200
Subject: [PATCH 2/3] selftest: run smb2.notify-inotify testsuite against
 fileserver

Next commit adds the suite and a test.

Bug: https://bugzilla.samba.org/show_bug.cgi?id=12903

Signed-off-by: Ralph Boehme <slow at samba.org>
---
 source3/selftest/tests.py | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py
index a624f85..17d34cc 100755
--- a/source3/selftest/tests.py
+++ b/source3/selftest/tests.py
@@ -56,6 +56,7 @@ finally:
 
 have_libarchive = ("HAVE_LIBARCHIVE" in config_hash)
 have_linux_kernel_oplocks = ("HAVE_KERNEL_OPLOCKS_LINUX" in config_hash)
+have_inotify = ("HAVE_INOTIFY" 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")])
@@ -502,6 +503,9 @@ for t in tests:
     elif t == "smb2.kernel-oplocks":
         if have_linux_kernel_oplocks:
             plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER/kernel_oplocks -U$USERNAME%$PASSWORD')
+    elif t == "smb2.notify-inotify":
+        if have_inotify:
+            plansmbtorture4testsuite(t, "fileserver", '//$SERVER_IP/tmp -U$USERNAME%$PASSWORD')
     elif t == "vfs.acl_xattr":
         plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/tmp -U$USERNAME%$PASSWORD')
     elif t == "smb2.compound_find":
-- 
2.9.4


From 414d2a3b375c9ca9cb458e0b50d1b50bf572a419 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Thu, 13 Jul 2017 16:05:49 +0200
Subject: [PATCH 3/3] s4/torture: add a test for rename change notification
 with inotify enabled

This is already fixed in master by
5eccc2fd0072409f166c63e6876266f926411423~10..5eccc2fd0072409f166c63e6876266f926411423.

Bug: https://bugzilla.samba.org/show_bug.cgi?id=12903

Signed-off-by: Ralph Boehme <slow at samba.org>
---
 source4/torture/smb2/notify.c | 158 ++++++++++++++++++++++++++++++++++++++++++
 source4/torture/smb2/smb2.c   |   1 +
 2 files changed, 159 insertions(+)

diff --git a/source4/torture/smb2/notify.c b/source4/torture/smb2/notify.c
index 9fc856c..936a4d2 100644
--- a/source4/torture/smb2/notify.c
+++ b/source4/torture/smb2/notify.c
@@ -2354,6 +2354,151 @@ static bool torture_smb2_notify_rmdir4(struct torture_context *torture,
 	return torture_smb2_notify_rmdir(torture, tree1, tree2, true);
 }
 
+static void notify_timeout(struct tevent_context *ev,
+			   struct tevent_timer *te,
+			   struct timeval current_time,
+			   void *private_data)
+{
+	struct smb2_request *req = talloc_get_type_abort(
+		private_data, struct smb2_request);
+
+	smb2_cancel(req);
+}
+
+static bool torture_smb2_inotify_rename(struct torture_context *torture,
+					struct smb2_tree *tree1,
+					struct smb2_tree *tree2)
+{
+	NTSTATUS status;
+	struct smb2_notify notify;
+	struct notify_changes change1 = {0};
+	struct notify_changes change2 = {0};
+ 	struct smb2_create create;
+	union smb_setfileinfo sinfo;
+	struct smb2_handle h1 = {{0}};
+	struct smb2_handle h2 = {{0}};
+	struct smb2_request *req;
+	struct tevent_timer *te = NULL;
+	bool ok = false;
+
+	smb2_deltree(tree1, BASEDIR);
+
+	torture_comment(torture, "Testing change notify of a rename with inotify\n");
+
+	status = torture_smb2_testdir(tree1, BASEDIR, &h1);
+	torture_assert_ntstatus_ok_goto(torture, status, ok, done, "torture_smb2_testdir failed");
+
+	ZERO_STRUCT(create);
+	create.in.desired_access = SEC_RIGHTS_FILE_READ |
+		SEC_RIGHTS_FILE_WRITE|
+		SEC_RIGHTS_FILE_ALL;
+	create.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
+	create.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
+	create.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
+		NTCREATEX_SHARE_ACCESS_WRITE |
+		NTCREATEX_SHARE_ACCESS_DELETE;
+	create.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
+	create.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
+	create.in.fname = BASEDIR "\\subdir-name";
+
+	status = smb2_create(tree2, torture, &create);
+	torture_assert_ntstatus_ok_goto(torture, status, ok, done, "smb2_create failed\n");
+	h2 = create.out.file.handle;
+
+	ZERO_STRUCT(notify);
+	notify.level = RAW_NOTIFY_SMB2;
+	notify.in.buffer_size = 4096;
+	notify.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
+	notify.in.file.handle = h1;
+	notify.in.recursive = true;
+	req = smb2_notify_send(tree1, &notify);
+	torture_assert_not_null_goto(torture, req, ok, done, "smb2_notify_send failed\n");
+
+	while (!NT_STATUS_EQUAL(req->status, STATUS_PENDING)) {
+		if (tevent_loop_once(torture->ev) != 0) {
+			return false;
+		}
+	}
+
+	ZERO_STRUCT(sinfo);
+	sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
+	sinfo.rename_information.in.file.handle = h2;
+	sinfo.rename_information.in.new_name = BASEDIR "\\subdir-name-r";
+
+	status = smb2_setinfo_file(tree2, &sinfo);
+	torture_assert_ntstatus_ok_goto(torture, status, ok, done, "smb2_setinfo_file failed\n");
+
+	smb2_util_close(tree2, h2);
+
+	te = tevent_add_timer(torture->ev,
+			      tree1,
+			      tevent_timeval_current_ofs(1, 0),
+			      notify_timeout,
+			      req);
+	torture_assert_not_null_goto(torture, te, ok, done, "tevent_add_timer failed\n");
+
+	status = smb2_notify_recv(req, torture, &notify);
+	torture_assert_ntstatus_ok_goto(torture, status, ok, done, "smb2_notify_recv failed\n");
+
+	torture_assert_goto(torture, notify.out.num_changes == 1 || notify.out.num_changes == 2,
+			    ok, done, "bad notify\n");
+
+	change1 = notify.out.changes[0];
+	if (notify.out.num_changes == 2) {
+		change2 = notify.out.changes[1];
+	} else {
+		/*
+		 * We may only get one event at a time, so check for the
+		 * matching second event for the oldname/newname or
+		 * removed/added pair.
+		 */
+		ZERO_STRUCT(notify);
+		notify.level = RAW_NOTIFY_SMB2;
+		notify.in.buffer_size = 4096;
+		notify.in.completion_filter = FILE_NOTIFY_CHANGE_NAME;
+		notify.in.file.handle = h1;
+		notify.in.recursive = true;
+		req = smb2_notify_send(tree1, &notify);
+		torture_assert_not_null_goto(torture, req, ok, done, "smb2_notify_send failed\n");
+
+		status = smb2_notify_recv(req, torture, &notify);
+		torture_assert_ntstatus_ok_goto(torture, status, ok, done, "smb2_notify_recv failed\n");
+
+		torture_assert_goto(torture, notify.out.num_changes == 1, ok, done,
+				    "bad notify\n");
+
+		change2 = notify.out.changes[0];
+	}
+
+	if ((change1.action != NOTIFY_ACTION_OLD_NAME) &&
+	    (change1.action != NOTIFY_ACTION_REMOVED))
+	{
+		torture_fail_goto(torture, done, "bad change notification\n");
+	}
+	torture_assert_str_equal_goto(torture, change1.name.s, "subdir-name",
+			    ok, done, "bad change notification\n");
+
+	if ((change2.action != NOTIFY_ACTION_NEW_NAME) &&
+	    (change2.action != NOTIFY_ACTION_ADDED))
+	{
+		torture_fail_goto(torture, done, "bad change notification\n");
+	}
+	torture_assert_str_equal_goto(torture, change2.name.s, "subdir-name-r",
+			    ok, done, "bad change notification\n");
+
+	ok = true;
+done:
+	if (!smb2_util_handle_empty(h1)) {
+		smb2_util_close(tree2, h1);
+	}
+	if (!smb2_util_handle_empty(h2)) {
+		smb2_util_close(tree2, h2);
+	}
+
+	smb2_deltree(tree1, BASEDIR);
+	return ok;
+}
+
 /*
    basic testing of SMB2 change notify
 */
@@ -2393,3 +2538,16 @@ struct torture_suite *torture_smb2_notify_init(TALLOC_CTX *ctx)
 	return suite;
 }
 
+/*
+   basic testing of SMB2 change notify
+*/
+struct torture_suite *torture_smb2_notify_inotify_init(TALLOC_CTX *ctx)
+{
+	struct torture_suite *suite = torture_suite_create(ctx, "notify-inotify");
+
+	suite->description = talloc_strdup(suite, "SMB2-NOTIFY tests that use inotify");
+
+	torture_suite_add_2smb2_test(suite, "inotify-rename", torture_smb2_inotify_rename);
+
+	return suite;
+}
diff --git a/source4/torture/smb2/smb2.c b/source4/torture/smb2/smb2.c
index 352a36e..344cf5a 100644
--- a/source4/torture/smb2/smb2.c
+++ b/source4/torture/smb2/smb2.c
@@ -155,6 +155,7 @@ NTSTATUS torture_smb2_init(TALLOC_CTX *ctx)
 	torture_suite_add_suite(suite, torture_smb2_create_init(suite));
 	torture_suite_add_suite(suite, torture_smb2_acls_init(suite));
 	torture_suite_add_suite(suite, torture_smb2_notify_init(suite));
+	torture_suite_add_suite(suite, torture_smb2_notify_inotify_init(suite));
 	torture_suite_add_suite(suite,
 		torture_smb2_notify_disabled_init(suite));
 	torture_suite_add_suite(suite, torture_smb2_durable_open_init(suite));
-- 
2.9.4



More information about the samba-technical mailing list