1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
6 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 only,
10 * as published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License version 2 for more details (a copy is included
16 * in the LICENSE file that accompanied this code).
18 * You should have received a copy of the GNU General Public License
19 * version 2 along with this program; If not, see
20 * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
22 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
23 * CA 95054 USA or visit www.sun.com if you need additional information or
29 * Copyright 2008 Sun Microsystems, Inc. All rights reserved
30 * Use is subject to license terms.
33 * This file is part of Lustre, http://www.lustre.org/
34 * Lustre is a trademark of Sun Microsystems, Inc.
36 * lnet/libcfs/darwin/darwin-utils.c
38 * Darwin porting library
39 * Make things easy to port
41 * Author: Phil Schwan <phil@clusterfs.com>
43 #define DEBUG_SUBSYSTEM S_LNET
45 #include <mach/mach_types.h>
47 #include <sys/errno.h>
48 #include <sys/types.h>
49 #include <sys/fcntl.h>
50 #include <lnet/types.h>
52 #include <libcfs/kp30.h>
58 return (c == ' ' || c == '\t' || c == '\n' || c == '\12');
62 char * strpbrk(const char * cs,const char * ct)
66 for( sc1 = cs; *sc1 != '\0'; ++sc1) {
67 for( sc2 = ct; *sc2 != '\0'; ++sc2) {
75 char * strsep(char **s, const char *ct)
77 char *sbegin = *s, *end;
81 end = strpbrk(sbegin, ct);
89 size_t strnlen(const char * s, size_t count)
93 for (sc = s; count-- && *sc != '\0'; ++sc)
99 strstr(const char *in, const char *str)
106 return (char *) in; // Trivial empty string case
115 } while (strncmp(in, str, len) != 0);
116 return (char *) (in - 1);
120 strrchr(const char *p, int ch)
122 const char *end = p + strlen(p);
124 if (*end == (char)ch)
126 } while (--end >= p);
131 ul2dstr(unsigned long address, char *buf, int len)
133 char *pos = buf + len - 1;
135 if (len <= 0 || !buf)
140 *--pos = address % 10 + '0';
147 * miscellaneous libcfs stuff
151 * Convert server error code to client format.
157 * cc /usr/include/asm/errno.h -E -dM | grep '#define E' | sort -n -k3,3
196 LINUX_ENAMETOOLONG = 36,
199 LINUX_ENOTEMPTY = 39,
230 LINUX_EMULTIHOP = 72,
233 LINUX_EOVERFLOW = 75,
247 LINUX_EDESTADDRREQ = 89,
249 LINUX_EPROTOTYPE = 91,
250 LINUX_ENOPROTOOPT = 92,
251 LINUX_EPROTONOSUPPORT = 93,
252 LINUX_ESOCKTNOSUPPORT = 94,
253 LINUX_EOPNOTSUPP = 95,
254 LINUX_EPFNOSUPPORT = 96,
255 LINUX_EAFNOSUPPORT = 97,
256 LINUX_EADDRINUSE = 98,
257 LINUX_EADDRNOTAVAIL = 99,
258 LINUX_ENETDOWN = 100,
259 LINUX_ENETUNREACH = 101,
260 LINUX_ENETRESET = 102,
261 LINUX_ECONNABORTED = 103,
262 LINUX_ECONNRESET = 104,
265 LINUX_ENOTCONN = 107,
266 LINUX_ESHUTDOWN = 108,
267 LINUX_ETOOMANYREFS = 109,
268 LINUX_ETIMEDOUT = 110,
269 LINUX_ECONNREFUSED = 111,
270 LINUX_EHOSTDOWN = 112,
271 LINUX_EHOSTUNREACH = 113,
272 LINUX_EALREADY = 114,
273 LINUX_EINPROGRESS = 115,
279 LINUX_EREMOTEIO = 121,
281 LINUX_ENOMEDIUM = 123,
282 LINUX_EMEDIUMTYPE = 124,
285 * we don't need these, but for completeness..
287 LINUX_EDEADLOCK = LINUX_EDEADLK,
288 LINUX_EWOULDBLOCK = LINUX_EAGAIN
291 int convert_server_error(__u64 ecode)
296 static int errno_xlate[] = {
297 /* success is always success */
299 [LINUX_EPERM] = EPERM,
300 [LINUX_ENOENT] = ENOENT,
301 [LINUX_ESRCH] = ESRCH,
302 [LINUX_EINTR] = EINTR,
304 [LINUX_ENXIO] = ENXIO,
305 [LINUX_E2BIG] = E2BIG,
306 [LINUX_ENOEXEC] = ENOEXEC,
307 [LINUX_EBADF] = EBADF,
308 [LINUX_ECHILD] = ECHILD,
309 [LINUX_EAGAIN] = EAGAIN,
310 [LINUX_ENOMEM] = ENOMEM,
311 [LINUX_EACCES] = EACCES,
312 [LINUX_EFAULT] = EFAULT,
313 [LINUX_ENOTBLK] = ENOTBLK,
314 [LINUX_EBUSY] = EBUSY,
315 [LINUX_EEXIST] = EEXIST,
316 [LINUX_EXDEV] = EXDEV,
317 [LINUX_ENODEV] = ENODEV,
318 [LINUX_ENOTDIR] = ENOTDIR,
319 [LINUX_EISDIR] = EISDIR,
320 [LINUX_EINVAL] = EINVAL,
321 [LINUX_ENFILE] = ENFILE,
322 [LINUX_EMFILE] = EMFILE,
323 [LINUX_ENOTTY] = ENOTTY,
324 [LINUX_ETXTBSY] = ETXTBSY,
325 [LINUX_EFBIG] = EFBIG,
326 [LINUX_ENOSPC] = ENOSPC,
327 [LINUX_ESPIPE] = ESPIPE,
328 [LINUX_EROFS] = EROFS,
329 [LINUX_EMLINK] = EMLINK,
330 [LINUX_EPIPE] = EPIPE,
332 [LINUX_ERANGE] = ERANGE,
333 [LINUX_EDEADLK] = EDEADLK,
334 [LINUX_ENAMETOOLONG] = ENAMETOOLONG,
335 [LINUX_ENOLCK] = ENOLCK,
336 [LINUX_ENOSYS] = ENOSYS,
337 [LINUX_ENOTEMPTY] = ENOTEMPTY,
338 [LINUX_ELOOP] = ELOOP,
339 [LINUX_ENOMSG] = ENOMSG,
340 [LINUX_EIDRM] = EIDRM,
341 [LINUX_ECHRNG] = EINVAL /* ECHRNG */,
342 [LINUX_EL2NSYNC] = EINVAL /* EL2NSYNC */,
343 [LINUX_EL3HLT] = EINVAL /* EL3HLT */,
344 [LINUX_EL3RST] = EINVAL /* EL3RST */,
345 [LINUX_ELNRNG] = EINVAL /* ELNRNG */,
346 [LINUX_EUNATCH] = EINVAL /* EUNATCH */,
347 [LINUX_ENOCSI] = EINVAL /* ENOCSI */,
348 [LINUX_EL2HLT] = EINVAL /* EL2HLT */,
349 [LINUX_EBADE] = EINVAL /* EBADE */,
350 [LINUX_EBADR] = EBADRPC,
351 [LINUX_EXFULL] = EINVAL /* EXFULL */,
352 [LINUX_ENOANO] = EINVAL /* ENOANO */,
353 [LINUX_EBADRQC] = EINVAL /* EBADRQC */,
354 [LINUX_EBADSLT] = EINVAL /* EBADSLT */,
355 [LINUX_EBFONT] = EINVAL /* EBFONT */,
356 [LINUX_ENOSTR] = EINVAL /* ENOSTR */,
357 [LINUX_ENODATA] = EINVAL /* ENODATA */,
358 [LINUX_ETIME] = EINVAL /* ETIME */,
359 [LINUX_ENOSR] = EINVAL /* ENOSR */,
360 [LINUX_ENONET] = EINVAL /* ENONET */,
361 [LINUX_ENOPKG] = EINVAL /* ENOPKG */,
362 [LINUX_EREMOTE] = EREMOTE,
363 [LINUX_ENOLINK] = EINVAL /* ENOLINK */,
364 [LINUX_EADV] = EINVAL /* EADV */,
365 [LINUX_ESRMNT] = EINVAL /* ESRMNT */,
366 [LINUX_ECOMM] = EINVAL /* ECOMM */,
367 [LINUX_EPROTO] = EPROTOTYPE,
368 [LINUX_EMULTIHOP] = EINVAL /* EMULTIHOP */,
369 [LINUX_EDOTDOT] = EINVAL /* EDOTDOT */,
370 [LINUX_EBADMSG] = EINVAL /* EBADMSG */,
371 [LINUX_EOVERFLOW] = EOVERFLOW,
372 [LINUX_ENOTUNIQ] = EINVAL /* ENOTUNIQ */,
373 [LINUX_EBADFD] = EINVAL /* EBADFD */,
374 [LINUX_EREMCHG] = EINVAL /* EREMCHG */,
375 [LINUX_ELIBACC] = EINVAL /* ELIBACC */,
376 [LINUX_ELIBBAD] = EINVAL /* ELIBBAD */,
377 [LINUX_ELIBSCN] = EINVAL /* ELIBSCN */,
378 [LINUX_ELIBMAX] = EINVAL /* ELIBMAX */,
379 [LINUX_ELIBEXEC] = EINVAL /* ELIBEXEC */,
380 [LINUX_EILSEQ] = EILSEQ,
381 [LINUX_ERESTART] = EINVAL /* because ERESTART is
382 * negative in XNU */,
383 [LINUX_ESTRPIPE] = EINVAL /* ESTRPIPE */,
384 [LINUX_EUSERS] = EUSERS,
385 [LINUX_ENOTSOCK] = ENOTSOCK,
386 [LINUX_EDESTADDRREQ] = EDESTADDRREQ,
387 [LINUX_EMSGSIZE] = EMSGSIZE,
388 [LINUX_EPROTOTYPE] = EPROTOTYPE,
389 [LINUX_ENOPROTOOPT] = ENOPROTOOPT,
390 [LINUX_EPROTONOSUPPORT] = EPROTONOSUPPORT,
391 [LINUX_ESOCKTNOSUPPORT] = ESOCKTNOSUPPORT,
392 [LINUX_EOPNOTSUPP] = EOPNOTSUPP,
393 [LINUX_EPFNOSUPPORT] = EPFNOSUPPORT,
394 [LINUX_EAFNOSUPPORT] = EAFNOSUPPORT,
395 [LINUX_EADDRINUSE] = EADDRINUSE,
396 [LINUX_EADDRNOTAVAIL] = EADDRNOTAVAIL,
397 [LINUX_ENETDOWN] = ENETDOWN,
398 [LINUX_ENETUNREACH] = ENETUNREACH,
399 [LINUX_ENETRESET] = ENETRESET,
400 [LINUX_ECONNABORTED] = ECONNABORTED,
401 [LINUX_ECONNRESET] = ECONNRESET,
402 [LINUX_ENOBUFS] = ENOBUFS,
403 [LINUX_EISCONN] = EISCONN,
404 [LINUX_ENOTCONN] = ENOTCONN,
405 [LINUX_ESHUTDOWN] = ESHUTDOWN,
406 [LINUX_ETOOMANYREFS] = ETOOMANYREFS,
407 [LINUX_ETIMEDOUT] = ETIMEDOUT,
408 [LINUX_ECONNREFUSED] = ECONNREFUSED,
409 [LINUX_EHOSTDOWN] = EHOSTDOWN,
410 [LINUX_EHOSTUNREACH] = EHOSTUNREACH,
411 [LINUX_EALREADY] = EALREADY,
412 [LINUX_EINPROGRESS] = EINPROGRESS,
413 [LINUX_ESTALE] = ESTALE,
414 [LINUX_EUCLEAN] = EINVAL /* EUCLEAN */,
415 [LINUX_ENOTNAM] = EINVAL /* ENOTNAM */,
416 [LINUX_ENAVAIL] = EINVAL /* ENAVAIL */,
417 [LINUX_EISNAM] = EINVAL /* EISNAM */,
418 [LINUX_EREMOTEIO] = EINVAL /* EREMOTEIO */,
419 [LINUX_EDQUOT] = EDQUOT,
420 [LINUX_ENOMEDIUM] = EINVAL /* ENOMEDIUM */,
421 [LINUX_EMEDIUMTYPE] = EINVAL /* EMEDIUMTYPE */,
430 if (code < (sizeof errno_xlate) / (sizeof errno_xlate[0])) {
431 code = errno_xlate[code];
441 LINUX_O_CREAT = 0100,
443 LINUX_O_NOCTTY = 0400,
444 LINUX_O_TRUNC = 01000,
445 LINUX_O_APPEND = 02000,
446 LINUX_O_NONBLOCK = 04000,
447 LINUX_O_NDELAY = LINUX_O_NONBLOCK,
448 LINUX_O_SYNC = 010000,
449 LINUX_O_FSYNC = LINUX_O_SYNC,
450 LINUX_O_ASYNC = 020000,
451 LINUX_O_DIRECT = 040000,
452 LINUX_O_NOFOLLOW = 0400000
455 static inline void obit_convert(int *cflag, int *sflag,
456 unsigned cmask, unsigned smask)
458 if (*cflag & cmask != 0) {
465 * convert <fcntl.h> flag from XNU client to Linux _i386_ server.
467 int convert_client_oflag(int cflag, int *result)
472 obit_convert(&cflag, &sflag, O_RDONLY, LINUX_O_RDONLY);
473 obit_convert(&cflag, &sflag, O_WRONLY, LINUX_O_WRONLY);
474 obit_convert(&cflag, &sflag, O_RDWR, LINUX_O_RDWR);
475 obit_convert(&cflag, &sflag, O_NONBLOCK, LINUX_O_NONBLOCK);
476 obit_convert(&cflag, &sflag, O_APPEND, LINUX_O_APPEND);
477 obit_convert(&cflag, &sflag, O_ASYNC, LINUX_O_ASYNC);
478 obit_convert(&cflag, &sflag, O_FSYNC, LINUX_O_FSYNC);
479 obit_convert(&cflag, &sflag, O_NOFOLLOW, LINUX_O_NOFOLLOW);
480 obit_convert(&cflag, &sflag, O_CREAT, LINUX_O_CREAT);
481 obit_convert(&cflag, &sflag, O_TRUNC, LINUX_O_TRUNC);
482 obit_convert(&cflag, &sflag, O_EXCL, LINUX_O_EXCL);
483 obit_convert(&cflag, &sflag, O_CREAT, LINUX_O_CREAT);
484 obit_convert(&cflag, &sflag, O_NDELAY, LINUX_O_NDELAY);
485 obit_convert(&cflag, &sflag, O_NOCTTY, LINUX_O_NOCTTY);
487 * Some more obscure BSD flags have no Linux counterparts:
503 #else /* !__DARWIN8__ */
504 extern int unix_syscall();
505 extern int unix_syscall_return();
507 extern int ktrsysret();
510 extern int ast_taken();
511 extern int ast_check();
514 extern int syscall_trace();
516 static int is_addr_in_range(void *addr, void *start, void *end)
518 return start <= addr && addr <= end;
521 extern void cfs_thread_agent (void);
523 static int is_last_frame(void *addr)
527 else if (is_addr_in_range(addr, unix_syscall, unix_syscall_return))
529 else if (is_addr_in_range(addr, ktrsysret, ktrace))
531 else if (is_addr_in_range(addr, ast_taken, ast_check))
533 else if (is_addr_in_range(addr, trap, syscall_trace))
535 else if (is_addr_in_range(addr, cfs_thread_agent, cfs_kernel_thread))
541 static void *get_frame(int i)
545 #define CASE(i) case (i): result = __builtin_return_address(i); break
568 panic("impossible frame number: %d\n", i);
574 void cfs_stack_trace_fill(struct cfs_stack_trace *trace)
578 memset(trace, 0, sizeof *trace);
579 for (i = 0; i < sizeof_array(trace->frame); ++ i) {
583 trace->frame[i] = addr;
584 if (is_last_frame(addr))
589 void *cfs_stack_trace_frame(struct cfs_stack_trace *trace, int frame_no)
591 if (0 <= frame_no && frame_no < sizeof_array(trace->frame))
592 return trace->frame[frame_no];
596 #endif /* !__DARWIN8__ */