diff options
Diffstat (limited to 'source3/torture')
-rw-r--r-- | source3/torture/proto.h | 1 | ||||
-rw-r--r-- | source3/torture/test_cleanup.c | 175 | ||||
-rw-r--r-- | source3/torture/torture.c | 1 |
3 files changed, 177 insertions, 0 deletions
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; i<ARRAY_SIZE(fns); i++) { + + printf("testing %s\n", fns[i].descr); + + if (!create_stale_share_mode_entry(fname, &id)) { + printf("create_stale_entry failed\n"); + return false; + } + + printf("%d %d %d\n", (int)id.devid, (int)id.inode, + (int)id.extid); + + if (!locking_init()) { + printf("locking_init failed\n"); + 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("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}, |