From e34b7306fc421741727f20275b9dd4878906ba05 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 11 May 2012 14:39:42 +0200 Subject: s3: Test whether get_share_mode_lock cleans up stale processes Signed-off-by: Jeremy Allison --- source3/Makefile.in | 3 +- source3/torture/proto.h | 1 + source3/torture/test_cleanup.c | 175 +++++++++++++++++++++++++++++++++++++++++ source3/torture/torture.c | 1 + 4 files changed, 179 insertions(+), 1 deletion(-) diff --git a/source3/Makefile.in b/source3/Makefile.in index 486ec726db..a40154355b 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -1280,11 +1280,12 @@ SMBTORTURE_OBJ1 = torture/torture.o torture/nbio.o torture/scanner.o torture/uta torture/t_strappend.o SMBTORTURE_OBJ = $(SMBTORTURE_OBJ1) $(PARAM_OBJ) $(TLDAP_OBJ) \ - $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) $(LIB_NONSMBD_OBJ) \ + $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) $(LIB_NONSMBD_OBJ) $(LOCKING_OBJ) \ @LIBWBCLIENT_STATIC@ \ torture/wbc_async.o \ ../nsswitch/wb_reqtrans.o \ ../libcli/lsarpc/util_lsarpc.o \ + lib/filename_util.o \ $(LIBMSRPC_OBJ) $(LIBMSRPC_GEN_OBJ) $(LIBCLI_ECHO_OBJ) MASKTEST_OBJ = torture/masktest.o $(PARAM_OBJ) $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) \ diff --git a/source3/torture/proto.h b/source3/torture/proto.h index 80618ceb34..4104fbc998 100644 --- a/source3/torture/proto.h +++ b/source3/torture/proto.h @@ -104,6 +104,7 @@ bool run_local_conv_auth_info(int dummy); bool run_local_sprintf_append(int dummy); bool run_cleanup1(int dummy); bool run_cleanup2(int dummy); +bool run_cleanup3(int dummy); bool run_ctdb_conn(int dummy); bool run_msg_test(int dummy); bool run_notify_bench2(int dummy); diff --git a/source3/torture/test_cleanup.c b/source3/torture/test_cleanup.c index 39f579a9cd..d9dce402de 100644 --- a/source3/torture/test_cleanup.c +++ b/source3/torture/test_cleanup.c @@ -18,11 +18,14 @@ */ #include "includes.h" +#include "locking/proto.h" #include "torture/proto.h" #include "system/filesys.h" +#include "system/select.h" #include "libsmb/libsmb.h" #include "libcli/smb/smbXcli_base.h" #include "libcli/security/security.h" +#include "librpc/gen_ndr/open_files.h" bool run_cleanup1(int dummy) { @@ -154,3 +157,175 @@ bool run_cleanup2(int dummy) } return true; } + +static bool create_stale_share_mode_entry(const char *fname, + struct file_id *p_id) +{ + struct cli_state *cli; + uint16_t fnum; + NTSTATUS status; + SMB_STRUCT_STAT sbuf; + struct file_id id; + + if (!torture_open_connection(&cli, 0)) { + return false; + } + + status = torture_setup_unix_extensions(cli); + if (!NT_STATUS_IS_OK(status)) { + printf("torture_setup_unix_extensions failed: %s\n", + nt_errstr(status)); + return false; + } + status = cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_ALL, &fnum); + if (!NT_STATUS_IS_OK(status)) { + printf("open of %s failed (%s)\n", fname, nt_errstr(status)); + return false; + } + status = cli_posix_stat(cli, fname, &sbuf); + if (!NT_STATUS_IS_OK(status)) { + printf("cli_posix_stat failed: %s\n", nt_errstr(status)); + return false; + } + status = smbXcli_conn_samba_suicide(cli->conn, 1); + if (!NT_STATUS_IS_OK(status)) { + printf("smbXcli_conn_samba_suicide failed: %s\n", + nt_errstr(status)); + return false; + } + + id.devid = sbuf.st_ex_rdev; + id.inode = sbuf.st_ex_ino; + id.extid = 0; + + poll(NULL, 0, 1000); + + *p_id = id; + return true; +} + +static bool corrupt_dummy(struct share_mode_data *d) +{ + return true; +} + +static bool invalidate_sharemode(struct share_mode_data *d) +{ + d->share_modes[0].op_type = + OPLOCK_EXCLUSIVE|OPLOCK_BATCH|OPLOCK_LEVEL_II; + d->modified = true; + return true; +} + +static bool duplicate_entry(struct share_mode_data *d, int i) +{ + struct share_mode_entry *tmp; + + if (i >= d->num_share_modes) { + return false; + } + + tmp = talloc_realloc(d, d->share_modes, struct share_mode_entry, + d->num_share_modes + 1); + if (tmp == NULL) { + return false; + } + d->share_modes = tmp; + d->num_share_modes += 1; + d->share_modes[d->num_share_modes-1] = d->share_modes[i]; + d->modified = true; + return true; +} + +static bool create_duplicate_batch(struct share_mode_data *d) +{ + if (d->num_share_modes != 1) { + return false; + } + d->share_modes[0].op_type = OPLOCK_BATCH; + if (!duplicate_entry(d, 0)) { + return false; + } + return true; +} + +struct corruption_fns { + bool (*fn)(struct share_mode_data *d); + const char *descr; +}; + +bool run_cleanup3(int dummy) +{ + struct cli_state *cli; + const char *fname = "cleanup3"; + uint16_t fnum; + NTSTATUS status; + struct share_mode_lock *lck; + struct file_id id; + size_t i; + + struct corruption_fns fns[] = { + { corrupt_dummy, "no corruption" }, + { invalidate_sharemode, "invalidate_sharemode" }, + { create_duplicate_batch, "create_duplicate_batch" }, + }; + + printf("CLEANUP3: Checking that a share mode is cleaned up on " + "conflict\n"); + + for (i=0; idata->num_share_modes != 1) { + printf("get_existing_share_mode_lock did clean up\n"); + return false; + } + + fns[i].fn(lck->data); + + TALLOC_FREE(lck); + + if (!torture_open_connection(&cli, 0)) { + return false; + } + status = cli_openx(cli, fname, O_RDWR|O_CREAT, DENY_ALL, + &fnum); + if (!NT_STATUS_IS_OK(status)) { + printf("open of %s failed (%s)\n", fname, + nt_errstr(status)); + return false; + } + lck = get_existing_share_mode_lock(talloc_tos(), id); + if (lck == NULL) { + printf("get_existing_share_mode_lock failed\n"); + return false; + } + if (lck->data->num_share_modes != 1) { + printf("conflicting open did not clean up\n"); + return false; + } + TALLOC_FREE(lck); + + torture_close_connection(cli); + } + + return true; +} diff --git a/source3/torture/torture.c b/source3/torture/torture.c index 962d0e7967..ad30d3dceb 100644 --- a/source3/torture/torture.c +++ b/source3/torture/torture.c @@ -8916,6 +8916,7 @@ static struct { { "SMB2-SESSION-REAUTH", run_smb2_session_reauth }, { "CLEANUP1", run_cleanup1 }, { "CLEANUP2", run_cleanup2 }, + { "CLEANUP3", run_cleanup3 }, { "LOCAL-SUBSTITUTE", run_local_substitute, 0}, { "LOCAL-GENCACHE", run_local_gencache, 0}, { "LOCAL-TALLOC-DICT", run_local_talloc_dict, 0}, -- cgit