@@ -958,21 +958,19 @@ CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
958958 return rc ;
959959}
960960
961- /* If no buffer passed in, then caller wants to do the copy
962- as in the case of readpages so the SMB buffer must be
963- freed by the caller */
964-
965961int
966962CIFSSMBRead (const int xid , struct cifsTconInfo * tcon ,
967- const int netfid , const unsigned int count ,
968- const __u64 lseek , unsigned int * nbytes , char * * buf )
963+ const int netfid , const unsigned int count ,
964+ const __u64 lseek , unsigned int * nbytes , char * * buf ,
965+ int * pbuf_type )
969966{
970967 int rc = - EACCES ;
971968 READ_REQ * pSMB = NULL ;
972969 READ_RSP * pSMBr = NULL ;
973970 char * pReadData = NULL ;
974- int bytes_returned ;
975971 int wct ;
972+ int resp_buf_type = 0 ;
973+ struct kvec iov [1 ];
976974
977975 cFYI (1 ,("Reading %d bytes on fid %d" ,count ,netfid ));
978976 if (tcon -> ses -> capabilities & CAP_LARGE_FILES )
@@ -981,22 +979,21 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
981979 wct = 10 ; /* old style read */
982980
983981 * nbytes = 0 ;
984- rc = smb_init (SMB_COM_READ_ANDX , wct , tcon , (void * * ) & pSMB ,
985- (void * * ) & pSMBr );
982+ rc = small_smb_init (SMB_COM_READ_ANDX , wct , tcon , (void * * ) & pSMB );
986983 if (rc )
987984 return rc ;
988985
989986 /* tcon and ses pointer are checked in smb_init */
990987 if (tcon -> ses -> server == NULL )
991988 return - ECONNABORTED ;
992989
993- pSMB -> AndXCommand = 0xFF ; /* none */
990+ pSMB -> AndXCommand = 0xFF ; /* none */
994991 pSMB -> Fid = netfid ;
995992 pSMB -> OffsetLow = cpu_to_le32 (lseek & 0xFFFFFFFF );
996993 if (wct == 12 )
997994 pSMB -> OffsetHigh = cpu_to_le32 (lseek >> 32 );
998- else if ((lseek >> 32 ) > 0 ) /* can not handle this big offset for old */
999- return - EIO ;
995+ else if ((lseek >> 32 ) > 0 ) /* can not handle this big offset for old */
996+ return - EIO ;
1000997
1001998 pSMB -> Remaining = 0 ;
1002999 pSMB -> MaxCount = cpu_to_le16 (count & 0xFFFF );
@@ -1005,14 +1002,18 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
10051002 pSMB -> ByteCount = 0 ; /* no need to do le conversion since 0 */
10061003 else {
10071004 /* old style read */
1008- struct smb_com_readx_req * pSMBW =
1005+ struct smb_com_readx_req * pSMBW =
10091006 (struct smb_com_readx_req * )pSMB ;
1010- pSMBW -> ByteCount = 0 ;
1007+ pSMBW -> ByteCount = 0 ;
10111008 }
1012-
1013- rc = SendReceive (xid , tcon -> ses , (struct smb_hdr * ) pSMB ,
1014- (struct smb_hdr * ) pSMBr , & bytes_returned , 0 );
1009+
1010+ iov [0 ].iov_base = (char * )pSMB ;
1011+ iov [0 ].iov_len = pSMB -> hdr .smb_buf_length + 4 ;
1012+ rc = SendReceive2 (xid , tcon -> ses , iov ,
1013+ 1 /* num iovecs */ ,
1014+ & resp_buf_type , 0 );
10151015 cifs_stats_inc (& tcon -> num_reads );
1016+ pSMBr = (READ_RSP * )iov [0 ].iov_base ;
10161017 if (rc ) {
10171018 cERROR (1 , ("Send error in read = %d" , rc ));
10181019 } else {
@@ -1022,33 +1023,43 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
10221023 * nbytes = data_length ;
10231024
10241025 /*check that DataLength would not go beyond end of SMB */
1025- if ((data_length > CIFSMaxBufSize )
1026+ if ((data_length > CIFSMaxBufSize )
10261027 || (data_length > count )) {
10271028 cFYI (1 ,("bad length %d for count %d" ,data_length ,count ));
10281029 rc = - EIO ;
10291030 * nbytes = 0 ;
10301031 } else {
1031- pReadData =
1032- (char * ) (& pSMBr -> hdr .Protocol ) +
1032+ pReadData = (char * ) (& pSMBr -> hdr .Protocol ) +
10331033 le16_to_cpu (pSMBr -> DataOffset );
1034- /* if(rc = copy_to_user(buf, pReadData, data_length)) {
1035- cERROR(1,("Faulting on read rc = %d",rc));
1036- rc = -EFAULT;
1037- }*/ /* can not use copy_to_user when using page cache*/
1034+ /* if(rc = copy_to_user(buf, pReadData, data_length)) {
1035+ cERROR(1,("Faulting on read rc = %d",rc));
1036+ rc = -EFAULT;
1037+ }*/ /* can not use copy_to_user when using page cache*/
10381038 if (* buf )
1039- memcpy (* buf ,pReadData ,data_length );
1039+ memcpy (* buf ,pReadData ,data_length );
10401040 }
10411041 }
1042- if (* buf )
1043- cifs_buf_release (pSMB );
1044- else
1045- * buf = (char * )pSMB ;
10461042
1047- /* Note: On -EAGAIN error only caller can retry on handle based calls
1043+ cifs_small_buf_release (pSMB );
1044+ if (* buf ) {
1045+ if (resp_buf_type == CIFS_SMALL_BUFFER )
1046+ cifs_small_buf_release (iov [0 ].iov_base );
1047+ else if (resp_buf_type == CIFS_LARGE_BUFFER )
1048+ cifs_buf_release (iov [0 ].iov_base );
1049+ } else /* return buffer to caller to free */ /* BB FIXME how do we tell caller if it is not a large buffer */ {
1050+ * buf = iov [0 ].iov_base ;
1051+ if (resp_buf_type == CIFS_SMALL_BUFFER )
1052+ * pbuf_type = CIFS_SMALL_BUFFER ;
1053+ else if (resp_buf_type == CIFS_LARGE_BUFFER )
1054+ * pbuf_type = CIFS_LARGE_BUFFER ;
1055+ }
1056+
1057+ /* Note: On -EAGAIN error only caller can retry on handle based calls
10481058 since file handle passed in no longer valid */
10491059 return rc ;
10501060}
10511061
1062+
10521063int
10531064CIFSSMBWrite (const int xid , struct cifsTconInfo * tcon ,
10541065 const int netfid , const unsigned int count ,
@@ -1163,10 +1174,10 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
11631174{
11641175 int rc = - EACCES ;
11651176 WRITE_REQ * pSMB = NULL ;
1166- int bytes_returned , wct ;
1177+ int wct ;
11671178 int smb_hdr_len ;
1179+ int resp_buf_type = 0 ;
11681180
1169- /* BB removeme BB */
11701181 cFYI (1 ,("write2 at %lld %d bytes" , (long long )offset , count ));
11711182
11721183 if (tcon -> ses -> capabilities & CAP_LARGE_FILES )
@@ -1209,22 +1220,34 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
12091220 pSMBW -> ByteCount = cpu_to_le16 (count + 5 );
12101221 }
12111222 iov [0 ].iov_base = pSMB ;
1212- iov [0 ].iov_len = smb_hdr_len + 4 ;
1223+ if (wct == 14 )
1224+ iov [0 ].iov_len = smb_hdr_len + 4 ;
1225+ else /* wct == 12 pad bigger by four bytes */
1226+ iov [0 ].iov_len = smb_hdr_len + 8 ;
1227+
12131228
1214- rc = SendReceive2 (xid , tcon -> ses , iov , n_vec + 1 , & bytes_returned ,
1229+ rc = SendReceive2 (xid , tcon -> ses , iov , n_vec + 1 , & resp_buf_type ,
12151230 long_op );
12161231 cifs_stats_inc (& tcon -> num_writes );
12171232 if (rc ) {
12181233 cFYI (1 , ("Send error Write2 = %d" , rc ));
12191234 * nbytes = 0 ;
1235+ } else if (resp_buf_type == 0 ) {
1236+ /* presumably this can not happen, but best to be safe */
1237+ rc = - EIO ;
1238+ * nbytes = 0 ;
12201239 } else {
1221- WRITE_RSP * pSMBr = (WRITE_RSP * )pSMB ;
1240+ WRITE_RSP * pSMBr = (WRITE_RSP * )iov [ 0 ]. iov_base ;
12221241 * nbytes = le16_to_cpu (pSMBr -> CountHigh );
12231242 * nbytes = (* nbytes ) << 16 ;
12241243 * nbytes += le16_to_cpu (pSMBr -> Count );
12251244 }
12261245
12271246 cifs_small_buf_release (pSMB );
1247+ if (resp_buf_type == CIFS_SMALL_BUFFER )
1248+ cifs_small_buf_release (iov [0 ].iov_base );
1249+ else if (resp_buf_type == CIFS_LARGE_BUFFER )
1250+ cifs_buf_release (iov [0 ].iov_base );
12281251
12291252 /* Note: On -EAGAIN error only caller can retry on handle based calls
12301253 since file handle passed in no longer valid */
0 commit comments