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 * libcfs/libcfs/darwin/darwin-utils.c
38 * Darwin porting library
39 * Make things easy to port
41 * Author: Phil Schwan <phil@clusterfs.com>
44 #define DEBUG_SUBSYSTEM S_LNET
46 #include <mach/mach_types.h>
48 #include <sys/errno.h>
49 #include <sys/types.h>
50 #include <sys/fcntl.h>
51 #include <lnet/types.h>
53 #include <libcfs/libcfs.h>
59 return (c == ' ' || c == '\t' || c == '\n' || c == '\12');
63 char * strpbrk(const char * cs,const char * ct)
67 for( sc1 = cs; *sc1 != '\0'; ++sc1) {
68 for( sc2 = ct; *sc2 != '\0'; ++sc2) {
76 char * strsep(char **s, const char *ct)
78 char *sbegin = *s, *end;
82 end = strpbrk(sbegin, ct);
90 size_t strnlen(const char * s, size_t count)
94 for (sc = s; count-- && *sc != '\0'; ++sc)
100 strstr(const char *in, const char *str)
107 return (char *) in; // Trivial empty string case
116 } while (strncmp(in, str, len) != 0);
117 return (char *) (in - 1);
121 strrchr(const char *p, int ch)
123 const char *end = p + strlen(p);
125 if (*end == (char)ch)
127 } while (--end >= p);
132 ul2dstr(unsigned long address, char *buf, int len)
134 char *pos = buf + len - 1;
136 if (len <= 0 || !buf)
141 *--pos = address % 10 + '0';
148 * miscellaneous libcfs stuff
152 * Convert server error code to client format.
158 * cc /usr/include/asm/errno.h -E -dM | grep '#define E' | sort -n -k3,3
197 LINUX_ENAMETOOLONG = 36,
200 LINUX_ENOTEMPTY = 39,
231 LINUX_EMULTIHOP = 72,
234 LINUX_EOVERFLOW = 75,
248 LINUX_EDESTADDRREQ = 89,
250 LINUX_EPROTOTYPE = 91,
251 LINUX_ENOPROTOOPT = 92,
252 LINUX_EPROTONOSUPPORT = 93,
253 LINUX_ESOCKTNOSUPPORT = 94,
254 LINUX_EOPNOTSUPP = 95,
255 LINUX_EPFNOSUPPORT = 96,
256 LINUX_EAFNOSUPPORT = 97,
257 LINUX_EADDRINUSE = 98,
258 LINUX_EADDRNOTAVAIL = 99,
259 LINUX_ENETDOWN = 100,
260 LINUX_ENETUNREACH = 101,
261 LINUX_ENETRESET = 102,
262 LINUX_ECONNABORTED = 103,
263 LINUX_ECONNRESET = 104,
266 LINUX_ENOTCONN = 107,
267 LINUX_ESHUTDOWN = 108,
268 LINUX_ETOOMANYREFS = 109,
269 LINUX_ETIMEDOUT = 110,
270 LINUX_ECONNREFUSED = 111,
271 LINUX_EHOSTDOWN = 112,
272 LINUX_EHOSTUNREACH = 113,
273 LINUX_EALREADY = 114,
274 LINUX_EINPROGRESS = 115,
280 LINUX_EREMOTEIO = 121,
282 LINUX_ENOMEDIUM = 123,
283 LINUX_EMEDIUMTYPE = 124,
286 * we don't need these, but for completeness..
288 LINUX_EDEADLOCK = LINUX_EDEADLK,
289 LINUX_EWOULDBLOCK = LINUX_EAGAIN
292 int convert_server_error(__u64 ecode)
297 static int errno_xlate[] = {
298 /* success is always success */
300 [LINUX_EPERM] = EPERM,
301 [LINUX_ENOENT] = ENOENT,
302 [LINUX_ESRCH] = ESRCH,
303 [LINUX_EINTR] = EINTR,
305 [LINUX_ENXIO] = ENXIO,
306 [LINUX_E2BIG] = E2BIG,
307 [LINUX_ENOEXEC] = ENOEXEC,
308 [LINUX_EBADF] = EBADF,
309 [LINUX_ECHILD] = ECHILD,
310 [LINUX_EAGAIN] = EAGAIN,
311 [LINUX_ENOMEM] = ENOMEM,
312 [LINUX_EACCES] = EACCES,
313 [LINUX_EFAULT] = EFAULT,
314 [LINUX_ENOTBLK] = ENOTBLK,
315 [LINUX_EBUSY] = EBUSY,
316 [LINUX_EEXIST] = EEXIST,
317 [LINUX_EXDEV] = EXDEV,
318 [LINUX_ENODEV] = ENODEV,
319 [LINUX_ENOTDIR] = ENOTDIR,
320 [LINUX_EISDIR] = EISDIR,
321 [LINUX_EINVAL] = EINVAL,
322 [LINUX_ENFILE] = ENFILE,
323 [LINUX_EMFILE] = EMFILE,
324 [LINUX_ENOTTY] = ENOTTY,
325 [LINUX_ETXTBSY] = ETXTBSY,
326 [LINUX_EFBIG] = EFBIG,
327 [LINUX_ENOSPC] = ENOSPC,
328 [LINUX_ESPIPE] = ESPIPE,
329 [LINUX_EROFS] = EROFS,
330 [LINUX_EMLINK] = EMLINK,
331 [LINUX_EPIPE] = EPIPE,
333 [LINUX_ERANGE] = ERANGE,
334 [LINUX_EDEADLK] = EDEADLK,
335 [LINUX_ENAMETOOLONG] = ENAMETOOLONG,
336 [LINUX_ENOLCK] = ENOLCK,
337 [LINUX_ENOSYS] = ENOSYS,
338 [LINUX_ENOTEMPTY] = ENOTEMPTY,
339 [LINUX_ELOOP] = ELOOP,
340 [LINUX_ENOMSG] = ENOMSG,
341 [LINUX_EIDRM] = EIDRM,
342 [LINUX_ECHRNG] = EINVAL /* ECHRNG */,
343 [LINUX_EL2NSYNC] = EINVAL /* EL2NSYNC */,
344 [LINUX_EL3HLT] = EINVAL /* EL3HLT */,
345 [LINUX_EL3RST] = EINVAL /* EL3RST */,
346 [LINUX_ELNRNG] = EINVAL /* ELNRNG */,
347 [LINUX_EUNATCH] = EINVAL /* EUNATCH */,
348 [LINUX_ENOCSI] = EINVAL /* ENOCSI */,
349 [LINUX_EL2HLT] = EINVAL /* EL2HLT */,
350 [LINUX_EBADE] = EINVAL /* EBADE */,
351 [LINUX_EBADR] = EBADRPC,
352 [LINUX_EXFULL] = EINVAL /* EXFULL */,
353 [LINUX_ENOANO] = EINVAL /* ENOANO */,
354 [LINUX_EBADRQC] = EINVAL /* EBADRQC */,
355 [LINUX_EBADSLT] = EINVAL /* EBADSLT */,
356 [LINUX_EBFONT] = EINVAL /* EBFONT */,
357 [LINUX_ENOSTR] = EINVAL /* ENOSTR */,
358 [LINUX_ENODATA] = EINVAL /* ENODATA */,
359 [LINUX_ETIME] = EINVAL /* ETIME */,
360 [LINUX_ENOSR] = EINVAL /* ENOSR */,
361 [LINUX_ENONET] = EINVAL /* ENONET */,
362 [LINUX_ENOPKG] = EINVAL /* ENOPKG */,
363 [LINUX_EREMOTE] = EREMOTE,
364 [LINUX_ENOLINK] = EINVAL /* ENOLINK */,
365 [LINUX_EADV] = EINVAL /* EADV */,
366 [LINUX_ESRMNT] = EINVAL /* ESRMNT */,
367 [LINUX_ECOMM] = EINVAL /* ECOMM */,
368 [LINUX_EPROTO] = EPROTOTYPE,
369 [LINUX_EMULTIHOP] = EINVAL /* EMULTIHOP */,
370 [LINUX_EDOTDOT] = EINVAL /* EDOTDOT */,
371 [LINUX_EBADMSG] = EINVAL /* EBADMSG */,
372 [LINUX_EOVERFLOW] = EOVERFLOW,
373 [LINUX_ENOTUNIQ] = EINVAL /* ENOTUNIQ */,
374 [LINUX_EBADFD] = EINVAL /* EBADFD */,
375 [LINUX_EREMCHG] = EINVAL /* EREMCHG */,
376 [LINUX_ELIBACC] = EINVAL /* ELIBACC */,
377 [LINUX_ELIBBAD] = EINVAL /* ELIBBAD */,
378 [LINUX_ELIBSCN] = EINVAL /* ELIBSCN */,
379 [LINUX_ELIBMAX] = EINVAL /* ELIBMAX */,
380 [LINUX_ELIBEXEC] = EINVAL /* ELIBEXEC */,
381 [LINUX_EILSEQ] = EILSEQ,
382 [LINUX_ERESTART] = EINVAL /* because ERESTART is
383 * negative in XNU */,
384 [LINUX_ESTRPIPE] = EINVAL /* ESTRPIPE */,
385 [LINUX_EUSERS] = EUSERS,
386 [LINUX_ENOTSOCK] = ENOTSOCK,
387 [LINUX_EDESTADDRREQ] = EDESTADDRREQ,
388 [LINUX_EMSGSIZE] = EMSGSIZE,
389 [LINUX_EPROTOTYPE] = EPROTOTYPE,
390 [LINUX_ENOPROTOOPT] = ENOPROTOOPT,
391 [LINUX_EPROTONOSUPPORT] = EPROTONOSUPPORT,
392 [LINUX_ESOCKTNOSUPPORT] = ESOCKTNOSUPPORT,
393 [LINUX_EOPNOTSUPP] = EOPNOTSUPP,
394 [LINUX_EPFNOSUPPORT] = EPFNOSUPPORT,
395 [LINUX_EAFNOSUPPORT] = EAFNOSUPPORT,
396 [LINUX_EADDRINUSE] = EADDRINUSE,
397 [LINUX_EADDRNOTAVAIL] = EADDRNOTAVAIL,
398 [LINUX_ENETDOWN] = ENETDOWN,
399 [LINUX_ENETUNREACH] = ENETUNREACH,
400 [LINUX_ENETRESET] = ENETRESET,
401 [LINUX_ECONNABORTED] = ECONNABORTED,
402 [LINUX_ECONNRESET] = ECONNRESET,
403 [LINUX_ENOBUFS] = ENOBUFS,
404 [LINUX_EISCONN] = EISCONN,
405 [LINUX_ENOTCONN] = ENOTCONN,
406 [LINUX_ESHUTDOWN] = ESHUTDOWN,
407 [LINUX_ETOOMANYREFS] = ETOOMANYREFS,
408 [LINUX_ETIMEDOUT] = ETIMEDOUT,
409 [LINUX_ECONNREFUSED] = ECONNREFUSED,
410 [LINUX_EHOSTDOWN] = EHOSTDOWN,
411 [LINUX_EHOSTUNREACH] = EHOSTUNREACH,
412 [LINUX_EALREADY] = EALREADY,
413 [LINUX_EINPROGRESS] = EINPROGRESS,
414 [LINUX_ESTALE] = ESTALE,
415 [LINUX_EUCLEAN] = EINVAL /* EUCLEAN */,
416 [LINUX_ENOTNAM] = EINVAL /* ENOTNAM */,
417 [LINUX_ENAVAIL] = EINVAL /* ENAVAIL */,
418 [LINUX_EISNAM] = EINVAL /* EISNAM */,
419 [LINUX_EREMOTEIO] = EINVAL /* EREMOTEIO */,
420 [LINUX_EDQUOT] = EDQUOT,
421 [LINUX_ENOMEDIUM] = EINVAL /* ENOMEDIUM */,
422 [LINUX_EMEDIUMTYPE] = EINVAL /* EMEDIUMTYPE */,
431 if (code < (sizeof errno_xlate) / (sizeof errno_xlate[0])) {
432 code = errno_xlate[code];
442 LINUX_O_CREAT = 0100,
444 LINUX_O_NOCTTY = 0400,
445 LINUX_O_TRUNC = 01000,
446 LINUX_O_APPEND = 02000,
447 LINUX_O_NONBLOCK = 04000,
448 LINUX_O_NDELAY = LINUX_O_NONBLOCK,
449 LINUX_O_SYNC = 010000,
450 LINUX_O_FSYNC = LINUX_O_SYNC,
451 LINUX_O_ASYNC = 020000,
452 LINUX_O_DIRECT = 040000,
453 LINUX_O_NOFOLLOW = 0400000
456 static inline void obit_convert(int *cflag, int *sflag,
457 unsigned cmask, unsigned smask)
459 if (*cflag & cmask != 0) {
466 * convert <fcntl.h> flag from XNU client to Linux _i386_ server.
468 int convert_client_oflag(int cflag, int *result)
473 obit_convert(&cflag, &sflag, O_RDONLY, LINUX_O_RDONLY);
474 obit_convert(&cflag, &sflag, O_WRONLY, LINUX_O_WRONLY);
475 obit_convert(&cflag, &sflag, O_RDWR, LINUX_O_RDWR);
476 obit_convert(&cflag, &sflag, O_NONBLOCK, LINUX_O_NONBLOCK);
477 obit_convert(&cflag, &sflag, O_APPEND, LINUX_O_APPEND);
478 obit_convert(&cflag, &sflag, O_ASYNC, LINUX_O_ASYNC);
479 obit_convert(&cflag, &sflag, O_FSYNC, LINUX_O_FSYNC);
480 obit_convert(&cflag, &sflag, O_NOFOLLOW, LINUX_O_NOFOLLOW);
481 obit_convert(&cflag, &sflag, O_CREAT, LINUX_O_CREAT);
482 obit_convert(&cflag, &sflag, O_TRUNC, LINUX_O_TRUNC);
483 obit_convert(&cflag, &sflag, O_EXCL, LINUX_O_EXCL);
484 obit_convert(&cflag, &sflag, O_CREAT, LINUX_O_CREAT);
485 obit_convert(&cflag, &sflag, O_NDELAY, LINUX_O_NDELAY);
486 obit_convert(&cflag, &sflag, O_NOCTTY, LINUX_O_NOCTTY);
488 * Some more obscure BSD flags have no Linux counterparts:
504 #else /* !__DARWIN8__ */
505 extern int unix_syscall();
506 extern int unix_syscall_return();
508 extern int ktrsysret();
511 extern int ast_taken();
512 extern int ast_check();
515 extern int syscall_trace();
517 static int is_addr_in_range(void *addr, void *start, void *end)
519 return start <= addr && addr <= end;
522 extern void cfs_thread_agent (void);
524 static int is_last_frame(void *addr)
528 else if (is_addr_in_range(addr, unix_syscall, unix_syscall_return))
530 else if (is_addr_in_range(addr, ktrsysret, ktrace))
532 else if (is_addr_in_range(addr, ast_taken, ast_check))
534 else if (is_addr_in_range(addr, trap, syscall_trace))
536 else if (is_addr_in_range(addr, cfs_thread_agent, cfs_kernel_thread))
542 static void *get_frame(int i)
546 #define CASE(i) case (i): result = __builtin_return_address(i); break
569 panic("impossible frame number: %d\n", i);
575 void cfs_stack_trace_fill(struct cfs_stack_trace *trace)
579 memset(trace, 0, sizeof *trace);
580 for (i = 0; i < ARRAY_SIZE(trace->frame); ++ i) {
584 trace->frame[i] = addr;
585 if (is_last_frame(addr))
590 void *cfs_stack_trace_frame(struct cfs_stack_trace *trace, int frame_no)
592 if (0 <= frame_no && frame_no < ARRAY_SIZE(trace->frame))
593 return trace->frame[frame_no];
597 #endif /* !__DARWIN8__ */