mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-21 21:38:04 -04:00
smb/client: fix incorrect nlink returned by fstat()
Reproducer:
1. mount -t cifs //${server_ip}/export /mnt
2. touch /mnt/file1; ln /mnt/file1 /mnt/file2; ln /mnt/file1 /mnt/file3
3. C program: int fd = open("/mnt/file1", O_RDONLY);
4. C program: struct stat stbuf; fstat(fd, &stbuf);
stbuf.st_nlink is always 1, should be 3
Setting `unknown_nlink` to true in `SMB2_open()` triggers the
`CIFS_FATTR_UNKNOWN_NLINK` flag in `cifs_open_info_to_fattr()`,
which safely preserves the existing i_nlink in
`cifs_nlink_fattr_to_inode()`.
See the detailed procedure below:
path_openat
open_last_lookups
lookup_open
atomic_open
cifs_atomic_open // dir->i_op->atomic_open
cifs_lookup
cifs_get_inode_info
cifs_get_fattr
smb2_query_path_info // server->ops->query_path_info
smb2_compound_op
SMB2_open_init
case SMB2_OP_QUERY_INFO
SMB2_query_info_init(FILE_ALL_INFORMATION,)
cifs_open_info_to_fattr
fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks)
update_inode_info
cifs_iget
cifs_fattr_to_inode
cifs_nlink_fattr_to_inode
set_nlink(inode, fattr->cf_nlink)
do_open
vfs_open
do_dentry_open
cifs_open
cifs_nt_open
smb2_open_file // server->ops->open
SMB2_open
buf->unknown_nlink = true
cifs_get_inode_info
cifs_get_fattr
cifs_open_info_to_fattr
if (data->unknown_nlink) // true
fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK
update_inode_info
cifs_fattr_to_inode
cifs_nlink_fattr_to_inode
if (fattr->cf_flags & CIFS_FATTR_UNKNOWN_NLINK) // true
return // do not modify nlink
Signed-off-by: ChenXiaoSong <chenxiaosong@kylinos.cn>
Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
committed by
Steve French
parent
8fce4cf436
commit
9dd1964ac5
@@ -250,6 +250,7 @@ struct cifs_open_info_data {
|
||||
bool adjust_tz;
|
||||
bool reparse_point;
|
||||
bool contains_posix_file_info;
|
||||
bool unknown_nlink;
|
||||
struct {
|
||||
/* ioctl response buffer */
|
||||
struct {
|
||||
|
||||
@@ -909,6 +909,8 @@ static void cifs_open_info_to_fattr(struct cifs_fattr *fattr,
|
||||
struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
|
||||
|
||||
memset(fattr, 0, sizeof(*fattr));
|
||||
if (data->unknown_nlink)
|
||||
fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK;
|
||||
fattr->cf_cifsattrs = le32_to_cpu(info->Attributes);
|
||||
if (info->DeletePending)
|
||||
fattr->cf_flags |= CIFS_FATTR_DELETE_PENDING;
|
||||
|
||||
@@ -3380,6 +3380,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
|
||||
file_info->EndOfFile = rsp->EndofFile;
|
||||
file_info->Attributes = rsp->FileAttributes;
|
||||
file_info->NumberOfLinks = cpu_to_le32(1);
|
||||
buf->unknown_nlink = true;
|
||||
file_info->DeletePending = 0; /* successful open = not delete pending */
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user