4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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.
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).
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
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
27 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
28 * Use is subject to license terms.
30 * Copyright (c) 2011, 2012, Intel Corporation.
33 * This file is part of Lustre, http://www.lustre.org/
34 * Lustre is a trademark of Sun Microsystems, Inc.
36 * lnet/selftest/brw_test.c
38 * Author: Isaac Huang <isaac@clusterfs.com>
43 static int brw_srv_workitems
= SFW_TEST_WI_MAX
;
44 CFS_MODULE_PARM(brw_srv_workitems
, "i", int, 0644, "# BRW server workitems");
46 static int brw_inject_errors
;
47 CFS_MODULE_PARM(brw_inject_errors
, "i", int, 0644,
48 "# data errors to inject randomly, zero by default");
51 brw_client_fini(sfw_test_instance_t
*tsi
)
56 LASSERT(tsi
->tsi_is_client
);
58 list_for_each_entry(tsu
, &tsi
->tsi_units
, tsu_list
) {
59 bulk
= tsu
->tsu_private
;
64 tsu
->tsu_private
= NULL
;
69 brw_client_init(sfw_test_instance_t
*tsi
)
71 sfw_session_t
*sn
= tsi
->tsi_batch
->bat_session
;
80 LASSERT(tsi
->tsi_is_client
);
82 if ((sn
->sn_features
& LST_FEAT_BULK_LEN
) == 0) {
83 test_bulk_req_t
*breq
= &tsi
->tsi_u
.bulk_v0
;
86 flags
= breq
->blk_flags
;
88 /* NB: this is not going to work for variable page size,
89 * but we have to keep it for compatibility */
90 len
= npg
* PAGE_CACHE_SIZE
;
93 test_bulk_req_v1_t
*breq
= &tsi
->tsi_u
.bulk_v1
;
95 /* I should never get this step if it's unknown feature
96 * because make_session will reject unknown feature */
97 LASSERT((sn
->sn_features
& ~LST_FEATS_MASK
) == 0);
100 flags
= breq
->blk_flags
;
102 npg
= (len
+ PAGE_CACHE_SIZE
- 1) >> PAGE_CACHE_SHIFT
;
105 if (npg
> LNET_MAX_IOV
|| npg
<= 0)
108 if (opc
!= LST_BRW_READ
&& opc
!= LST_BRW_WRITE
)
111 if (flags
!= LST_BRW_CHECK_NONE
&&
112 flags
!= LST_BRW_CHECK_FULL
&& flags
!= LST_BRW_CHECK_SIMPLE
)
115 list_for_each_entry(tsu
, &tsi
->tsi_units
, tsu_list
) {
116 bulk
= srpc_alloc_bulk(lnet_cpt_of_nid(tsu
->tsu_dest
.nid
),
117 npg
, len
, opc
== LST_BRW_READ
);
119 brw_client_fini(tsi
);
123 tsu
->tsu_private
= bulk
;
129 #define BRW_POISON 0xbeefbeefbeefbeefULL
130 #define BRW_MAGIC 0xeeb0eeb1eeb2eeb3ULL
131 #define BRW_MSIZE sizeof(__u64)
134 brw_inject_one_error(void)
138 if (brw_inject_errors
<= 0)
141 do_gettimeofday(&tv
);
143 if ((tv
.tv_usec
& 1) == 0)
146 return brw_inject_errors
--;
150 brw_fill_page(struct page
*pg
, int pattern
, __u64 magic
)
152 char *addr
= page_address(pg
);
155 LASSERT(addr
!= NULL
);
157 if (pattern
== LST_BRW_CHECK_NONE
)
160 if (magic
== BRW_MAGIC
)
161 magic
+= brw_inject_one_error();
163 if (pattern
== LST_BRW_CHECK_SIMPLE
) {
164 memcpy(addr
, &magic
, BRW_MSIZE
);
165 addr
+= PAGE_CACHE_SIZE
- BRW_MSIZE
;
166 memcpy(addr
, &magic
, BRW_MSIZE
);
170 if (pattern
== LST_BRW_CHECK_FULL
) {
171 for (i
= 0; i
< PAGE_CACHE_SIZE
/ BRW_MSIZE
; i
++)
172 memcpy(addr
+ i
* BRW_MSIZE
, &magic
, BRW_MSIZE
);
181 brw_check_page(struct page
*pg
, int pattern
, __u64 magic
)
183 char *addr
= page_address(pg
);
184 __u64 data
= 0; /* make compiler happy */
187 LASSERT(addr
!= NULL
);
189 if (pattern
== LST_BRW_CHECK_NONE
)
192 if (pattern
== LST_BRW_CHECK_SIMPLE
) {
193 data
= *((__u64
*) addr
);
197 addr
+= PAGE_CACHE_SIZE
- BRW_MSIZE
;
198 data
= *((__u64
*) addr
);
205 if (pattern
== LST_BRW_CHECK_FULL
) {
206 for (i
= 0; i
< PAGE_CACHE_SIZE
/ BRW_MSIZE
; i
++) {
207 data
= *(((__u64
*) addr
) + i
);
218 CERROR("Bad data in page %p: "LPX64
", "LPX64
" expected\n",
224 brw_fill_bulk(srpc_bulk_t
*bk
, int pattern
, __u64 magic
)
229 for (i
= 0; i
< bk
->bk_niov
; i
++) {
230 pg
= bk
->bk_iovs
[i
].kiov_page
;
231 brw_fill_page(pg
, pattern
, magic
);
236 brw_check_bulk(srpc_bulk_t
*bk
, int pattern
, __u64 magic
)
241 for (i
= 0; i
< bk
->bk_niov
; i
++) {
242 pg
= bk
->bk_iovs
[i
].kiov_page
;
243 if (brw_check_page(pg
, pattern
, magic
) != 0) {
244 CERROR("Bulk page %p (%d/%d) is corrupted!\n",
254 brw_client_prep_rpc(sfw_test_unit_t
*tsu
,
255 lnet_process_id_t dest
, srpc_client_rpc_t
**rpcpp
)
257 srpc_bulk_t
*bulk
= tsu
->tsu_private
;
258 sfw_test_instance_t
*tsi
= tsu
->tsu_instance
;
259 sfw_session_t
*sn
= tsi
->tsi_batch
->bat_session
;
260 srpc_client_rpc_t
*rpc
;
261 srpc_brw_reqst_t
*req
;
269 LASSERT(bulk
!= NULL
);
271 if ((sn
->sn_features
& LST_FEAT_BULK_LEN
) == 0) {
272 test_bulk_req_t
*breq
= &tsi
->tsi_u
.bulk_v0
;
275 flags
= breq
->blk_flags
;
277 len
= npg
* PAGE_CACHE_SIZE
;
280 test_bulk_req_v1_t
*breq
= &tsi
->tsi_u
.bulk_v1
;
282 /* I should never get this step if it's unknown feature
283 * because make_session will reject unknown feature */
284 LASSERT((sn
->sn_features
& ~LST_FEATS_MASK
) == 0);
287 flags
= breq
->blk_flags
;
289 npg
= (len
+ PAGE_CACHE_SIZE
- 1) >> PAGE_CACHE_SHIFT
;
292 rc
= sfw_create_test_rpc(tsu
, dest
, sn
->sn_features
, npg
, len
, &rpc
);
296 memcpy(&rpc
->crpc_bulk
, bulk
, offsetof(srpc_bulk_t
, bk_iovs
[npg
]));
297 if (opc
== LST_BRW_WRITE
)
298 brw_fill_bulk(&rpc
->crpc_bulk
, flags
, BRW_MAGIC
);
300 brw_fill_bulk(&rpc
->crpc_bulk
, flags
, BRW_POISON
);
302 req
= &rpc
->crpc_reqstmsg
.msg_body
.brw_reqst
;
303 req
->brw_flags
= flags
;
312 brw_client_done_rpc(sfw_test_unit_t
*tsu
, srpc_client_rpc_t
*rpc
)
314 __u64 magic
= BRW_MAGIC
;
315 sfw_test_instance_t
*tsi
= tsu
->tsu_instance
;
316 sfw_session_t
*sn
= tsi
->tsi_batch
->bat_session
;
317 srpc_msg_t
*msg
= &rpc
->crpc_replymsg
;
318 srpc_brw_reply_t
*reply
= &msg
->msg_body
.brw_reply
;
319 srpc_brw_reqst_t
*reqst
= &rpc
->crpc_reqstmsg
.msg_body
.brw_reqst
;
323 if (rpc
->crpc_status
!= 0) {
324 CERROR("BRW RPC to %s failed with %d\n",
325 libcfs_id2str(rpc
->crpc_dest
), rpc
->crpc_status
);
326 if (!tsi
->tsi_stopping
) /* rpc could have been aborted */
327 atomic_inc(&sn
->sn_brw_errors
);
331 if (msg
->msg_magic
!= SRPC_MSG_MAGIC
) {
333 __swab32s(&reply
->brw_status
);
336 CDEBUG(reply
->brw_status
? D_WARNING
: D_NET
,
337 "BRW RPC to %s finished with brw_status: %d\n",
338 libcfs_id2str(rpc
->crpc_dest
), reply
->brw_status
);
340 if (reply
->brw_status
!= 0) {
341 atomic_inc(&sn
->sn_brw_errors
);
342 rpc
->crpc_status
= -(int)reply
->brw_status
;
346 if (reqst
->brw_rw
== LST_BRW_WRITE
)
349 if (brw_check_bulk(&rpc
->crpc_bulk
, reqst
->brw_flags
, magic
) != 0) {
350 CERROR("Bulk data from %s is corrupted!\n",
351 libcfs_id2str(rpc
->crpc_dest
));
352 atomic_inc(&sn
->sn_brw_errors
);
353 rpc
->crpc_status
= -EBADMSG
;
361 brw_server_rpc_done(srpc_server_rpc_t
*rpc
)
363 srpc_bulk_t
*blk
= rpc
->srpc_bulk
;
368 if (rpc
->srpc_status
!= 0)
369 CERROR("Bulk transfer %s %s has failed: %d\n",
370 blk
->bk_sink
? "from" : "to",
371 libcfs_id2str(rpc
->srpc_peer
), rpc
->srpc_status
);
373 CDEBUG(D_NET
, "Transferred %d pages bulk data %s %s\n",
374 blk
->bk_niov
, blk
->bk_sink
? "from" : "to",
375 libcfs_id2str(rpc
->srpc_peer
));
381 brw_bulk_ready(srpc_server_rpc_t
*rpc
, int status
)
383 __u64 magic
= BRW_MAGIC
;
384 srpc_brw_reply_t
*reply
= &rpc
->srpc_replymsg
.msg_body
.brw_reply
;
385 srpc_brw_reqst_t
*reqst
;
386 srpc_msg_t
*reqstmsg
;
388 LASSERT(rpc
->srpc_bulk
!= NULL
);
389 LASSERT(rpc
->srpc_reqstbuf
!= NULL
);
391 reqstmsg
= &rpc
->srpc_reqstbuf
->buf_msg
;
392 reqst
= &reqstmsg
->msg_body
.brw_reqst
;
395 CERROR("BRW bulk %s failed for RPC from %s: %d\n",
396 reqst
->brw_rw
== LST_BRW_READ
? "READ" : "WRITE",
397 libcfs_id2str(rpc
->srpc_peer
), status
);
401 if (reqst
->brw_rw
== LST_BRW_READ
)
404 if (reqstmsg
->msg_magic
!= SRPC_MSG_MAGIC
)
407 if (brw_check_bulk(rpc
->srpc_bulk
, reqst
->brw_flags
, magic
) != 0) {
408 CERROR("Bulk data from %s is corrupted!\n",
409 libcfs_id2str(rpc
->srpc_peer
));
410 reply
->brw_status
= EBADMSG
;
417 brw_server_handle(struct srpc_server_rpc
*rpc
)
419 struct srpc_service
*sv
= rpc
->srpc_scd
->scd_svc
;
420 srpc_msg_t
*replymsg
= &rpc
->srpc_replymsg
;
421 srpc_msg_t
*reqstmsg
= &rpc
->srpc_reqstbuf
->buf_msg
;
422 srpc_brw_reply_t
*reply
= &replymsg
->msg_body
.brw_reply
;
423 srpc_brw_reqst_t
*reqst
= &reqstmsg
->msg_body
.brw_reqst
;
427 LASSERT(sv
->sv_id
== SRPC_SERVICE_BRW
);
429 if (reqstmsg
->msg_magic
!= SRPC_MSG_MAGIC
) {
430 LASSERT(reqstmsg
->msg_magic
== __swab32(SRPC_MSG_MAGIC
));
432 __swab32s(&reqst
->brw_rw
);
433 __swab32s(&reqst
->brw_len
);
434 __swab32s(&reqst
->brw_flags
);
435 __swab64s(&reqst
->brw_rpyid
);
436 __swab64s(&reqst
->brw_bulkid
);
438 LASSERT(reqstmsg
->msg_type
== (__u32
)srpc_service2request(sv
->sv_id
));
440 reply
->brw_status
= 0;
441 rpc
->srpc_done
= brw_server_rpc_done
;
443 if ((reqst
->brw_rw
!= LST_BRW_READ
&& reqst
->brw_rw
!= LST_BRW_WRITE
) ||
444 (reqst
->brw_flags
!= LST_BRW_CHECK_NONE
&&
445 reqst
->brw_flags
!= LST_BRW_CHECK_FULL
&&
446 reqst
->brw_flags
!= LST_BRW_CHECK_SIMPLE
)) {
447 reply
->brw_status
= EINVAL
;
451 if ((reqstmsg
->msg_ses_feats
& ~LST_FEATS_MASK
) != 0) {
452 replymsg
->msg_ses_feats
= LST_FEATS_MASK
;
453 reply
->brw_status
= EPROTO
;
457 if ((reqstmsg
->msg_ses_feats
& LST_FEAT_BULK_LEN
) == 0) {
458 /* compat with old version */
459 if ((reqst
->brw_len
& ~CFS_PAGE_MASK
) != 0) {
460 reply
->brw_status
= EINVAL
;
463 npg
= reqst
->brw_len
>> PAGE_CACHE_SHIFT
;
466 npg
= (reqst
->brw_len
+ PAGE_CACHE_SIZE
- 1) >> PAGE_CACHE_SHIFT
;
469 replymsg
->msg_ses_feats
= reqstmsg
->msg_ses_feats
;
471 if (reqst
->brw_len
== 0 || npg
> LNET_MAX_IOV
) {
472 reply
->brw_status
= EINVAL
;
476 rc
= sfw_alloc_pages(rpc
, rpc
->srpc_scd
->scd_cpt
, npg
,
478 reqst
->brw_rw
== LST_BRW_WRITE
);
482 if (reqst
->brw_rw
== LST_BRW_READ
)
483 brw_fill_bulk(rpc
->srpc_bulk
, reqst
->brw_flags
, BRW_MAGIC
);
485 brw_fill_bulk(rpc
->srpc_bulk
, reqst
->brw_flags
, BRW_POISON
);
490 sfw_test_client_ops_t brw_test_client
;
491 void brw_init_test_client(void)
493 brw_test_client
.tso_init
= brw_client_init
;
494 brw_test_client
.tso_fini
= brw_client_fini
;
495 brw_test_client
.tso_prep_rpc
= brw_client_prep_rpc
;
496 brw_test_client
.tso_done_rpc
= brw_client_done_rpc
;
499 srpc_service_t brw_test_service
;
500 void brw_init_test_service(void)
503 brw_test_service
.sv_id
= SRPC_SERVICE_BRW
;
504 brw_test_service
.sv_name
= "brw_test";
505 brw_test_service
.sv_handler
= brw_server_handle
;
506 brw_test_service
.sv_bulk_ready
= brw_bulk_ready
;
507 brw_test_service
.sv_wi_total
= brw_srv_workitems
;