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