mirror of
https://github.com/samba-team/samba.git
synced 2025-02-26 21:57:41 +03:00
torture/smb2: Windows 2019 15 ms timestamp resolution
This test demonstrates that Windows has a timestamp resolution of ~15ms. When a smaller amount of time than that has passed between modifying operations on a file, it's not necessarily detectable on a Windows 2019 server that implements immediate timestamp updates (no delayed magic). Note that this test relies on a low latency SMB connection. Even with a low latency connection of eg 1m there's a chance of 1/15 that the first part of the test expecting no timestamp change fails as the writetime is updated. Due to this timing dependency this test is skipped in Samba CI, but it is preserved here for future SMB2 timestamps behaviour archealogists. See also: https://lists.samba.org/archive/cifs-protocol/2019-December/003358.html Signed-off-by: Ralph Boehme <slow@samba.org> Reviewed-by: Jeremy Allison <jra@samba.org>
This commit is contained in:
parent
7b90fe69a8
commit
6f7d1d8a37
@ -75,6 +75,8 @@
|
||||
^samba3.smb2.durable-open-disconnect # Not a test, but a way to create a disconnected durable
|
||||
^samba3.smb2.scan # No tests
|
||||
^samba3.smb2.oplock.levelii501 # No test yet
|
||||
^samba3.smb2.timestamp_resolution # See the comment on the test
|
||||
^samba4.smb2.timestamp_resolution
|
||||
^samba3.rpc.samr.passwords.lockout\(ad_dc\) # No point running this version, it just waits 12 times longer the samba4 version of this test, covering the same code
|
||||
^samba4.base.iometer
|
||||
^samba4.base.casetable
|
||||
|
@ -198,6 +198,7 @@ NTSTATUS torture_smb2_init(TALLOC_CTX *ctx)
|
||||
torture_suite_add_suite(suite, torture_smb2_multichannel_init(suite));
|
||||
torture_suite_add_suite(suite, torture_smb2_samba3misc_init(suite));
|
||||
torture_suite_add_suite(suite, torture_smb2_timestamps_init(suite));
|
||||
torture_suite_add_suite(suite, torture_smb2_timestamp_resolution_init(suite));
|
||||
torture_suite_add_1smb2_test(suite, "openattr", torture_smb2_openattrtest);
|
||||
torture_suite_add_1smb2_test(suite, "winattr", torture_smb2_winattrtest);
|
||||
torture_suite_add_suite(suite, torture_smb2_readwrite_init(suite));
|
||||
|
@ -727,3 +727,148 @@ struct torture_suite *torture_smb2_timestamps_init(TALLOC_CTX *ctx)
|
||||
|
||||
return suite;
|
||||
}
|
||||
|
||||
/*
|
||||
* This test shows that Windows has a timestamp resolution of ~15ms. When so
|
||||
* when a smaller amount of time than that has passed it's not necessarily
|
||||
* detectable on a Windows 2019 and newer who implement immediate timestamp
|
||||
* updates.
|
||||
*
|
||||
* Note that this test relies on a low latency SMB connection. Even with a low
|
||||
* latency connection of eg 1m there's a chance of 1/15 that the first part of
|
||||
* the test expecting no timestamp change fails as the writetime is updated.
|
||||
*
|
||||
* Due to this timing dependency this test is skipped in Samba CI, but it is
|
||||
* preserved here for future SMB2 timestamps behaviour archealogists.
|
||||
*
|
||||
* See also: https://lists.samba.org/archive/cifs-protocol/2019-December/003358.html
|
||||
*/
|
||||
static bool test_timestamp_resolution1(struct torture_context *tctx,
|
||||
struct smb2_tree *tree)
|
||||
{
|
||||
union smb_fileinfo finfo1;
|
||||
const char *fname = BASEDIR "\\" FNAME;
|
||||
struct smb2_create cr;
|
||||
struct smb2_handle h = {{0}};
|
||||
struct smb2_close cl;
|
||||
NTSTATUS status;
|
||||
bool ret = true;
|
||||
|
||||
smb2_deltree(tree, BASEDIR);
|
||||
status = torture_smb2_testdir(tree, BASEDIR, &h);
|
||||
torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
|
||||
"create failed\n");
|
||||
status = smb2_util_close(tree, h );
|
||||
torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
|
||||
"close failed\n");
|
||||
|
||||
torture_comment(tctx, "Write without delay, expect no "
|
||||
"write-time change\n");
|
||||
|
||||
smb2_generic_create(&cr, NULL, false, fname,
|
||||
NTCREATEX_DISP_CREATE,
|
||||
smb2_util_oplock_level(""), 0, 0);
|
||||
status = smb2_create(tree, tree, &cr);
|
||||
torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
|
||||
"create failed\n");
|
||||
h = cr.out.file.handle;
|
||||
|
||||
finfo1 = (union smb_fileinfo) {
|
||||
.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
|
||||
.generic.in.file.handle = h,
|
||||
};
|
||||
status = smb2_getinfo_file(tree, tree, &finfo1);
|
||||
torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
|
||||
"getinfo failed\n");
|
||||
|
||||
status = smb2_util_write(tree, h, "123456789", 0, 9);
|
||||
torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
|
||||
"write failed\n");
|
||||
|
||||
cl = (struct smb2_close) {
|
||||
.in.file.handle = h,
|
||||
.in.flags = SMB2_CLOSE_FLAGS_FULL_INFORMATION,
|
||||
};
|
||||
|
||||
status = smb2_close(tree, &cl);
|
||||
torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
|
||||
"close failed\n");
|
||||
ZERO_STRUCT(h);
|
||||
|
||||
torture_comment(tctx, "Initial: %s\nClose: %s\n",
|
||||
nt_time_string(tctx, finfo1.basic_info.out.write_time),
|
||||
nt_time_string(tctx, cl.out.write_time));
|
||||
|
||||
torture_assert_u64_equal_goto(tctx,
|
||||
finfo1.basic_info.out.write_time,
|
||||
cl.out.write_time,
|
||||
ret, done,
|
||||
"Write time changed (wrong!)\n");
|
||||
|
||||
torture_comment(tctx, "Write with 20 ms delay, expect "
|
||||
"write-time change\n");
|
||||
|
||||
smb2_generic_create(&cr, NULL, false, fname,
|
||||
NTCREATEX_DISP_OPEN,
|
||||
smb2_util_oplock_level(""), 0, 0);
|
||||
status = smb2_create(tree, tree, &cr);
|
||||
torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
|
||||
"create failed\n");
|
||||
h = cr.out.file.handle;
|
||||
|
||||
finfo1 = (union smb_fileinfo) {
|
||||
.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
|
||||
.generic.in.file.handle = h,
|
||||
};
|
||||
status = smb2_getinfo_file(tree, tree, &finfo1);
|
||||
torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
|
||||
"getinfo failed\n");
|
||||
|
||||
smb_msleep(20);
|
||||
|
||||
status = smb2_util_write(tree, h, "123456789", 0, 9);
|
||||
torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
|
||||
"write failed\n");
|
||||
|
||||
cl = (struct smb2_close) {
|
||||
.in.file.handle = h,
|
||||
.in.flags = SMB2_CLOSE_FLAGS_FULL_INFORMATION,
|
||||
};
|
||||
|
||||
status = smb2_close(tree, &cl);
|
||||
torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
|
||||
"close failed\n");
|
||||
ZERO_STRUCT(h);
|
||||
|
||||
torture_comment(tctx, "Initial: %s\nClose: %s\n",
|
||||
nt_time_string(tctx, finfo1.basic_info.out.write_time),
|
||||
nt_time_string(tctx, cl.out.write_time));
|
||||
|
||||
torture_assert_u64_not_equal_goto(
|
||||
tctx,
|
||||
finfo1.basic_info.out.write_time,
|
||||
cl.out.write_time,
|
||||
ret, done,
|
||||
"Write time did not change (wrong!)\n");
|
||||
|
||||
done:
|
||||
if (!smb2_util_handle_empty(h)) {
|
||||
smb2_util_close(tree, h);
|
||||
}
|
||||
smb2_deltree(tree, BASEDIR);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
basic testing of SMB2 timestamps
|
||||
*/
|
||||
struct torture_suite *torture_smb2_timestamp_resolution_init(TALLOC_CTX *ctx)
|
||||
{
|
||||
struct torture_suite *suite = torture_suite_create(ctx, "timestamp_resolution");
|
||||
|
||||
torture_suite_add_1smb2_test(suite, "resolution1", test_timestamp_resolution1);
|
||||
|
||||
suite->description = talloc_strdup(suite, "SMB2 timestamp tests");
|
||||
|
||||
return suite;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user