]>
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 | |
6a5b99a4 | 18 | * http://www.gnu.org/licenses/gpl-2.0.html |
d7e09d03 | 19 | * |
d7e09d03 PT |
20 | * GPL HEADER END |
21 | */ | |
22 | /* | |
23 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. | |
24 | * Use is subject to license terms. | |
25 | * | |
1dc563a6 | 26 | * Copyright (c) 2011, 2015, Intel Corporation. |
d7e09d03 PT |
27 | */ |
28 | /* | |
29 | * This file is part of Lustre, http://www.lustre.org/ | |
30 | * Lustre is a trademark of Sun Microsystems, Inc. | |
31 | * | |
32 | * lnet/selftest/brw_test.c | |
33 | * | |
34 | * Author: Isaac Huang <isaac@clusterfs.com> | |
35 | */ | |
36 | ||
37 | #include "selftest.h" | |
38 | ||
39 | static int brw_srv_workitems = SFW_TEST_WI_MAX; | |
8cc7b4b9 PT |
40 | module_param(brw_srv_workitems, int, 0644); |
41 | MODULE_PARM_DESC(brw_srv_workitems, "# BRW server workitems"); | |
d7e09d03 PT |
42 | |
43 | static int brw_inject_errors; | |
8cc7b4b9 PT |
44 | module_param(brw_inject_errors, int, 0644); |
45 | MODULE_PARM_DESC(brw_inject_errors, "# data errors to inject randomly, zero by default"); | |
d7e09d03 | 46 | |
b73d803b LZ |
47 | #define BRW_POISON 0xbeefbeefbeefbeefULL |
48 | #define BRW_MAGIC 0xeeb0eeb1eeb2eeb3ULL | |
49 | #define BRW_MSIZE sizeof(u64) | |
50 | ||
d7e09d03 | 51 | static void |
7ca48d85 | 52 | brw_client_fini(struct sfw_test_instance *tsi) |
d7e09d03 | 53 | { |
eb6e1342 | 54 | struct srpc_bulk *bulk; |
d875b0ce | 55 | struct sfw_test_unit *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 |
7ca48d85 | 70 | brw_client_init(struct sfw_test_instance *tsi) |
d7e09d03 | 71 | { |
693d2664 | 72 | struct sfw_session *sn = tsi->tsi_batch->bat_session; |
00b5fdb7 | 73 | int flags; |
b73d803b | 74 | int off; |
00b5fdb7 JS |
75 | int npg; |
76 | int len; | |
77 | int opc; | |
eb6e1342 | 78 | struct srpc_bulk *bulk; |
d875b0ce | 79 | struct sfw_test_unit *tsu; |
d7e09d03 | 80 | |
06ace26e | 81 | LASSERT(sn); |
d7e09d03 PT |
82 | LASSERT(tsi->tsi_is_client); |
83 | ||
5fd88337 | 84 | if (!(sn->sn_features & LST_FEAT_BULK_LEN)) { |
45d2f4fb | 85 | struct test_bulk_req *breq = &tsi->tsi_u.bulk_v0; |
d7e09d03 | 86 | |
ec436b9a | 87 | opc = breq->blk_opc; |
d7e09d03 | 88 | flags = breq->blk_flags; |
ec436b9a | 89 | npg = breq->blk_npg; |
4420cfd3 JS |
90 | /* |
91 | * NB: this is not going to work for variable page size, | |
92 | * but we have to keep it for compatibility | |
93 | */ | |
09cbfeaf | 94 | len = npg * PAGE_SIZE; |
b73d803b | 95 | off = 0; |
d7e09d03 | 96 | } else { |
45d2f4fb | 97 | struct test_bulk_req_v1 *breq = &tsi->tsi_u.bulk_v1; |
d7e09d03 | 98 | |
4420cfd3 JS |
99 | /* |
100 | * I should never get this step if it's unknown feature | |
101 | * because make_session will reject unknown feature | |
102 | */ | |
5fd88337 | 103 | LASSERT(!(sn->sn_features & ~LST_FEATS_MASK)); |
d7e09d03 | 104 | |
ec436b9a | 105 | opc = breq->blk_opc; |
d7e09d03 | 106 | flags = breq->blk_flags; |
ec436b9a | 107 | len = breq->blk_len; |
b73d803b LZ |
108 | off = breq->blk_offset & ~PAGE_MASK; |
109 | npg = (off + len + PAGE_SIZE - 1) >> PAGE_SHIFT; | |
d7e09d03 PT |
110 | } |
111 | ||
b73d803b LZ |
112 | if (off % BRW_MSIZE) |
113 | return -EINVAL; | |
114 | ||
d7e09d03 PT |
115 | if (npg > LNET_MAX_IOV || npg <= 0) |
116 | return -EINVAL; | |
117 | ||
118 | if (opc != LST_BRW_READ && opc != LST_BRW_WRITE) | |
119 | return -EINVAL; | |
120 | ||
121 | if (flags != LST_BRW_CHECK_NONE && | |
122 | flags != LST_BRW_CHECK_FULL && flags != LST_BRW_CHECK_SIMPLE) | |
123 | return -EINVAL; | |
124 | ||
125 | list_for_each_entry(tsu, &tsi->tsi_units, tsu_list) { | |
126 | bulk = srpc_alloc_bulk(lnet_cpt_of_nid(tsu->tsu_dest.nid), | |
b73d803b | 127 | off, npg, len, opc == LST_BRW_READ); |
06ace26e | 128 | if (!bulk) { |
d7e09d03 PT |
129 | brw_client_fini(tsi); |
130 | return -ENOMEM; | |
131 | } | |
132 | ||
133 | tsu->tsu_private = bulk; | |
134 | } | |
135 | ||
136 | return 0; | |
137 | } | |
138 | ||
b73d803b | 139 | int 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 |
b73d803b | 155 | brw_fill_page(struct page *pg, int off, int len, int pattern, __u64 magic) |
d7e09d03 | 156 | { |
b73d803b | 157 | char *addr = page_address(pg) + off; |
00b5fdb7 | 158 | int i; |
d7e09d03 | 159 | |
06ace26e | 160 | LASSERT(addr); |
b73d803b | 161 | LASSERT(!(off % BRW_MSIZE) && !(len % BRW_MSIZE)); |
d7e09d03 | 162 | |
5252bbfd LN |
163 | if (pattern == LST_BRW_CHECK_NONE) |
164 | return; | |
d7e09d03 PT |
165 | |
166 | if (magic == BRW_MAGIC) | |
167 | magic += brw_inject_one_error(); | |
168 | ||
169 | if (pattern == LST_BRW_CHECK_SIMPLE) { | |
170 | memcpy(addr, &magic, BRW_MSIZE); | |
b73d803b LZ |
171 | if (len > BRW_MSIZE) { |
172 | addr += PAGE_SIZE - BRW_MSIZE; | |
173 | memcpy(addr, &magic, BRW_MSIZE); | |
174 | } | |
d7e09d03 PT |
175 | return; |
176 | } | |
177 | ||
178 | if (pattern == LST_BRW_CHECK_FULL) { | |
b73d803b LZ |
179 | for (i = 0; i < len; i += BRW_MSIZE) |
180 | memcpy(addr + i, &magic, BRW_MSIZE); | |
d7e09d03 PT |
181 | return; |
182 | } | |
183 | ||
5f849bb0 | 184 | LBUG(); |
d7e09d03 PT |
185 | } |
186 | ||
43311238 | 187 | static int |
b73d803b | 188 | brw_check_page(struct page *pg, int off, int len, int pattern, __u64 magic) |
d7e09d03 | 189 | { |
b73d803b | 190 | char *addr = page_address(pg) + off; |
00b5fdb7 JS |
191 | __u64 data = 0; /* make compiler happy */ |
192 | int i; | |
d7e09d03 | 193 | |
06ace26e | 194 | LASSERT(addr); |
b73d803b | 195 | LASSERT(!(off % BRW_MSIZE) && !(len % BRW_MSIZE)); |
d7e09d03 PT |
196 | |
197 | if (pattern == LST_BRW_CHECK_NONE) | |
198 | return 0; | |
199 | ||
200 | if (pattern == LST_BRW_CHECK_SIMPLE) { | |
d47e33e8 | 201 | data = *((__u64 *)addr); |
5252bbfd LN |
202 | if (data != magic) |
203 | goto bad_data; | |
d7e09d03 | 204 | |
b73d803b LZ |
205 | if (len > BRW_MSIZE) { |
206 | addr += PAGE_SIZE - BRW_MSIZE; | |
207 | data = *((__u64 *)addr); | |
208 | if (data != magic) | |
209 | goto bad_data; | |
210 | } | |
d7e09d03 PT |
211 | return 0; |
212 | } | |
213 | ||
214 | if (pattern == LST_BRW_CHECK_FULL) { | |
b73d803b LZ |
215 | for (i = 0; i < len; i += BRW_MSIZE) { |
216 | data = *(u64 *)(addr + i); | |
5252bbfd LN |
217 | if (data != magic) |
218 | goto bad_data; | |
d7e09d03 | 219 | } |
d7e09d03 PT |
220 | return 0; |
221 | } | |
222 | ||
5f849bb0 | 223 | LBUG(); |
d7e09d03 PT |
224 | |
225 | bad_data: | |
55f5a824 | 226 | CERROR("Bad data in page %p: %#llx, %#llx expected\n", |
c314c319 | 227 | pg, data, magic); |
d7e09d03 PT |
228 | return 1; |
229 | } | |
230 | ||
56e1ccac | 231 | static void |
eb6e1342 | 232 | brw_fill_bulk(struct srpc_bulk *bk, int pattern, __u64 magic) |
d7e09d03 | 233 | { |
74d68011 | 234 | int i; |
d7e09d03 PT |
235 | struct page *pg; |
236 | ||
237 | for (i = 0; i < bk->bk_niov; i++) { | |
b73d803b LZ |
238 | int off, len; |
239 | ||
65ffc679 | 240 | pg = bk->bk_iovs[i].bv_page; |
b73d803b LZ |
241 | off = bk->bk_iovs[i].bv_offset; |
242 | len = bk->bk_iovs[i].bv_len; | |
243 | brw_fill_page(pg, off, len, pattern, magic); | |
d7e09d03 PT |
244 | } |
245 | } | |
246 | ||
ec17e811 | 247 | static int |
eb6e1342 | 248 | brw_check_bulk(struct srpc_bulk *bk, int pattern, __u64 magic) |
d7e09d03 | 249 | { |
74d68011 | 250 | int i; |
d7e09d03 PT |
251 | struct page *pg; |
252 | ||
253 | for (i = 0; i < bk->bk_niov; i++) { | |
b73d803b LZ |
254 | int off, len; |
255 | ||
65ffc679 | 256 | pg = bk->bk_iovs[i].bv_page; |
b73d803b LZ |
257 | off = bk->bk_iovs[i].bv_offset; |
258 | len = bk->bk_iovs[i].bv_len; | |
259 | if (brw_check_page(pg, off, len, pattern, magic)) { | |
5f849bb0 | 260 | CERROR("Bulk page %p (%d/%d) is corrupted!\n", |
c314c319 | 261 | pg, i, bk->bk_niov); |
d7e09d03 PT |
262 | return 1; |
263 | } | |
264 | } | |
265 | ||
266 | return 0; | |
267 | } | |
268 | ||
269 | static int | |
d875b0ce | 270 | brw_client_prep_rpc(struct sfw_test_unit *tsu, |
20234da5 | 271 | lnet_process_id_t dest, struct srpc_client_rpc **rpcpp) |
d7e09d03 | 272 | { |
eb6e1342 | 273 | struct srpc_bulk *bulk = tsu->tsu_private; |
7ca48d85 | 274 | struct sfw_test_instance *tsi = tsu->tsu_instance; |
693d2664 | 275 | struct sfw_session *sn = tsi->tsi_batch->bat_session; |
20234da5 | 276 | struct srpc_client_rpc *rpc; |
45d2f4fb | 277 | struct srpc_brw_reqst *req; |
74d68011 MS |
278 | int flags; |
279 | int npg; | |
280 | int len; | |
281 | int opc; | |
282 | int rc; | |
d7e09d03 | 283 | |
06ace26e JS |
284 | LASSERT(sn); |
285 | LASSERT(bulk); | |
d7e09d03 | 286 | |
5fd88337 | 287 | if (!(sn->sn_features & LST_FEAT_BULK_LEN)) { |
45d2f4fb | 288 | struct test_bulk_req *breq = &tsi->tsi_u.bulk_v0; |
d7e09d03 | 289 | |
ec436b9a | 290 | opc = breq->blk_opc; |
d7e09d03 | 291 | flags = breq->blk_flags; |
ec436b9a | 292 | npg = breq->blk_npg; |
09cbfeaf | 293 | len = npg * PAGE_SIZE; |
d7e09d03 | 294 | } else { |
45d2f4fb | 295 | struct test_bulk_req_v1 *breq = &tsi->tsi_u.bulk_v1; |
b73d803b | 296 | int off; |
d7e09d03 | 297 | |
4420cfd3 JS |
298 | /* |
299 | * I should never get this step if it's unknown feature | |
300 | * because make_session will reject unknown feature | |
301 | */ | |
5fd88337 | 302 | LASSERT(!(sn->sn_features & ~LST_FEATS_MASK)); |
d7e09d03 | 303 | |
ec436b9a | 304 | opc = breq->blk_opc; |
d7e09d03 | 305 | flags = breq->blk_flags; |
ec436b9a | 306 | len = breq->blk_len; |
b73d803b LZ |
307 | off = breq->blk_offset; |
308 | npg = (off + len + PAGE_SIZE - 1) >> PAGE_SHIFT; | |
d7e09d03 PT |
309 | } |
310 | ||
311 | rc = sfw_create_test_rpc(tsu, dest, sn->sn_features, npg, len, &rpc); | |
5fd88337 | 312 | if (rc) |
d7e09d03 PT |
313 | return rc; |
314 | ||
eb6e1342 | 315 | memcpy(&rpc->crpc_bulk, bulk, offsetof(struct srpc_bulk, bk_iovs[npg])); |
d7e09d03 PT |
316 | if (opc == LST_BRW_WRITE) |
317 | brw_fill_bulk(&rpc->crpc_bulk, flags, BRW_MAGIC); | |
318 | else | |
319 | brw_fill_bulk(&rpc->crpc_bulk, flags, BRW_POISON); | |
320 | ||
321 | req = &rpc->crpc_reqstmsg.msg_body.brw_reqst; | |
322 | req->brw_flags = flags; | |
ec436b9a JS |
323 | req->brw_rw = opc; |
324 | req->brw_len = len; | |
d7e09d03 PT |
325 | |
326 | *rpcpp = rpc; | |
327 | return 0; | |
328 | } | |
329 | ||
330 | static void | |
d875b0ce | 331 | brw_client_done_rpc(struct sfw_test_unit *tsu, struct srpc_client_rpc *rpc) |
d7e09d03 | 332 | { |
74d68011 | 333 | __u64 magic = BRW_MAGIC; |
7ca48d85 | 334 | struct sfw_test_instance *tsi = tsu->tsu_instance; |
693d2664 | 335 | struct sfw_session *sn = tsi->tsi_batch->bat_session; |
fd7a1a32 | 336 | struct srpc_msg *msg = &rpc->crpc_replymsg; |
45d2f4fb JS |
337 | struct srpc_brw_reply *reply = &msg->msg_body.brw_reply; |
338 | struct srpc_brw_reqst *reqst = &rpc->crpc_reqstmsg.msg_body.brw_reqst; | |
d7e09d03 | 339 | |
06ace26e | 340 | LASSERT(sn); |
d7e09d03 | 341 | |
5fd88337 | 342 | if (rpc->crpc_status) { |
5f849bb0 | 343 | CERROR("BRW RPC to %s failed with %d\n", |
c314c319 | 344 | libcfs_id2str(rpc->crpc_dest), rpc->crpc_status); |
dae0587e | 345 | if (!tsi->tsi_stopping) /* rpc could have been aborted */ |
d7e09d03 | 346 | atomic_inc(&sn->sn_brw_errors); |
8a2c2306 | 347 | return; |
d7e09d03 PT |
348 | } |
349 | ||
350 | if (msg->msg_magic != SRPC_MSG_MAGIC) { | |
351 | __swab64s(&magic); | |
352 | __swab32s(&reply->brw_status); | |
353 | } | |
354 | ||
5f849bb0 | 355 | CDEBUG(reply->brw_status ? D_WARNING : D_NET, |
c314c319 JS |
356 | "BRW RPC to %s finished with brw_status: %d\n", |
357 | libcfs_id2str(rpc->crpc_dest), reply->brw_status); | |
d7e09d03 | 358 | |
5fd88337 | 359 | if (reply->brw_status) { |
d7e09d03 PT |
360 | atomic_inc(&sn->sn_brw_errors); |
361 | rpc->crpc_status = -(int)reply->brw_status; | |
8a2c2306 | 362 | return; |
d7e09d03 PT |
363 | } |
364 | ||
5252bbfd | 365 | if (reqst->brw_rw == LST_BRW_WRITE) |
8a2c2306 | 366 | return; |
d7e09d03 | 367 | |
5fd88337 | 368 | if (brw_check_bulk(&rpc->crpc_bulk, reqst->brw_flags, magic)) { |
5f849bb0 | 369 | CERROR("Bulk data from %s is corrupted!\n", |
c314c319 | 370 | libcfs_id2str(rpc->crpc_dest)); |
d7e09d03 PT |
371 | atomic_inc(&sn->sn_brw_errors); |
372 | rpc->crpc_status = -EBADMSG; | |
373 | } | |
d7e09d03 PT |
374 | } |
375 | ||
6888871c | 376 | static void |
168c7a13 | 377 | brw_server_rpc_done(struct srpc_server_rpc *rpc) |
d7e09d03 | 378 | { |
eb6e1342 | 379 | struct srpc_bulk *blk = rpc->srpc_bulk; |
d7e09d03 | 380 | |
06ace26e | 381 | if (!blk) |
5252bbfd | 382 | return; |
d7e09d03 | 383 | |
5fd88337 | 384 | if (rpc->srpc_status) |
5f849bb0 | 385 | CERROR("Bulk transfer %s %s has failed: %d\n", |
c314c319 JS |
386 | blk->bk_sink ? "from" : "to", |
387 | libcfs_id2str(rpc->srpc_peer), rpc->srpc_status); | |
d7e09d03 | 388 | else |
5f849bb0 | 389 | CDEBUG(D_NET, "Transferred %d pages bulk data %s %s\n", |
c314c319 JS |
390 | blk->bk_niov, blk->bk_sink ? "from" : "to", |
391 | libcfs_id2str(rpc->srpc_peer)); | |
d7e09d03 PT |
392 | |
393 | sfw_free_pages(rpc); | |
394 | } | |
395 | ||
0c05ef92 | 396 | static int |
168c7a13 | 397 | brw_bulk_ready(struct srpc_server_rpc *rpc, int status) |
d7e09d03 | 398 | { |
74d68011 | 399 | __u64 magic = BRW_MAGIC; |
45d2f4fb JS |
400 | struct srpc_brw_reply *reply = &rpc->srpc_replymsg.msg_body.brw_reply; |
401 | struct srpc_brw_reqst *reqst; | |
fd7a1a32 | 402 | struct srpc_msg *reqstmsg; |
d7e09d03 | 403 | |
06ace26e JS |
404 | LASSERT(rpc->srpc_bulk); |
405 | LASSERT(rpc->srpc_reqstbuf); | |
d7e09d03 PT |
406 | |
407 | reqstmsg = &rpc->srpc_reqstbuf->buf_msg; | |
408 | reqst = &reqstmsg->msg_body.brw_reqst; | |
409 | ||
5fd88337 | 410 | if (status) { |
5f849bb0 | 411 | CERROR("BRW bulk %s failed for RPC from %s: %d\n", |
c314c319 JS |
412 | reqst->brw_rw == LST_BRW_READ ? "READ" : "WRITE", |
413 | libcfs_id2str(rpc->srpc_peer), status); | |
d7e09d03 PT |
414 | return -EIO; |
415 | } | |
416 | ||
417 | if (reqst->brw_rw == LST_BRW_READ) | |
418 | return 0; | |
419 | ||
420 | if (reqstmsg->msg_magic != SRPC_MSG_MAGIC) | |
421 | __swab64s(&magic); | |
422 | ||
5fd88337 | 423 | if (brw_check_bulk(rpc->srpc_bulk, reqst->brw_flags, magic)) { |
5f849bb0 | 424 | CERROR("Bulk data from %s is corrupted!\n", |
c314c319 | 425 | libcfs_id2str(rpc->srpc_peer)); |
d7e09d03 PT |
426 | reply->brw_status = EBADMSG; |
427 | } | |
428 | ||
429 | return 0; | |
430 | } | |
431 | ||
4a1b86dc | 432 | static int |
d7e09d03 PT |
433 | brw_server_handle(struct srpc_server_rpc *rpc) |
434 | { | |
74d68011 | 435 | struct srpc_service *sv = rpc->srpc_scd->scd_svc; |
fd7a1a32 JS |
436 | struct srpc_msg *replymsg = &rpc->srpc_replymsg; |
437 | struct srpc_msg *reqstmsg = &rpc->srpc_reqstbuf->buf_msg; | |
45d2f4fb JS |
438 | struct srpc_brw_reply *reply = &replymsg->msg_body.brw_reply; |
439 | struct srpc_brw_reqst *reqst = &reqstmsg->msg_body.brw_reqst; | |
74d68011 MS |
440 | int npg; |
441 | int rc; | |
d7e09d03 | 442 | |
5f849bb0 | 443 | LASSERT(sv->sv_id == SRPC_SERVICE_BRW); |
d7e09d03 PT |
444 | |
445 | if (reqstmsg->msg_magic != SRPC_MSG_MAGIC) { | |
5f849bb0 | 446 | LASSERT(reqstmsg->msg_magic == __swab32(SRPC_MSG_MAGIC)); |
d7e09d03 PT |
447 | |
448 | __swab32s(&reqst->brw_rw); | |
449 | __swab32s(&reqst->brw_len); | |
450 | __swab32s(&reqst->brw_flags); | |
451 | __swab64s(&reqst->brw_rpyid); | |
452 | __swab64s(&reqst->brw_bulkid); | |
453 | } | |
5f849bb0 | 454 | LASSERT(reqstmsg->msg_type == (__u32)srpc_service2request(sv->sv_id)); |
d7e09d03 PT |
455 | |
456 | reply->brw_status = 0; | |
457 | rpc->srpc_done = brw_server_rpc_done; | |
458 | ||
459 | if ((reqst->brw_rw != LST_BRW_READ && reqst->brw_rw != LST_BRW_WRITE) || | |
460 | (reqst->brw_flags != LST_BRW_CHECK_NONE && | |
461 | reqst->brw_flags != LST_BRW_CHECK_FULL && | |
462 | reqst->brw_flags != LST_BRW_CHECK_SIMPLE)) { | |
463 | reply->brw_status = EINVAL; | |
464 | return 0; | |
465 | } | |
466 | ||
5fd88337 | 467 | if (reqstmsg->msg_ses_feats & ~LST_FEATS_MASK) { |
d7e09d03 PT |
468 | replymsg->msg_ses_feats = LST_FEATS_MASK; |
469 | reply->brw_status = EPROTO; | |
470 | return 0; | |
471 | } | |
472 | ||
5fd88337 | 473 | if (!(reqstmsg->msg_ses_feats & LST_FEAT_BULK_LEN)) { |
d7e09d03 | 474 | /* compat with old version */ |
616387e8 | 475 | if (reqst->brw_len & ~PAGE_MASK) { |
d7e09d03 PT |
476 | reply->brw_status = EINVAL; |
477 | return 0; | |
478 | } | |
09cbfeaf | 479 | npg = reqst->brw_len >> PAGE_SHIFT; |
d7e09d03 PT |
480 | |
481 | } else { | |
09cbfeaf | 482 | npg = (reqst->brw_len + PAGE_SIZE - 1) >> PAGE_SHIFT; |
d7e09d03 PT |
483 | } |
484 | ||
485 | replymsg->msg_ses_feats = reqstmsg->msg_ses_feats; | |
486 | ||
5fd88337 | 487 | if (!reqst->brw_len || npg > LNET_MAX_IOV) { |
d7e09d03 PT |
488 | reply->brw_status = EINVAL; |
489 | return 0; | |
490 | } | |
491 | ||
492 | rc = sfw_alloc_pages(rpc, rpc->srpc_scd->scd_cpt, npg, | |
493 | reqst->brw_len, | |
494 | reqst->brw_rw == LST_BRW_WRITE); | |
5fd88337 | 495 | if (rc) |
d7e09d03 PT |
496 | return rc; |
497 | ||
498 | if (reqst->brw_rw == LST_BRW_READ) | |
499 | brw_fill_bulk(rpc->srpc_bulk, reqst->brw_flags, BRW_MAGIC); | |
500 | else | |
501 | brw_fill_bulk(rpc->srpc_bulk, reqst->brw_flags, BRW_POISON); | |
502 | ||
503 | return 0; | |
504 | } | |
505 | ||
d9c460ea JS |
506 | struct sfw_test_client_ops brw_test_client; |
507 | ||
d7e09d03 PT |
508 | void brw_init_test_client(void) |
509 | { | |
ec436b9a JS |
510 | brw_test_client.tso_init = brw_client_init; |
511 | brw_test_client.tso_fini = brw_client_fini; | |
74d68011 MS |
512 | brw_test_client.tso_prep_rpc = brw_client_prep_rpc; |
513 | brw_test_client.tso_done_rpc = brw_client_done_rpc; | |
d7e09d03 PT |
514 | }; |
515 | ||
682513b8 JS |
516 | struct srpc_service brw_test_service; |
517 | ||
d7e09d03 PT |
518 | void brw_init_test_service(void) |
519 | { | |
ec436b9a JS |
520 | brw_test_service.sv_id = SRPC_SERVICE_BRW; |
521 | brw_test_service.sv_name = "brw_test"; | |
522 | brw_test_service.sv_handler = brw_server_handle; | |
d7e09d03 | 523 | brw_test_service.sv_bulk_ready = brw_bulk_ready; |
ec436b9a | 524 | brw_test_service.sv_wi_total = brw_srv_workitems; |
d7e09d03 | 525 | } |