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

+213 -15
+1 -1
fs/cifs/cifsfs.h
··· 156 156 extern const struct export_operations cifs_export_ops; 157 157 #endif /* CONFIG_CIFS_NFSD_EXPORT */ 158 158 159 - #define CIFS_VERSION "2.28" 159 + #define CIFS_VERSION "2.29" 160 160 #endif /* _CIFSFS_H */
+4
fs/cifs/cifsglob.h
··· 298 298 /* query file data from the server */ 299 299 int (*query_file_info)(const unsigned int, struct cifs_tcon *, 300 300 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); 301 305 /* get server index number */ 302 306 int (*get_srv_inum)(const unsigned int, struct cifs_tcon *, 303 307 struct cifs_sb_info *, const char *,
+36 -8
fs/cifs/inode.c
··· 656 656 static void 657 657 cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info, 658 658 struct super_block *sb, bool adjust_tz, 659 - bool symlink) 659 + bool symlink, u32 reparse_tag) 660 660 { 661 661 struct cifs_sb_info *cifs_sb = CIFS_SB(sb); 662 662 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); ··· 684 684 fattr->cf_createtime = le64_to_cpu(info->CreationTime); 685 685 686 686 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 */ 689 703 fattr->cf_mode = S_IFLNK; 690 704 fattr->cf_dtype = DT_LNK; 691 705 } else if (fattr->cf_cifsattrs & ATTR_DIRECTORY) { ··· 754 740 rc = server->ops->query_file_info(xid, tcon, &cfile->fid, &find_data); 755 741 switch (rc) { 756 742 case 0: 743 + /* TODO: add support to query reparse tag */ 757 744 cifs_all_info_to_fattr(&fattr, &find_data, inode->i_sb, false, 758 - false); 745 + false, 0 /* no reparse tag */); 759 746 break; 760 747 case -EREMOTE: 761 748 cifs_create_dfs_fattr(&fattr, inode->i_sb); ··· 925 910 struct cifs_sb_info *cifs_sb = CIFS_SB(sb); 926 911 bool adjust_tz = false; 927 912 struct cifs_fattr fattr = {0}; 928 - bool symlink = false; 913 + bool is_reparse_point = false; 929 914 FILE_ALL_INFO *data = in_data; 930 915 FILE_ALL_INFO *tmp_data = NULL; 931 916 void *smb1_backup_rsp_buf = NULL; 932 917 int rc = 0; 933 918 int tmprc = 0; 919 + __u32 reparse_tag = 0; 934 920 935 921 tlink = cifs_sb_tlink(cifs_sb); 936 922 if (IS_ERR(tlink)) ··· 954 938 goto out; 955 939 } 956 940 rc = server->ops->query_path_info(xid, tcon, cifs_sb, 957 - full_path, tmp_data, 958 - &adjust_tz, &symlink); 941 + full_path, tmp_data, 942 + &adjust_tz, &is_reparse_point); 959 943 data = tmp_data; 960 944 } 961 945 ··· 965 949 966 950 switch (rc) { 967 951 case 0: 968 - cifs_all_info_to_fattr(&fattr, data, sb, adjust_tz, symlink); 952 + /* 953 + * If the file is a reparse point, it is more complicated 954 + * since we have to check if its reparse tag matches a known 955 + * special file type e.g. symlink or fifo or char etc. 956 + */ 957 + if ((le32_to_cpu(data->Attributes) & ATTR_REPARSE) && 958 + server->ops->query_reparse_tag) { 959 + rc = server->ops->query_reparse_tag(xid, tcon, cifs_sb, 960 + full_path, &reparse_tag); 961 + cifs_dbg(FYI, "reparse tag 0x%x\n", reparse_tag); 962 + } 963 + cifs_all_info_to_fattr(&fattr, data, sb, adjust_tz, 964 + is_reparse_point, reparse_tag); 969 965 break; 970 966 case -EREMOTE: 971 967 /* DFS link, no metadata available on this server */
+6 -6
fs/cifs/smb2inode.c
··· 506 506 int 507 507 smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, 508 508 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) 510 510 { 511 511 int rc; 512 512 struct smb2_file_all_info *smb2_data; ··· 516 516 struct cached_fid *cfid = NULL; 517 517 518 518 *adjust_tz = false; 519 - *symlink = false; 519 + *reparse = false; 520 520 521 521 smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + PATH_MAX * 2, 522 522 GFP_KERNEL); ··· 548 548 FILE_READ_ATTRIBUTES, FILE_OPEN, create_options, 549 549 ACL_NO_MODE, smb2_data, SMB2_OP_QUERY_INFO, cfile); 550 550 if (rc == -EOPNOTSUPP) { 551 - *symlink = true; 551 + *reparse = true; 552 552 create_options |= OPEN_REPARSE_POINT; 553 553 554 554 /* Failed on a symbolic link - query a reparse point info */ ··· 570 570 int 571 571 smb311_posix_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, 572 572 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) 574 574 { 575 575 int rc; 576 576 __u32 create_options = 0; ··· 578 578 struct smb311_posix_qinfo *smb2_data; 579 579 580 580 *adjust_tz = false; 581 - *symlink = false; 581 + *reparse = false; 582 582 583 583 /* BB TODO: Make struct larger when add support for parsing owner SIDs */ 584 584 smb2_data = kzalloc(sizeof(struct smb311_posix_qinfo), ··· 599 599 ACL_NO_MODE, smb2_data, SMB2_OP_POSIX_QUERY_INFO, cfile); 600 600 if (rc == -EOPNOTSUPP) { 601 601 /* BB TODO: When support for special files added to Samba re-verify this path */ 602 - *symlink = true; 602 + *reparse = true; 603 603 create_options |= OPEN_REPARSE_POINT; 604 604 605 605 /* Failed on a symbolic link - query a reparse point info */
+130
fs/cifs/smb2ops.c
··· 3034 3034 return rc; 3035 3035 } 3036 3036 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 + 3037 3164 static struct cifs_ntsd * 3038 3165 get_smb2_acl_by_fid(struct cifs_sb_info *cifs_sb, 3039 3166 const struct cifs_fid *cifsfid, u32 *pacllen) ··· 5113 4986 .can_echo = smb2_can_echo, 5114 4987 .echo = SMB2_echo, 5115 4988 .query_path_info = smb2_query_path_info, 4989 + /* WSL tags introduced long after smb2.1, enable for SMB3, 3.11 only */ 4990 + .query_reparse_tag = smb2_query_reparse_tag, 5116 4991 .get_srv_inum = smb2_get_srv_inum, 5117 4992 .query_file_info = smb2_query_file_info, 5118 4993 .set_path_size = smb2_set_path_size, ··· 5226 5097 .can_echo = smb2_can_echo, 5227 5098 .echo = SMB2_echo, 5228 5099 .query_path_info = smb2_query_path_info, 5100 + .query_reparse_tag = smb2_query_reparse_tag, 5229 5101 .get_srv_inum = smb2_get_srv_inum, 5230 5102 .query_file_info = smb2_query_file_info, 5231 5103 .set_path_size = smb2_set_path_size,
+31
fs/cifs/smb2pdu.h
··· 999 999 __le32 TotalBytesWritten; 1000 1000 } __packed; 1001 1001 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 + 1002 1027 struct fsctl_set_integrity_information_req { 1003 1028 __le16 ChecksumAlgorithm; 1004 1029 __le16 Reserved; ··· 1665 1640 __u64 RootDirectory; /* MBZ for network operations (why says spec?) */ 1666 1641 __le32 FileNameLength; 1667 1642 char FileName[]; /* New name to be assigned */ 1643 + /* padding - overall struct size must be >= 24 so filename + pad >= 6 */ 1668 1644 } __packed; /* level 10 Set */ 1669 1645 1670 1646 struct smb2_file_link_info { /* encoding of request for level 11 */ ··· 1716 1690 struct smb2_file_eof_info { /* encoding of request for level 10 */ 1717 1691 __le64 EndOfFile; /* new end of file value */ 1718 1692 } __packed; /* level 20 Set */ 1693 + 1694 + struct smb2_file_reparse_point_info { 1695 + __le64 IndexNumber; 1696 + __le32 Tag; 1697 + } __packed; 1719 1698 1720 1699 struct smb2_file_network_open_info { 1721 1700 __le64 CreationTime;
+3
fs/cifs/smb2proto.h
··· 77 77 extern void close_shroot_lease_locked(struct cached_fid *cfid); 78 78 extern void move_smb2_info_to_cifs(FILE_ALL_INFO *dst, 79 79 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); 80 83 extern int smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, 81 84 struct cifs_sb_info *cifs_sb, 82 85 const char *full_path, FILE_ALL_INFO *data,
+2
fs/cifs/smbfsctl.h
··· 103 103 #define FSCTL_SET_ZERO_ON_DEALLOC 0x00090194 /* BB add struct */ 104 104 #define FSCTL_SET_SHORT_NAME_BEHAVIOR 0x000901B4 /* BB add struct */ 105 105 #define FSCTL_GET_INTEGRITY_INFORMATION 0x0009027C 106 + #define FSCTL_GET_RETRIEVAL_POINTERS_AND_REFCOUNT 0x000903d3 107 + #define FSCTL_GET_RETRIEVAL_POINTER_COUNT 0x0009042b 106 108 #define FSCTL_QUERY_ALLOCATED_RANGES 0x000940CF 107 109 #define FSCTL_SET_DEFECT_MANAGEMENT 0x00098134 /* BB add struct */ 108 110 #define FSCTL_FILE_LEVEL_TRIM 0x00098208 /* BB add struct */