@@ -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 */
@@ -637,7 +637,14 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
637
637
tcon -> need_reconnect = true;
638
638
}
639
639
640
+ tmp_rc = rc ;
640
641
for (i = 0 ; i < num_cmds ; i ++ ) {
642
+ char * buf = rsp_iov [i + i ].iov_base ;
643
+
644
+ if (buf && resp_buftype [i + 1 ] != CIFS_NO_BUFFER )
645
+ rc = server -> ops -> map_error (buf , false);
646
+ else
647
+ rc = tmp_rc ;
641
648
switch (cmds [i ]) {
642
649
case SMB2_OP_QUERY_INFO :
643
650
idata = in_iov [i ].iov_base ;
@@ -803,6 +810,7 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
803
810
}
804
811
}
805
812
SMB2_close_free (& rqst [num_rqst ]);
813
+ rc = tmp_rc ;
806
814
807
815
num_cmds += 2 ;
808
816
if (out_iov && out_buftype ) {
@@ -858,22 +866,52 @@ static int parse_create_response(struct cifs_open_info_data *data,
858
866
return rc ;
859
867
}
860
868
869
+ /* Check only if SMB2_OP_QUERY_WSL_EA command failed in the compound chain */
870
+ static bool ea_unsupported (int * cmds , int num_cmds ,
871
+ struct kvec * out_iov , int * out_buftype )
872
+ {
873
+ int i ;
874
+
875
+ if (cmds [num_cmds - 1 ] != SMB2_OP_QUERY_WSL_EA )
876
+ return false;
877
+
878
+ for (i = 1 ; i < num_cmds - 1 ; i ++ ) {
879
+ struct smb2_hdr * hdr = out_iov [i ].iov_base ;
880
+
881
+ if (out_buftype [i ] == CIFS_NO_BUFFER || !hdr ||
882
+ hdr -> Status != STATUS_SUCCESS )
883
+ return false;
884
+ }
885
+ return true;
886
+ }
887
+
888
+ static inline void free_rsp_iov (struct kvec * iovs , int * buftype , int count )
889
+ {
890
+ int i ;
891
+
892
+ for (i = 0 ; i < count ; i ++ ) {
893
+ free_rsp_buf (buftype [i ], iovs [i ].iov_base );
894
+ memset (& iovs [i ], 0 , sizeof (* iovs ));
895
+ buftype [i ] = CIFS_NO_BUFFER ;
896
+ }
897
+ }
898
+
861
899
int smb2_query_path_info (const unsigned int xid ,
862
900
struct cifs_tcon * tcon ,
863
901
struct cifs_sb_info * cifs_sb ,
864
902
const char * full_path ,
865
903
struct cifs_open_info_data * data )
866
904
{
905
+ struct kvec in_iov [3 ], out_iov [5 ] = {};
906
+ struct cached_fid * cfid = NULL ;
867
907
struct cifs_open_parms oparms ;
868
- __u32 create_options = 0 ;
869
908
struct cifsFileInfo * cfile ;
870
- struct cached_fid * cfid = NULL ;
909
+ __u32 create_options = 0 ;
910
+ int out_buftype [5 ] = {};
871
911
struct smb2_hdr * hdr ;
872
- struct kvec in_iov [3 ], out_iov [3 ] = {};
873
- int out_buftype [3 ] = {};
912
+ int num_cmds = 0 ;
874
913
int cmds [3 ];
875
914
bool islink ;
876
- int i , num_cmds = 0 ;
877
915
int rc , rc2 ;
878
916
879
917
data -> adjust_tz = false;
@@ -943,24 +981,33 @@ int smb2_query_path_info(const unsigned int xid,
943
981
if (rc || !data -> reparse_point )
944
982
goto out ;
945
983
946
- if (!tcon -> posix_extensions )
947
- cmds [num_cmds ++ ] = SMB2_OP_QUERY_WSL_EA ;
948
984
/*
949
985
* Skip SMB2_OP_GET_REPARSE if symlink already parsed in create
950
986
* response.
951
987
*/
952
988
if (data -> reparse .tag != IO_REPARSE_TAG_SYMLINK )
953
989
cmds [num_cmds ++ ] = SMB2_OP_GET_REPARSE ;
990
+ if (!tcon -> posix_extensions )
991
+ cmds [num_cmds ++ ] = SMB2_OP_QUERY_WSL_EA ;
954
992
955
993
oparms = CIFS_OPARMS (cifs_sb , tcon , full_path ,
956
994
FILE_READ_ATTRIBUTES |
957
995
FILE_READ_EA | SYNCHRONIZE ,
958
996
FILE_OPEN , create_options |
959
997
OPEN_REPARSE_POINT , ACL_NO_MODE );
960
998
cifs_get_readable_path (tcon , full_path , & cfile );
999
+ free_rsp_iov (out_iov , out_buftype , ARRAY_SIZE (out_iov ));
961
1000
rc = smb2_compound_op (xid , tcon , cifs_sb , full_path ,
962
1001
& oparms , in_iov , cmds , num_cmds ,
963
- cfile , NULL , NULL , NULL );
1002
+ cfile , out_iov , out_buftype , NULL );
1003
+ if (rc && ea_unsupported (cmds , num_cmds ,
1004
+ out_iov , out_buftype )) {
1005
+ if (data -> reparse .tag != IO_REPARSE_TAG_LX_BLK &&
1006
+ data -> reparse .tag != IO_REPARSE_TAG_LX_CHR )
1007
+ rc = 0 ;
1008
+ else
1009
+ rc = - EOPNOTSUPP ;
1010
+ }
964
1011
break ;
965
1012
case - EREMOTE :
966
1013
break ;
@@ -978,8 +1025,7 @@ int smb2_query_path_info(const unsigned int xid,
978
1025
}
979
1026
980
1027
out :
981
- for (i = 0 ; i < ARRAY_SIZE (out_buftype ); i ++ )
982
- free_rsp_buf (out_buftype [i ], out_iov [i ].iov_base );
1028
+ free_rsp_iov (out_iov , out_buftype , ARRAY_SIZE (out_iov ));
983
1029
return rc ;
984
1030
}
985
1031
0 commit comments