@@ -176,27 +176,27 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
176
176
struct kvec * out_iov , int * out_buftype , struct dentry * dentry )
177
177
{
178
178
179
- struct reparse_data_buffer * rbuf ;
179
+ struct smb2_query_info_rsp * qi_rsp = NULL ;
180
180
struct smb2_compound_vars * vars = NULL ;
181
- struct kvec * rsp_iov , * iov ;
182
- struct smb_rqst * rqst ;
183
- int rc ;
184
- __le16 * utf16_path = NULL ;
185
181
__u8 oplock = SMB2_OPLOCK_LEVEL_NONE ;
186
- struct cifs_fid fid ;
182
+ struct cifs_open_info_data * idata ;
187
183
struct cifs_ses * ses = tcon -> ses ;
184
+ struct reparse_data_buffer * rbuf ;
188
185
struct TCP_Server_Info * server ;
189
- int num_rqst = 0 , i ;
190
186
int resp_buftype [MAX_COMPOUND ];
191
- struct smb2_query_info_rsp * qi_rsp = NULL ;
192
- struct cifs_open_info_data * idata ;
187
+ int retries = 0 , cur_sleep = 1 ;
188
+ __u8 delete_pending [8 ] = {1 ,};
189
+ struct kvec * rsp_iov , * iov ;
193
190
struct inode * inode = NULL ;
194
- int flags = 0 ;
195
- __u8 delete_pending [ 8 ] = { 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } ;
191
+ __le16 * utf16_path = NULL ;
192
+ struct smb_rqst * rqst ;
196
193
unsigned int size [2 ];
197
- void * data [2 ];
194
+ struct cifs_fid fid ;
195
+ int num_rqst = 0 , i ;
198
196
unsigned int len ;
199
- int retries = 0 , cur_sleep = 1 ;
197
+ int tmp_rc , rc ;
198
+ int flags = 0 ;
199
+ void * data [2 ];
200
200
201
201
replay_again :
202
202
/* reinitialize for possible replay */
@@ -639,7 +639,14 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
639
639
tcon -> need_reconnect = true;
640
640
}
641
641
642
+ tmp_rc = rc ;
642
643
for (i = 0 ; i < num_cmds ; i ++ ) {
644
+ char * buf = rsp_iov [i + i ].iov_base ;
645
+
646
+ if (buf && resp_buftype [i + 1 ] != CIFS_NO_BUFFER )
647
+ rc = server -> ops -> map_error (buf , false);
648
+ else
649
+ rc = tmp_rc ;
643
650
switch (cmds [i ]) {
644
651
case SMB2_OP_QUERY_INFO :
645
652
idata = in_iov [i ].iov_base ;
@@ -805,6 +812,7 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
805
812
}
806
813
}
807
814
SMB2_close_free (& rqst [num_rqst ]);
815
+ rc = tmp_rc ;
808
816
809
817
num_cmds += 2 ;
810
818
if (out_iov && out_buftype ) {
@@ -860,22 +868,52 @@ static int parse_create_response(struct cifs_open_info_data *data,
860
868
return rc ;
861
869
}
862
870
871
+ /* Check only if SMB2_OP_QUERY_WSL_EA command failed in the compound chain */
872
+ static bool ea_unsupported (int * cmds , int num_cmds ,
873
+ struct kvec * out_iov , int * out_buftype )
874
+ {
875
+ int i ;
876
+
877
+ if (cmds [num_cmds - 1 ] != SMB2_OP_QUERY_WSL_EA )
878
+ return false;
879
+
880
+ for (i = 1 ; i < num_cmds - 1 ; i ++ ) {
881
+ struct smb2_hdr * hdr = out_iov [i ].iov_base ;
882
+
883
+ if (out_buftype [i ] == CIFS_NO_BUFFER || !hdr ||
884
+ hdr -> Status != STATUS_SUCCESS )
885
+ return false;
886
+ }
887
+ return true;
888
+ }
889
+
890
+ static inline void free_rsp_iov (struct kvec * iovs , int * buftype , int count )
891
+ {
892
+ int i ;
893
+
894
+ for (i = 0 ; i < count ; i ++ ) {
895
+ free_rsp_buf (buftype [i ], iovs [i ].iov_base );
896
+ memset (& iovs [i ], 0 , sizeof (* iovs ));
897
+ buftype [i ] = CIFS_NO_BUFFER ;
898
+ }
899
+ }
900
+
863
901
int smb2_query_path_info (const unsigned int xid ,
864
902
struct cifs_tcon * tcon ,
865
903
struct cifs_sb_info * cifs_sb ,
866
904
const char * full_path ,
867
905
struct cifs_open_info_data * data )
868
906
{
907
+ struct kvec in_iov [3 ], out_iov [5 ] = {};
908
+ struct cached_fid * cfid = NULL ;
869
909
struct cifs_open_parms oparms ;
870
- __u32 create_options = 0 ;
871
910
struct cifsFileInfo * cfile ;
872
- struct cached_fid * cfid = NULL ;
911
+ __u32 create_options = 0 ;
912
+ int out_buftype [5 ] = {};
873
913
struct smb2_hdr * hdr ;
874
- struct kvec in_iov [3 ], out_iov [3 ] = {};
875
- int out_buftype [3 ] = {};
914
+ int num_cmds = 0 ;
876
915
int cmds [3 ];
877
916
bool islink ;
878
- int i , num_cmds = 0 ;
879
917
int rc , rc2 ;
880
918
881
919
data -> adjust_tz = false;
@@ -945,24 +983,33 @@ int smb2_query_path_info(const unsigned int xid,
945
983
if (rc || !data -> reparse_point )
946
984
goto out ;
947
985
948
- if (!tcon -> posix_extensions )
949
- cmds [num_cmds ++ ] = SMB2_OP_QUERY_WSL_EA ;
950
986
/*
951
987
* Skip SMB2_OP_GET_REPARSE if symlink already parsed in create
952
988
* response.
953
989
*/
954
990
if (data -> reparse .tag != IO_REPARSE_TAG_SYMLINK )
955
991
cmds [num_cmds ++ ] = SMB2_OP_GET_REPARSE ;
992
+ if (!tcon -> posix_extensions )
993
+ cmds [num_cmds ++ ] = SMB2_OP_QUERY_WSL_EA ;
956
994
957
995
oparms = CIFS_OPARMS (cifs_sb , tcon , full_path ,
958
996
FILE_READ_ATTRIBUTES |
959
997
FILE_READ_EA | SYNCHRONIZE ,
960
998
FILE_OPEN , create_options |
961
999
OPEN_REPARSE_POINT , ACL_NO_MODE );
962
1000
cifs_get_readable_path (tcon , full_path , & cfile );
1001
+ free_rsp_iov (out_iov , out_buftype , ARRAY_SIZE (out_iov ));
963
1002
rc = smb2_compound_op (xid , tcon , cifs_sb , full_path ,
964
1003
& oparms , in_iov , cmds , num_cmds ,
965
- cfile , NULL , NULL , NULL );
1004
+ cfile , out_iov , out_buftype , NULL );
1005
+ if (rc && ea_unsupported (cmds , num_cmds ,
1006
+ out_iov , out_buftype )) {
1007
+ if (data -> reparse .tag != IO_REPARSE_TAG_LX_BLK &&
1008
+ data -> reparse .tag != IO_REPARSE_TAG_LX_CHR )
1009
+ rc = 0 ;
1010
+ else
1011
+ rc = - EOPNOTSUPP ;
1012
+ }
966
1013
break ;
967
1014
case - EREMOTE :
968
1015
break ;
@@ -980,8 +1027,7 @@ int smb2_query_path_info(const unsigned int xid,
980
1027
}
981
1028
982
1029
out :
983
- for (i = 0 ; i < ARRAY_SIZE (out_buftype ); i ++ )
984
- free_rsp_buf (out_buftype [i ], out_iov [i ].iov_base );
1030
+ free_rsp_iov (out_iov , out_buftype , ARRAY_SIZE (out_iov ));
985
1031
return rc ;
986
1032
}
987
1033
0 commit comments