Whamcloud - gitweb
da9d15019cb7b21043fd48f26c1f35c0c4a3bd75
[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                 LASSERT (bk->bk_pages != NULL);
168                 pg = bk->bk_pages[i];
169 #endif
170                 brw_fill_page(pg, pattern, magic);
171         }
172 }
173
174 int
175 brw_check_bulk (srpc_bulk_t *bk, int pattern, __u64 magic)
176 {
177         int         i;
178         cfs_page_t *pg;
179
180         for (i = 0; i < bk->bk_niov; i++) {
181 #ifdef __KERNEL__
182                 pg = bk->bk_iovs[i].kiov_page;
183 #else
184                 LASSERT (bk->bk_pages != NULL);
185                 pg = bk->bk_pages[i];
186 #endif
187                 if (brw_check_page(pg, pattern, magic) != 0) {
188                         CERROR ("Bulk page %p (%d/%d) is corrupted!\n",
189                                 pg, i, bk->bk_niov);
190                         return 1;
191                 }
192         }
193
194         return 0;
195 }
196
197 static int
198 brw_client_prep_rpc (sfw_test_unit_t *tsu,
199                      lnet_process_id_t dest, srpc_client_rpc_t **rpcpp)
200 {
201         srpc_bulk_t         *bulk = tsu->tsu_private;
202         sfw_test_instance_t *tsi = tsu->tsu_instance;
203         test_bulk_req_t     *breq = &tsi->tsi_u.bulk;
204         int                  npg = breq->blk_npg;
205         int                  flags = breq->blk_flags;
206         srpc_client_rpc_t   *rpc;
207         srpc_brw_reqst_t    *req;
208         int                  rc;
209
210         LASSERT (bulk != NULL);
211         LASSERT (bulk->bk_niov == npg);
212
213         rc = sfw_create_test_rpc(tsu, dest, npg, npg * CFS_PAGE_SIZE, &rpc);
214         if (rc != 0) return rc;
215
216         memcpy(&rpc->crpc_bulk, bulk, offsetof(srpc_bulk_t, bk_iovs[npg]));
217         if (breq->blk_opc == LST_BRW_WRITE)
218                 brw_fill_bulk(&rpc->crpc_bulk, flags, BRW_MAGIC);
219         else
220                 brw_fill_bulk(&rpc->crpc_bulk, flags, BRW_POISON);
221
222         req = &rpc->crpc_reqstmsg.msg_body.brw_reqst;
223         req->brw_flags = flags;
224         req->brw_rw    = breq->blk_opc; 
225         req->brw_len   = npg * CFS_PAGE_SIZE;
226
227         *rpcpp = rpc;
228         return 0;
229 }
230
231 static void
232 brw_client_done_rpc (sfw_test_unit_t *tsu, srpc_client_rpc_t *rpc)
233 {
234         __u64             magic = BRW_MAGIC;
235         srpc_msg_t       *msg = &rpc->crpc_replymsg;
236         srpc_brw_reply_t *reply = &msg->msg_body.brw_reply;
237         srpc_brw_reqst_t *reqst = &rpc->crpc_reqstmsg.msg_body.brw_reqst;
238         sfw_session_t    *sn = tsu->tsu_instance->tsi_batch->bat_session;
239
240         LASSERT (sn != NULL);
241
242         if (rpc->crpc_status != 0) {
243                 CERROR ("BRW RPC to %s failed with %d\n",
244                         libcfs_id2str(rpc->crpc_dest), rpc->crpc_status);
245                 goto out;
246         }
247
248         if (msg->msg_magic != SRPC_MSG_MAGIC) {
249                 __swab64s(&magic);
250                 __swab32s(&reply->brw_status);
251         }
252
253         if (tsu->tsu_error == 0)
254                 tsu->tsu_error = -reply->brw_status;
255
256         CDEBUG (reply->brw_status ? D_WARNING : D_NET,
257                 "BRW RPC to %s finished with brw_status: %d\n",
258                 libcfs_id2str(rpc->crpc_dest), reply->brw_status);
259
260         if (reply->brw_status != 0) {
261                 atomic_inc(&sn->sn_brw_errors);
262                 goto out;
263         }
264
265         if (reqst->brw_rw == LST_BRW_WRITE) goto out;
266
267         if (brw_check_bulk(&rpc->crpc_bulk, reqst->brw_flags, magic) != 0) {
268                 CERROR ("Bulk data from %s is corrupted!\n",
269                         libcfs_id2str(rpc->crpc_dest));
270                 tsu->tsu_error = -EBADMSG;
271                 atomic_inc(&sn->sn_brw_errors);
272         }
273
274 out:
275 #ifndef __KERNEL__
276         rpc->crpc_bulk.bk_pages = NULL;
277 #endif
278         return;
279 }
280
281 void
282 brw_server_rpc_done (srpc_server_rpc_t *rpc)
283 {
284         srpc_bulk_t *blk = rpc->srpc_bulk;
285
286         if (blk == NULL) return;
287
288         if (rpc->srpc_status != 0)
289                 CERROR ("Bulk transfer %s %s has failed: %d\n",
290                         blk->bk_sink ? "from" : "to",
291                         libcfs_id2str(rpc->srpc_peer), rpc->srpc_status);
292         else
293                 CDEBUG (D_NET, "Transfered %d pages bulk data %s %s\n",
294                         blk->bk_niov, blk->bk_sink ? "from" : "to",
295                         libcfs_id2str(rpc->srpc_peer));
296
297         sfw_free_pages(rpc);
298 }
299
300 int
301 brw_bulk_ready (srpc_server_rpc_t *rpc, int status)
302 {
303         __u64             magic = BRW_MAGIC;
304         srpc_brw_reply_t *reply = &rpc->srpc_replymsg.msg_body.brw_reply;
305         srpc_brw_reqst_t *reqst;
306         srpc_msg_t       *reqstmsg;
307
308         LASSERT (rpc->srpc_bulk != NULL);
309         LASSERT (rpc->srpc_reqstbuf != NULL);
310
311         reqstmsg = &rpc->srpc_reqstbuf->buf_msg;
312         reqst = &reqstmsg->msg_body.brw_reqst;
313
314         if (status != 0) {
315                 CERROR ("BRW bulk %s failed for RPC from %s: %d\n",
316                         reqst->brw_rw == LST_BRW_READ ? "READ" : "WRITE",
317                         libcfs_id2str(rpc->srpc_peer), status);
318                 return -EIO;
319         }
320
321         if (reqst->brw_rw == LST_BRW_READ)
322                 return 0;
323
324         if (reqstmsg->msg_magic != SRPC_MSG_MAGIC)
325                 __swab64s(&magic);
326
327         if (brw_check_bulk(rpc->srpc_bulk, reqst->brw_flags, magic) != 0) {
328                 CERROR ("Bulk data from %s is corrupted!\n",
329                         libcfs_id2str(rpc->srpc_peer));
330                 reply->brw_status = EBADMSG;
331         }
332
333         return 0;
334 }
335
336 int
337 brw_server_handle (srpc_server_rpc_t *rpc)
338 {
339         srpc_service_t   *sv = rpc->srpc_service;
340         srpc_msg_t       *replymsg = &rpc->srpc_replymsg;
341         srpc_msg_t       *reqstmsg = &rpc->srpc_reqstbuf->buf_msg;
342         srpc_brw_reply_t *reply = &replymsg->msg_body.brw_reply;
343         srpc_brw_reqst_t *reqst = &reqstmsg->msg_body.brw_reqst;
344         int               rc;
345
346         LASSERT (sv->sv_id == SRPC_SERVICE_BRW);
347
348         if (reqstmsg->msg_magic != SRPC_MSG_MAGIC) {
349                 LASSERT (reqstmsg->msg_magic == __swab32(SRPC_MSG_MAGIC));
350
351                 __swab32s(&reqstmsg->msg_type);
352                 __swab32s(&reqst->brw_rw);
353                 __swab32s(&reqst->brw_len);
354                 __swab32s(&reqst->brw_flags);
355                 __swab64s(&reqst->brw_rpyid);
356                 __swab64s(&reqst->brw_bulkid);
357         }
358         LASSERT (reqstmsg->msg_type == srpc_service2request(sv->sv_id));
359
360         rpc->srpc_done = brw_server_rpc_done;
361
362         if ((reqst->brw_rw != LST_BRW_READ && reqst->brw_rw != LST_BRW_WRITE) ||
363             reqst->brw_len == 0 || (reqst->brw_len & ~CFS_PAGE_MASK) != 0 ||
364             reqst->brw_len / CFS_PAGE_SIZE > LNET_MAX_IOV ||
365             (reqst->brw_flags != LST_BRW_CHECK_NONE &&
366              reqst->brw_flags != LST_BRW_CHECK_FULL &&
367              reqst->brw_flags != LST_BRW_CHECK_SIMPLE)) {
368                 reply->brw_status = EINVAL;
369                 return 0;
370         }
371         
372         reply->brw_status = 0;
373         rc = sfw_alloc_pages(rpc, reqst->brw_len / CFS_PAGE_SIZE,
374                              reqst->brw_rw == LST_BRW_WRITE);
375         if (rc != 0) return rc;
376
377         if (reqst->brw_rw == LST_BRW_READ)
378                 brw_fill_bulk(rpc->srpc_bulk, reqst->brw_flags, BRW_MAGIC);
379         else
380                 brw_fill_bulk(rpc->srpc_bulk, reqst->brw_flags, BRW_POISON);
381
382         return 0;
383 }
384
385 sfw_test_client_ops_t brw_test_client =
386 {
387         .tso_init      = brw_client_init,
388         .tso_fini      = brw_client_fini,
389         .tso_prep_rpc  = brw_client_prep_rpc,
390         .tso_done_rpc  = brw_client_done_rpc,
391 };
392
393 srpc_service_t brw_test_service =
394 {
395         .sv_name       = "brw test",
396         .sv_handler    = brw_server_handle,
397         .sv_bulk_ready = brw_bulk_ready,
398         .sv_id         = SRPC_SERVICE_BRW,
399 };