Whamcloud - gitweb
efb6523fe9af4cbb9ea2b4e799ff517a6cd02a14
[fs/lustre-release.git] / lnet / include / libcfs / kp30.h
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  */
4 #ifndef __LIBCFS_KP30_H__
5 #define __LIBCFS_KP30_H__
6
7 #define PORTAL_DEBUG
8 #include <libcfs/libcfs.h>
9
10 #if defined(__linux__)
11 #include <libcfs/linux/kp30.h>
12 #elif defined(__APPLE__)
13 #include <libcfs/darwin/kp30.h>
14 #else
15 #error Unsupported operating system
16 #endif
17
18 #ifdef __KERNEL__
19
20 # ifndef DEBUG_SUBSYSTEM
21 #  define DEBUG_SUBSYSTEM S_UNDEFINED
22 # endif
23
24 #ifdef PORTAL_DEBUG
25 extern void kportal_assertion_failed(char *expr, char *file, const char *func,
26                                      const int line);
27 #define LASSERT(e) ((e) ? 0 : kportal_assertion_failed( #e , __FILE__,  \
28                                                         __FUNCTION__, __LINE__))
29 #define LASSERTF(cond, fmt...)                                                \
30         do {                                                                  \
31                 if (unlikely(!(cond))) {                                      \
32                         portals_debug_msg(DEBUG_SUBSYSTEM, D_EMERG,  __FILE__,\
33                                           __FUNCTION__,__LINE__, CDEBUG_STACK,\
34                                           "ASSERTION(" #cond ") failed:" fmt);\
35                         LBUG();                                               \
36                 }                                                             \
37         } while (0)
38
39 #else
40 #define LASSERT(e)
41 #define LASSERTF(cond, fmt...) do { } while (0)
42 #endif
43
44 /* LBUG_WITH_LOC defined in portals/<os>/kp30.h */
45 #define LBUG() LBUG_WITH_LOC(__FILE__, __FUNCTION__, __LINE__)
46
47 /*
48  * Memory
49  */
50 #ifdef PORTAL_DEBUG
51 extern atomic_t portal_kmemory;
52
53 # define portal_kmem_inc(ptr, size)                                           \
54 do {                                                                          \
55         atomic_add(size, &portal_kmemory);                                    \
56 } while (0)
57
58 # define portal_kmem_dec(ptr, size) do {                                      \
59         atomic_sub(size, &portal_kmemory);                                    \
60 } while (0)
61
62 #else
63 # define portal_kmem_inc(ptr, size) do {} while (0)
64 # define portal_kmem_dec(ptr, size) do {} while (0)
65 #endif /* PORTAL_DEBUG */
66
67 #define PORTAL_VMALLOC_SIZE        16384
68
69 #define PORTAL_ALLOC_GFP(ptr, size, mask)                                 \
70 do {                                                                      \
71         LASSERT(!in_interrupt() ||                                        \
72                (size <= PORTAL_VMALLOC_SIZE && mask == CFS_ALLOC_ATOMIC));\
73         if ((size) > PORTAL_VMALLOC_SIZE)                                 \
74                 (ptr) = cfs_alloc_large(size);                            \
75         else                                                              \
76                 (ptr) = cfs_alloc((size), (mask));                        \
77         if ((ptr) == NULL) {                                              \
78                 CERROR("PORTALS: out of memory at %s:%d (tried to alloc '"\
79                        #ptr "' = %d)\n", __FILE__, __LINE__, (int)(size));\
80                 CERROR("PORTALS: %d total bytes allocated by portals\n",  \
81                        atomic_read(&portal_kmemory));                     \
82         } else {                                                          \
83                 portal_kmem_inc((ptr), (size));                           \
84                 if (!((mask) & CFS_ALLOC_ZERO))                           \
85                        memset((ptr), 0, (size));                          \
86         }                                                                 \
87         CDEBUG(D_MALLOC, "kmalloced '" #ptr "': %d at %p (tot %d).\n",    \
88                (int)(size), (ptr), atomic_read (&portal_kmemory));        \
89 } while (0)
90
91 #define PORTAL_ALLOC(ptr, size) \
92         PORTAL_ALLOC_GFP(ptr, size, CFS_ALLOC_IO)
93
94 #define PORTAL_ALLOC_ATOMIC(ptr, size) \
95         PORTAL_ALLOC_GFP(ptr, size, CFS_ALLOC_ATOMIC)
96
97 #define PORTAL_FREE(ptr, size)                                          \
98 do {                                                                    \
99         int s = (size);                                                 \
100         if ((ptr) == NULL) {                                            \
101                 CERROR("PORTALS: free NULL '" #ptr "' (%d bytes) at "   \
102                        "%s:%d\n", s, __FILE__, __LINE__);               \
103                 break;                                                  \
104         }                                                               \
105         if (s > PORTAL_VMALLOC_SIZE)                                    \
106                 cfs_free_large(ptr);                                    \
107         else                                                            \
108                 cfs_free(ptr);                                          \
109         portal_kmem_dec((ptr), s);                                      \
110         CDEBUG(D_MALLOC, "kfreed '" #ptr "': %d at %p (tot %d).\n",     \
111                s, (ptr), atomic_read(&portal_kmemory));                 \
112 } while (0)
113
114 /******************************************************************************/
115
116 #ifdef PORTALS_PROFILING
117 #define prof_enum(FOO) PROF__##FOO
118 enum {
119         prof_enum(our_recvmsg),
120         prof_enum(our_sendmsg),
121         prof_enum(socknal_recv),
122         prof_enum(lib_parse),
123         prof_enum(conn_list_walk),
124         prof_enum(memcpy),
125         prof_enum(lib_finalize),
126         prof_enum(pingcli_time),
127         prof_enum(gmnal_send),
128         prof_enum(gmnal_recv),
129         MAX_PROFS
130 };
131
132 struct prof_ent {
133         char *str;
134         /* hrmph.  wrap-tastic. */
135         u32       starts;
136         u32       finishes;
137         cycles_t  total_cycles;
138         cycles_t  start;
139         cycles_t  end;
140 };
141
142 extern struct prof_ent prof_ents[MAX_PROFS];
143
144 #define PROF_START(FOO)                                         \
145         do {                                                    \
146                 struct prof_ent *pe = &prof_ents[PROF__##FOO];  \
147                 pe->starts++;                                   \
148                 pe->start = get_cycles();                       \
149         } while (0)
150
151 #define PROF_FINISH(FOO)                                        \
152         do {                                                    \
153                 struct prof_ent *pe = &prof_ents[PROF__##FOO];  \
154                 pe->finishes++;                                 \
155                 pe->end = get_cycles();                         \
156                 pe->total_cycles += (pe->end - pe->start);      \
157         } while (0)
158 #else /* !PORTALS_PROFILING */
159 #define PROF_START(FOO) do {} while(0)
160 #define PROF_FINISH(FOO) do {} while(0)
161 #endif /* PORTALS_PROFILING */
162
163 /* debug.c */
164 extern spinlock_t stack_backtrace_lock;
165
166 void portals_debug_dumpstack(cfs_task_t *tsk);
167 void portals_run_upcall(char **argv);
168 void portals_run_lbug_upcall(char * file, const char *fn, const int line);
169 void portals_debug_dumplog(void);
170 int portals_debug_init(unsigned long bufsize);
171 int portals_debug_cleanup(void);
172 int portals_debug_clear_buffer(void);
173 int portals_debug_mark_buffer(char *text);
174 int portals_debug_set_daemon(unsigned int cmd, unsigned int length,
175                              char *file, unsigned int size);
176 __s32 portals_debug_copy_to_user(char *buf, unsigned long len);
177 /* Use the special GNU C __attribute__ hack to have the compiler check the
178  * printf style argument string against the actual argument count and
179  * types.
180  */
181 void portals_debug_msg(int subsys, int mask, char *file, const char *fn,
182                        const int line, unsigned long stack,
183                        char *format, ...)
184         __attribute__ ((format (printf, 7, 8)));
185 void portals_debug_set_level(unsigned int debug_level);
186
187 extern void kportal_daemonize (char *name);
188 extern void kportal_blockallsigs (void);
189
190 #else  /* !__KERNEL__ */
191 # ifndef DEBUG_SUBSYSTEM
192 #  define DEBUG_SUBSYSTEM S_UNDEFINED
193 # endif
194 # ifdef PORTAL_DEBUG
195 #  undef NDEBUG
196 #  include <assert.h>
197 #  define LASSERT(e)     assert(e)
198 #  define LASSERTF(cond, args...)                                              \
199 do {                                                                           \
200           if (!(cond))                                                         \
201                 CERROR(args);                                                  \
202           assert(cond);                                                        \
203 } while (0)
204 # else
205 #  define LASSERT(e)
206 #  define LASSERTF(cond, args...) do { } while (0)
207 # endif
208 # define printk(format, args...) printf (format, ## args)
209 # define PORTAL_ALLOC(ptr, size) do { (ptr) = malloc(size); } while (0);
210 # define PORTAL_FREE(a, b) do { free(a); } while (0);
211 void portals_debug_dumplog(void);
212 # define portals_debug_msg(subsys, mask, file, fn, line, stack, format, a...) \
213     printf("%02x:%06x (@%lu %s:%s,l. %d %d %lu): " format,                    \
214            (subsys), (mask), (long)time(0), file, fn, line,                   \
215            getpid(), (unsigned long)stack, ## a);
216
217 #undef CWARN
218 #undef CERROR
219 #define CWARN(format, a...) CDEBUG(D_WARNING, format, ## a)
220 #define CERROR(format, a...) CDEBUG(D_ERROR, format, ## a)
221 #endif
222
223 /*
224  * compile-time assertions. @cond has to be constant expression.
225  * ISO C Standard:
226  *
227  *        6.8.4.2  The switch statement
228  *
229  *       ....
230  *
231  *       [#3] The expression of each case label shall be  an  integer
232  *       constant   expression  and  no  two  of  the  case  constant
233  *       expressions in the same switch statement shall have the same
234  *       value  after  conversion...
235  *
236  */
237 #define CLASSERT(cond) ({ switch(42) { case (cond): case 0: break; } })
238
239 /* support decl needed both by kernel and liblustre */
240 char *portals_nid2str(int nal, ptl_nid_t nid, char *str);
241 char *portals_id2str(int nal, ptl_process_id_t nid, char *str);
242
243 #ifndef CURRENT_TIME
244 # define CURRENT_TIME time(0)
245 #endif
246
247 /* --------------------------------------------------------------------
248  * Light-weight trace
249  * Support for temporary event tracing with minimal Heisenberg effect.
250  * All stuff about lwt are put in arch/kp30.h
251  * -------------------------------------------------------------------- */
252
253 struct portals_device_userstate
254 {
255         int          pdu_memhog_pages;
256         cfs_page_t   *pdu_memhog_root_page;
257 };
258
259 #include <libcfs/portals_lib.h>
260
261 /*
262  * USER LEVEL STUFF BELOW
263  */
264
265 #define PORTAL_IOCTL_VERSION 0x00010007
266 #define PING_SYNC       0
267 #define PING_ASYNC      1
268
269 struct portal_ioctl_hdr {
270         __u32 ioc_len;
271         __u32 ioc_version;
272 };
273
274 struct portals_debug_ioctl_data
275 {
276         struct portal_ioctl_hdr hdr;
277         unsigned int subs;
278         unsigned int debug;
279 };
280
281 #define PORTAL_IOC_INIT(data)                           \
282 do {                                                    \
283         memset(&data, 0, sizeof(data));                 \
284         data.ioc_version = PORTAL_IOCTL_VERSION;        \
285         data.ioc_len = sizeof(data);                    \
286 } while (0)
287
288 /* FIXME check conflict with lustre_lib.h */
289 #define PTL_IOC_DEBUG_MASK             _IOWR('f', 250, long)
290
291 static inline int portal_ioctl_packlen(struct portal_ioctl_data *data)
292 {
293         int len = sizeof(*data);
294         len += size_round(data->ioc_inllen1);
295         len += size_round(data->ioc_inllen2);
296         return len;
297 }
298
299 static inline int portal_ioctl_is_invalid(struct portal_ioctl_data *data)
300 {
301         if (data->ioc_len > (1<<30)) {
302                 CERROR ("PORTALS ioctl: ioc_len larger than 1<<30\n");
303                 return 1;
304         }
305         if (data->ioc_inllen1 > (1<<30)) {
306                 CERROR ("PORTALS ioctl: ioc_inllen1 larger than 1<<30\n");
307                 return 1;
308         }
309         if (data->ioc_inllen2 > (1<<30)) {
310                 CERROR ("PORTALS ioctl: ioc_inllen2 larger than 1<<30\n");
311                 return 1;
312         }
313         if (data->ioc_inlbuf1 && !data->ioc_inllen1) {
314                 CERROR ("PORTALS ioctl: inlbuf1 pointer but 0 length\n");
315                 return 1;
316         }
317         if (data->ioc_inlbuf2 && !data->ioc_inllen2) {
318                 CERROR ("PORTALS ioctl: inlbuf2 pointer but 0 length\n");
319                 return 1;
320         }
321         if (data->ioc_pbuf1 && !data->ioc_plen1) {
322                 CERROR ("PORTALS ioctl: pbuf1 pointer but 0 length\n");
323                 return 1;
324         }
325         if (data->ioc_pbuf2 && !data->ioc_plen2) {
326                 CERROR ("PORTALS ioctl: pbuf2 pointer but 0 length\n");
327                 return 1;
328         }
329         if (data->ioc_plen1 && !data->ioc_pbuf1) {
330                 CERROR ("PORTALS ioctl: plen1 nonzero but no pbuf1 pointer\n");
331                 return 1;
332         }
333         if (data->ioc_plen2 && !data->ioc_pbuf2) {
334                 CERROR ("PORTALS ioctl: plen2 nonzero but no pbuf2 pointer\n");
335                 return 1;
336         }
337         if (portal_ioctl_packlen(data) != data->ioc_len ) {
338                 CERROR ("PORTALS ioctl: packlen != ioc_len\n");
339                 return 1;
340         }
341         if (data->ioc_inllen1 &&
342             data->ioc_bulk[data->ioc_inllen1 - 1] != '\0') {
343                 CERROR ("PORTALS ioctl: inlbuf1 not 0 terminated\n");
344                 return 1;
345         }
346         if (data->ioc_inllen2 &&
347             data->ioc_bulk[size_round(data->ioc_inllen1) +
348                            data->ioc_inllen2 - 1] != '\0') {
349                 CERROR ("PORTALS ioctl: inlbuf2 not 0 terminated\n");
350                 return 1;
351         }
352         return 0;
353 }
354
355 #ifndef __KERNEL__
356 static inline int portal_ioctl_pack(struct portal_ioctl_data *data, char **pbuf,
357                                     int max)
358 {
359         char *ptr;
360         struct portal_ioctl_data *overlay;
361         data->ioc_len = portal_ioctl_packlen(data);
362         data->ioc_version = PORTAL_IOCTL_VERSION;
363
364         if (*pbuf && portal_ioctl_packlen(data) > max)
365                 return 1;
366         if (*pbuf == NULL) {
367                 *pbuf = malloc(data->ioc_len);
368         }
369         if (!*pbuf)
370                 return 1;
371         overlay = (struct portal_ioctl_data *)*pbuf;
372         memcpy(*pbuf, data, sizeof(*data));
373
374         ptr = overlay->ioc_bulk;
375         if (data->ioc_inlbuf1)
376                 LOGL(data->ioc_inlbuf1, data->ioc_inllen1, ptr);
377         if (data->ioc_inlbuf2)
378                 LOGL(data->ioc_inlbuf2, data->ioc_inllen2, ptr);
379         if (portal_ioctl_is_invalid(overlay))
380                 return 1;
381
382         return 0;
383 }
384
385 #else
386
387 extern int portal_ioctl_getdata(char *buf, char *end, void *arg);
388
389 #endif
390
391 /* ioctls for manipulating snapshots 30- */
392 #define IOC_PORTAL_TYPE                   'e'
393 #define IOC_PORTAL_MIN_NR                 30
394
395 #define IOC_PORTAL_PING                    _IOWR('e', 30, IOCTL_PORTAL_TYPE)
396
397 #define IOC_PORTAL_CLEAR_DEBUG             _IOWR('e', 32, IOCTL_PORTAL_TYPE)
398 #define IOC_PORTAL_MARK_DEBUG              _IOWR('e', 33, IOCTL_PORTAL_TYPE)
399 #define IOC_PORTAL_PANIC                   _IOWR('e', 34, IOCTL_PORTAL_TYPE)
400 #define IOC_PORTAL_NAL_CMD                 _IOWR('e', 35, IOCTL_PORTAL_TYPE)
401 #define IOC_PORTAL_GET_NID                 _IOWR('e', 36, IOCTL_PORTAL_TYPE)
402 #define IOC_PORTAL_FAIL_NID                _IOWR('e', 37, IOCTL_PORTAL_TYPE)
403 #define IOC_PORTAL_LOOPBACK                _IOWR('e', 38, IOCTL_PORTAL_TYPE)
404 #define IOC_PORTAL_LWT_CONTROL             _IOWR('e', 39, IOCTL_PORTAL_TYPE)
405 #define IOC_PORTAL_LWT_SNAPSHOT            _IOWR('e', 40, IOCTL_PORTAL_TYPE)
406 #define IOC_PORTAL_LWT_LOOKUP_STRING       _IOWR('e', 41, IOCTL_PORTAL_TYPE)
407 #define IOC_PORTAL_MEMHOG                  _IOWR('e', 42, IOCTL_PORTAL_TYPE)
408 #define IOC_PORTAL_MAX_NR                             42
409
410 enum {
411         QSWNAL    = 1,
412         SOCKNAL   = 2,
413         GMNAL     = 3,
414         /*          4 unused */
415         TCPNAL    = 5,
416         ROUTER    = 6,
417         OPENIBNAL = 7,
418         IIBNAL    = 8,
419         LONAL     = 9,
420         RANAL     = 10,
421         VIBNAL    = 11,
422         NAL_ENUM_END_MARKER
423 };
424
425 #define PTL_NALFMT_SIZE             32 /* %u:%u.%u.%u.%u,%u (10+4+4+4+3+5+1) */
426
427 #define NAL_MAX_NR (NAL_ENUM_END_MARKER - 1)
428
429 #define NAL_CMD_REGISTER_PEER_FD     100
430 #define NAL_CMD_CLOSE_CONNECTION     101
431 #define NAL_CMD_REGISTER_MYNID       102
432 #define NAL_CMD_PUSH_CONNECTION      103
433 #define NAL_CMD_GET_CONN             104
434 #define NAL_CMD_DEL_PEER             105
435 #define NAL_CMD_ADD_PEER             106
436 #define NAL_CMD_GET_PEER             107
437 #define NAL_CMD_GET_TXDESC           108
438 #define NAL_CMD_ADD_ROUTE            109
439 #define NAL_CMD_DEL_ROUTE            110
440 #define NAL_CMD_GET_ROUTE            111
441 #define NAL_CMD_NOTIFY_ROUTER        112
442 #define NAL_CMD_ADD_INTERFACE        113
443 #define NAL_CMD_DEL_INTERFACE        114
444 #define NAL_CMD_GET_INTERFACE        115
445
446
447 enum {
448         DEBUG_DAEMON_START       =  1,
449         DEBUG_DAEMON_STOP        =  2,
450         DEBUG_DAEMON_PAUSE       =  3,
451         DEBUG_DAEMON_CONTINUE    =  4,
452 };
453
454
455 enum cfg_record_type {
456         PORTALS_CFG_TYPE = 1,
457         LUSTRE_CFG_TYPE = 123,
458 };
459
460 typedef int (*cfg_record_cb_t)(enum cfg_record_type, int len, void *data);
461
462 /* lustre_id output helper macros */
463 #define DLID4   "%lu/%lu/%lu/%lu"
464
465 #define OLID4(id)                              \
466     (unsigned long)(id)->li_fid.lf_id,         \
467     (unsigned long)(id)->li_fid.lf_group,      \
468     (unsigned long)(id)->li_stc.u.e3s.l3s_ino, \
469     (unsigned long)(id)->li_stc.u.e3s.l3s_gen
470
471 #endif