From: Namjae Jeon Date: Wed, 1 Jul 2026 14:59:29 +0000 (+0900) Subject: ksmbd: coalesce sub-15ms write time updates on close X-Git-Tag: v7.2-rc3~28^2~7 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a0b765030f6ba37aaac59618d4f39dac18d42757;p=thirdparty%2Fkernel%2Flinux.git 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 Signed-off-by: Steve French --- diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c index 9c00f944fa3b..b1204d1d3cdd 100644 --- a/fs/smb/server/smb2pdu.c +++ b/fs/smb/server/smb2pdu.c @@ -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 @@ reconnected_fp: 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); diff --git a/fs/smb/server/vfs_cache.h b/fs/smb/server/vfs_cache.h index 287f3e675cd3..b9e27307a26c 100644 --- a/fs/smb/server/vfs_cache.h +++ b/fs/smb/server/vfs_cache.h @@ -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;