Skip to content

Commit 3d78fe7

Browse files
dhowellsSteve French
authored andcommitted
cifs: Build the RDMA SGE list directly from an iterator
In the depths of the cifs RDMA code, extract part of an iov iterator directly into an SGE list without going through an intermediate scatterlist. Note that this doesn't support extraction from an IOBUF- or UBUF-type iterator (ie. user-supplied buffer). The assumption is that the higher layers will extract those to a BVEC-type iterator first and do whatever is required to stop the pages from going away. Signed-off-by: David Howells <[email protected]> cc: Steve French <[email protected]> cc: Shyam Prasad N <[email protected]> cc: Rohith Surabattula <[email protected]> cc: Tom Talpey <[email protected]> cc: Jeff Layton <[email protected]> cc: [email protected] cc: [email protected] Link: https://lore.kernel.org/r/166697260361.61150.5064013393408112197.stgit@warthog.procyon.org.uk/ # rfc Link: https://lore.kernel.org/r/166732032518.3186319.1859601819981624629.stgit@warthog.procyon.org.uk/ # rfc Signed-off-by: Steve French <[email protected]>
1 parent d08089f commit 3d78fe7

File tree

2 files changed

+63
-93
lines changed

2 files changed

+63
-93
lines changed

fs/cifs/smbdirect.c

Lines changed: 62 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -828,16 +828,16 @@ static int smbd_post_send(struct smbd_connection *info,
828828
return rc;
829829
}
830830

831-
static int smbd_post_send_sgl(struct smbd_connection *info,
832-
struct scatterlist *sgl, int data_length, int remaining_data_length)
831+
static int smbd_post_send_iter(struct smbd_connection *info,
832+
struct iov_iter *iter,
833+
int *_remaining_data_length)
833834
{
834-
int num_sgs;
835835
int i, rc;
836836
int header_length;
837+
int data_length;
837838
struct smbd_request *request;
838839
struct smbd_data_transfer *packet;
839840
int new_credits;
840-
struct scatterlist *sg;
841841

842842
wait_credit:
843843
/* Wait for send credits. A SMBD packet needs one credit */
@@ -881,6 +881,30 @@ static int smbd_post_send_sgl(struct smbd_connection *info,
881881
}
882882

883883
request->info = info;
884+
memset(request->sge, 0, sizeof(request->sge));
885+
886+
/* Fill in the data payload to find out how much data we can add */
887+
if (iter) {
888+
struct smb_extract_to_rdma extract = {
889+
.nr_sge = 1,
890+
.max_sge = SMBDIRECT_MAX_SEND_SGE,
891+
.sge = request->sge,
892+
.device = info->id->device,
893+
.local_dma_lkey = info->pd->local_dma_lkey,
894+
.direction = DMA_TO_DEVICE,
895+
};
896+
897+
rc = smb_extract_iter_to_rdma(iter, *_remaining_data_length,
898+
&extract);
899+
if (rc < 0)
900+
goto err_dma;
901+
data_length = rc;
902+
request->num_sge = extract.nr_sge;
903+
*_remaining_data_length -= data_length;
904+
} else {
905+
data_length = 0;
906+
request->num_sge = 1;
907+
}
884908

885909
/* Fill in the packet header */
886910
packet = smbd_request_payload(request);
@@ -902,7 +926,7 @@ static int smbd_post_send_sgl(struct smbd_connection *info,
902926
else
903927
packet->data_offset = cpu_to_le32(24);
904928
packet->data_length = cpu_to_le32(data_length);
905-
packet->remaining_data_length = cpu_to_le32(remaining_data_length);
929+
packet->remaining_data_length = cpu_to_le32(*_remaining_data_length);
906930
packet->padding = 0;
907931

908932
log_outgoing(INFO, "credits_requested=%d credits_granted=%d data_offset=%d data_length=%d remaining_data_length=%d\n",
@@ -918,7 +942,6 @@ static int smbd_post_send_sgl(struct smbd_connection *info,
918942
if (!data_length)
919943
header_length = offsetof(struct smbd_data_transfer, padding);
920944

921-
request->num_sge = 1;
922945
request->sge[0].addr = ib_dma_map_single(info->id->device,
923946
(void *)packet,
924947
header_length,
@@ -932,23 +955,6 @@ static int smbd_post_send_sgl(struct smbd_connection *info,
932955
request->sge[0].length = header_length;
933956
request->sge[0].lkey = info->pd->local_dma_lkey;
934957

935-
/* Fill in the packet data payload */
936-
num_sgs = sgl ? sg_nents(sgl) : 0;
937-
for_each_sg(sgl, sg, num_sgs, i) {
938-
request->sge[i+1].addr =
939-
ib_dma_map_page(info->id->device, sg_page(sg),
940-
sg->offset, sg->length, DMA_TO_DEVICE);
941-
if (ib_dma_mapping_error(
942-
info->id->device, request->sge[i+1].addr)) {
943-
rc = -EIO;
944-
request->sge[i+1].addr = 0;
945-
goto err_dma;
946-
}
947-
request->sge[i+1].length = sg->length;
948-
request->sge[i+1].lkey = info->pd->local_dma_lkey;
949-
request->num_sge++;
950-
}
951-
952958
rc = smbd_post_send(info, request);
953959
if (!rc)
954960
return 0;
@@ -987,8 +993,10 @@ static int smbd_post_send_sgl(struct smbd_connection *info,
987993
*/
988994
static int smbd_post_send_empty(struct smbd_connection *info)
989995
{
996+
int remaining_data_length = 0;
997+
990998
info->count_send_empty++;
991-
return smbd_post_send_sgl(info, NULL, 0, 0);
999+
return smbd_post_send_iter(info, NULL, &remaining_data_length);
9921000
}
9931001

9941002
/*
@@ -1934,42 +1942,6 @@ int smbd_recv(struct smbd_connection *info, struct msghdr *msg)
19341942
return rc;
19351943
}
19361944

1937-
/*
1938-
* Send the contents of an iterator
1939-
* @iter: The iterator to send
1940-
* @_remaining_data_length: remaining data to send in this payload
1941-
*/
1942-
static int smbd_post_send_iter(struct smbd_connection *info,
1943-
struct iov_iter *iter,
1944-
int *_remaining_data_length)
1945-
{
1946-
struct scatterlist sgl[SMBDIRECT_MAX_SEND_SGE - 1];
1947-
unsigned int max_payload = info->max_send_size - sizeof(struct smbd_data_transfer);
1948-
ssize_t rc;
1949-
1950-
/* We're not expecting a user-backed iter */
1951-
WARN_ON(iov_iter_extract_will_pin(iter));
1952-
1953-
do {
1954-
struct sg_table sgtable = { .sgl = sgl };
1955-
size_t maxlen = min_t(size_t, *_remaining_data_length, max_payload);
1956-
1957-
sg_init_table(sgtable.sgl, ARRAY_SIZE(sgl));
1958-
rc = netfs_extract_iter_to_sg(iter, maxlen,
1959-
&sgtable, ARRAY_SIZE(sgl), 0);
1960-
if (rc < 0)
1961-
break;
1962-
if (WARN_ON_ONCE(sgtable.nents == 0))
1963-
return -EIO;
1964-
1965-
sg_mark_end(&sgl[sgtable.nents - 1]);
1966-
*_remaining_data_length -= rc;
1967-
rc = smbd_post_send_sgl(info, sgl, rc, *_remaining_data_length);
1968-
} while (rc == 0 && iov_iter_count(iter) > 0);
1969-
1970-
return rc;
1971-
}
1972-
19731945
/*
19741946
* Send data to transport
19751947
* Each rqst is transported as a SMBDirect payload
@@ -2130,10 +2102,10 @@ static void destroy_mr_list(struct smbd_connection *info)
21302102
cancel_work_sync(&info->mr_recovery_work);
21312103
list_for_each_entry_safe(mr, tmp, &info->mr_list, list) {
21322104
if (mr->state == MR_INVALIDATED)
2133-
ib_dma_unmap_sg(info->id->device, mr->sgl,
2134-
mr->sgl_count, mr->dir);
2105+
ib_dma_unmap_sg(info->id->device, mr->sgt.sgl,
2106+
mr->sgt.nents, mr->dir);
21352107
ib_dereg_mr(mr->mr);
2136-
kfree(mr->sgl);
2108+
kfree(mr->sgt.sgl);
21372109
kfree(mr);
21382110
}
21392111
}
@@ -2169,11 +2141,10 @@ static int allocate_mr_list(struct smbd_connection *info)
21692141
info->mr_type, info->max_frmr_depth);
21702142
goto out;
21712143
}
2172-
smbdirect_mr->sgl = kcalloc(
2173-
info->max_frmr_depth,
2174-
sizeof(struct scatterlist),
2175-
GFP_KERNEL);
2176-
if (!smbdirect_mr->sgl) {
2144+
smbdirect_mr->sgt.sgl = kcalloc(info->max_frmr_depth,
2145+
sizeof(struct scatterlist),
2146+
GFP_KERNEL);
2147+
if (!smbdirect_mr->sgt.sgl) {
21772148
log_rdma_mr(ERR, "failed to allocate sgl\n");
21782149
ib_dereg_mr(smbdirect_mr->mr);
21792150
goto out;
@@ -2192,7 +2163,7 @@ static int allocate_mr_list(struct smbd_connection *info)
21922163
list_for_each_entry_safe(smbdirect_mr, tmp, &info->mr_list, list) {
21932164
list_del(&smbdirect_mr->list);
21942165
ib_dereg_mr(smbdirect_mr->mr);
2195-
kfree(smbdirect_mr->sgl);
2166+
kfree(smbdirect_mr->sgt.sgl);
21962167
kfree(smbdirect_mr);
21972168
}
21982169
return -ENOMEM;
@@ -2246,22 +2217,20 @@ static struct smbd_mr *get_mr(struct smbd_connection *info)
22462217

22472218
/*
22482219
* Transcribe the pages from an iterator into an MR scatterlist.
2249-
* @iter: The iterator to transcribe
2250-
* @_remaining_data_length: remaining data to send in this payload
22512220
*/
22522221
static int smbd_iter_to_mr(struct smbd_connection *info,
22532222
struct iov_iter *iter,
2254-
struct scatterlist *sgl,
2255-
unsigned int num_pages)
2223+
struct sg_table *sgt,
2224+
unsigned int max_sg)
22562225
{
2257-
struct sg_table sgtable = { .sgl = sgl };
22582226
int ret;
22592227

2260-
sg_init_table(sgl, num_pages);
2228+
memset(sgt->sgl, 0, max_sg * sizeof(struct scatterlist));
22612229

2262-
ret = netfs_extract_iter_to_sg(iter, iov_iter_count(iter),
2263-
&sgtable, num_pages, 0);
2230+
ret = netfs_extract_iter_to_sg(iter, iov_iter_count(iter), sgt, max_sg, 0);
22642231
WARN_ON(ret < 0);
2232+
if (sgt->nents > 0)
2233+
sg_mark_end(&sgt->sgl[sgt->nents - 1]);
22652234
return ret;
22662235
}
22672236

@@ -2298,25 +2267,27 @@ struct smbd_mr *smbd_register_mr(struct smbd_connection *info,
22982267
dir = writing ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
22992268
smbdirect_mr->dir = dir;
23002269
smbdirect_mr->need_invalidate = need_invalidate;
2301-
smbdirect_mr->sgl_count = num_pages;
2270+
smbdirect_mr->sgt.nents = 0;
2271+
smbdirect_mr->sgt.orig_nents = 0;
23022272

2303-
log_rdma_mr(INFO, "num_pages=0x%x count=0x%zx\n",
2304-
num_pages, iov_iter_count(iter));
2305-
smbd_iter_to_mr(info, iter, smbdirect_mr->sgl, num_pages);
2273+
log_rdma_mr(INFO, "num_pages=0x%x count=0x%zx depth=%u\n",
2274+
num_pages, iov_iter_count(iter), info->max_frmr_depth);
2275+
smbd_iter_to_mr(info, iter, &smbdirect_mr->sgt, info->max_frmr_depth);
23062276

2307-
rc = ib_dma_map_sg(info->id->device, smbdirect_mr->sgl, num_pages, dir);
2277+
rc = ib_dma_map_sg(info->id->device, smbdirect_mr->sgt.sgl,
2278+
smbdirect_mr->sgt.nents, dir);
23082279
if (!rc) {
23092280
log_rdma_mr(ERR, "ib_dma_map_sg num_pages=%x dir=%x rc=%x\n",
23102281
num_pages, dir, rc);
23112282
goto dma_map_error;
23122283
}
23132284

2314-
rc = ib_map_mr_sg(smbdirect_mr->mr, smbdirect_mr->sgl, num_pages,
2315-
NULL, PAGE_SIZE);
2316-
if (rc != num_pages) {
2285+
rc = ib_map_mr_sg(smbdirect_mr->mr, smbdirect_mr->sgt.sgl,
2286+
smbdirect_mr->sgt.nents, NULL, PAGE_SIZE);
2287+
if (rc != smbdirect_mr->sgt.nents) {
23172288
log_rdma_mr(ERR,
2318-
"ib_map_mr_sg failed rc = %d num_pages = %x\n",
2319-
rc, num_pages);
2289+
"ib_map_mr_sg failed rc = %d nents = %x\n",
2290+
rc, smbdirect_mr->sgt.nents);
23202291
goto map_mr_error;
23212292
}
23222293

@@ -2348,8 +2319,8 @@ struct smbd_mr *smbd_register_mr(struct smbd_connection *info,
23482319

23492320
/* If all failed, attempt to recover this MR by setting it MR_ERROR*/
23502321
map_mr_error:
2351-
ib_dma_unmap_sg(info->id->device, smbdirect_mr->sgl,
2352-
smbdirect_mr->sgl_count, smbdirect_mr->dir);
2322+
ib_dma_unmap_sg(info->id->device, smbdirect_mr->sgt.sgl,
2323+
smbdirect_mr->sgt.nents, smbdirect_mr->dir);
23532324

23542325
dma_map_error:
23552326
smbdirect_mr->state = MR_ERROR;
@@ -2416,8 +2387,8 @@ int smbd_deregister_mr(struct smbd_mr *smbdirect_mr)
24162387

24172388
if (smbdirect_mr->state == MR_INVALIDATED) {
24182389
ib_dma_unmap_sg(
2419-
info->id->device, smbdirect_mr->sgl,
2420-
smbdirect_mr->sgl_count,
2390+
info->id->device, smbdirect_mr->sgt.sgl,
2391+
smbdirect_mr->sgt.nents,
24212392
smbdirect_mr->dir);
24222393
smbdirect_mr->state = MR_READY;
24232394
if (atomic_inc_return(&info->mr_ready_count) == 1)

fs/cifs/smbdirect.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -288,8 +288,7 @@ struct smbd_mr {
288288
struct list_head list;
289289
enum mr_state state;
290290
struct ib_mr *mr;
291-
struct scatterlist *sgl;
292-
int sgl_count;
291+
struct sg_table sgt;
293292
enum dma_data_direction dir;
294293
union {
295294
struct ib_reg_wr wr;

0 commit comments

Comments
 (0)