Skip to content

Commit adeb964

Browse files
TTalpeysmfrench
authored andcommitted
Handle variable number of SGEs in client smbdirect send.
If/when an outgoing request contains more scatter/gather segments than can be mapped in a single RDMA send work request, use smbdirect fragments to send it in multiple packets. Acked-by: Paulo Alcantara (SUSE) <[email protected]> Signed-off-by: Tom Talpey <[email protected]> Signed-off-by: Steve French <[email protected]>
1 parent 3c62df5 commit adeb964

File tree

1 file changed

+77
-108
lines changed

1 file changed

+77
-108
lines changed

fs/cifs/smbdirect.c

Lines changed: 77 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -1984,10 +1984,11 @@ int smbd_send(struct TCP_Server_Info *server,
19841984
int num_rqst, struct smb_rqst *rqst_array)
19851985
{
19861986
struct smbd_connection *info = server->smbd_conn;
1987-
struct kvec vec;
1987+
struct kvec vecs[SMBDIRECT_MAX_SEND_SGE - 1];
19881988
int nvecs;
19891989
int size;
19901990
unsigned int buflen, remaining_data_length;
1991+
unsigned int offset, remaining_vec_data_length;
19911992
int start, i, j;
19921993
int max_iov_size =
19931994
info->max_send_size - sizeof(struct smbd_data_transfer);
@@ -1996,10 +1997,8 @@ int smbd_send(struct TCP_Server_Info *server,
19961997
struct smb_rqst *rqst;
19971998
int rqst_idx;
19981999

1999-
if (info->transport_status != SMBD_CONNECTED) {
2000-
rc = -EAGAIN;
2001-
goto done;
2002-
}
2000+
if (info->transport_status != SMBD_CONNECTED)
2001+
return -EAGAIN;
20032002

20042003
/*
20052004
* 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,
20102009
for (i = 0; i < num_rqst; i++)
20112010
remaining_data_length += smb_rqst_len(server, &rqst_array[i]);
20122011

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 */
20142014
log_write(ERR, "payload size %d > max size %d\n",
20152015
remaining_data_length, info->max_fragmented_send_size);
2016-
rc = -EINVAL;
2017-
goto done;
2016+
return -EINVAL;
20182017
}
20192018

20202019
log_write(INFO, "num_rqst=%d total length=%u\n",
20212020
num_rqst, remaining_data_length);
20222021

20232022
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;
20792062
}
2080-
i++;
2081-
if (i == rqst->rq_nvec)
2082-
break;
2063+
++j;
20832064
}
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+
20842074
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,
20932091
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);
20962096
if (rc)
20972097
goto done;
2098-
break;
20992098
}
21002099
}
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);
21322101

21332102
done:
21342103
/*

0 commit comments

Comments
 (0)