mirror of
https://github.com/samba-team/samba.git
synced 2024-12-22 13:34:15 +03:00
smbtorture: Directory Leases vs hardlink
Signed-off-by: Ralph Boehme <slow@samba.org> Reviewed-by: Stefan Metzmacher <metze@samba.org>
This commit is contained in:
parent
4ed15961d7
commit
d805f6e22f
@ -6769,6 +6769,258 @@ done:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct dlt_hardlink {
|
||||
const char *testname;
|
||||
bool expect_srcdir_break;
|
||||
bool expect_dstdir_break;
|
||||
const char *srcdir;
|
||||
const char *dstdir;
|
||||
uint64_t srcdir_leasekey;
|
||||
uint64_t dstdir_leasekey;
|
||||
uint64_t parent_leasekey;
|
||||
const char *srcfname;
|
||||
const char *dstfname;
|
||||
} dlt_hardlinks[] = {
|
||||
{
|
||||
.testname = "samedir-correct-parent-leaskey",
|
||||
.expect_srcdir_break = false,
|
||||
.expect_dstdir_break = false,
|
||||
.srcdir = "test_dirlease_rename_dir",
|
||||
.dstdir = "test_dirlease_rename_dir",
|
||||
.srcdir_leasekey = DLEASE1,
|
||||
.dstdir_leasekey = DLEASE2,
|
||||
.parent_leasekey = DLEASE1,
|
||||
.srcfname = "test_dirlease_rename_dir\\srcfile",
|
||||
.dstfname = "test_dirlease_rename_dir\\dstfile",
|
||||
}, {
|
||||
.testname = "samedir-wrong-parent-leaskey",
|
||||
.expect_srcdir_break = true,
|
||||
.expect_dstdir_break = false,
|
||||
.srcdir = "test_dirlease_rename_dir",
|
||||
.dstdir = "test_dirlease_rename_dir",
|
||||
.srcdir_leasekey = DLEASE1,
|
||||
.dstdir_leasekey = DLEASE2,
|
||||
.parent_leasekey = DLEASE3,
|
||||
.srcfname = "test_dirlease_rename_dir\\srcfile",
|
||||
.dstfname = "test_dirlease_rename_dir\\dstfile",
|
||||
}, {
|
||||
.testname = "samedir-no-parent-leaskey",
|
||||
.expect_srcdir_break = true,
|
||||
.expect_dstdir_break = false,
|
||||
.srcdir = "test_dirlease_rename_dir",
|
||||
.dstdir = "test_dirlease_rename_dir",
|
||||
.srcdir_leasekey = DLEASE1,
|
||||
.dstdir_leasekey = DLEASE2,
|
||||
.parent_leasekey = 0,
|
||||
.srcfname = "test_dirlease_rename_dir\\srcfile",
|
||||
.dstfname = "test_dirlease_rename_dir\\dstfile",
|
||||
}, {
|
||||
.testname = "otherdir-correct-srcparent-leaskey",
|
||||
.expect_srcdir_break = false,
|
||||
.expect_dstdir_break = true,
|
||||
.srcdir = "test_dirlease_rename_dir",
|
||||
.dstdir = "test_dirlease_rename_dir2",
|
||||
.srcdir_leasekey = DLEASE1,
|
||||
.dstdir_leasekey = DLEASE2,
|
||||
.parent_leasekey = DLEASE1,
|
||||
.srcfname = "test_dirlease_rename_dir\\srcfile",
|
||||
.dstfname = "test_dirlease_rename_dir2\\dstfile",
|
||||
}, {
|
||||
.testname = "otherdir-correct-dstparent-leaskey",
|
||||
.expect_srcdir_break = false,
|
||||
.expect_dstdir_break = false,
|
||||
.srcdir = "test_dirlease_rename_dir",
|
||||
.dstdir = "test_dirlease_rename_dir2",
|
||||
.srcdir_leasekey = DLEASE1,
|
||||
.dstdir_leasekey = DLEASE2,
|
||||
.parent_leasekey = DLEASE2,
|
||||
.srcfname = "test_dirlease_rename_dir\\srcfile",
|
||||
.dstfname = "test_dirlease_rename_dir2\\dstfile",
|
||||
}, {
|
||||
.testname = "otherdir-wrong-parent-leaskey",
|
||||
.expect_srcdir_break = false,
|
||||
.expect_dstdir_break = true,
|
||||
.srcdir = "test_dirlease_rename_dir",
|
||||
.dstdir = "test_dirlease_rename_dir2",
|
||||
.srcdir_leasekey = DLEASE1,
|
||||
.dstdir_leasekey = DLEASE2,
|
||||
.parent_leasekey = DLEASE3,
|
||||
.srcfname = "test_dirlease_rename_dir\\srcfile",
|
||||
.dstfname = "test_dirlease_rename_dir2\\dstfile",
|
||||
}, {
|
||||
.testname = "otherdir-no-parent-leaskey",
|
||||
.expect_srcdir_break = false,
|
||||
.expect_dstdir_break = true,
|
||||
.srcdir = "test_dirlease_rename_dir",
|
||||
.dstdir = "test_dirlease_rename_dir2",
|
||||
.srcdir_leasekey = DLEASE1,
|
||||
.dstdir_leasekey = DLEASE2,
|
||||
.parent_leasekey = 0,
|
||||
.srcfname = "test_dirlease_rename_dir\\srcfile",
|
||||
.dstfname = "test_dirlease_rename_dir2\\dstfile",
|
||||
}, {
|
||||
.testname = NULL,
|
||||
}
|
||||
};
|
||||
|
||||
static bool test_hardlink_one(struct torture_context *tctx,
|
||||
struct smb2_tree *tree,
|
||||
struct dlt_hardlink *t)
|
||||
{
|
||||
TALLOC_CTX *mem_ctx = talloc_new(tctx);
|
||||
struct smb2_create c;
|
||||
struct smb2_lease dirlease1;
|
||||
struct smb2_lease dirlease2;
|
||||
struct smb2_handle dirh1 = {};
|
||||
struct smb2_handle dirh2 = {};
|
||||
struct smb2_lease lease1;
|
||||
struct smb2_handle h1 = {};
|
||||
struct smb2_lease_break_ack ack = {};
|
||||
bool samedir = strequal(t->srcdir, t->dstdir);
|
||||
union smb_setfileinfo sfinfo = {};
|
||||
NTSTATUS status;
|
||||
bool ret = true;
|
||||
|
||||
torture_comment(tctx, "\nHardlink subtest: %s\n"
|
||||
"==================================\n",
|
||||
t->testname);
|
||||
|
||||
smb2_deltree(tree, t->srcdir);
|
||||
smb2_deltree(tree, t->dstdir);
|
||||
torture_reset_lease_break_info(tctx, &lease_break_info);
|
||||
|
||||
|
||||
/* Get an RH directory lease on the src directory */
|
||||
smb2_lease_v2_create_share(&c, &dirlease1, true, t->srcdir,
|
||||
smb2_util_share_access("RWD"),
|
||||
t->srcdir_leasekey, NULL,
|
||||
smb2_util_lease_state("RHW"), 0);
|
||||
c.in.desired_access &= ~DELETE_ACCESS;
|
||||
status = smb2_create(tree, mem_ctx, &c);
|
||||
torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
|
||||
"smb2_create failed\n");
|
||||
dirh1 = c.out.file.handle;
|
||||
CHECK_LEASE_V2(&c, "RH", true, t->srcdir_leasekey, 0, 0, ++dirlease1.lease_epoch);
|
||||
|
||||
if (!samedir) {
|
||||
/* Get an RH directory lease on the dst directory */
|
||||
smb2_lease_v2_create_share(&c, &dirlease2, true, t->dstdir,
|
||||
smb2_util_share_access("RWD"),
|
||||
t->dstdir_leasekey, NULL,
|
||||
smb2_util_lease_state("RHW"), 0);
|
||||
c.in.desired_access &= ~DELETE_ACCESS;
|
||||
status = smb2_create(tree, mem_ctx, &c);
|
||||
torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
|
||||
"smb2_create failed\n");
|
||||
dirh2 = c.out.file.handle;
|
||||
CHECK_LEASE_V2(&c, "RH", true, t->dstdir_leasekey, 0, 0, ++dirlease2.lease_epoch);
|
||||
}
|
||||
|
||||
/* Create the to be hardlinkd file */
|
||||
smb2_lease_v2_create_share(&c, &lease1, false, t->srcfname,
|
||||
smb2_util_share_access("RWD"),
|
||||
LEASE4, &t->srcdir_leasekey,
|
||||
smb2_util_lease_state("RHW"),
|
||||
0x33);
|
||||
status = smb2_create(tree, mem_ctx, &c);
|
||||
torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
|
||||
"smb2_create failed\n");
|
||||
h1 = c.out.file.handle;
|
||||
smb2_util_close(tree, h1);
|
||||
ZERO_STRUCT(h1);
|
||||
|
||||
/* Open the testfile, possibly with a bad parent leasekey */
|
||||
smb2_lease_v2_create_share(&c, &lease1, false, t->srcfname,
|
||||
smb2_util_share_access("RWD"),
|
||||
LEASE4,
|
||||
t->parent_leasekey != 0 ? &t->parent_leasekey : NULL,
|
||||
smb2_util_lease_state("RHW"),
|
||||
0x33);
|
||||
status = smb2_create(tree, mem_ctx, &c);
|
||||
torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
|
||||
"smb2_create failed\n");
|
||||
h1 = c.out.file.handle;
|
||||
|
||||
sfinfo.generic.level = RAW_SFILEINFO_LINK_INFORMATION;
|
||||
sfinfo.generic.in.file.handle = h1;
|
||||
sfinfo.link_information.in.new_name = t->dstfname;
|
||||
|
||||
status = smb2_setinfo_file(tree, &sfinfo);
|
||||
torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
|
||||
"smb2_setinfo_file failed\n");
|
||||
if (t->expect_srcdir_break) {
|
||||
/* Delay the ack in order to be able to possibly process two breaks */
|
||||
lease_break_info.lease_skip_ack = true;
|
||||
CHECK_BREAK_INFO_V2(tree->session->transport,
|
||||
"RH", "",
|
||||
t->srcdir_leasekey,
|
||||
++dirlease1.lease_epoch);
|
||||
ack.in.lease.lease_key = lease_break_info.lease_break.current_lease.lease_key;
|
||||
ack.in.lease.lease_state = lease_break_info.lease_break.new_lease_state;
|
||||
torture_reset_lease_break_info(tctx, &lease_break_info);
|
||||
if (!t->expect_dstdir_break) {
|
||||
CHECK_NO_BREAK(tctx);
|
||||
}
|
||||
}
|
||||
if (t->expect_dstdir_break) {
|
||||
CHECK_BREAK_INFO_V2(tree->session->transport,
|
||||
"RH", "",
|
||||
t->dstdir_leasekey,
|
||||
++dirlease2.lease_epoch);
|
||||
torture_reset_lease_break_info(tctx, &lease_break_info);
|
||||
if (!t->expect_srcdir_break) {
|
||||
CHECK_NO_BREAK(tctx);
|
||||
}
|
||||
}
|
||||
if (!t->expect_srcdir_break && !t->expect_dstdir_break) {
|
||||
CHECK_NO_BREAK(tctx);
|
||||
}
|
||||
|
||||
if (t->expect_srcdir_break) {
|
||||
/* ack the first lease break. */
|
||||
status = smb2_lease_break_ack(tree, &ack);
|
||||
torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
|
||||
"smb2_lease_break_ack failed\n");
|
||||
CHECK_LEASE_BREAK_ACK(&ack, "", t->srcdir_leasekey);
|
||||
}
|
||||
|
||||
|
||||
done:
|
||||
if (!smb2_util_handle_empty(h1)) {
|
||||
smb2_util_close(tree, h1);
|
||||
}
|
||||
if (!smb2_util_handle_empty(dirh1)) {
|
||||
smb2_util_close(tree, dirh1);
|
||||
}
|
||||
if (!smb2_util_handle_empty(dirh2)) {
|
||||
smb2_util_close(tree, dirh2);
|
||||
}
|
||||
smb2_deltree(tree, t->srcdir);
|
||||
smb2_deltree(tree, t->dstdir);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool test_hardlink(struct torture_context *tctx,
|
||||
struct smb2_tree *tree)
|
||||
{
|
||||
struct dlt_hardlink *t = NULL;
|
||||
bool ret = true;
|
||||
|
||||
tree->session->transport->lease.handler = torture_lease_handler;
|
||||
tree->session->transport->lease.private_data = tree;
|
||||
torture_reset_lease_break_info(tctx, &lease_break_info);
|
||||
|
||||
for (t = dlt_hardlinks; t->testname != NULL; t++) {
|
||||
ret = test_hardlink_one(tctx, tree, t);
|
||||
torture_assert_goto(tctx, ret, ret, done,
|
||||
talloc_asprintf(tctx, "%s failed\n",
|
||||
t->testname));
|
||||
}
|
||||
|
||||
done:
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct torture_suite *torture_smb2_dirlease_init(TALLOC_CTX *ctx)
|
||||
{
|
||||
struct torture_suite *suite =
|
||||
@ -6787,5 +7039,6 @@ struct torture_suite *torture_smb2_dirlease_init(TALLOC_CTX *ctx)
|
||||
torture_suite_add_2smb2_test(suite, "setatime", test_dirlease_setatime);
|
||||
torture_suite_add_1smb2_test(suite, "rename", test_rename);
|
||||
torture_suite_add_2smb2_test(suite, "overwrite", test_overwrite);
|
||||
torture_suite_add_1smb2_test(suite, "hardlink", test_hardlink);
|
||||
return suite;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user