mirror of
https://github.com/torvalds/linux.git
synced 2026-07-28 18:21:24 +02:00
ksmbd: preserve open change time across rename
inode ctime is updated when a file is renamed. ksmbd returned that ctime directly as SMB2 ChangeTime for handle-based query information. This makes ChangeTime change after a rename through an already-open handle, while Windows keeps the handle's ChangeTime stable for this case. Store the SMB ChangeTime in struct ksmbd_file when the handle is opened and use that value for create, close, and handle-based query information responses. If a client explicitly sets FILE_BASIC_INFORMATION ChangeTime, update the stored value as well. This fixes smbtorture smb2.rename.simple_modtime, which expects ChangeTime and LastWriteTime to remain unchanged after renaming an already-open file. Signed-off-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
parent
16c3064970
commit
24dcee8305
|
|
@ -3783,6 +3783,7 @@ int smb2_open(struct ksmbd_work *work)
|
|||
fp->create_time = ksmbd_UnixTimeToNT(stat.btime);
|
||||
else
|
||||
fp->create_time = ksmbd_UnixTimeToNT(stat.ctime);
|
||||
fp->change_time = ksmbd_UnixTimeToNT(stat.ctime);
|
||||
if (req->FileAttributes || fp->f_ci->m_fattr == 0)
|
||||
fp->f_ci->m_fattr =
|
||||
cpu_to_le32(smb2_get_dos_mode(&stat, le32_to_cpu(req->FileAttributes)));
|
||||
|
|
@ -3832,8 +3833,7 @@ int smb2_open(struct ksmbd_work *work)
|
|||
rsp->LastAccessTime = cpu_to_le64(time);
|
||||
time = ksmbd_UnixTimeToNT(stat.mtime);
|
||||
rsp->LastWriteTime = cpu_to_le64(time);
|
||||
time = ksmbd_UnixTimeToNT(stat.ctime);
|
||||
rsp->ChangeTime = cpu_to_le64(time);
|
||||
rsp->ChangeTime = cpu_to_le64(fp->change_time);
|
||||
rsp->AllocationSize = S_ISDIR(stat.mode) ? 0 :
|
||||
cpu_to_le64(stat.blocks << 9);
|
||||
rsp->EndofFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size);
|
||||
|
|
@ -5102,8 +5102,7 @@ static int get_file_basic_info(struct smb2_query_info_rsp *rsp,
|
|||
basic_info->LastAccessTime = cpu_to_le64(time);
|
||||
time = ksmbd_UnixTimeToNT(stat.mtime);
|
||||
basic_info->LastWriteTime = cpu_to_le64(time);
|
||||
time = ksmbd_UnixTimeToNT(stat.ctime);
|
||||
basic_info->ChangeTime = cpu_to_le64(time);
|
||||
basic_info->ChangeTime = cpu_to_le64(fp->change_time);
|
||||
basic_info->Attributes = fp->f_ci->m_fattr;
|
||||
basic_info->Pad = 0;
|
||||
rsp->OutputBufferLength =
|
||||
|
|
@ -5205,8 +5204,7 @@ static int get_file_all_info(struct ksmbd_work *work,
|
|||
file_info->LastAccessTime = cpu_to_le64(time);
|
||||
time = ksmbd_UnixTimeToNT(stat.mtime);
|
||||
file_info->LastWriteTime = cpu_to_le64(time);
|
||||
time = ksmbd_UnixTimeToNT(stat.ctime);
|
||||
file_info->ChangeTime = cpu_to_le64(time);
|
||||
file_info->ChangeTime = cpu_to_le64(fp->change_time);
|
||||
file_info->Attributes = fp->f_ci->m_fattr;
|
||||
file_info->Pad1 = 0;
|
||||
if (ksmbd_stream_fd(fp) == false) {
|
||||
|
|
@ -5415,8 +5413,7 @@ static int get_file_network_open_info(struct smb2_query_info_rsp *rsp,
|
|||
file_info->LastAccessTime = cpu_to_le64(time);
|
||||
time = ksmbd_UnixTimeToNT(stat.mtime);
|
||||
file_info->LastWriteTime = cpu_to_le64(time);
|
||||
time = ksmbd_UnixTimeToNT(stat.ctime);
|
||||
file_info->ChangeTime = cpu_to_le64(time);
|
||||
file_info->ChangeTime = cpu_to_le64(fp->change_time);
|
||||
file_info->Attributes = fp->f_ci->m_fattr;
|
||||
if (ksmbd_stream_fd(fp) == false) {
|
||||
file_info->AllocationSize = cpu_to_le64(stat.blocks << 9);
|
||||
|
|
@ -5547,8 +5544,7 @@ static int find_file_posix_info(struct smb2_query_info_rsp *rsp,
|
|||
file_info->LastAccessTime = cpu_to_le64(time);
|
||||
time = ksmbd_UnixTimeToNT(stat.mtime);
|
||||
file_info->LastWriteTime = cpu_to_le64(time);
|
||||
time = ksmbd_UnixTimeToNT(stat.ctime);
|
||||
file_info->ChangeTime = cpu_to_le64(time);
|
||||
file_info->ChangeTime = cpu_to_le64(fp->change_time);
|
||||
file_info->DosAttributes = fp->f_ci->m_fattr;
|
||||
file_info->Inode = cpu_to_le64(stat.ino);
|
||||
if (ksmbd_stream_fd(fp) == false) {
|
||||
|
|
@ -6271,8 +6267,7 @@ int smb2_close(struct ksmbd_work *work)
|
|||
rsp->LastAccessTime = cpu_to_le64(time);
|
||||
time = ksmbd_UnixTimeToNT(stat.mtime);
|
||||
rsp->LastWriteTime = cpu_to_le64(time);
|
||||
time = ksmbd_UnixTimeToNT(stat.ctime);
|
||||
rsp->ChangeTime = cpu_to_le64(time);
|
||||
rsp->ChangeTime = cpu_to_le64(fp->change_time);
|
||||
ksmbd_fd_put(work, fp);
|
||||
} else {
|
||||
rsp->Flags = 0;
|
||||
|
|
@ -6485,9 +6480,11 @@ static int set_file_basic_info(struct ksmbd_file *fp,
|
|||
attrs.ia_valid |= (ATTR_ATIME | ATTR_ATIME_SET);
|
||||
}
|
||||
|
||||
if (file_info->ChangeTime)
|
||||
if (file_info->ChangeTime) {
|
||||
fp->change_time = le64_to_cpu(file_info->ChangeTime);
|
||||
inode_set_ctime_to_ts(inode,
|
||||
ksmbd_NTtimeToUnix(file_info->ChangeTime));
|
||||
}
|
||||
|
||||
if (file_info->LastWriteTime) {
|
||||
attrs.ia_mtime = ksmbd_NTtimeToUnix(file_info->LastWriteTime);
|
||||
|
|
|
|||
|
|
@ -97,6 +97,7 @@ struct ksmbd_file {
|
|||
__le32 coption;
|
||||
__le32 cdoption;
|
||||
__u64 create_time;
|
||||
__u64 change_time;
|
||||
__u64 itime;
|
||||
|
||||
bool is_nt_open;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user