Commit | Line | Data |
---|---|---|
d7e09d03 PT |
1 | /* |
2 | * GPL HEADER START | |
3 | * | |
4 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License version 2 only, | |
8 | * as published by the Free Software Foundation. | |
9 | * | |
10 | * This program is distributed in the hope that it will be useful, but | |
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | * General Public License version 2 for more details (a copy is included | |
14 | * in the LICENSE file that accompanied this code). | |
15 | * | |
16 | * You should have received a copy of the GNU General Public License | |
17 | * version 2 along with this program; If not, see | |
18 | * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf | |
19 | * | |
20 | * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | |
21 | * CA 95054 USA or visit www.sun.com if you need additional information or | |
22 | * have any questions. | |
23 | * | |
24 | * GPL HEADER END | |
25 | */ | |
26 | /* | |
27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. | |
28 | * Use is subject to license terms. | |
29 | * | |
1dc563a6 | 30 | * Copyright (c) 2011, 2015, Intel Corporation. |
d7e09d03 PT |
31 | */ |
32 | /* | |
33 | * This file is part of Lustre, http://www.lustre.org/ | |
34 | * Lustre is a trademark of Sun Microsystems, Inc. | |
35 | * | |
36 | * lnet/selftest/brw_test.c | |
37 | * | |
38 | * Author: Isaac Huang <isaac@clusterfs.com> | |
39 | */ | |
40 | ||
41 | #include "selftest.h" | |
42 | ||
43 | static int brw_srv_workitems = SFW_TEST_WI_MAX; | |
8cc7b4b9 PT |
44 | module_param(brw_srv_workitems, int, 0644); |
45 | MODULE_PARM_DESC(brw_srv_workitems, "# BRW server workitems"); | |
d7e09d03 PT |
46 | |
47 | static int brw_inject_errors; | |
8cc7b4b9 PT |
48 | module_param(brw_inject_errors, int, 0644); |
49 | MODULE_PARM_DESC(brw_inject_errors, "# data errors to inject randomly, zero by default"); | |
d7e09d03 PT |
50 | |
51 | static void | |
5f849bb0 | 52 | brw_client_fini(sfw_test_instance_t *tsi) |
d7e09d03 | 53 | { |
00b5fdb7 JS |
54 | srpc_bulk_t *bulk; |
55 | sfw_test_unit_t *tsu; | |
d7e09d03 | 56 | |
5f849bb0 | 57 | LASSERT(tsi->tsi_is_client); |
d7e09d03 | 58 | |
5f849bb0 | 59 | list_for_each_entry(tsu, &tsi->tsi_units, tsu_list) { |
d7e09d03 | 60 | bulk = tsu->tsu_private; |
06ace26e | 61 | if (!bulk) |
5252bbfd | 62 | continue; |
d7e09d03 PT |
63 | |
64 | srpc_free_bulk(bulk); | |
65 | tsu->tsu_private = NULL; | |
66 | } | |
67 | } | |
68 | ||
d5bd0504 | 69 | static int |
5f849bb0 | 70 | brw_client_init(sfw_test_instance_t *tsi) |
d7e09d03 | 71 | { |
00b5fdb7 JS |
72 | sfw_session_t *sn = tsi->tsi_batch->bat_session; |
73 | int flags; | |
74 | int npg; | |
75 | int len; | |
76 | int opc; | |
77 | srpc_bulk_t *bulk; | |
78 | sfw_test_unit_t *tsu; | |
d7e09d03 | 79 | |
06ace26e | 80 | LASSERT(sn); |
d7e09d03 PT |
81 | LASSERT(tsi->tsi_is_client); |
82 | ||
5fd88337 | 83 | if (!(sn->sn_features & LST_FEAT_BULK_LEN)) { |
00b5fdb7 | 84 | test_bulk_req_t *breq = &tsi->tsi_u.bulk_v0; |
d7e09d03 | 85 | |
ec436b9a | 86 | opc = breq->blk_opc; |
d7e09d03 | 87 | flags = breq->blk_flags; |
ec436b9a | 88 | npg = breq->blk_npg; |
4420cfd3 JS |
89 | /* |
90 | * NB: this is not going to work for variable page size, | |
91 | * but we have to keep it for compatibility | |
92 | */ | |
09cbfeaf | 93 | len = npg * PAGE_SIZE; |
d7e09d03 PT |
94 | |
95 | } else { | |
74d68011 | 96 | test_bulk_req_v1_t *breq = &tsi->tsi_u.bulk_v1; |
d7e09d03 | 97 | |
4420cfd3 JS |
98 | /* |
99 | * I should never get this step if it's unknown feature | |
100 | * because make_session will reject unknown feature | |
101 | */ | |
5fd88337 | 102 | LASSERT(!(sn->sn_features & ~LST_FEATS_MASK)); |
d7e09d03 | 103 | |
ec436b9a | 104 | opc = breq->blk_opc; |
d7e09d03 | 105 | flags = breq->blk_flags; |
ec436b9a | 106 | len = breq->blk_len; |
09cbfeaf | 107 | npg = (len + PAGE_SIZE - 1) >> PAGE_SHIFT; |
d7e09d03 PT |
108 | } |
109 | ||
110 | if (npg > LNET_MAX_IOV || npg <= 0) | |
111 | return -EINVAL; | |
112 | ||
113 | if (opc != LST_BRW_READ && opc != LST_BRW_WRITE) | |
114 | return -EINVAL; | |
115 | ||
116 | if (flags != LST_BRW_CHECK_NONE && | |
117 | flags != LST_BRW_CHECK_FULL && flags != LST_BRW_CHECK_SIMPLE) | |
118 | return -EINVAL; | |
119 | ||
120 | list_for_each_entry(tsu, &tsi->tsi_units, tsu_list) { | |
121 | bulk = srpc_alloc_bulk(lnet_cpt_of_nid(tsu->tsu_dest.nid), | |
122 | npg, len, opc == LST_BRW_READ); | |
06ace26e | 123 | if (!bulk) { |
d7e09d03 PT |
124 | brw_client_fini(tsi); |
125 | return -ENOMEM; | |
126 | } | |
127 | ||
128 | tsu->tsu_private = bulk; | |
129 | } | |
130 | ||
131 | return 0; | |
132 | } | |
133 | ||
b794d796 JS |
134 | #define BRW_POISON 0xbeefbeefbeefbeefULL |
135 | #define BRW_MAGIC 0xeeb0eeb1eeb2eeb3ULL | |
136 | #define BRW_MSIZE sizeof(__u64) | |
d7e09d03 | 137 | |
d4b2d88a | 138 | static int |
5f849bb0 | 139 | brw_inject_one_error(void) |
d7e09d03 | 140 | { |
d9f79e6b | 141 | struct timespec64 ts; |
d7e09d03 | 142 | |
5252bbfd LN |
143 | if (brw_inject_errors <= 0) |
144 | return 0; | |
d7e09d03 | 145 | |
d9f79e6b | 146 | ktime_get_ts64(&ts); |
d7e09d03 | 147 | |
5fd88337 | 148 | if (!((ts.tv_nsec / NSEC_PER_USEC) & 1)) |
5252bbfd | 149 | return 0; |
d7e09d03 PT |
150 | |
151 | return brw_inject_errors--; | |
152 | } | |
153 | ||
2e3e133d | 154 | static void |
5f849bb0 | 155 | brw_fill_page(struct page *pg, int pattern, __u64 magic) |
d7e09d03 PT |
156 | { |
157 | char *addr = page_address(pg); | |
00b5fdb7 | 158 | int i; |
d7e09d03 | 159 | |
06ace26e | 160 | LASSERT(addr); |
d7e09d03 | 161 | |
5252bbfd LN |
162 | if (pattern == LST_BRW_CHECK_NONE) |
163 | return; | |
d7e09d03 PT |
164 | |
165 | if (magic == BRW_MAGIC) | |
166 | magic += brw_inject_one_error(); | |
167 | ||
168 | if (pattern == LST_BRW_CHECK_SIMPLE) { | |
169 | memcpy(addr, &magic, BRW_MSIZE); | |
09cbfeaf | 170 | addr += PAGE_SIZE - BRW_MSIZE; |
d7e09d03 PT |
171 | memcpy(addr, &magic, BRW_MSIZE); |
172 | return; | |
173 | } | |
174 | ||
175 | if (pattern == LST_BRW_CHECK_FULL) { | |
09cbfeaf | 176 | for (i = 0; i < PAGE_SIZE / BRW_MSIZE; i++) |
d7e09d03 PT |
177 | memcpy(addr + i * BRW_MSIZE, &magic, BRW_MSIZE); |
178 | return; | |
179 | } | |
180 | ||
5f849bb0 | 181 | LBUG(); |
d7e09d03 PT |
182 | } |
183 | ||
43311238 | 184 | static int |
5f849bb0 | 185 | brw_check_page(struct page *pg, int pattern, __u64 magic) |
d7e09d03 | 186 | { |
00b5fdb7 JS |
187 | char *addr = page_address(pg); |
188 | __u64 data = 0; /* make compiler happy */ | |
189 | int i; | |
d7e09d03 | 190 | |
06ace26e | 191 | LASSERT(addr); |
d7e09d03 PT |
192 | |
193 | if (pattern == LST_BRW_CHECK_NONE) | |
194 | return 0; | |
195 | ||
196 | if (pattern == LST_BRW_CHECK_SIMPLE) { | |
d47e33e8 | 197 | data = *((__u64 *)addr); |
5252bbfd LN |
198 | if (data != magic) |
199 | goto bad_data; | |
d7e09d03 | 200 | |
09cbfeaf | 201 | addr += PAGE_SIZE - BRW_MSIZE; |
d47e33e8 | 202 | data = *((__u64 *)addr); |
5252bbfd LN |
203 | if (data != magic) |
204 | goto bad_data; | |
d7e09d03 PT |
205 | |
206 | return 0; | |
207 | } | |
208 | ||
209 | if (pattern == LST_BRW_CHECK_FULL) { | |
09cbfeaf | 210 | for (i = 0; i < PAGE_SIZE / BRW_MSIZE; i++) { |
d47e33e8 | 211 | data = *(((__u64 *)addr) + i); |
5252bbfd LN |
212 | if (data != magic) |
213 | goto bad_data; | |
d7e09d03 PT |
214 | } |
215 | ||
216 | return 0; | |
217 | } | |
218 | ||
5f849bb0 | 219 | LBUG(); |
d7e09d03 PT |
220 | |
221 | bad_data: | |
55f5a824 | 222 | CERROR("Bad data in page %p: %#llx, %#llx expected\n", |
c314c319 | 223 | pg, data, magic); |
d7e09d03 PT |
224 | return 1; |
225 | } | |
226 | ||
56e1ccac | 227 | static void |
5f849bb0 | 228 | brw_fill_bulk(srpc_bulk_t *bk, int pattern, __u64 magic) |
d7e09d03 | 229 | { |
74d68011 | 230 | int i; |
d7e09d03 PT |
231 | struct page *pg; |
232 | ||
233 | for (i = 0; i < bk->bk_niov; i++) { | |
234 | pg = bk->bk_iovs[i].kiov_page; | |
235 | brw_fill_page(pg, pattern, magic); | |
236 | } | |
237 | } | |
238 | ||
ec17e811 | 239 | static int |
5f849bb0 | 240 | brw_check_bulk(srpc_bulk_t *bk, int pattern, __u64 magic) |
d7e09d03 | 241 | { |
74d68011 | 242 | int i; |
d7e09d03 PT |
243 | struct page *pg; |
244 | ||
245 | for (i = 0; i < bk->bk_niov; i++) { | |
246 | pg = bk->bk_iovs[i].kiov_page; | |
5fd88337 | 247 | if (brw_check_page(pg, pattern, magic)) { |
5f849bb0 | 248 | CERROR("Bulk page %p (%d/%d) is corrupted!\n", |
c314c319 | 249 | pg, i, bk->bk_niov); |
d7e09d03 PT |
250 | return 1; |
251 | } | |
252 | } | |
253 | ||
254 | return 0; | |
255 | } | |
256 | ||
257 | static int | |
5f849bb0 | 258 | brw_client_prep_rpc(sfw_test_unit_t *tsu, |
c314c319 | 259 | lnet_process_id_t dest, srpc_client_rpc_t **rpcpp) |
d7e09d03 | 260 | { |
74d68011 | 261 | srpc_bulk_t *bulk = tsu->tsu_private; |
d7e09d03 | 262 | sfw_test_instance_t *tsi = tsu->tsu_instance; |
74d68011 MS |
263 | sfw_session_t *sn = tsi->tsi_batch->bat_session; |
264 | srpc_client_rpc_t *rpc; | |
265 | srpc_brw_reqst_t *req; | |
266 | int flags; | |
267 | int npg; | |
268 | int len; | |
269 | int opc; | |
270 | int rc; | |
d7e09d03 | 271 | |
06ace26e JS |
272 | LASSERT(sn); |
273 | LASSERT(bulk); | |
d7e09d03 | 274 | |
5fd88337 | 275 | if (!(sn->sn_features & LST_FEAT_BULK_LEN)) { |
d7e09d03 PT |
276 | test_bulk_req_t *breq = &tsi->tsi_u.bulk_v0; |
277 | ||
ec436b9a | 278 | opc = breq->blk_opc; |
d7e09d03 | 279 | flags = breq->blk_flags; |
ec436b9a | 280 | npg = breq->blk_npg; |
09cbfeaf | 281 | len = npg * PAGE_SIZE; |
d7e09d03 PT |
282 | |
283 | } else { | |
74d68011 | 284 | test_bulk_req_v1_t *breq = &tsi->tsi_u.bulk_v1; |
d7e09d03 | 285 | |
4420cfd3 JS |
286 | /* |
287 | * I should never get this step if it's unknown feature | |
288 | * because make_session will reject unknown feature | |
289 | */ | |
5fd88337 | 290 | LASSERT(!(sn->sn_features & ~LST_FEATS_MASK)); |
d7e09d03 | 291 | |
ec436b9a | 292 | opc = breq->blk_opc; |
d7e09d03 | 293 | flags = breq->blk_flags; |
ec436b9a | 294 | len = breq->blk_len; |
09cbfeaf | 295 | npg = (len + PAGE_SIZE - 1) >> PAGE_SHIFT; |
d7e09d03 PT |
296 | } |
297 | ||
298 | rc = sfw_create_test_rpc(tsu, dest, sn->sn_features, npg, len, &rpc); | |
5fd88337 | 299 | if (rc) |
d7e09d03 PT |
300 | return rc; |
301 | ||
302 | memcpy(&rpc->crpc_bulk, bulk, offsetof(srpc_bulk_t, bk_iovs[npg])); | |
303 | if (opc == LST_BRW_WRITE) | |
304 | brw_fill_bulk(&rpc->crpc_bulk, flags, BRW_MAGIC); | |
305 | else | |
306 | brw_fill_bulk(&rpc->crpc_bulk, flags, BRW_POISON); | |
307 | ||
308 | req = &rpc->crpc_reqstmsg.msg_body.brw_reqst; | |
309 | req->brw_flags = flags; | |
ec436b9a JS |
310 | req->brw_rw = opc; |
311 | req->brw_len = len; | |
d7e09d03 PT |
312 | |
313 | *rpcpp = rpc; | |
314 | return 0; | |
315 | } | |
316 | ||
317 | static void | |
5f849bb0 | 318 | brw_client_done_rpc(sfw_test_unit_t *tsu, srpc_client_rpc_t *rpc) |
d7e09d03 | 319 | { |
74d68011 | 320 | __u64 magic = BRW_MAGIC; |
d7e09d03 | 321 | sfw_test_instance_t *tsi = tsu->tsu_instance; |
74d68011 MS |
322 | sfw_session_t *sn = tsi->tsi_batch->bat_session; |
323 | srpc_msg_t *msg = &rpc->crpc_replymsg; | |
324 | srpc_brw_reply_t *reply = &msg->msg_body.brw_reply; | |
325 | srpc_brw_reqst_t *reqst = &rpc->crpc_reqstmsg.msg_body.brw_reqst; | |
d7e09d03 | 326 | |
06ace26e | 327 | LASSERT(sn); |
d7e09d03 | 328 | |
5fd88337 | 329 | if (rpc->crpc_status) { |
5f849bb0 | 330 | CERROR("BRW RPC to %s failed with %d\n", |
c314c319 | 331 | libcfs_id2str(rpc->crpc_dest), rpc->crpc_status); |
d7e09d03 PT |
332 | if (!tsi->tsi_stopping) /* rpc could have been aborted */ |
333 | atomic_inc(&sn->sn_brw_errors); | |
8a2c2306 | 334 | return; |
d7e09d03 PT |
335 | } |
336 | ||
337 | if (msg->msg_magic != SRPC_MSG_MAGIC) { | |
338 | __swab64s(&magic); | |
339 | __swab32s(&reply->brw_status); | |
340 | } | |
341 | ||
5f849bb0 | 342 | CDEBUG(reply->brw_status ? D_WARNING : D_NET, |
c314c319 JS |
343 | "BRW RPC to %s finished with brw_status: %d\n", |
344 | libcfs_id2str(rpc->crpc_dest), reply->brw_status); | |
d7e09d03 | 345 | |
5fd88337 | 346 | if (reply->brw_status) { |
d7e09d03 PT |
347 | atomic_inc(&sn->sn_brw_errors); |
348 | rpc->crpc_status = -(int)reply->brw_status; | |
8a2c2306 | 349 | return; |
d7e09d03 PT |
350 | } |
351 | ||
5252bbfd | 352 | if (reqst->brw_rw == LST_BRW_WRITE) |
8a2c2306 | 353 | return; |
d7e09d03 | 354 | |
5fd88337 | 355 | if (brw_check_bulk(&rpc->crpc_bulk, reqst->brw_flags, magic)) { |
5f849bb0 | 356 | CERROR("Bulk data from %s is corrupted!\n", |
c314c319 | 357 | libcfs_id2str(rpc->crpc_dest)); |
d7e09d03 PT |
358 | atomic_inc(&sn->sn_brw_errors); |
359 | rpc->crpc_status = -EBADMSG; | |
360 | } | |
d7e09d03 PT |
361 | } |
362 | ||
6888871c | 363 | static void |
168c7a13 | 364 | brw_server_rpc_done(struct srpc_server_rpc *rpc) |
d7e09d03 PT |
365 | { |
366 | srpc_bulk_t *blk = rpc->srpc_bulk; | |
367 | ||
06ace26e | 368 | if (!blk) |
5252bbfd | 369 | return; |
d7e09d03 | 370 | |
5fd88337 | 371 | if (rpc->srpc_status) |
5f849bb0 | 372 | CERROR("Bulk transfer %s %s has failed: %d\n", |
c314c319 JS |
373 | blk->bk_sink ? "from" : "to", |
374 | libcfs_id2str(rpc->srpc_peer), rpc->srpc_status); | |
d7e09d03 | 375 | else |
5f849bb0 | 376 | CDEBUG(D_NET, "Transferred %d pages bulk data %s %s\n", |
c314c319 JS |
377 | blk->bk_niov, blk->bk_sink ? "from" : "to", |
378 | libcfs_id2str(rpc->srpc_peer)); | |
d7e09d03 PT |
379 | |
380 | sfw_free_pages(rpc); | |
381 | } | |
382 | ||
0c05ef92 | 383 | static int |
168c7a13 | 384 | brw_bulk_ready(struct srpc_server_rpc *rpc, int status) |
d7e09d03 | 385 | { |
74d68011 | 386 | __u64 magic = BRW_MAGIC; |
d7e09d03 PT |
387 | srpc_brw_reply_t *reply = &rpc->srpc_replymsg.msg_body.brw_reply; |
388 | srpc_brw_reqst_t *reqst; | |
74d68011 | 389 | srpc_msg_t *reqstmsg; |
d7e09d03 | 390 | |
06ace26e JS |
391 | LASSERT(rpc->srpc_bulk); |
392 | LASSERT(rpc->srpc_reqstbuf); | |
d7e09d03 PT |
393 | |
394 | reqstmsg = &rpc->srpc_reqstbuf->buf_msg; | |
395 | reqst = &reqstmsg->msg_body.brw_reqst; | |
396 | ||
5fd88337 | 397 | if (status) { |
5f849bb0 | 398 | CERROR("BRW bulk %s failed for RPC from %s: %d\n", |
c314c319 JS |
399 | reqst->brw_rw == LST_BRW_READ ? "READ" : "WRITE", |
400 | libcfs_id2str(rpc->srpc_peer), status); | |
d7e09d03 PT |
401 | return -EIO; |
402 | } | |
403 | ||
404 | if (reqst->brw_rw == LST_BRW_READ) | |
405 | return 0; | |
406 | ||
407 | if (reqstmsg->msg_magic != SRPC_MSG_MAGIC) | |
408 | __swab64s(&magic); | |
409 | ||
5fd88337 | 410 | if (brw_check_bulk(rpc->srpc_bulk, reqst->brw_flags, magic)) { |
5f849bb0 | 411 | CERROR("Bulk data from %s is corrupted!\n", |
c314c319 | 412 | libcfs_id2str(rpc->srpc_peer)); |
d7e09d03 PT |
413 | reply->brw_status = EBADMSG; |
414 | } | |
415 | ||
416 | return 0; | |
417 | } | |
418 | ||
4a1b86dc | 419 | static int |
d7e09d03 PT |
420 | brw_server_handle(struct srpc_server_rpc *rpc) |
421 | { | |
74d68011 MS |
422 | struct srpc_service *sv = rpc->srpc_scd->scd_svc; |
423 | srpc_msg_t *replymsg = &rpc->srpc_replymsg; | |
424 | srpc_msg_t *reqstmsg = &rpc->srpc_reqstbuf->buf_msg; | |
d7e09d03 PT |
425 | srpc_brw_reply_t *reply = &replymsg->msg_body.brw_reply; |
426 | srpc_brw_reqst_t *reqst = &reqstmsg->msg_body.brw_reqst; | |
74d68011 MS |
427 | int npg; |
428 | int rc; | |
d7e09d03 | 429 | |
5f849bb0 | 430 | LASSERT(sv->sv_id == SRPC_SERVICE_BRW); |
d7e09d03 PT |
431 | |
432 | if (reqstmsg->msg_magic != SRPC_MSG_MAGIC) { | |
5f849bb0 | 433 | LASSERT(reqstmsg->msg_magic == __swab32(SRPC_MSG_MAGIC)); |
d7e09d03 PT |
434 | |
435 | __swab32s(&reqst->brw_rw); | |
436 | __swab32s(&reqst->brw_len); | |
437 | __swab32s(&reqst->brw_flags); | |
438 | __swab64s(&reqst->brw_rpyid); | |
439 | __swab64s(&reqst->brw_bulkid); | |
440 | } | |
5f849bb0 | 441 | LASSERT(reqstmsg->msg_type == (__u32)srpc_service2request(sv->sv_id)); |
d7e09d03 PT |
442 | |
443 | reply->brw_status = 0; | |
444 | rpc->srpc_done = brw_server_rpc_done; | |
445 | ||
446 | if ((reqst->brw_rw != LST_BRW_READ && reqst->brw_rw != LST_BRW_WRITE) || | |
447 | (reqst->brw_flags != LST_BRW_CHECK_NONE && | |
448 | reqst->brw_flags != LST_BRW_CHECK_FULL && | |
449 | reqst->brw_flags != LST_BRW_CHECK_SIMPLE)) { | |
450 | reply->brw_status = EINVAL; | |
451 | return 0; | |
452 | } | |
453 | ||
5fd88337 | 454 | if (reqstmsg->msg_ses_feats & ~LST_FEATS_MASK) { |
d7e09d03 PT |
455 | replymsg->msg_ses_feats = LST_FEATS_MASK; |
456 | reply->brw_status = EPROTO; | |
457 | return 0; | |
458 | } | |
459 | ||
5fd88337 | 460 | if (!(reqstmsg->msg_ses_feats & LST_FEAT_BULK_LEN)) { |
d7e09d03 | 461 | /* compat with old version */ |
5fd88337 | 462 | if (reqst->brw_len & ~CFS_PAGE_MASK) { |
d7e09d03 PT |
463 | reply->brw_status = EINVAL; |
464 | return 0; | |
465 | } | |
09cbfeaf | 466 | npg = reqst->brw_len >> PAGE_SHIFT; |
d7e09d03 PT |
467 | |
468 | } else { | |
09cbfeaf | 469 | npg = (reqst->brw_len + PAGE_SIZE - 1) >> PAGE_SHIFT; |
d7e09d03 PT |
470 | } |
471 | ||
472 | replymsg->msg_ses_feats = reqstmsg->msg_ses_feats; | |
473 | ||
5fd88337 | 474 | if (!reqst->brw_len || npg > LNET_MAX_IOV) { |
d7e09d03 PT |
475 | reply->brw_status = EINVAL; |
476 | return 0; | |
477 | } | |
478 | ||
479 | rc = sfw_alloc_pages(rpc, rpc->srpc_scd->scd_cpt, npg, | |
480 | reqst->brw_len, | |
481 | reqst->brw_rw == LST_BRW_WRITE); | |
5fd88337 | 482 | if (rc) |
d7e09d03 PT |
483 | return rc; |
484 | ||
485 | if (reqst->brw_rw == LST_BRW_READ) | |
486 | brw_fill_bulk(rpc->srpc_bulk, reqst->brw_flags, BRW_MAGIC); | |
487 | else | |
488 | brw_fill_bulk(rpc->srpc_bulk, reqst->brw_flags, BRW_POISON); | |
489 | ||
490 | return 0; | |
491 | } | |
492 | ||
493 | sfw_test_client_ops_t brw_test_client; | |
494 | void brw_init_test_client(void) | |
495 | { | |
ec436b9a JS |
496 | brw_test_client.tso_init = brw_client_init; |
497 | brw_test_client.tso_fini = brw_client_fini; | |
74d68011 MS |
498 | brw_test_client.tso_prep_rpc = brw_client_prep_rpc; |
499 | brw_test_client.tso_done_rpc = brw_client_done_rpc; | |
d7e09d03 PT |
500 | }; |
501 | ||
502 | srpc_service_t brw_test_service; | |
503 | void brw_init_test_service(void) | |
504 | { | |
ec436b9a JS |
505 | brw_test_service.sv_id = SRPC_SERVICE_BRW; |
506 | brw_test_service.sv_name = "brw_test"; | |
507 | brw_test_service.sv_handler = brw_server_handle; | |
d7e09d03 | 508 | brw_test_service.sv_bulk_ready = brw_bulk_ready; |
ec436b9a | 509 | brw_test_service.sv_wi_total = brw_srv_workitems; |
d7e09d03 | 510 | } |