ksmbd: replace generic_fillattr with vfs_getattr
[ Upstream commit 5614c8c487f6af627614dd2efca038e4afe0c6d7 ] 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> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
ef309589f0
commit
c8f7ad2df0
|
@ -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 {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -1669,11 +1669,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;
|
||||||
|
|
Loading…
Reference in New Issue