summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/torture/raw/oplock.c109
-rw-r--r--source4/torture/raw/raw.c1
2 files changed, 110 insertions, 0 deletions
diff --git a/source4/torture/raw/oplock.c b/source4/torture/raw/oplock.c
index f1779ad9cf..7a921af422 100644
--- a/source4/torture/raw/oplock.c
+++ b/source4/torture/raw/oplock.c
@@ -1388,3 +1388,112 @@ done:
talloc_free(mem_ctx);
return ret;
}
+
+
+static struct hold_oplock_info {
+ const char *fname;
+ bool close_on_break;
+ uint32_t share_access;
+ uint16_t fnum;
+} hold_info[] = {
+ { BASEDIR "\\notshared_close", True,
+ NTCREATEX_SHARE_ACCESS_NONE, },
+ { BASEDIR "\\notshared_noclose", False,
+ NTCREATEX_SHARE_ACCESS_NONE, },
+ { BASEDIR "\\shared_close", True,
+ NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, },
+ { BASEDIR "\\shared_noclose", False,
+ NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, },
+};
+
+static BOOL oplock_handler_hold(struct smbcli_transport *transport, uint16_t tid,
+ uint16_t fnum, uint8_t level, void *private)
+{
+ struct smbcli_tree *tree = private;
+ struct hold_oplock_info *info;
+ int i;
+
+ for (i=0;i<ARRAY_SIZE(hold_info);i++) {
+ if (hold_info[i].fnum == fnum) break;
+ }
+
+ if (i == ARRAY_SIZE(hold_info)) {
+ printf("oplock break for unknown fnum %u\n", fnum);
+ return False;
+ }
+
+ info = &hold_info[i];
+
+ if (info->close_on_break) {
+ printf("oplock break on %s - closing\n",
+ info->fname);
+ oplock_handler_close(transport, tid, fnum, level, private);
+ return True;
+ }
+
+ printf("oplock break on %s - acking break\n", info->fname);
+
+ return smbcli_oplock_ack(tree, fnum, OPLOCK_BREAK_TO_NONE);
+}
+
+
+/*
+ used for manual testing of oplocks - especially interaction with
+ other filesystems (such as NFS and local access)
+*/
+BOOL torture_hold_oplock(struct torture_context *torture,
+ struct smbcli_state *cli)
+{
+ struct event_context *ev = cli->transport->socket->event.ctx;
+ int i;
+
+ printf("Setting up open files with oplocks in %s\n", BASEDIR);
+
+ if (!torture_setup_dir(cli, BASEDIR)) {
+ return False;
+ }
+
+ smbcli_oplock_handler(cli->transport, oplock_handler_hold, cli->tree);
+
+ /* setup the files */
+ for (i=0;i<ARRAY_SIZE(hold_info);i++) {
+ union smb_open io;
+ NTSTATUS status;
+
+ io.generic.level = RAW_OPEN_NTCREATEX;
+ io.ntcreatex.in.root_fid = 0;
+ io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
+ io.ntcreatex.in.alloc_size = 0;
+ io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+ io.ntcreatex.in.share_access = hold_info[i].share_access;
+ io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
+ io.ntcreatex.in.create_options = 0;
+ io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+ io.ntcreatex.in.security_flags = 0;
+ io.ntcreatex.in.fname = hold_info[i].fname;
+ io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
+ NTCREATEX_FLAGS_REQUEST_OPLOCK |
+ NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
+ printf("opening %s\n", hold_info[i].fname);
+
+ status = smb_raw_open(cli->tree, cli, &io);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("Failed to open %s - %s\n",
+ hold_info[i].fname, nt_errstr(status));
+ return False;
+ }
+
+ if (io.ntcreatex.out.oplock_level != BATCH_OPLOCK_RETURN) {
+ printf("Oplock not granted for %s - expected %d but got %d\n",
+ hold_info[i].fname, BATCH_OPLOCK_RETURN,
+ io.ntcreatex.out.oplock_level);
+ return False;
+ }
+ hold_info[i].fnum = io.ntcreatex.out.file.fnum;
+ }
+
+ printf("Waiting for oplock events\n");
+ event_loop_wait(ev);
+
+ return True;
+}
diff --git a/source4/torture/raw/raw.c b/source4/torture/raw/raw.c
index 85db92661b..d85f267035 100644
--- a/source4/torture/raw/raw.c
+++ b/source4/torture/raw/raw.c
@@ -44,6 +44,7 @@ NTSTATUS torture_raw_init(void)
torture_suite_add_1smb_test(suite, "OPEN", torture_raw_open);
torture_suite_add_1smb_test(suite, "MKDIR", torture_raw_mkdir);
torture_suite_add_suite(suite, torture_raw_oplock(suite));
+ torture_suite_add_1smb_test(suite, "HOLD-OPLOCK", torture_hold_oplock);
torture_suite_add_2smb_test(suite, "NOTIFY", torture_raw_notify);
torture_suite_add_1smb_test(suite, "MUX", torture_raw_mux);
torture_suite_add_1smb_test(suite, "IOCTL", torture_raw_ioctl);