ksmbd: replace generic_fillattr with vfs_getattr

generic_fillattr should not be used outside of ->getattr
implementations.

Use vfs_getattr instead, and adapt functions to return an
error code to the caller.

Cc: stable@vger.kernel.org
Signed-off-by: Marios Makassikis <mmakassikis@freebox.fr>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
Marios Makassikis 2024-02-22 10:58:19 +01:00 committed by Steve French
parent e8f897f4af
commit 5614c8c487
3 changed files with 127 additions and 66 deletions

View File

@ -3828,11 +3828,16 @@ static int process_query_dir_entries(struct smb2_query_dir_private *priv)
} }
ksmbd_kstat.kstat = &kstat; ksmbd_kstat.kstat = &kstat;
if (priv->info_level != FILE_NAMES_INFORMATION) if (priv->info_level != FILE_NAMES_INFORMATION) {
ksmbd_vfs_fill_dentry_attrs(priv->work, rc = ksmbd_vfs_fill_dentry_attrs(priv->work,
idmap, idmap,
dent, dent,
&ksmbd_kstat); &ksmbd_kstat);
if (rc) {
dput(dent);
continue;
}
}
rc = smb2_populate_readdir_entry(priv->work->conn, rc = smb2_populate_readdir_entry(priv->work->conn,
priv->info_level, priv->info_level,
@ -4480,6 +4485,7 @@ static int get_file_basic_info(struct smb2_query_info_rsp *rsp,
struct smb2_file_basic_info *basic_info; struct smb2_file_basic_info *basic_info;
struct kstat stat; struct kstat stat;
u64 time; u64 time;
int ret;
if (!(fp->daccess & FILE_READ_ATTRIBUTES_LE)) { if (!(fp->daccess & FILE_READ_ATTRIBUTES_LE)) {
pr_err("no right to read the attributes : 0x%x\n", pr_err("no right to read the attributes : 0x%x\n",
@ -4487,9 +4493,12 @@ static int get_file_basic_info(struct smb2_query_info_rsp *rsp,
return -EACCES; return -EACCES;
} }
ret = vfs_getattr(&fp->filp->f_path, &stat, STATX_BASIC_STATS,
AT_STATX_SYNC_AS_STAT);
if (ret)
return ret;
basic_info = (struct smb2_file_basic_info *)rsp->Buffer; basic_info = (struct smb2_file_basic_info *)rsp->Buffer;
generic_fillattr(file_mnt_idmap(fp->filp), STATX_BASIC_STATS,
file_inode(fp->filp), &stat);
basic_info->CreationTime = cpu_to_le64(fp->create_time); basic_info->CreationTime = cpu_to_le64(fp->create_time);
time = ksmbd_UnixTimeToNT(stat.atime); time = ksmbd_UnixTimeToNT(stat.atime);
basic_info->LastAccessTime = cpu_to_le64(time); basic_info->LastAccessTime = cpu_to_le64(time);
@ -4504,27 +4513,31 @@ static int get_file_basic_info(struct smb2_query_info_rsp *rsp,
return 0; return 0;
} }
static void get_file_standard_info(struct smb2_query_info_rsp *rsp, static int get_file_standard_info(struct smb2_query_info_rsp *rsp,
struct ksmbd_file *fp, void *rsp_org) struct ksmbd_file *fp, void *rsp_org)
{ {
struct smb2_file_standard_info *sinfo; struct smb2_file_standard_info *sinfo;
unsigned int delete_pending; unsigned int delete_pending;
struct inode *inode;
struct kstat stat; struct kstat stat;
int ret;
inode = file_inode(fp->filp); ret = vfs_getattr(&fp->filp->f_path, &stat, STATX_BASIC_STATS,
generic_fillattr(file_mnt_idmap(fp->filp), STATX_BASIC_STATS, inode, &stat); AT_STATX_SYNC_AS_STAT);
if (ret)
return ret;
sinfo = (struct smb2_file_standard_info *)rsp->Buffer; sinfo = (struct smb2_file_standard_info *)rsp->Buffer;
delete_pending = ksmbd_inode_pending_delete(fp); delete_pending = ksmbd_inode_pending_delete(fp);
sinfo->AllocationSize = cpu_to_le64(inode->i_blocks << 9); sinfo->AllocationSize = cpu_to_le64(stat.blocks << 9);
sinfo->EndOfFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size); sinfo->EndOfFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size);
sinfo->NumberOfLinks = cpu_to_le32(get_nlink(&stat) - delete_pending); sinfo->NumberOfLinks = cpu_to_le32(get_nlink(&stat) - delete_pending);
sinfo->DeletePending = delete_pending; sinfo->DeletePending = delete_pending;
sinfo->Directory = S_ISDIR(stat.mode) ? 1 : 0; sinfo->Directory = S_ISDIR(stat.mode) ? 1 : 0;
rsp->OutputBufferLength = rsp->OutputBufferLength =
cpu_to_le32(sizeof(struct smb2_file_standard_info)); cpu_to_le32(sizeof(struct smb2_file_standard_info));
return 0;
} }
static void get_file_alignment_info(struct smb2_query_info_rsp *rsp, static void get_file_alignment_info(struct smb2_query_info_rsp *rsp,
@ -4546,11 +4559,11 @@ static int get_file_all_info(struct ksmbd_work *work,
struct ksmbd_conn *conn = work->conn; struct ksmbd_conn *conn = work->conn;
struct smb2_file_all_info *file_info; struct smb2_file_all_info *file_info;
unsigned int delete_pending; unsigned int delete_pending;
struct inode *inode;
struct kstat stat; struct kstat stat;
int conv_len; int conv_len;
char *filename; char *filename;
u64 time; u64 time;
int ret;
if (!(fp->daccess & FILE_READ_ATTRIBUTES_LE)) { if (!(fp->daccess & FILE_READ_ATTRIBUTES_LE)) {
ksmbd_debug(SMB, "no right to read the attributes : 0x%x\n", ksmbd_debug(SMB, "no right to read the attributes : 0x%x\n",
@ -4562,8 +4575,10 @@ static int get_file_all_info(struct ksmbd_work *work,
if (IS_ERR(filename)) if (IS_ERR(filename))
return PTR_ERR(filename); return PTR_ERR(filename);
inode = file_inode(fp->filp); ret = vfs_getattr(&fp->filp->f_path, &stat, STATX_BASIC_STATS,
generic_fillattr(file_mnt_idmap(fp->filp), STATX_BASIC_STATS, inode, &stat); AT_STATX_SYNC_AS_STAT);
if (ret)
return ret;
ksmbd_debug(SMB, "filename = %s\n", filename); ksmbd_debug(SMB, "filename = %s\n", filename);
delete_pending = ksmbd_inode_pending_delete(fp); delete_pending = ksmbd_inode_pending_delete(fp);
@ -4579,7 +4594,7 @@ static int get_file_all_info(struct ksmbd_work *work,
file_info->Attributes = fp->f_ci->m_fattr; file_info->Attributes = fp->f_ci->m_fattr;
file_info->Pad1 = 0; file_info->Pad1 = 0;
file_info->AllocationSize = file_info->AllocationSize =
cpu_to_le64(inode->i_blocks << 9); cpu_to_le64(stat.blocks << 9);
file_info->EndOfFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size); file_info->EndOfFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size);
file_info->NumberOfLinks = file_info->NumberOfLinks =
cpu_to_le32(get_nlink(&stat) - delete_pending); cpu_to_le32(get_nlink(&stat) - delete_pending);
@ -4623,10 +4638,10 @@ static void get_file_alternate_info(struct ksmbd_work *work,
cpu_to_le32(sizeof(struct smb2_file_alt_name_info) + conv_len); cpu_to_le32(sizeof(struct smb2_file_alt_name_info) + conv_len);
} }
static void get_file_stream_info(struct ksmbd_work *work, static int get_file_stream_info(struct ksmbd_work *work,
struct smb2_query_info_rsp *rsp, struct smb2_query_info_rsp *rsp,
struct ksmbd_file *fp, struct ksmbd_file *fp,
void *rsp_org) void *rsp_org)
{ {
struct ksmbd_conn *conn = work->conn; struct ksmbd_conn *conn = work->conn;
struct smb2_file_stream_info *file_info; struct smb2_file_stream_info *file_info;
@ -4637,9 +4652,13 @@ static void get_file_stream_info(struct ksmbd_work *work,
int nbytes = 0, streamlen, stream_name_len, next, idx = 0; int nbytes = 0, streamlen, stream_name_len, next, idx = 0;
int buf_free_len; int buf_free_len;
struct smb2_query_info_req *req = ksmbd_req_buf_next(work); struct smb2_query_info_req *req = ksmbd_req_buf_next(work);
int ret;
ret = vfs_getattr(&fp->filp->f_path, &stat, STATX_BASIC_STATS,
AT_STATX_SYNC_AS_STAT);
if (ret)
return ret;
generic_fillattr(file_mnt_idmap(fp->filp), STATX_BASIC_STATS,
file_inode(fp->filp), &stat);
file_info = (struct smb2_file_stream_info *)rsp->Buffer; file_info = (struct smb2_file_stream_info *)rsp->Buffer;
buf_free_len = buf_free_len =
@ -4720,29 +4739,37 @@ out:
kvfree(xattr_list); kvfree(xattr_list);
rsp->OutputBufferLength = cpu_to_le32(nbytes); rsp->OutputBufferLength = cpu_to_le32(nbytes);
return 0;
} }
static void get_file_internal_info(struct smb2_query_info_rsp *rsp, static int get_file_internal_info(struct smb2_query_info_rsp *rsp,
struct ksmbd_file *fp, void *rsp_org) struct ksmbd_file *fp, void *rsp_org)
{ {
struct smb2_file_internal_info *file_info; struct smb2_file_internal_info *file_info;
struct kstat stat; struct kstat stat;
int ret;
ret = vfs_getattr(&fp->filp->f_path, &stat, STATX_BASIC_STATS,
AT_STATX_SYNC_AS_STAT);
if (ret)
return ret;
generic_fillattr(file_mnt_idmap(fp->filp), STATX_BASIC_STATS,
file_inode(fp->filp), &stat);
file_info = (struct smb2_file_internal_info *)rsp->Buffer; file_info = (struct smb2_file_internal_info *)rsp->Buffer;
file_info->IndexNumber = cpu_to_le64(stat.ino); file_info->IndexNumber = cpu_to_le64(stat.ino);
rsp->OutputBufferLength = rsp->OutputBufferLength =
cpu_to_le32(sizeof(struct smb2_file_internal_info)); cpu_to_le32(sizeof(struct smb2_file_internal_info));
return 0;
} }
static int get_file_network_open_info(struct smb2_query_info_rsp *rsp, static int get_file_network_open_info(struct smb2_query_info_rsp *rsp,
struct ksmbd_file *fp, void *rsp_org) struct ksmbd_file *fp, void *rsp_org)
{ {
struct smb2_file_ntwrk_info *file_info; struct smb2_file_ntwrk_info *file_info;
struct inode *inode;
struct kstat stat; struct kstat stat;
u64 time; u64 time;
int ret;
if (!(fp->daccess & FILE_READ_ATTRIBUTES_LE)) { if (!(fp->daccess & FILE_READ_ATTRIBUTES_LE)) {
pr_err("no right to read the attributes : 0x%x\n", pr_err("no right to read the attributes : 0x%x\n",
@ -4750,10 +4777,12 @@ static int get_file_network_open_info(struct smb2_query_info_rsp *rsp,
return -EACCES; return -EACCES;
} }
file_info = (struct smb2_file_ntwrk_info *)rsp->Buffer; ret = vfs_getattr(&fp->filp->f_path, &stat, STATX_BASIC_STATS,
AT_STATX_SYNC_AS_STAT);
if (ret)
return ret;
inode = file_inode(fp->filp); file_info = (struct smb2_file_ntwrk_info *)rsp->Buffer;
generic_fillattr(file_mnt_idmap(fp->filp), STATX_BASIC_STATS, inode, &stat);
file_info->CreationTime = cpu_to_le64(fp->create_time); file_info->CreationTime = cpu_to_le64(fp->create_time);
time = ksmbd_UnixTimeToNT(stat.atime); time = ksmbd_UnixTimeToNT(stat.atime);
@ -4763,8 +4792,7 @@ static int get_file_network_open_info(struct smb2_query_info_rsp *rsp,
time = ksmbd_UnixTimeToNT(stat.ctime); time = ksmbd_UnixTimeToNT(stat.ctime);
file_info->ChangeTime = cpu_to_le64(time); file_info->ChangeTime = cpu_to_le64(time);
file_info->Attributes = fp->f_ci->m_fattr; file_info->Attributes = fp->f_ci->m_fattr;
file_info->AllocationSize = file_info->AllocationSize = cpu_to_le64(stat.blocks << 9);
cpu_to_le64(inode->i_blocks << 9);
file_info->EndOfFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size); file_info->EndOfFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size);
file_info->Reserved = cpu_to_le32(0); file_info->Reserved = cpu_to_le32(0);
rsp->OutputBufferLength = rsp->OutputBufferLength =
@ -4804,14 +4832,17 @@ static void get_file_mode_info(struct smb2_query_info_rsp *rsp,
cpu_to_le32(sizeof(struct smb2_file_mode_info)); cpu_to_le32(sizeof(struct smb2_file_mode_info));
} }
static void get_file_compression_info(struct smb2_query_info_rsp *rsp, static int get_file_compression_info(struct smb2_query_info_rsp *rsp,
struct ksmbd_file *fp, void *rsp_org) struct ksmbd_file *fp, void *rsp_org)
{ {
struct smb2_file_comp_info *file_info; struct smb2_file_comp_info *file_info;
struct kstat stat; struct kstat stat;
int ret;
generic_fillattr(file_mnt_idmap(fp->filp), STATX_BASIC_STATS, ret = vfs_getattr(&fp->filp->f_path, &stat, STATX_BASIC_STATS,
file_inode(fp->filp), &stat); AT_STATX_SYNC_AS_STAT);
if (ret)
return ret;
file_info = (struct smb2_file_comp_info *)rsp->Buffer; file_info = (struct smb2_file_comp_info *)rsp->Buffer;
file_info->CompressedFileSize = cpu_to_le64(stat.blocks << 9); file_info->CompressedFileSize = cpu_to_le64(stat.blocks << 9);
@ -4823,6 +4854,8 @@ static void get_file_compression_info(struct smb2_query_info_rsp *rsp,
rsp->OutputBufferLength = rsp->OutputBufferLength =
cpu_to_le32(sizeof(struct smb2_file_comp_info)); cpu_to_le32(sizeof(struct smb2_file_comp_info));
return 0;
} }
static int get_file_attribute_tag_info(struct smb2_query_info_rsp *rsp, static int get_file_attribute_tag_info(struct smb2_query_info_rsp *rsp,
@ -4844,7 +4877,7 @@ static int get_file_attribute_tag_info(struct smb2_query_info_rsp *rsp,
return 0; return 0;
} }
static void find_file_posix_info(struct smb2_query_info_rsp *rsp, static int find_file_posix_info(struct smb2_query_info_rsp *rsp,
struct ksmbd_file *fp, void *rsp_org) struct ksmbd_file *fp, void *rsp_org)
{ {
struct smb311_posix_qinfo *file_info; struct smb311_posix_qinfo *file_info;
@ -4852,24 +4885,31 @@ static void find_file_posix_info(struct smb2_query_info_rsp *rsp,
struct mnt_idmap *idmap = file_mnt_idmap(fp->filp); struct mnt_idmap *idmap = file_mnt_idmap(fp->filp);
vfsuid_t vfsuid = i_uid_into_vfsuid(idmap, inode); vfsuid_t vfsuid = i_uid_into_vfsuid(idmap, inode);
vfsgid_t vfsgid = i_gid_into_vfsgid(idmap, inode); vfsgid_t vfsgid = i_gid_into_vfsgid(idmap, inode);
struct kstat stat;
u64 time; u64 time;
int out_buf_len = sizeof(struct smb311_posix_qinfo) + 32; int out_buf_len = sizeof(struct smb311_posix_qinfo) + 32;
int ret;
ret = vfs_getattr(&fp->filp->f_path, &stat, STATX_BASIC_STATS,
AT_STATX_SYNC_AS_STAT);
if (ret)
return ret;
file_info = (struct smb311_posix_qinfo *)rsp->Buffer; file_info = (struct smb311_posix_qinfo *)rsp->Buffer;
file_info->CreationTime = cpu_to_le64(fp->create_time); file_info->CreationTime = cpu_to_le64(fp->create_time);
time = ksmbd_UnixTimeToNT(inode_get_atime(inode)); time = ksmbd_UnixTimeToNT(stat.atime);
file_info->LastAccessTime = cpu_to_le64(time); file_info->LastAccessTime = cpu_to_le64(time);
time = ksmbd_UnixTimeToNT(inode_get_mtime(inode)); time = ksmbd_UnixTimeToNT(stat.mtime);
file_info->LastWriteTime = cpu_to_le64(time); file_info->LastWriteTime = cpu_to_le64(time);
time = ksmbd_UnixTimeToNT(inode_get_ctime(inode)); time = ksmbd_UnixTimeToNT(stat.ctime);
file_info->ChangeTime = cpu_to_le64(time); file_info->ChangeTime = cpu_to_le64(time);
file_info->DosAttributes = fp->f_ci->m_fattr; file_info->DosAttributes = fp->f_ci->m_fattr;
file_info->Inode = cpu_to_le64(inode->i_ino); file_info->Inode = cpu_to_le64(stat.ino);
file_info->EndOfFile = cpu_to_le64(inode->i_size); file_info->EndOfFile = cpu_to_le64(stat.size);
file_info->AllocationSize = cpu_to_le64(inode->i_blocks << 9); file_info->AllocationSize = cpu_to_le64(stat.blocks << 9);
file_info->HardLinks = cpu_to_le32(inode->i_nlink); file_info->HardLinks = cpu_to_le32(stat.nlink);
file_info->Mode = cpu_to_le32(inode->i_mode & 0777); file_info->Mode = cpu_to_le32(stat.mode & 0777);
file_info->DeviceId = cpu_to_le32(inode->i_rdev); file_info->DeviceId = cpu_to_le32(stat.rdev);
/* /*
* Sids(32) contain two sids(Domain sid(16), UNIX group sid(16)). * Sids(32) contain two sids(Domain sid(16), UNIX group sid(16)).
@ -4882,6 +4922,8 @@ static void find_file_posix_info(struct smb2_query_info_rsp *rsp,
SIDUNIX_GROUP, (struct smb_sid *)&file_info->Sids[16]); SIDUNIX_GROUP, (struct smb_sid *)&file_info->Sids[16]);
rsp->OutputBufferLength = cpu_to_le32(out_buf_len); rsp->OutputBufferLength = cpu_to_le32(out_buf_len);
return 0;
} }
static int smb2_get_info_file(struct ksmbd_work *work, static int smb2_get_info_file(struct ksmbd_work *work,
@ -4930,7 +4972,7 @@ static int smb2_get_info_file(struct ksmbd_work *work,
break; break;
case FILE_STANDARD_INFORMATION: case FILE_STANDARD_INFORMATION:
get_file_standard_info(rsp, fp, work->response_buf); rc = get_file_standard_info(rsp, fp, work->response_buf);
break; break;
case FILE_ALIGNMENT_INFORMATION: case FILE_ALIGNMENT_INFORMATION:
@ -4946,11 +4988,11 @@ static int smb2_get_info_file(struct ksmbd_work *work,
break; break;
case FILE_STREAM_INFORMATION: case FILE_STREAM_INFORMATION:
get_file_stream_info(work, rsp, fp, work->response_buf); rc = get_file_stream_info(work, rsp, fp, work->response_buf);
break; break;
case FILE_INTERNAL_INFORMATION: case FILE_INTERNAL_INFORMATION:
get_file_internal_info(rsp, fp, work->response_buf); rc = get_file_internal_info(rsp, fp, work->response_buf);
break; break;
case FILE_NETWORK_OPEN_INFORMATION: case FILE_NETWORK_OPEN_INFORMATION:
@ -4974,7 +5016,7 @@ static int smb2_get_info_file(struct ksmbd_work *work,
break; break;
case FILE_COMPRESSION_INFORMATION: case FILE_COMPRESSION_INFORMATION:
get_file_compression_info(rsp, fp, work->response_buf); rc = get_file_compression_info(rsp, fp, work->response_buf);
break; break;
case FILE_ATTRIBUTE_TAG_INFORMATION: case FILE_ATTRIBUTE_TAG_INFORMATION:
@ -4985,7 +5027,7 @@ static int smb2_get_info_file(struct ksmbd_work *work,
pr_err("client doesn't negotiate with SMB3.1.1 POSIX Extensions\n"); pr_err("client doesn't negotiate with SMB3.1.1 POSIX Extensions\n");
rc = -EOPNOTSUPP; rc = -EOPNOTSUPP;
} else { } else {
find_file_posix_info(rsp, fp, work->response_buf); rc = find_file_posix_info(rsp, fp, work->response_buf);
} }
break; break;
default: default:
@ -5398,7 +5440,6 @@ int smb2_close(struct ksmbd_work *work)
struct smb2_close_rsp *rsp; struct smb2_close_rsp *rsp;
struct ksmbd_conn *conn = work->conn; struct ksmbd_conn *conn = work->conn;
struct ksmbd_file *fp; struct ksmbd_file *fp;
struct inode *inode;
u64 time; u64 time;
int err = 0; int err = 0;
@ -5453,24 +5494,33 @@ int smb2_close(struct ksmbd_work *work)
rsp->Reserved = 0; rsp->Reserved = 0;
if (req->Flags == SMB2_CLOSE_FLAG_POSTQUERY_ATTRIB) { if (req->Flags == SMB2_CLOSE_FLAG_POSTQUERY_ATTRIB) {
struct kstat stat;
int ret;
fp = ksmbd_lookup_fd_fast(work, volatile_id); fp = ksmbd_lookup_fd_fast(work, volatile_id);
if (!fp) { if (!fp) {
err = -ENOENT; err = -ENOENT;
goto out; goto out;
} }
inode = file_inode(fp->filp); ret = vfs_getattr(&fp->filp->f_path, &stat, STATX_BASIC_STATS,
AT_STATX_SYNC_AS_STAT);
if (ret) {
ksmbd_fd_put(work, fp);
goto out;
}
rsp->Flags = SMB2_CLOSE_FLAG_POSTQUERY_ATTRIB; rsp->Flags = SMB2_CLOSE_FLAG_POSTQUERY_ATTRIB;
rsp->AllocationSize = S_ISDIR(inode->i_mode) ? 0 : rsp->AllocationSize = S_ISDIR(stat.mode) ? 0 :
cpu_to_le64(inode->i_blocks << 9); cpu_to_le64(stat.blocks << 9);
rsp->EndOfFile = cpu_to_le64(inode->i_size); rsp->EndOfFile = cpu_to_le64(stat.size);
rsp->Attributes = fp->f_ci->m_fattr; rsp->Attributes = fp->f_ci->m_fattr;
rsp->CreationTime = cpu_to_le64(fp->create_time); rsp->CreationTime = cpu_to_le64(fp->create_time);
time = ksmbd_UnixTimeToNT(inode_get_atime(inode)); time = ksmbd_UnixTimeToNT(stat.atime);
rsp->LastAccessTime = cpu_to_le64(time); rsp->LastAccessTime = cpu_to_le64(time);
time = ksmbd_UnixTimeToNT(inode_get_mtime(inode)); time = ksmbd_UnixTimeToNT(stat.mtime);
rsp->LastWriteTime = cpu_to_le64(time); rsp->LastWriteTime = cpu_to_le64(time);
time = ksmbd_UnixTimeToNT(inode_get_ctime(inode)); time = ksmbd_UnixTimeToNT(stat.ctime);
rsp->ChangeTime = cpu_to_le64(time); rsp->ChangeTime = cpu_to_le64(time);
ksmbd_fd_put(work, fp); ksmbd_fd_put(work, fp);
} else { } else {

View File

@ -457,10 +457,13 @@ int ksmbd_populate_dot_dotdot_entries(struct ksmbd_work *work, int info_level,
} }
ksmbd_kstat.kstat = &kstat; ksmbd_kstat.kstat = &kstat;
ksmbd_vfs_fill_dentry_attrs(work, rc = ksmbd_vfs_fill_dentry_attrs(work,
idmap, idmap,
dentry, dentry,
&ksmbd_kstat); &ksmbd_kstat);
if (rc)
break;
rc = fn(conn, info_level, d_info, &ksmbd_kstat); rc = fn(conn, info_level, d_info, &ksmbd_kstat);
if (rc) if (rc)
break; break;

View File

@ -1682,11 +1682,19 @@ int ksmbd_vfs_fill_dentry_attrs(struct ksmbd_work *work,
struct dentry *dentry, struct dentry *dentry,
struct ksmbd_kstat *ksmbd_kstat) struct ksmbd_kstat *ksmbd_kstat)
{ {
struct ksmbd_share_config *share_conf = work->tcon->share_conf;
u64 time; u64 time;
int rc; int rc;
struct path path = {
.mnt = share_conf->vfs_path.mnt,
.dentry = dentry,
};
generic_fillattr(idmap, STATX_BASIC_STATS, d_inode(dentry), rc = vfs_getattr(&path, ksmbd_kstat->kstat,
ksmbd_kstat->kstat); STATX_BASIC_STATS | STATX_BTIME,
AT_STATX_SYNC_AS_STAT);
if (rc)
return rc;
time = ksmbd_UnixTimeToNT(ksmbd_kstat->kstat->ctime); time = ksmbd_UnixTimeToNT(ksmbd_kstat->kstat->ctime);
ksmbd_kstat->create_time = time; ksmbd_kstat->create_time = time;