@@ -1984,10 +1984,11 @@ int smbd_send(struct TCP_Server_Info *server,
1984
1984
int num_rqst , struct smb_rqst * rqst_array )
1985
1985
{
1986
1986
struct smbd_connection * info = server -> smbd_conn ;
1987
- struct kvec vec ;
1987
+ struct kvec vecs [ SMBDIRECT_MAX_SEND_SGE - 1 ] ;
1988
1988
int nvecs ;
1989
1989
int size ;
1990
1990
unsigned int buflen , remaining_data_length ;
1991
+ unsigned int offset , remaining_vec_data_length ;
1991
1992
int start , i , j ;
1992
1993
int max_iov_size =
1993
1994
info -> max_send_size - sizeof (struct smbd_data_transfer );
@@ -1996,10 +1997,8 @@ int smbd_send(struct TCP_Server_Info *server,
1996
1997
struct smb_rqst * rqst ;
1997
1998
int rqst_idx ;
1998
1999
1999
- if (info -> transport_status != SMBD_CONNECTED ) {
2000
- rc = - EAGAIN ;
2001
- goto done ;
2002
- }
2000
+ if (info -> transport_status != SMBD_CONNECTED )
2001
+ return - EAGAIN ;
2003
2002
2004
2003
/*
2005
2004
* Add in the page array if there is one. The caller needs to set
@@ -2010,125 +2009,95 @@ int smbd_send(struct TCP_Server_Info *server,
2010
2009
for (i = 0 ; i < num_rqst ; i ++ )
2011
2010
remaining_data_length += smb_rqst_len (server , & rqst_array [i ]);
2012
2011
2013
- if (remaining_data_length > info -> max_fragmented_send_size ) {
2012
+ if (unlikely (remaining_data_length > info -> max_fragmented_send_size )) {
2013
+ /* assertion: payload never exceeds negotiated maximum */
2014
2014
log_write (ERR , "payload size %d > max size %d\n" ,
2015
2015
remaining_data_length , info -> max_fragmented_send_size );
2016
- rc = - EINVAL ;
2017
- goto done ;
2016
+ return - EINVAL ;
2018
2017
}
2019
2018
2020
2019
log_write (INFO , "num_rqst=%d total length=%u\n" ,
2021
2020
num_rqst , remaining_data_length );
2022
2021
2023
2022
rqst_idx = 0 ;
2024
- next_rqst :
2025
- rqst = & rqst_array [rqst_idx ];
2026
- iov = rqst -> rq_iov ;
2027
-
2028
- cifs_dbg (FYI , "Sending smb (RDMA): idx=%d smb_len=%lu\n" ,
2029
- rqst_idx , smb_rqst_len (server , rqst ));
2030
- for (i = 0 ; i < rqst -> rq_nvec ; i ++ )
2031
- dump_smb (iov [i ].iov_base , iov [i ].iov_len );
2032
-
2033
-
2034
- log_write (INFO , "rqst_idx=%d nvec=%d rqst->rq_npages=%d rq_pagesz=%d rq_tailsz=%d buflen=%lu\n" ,
2035
- rqst_idx , rqst -> rq_nvec , rqst -> rq_npages , rqst -> rq_pagesz ,
2036
- rqst -> rq_tailsz , smb_rqst_len (server , rqst ));
2037
-
2038
- start = i = 0 ;
2039
- buflen = 0 ;
2040
- while (true) {
2041
- buflen += iov [i ].iov_len ;
2042
- if (buflen > max_iov_size ) {
2043
- if (i > start ) {
2044
- remaining_data_length -=
2045
- (buflen - iov [i ].iov_len );
2046
- log_write (INFO , "sending iov[] from start=%d i=%d nvecs=%d remaining_data_length=%d\n" ,
2047
- start , i , i - start ,
2048
- remaining_data_length );
2049
- rc = smbd_post_send_data (
2050
- info , & iov [start ], i - start ,
2051
- remaining_data_length );
2052
- if (rc )
2053
- goto done ;
2054
- } else {
2055
- /* iov[start] is too big, break it */
2056
- nvecs = (buflen + max_iov_size - 1 )/max_iov_size ;
2057
- log_write (INFO , "iov[%d] iov_base=%p buflen=%d break to %d vectors\n" ,
2058
- start , iov [start ].iov_base ,
2059
- buflen , nvecs );
2060
- for (j = 0 ; j < nvecs ; j ++ ) {
2061
- vec .iov_base =
2062
- (char * )iov [start ].iov_base +
2063
- j * max_iov_size ;
2064
- vec .iov_len = max_iov_size ;
2065
- if (j == nvecs - 1 )
2066
- vec .iov_len =
2067
- buflen -
2068
- max_iov_size * (nvecs - 1 );
2069
- remaining_data_length -= vec .iov_len ;
2070
- log_write (INFO ,
2071
- "sending vec j=%d iov_base=%p iov_len=%zu remaining_data_length=%d\n" ,
2072
- j , vec .iov_base , vec .iov_len ,
2073
- remaining_data_length );
2074
- rc = smbd_post_send_data (
2075
- info , & vec , 1 ,
2076
- remaining_data_length );
2077
- if (rc )
2078
- goto done ;
2023
+ do {
2024
+ rqst = & rqst_array [rqst_idx ];
2025
+ iov = rqst -> rq_iov ;
2026
+
2027
+ cifs_dbg (FYI , "Sending smb (RDMA): idx=%d smb_len=%lu\n" ,
2028
+ rqst_idx , smb_rqst_len (server , rqst ));
2029
+ remaining_vec_data_length = 0 ;
2030
+ for (i = 0 ; i < rqst -> rq_nvec ; i ++ ) {
2031
+ remaining_vec_data_length += iov [i ].iov_len ;
2032
+ dump_smb (iov [i ].iov_base , iov [i ].iov_len );
2033
+ }
2034
+
2035
+ log_write (INFO , "rqst_idx=%d nvec=%d rqst->rq_npages=%d rq_pagesz=%d rq_tailsz=%d buflen=%lu\n" ,
2036
+ rqst_idx , rqst -> rq_nvec ,
2037
+ rqst -> rq_npages , rqst -> rq_pagesz ,
2038
+ rqst -> rq_tailsz , smb_rqst_len (server , rqst ));
2039
+
2040
+ start = 0 ;
2041
+ offset = 0 ;
2042
+ do {
2043
+ buflen = 0 ;
2044
+ i = start ;
2045
+ j = 0 ;
2046
+ while (i < rqst -> rq_nvec &&
2047
+ j < SMBDIRECT_MAX_SEND_SGE - 1 &&
2048
+ buflen < max_iov_size ) {
2049
+
2050
+ vecs [j ].iov_base = iov [i ].iov_base + offset ;
2051
+ if (buflen + iov [i ].iov_len > max_iov_size ) {
2052
+ vecs [j ].iov_len =
2053
+ max_iov_size - iov [i ].iov_len ;
2054
+ buflen = max_iov_size ;
2055
+ offset = vecs [j ].iov_len ;
2056
+ } else {
2057
+ vecs [j ].iov_len =
2058
+ iov [i ].iov_len - offset ;
2059
+ buflen += vecs [j ].iov_len ;
2060
+ offset = 0 ;
2061
+ ++ i ;
2079
2062
}
2080
- i ++ ;
2081
- if (i == rqst -> rq_nvec )
2082
- break ;
2063
+ ++ j ;
2083
2064
}
2065
+
2066
+ remaining_vec_data_length -= buflen ;
2067
+ remaining_data_length -= buflen ;
2068
+ log_write (INFO , "sending %s iov[%d] from start=%d nvecs=%d remaining_data_length=%d\n" ,
2069
+ remaining_vec_data_length > 0 ?
2070
+ "partial" : "complete" ,
2071
+ rqst -> rq_nvec , start , j ,
2072
+ remaining_data_length );
2073
+
2084
2074
start = i ;
2085
- buflen = 0 ;
2086
- } else {
2087
- i ++ ;
2088
- if (i == rqst -> rq_nvec ) {
2089
- /* send out all remaining vecs */
2090
- remaining_data_length -= buflen ;
2091
- log_write (INFO , "sending iov[] from start=%d i=%d nvecs=%d remaining_data_length=%d\n" ,
2092
- start , i , i - start ,
2075
+ rc = smbd_post_send_data (info , vecs , j , remaining_data_length );
2076
+ if (rc )
2077
+ goto done ;
2078
+ } while (remaining_vec_data_length > 0 );
2079
+
2080
+ /* now sending pages if there are any */
2081
+ for (i = 0 ; i < rqst -> rq_npages ; i ++ ) {
2082
+ rqst_page_get_length (rqst , i , & buflen , & offset );
2083
+ nvecs = (buflen + max_iov_size - 1 ) / max_iov_size ;
2084
+ log_write (INFO , "sending pages buflen=%d nvecs=%d\n" ,
2085
+ buflen , nvecs );
2086
+ for (j = 0 ; j < nvecs ; j ++ ) {
2087
+ size = min_t (unsigned int , max_iov_size , remaining_data_length );
2088
+ remaining_data_length -= size ;
2089
+ log_write (INFO , "sending pages i=%d offset=%d size=%d remaining_data_length=%d\n" ,
2090
+ i , j * max_iov_size + offset , size ,
2093
2091
remaining_data_length );
2094
- rc = smbd_post_send_data (info , & iov [start ],
2095
- i - start , remaining_data_length );
2092
+ rc = smbd_post_send_page (
2093
+ info , rqst -> rq_pages [i ],
2094
+ j * max_iov_size + offset ,
2095
+ size , remaining_data_length );
2096
2096
if (rc )
2097
2097
goto done ;
2098
- break ;
2099
2098
}
2100
2099
}
2101
- log_write (INFO , "looping i=%d buflen=%d\n" , i , buflen );
2102
- }
2103
-
2104
- /* now sending pages if there are any */
2105
- for (i = 0 ; i < rqst -> rq_npages ; i ++ ) {
2106
- unsigned int offset ;
2107
-
2108
- rqst_page_get_length (rqst , i , & buflen , & offset );
2109
- nvecs = (buflen + max_iov_size - 1 ) / max_iov_size ;
2110
- log_write (INFO , "sending pages buflen=%d nvecs=%d\n" ,
2111
- buflen , nvecs );
2112
- for (j = 0 ; j < nvecs ; j ++ ) {
2113
- size = max_iov_size ;
2114
- if (j == nvecs - 1 )
2115
- size = buflen - j * max_iov_size ;
2116
- remaining_data_length -= size ;
2117
- log_write (INFO , "sending pages i=%d offset=%d size=%d remaining_data_length=%d\n" ,
2118
- i , j * max_iov_size + offset , size ,
2119
- remaining_data_length );
2120
- rc = smbd_post_send_page (
2121
- info , rqst -> rq_pages [i ],
2122
- j * max_iov_size + offset ,
2123
- size , remaining_data_length );
2124
- if (rc )
2125
- goto done ;
2126
- }
2127
- }
2128
-
2129
- rqst_idx ++ ;
2130
- if (rqst_idx < num_rqst )
2131
- goto next_rqst ;
2100
+ } while (++ rqst_idx < num_rqst );
2132
2101
2133
2102
done :
2134
2103
/*
0 commit comments