Whamcloud - gitweb
ee2d0246ae06eeac3b9741e36feedcf7f98ee336
[fs/lustre-release.git] / lnet / selftest / brw_test.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * Copyright (C) 2001, 2002 Cluster File Systems, Inc.
5  *   Author: Isaac Huang <isaac@clusterfs.com>
6  *
7  */
8
9 #include <libcfs/kp30.h>
10 #include "selftest.h"
11
12
13 static int brw_inject_errors = 0;
14 CFS_MODULE_PARM(brw_inject_errors, "i", int, 0644,
15                 "# data errors to inject randomly");
16
17 static void
18 brw_client_fini (sfw_test_instance_t *tsi)
19 {
20         srpc_bulk_t     *bulk;
21         sfw_test_unit_t *tsu;
22
23         list_for_each_entry (tsu, &tsi->tsi_units, tsu_list) {
24                 bulk = tsu->tsu_private;
25                 if (bulk == NULL) continue;
26
27                 srpc_free_bulk(bulk);
28                 tsu->tsu_private = NULL;
29         }
30 }
31
32 int
33 brw_client_init (sfw_test_instance_t *tsi)
34 {
35         test_bulk_req_t  *breq = &tsi->tsi_u.bulk;
36         int               flags = breq->blk_flags;
37         int               npg = breq->blk_npg;
38         srpc_bulk_t      *bulk;
39         sfw_test_unit_t  *tsu;
40
41         if (npg > LNET_MAX_IOV || npg <= 0)
42                 return -EINVAL;
43
44         if (breq->blk_opc != LST_BRW_READ && breq->blk_opc != LST_BRW_WRITE)
45                 return -EINVAL;
46
47         if (flags != LST_BRW_CHECK_NONE &&
48             flags != LST_BRW_CHECK_FULL && flags != LST_BRW_CHECK_SIMPLE)
49                 return -EINVAL;
50
51         list_for_each_entry (tsu, &tsi->tsi_units, tsu_list) {
52                 bulk = srpc_alloc_bulk(npg, breq->blk_opc == LST_BRW_READ);
53                 if (bulk == NULL) {
54                         brw_client_fini(tsi);
55                         return -ENOMEM;
56                 }
57
58                 tsu->tsu_private = bulk;
59         }
60
61         return 0;
62 }
63
64 #define BRW_POISON      0xbeefbeefbeefbeefULL
65 #define BRW_MAGIC       0xeeb0eeb1eeb2eeb3ULL
66 #define BRW_MSIZE       sizeof(__u64)
67
68 int
69 brw_inject_one_error (void)
70 {
71         struct timeval tv;
72
73         if (brw_inject_errors <= 0) return 0;
74
75 #ifndef __KERNEL__
76         gettimeofday(&tv, NULL);
77 #else
78         do_gettimeofday(&tv);
79 #endif
80
81         if ((tv.tv_usec & 1) == 0) return 0;
82
83         return brw_inject_errors--;
84 }
85
86 void
87 brw_fill_page (cfs_page_t *pg, int pattern, __u64 magic)
88 {
89         char *addr = cfs_page_address(pg);
90         int   i;
91
92         LASSERT (addr != NULL);
93
94         if (pattern == LST_BRW_CHECK_NONE)
95                 return;
96
97         if (magic == BRW_MAGIC)
98                 magic += brw_inject_one_error();
99
100         if (pattern == LST_BRW_CHECK_SIMPLE) {
101                 memcpy(addr, &magic, BRW_MSIZE);
102                 addr += CFS_PAGE_SIZE - BRW_MSIZE;
103                 memcpy(addr, &magic, BRW_MSIZE);
104                 return;
105         }
106
107         if (pattern == LST_BRW_CHECK_FULL) {
108                 for (i = 0; i < CFS_PAGE_SIZE / BRW_MSIZE; i++)
109                         memcpy(addr + i * BRW_MSIZE, &magic, BRW_MSIZE);
110                 return;
111         }
112
113         LBUG ();
114         return;
115 }
116
117 int
118 brw_check_page (cfs_page_t *pg, int pattern, __u64 magic)
119 {
120         char  *addr = cfs_page_address(pg);
121         __u64  data;
122         int    i;
123
124         LASSERT (addr != NULL);
125
126         if (pattern == LST_BRW_CHECK_NONE)
127                 return 0;
128
129         if (pattern == LST_BRW_CHECK_SIMPLE) {
130                 data = *((__u64 *) addr);
131                 if (data != magic) goto bad_data;
132
133                 addr += CFS_PAGE_SIZE - BRW_MSIZE;
134                 data = *((__u64 *) addr);
135                 if (data != magic) goto bad_data;
136
137                 return 0;
138         }
139
140         if (pattern == LST_BRW_CHECK_FULL) {
141                 for (i = 0; i < CFS_PAGE_SIZE / BRW_MSIZE; i++) {
142                         data = *(((__u64 *) addr) + i);
143                         if (data != magic) goto bad_data;
144                 }
145
146                 return 0;
147         }
148
149         LBUG ();
150
151 bad_data:
152         CERROR ("Bad data in page %p: "LPU64", "LPU64" expected\n",
153                 pg, data, magic);
154         return 1;
155 }
156
157 void
158 brw_fill_bulk (srpc_bulk_t *bk, int pattern, __u64 magic)
159 {
160         int         i;
161         cfs_page_t *pg;
162
163         for (i = 0; i < bk->bk_niov; i++) {
164 #ifdef __KERNEL__
165                 pg = bk->bk_iovs[i].kiov_page;
166 #else
167                 pg = bk->bk_pages[i];
168 #endif
169                 brw_fill_page(pg, pattern, magic);
170         }
171 }
172
173 int
174 brw_check_bulk (srpc_bulk_t *bk, int pattern, __u64 magic)
175 {
176         int         i;
177         cfs_page_t *pg;
178
179         for (i = 0; i < bk->bk_niov; i++) {
180 #ifdef __KERNEL__
181                 pg = bk->bk_iovs[i].kiov_page;
182 #else
183                 pg = bk->bk_pages[i];
184 #endif
185                 if (brw_check_page(pg, pattern, magic) != 0) {
186                         CERROR ("Bulk page %p (%d/%d) is corrupted!\n",
187                                 pg, i, bk->bk_niov);
188                         return 1;
189                 }
190         }
191
192         return 0;
193 }
194
195 static int
196 brw_client_prep_rpc (sfw_test_unit_t *tsu,
197                      lnet_process_id_t dest, srpc_client_rpc_t **rpcpp)
198 {
199         srpc_bulk_t         *bulk = tsu->tsu_private;
200         sfw_test_instance_t *tsi = tsu->tsu_instance;
201         test_bulk_req_t     *breq = &tsi->tsi_u.bulk;
202         int                  npg = breq->blk_npg;
203         int                  flags = breq->blk_flags;
204         srpc_client_rpc_t   *rpc;
205         srpc_brw_reqst_t    *req;
206         int                  rc;
207
208         LASSERT (bulk != NULL);
209         LASSERT (bulk->bk_niov == npg);
210
211         rc = sfw_create_test_rpc(tsu, dest, npg, npg * CFS_PAGE_SIZE, &rpc);
212         if (rc != 0) return rc;
213
214         memcpy(&rpc->crpc_bulk, bulk, offsetof(srpc_bulk_t, bk_iovs[npg]));
215         if (breq->blk_opc == LST_BRW_WRITE)
216                 brw_fill_bulk(&rpc->crpc_bulk, flags, BRW_MAGIC);
217         else
218                 brw_fill_bulk(&rpc->crpc_bulk, flags, BRW_POISON);
219
220         req = &rpc->crpc_reqstmsg.msg_body.brw_reqst;
221         req->brw_flags = flags;
222         req->brw_rw    = breq->blk_opc; 
223         req->brw_len   = npg * CFS_PAGE_SIZE;
224
225         *rpcpp = rpc;
226         return 0;
227 }
228
229 static void
230 brw_client_done_rpc (sfw_test_unit_t *tsu, srpc_client_rpc_t *rpc)
231 {
232         __u64             magic = BRW_MAGIC;
233         srpc_msg_t       *msg = &rpc->crpc_replymsg;
234         srpc_brw_reply_t *reply = &msg->msg_body.brw_reply;
235         srpc_brw_reqst_t *reqst = &rpc->crpc_reqstmsg.msg_body.brw_reqst;
236         sfw_session_t    *sn = tsu->tsu_instance->tsi_batch->bat_session;
237
238         LASSERT (sn != NULL);
239
240 #ifndef __KERNEL__
241         rpc->crpc_bulk.bk_pages = NULL;
242 #endif
243
244         if (rpc->crpc_status != 0) {
245                 CERROR ("BRW RPC to %s failed with %d\n",
246                         libcfs_id2str(rpc->crpc_dest), rpc->crpc_status);
247                 return;
248         }
249
250         if (msg->msg_magic != SRPC_MSG_MAGIC) {
251                 __swab64s(&magic);
252                 __swab32s(&reply->brw_status);
253         }
254
255         if (tsu->tsu_error == 0)
256                 tsu->tsu_error = -reply->brw_status;
257
258         CDEBUG (reply->brw_status ? D_WARNING : D_NET,
259                 "BRW RPC to %s finished with brw_status: %d\n",
260                 libcfs_id2str(rpc->crpc_dest), reply->brw_status);
261
262         if (reply->brw_status != 0) {
263                 atomic_inc(&sn->sn_brw_errors);
264                 return;
265         }
266
267         if (reqst->brw_rw == LST_BRW_WRITE) return;
268
269         if (brw_check_bulk(&rpc->crpc_bulk, reqst->brw_flags, magic) != 0) {
270                 CERROR ("Bulk data from %s is corrupted!\n",
271                         libcfs_id2str(rpc->crpc_dest));
272                 tsu->tsu_error = -EBADMSG;
273                 atomic_inc(&sn->sn_brw_errors);
274         }
275
276         return;
277 }
278
279 void
280 brw_server_rpc_done (srpc_server_rpc_t *rpc)
281 {
282         srpc_bulk_t *blk = rpc->srpc_bulk;
283
284         if (blk == NULL) return;
285
286         if (rpc->srpc_status != 0)
287                 CERROR ("Bulk transfer %s %s has failed: %d\n",
288                         blk->bk_sink ? "from" : "to",
289                         libcfs_id2str(rpc->srpc_peer), rpc->srpc_status);
290         else
291                 CDEBUG (D_NET, "Transfered %d pages bulk data %s %s\n",
292                         blk->bk_niov, blk->bk_sink ? "from" : "to",
293                         libcfs_id2str(rpc->srpc_peer));
294
295         sfw_free_pages(rpc);
296 }
297
298 int
299 brw_bulk_ready (srpc_server_rpc_t *rpc, int status)
300 {
301         __u64             magic = BRW_MAGIC;
302         srpc_brw_reply_t *reply = &rpc->srpc_replymsg.msg_body.brw_reply;
303         srpc_brw_reqst_t *reqst;
304         srpc_msg_t       *reqstmsg;
305
306         LASSERT (rpc->srpc_bulk != NULL);
307         LASSERT (rpc->srpc_reqstbuf != NULL);
308
309         reqstmsg = &rpc->srpc_reqstbuf->buf_msg;
310         reqst = &reqstmsg->msg_body.brw_reqst;
311
312         if (status != 0) {
313                 CERROR ("BRW bulk %s failed for RPC from %s: %d\n",
314                         reqst->brw_rw == LST_BRW_READ ? "READ" : "WRITE",
315                         libcfs_id2str(rpc->srpc_peer), status);
316                 return -EIO;
317         }
318
319         if (reqst->brw_rw == LST_BRW_READ)
320                 return 0;
321
322         if (reqstmsg->msg_magic != SRPC_MSG_MAGIC)
323                 __swab64s(&magic);
324
325         if (brw_check_bulk(rpc->srpc_bulk, reqst->brw_flags, magic) != 0) {
326                 CERROR ("Bulk data from %s is corrupted!\n",
327                         libcfs_id2str(rpc->srpc_peer));
328                 reply->brw_status = EBADMSG;
329         }
330
331         return 0;
332 }
333
334 int
335 brw_server_handle (srpc_server_rpc_t *rpc)
336 {
337         srpc_service_t   *sv = rpc->srpc_service;
338         srpc_msg_t       *replymsg = &rpc->srpc_replymsg;
339         srpc_msg_t       *reqstmsg = &rpc->srpc_reqstbuf->buf_msg;
340         srpc_brw_reply_t *reply = &replymsg->msg_body.brw_reply;
341         srpc_brw_reqst_t *reqst = &reqstmsg->msg_body.brw_reqst;
342         int               rc;
343
344         LASSERT (sv->sv_id == SRPC_SERVICE_BRW);
345
346         if (reqstmsg->msg_magic != SRPC_MSG_MAGIC) {
347                 LASSERT (reqstmsg->msg_magic == __swab32(SRPC_MSG_MAGIC));
348
349                 __swab32s(&reqstmsg->msg_type);
350                 __swab32s(&reqst->brw_rw);
351                 __swab32s(&reqst->brw_len);
352                 __swab32s(&reqst->brw_flags);
353                 __swab64s(&reqst->brw_rpyid);
354                 __swab64s(&reqst->brw_bulkid);
355         }
356         LASSERT (reqstmsg->msg_type == srpc_service2request(sv->sv_id));
357
358         rpc->srpc_done = brw_server_rpc_done;
359
360         if ((reqst->brw_rw != LST_BRW_READ && reqst->brw_rw != LST_BRW_WRITE) ||
361             reqst->brw_len == 0 || (reqst->brw_len & ~CFS_PAGE_MASK) != 0 ||
362             reqst->brw_len / CFS_PAGE_SIZE > LNET_MAX_IOV ||
363             (reqst->brw_flags != LST_BRW_CHECK_NONE &&
364              reqst->brw_flags != LST_BRW_CHECK_FULL &&
365              reqst->brw_flags != LST_BRW_CHECK_SIMPLE)) {
366                 reply->brw_status = EINVAL;
367                 return 0;
368         }
369         
370         reply->brw_status = 0;
371         rc = sfw_alloc_pages(rpc, reqst->brw_len / CFS_PAGE_SIZE,
372                              reqst->brw_rw == LST_BRW_WRITE);
373         if (rc != 0) return rc;
374
375         if (reqst->brw_rw == LST_BRW_READ)
376                 brw_fill_bulk(rpc->srpc_bulk, reqst->brw_flags, BRW_MAGIC);
377         else
378                 brw_fill_bulk(rpc->srpc_bulk, reqst->brw_flags, BRW_POISON);
379
380         return 0;
381 }
382
383 sfw_test_client_ops_t brw_test_client =
384 {
385         .tso_init      = brw_client_init,
386         .tso_fini      = brw_client_fini,
387         .tso_prep_rpc  = brw_client_prep_rpc,
388         .tso_done_rpc  = brw_client_done_rpc,
389 };
390
391 srpc_service_t brw_test_service =
392 {
393         .sv_name       = "brw test",
394         .sv_handler    = brw_server_handle,
395         .sv_bulk_ready = brw_bulk_ready,
396         .sv_id         = SRPC_SERVICE_BRW,
397 };