Whamcloud - gitweb
8b0dd01d77f3fde587043edc99074cb7f14ee8b2
[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 "selftest.h"
10
11
12 extern int brw_inject_errors;
13
14 static void
15 brw_client_fini (sfw_test_instance_t *tsi)
16 {
17         srpc_bulk_t     *bulk;
18         sfw_test_unit_t *tsu;
19
20         LASSERT (tsi->tsi_is_client);
21
22         list_for_each_entry (tsu, &tsi->tsi_units, tsu_list) {
23                 bulk = tsu->tsu_private;
24                 if (bulk == NULL) continue;
25
26                 srpc_free_bulk(bulk);
27                 tsu->tsu_private = NULL;
28         }
29 }
30
31 int
32 brw_client_init (sfw_test_instance_t *tsi)
33 {
34         test_bulk_req_t  *breq = &tsi->tsi_u.bulk;
35         int               flags = breq->blk_flags;
36         int               npg = breq->blk_npg;
37         srpc_bulk_t      *bulk;
38         sfw_test_unit_t  *tsu;
39
40         LASSERT (tsi->tsi_is_client);
41
42         if (npg > LNET_MAX_IOV || npg <= 0)
43                 return -EINVAL;
44
45         if (breq->blk_opc != LST_BRW_READ && breq->blk_opc != LST_BRW_WRITE)
46                 return -EINVAL;
47
48         if (flags != LST_BRW_CHECK_NONE &&
49             flags != LST_BRW_CHECK_FULL && flags != LST_BRW_CHECK_SIMPLE)
50                 return -EINVAL;
51
52         list_for_each_entry (tsu, &tsi->tsi_units, tsu_list) {
53                 bulk = srpc_alloc_bulk(npg, breq->blk_opc == LST_BRW_READ);
54                 if (bulk == NULL) {
55                         brw_client_fini(tsi);
56                         return -ENOMEM;
57                 }
58
59                 tsu->tsu_private = bulk;
60         }
61
62         return 0;
63 }
64
65 #define BRW_POISON      0xbeefbeefbeefbeefULL
66 #define BRW_MAGIC       0xeeb0eeb1eeb2eeb3ULL
67 #define BRW_MSIZE       sizeof(__u64)
68
69 int
70 brw_inject_one_error (void)
71 {
72         struct timeval tv;
73
74         if (brw_inject_errors <= 0) return 0;
75
76 #ifndef __KERNEL__
77         gettimeofday(&tv, NULL);
78 #else
79         do_gettimeofday(&tv);
80 #endif
81
82         if ((tv.tv_usec & 1) == 0) return 0;
83
84         return brw_inject_errors--;
85 }
86
87 void
88 brw_fill_page (cfs_page_t *pg, int pattern, __u64 magic)
89 {
90         char *addr = cfs_page_address(pg);
91         int   i;
92
93         LASSERT (addr != NULL);
94
95         if (pattern == LST_BRW_CHECK_NONE) 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         sfw_test_instance_t *tsi = tsu->tsu_instance;
236         sfw_session_t       *sn = tsi->tsi_batch->bat_session;
237         srpc_msg_t          *msg = &rpc->crpc_replymsg;
238         srpc_brw_reply_t    *reply = &msg->msg_body.brw_reply;
239         srpc_brw_reqst_t    *reqst = &rpc->crpc_reqstmsg.msg_body.brw_reqst;
240
241         LASSERT (sn != NULL);
242
243         if (rpc->crpc_status != 0) {
244                 CERROR ("BRW RPC to %s failed with %d\n",
245                         libcfs_id2str(rpc->crpc_dest), rpc->crpc_status);
246                 if (!tsi->tsi_stopping) /* rpc could have been aborted */
247                         atomic_inc(&sn->sn_brw_errors);
248                 goto out;
249         }
250
251         if (msg->msg_magic != SRPC_MSG_MAGIC) {
252                 __swab64s(&magic);
253                 __swab32s(&reply->brw_status);
254         }
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                 rpc->crpc_status = -reply->brw_status;
263                 goto out;
264         }
265
266         if (reqst->brw_rw == LST_BRW_WRITE) goto out;
267
268         if (brw_check_bulk(&rpc->crpc_bulk, reqst->brw_flags, magic) != 0) {
269                 CERROR ("Bulk data from %s is corrupted!\n",
270                         libcfs_id2str(rpc->crpc_dest));
271                 atomic_inc(&sn->sn_brw_errors);
272                 rpc->crpc_status = -EBADMSG;
273         }
274
275 out:
276 #ifndef __KERNEL__
277         rpc->crpc_bulk.bk_pages = NULL;
278 #endif
279         return;
280 }
281
282 void
283 brw_server_rpc_done (srpc_server_rpc_t *rpc)
284 {
285         srpc_bulk_t *blk = rpc->srpc_bulk;
286
287         if (blk == NULL) return;
288
289         if (rpc->srpc_status != 0)
290                 CERROR ("Bulk transfer %s %s has failed: %d\n",
291                         blk->bk_sink ? "from" : "to",
292                         libcfs_id2str(rpc->srpc_peer), rpc->srpc_status);
293         else
294                 CDEBUG (D_NET, "Transfered %d pages bulk data %s %s\n",
295                         blk->bk_niov, blk->bk_sink ? "from" : "to",
296                         libcfs_id2str(rpc->srpc_peer));
297
298         sfw_free_pages(rpc);
299 }
300
301 int
302 brw_bulk_ready (srpc_server_rpc_t *rpc, int status)
303 {
304         __u64             magic = BRW_MAGIC;
305         srpc_brw_reply_t *reply = &rpc->srpc_replymsg.msg_body.brw_reply;
306         srpc_brw_reqst_t *reqst;
307         srpc_msg_t       *reqstmsg;
308
309         LASSERT (rpc->srpc_bulk != NULL);
310         LASSERT (rpc->srpc_reqstbuf != NULL);
311
312         reqstmsg = &rpc->srpc_reqstbuf->buf_msg;
313         reqst = &reqstmsg->msg_body.brw_reqst;
314
315         if (status != 0) {
316                 CERROR ("BRW bulk %s failed for RPC from %s: %d\n",
317                         reqst->brw_rw == LST_BRW_READ ? "READ" : "WRITE",
318                         libcfs_id2str(rpc->srpc_peer), status);
319                 return -EIO;
320         }
321
322         if (reqst->brw_rw == LST_BRW_READ)
323                 return 0;
324
325         if (reqstmsg->msg_magic != SRPC_MSG_MAGIC)
326                 __swab64s(&magic);
327
328         if (brw_check_bulk(rpc->srpc_bulk, reqst->brw_flags, magic) != 0) {
329                 CERROR ("Bulk data from %s is corrupted!\n",
330                         libcfs_id2str(rpc->srpc_peer));
331                 reply->brw_status = EBADMSG;
332         }
333
334         return 0;
335 }
336
337 int
338 brw_server_handle (srpc_server_rpc_t *rpc)
339 {
340         srpc_service_t   *sv = rpc->srpc_service;
341         srpc_msg_t       *replymsg = &rpc->srpc_replymsg;
342         srpc_msg_t       *reqstmsg = &rpc->srpc_reqstbuf->buf_msg;
343         srpc_brw_reply_t *reply = &replymsg->msg_body.brw_reply;
344         srpc_brw_reqst_t *reqst = &reqstmsg->msg_body.brw_reqst;
345         int               rc;
346
347         LASSERT (sv->sv_id == SRPC_SERVICE_BRW);
348
349         if (reqstmsg->msg_magic != SRPC_MSG_MAGIC) {
350                 LASSERT (reqstmsg->msg_magic == __swab32(SRPC_MSG_MAGIC));
351
352                 __swab32s(&reqstmsg->msg_type);
353                 __swab32s(&reqst->brw_rw);
354                 __swab32s(&reqst->brw_len);
355                 __swab32s(&reqst->brw_flags);
356                 __swab64s(&reqst->brw_rpyid);
357                 __swab64s(&reqst->brw_bulkid);
358         }
359         LASSERT (reqstmsg->msg_type == srpc_service2request(sv->sv_id));
360
361         rpc->srpc_done = brw_server_rpc_done;
362
363         if ((reqst->brw_rw != LST_BRW_READ && reqst->brw_rw != LST_BRW_WRITE) ||
364             reqst->brw_len == 0 || (reqst->brw_len & ~CFS_PAGE_MASK) != 0 ||
365             reqst->brw_len / CFS_PAGE_SIZE > LNET_MAX_IOV ||
366             (reqst->brw_flags != LST_BRW_CHECK_NONE &&
367              reqst->brw_flags != LST_BRW_CHECK_FULL &&
368              reqst->brw_flags != LST_BRW_CHECK_SIMPLE)) {
369                 reply->brw_status = EINVAL;
370                 return 0;
371         }
372         
373         reply->brw_status = 0;
374         rc = sfw_alloc_pages(rpc, reqst->brw_len / CFS_PAGE_SIZE,
375                              reqst->brw_rw == LST_BRW_WRITE);
376         if (rc != 0) return rc;
377
378         if (reqst->brw_rw == LST_BRW_READ)
379                 brw_fill_bulk(rpc->srpc_bulk, reqst->brw_flags, BRW_MAGIC);
380         else
381                 brw_fill_bulk(rpc->srpc_bulk, reqst->brw_flags, BRW_POISON);
382
383         return 0;
384 }
385
386 sfw_test_client_ops_t brw_test_client =
387 {
388         .tso_init      = brw_client_init,
389         .tso_fini      = brw_client_fini,
390         .tso_prep_rpc  = brw_client_prep_rpc,
391         .tso_done_rpc  = brw_client_done_rpc,
392 };
393
394 srpc_service_t brw_test_service =
395 {
396         .sv_name       = "brw test",
397         .sv_handler    = brw_server_handle,
398         .sv_bulk_ready = brw_bulk_ready,
399         .sv_id         = SRPC_SERVICE_BRW,
400 };