Whamcloud - gitweb
LU-17662 osd-zfs: Support for ZFS 2.2.3
[fs/lustre-release.git] / lnet / selftest / selftest.h
1 // SPDX-License-Identifier: GPL-2.0
2
3 /*
4  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
5  * Use is subject to license terms.
6  *
7  * Copyright (c) 2012, 2017, Intel Corporation.
8  */
9
10 /*
11  * This file is part of Lustre, http://www.lustre.org/
12  *
13  * Author: Isaac Huang <isaac@clusterfs.com>
14  */
15
16 #ifndef __SELFTEST_SELFTEST_H__
17 #define __SELFTEST_SELFTEST_H__
18
19 #define LNET_ONLY
20
21 #include <libcfs/libcfs.h>
22 #include <lnet/api.h>
23 #include <lnet/lib-lnet.h>
24 #include <lnet/lib-types.h>
25 #include <uapi/linux/lnet/lnetst.h>
26 #include <linux/refcount.h>
27
28 #include "rpc.h"
29 #include "timer.h"
30
31 #ifndef MADE_WITHOUT_COMPROMISE
32 #define MADE_WITHOUT_COMPROMISE
33 #endif
34
35 /* enum lnet_selftest_session_attrs   - LNet selftest session Netlink
36  *                                      attributes
37  *
38  *  @LNET_SELFTEST_SESSION_UNSPEC:      unspecified attribute to catch errors
39  *  @LNET_SELFTEST_SESSION_PAD:         padding for 64-bit attributes, ignore
40  *
41  *  @LENT_SELFTEST_SESSION_HDR:         Netlink group this data is for
42  *                                      (NLA_NUL_STRING)
43  *  @LNET_SELFTEST_SESSION_NAME:        name of this session (NLA_STRING)
44  *  @LNET_SELFTEST_SESSION_KEY:         key used to represent the session
45  *                                      (NLA_U32)
46  *  @LNET_SELFTEST_SESSION_TIMESTAMP:   timestamp when the session was created
47  *                                      (NLA_S64)
48  *  @LNET_SELFTEST_SESSION_NID:         NID of the node selftest ran on
49  *                                      (NLA_STRING)
50  *  @LNET_SELFTEST_SESSION_NODE_COUNT:  Number of nodes in use (NLA_U16)
51  */
52 enum lnet_selftest_session_attrs {
53         LNET_SELFTEST_SESSION_UNSPEC = 0,
54         LNET_SELFTEST_SESSION_PAD = LNET_SELFTEST_SESSION_UNSPEC,
55
56         LNET_SELFTEST_SESSION_HDR,
57         LNET_SELFTEST_SESSION_NAME,
58         LNET_SELFTEST_SESSION_KEY,
59         LNET_SELFTEST_SESSION_TIMESTAMP,
60         LNET_SELFTEST_SESSION_NID,
61         LNET_SELFTEST_SESSION_NODE_COUNT,
62
63         __LNET_SELFTEST_SESSION_MAX_PLUS_ONE,
64 };
65
66 #define LNET_SELFTEST_SESSION_MAX       (__LNET_SELFTEST_SESSION_MAX_PLUS_ONE - 1)
67
68 /* enum lnet_selftest_group_attrs     - LNet selftest group Netlink attributes
69  *
70  *  @LNET_SELFTEST_GROUP_ATTR_UNSPEC:   unspecified attribute to catch errors
71  *
72  *  @LENT_SELFTEST_GROUP_ATTR_HDR:      Netlink group this data is for
73  *                                      (NLA_NUL_STRING)
74  *  @LNET_SELFTEST_GROUP_ATTR_NAME:     name of this group (NLA_STRING)
75  *  @LNET_SELFTEST_GROUP_ATTR_NODELIST: List of nodes belonging to the group
76  *                                      (NLA_NESTED)
77  */
78 enum lnet_selftest_group_attrs {
79         LNET_SELFTEST_GROUP_ATTR_UNSPEC = 0,
80
81         LNET_SELFTEST_GROUP_ATTR_HDR,
82         LNET_SELFTEST_GROUP_ATTR_NAME,
83         LNET_SELFTEST_GROUP_ATTR_NODELIST,
84
85         __LNET_SELFTEST_GROUP_MAX_PLUS_ONE,
86 };
87
88 #define LNET_SELFTEST_GROUP_MAX         (__LNET_SELFTEST_GROUP_MAX_PLUS_ONE - 1)
89
90 /* enum lnet_selftest_group_nodelist_prop_attrs       - Netlink attributes for
91  *                                                      the properties of the
92  *                                                      nodes that belong to a
93  *                                                      group
94  *
95  *  @LNET_SELFTEST_GROUP_NODELIST_PROP_ATTR_UNSPEC:     unspecified attribute
96  *                                                      to catch errors
97  *
98  *  @LENT_SELFTEST_GROUP_NODELIST_PROP_ATTR_NID:        Nodes's NID (NLA_STRING)
99  *  @LNET_SELFTEST_GROUP_NODELIST_PROP_ATTR_STATUS:     Status of the node
100  *                                                      (NLA_STRING)
101  */
102 enum lnet_selftest_group_nodelist_prop_attrs {
103         LNET_SELFTEST_GROUP_NODELIST_PROP_ATTR_UNSPEC = 0,
104
105         LNET_SELFTEST_GROUP_NODELIST_PROP_ATTR_NID,
106         LNET_SELFTEST_GROUP_NODELIST_PROP_ATTR_STATUS,
107         __LNET_SELFTEST_GROUP_NODELIST_PROP_MAX_PLUS_ONE,
108 };
109
110 #define LNET_SELFTEST_GROUP_NODELIST_PROP_MAX   (__LNET_SELFTEST_GROUP_NODELIST_PROP_MAX_PLUS_ONE - 1)
111
112 enum lsr_swi_state {
113         SWI_STATE_DONE = 0,
114         SWI_STATE_NEWBORN,
115         SWI_STATE_REPLY_SUBMITTED,
116         SWI_STATE_REPLY_SENT,
117         SWI_STATE_REQUEST_SUBMITTED,
118         SWI_STATE_REQUEST_SENT,
119         SWI_STATE_REPLY_RECEIVED,
120         SWI_STATE_BULK_STARTED,
121         SWI_STATE_RUNNING,
122         SWI_STATE_PAUSE,
123 };
124
125 /* forward refs */
126 struct srpc_service;
127 struct srpc_service_cd;
128 struct sfw_test_unit;
129 struct sfw_test_instance;
130
131 /* services below SRPC_FRAMEWORK_SERVICE_MAX_ID are framework
132  * services, e.g. create/modify session.
133  */
134 #define SRPC_SERVICE_DEBUG              0
135 #define SRPC_SERVICE_MAKE_SESSION       1
136 #define SRPC_SERVICE_REMOVE_SESSION     2
137 #define SRPC_SERVICE_BATCH              3
138 #define SRPC_SERVICE_TEST               4
139 #define SRPC_SERVICE_QUERY_STAT         5
140 #define SRPC_SERVICE_JOIN               6
141 #define SRPC_FRAMEWORK_SERVICE_MAX_ID   10
142 /* other services start from SRPC_FRAMEWORK_SERVICE_MAX_ID+1 */
143 #define SRPC_SERVICE_BRW                11
144 #define SRPC_SERVICE_PING               12
145 #define SRPC_SERVICE_MAX_ID             12
146
147 #define SRPC_REQUEST_PORTAL             50
148 /* a lazy portal for framework RPC requests */
149 #define SRPC_FRAMEWORK_REQUEST_PORTAL   51
150 /* all reply/bulk RDMAs go to this portal */
151 #define SRPC_RDMA_PORTAL                52
152
153 static inline enum srpc_msg_type
154 srpc_service2request(int service)
155 {
156         switch (service) {
157         default:
158                 LBUG();
159         case SRPC_SERVICE_DEBUG:
160                 return SRPC_MSG_DEBUG_REQST;
161
162         case SRPC_SERVICE_MAKE_SESSION:
163                 return SRPC_MSG_MKSN_REQST;
164
165         case SRPC_SERVICE_REMOVE_SESSION:
166                 return SRPC_MSG_RMSN_REQST;
167
168         case SRPC_SERVICE_BATCH:
169                 return SRPC_MSG_BATCH_REQST;
170
171         case SRPC_SERVICE_TEST:
172                 return SRPC_MSG_TEST_REQST;
173
174         case SRPC_SERVICE_QUERY_STAT:
175                 return SRPC_MSG_STAT_REQST;
176
177         case SRPC_SERVICE_BRW:
178                 return SRPC_MSG_BRW_REQST;
179
180         case SRPC_SERVICE_PING:
181                 return SRPC_MSG_PING_REQST;
182
183         case SRPC_SERVICE_JOIN:
184                 return SRPC_MSG_JOIN_REQST;
185         }
186 }
187
188 static inline enum srpc_msg_type
189 srpc_service2reply(int service)
190 {
191         return srpc_service2request(service) + 1;
192 }
193
194 enum srpc_event_type {
195         SRPC_BULK_REQ_RCVD   = 1, /* passive bulk request(PUT sink/GET source) received */
196         SRPC_BULK_PUT_SENT   = 2, /* active bulk PUT sent (source) */
197         SRPC_BULK_GET_RPLD   = 3, /* active bulk GET replied (sink) */
198         SRPC_REPLY_RCVD      = 4, /* incoming reply received */
199         SRPC_REPLY_SENT      = 5, /* outgoing reply sent */
200         SRPC_REQUEST_RCVD    = 6, /* incoming request received */
201         SRPC_REQUEST_SENT    = 7, /* outgoing request sent */
202 };
203
204 /* RPC event */
205 struct srpc_event {
206         enum srpc_event_type    ev_type;   /* what's up */
207         enum lnet_event_kind    ev_lnet;   /* LNet event type */
208         int               ev_fired;  /* LNet event fired? */
209         int               ev_status; /* LNet event status */
210         void             *ev_data;   /* owning server/client RPC */
211 };
212
213 /* bulk descriptor */
214 struct srpc_bulk {
215         int                     bk_len;  /* len of bulk data */
216         struct lnet_handle_md   bk_mdh;
217         int                     bk_sink; /* sink/source */
218         int                     bk_alloc; /* # allocated iov */
219         int                     bk_niov; /* # iov in bk_iovs */
220         struct bio_vec          bk_iovs[0];
221 };
222
223 /* message buffer descriptor */
224 struct srpc_buffer {
225         struct list_head        buf_list; /* chain on srpc_service::*_msgq */
226         struct srpc_msg         buf_msg;
227         struct lnet_handle_md   buf_mdh;
228         lnet_nid_t              buf_self;
229         struct lnet_process_id  buf_peer;
230 };
231
232 struct swi_workitem;
233 typedef void (*swi_action_t)(struct swi_workitem *);
234
235 struct swi_workitem {
236         struct workqueue_struct *swi_wq;
237         struct work_struct      swi_work;
238         swi_action_t            swi_action;
239         enum lsr_swi_state      swi_state;
240 };
241
242 /* server-side state of a RPC */
243 struct srpc_server_rpc {
244         /* chain on srpc_service::*_rpcq */
245         struct list_head        srpc_list;
246         struct srpc_service_cd *srpc_scd;
247         struct swi_workitem     srpc_wi;
248         struct srpc_event       srpc_ev;        /* bulk/reply event */
249         lnet_nid_t              srpc_self;
250         struct lnet_process_id  srpc_peer;
251         struct srpc_msg         srpc_replymsg;
252         struct lnet_handle_md   srpc_replymdh;
253         struct srpc_buffer     *srpc_reqstbuf;
254         struct srpc_bulk       *srpc_bulk;
255
256         unsigned int    srpc_aborted; /* being given up */
257         int             srpc_status;
258         void            (*srpc_done)(struct srpc_server_rpc *);
259 };
260
261 /* client-side state of a RPC */
262 struct srpc_client_rpc {
263         struct list_head        crpc_list;      /* chain on user's lists */
264         spinlock_t              crpc_lock;      /* serialize */
265         int                     crpc_service;
266         atomic_t                crpc_refcount;
267         /* # seconds to wait for reply */
268         int                     crpc_timeout;
269         struct stt_timer        crpc_timer;
270         struct swi_workitem     crpc_wi;
271         struct lnet_process_id  crpc_dest;
272
273         void               (*crpc_done)(struct srpc_client_rpc *);
274         void               (*crpc_fini)(struct srpc_client_rpc *);
275         int                  crpc_status;    /* completion status */
276         void                *crpc_priv;      /* caller data */
277
278         /* state flags */
279         unsigned int         crpc_aborted:1; /* being given up */
280         unsigned int         crpc_closed:1;  /* completed */
281
282         /* RPC events */
283         struct srpc_event       crpc_bulkev;    /* bulk event */
284         struct srpc_event       crpc_reqstev;   /* request event */
285         struct srpc_event       crpc_replyev;   /* reply event */
286
287         /* bulk, request(reqst), and reply exchanged on wire */
288         struct srpc_msg         crpc_reqstmsg;
289         struct srpc_msg         crpc_replymsg;
290         struct lnet_handle_md   crpc_reqstmdh;
291         struct lnet_handle_md   crpc_replymdh;
292         struct srpc_bulk        crpc_bulk;
293 };
294
295 #define srpc_client_rpc_size(rpc)                                       \
296 offsetof(struct srpc_client_rpc, crpc_bulk.bk_iovs[(rpc)->crpc_bulk.bk_niov])
297
298 #define srpc_client_rpc_addref(rpc)                                     \
299 do {                                                                    \
300         CDEBUG(D_NET, "RPC[%p] -> %s (%d)++\n",                         \
301                (rpc), libcfs_id2str((rpc)->crpc_dest),                  \
302                atomic_read(&(rpc)->crpc_refcount));                     \
303         LASSERT(atomic_read(&(rpc)->crpc_refcount) > 0);                \
304         atomic_inc(&(rpc)->crpc_refcount);                              \
305 } while (0)
306
307 #define srpc_client_rpc_decref(rpc)                                     \
308 do {                                                                    \
309         CDEBUG(D_NET, "RPC[%p] -> %s (%d)--\n",                         \
310                (rpc), libcfs_id2str((rpc)->crpc_dest),                  \
311                atomic_read(&(rpc)->crpc_refcount));                     \
312         LASSERT(atomic_read(&(rpc)->crpc_refcount) > 0);                \
313         if (atomic_dec_and_test(&(rpc)->crpc_refcount))                 \
314                 srpc_destroy_client_rpc(rpc);                           \
315 } while (0)
316
317 #define srpc_event_pending(rpc)   ((rpc)->crpc_bulkev.ev_fired == 0 ||  \
318                                    (rpc)->crpc_reqstev.ev_fired == 0 || \
319                                    (rpc)->crpc_replyev.ev_fired == 0)
320
321 /* CPU partition data of srpc service */
322 struct srpc_service_cd {
323         /** serialize */
324         spinlock_t              scd_lock;
325         /** backref to service */
326         struct srpc_service     *scd_svc;
327         /** event buffer */
328         struct srpc_event       scd_ev;
329         /** free RPC descriptors */
330         struct list_head        scd_rpc_free;
331         /** in-flight RPCs */
332         struct list_head        scd_rpc_active;
333         /** workitem for posting buffer */
334         struct swi_workitem     scd_buf_wi;
335         /** CPT id */
336         int                     scd_cpt;
337         /** error code for scd_buf_wi */
338         int                     scd_buf_err;
339         /** timestamp for scd_buf_err */
340         time64_t                scd_buf_err_stamp;
341         /** total # request buffers */
342         int                     scd_buf_total;
343         /** # posted request buffers */
344         int                     scd_buf_nposted;
345         /** in progress of buffer posting */
346         int                     scd_buf_posting;
347         /** allocate more buffers if scd_buf_nposted < scd_buf_low */
348         int                     scd_buf_low;
349         /** increase/decrease some buffers */
350         int                     scd_buf_adjust;
351         /** posted message buffers */
352         struct list_head        scd_buf_posted;
353         /** blocked for RPC descriptor */
354         struct list_head        scd_buf_blocked;
355 };
356
357 /* number of server workitems (mini-thread) for testing service */
358 #define SFW_TEST_WI_MIN         256
359 #define SFW_TEST_WI_MAX         2048
360 /* extra buffers for tolerating buggy peers, or unbalanced number
361  * of peers between partitions  */
362 #define SFW_TEST_WI_EXTRA       64
363
364 /* number of server workitems (mini-thread) for framework service */
365 #define SFW_FRWK_WI_MIN         16
366 #define SFW_FRWK_WI_MAX         256
367
368 struct srpc_service {
369         int                     sv_id;          /* service id */
370         const char              *sv_name;       /* human readable name */
371         int                     sv_wi_total;    /* total server workitems */
372         int                     sv_shuttingdown;
373         int                     sv_ncpts;
374         /* percpt data for srpc_service */
375         struct srpc_service_cd  **sv_cpt_data;
376         /* Service callbacks:
377          * - sv_handler: process incoming RPC request
378          * - sv_bulk_ready: notify bulk data
379          */
380         int              (*sv_handler)(struct srpc_server_rpc *);
381         int              (*sv_bulk_ready)(struct srpc_server_rpc *, int);
382
383         /** Service side srpc constructor/destructor.
384          *  used for the bulk preallocation as usual.
385          */
386         int              (*sv_srpc_init)(struct srpc_server_rpc *, int);
387         void             (*sv_srpc_fini)(struct srpc_server_rpc *);
388 };
389
390 struct lst_session_id {
391         s64                     ses_stamp;      /* time stamp in milliseconds */
392         struct lnet_nid         ses_nid;        /* nid of console node */
393 };                                              /*** session id (large addr) */
394
395 extern struct lst_session_id LST_INVALID_SID;
396
397 struct sfw_session {
398         /* chain on fw_zombie_sessions */
399         struct list_head        sn_list;
400         struct lst_session_id   sn_id;          /* unique identifier */
401         /* # seconds' inactivity to expire */
402         unsigned int            sn_timeout;
403         int                     sn_timer_active;
404         unsigned int            sn_features;
405         struct stt_timer        sn_timer;
406         struct list_head        sn_batches;     /* list of batches */
407         char                    sn_name[LST_NAME_SIZE];
408         refcount_t              sn_refcount;
409         atomic_t                sn_brw_errors;
410         atomic_t                sn_ping_errors;
411         ktime_t                 sn_started;
412 };
413
414 static inline int sfw_sid_equal(struct lst_sid sid0,
415                                 struct lst_session_id sid1)
416 {
417         struct lnet_nid ses_nid;
418
419         lnet_nid4_to_nid(sid0.ses_nid, &ses_nid);
420
421         return ((sid0.ses_stamp == sid1.ses_stamp) &&
422                 nid_same(&ses_nid, &sid1.ses_nid));
423 }
424
425 struct sfw_batch {
426         struct list_head        bat_list;       /* chain on sn_batches */
427         struct lst_bid          bat_id;         /* batch id */
428         int                     bat_error;      /* error code of batch */
429         struct sfw_session      *bat_session;   /* batch's session */
430         atomic_t                bat_nactive;    /* # of active tests */
431         struct list_head        bat_tests;      /* test instances */
432 };
433
434 struct sfw_test_client_ops {
435         int  (*tso_init)(struct sfw_test_instance *tsi); /* intailize test client */
436         void (*tso_fini)(struct sfw_test_instance *tsi); /* finalize test client */
437         int  (*tso_prep_rpc)(struct sfw_test_unit *tsu,
438                              struct lnet_process_id dest,
439                              struct srpc_client_rpc **rpc); /* prep a tests rpc */
440         void (*tso_done_rpc)(struct sfw_test_unit *tsu,
441                              struct srpc_client_rpc *rpc);  /* done a test rpc */
442 };
443
444 struct sfw_test_instance {
445         struct list_head        tsi_list; /* chain on batch */
446         int                     tsi_service; /* test type */
447         struct sfw_batch        *tsi_batch; /* batch */
448         struct sfw_test_client_ops      *tsi_ops; /* test client operations */
449
450         /* public parameter for all test units */
451         unsigned int            tsi_is_client:1;     /* is test client */
452         unsigned int            tsi_stoptsu_onerr:1; /* stop tsu on error */
453         int                     tsi_concur;          /* concurrency */
454         int                     tsi_loop;            /* loop count */
455
456         /* status of test instance */
457         spinlock_t              tsi_lock;       /* serialize */
458         unsigned int            tsi_stopping:1; /* test is stopping */
459         atomic_t                tsi_nactive;    /* # of active test unit */
460         struct list_head        tsi_units;      /* test units */
461         struct list_head        tsi_free_rpcs;  /* free rpcs */
462         struct list_head        tsi_active_rpcs;/* active rpcs */
463
464         union {
465                 struct test_ping_req    ping;     /* ping parameter */
466                 struct test_bulk_req    bulk_v0;  /* bulk parameter */
467                 struct test_bulk_req_v1 bulk_v1;  /* bulk v1 parameter */
468         } tsi_u;
469 };
470
471 /* XXX: trailing (PAGE_SIZE % sizeof(struct lnet_process_id)) bytes at
472  * the end of pages are not used */
473 #define SFW_MAX_CONCUR     LST_MAX_CONCUR
474 #define SFW_ID_PER_PAGE    (PAGE_SIZE / sizeof(struct lnet_process_id_packed))
475 #define SFW_MAX_NDESTS     (LNET_MAX_IOV * SFW_ID_PER_PAGE)
476 #define sfw_id_pages(n)    (((n) + SFW_ID_PER_PAGE - 1) / SFW_ID_PER_PAGE)
477
478 struct sfw_test_unit {
479         struct list_head        tsu_list;       /* chain on lst_test_instance */
480         struct lnet_process_id  tsu_dest;       /* id of dest node */
481         int                     tsu_loop;       /* loop count of the test */
482         struct sfw_test_instance *tsu_instance; /* pointer to test instance */
483         void                    *tsu_private;   /* private data */
484         struct swi_workitem      tsu_worker;    /* workitem of the test unit */
485 };
486
487 struct sfw_test_case {
488         struct list_head                tsc_list; /* chain on fw_tests */
489         struct srpc_service             *tsc_srv_service; /* test service */
490         struct sfw_test_client_ops      *tsc_cli_ops; /* ops of test client */
491 };
492
493 struct srpc_client_rpc *
494 sfw_create_rpc(struct lnet_process_id peer, int service,
495                unsigned int features, int nbulkiov, int bulklen,
496                void (*done)(struct srpc_client_rpc *), void *priv);
497 int sfw_create_test_rpc(struct sfw_test_unit *tsu,
498                         struct lnet_process_id peer, unsigned int features,
499                         int nblk, int blklen, struct srpc_client_rpc **rpc);
500 void sfw_abort_rpc(struct srpc_client_rpc *rpc);
501 void sfw_post_rpc(struct srpc_client_rpc *rpc);
502 void sfw_client_rpc_done(struct srpc_client_rpc *rpc);
503 void sfw_unpack_message(struct srpc_msg *msg);
504 void sfw_add_bulk_page(struct srpc_bulk *bk, struct page *pg, int i);
505 int sfw_alloc_pages(struct srpc_server_rpc *rpc, int cpt, int len,
506                     int sink);
507 int sfw_make_session(struct srpc_mksn_reqst *request,
508                      struct srpc_mksn_reply *reply);
509
510 struct srpc_client_rpc *
511 srpc_create_client_rpc(struct lnet_process_id peer, int service,
512                        int nbulkiov, int bulklen,
513                        void (*rpc_done)(struct srpc_client_rpc *),
514                        void (*rpc_fini)(struct srpc_client_rpc *), void *priv);
515 void srpc_post_rpc(struct srpc_client_rpc *rpc);
516 void srpc_abort_rpc(struct srpc_client_rpc *rpc, int why);
517 void srpc_free_bulk(struct srpc_bulk *bk);
518
519 struct srpc_bulk *srpc_alloc_bulk(int cpt, unsigned int bulk_len);
520 void srpc_init_bulk(struct srpc_bulk *bk, unsigned int off,
521                     unsigned int bulk_len, int sink);
522
523 void srpc_send_rpc(struct swi_workitem *wi);
524 int srpc_send_reply(struct srpc_server_rpc *rpc);
525 int srpc_add_service(struct srpc_service *sv);
526 int srpc_remove_service(struct srpc_service *sv);
527 void srpc_shutdown_service(struct srpc_service *sv);
528 void srpc_abort_service(struct srpc_service *sv);
529 int srpc_finish_service(struct srpc_service *sv);
530 int srpc_service_add_buffers(struct srpc_service *sv, int nbuffer);
531 void srpc_service_remove_buffers(struct srpc_service *sv, int nbuffer);
532 void srpc_get_counters(struct srpc_counters *cnt);
533
534 extern struct workqueue_struct *lst_serial_wq;
535 extern struct workqueue_struct **lst_test_wq;
536
537 static inline int
538 srpc_serv_is_framework(struct srpc_service *svc)
539 {
540         return svc->sv_id < SRPC_FRAMEWORK_SERVICE_MAX_ID;
541 }
542
543 static void
544 swi_wi_action(struct work_struct *wi)
545 {
546         struct swi_workitem *swi;
547
548         swi = container_of(wi, struct swi_workitem, swi_work);
549         swi->swi_action(swi);
550 }
551
552 static inline void
553 swi_init_workitem(struct swi_workitem *swi,
554                   swi_action_t action, struct workqueue_struct *wq)
555 {
556         swi->swi_wq = wq;
557         swi->swi_action = action;
558         swi->swi_state  = SWI_STATE_NEWBORN;
559         INIT_WORK(&swi->swi_work, swi_wi_action);
560 }
561
562 static inline void
563 swi_schedule_workitem(struct swi_workitem *wi)
564 {
565         queue_work(wi->swi_wq, &wi->swi_work);
566 }
567
568 static inline int
569 swi_cancel_workitem(struct swi_workitem *swi)
570 {
571         swi->swi_state = SWI_STATE_DONE;
572         return cancel_work_sync(&swi->swi_work);
573 }
574
575 int sfw_startup(void);
576 int srpc_startup(void);
577 void sfw_shutdown(void);
578 void srpc_shutdown(void);
579
580 static inline void
581 srpc_destroy_client_rpc(struct srpc_client_rpc *rpc)
582 {
583         LASSERT(rpc != NULL);
584         LASSERT(!srpc_event_pending(rpc));
585         LASSERT(atomic_read(&rpc->crpc_refcount) == 0);
586
587         if (rpc->crpc_fini == NULL)
588                 LIBCFS_FREE(rpc, srpc_client_rpc_size(rpc));
589         else
590                 (*rpc->crpc_fini) (rpc);
591 }
592
593 static inline void
594 srpc_init_client_rpc(struct srpc_client_rpc *rpc, struct lnet_process_id peer,
595                      int service, int nbulkiov, int bulklen,
596                      void (*rpc_done)(struct srpc_client_rpc *),
597                      void (*rpc_fini)(struct srpc_client_rpc *), void *priv)
598 {
599         LASSERT(nbulkiov <= LNET_MAX_IOV);
600
601         memset(rpc, 0, offsetof(struct srpc_client_rpc,
602                                 crpc_bulk.bk_iovs[nbulkiov]));
603
604         INIT_LIST_HEAD(&rpc->crpc_list);
605         swi_init_workitem(&rpc->crpc_wi, srpc_send_rpc,
606                           lst_test_wq[lnet_cpt_of_nid(peer.nid, NULL)]);
607         spin_lock_init(&rpc->crpc_lock);
608         atomic_set(&rpc->crpc_refcount, 1); /* 1 ref for caller */
609
610         rpc->crpc_dest         = peer;
611         rpc->crpc_priv         = priv;
612         rpc->crpc_service      = service;
613         rpc->crpc_bulk.bk_len  = bulklen;
614         rpc->crpc_bulk.bk_niov = nbulkiov;
615         rpc->crpc_done         = rpc_done;
616         rpc->crpc_fini         = rpc_fini;
617         LNetInvalidateMDHandle(&rpc->crpc_reqstmdh);
618         LNetInvalidateMDHandle(&rpc->crpc_replymdh);
619         LNetInvalidateMDHandle(&rpc->crpc_bulk.bk_mdh);
620
621         /* no event is expected at this point */
622         rpc->crpc_bulkev.ev_fired  =
623         rpc->crpc_reqstev.ev_fired =
624         rpc->crpc_replyev.ev_fired = 1;
625
626         rpc->crpc_reqstmsg.msg_magic   = SRPC_MSG_MAGIC;
627         rpc->crpc_reqstmsg.msg_version = SRPC_MSG_VERSION;
628         rpc->crpc_reqstmsg.msg_type    = srpc_service2request(service);
629 }
630
631 static inline const char *
632 swi_state2str(int state)
633 {
634 #define STATE2STR(x) case x: return #x
635         switch (state) {
636         default:
637                 LBUG();
638         STATE2STR(SWI_STATE_NEWBORN);
639         STATE2STR(SWI_STATE_REPLY_SUBMITTED);
640         STATE2STR(SWI_STATE_REPLY_SENT);
641         STATE2STR(SWI_STATE_REQUEST_SUBMITTED);
642         STATE2STR(SWI_STATE_REQUEST_SENT);
643         STATE2STR(SWI_STATE_REPLY_RECEIVED);
644         STATE2STR(SWI_STATE_BULK_STARTED);
645         STATE2STR(SWI_STATE_DONE);
646         }
647 #undef STATE2STR
648 }
649
650 #define lst_wait_until(cond, lock, fmt, ...)                            \
651 do {                                                                    \
652         int __I = 2;                                                    \
653         while (!(cond)) {                                               \
654                 CDEBUG(is_power_of_2(++__I) ? D_WARNING : D_NET,        \
655                        fmt, ## __VA_ARGS__);                            \
656                 spin_unlock(&(lock));                                   \
657                                                                         \
658                 schedule_timeout_uninterruptible(                       \
659                         cfs_time_seconds(1) / 10);                      \
660                                                                         \
661                 spin_lock(&(lock));                                     \
662         }                                                               \
663 } while (0)
664
665 static inline void
666 srpc_wait_service_shutdown(struct srpc_service *sv)
667 {
668         int i = 2;
669
670         LASSERT(sv->sv_shuttingdown);
671
672         while (srpc_finish_service(sv) == 0) {
673                 i++;
674                 CDEBUG(((i & -i) == i) ? D_WARNING : D_NET,
675                        "Waiting for %s service to shutdown...\n",
676                        sv->sv_name);
677                 schedule_timeout_uninterruptible(cfs_time_seconds(1) / 10);
678         }
679 }
680
681 extern struct sfw_test_client_ops ping_test_client;
682 extern struct srpc_service ping_test_service;
683 void ping_init_test_client(void);
684 void ping_init_test_service(void);
685
686 extern struct sfw_test_client_ops brw_test_client;
687 extern struct srpc_service brw_test_service;
688 void brw_init_test_service(void);
689
690 #endif /* __SELFTEST_SELFTEST_H__ */