ksmbd: coalesce sub-15ms write time updates on close

Windows reports automatic write-time updates with a resolution of roughly
15 milliseconds. If a file is written and closed within that interval, a
close response requesting full information can report the write time from
the open rather than the filesystem's finer-grained mtime update.

ksmbd currently converts the filesystem mtime directly in SMB2 CLOSE, so
even a sub-millisecond write is visible to the client. This makes
smb2.timestamp_resolution.resolution1 fail because the immediate write
changes LastWriteTime.

Save the write time returned by SMB2 CREATE in the file handle. When CLOSE
requests post-query attributes, coalesce a positive mtime change smaller
than 15 milliseconds to that saved value. Larger changes remain visible,
including the test's write after a 20 millisecond delay.

Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
Namjae Jeon 2026-07-01 23:59:29 +09:00 committed by Steve French
parent 4b706360ff
commit a0b765030f
2 changed files with 8 additions and 0 deletions

View File

@ -61,6 +61,9 @@ static void __wbuf(struct ksmbd_work *work, void **req, void **rsp)
(FILE_ATTRIBUTE_MASK & ~(FILE_ATTRIBUTE_INTEGRITY_STREAM | \
FILE_ATTRIBUTE_NO_SCRUB_DATA))
/* Windows reports automatic write-time updates at roughly 15 ms resolution. */
#define KSMBD_WRITE_TIME_RESOLUTION (15ULL * 10000)
/**
* check_session_id() - check for valid session id in smb header
* @conn: connection instance
@ -3985,6 +3988,7 @@ int smb2_open(struct ksmbd_work *work)
time = ksmbd_UnixTimeToNT(stat.atime);
rsp->LastAccessTime = cpu_to_le64(time);
time = ksmbd_UnixTimeToNT(stat.mtime);
fp->open_mtime = time;
rsp->LastWriteTime = cpu_to_le64(time);
rsp->ChangeTime = cpu_to_le64(fp->change_time);
/*
@ -6451,6 +6455,9 @@ int smb2_close(struct ksmbd_work *work)
time = ksmbd_UnixTimeToNT(stat.atime);
rsp->LastAccessTime = cpu_to_le64(time);
time = ksmbd_UnixTimeToNT(stat.mtime);
if (time > fp->open_mtime &&
time - fp->open_mtime < KSMBD_WRITE_TIME_RESOLUTION)
time = fp->open_mtime;
rsp->LastWriteTime = cpu_to_le64(time);
rsp->ChangeTime = cpu_to_le64(fp->change_time);
ksmbd_fd_put(work, fp);

View File

@ -105,6 +105,7 @@ struct ksmbd_file {
__u64 change_time;
__u64 allocation_size;
__u64 itime;
__u64 open_mtime;
bool is_nt_open;
bool attrib_only;