Skip to content

Commit c10037f

Browse files
committed
Merge tag '5.10-rc-smb3-fixes-part2' of git://git.samba.org/sfrench/cifs-2.6
Pull more cifs updates from Steve French: "Add support for stat of various special file types (WSL reparse points for char, block, fifo)" * tag '5.10-rc-smb3-fixes-part2' of git://git.samba.org/sfrench/cifs-2.6: cifs: update internal module version number smb3: add some missing definitions from MS-FSCC smb3: remove two unused variables smb3: add support for stat of WSL reparse points for special file types
2 parents f9c25d9 + aef0388 commit c10037f

File tree

8 files changed

+213
-15
lines changed

8 files changed

+213
-15
lines changed

fs/cifs/cifsfs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,5 +156,5 @@ extern int cifs_truncate_page(struct address_space *mapping, loff_t from);
156156
extern const struct export_operations cifs_export_ops;
157157
#endif /* CONFIG_CIFS_NFSD_EXPORT */
158158

159-
#define CIFS_VERSION "2.28"
159+
#define CIFS_VERSION "2.29"
160160
#endif /* _CIFSFS_H */

fs/cifs/cifsglob.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,10 @@ struct smb_version_operations {
298298
/* query file data from the server */
299299
int (*query_file_info)(const unsigned int, struct cifs_tcon *,
300300
struct cifs_fid *, FILE_ALL_INFO *);
301+
/* query reparse tag from srv to determine which type of special file */
302+
int (*query_reparse_tag)(const unsigned int xid, struct cifs_tcon *tcon,
303+
struct cifs_sb_info *cifs_sb, const char *path,
304+
__u32 *reparse_tag);
301305
/* get server index number */
302306
int (*get_srv_inum)(const unsigned int, struct cifs_tcon *,
303307
struct cifs_sb_info *, const char *,

fs/cifs/inode.c

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -656,7 +656,7 @@ smb311_posix_info_to_fattr(struct cifs_fattr *fattr, struct smb311_posix_qinfo *
656656
static void
657657
cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
658658
struct super_block *sb, bool adjust_tz,
659-
bool symlink)
659+
bool symlink, u32 reparse_tag)
660660
{
661661
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
662662
struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
@@ -684,8 +684,22 @@ cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
684684
fattr->cf_createtime = le64_to_cpu(info->CreationTime);
685685

686686
fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks);
687-
688-
if (symlink) {
687+
if (reparse_tag == IO_REPARSE_TAG_LX_SYMLINK) {
688+
fattr->cf_mode |= S_IFLNK | cifs_sb->mnt_file_mode;
689+
fattr->cf_dtype = DT_LNK;
690+
} else if (reparse_tag == IO_REPARSE_TAG_LX_FIFO) {
691+
fattr->cf_mode |= S_IFIFO | cifs_sb->mnt_file_mode;
692+
fattr->cf_dtype = DT_FIFO;
693+
} else if (reparse_tag == IO_REPARSE_TAG_AF_UNIX) {
694+
fattr->cf_mode |= S_IFSOCK | cifs_sb->mnt_file_mode;
695+
fattr->cf_dtype = DT_SOCK;
696+
} else if (reparse_tag == IO_REPARSE_TAG_LX_CHR) {
697+
fattr->cf_mode |= S_IFCHR | cifs_sb->mnt_file_mode;
698+
fattr->cf_dtype = DT_CHR;
699+
} else if (reparse_tag == IO_REPARSE_TAG_LX_BLK) {
700+
fattr->cf_mode |= S_IFBLK | cifs_sb->mnt_file_mode;
701+
fattr->cf_dtype = DT_BLK;
702+
} else if (symlink) { /* TODO add more reparse tag checks */
689703
fattr->cf_mode = S_IFLNK;
690704
fattr->cf_dtype = DT_LNK;
691705
} else if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
@@ -740,8 +754,9 @@ cifs_get_file_info(struct file *filp)
740754
rc = server->ops->query_file_info(xid, tcon, &cfile->fid, &find_data);
741755
switch (rc) {
742756
case 0:
757+
/* TODO: add support to query reparse tag */
743758
cifs_all_info_to_fattr(&fattr, &find_data, inode->i_sb, false,
744-
false);
759+
false, 0 /* no reparse tag */);
745760
break;
746761
case -EREMOTE:
747762
cifs_create_dfs_fattr(&fattr, inode->i_sb);
@@ -910,12 +925,13 @@ cifs_get_inode_info(struct inode **inode,
910925
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
911926
bool adjust_tz = false;
912927
struct cifs_fattr fattr = {0};
913-
bool symlink = false;
928+
bool is_reparse_point = false;
914929
FILE_ALL_INFO *data = in_data;
915930
FILE_ALL_INFO *tmp_data = NULL;
916931
void *smb1_backup_rsp_buf = NULL;
917932
int rc = 0;
918933
int tmprc = 0;
934+
__u32 reparse_tag = 0;
919935

920936
tlink = cifs_sb_tlink(cifs_sb);
921937
if (IS_ERR(tlink))
@@ -938,8 +954,8 @@ cifs_get_inode_info(struct inode **inode,
938954
goto out;
939955
}
940956
rc = server->ops->query_path_info(xid, tcon, cifs_sb,
941-
full_path, tmp_data,
942-
&adjust_tz, &symlink);
957+
full_path, tmp_data,
958+
&adjust_tz, &is_reparse_point);
943959
data = tmp_data;
944960
}
945961

@@ -949,7 +965,19 @@ cifs_get_inode_info(struct inode **inode,
949965

950966
switch (rc) {
951967
case 0:
952-
cifs_all_info_to_fattr(&fattr, data, sb, adjust_tz, symlink);
968+
/*
969+
* If the file is a reparse point, it is more complicated
970+
* since we have to check if its reparse tag matches a known
971+
* special file type e.g. symlink or fifo or char etc.
972+
*/
973+
if ((le32_to_cpu(data->Attributes) & ATTR_REPARSE) &&
974+
server->ops->query_reparse_tag) {
975+
rc = server->ops->query_reparse_tag(xid, tcon, cifs_sb,
976+
full_path, &reparse_tag);
977+
cifs_dbg(FYI, "reparse tag 0x%x\n", reparse_tag);
978+
}
979+
cifs_all_info_to_fattr(&fattr, data, sb, adjust_tz,
980+
is_reparse_point, reparse_tag);
953981
break;
954982
case -EREMOTE:
955983
/* DFS link, no metadata available on this server */

fs/cifs/smb2inode.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -506,7 +506,7 @@ move_smb2_info_to_cifs(FILE_ALL_INFO *dst, struct smb2_file_all_info *src)
506506
int
507507
smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
508508
struct cifs_sb_info *cifs_sb, const char *full_path,
509-
FILE_ALL_INFO *data, bool *adjust_tz, bool *symlink)
509+
FILE_ALL_INFO *data, bool *adjust_tz, bool *reparse)
510510
{
511511
int rc;
512512
struct smb2_file_all_info *smb2_data;
@@ -516,7 +516,7 @@ smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
516516
struct cached_fid *cfid = NULL;
517517

518518
*adjust_tz = false;
519-
*symlink = false;
519+
*reparse = false;
520520

521521
smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + PATH_MAX * 2,
522522
GFP_KERNEL);
@@ -548,7 +548,7 @@ smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
548548
FILE_READ_ATTRIBUTES, FILE_OPEN, create_options,
549549
ACL_NO_MODE, smb2_data, SMB2_OP_QUERY_INFO, cfile);
550550
if (rc == -EOPNOTSUPP) {
551-
*symlink = true;
551+
*reparse = true;
552552
create_options |= OPEN_REPARSE_POINT;
553553

554554
/* Failed on a symbolic link - query a reparse point info */
@@ -570,15 +570,15 @@ smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
570570
int
571571
smb311_posix_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
572572
struct cifs_sb_info *cifs_sb, const char *full_path,
573-
struct smb311_posix_qinfo *data, bool *adjust_tz, bool *symlink)
573+
struct smb311_posix_qinfo *data, bool *adjust_tz, bool *reparse)
574574
{
575575
int rc;
576576
__u32 create_options = 0;
577577
struct cifsFileInfo *cfile;
578578
struct smb311_posix_qinfo *smb2_data;
579579

580580
*adjust_tz = false;
581-
*symlink = false;
581+
*reparse = false;
582582

583583
/* BB TODO: Make struct larger when add support for parsing owner SIDs */
584584
smb2_data = kzalloc(sizeof(struct smb311_posix_qinfo),
@@ -599,7 +599,7 @@ smb311_posix_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
599599
ACL_NO_MODE, smb2_data, SMB2_OP_POSIX_QUERY_INFO, cfile);
600600
if (rc == -EOPNOTSUPP) {
601601
/* BB TODO: When support for special files added to Samba re-verify this path */
602-
*symlink = true;
602+
*reparse = true;
603603
create_options |= OPEN_REPARSE_POINT;
604604

605605
/* Failed on a symbolic link - query a reparse point info */

fs/cifs/smb2ops.c

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3034,6 +3034,133 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
30343034
return rc;
30353035
}
30363036

3037+
int
3038+
smb2_query_reparse_tag(const unsigned int xid, struct cifs_tcon *tcon,
3039+
struct cifs_sb_info *cifs_sb, const char *full_path,
3040+
__u32 *tag)
3041+
{
3042+
int rc;
3043+
__le16 *utf16_path = NULL;
3044+
__u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
3045+
struct cifs_open_parms oparms;
3046+
struct cifs_fid fid;
3047+
struct TCP_Server_Info *server = cifs_pick_channel(tcon->ses);
3048+
int flags = 0;
3049+
struct smb_rqst rqst[3];
3050+
int resp_buftype[3];
3051+
struct kvec rsp_iov[3];
3052+
struct kvec open_iov[SMB2_CREATE_IOV_SIZE];
3053+
struct kvec io_iov[SMB2_IOCTL_IOV_SIZE];
3054+
struct kvec close_iov[1];
3055+
struct smb2_ioctl_rsp *ioctl_rsp;
3056+
struct reparse_data_buffer *reparse_buf;
3057+
u32 plen;
3058+
3059+
cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path);
3060+
3061+
if (smb3_encryption_required(tcon))
3062+
flags |= CIFS_TRANSFORM_REQ;
3063+
3064+
memset(rqst, 0, sizeof(rqst));
3065+
resp_buftype[0] = resp_buftype[1] = resp_buftype[2] = CIFS_NO_BUFFER;
3066+
memset(rsp_iov, 0, sizeof(rsp_iov));
3067+
3068+
utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb);
3069+
if (!utf16_path)
3070+
return -ENOMEM;
3071+
3072+
/*
3073+
* setup smb2open - TODO add optimization to call cifs_get_readable_path
3074+
* to see if there is a handle already open that we can use
3075+
*/
3076+
memset(&open_iov, 0, sizeof(open_iov));
3077+
rqst[0].rq_iov = open_iov;
3078+
rqst[0].rq_nvec = SMB2_CREATE_IOV_SIZE;
3079+
3080+
memset(&oparms, 0, sizeof(oparms));
3081+
oparms.tcon = tcon;
3082+
oparms.desired_access = FILE_READ_ATTRIBUTES;
3083+
oparms.disposition = FILE_OPEN;
3084+
oparms.create_options = cifs_create_options(cifs_sb, OPEN_REPARSE_POINT);
3085+
oparms.fid = &fid;
3086+
oparms.reconnect = false;
3087+
3088+
rc = SMB2_open_init(tcon, server,
3089+
&rqst[0], &oplock, &oparms, utf16_path);
3090+
if (rc)
3091+
goto query_rp_exit;
3092+
smb2_set_next_command(tcon, &rqst[0]);
3093+
3094+
3095+
/* IOCTL */
3096+
memset(&io_iov, 0, sizeof(io_iov));
3097+
rqst[1].rq_iov = io_iov;
3098+
rqst[1].rq_nvec = SMB2_IOCTL_IOV_SIZE;
3099+
3100+
rc = SMB2_ioctl_init(tcon, server,
3101+
&rqst[1], fid.persistent_fid,
3102+
fid.volatile_fid, FSCTL_GET_REPARSE_POINT,
3103+
true /* is_fctl */, NULL, 0,
3104+
CIFSMaxBufSize -
3105+
MAX_SMB2_CREATE_RESPONSE_SIZE -
3106+
MAX_SMB2_CLOSE_RESPONSE_SIZE);
3107+
if (rc)
3108+
goto query_rp_exit;
3109+
3110+
smb2_set_next_command(tcon, &rqst[1]);
3111+
smb2_set_related(&rqst[1]);
3112+
3113+
3114+
/* Close */
3115+
memset(&close_iov, 0, sizeof(close_iov));
3116+
rqst[2].rq_iov = close_iov;
3117+
rqst[2].rq_nvec = 1;
3118+
3119+
rc = SMB2_close_init(tcon, server,
3120+
&rqst[2], COMPOUND_FID, COMPOUND_FID, false);
3121+
if (rc)
3122+
goto query_rp_exit;
3123+
3124+
smb2_set_related(&rqst[2]);
3125+
3126+
rc = compound_send_recv(xid, tcon->ses, server,
3127+
flags, 3, rqst,
3128+
resp_buftype, rsp_iov);
3129+
3130+
ioctl_rsp = rsp_iov[1].iov_base;
3131+
3132+
/*
3133+
* Open was successful and we got an ioctl response.
3134+
*/
3135+
if (rc == 0) {
3136+
/* See MS-FSCC 2.3.23 */
3137+
3138+
reparse_buf = (struct reparse_data_buffer *)
3139+
((char *)ioctl_rsp +
3140+
le32_to_cpu(ioctl_rsp->OutputOffset));
3141+
plen = le32_to_cpu(ioctl_rsp->OutputCount);
3142+
3143+
if (plen + le32_to_cpu(ioctl_rsp->OutputOffset) >
3144+
rsp_iov[1].iov_len) {
3145+
cifs_tcon_dbg(FYI, "srv returned invalid ioctl len: %d\n",
3146+
plen);
3147+
rc = -EIO;
3148+
goto query_rp_exit;
3149+
}
3150+
*tag = le32_to_cpu(reparse_buf->ReparseTag);
3151+
}
3152+
3153+
query_rp_exit:
3154+
kfree(utf16_path);
3155+
SMB2_open_free(&rqst[0]);
3156+
SMB2_ioctl_free(&rqst[1]);
3157+
SMB2_close_free(&rqst[2]);
3158+
free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base);
3159+
free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base);
3160+
free_rsp_buf(resp_buftype[2], rsp_iov[2].iov_base);
3161+
return rc;
3162+
}
3163+
30373164
static struct cifs_ntsd *
30383165
get_smb2_acl_by_fid(struct cifs_sb_info *cifs_sb,
30393166
const struct cifs_fid *cifsfid, u32 *pacllen)
@@ -4986,6 +5113,8 @@ struct smb_version_operations smb30_operations = {
49865113
.can_echo = smb2_can_echo,
49875114
.echo = SMB2_echo,
49885115
.query_path_info = smb2_query_path_info,
5116+
/* WSL tags introduced long after smb2.1, enable for SMB3, 3.11 only */
5117+
.query_reparse_tag = smb2_query_reparse_tag,
49895118
.get_srv_inum = smb2_get_srv_inum,
49905119
.query_file_info = smb2_query_file_info,
49915120
.set_path_size = smb2_set_path_size,
@@ -5097,6 +5226,7 @@ struct smb_version_operations smb311_operations = {
50975226
.can_echo = smb2_can_echo,
50985227
.echo = SMB2_echo,
50995228
.query_path_info = smb2_query_path_info,
5229+
.query_reparse_tag = smb2_query_reparse_tag,
51005230
.get_srv_inum = smb2_get_srv_inum,
51015231
.query_file_info = smb2_query_file_info,
51025232
.set_path_size = smb2_set_path_size,

fs/cifs/smb2pdu.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -999,6 +999,31 @@ struct copychunk_ioctl_rsp {
999999
__le32 TotalBytesWritten;
10001000
} __packed;
10011001

1002+
/* See MS-FSCC 2.3.29 and 2.3.30 */
1003+
struct get_retrieval_pointer_count_req {
1004+
__le64 StartingVcn; /* virtual cluster number (signed) */
1005+
} __packed;
1006+
1007+
struct get_retrieval_pointer_count_rsp {
1008+
__le32 ExtentCount;
1009+
} __packed;
1010+
1011+
/*
1012+
* See MS-FSCC 2.3.33 and 2.3.34
1013+
* request is the same as get_retrieval_point_count_req struct above
1014+
*/
1015+
struct smb3_extents {
1016+
__le64 NextVcn;
1017+
__le64 Lcn; /* logical cluster number */
1018+
} __packed;
1019+
1020+
struct get_retrieval_pointers_refcount_rsp {
1021+
__le32 ExtentCount;
1022+
__u32 Reserved;
1023+
__le64 StartingVcn;
1024+
struct smb3_extents extents[];
1025+
} __packed;
1026+
10021027
struct fsctl_set_integrity_information_req {
10031028
__le16 ChecksumAlgorithm;
10041029
__le16 Reserved;
@@ -1640,6 +1665,7 @@ struct smb2_file_rename_info { /* encoding of request for level 10 */
16401665
__u64 RootDirectory; /* MBZ for network operations (why says spec?) */
16411666
__le32 FileNameLength;
16421667
char FileName[]; /* New name to be assigned */
1668+
/* padding - overall struct size must be >= 24 so filename + pad >= 6 */
16431669
} __packed; /* level 10 Set */
16441670

16451671
struct smb2_file_link_info { /* encoding of request for level 11 */
@@ -1691,6 +1717,11 @@ struct smb2_file_eof_info { /* encoding of request for level 10 */
16911717
__le64 EndOfFile; /* new end of file value */
16921718
} __packed; /* level 20 Set */
16931719

1720+
struct smb2_file_reparse_point_info {
1721+
__le64 IndexNumber;
1722+
__le32 Tag;
1723+
} __packed;
1724+
16941725
struct smb2_file_network_open_info {
16951726
__le64 CreationTime;
16961727
__le64 LastAccessTime;

fs/cifs/smb2proto.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@ extern void close_shroot_lease(struct cached_fid *cfid);
7777
extern void close_shroot_lease_locked(struct cached_fid *cfid);
7878
extern void move_smb2_info_to_cifs(FILE_ALL_INFO *dst,
7979
struct smb2_file_all_info *src);
80+
extern int smb2_query_reparse_tag(const unsigned int xid, struct cifs_tcon *tcon,
81+
struct cifs_sb_info *cifs_sb, const char *path,
82+
__u32 *reparse_tag);
8083
extern int smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
8184
struct cifs_sb_info *cifs_sb,
8285
const char *full_path, FILE_ALL_INFO *data,

fs/cifs/smbfsctl.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,8 @@
103103
#define FSCTL_SET_ZERO_ON_DEALLOC 0x00090194 /* BB add struct */
104104
#define FSCTL_SET_SHORT_NAME_BEHAVIOR 0x000901B4 /* BB add struct */
105105
#define FSCTL_GET_INTEGRITY_INFORMATION 0x0009027C
106+
#define FSCTL_GET_RETRIEVAL_POINTERS_AND_REFCOUNT 0x000903d3
107+
#define FSCTL_GET_RETRIEVAL_POINTER_COUNT 0x0009042b
106108
#define FSCTL_QUERY_ALLOCATED_RANGES 0x000940CF
107109
#define FSCTL_SET_DEFECT_MANAGEMENT 0x00098134 /* BB add struct */
108110
#define FSCTL_FILE_LEVEL_TRIM 0x00098208 /* BB add struct */

0 commit comments

Comments
 (0)