]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
s4/torture: add a test for rename change notification with inotify enabled
authorRalph Boehme <slow@samba.org>
Thu, 13 Jul 2017 14:05:49 +0000 (16:05 +0200)
committerKarolin Seeger <kseeger@samba.org>
Wed, 25 Oct 2017 06:43:01 +0000 (08:43 +0200)
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@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
Autobuild-User(master): Jeremy Allison <jra@samba.org>
Autobuild-Date(master): Sat Aug 26 05:05:08 CEST 2017 on sn-devel-144

(backported from commit 51f40a0e1d10069f55a5884ff1579e8f15f10a1e)

source4/torture/smb2/notify.c
source4/torture/smb2/smb2.c

index 90f5ad9a6337ffe691020eb7e90c827c7caa726c..8ca413a9b016ccc046e98d7edb9d8fb4da79d964 100644 (file)
@@ -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(void)
        return suite;
 }
 
+/*
+   basic testing of SMB2 change notify
+*/
+struct torture_suite *torture_smb2_notify_inotify_init(void)
+{
+       struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "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;
+}
index cfea98327833085280df4f70a36751a135b9bd28..0b82276929dda4a646893ce5762a84095245cbbb 100644 (file)
@@ -155,6 +155,7 @@ NTSTATUS torture_smb2_init(void)
        torture_suite_add_suite(suite, torture_smb2_create_init());
        torture_suite_add_suite(suite, torture_smb2_acls_init());
        torture_suite_add_suite(suite, torture_smb2_notify_init());
+       torture_suite_add_suite(suite, torture_smb2_notify_inotify_init());
        torture_suite_add_suite(suite, torture_smb2_notify_disabled_init());
        torture_suite_add_suite(suite, torture_smb2_durable_open_init());
        torture_suite_add_suite(suite, torture_smb2_durable_open_disconnect_init());