]> git.saurik.com Git - apple/system_cmds.git/blob - system_cmds-597.1.1/fs_usage.tproj/fs_usage.c
system_cmds-597.90.1.tar.gz
[apple/system_cmds.git] / system_cmds-597.1.1 / fs_usage.tproj / fs_usage.c
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.0 (the 'License'). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
20 * under the License."
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24
25 /*
26 cc -I/System/Library/Frameworks/System.framework/Versions/B/PrivateHeaders -DPRIVATE -D__APPLE_PRIVATE -arch x86_64 -arch i386 -O -lutil -o fs_usage fs_usage.c
27 */
28
29 #include <stdlib.h>
30 #include <stdio.h>
31 #include <signal.h>
32 #include <strings.h>
33 #include <nlist.h>
34 #include <fcntl.h>
35 #include <aio.h>
36 #include <string.h>
37 #include <dirent.h>
38 #include <libc.h>
39 #include <termios.h>
40 #include <errno.h>
41 #include <err.h>
42 #include <libutil.h>
43
44 #include <sys/types.h>
45 #include <sys/param.h>
46 #include <sys/time.h>
47 #include <sys/ioctl.h>
48 #include <sys/socket.h>
49 #include <sys/mman.h>
50 #include <sys/sysctl.h>
51 #include <sys/disk.h>
52 #include <sys/file.h>
53
54 #ifndef KERNEL_PRIVATE
55 #define KERNEL_PRIVATE
56 #include <sys/kdebug.h>
57 #undef KERNEL_PRIVATE
58 #else
59 #include <sys/kdebug.h>
60 #endif /*KERNEL_PRIVATE*/
61
62 #import <mach/clock_types.h>
63 #import <mach/mach_time.h>
64
65
66
67 #define F_OPENFROM 56 /* SPI: open a file relative to fd (must be a dir) */
68 #define F_UNLINKFROM 57 /* SPI: open a file relative to fd (must be a dir) */
69 #define F_CHECK_OPENEVT 58 /* SPI: if a process is marked OPENEVT, or in O_EVTONLY on opens of this vnode */
70
71
72 #ifndef RAW_VERSION1
73 typedef struct {
74 int version_no;
75 int thread_count;
76 uint64_t TOD_secs;
77 uint32_t TOD_usecs;
78 } RAW_header;
79
80 #define RAW_VERSION0 0x55aa0000
81 #define RAW_VERSION1 0x55aa0101
82 #endif
83
84
85 #define MAXINDEX 2048
86
87 typedef struct LibraryRange {
88 uint64_t b_address;
89 uint64_t e_address;
90 } LibraryRange;
91
92 LibraryRange framework32;
93 LibraryRange framework64;
94
95
96 #define TEXT_R 0
97 #define DATA_R 1
98 #define OBJC_R 2
99 #define IMPORT_R 3
100 #define UNICODE_R 4
101 #define IMAGE_R 5
102 #define LINKEDIT_R 6
103
104
105 char *frameworkType[] = {
106 "<TEXT> ",
107 "<DATA> ",
108 "<OBJC> ",
109 "<IMPORT> ",
110 "<UNICODE> ",
111 "<IMAGE> ",
112 "<LINKEDIT>",
113 };
114
115
116 typedef struct LibraryInfo {
117 uint64_t b_address;
118 uint64_t e_address;
119 int r_type;
120 char *name;
121 } LibraryInfo;
122
123 LibraryInfo frameworkInfo[MAXINDEX];
124 int numFrameworks = 0;
125
126
127 /*
128 * MAXCOLS controls when extra data kicks in.
129 * MAX_WIDE_MODE_COLS controls -w mode to get even wider data in path.
130 * If NUMPARMS changes to match the kernel, it will automatically
131 * get reflected in the -w mode output.
132 */
133 #define NUMPARMS 23
134 #define PATHLENGTH (NUMPARMS*sizeof(uintptr_t))
135
136 #define MAXCOLS 132
137 #define MAX_WIDE_MODE_COLS (PATHLENGTH + 80)
138 #define MAXWIDTH MAX_WIDE_MODE_COLS + 64
139
140 #define MAX_PATHNAMES 3
141 #define MAX_SCALL_PATHNAMES 2
142
143 typedef struct th_info *th_info_t;
144
145 struct lookup {
146 uintptr_t pathname[NUMPARMS + 1]; /* add room for null terminator */
147 };
148
149 struct th_info {
150 th_info_t next;
151 uintptr_t thread;
152 uintptr_t child_thread;
153
154 int in_filemgr;
155 int in_hfs_update;
156 int pid;
157 int type;
158 int arg1;
159 int arg2;
160 int arg3;
161 int arg4;
162 int arg5;
163 int arg6;
164 int arg7;
165 int arg8;
166 int waited;
167 double stime;
168 uint64_t vnodeid;
169 char *nameptr;
170 uintptr_t *pathptr;
171 int pn_scall_index;
172 int pn_work_index;
173 struct lookup lookups[MAX_PATHNAMES];
174 };
175
176
177 typedef struct threadmap * threadmap_t;
178
179 struct threadmap {
180 threadmap_t tm_next;
181
182 uintptr_t tm_thread;
183 unsigned int tm_setsize; /* this is a bit count */
184 unsigned long *tm_setptr; /* file descripter bitmap */
185 char tm_command[MAXCOMLEN + 1];
186 };
187
188
189 typedef struct vnode_info * vnode_info_t;
190
191 struct vnode_info {
192 vnode_info_t vn_next;
193 uint64_t vn_id;
194 uintptr_t vn_pathname[NUMPARMS + 1];
195 };
196
197 typedef struct meta_info * meta_info_t;
198
199 struct meta_info {
200 meta_info_t m_next;
201 uint64_t m_blkno;
202 char *m_nameptr;
203 };
204
205 #define HASH_SIZE 1024
206 #define HASH_MASK (HASH_SIZE - 1)
207
208 th_info_t th_info_hash[HASH_SIZE];
209 th_info_t th_info_freelist;
210
211 threadmap_t threadmap_hash[HASH_SIZE];
212 threadmap_t threadmap_freelist;
213
214
215 #define VN_HASH_SHIFT 3
216 #define VN_HASH_SIZE 16384
217 #define VN_HASH_MASK (VN_HASH_SIZE - 1)
218
219 vnode_info_t vn_info_hash[VN_HASH_SIZE];
220 meta_info_t m_info_hash[VN_HASH_SIZE];
221
222
223 int filemgr_in_progress = 0;
224 int need_new_map = 1;
225 int bias_secs = 0;
226 long last_time;
227 int wideflag = 0;
228 int columns = 0;
229
230 int one_good_pid = 0; /* Used to fail gracefully when bad pids given */
231 int select_pid_mode = 0; /* Flag set indicates that output is restricted
232 to selected pids or commands */
233
234 char *arguments = 0;
235 int argmax = 0;
236
237
238 #define USLEEP_MIN 1
239 #define USLEEP_BEHIND 2
240 #define USLEEP_MAX 32
241 int usleep_ms = USLEEP_MIN;
242
243 /*
244 * Network only or filesystem only output filter
245 * Default of zero means report all activity - no filtering
246 */
247 #define FILESYS_FILTER 0x01
248 #define NETWORK_FILTER 0x02
249 #define EXEC_FILTER 0x08
250 #define PATHNAME_FILTER 0x10
251 #define DISKIO_FILTER 0x20
252 #define DEFAULT_DO_NOT_FILTER 0x00
253
254 int filter_mode = DEFAULT_DO_NOT_FILTER;
255
256 boolean_t show_cachehits = FALSE;
257
258 #define NFS_DEV -1
259 #define CS_DEV -2
260
261 struct diskrec {
262 struct diskrec *next;
263 char *diskname;
264 int dev;
265 };
266
267 struct diskio {
268 struct diskio *next;
269 struct diskio *prev;
270 int type;
271 int bp;
272 int dev;
273 int blkno;
274 int iosize;
275 int io_errno;
276 int is_meta;
277 uint64_t vnodeid;
278 uintptr_t issuing_thread;
279 uintptr_t completion_thread;
280 char issuing_command[MAXCOMLEN];
281 double issued_time;
282 double completed_time;
283 uint32_t bc_info;
284 };
285
286 struct diskrec *disk_list = NULL;
287 struct diskio *free_diskios = NULL;
288 struct diskio *busy_diskios = NULL;
289
290
291 struct diskio *insert_diskio();
292 struct diskio *find_diskio(int);
293 struct diskio *complete_diskio();
294 void free_diskio();
295 void print_diskio();
296
297 int check_filter_mode(struct th_info *, int, int, int, char *);
298 void format_print(struct th_info *, char *, uintptr_t, int, uintptr_t, uintptr_t, uintptr_t, uintptr_t, int, double, double, int, char *, struct diskio *);
299 void enter_event_now(uintptr_t, int, kd_buf *, char *, double);
300 void enter_event(uintptr_t, int, kd_buf *, char *, double);
301 void exit_event(char *, uintptr_t, int, uintptr_t, uintptr_t, uintptr_t, uintptr_t, int, double);
302 void extend_syscall(uintptr_t, int, kd_buf *);
303
304 char *generate_cs_disk_name(int, char *s);
305 char *find_disk_name(int);
306 void cache_disk_names();
307 void recache_disk_names();
308
309 void lookup_name(uint64_t user_addr, char **type, char **name);
310 int ReadSharedCacheMap(const char *, LibraryRange *, char *);
311 void SortFrameworkAddresses();
312
313 void fs_usage_fd_set(uintptr_t, unsigned int);
314 int fs_usage_fd_isset(uintptr_t, unsigned int);
315 void fs_usage_fd_clear(uintptr_t, unsigned int);
316
317 void init_arguments_buffer();
318 int get_real_command_name(int, char *, int);
319
320 void delete_all_events();
321 void delete_event(th_info_t);
322 th_info_t add_event(uintptr_t, int);
323 th_info_t find_event(uintptr_t, int);
324 void mark_thread_waited(uintptr_t);
325
326 void read_command_map();
327 void delete_all_map_entries();
328 void create_map_entry(uintptr_t, int, char *);
329 void delete_map_entry(uintptr_t);
330 threadmap_t find_map_entry(uintptr_t);
331
332 char *add_vnode_name(uint64_t, char *);
333 char *find_vnode_name(uint64_t);
334 char *find_meta_name(uint64_t);
335 void add_meta_name(uint64_t, char *);
336
337 void getdivisor();
338 void argtopid();
339 void set_remove();
340 void set_pidcheck();
341 void set_pidexclude();
342 int quit();
343
344
345 #define CLASS_MASK 0xff000000
346 #define CSC_MASK 0xffff0000
347 #define BSC_INDEX(type) ((type >> 2) & 0x3fff)
348
349
350 #define TRACE_DATA_NEWTHREAD 0x07000004
351 #define TRACE_DATA_EXEC 0x07000008
352 #define TRACE_STRING_NEWTHREAD 0x07010004
353 #define TRACE_STRING_EXEC 0x07010008
354
355 #define MACH_vmfault 0x01300008
356 #define MACH_pageout 0x01300004
357 #define MACH_sched 0x01400000
358 #define MACH_stkhandoff 0x01400008
359 #define MACH_idle 0x01400024
360 #define VFS_LOOKUP 0x03010090
361 #define VFS_ALIAS_VP 0x03010094
362
363 #define BSC_thread_terminate 0x040c05a4
364
365 #define HFS_update 0x3018000
366 #define HFS_modify_block_end 0x3018004
367
368 #define Throttled 0x3010184
369 #define SPEC_ioctl 0x3060000
370 #define SPEC_unmap_info 0x3060004
371 #define proc_exit 0x4010004
372
373 #define BC_IO_HIT 0x03070010
374 #define BC_IO_HIT_STALLED 0x03070020
375 #define BC_IO_MISS 0x03070040
376 #define BC_IO_MISS_CUT_THROUGH 0x03070080
377 #define BC_PLAYBACK_IO 0x03070100
378 #define BC_STR(s) ( \
379 (s == BC_IO_HIT) ? "HIT" : \
380 (s == BC_IO_HIT_STALLED) ? "STALL" : \
381 (s == BC_IO_MISS) ? "MISS" : \
382 (s == BC_IO_MISS_CUT_THROUGH) ? "CUT" : \
383 (s == BC_PLAYBACK_IO) ? "PLBK" : \
384 (s == 0x0) ? "NONE" : "UNKN" )
385
386 #ifndef DKIO_NOCACHE
387 #define DKIO_NOCACHE 0x80
388 #endif
389
390 #define P_DISKIO_READ (DKIO_READ << 2)
391 #define P_DISKIO_ASYNC (DKIO_ASYNC << 2)
392 #define P_DISKIO_META (DKIO_META << 2)
393 #define P_DISKIO_PAGING (DKIO_PAGING << 2)
394 #define P_DISKIO_THROTTLE (DKIO_THROTTLE << 2)
395 #define P_DISKIO_PASSIVE (DKIO_PASSIVE << 2)
396 #define P_DISKIO_NOCACHE (DKIO_NOCACHE << 2)
397 #define P_DISKIO_TIER_MASK (DKIO_TIER_MASK << 2)
398 #define P_DISKIO_TIER_SHIFT (DKIO_TIER_SHIFT + 2)
399
400 #define P_DISKIO (FSDBG_CODE(DBG_DKRW, 0))
401 #define P_DISKIO_DONE (P_DISKIO | (DKIO_DONE << 2))
402 #define P_DISKIO_TYPE (P_DISKIO | P_DISKIO_READ | P_DISKIO_META | P_DISKIO_PAGING)
403 #define P_DISKIO_MASK (CSC_MASK | 0x4)
404
405 #define P_WrData (P_DISKIO)
406 #define P_RdData (P_DISKIO | P_DISKIO_READ)
407 #define P_WrMeta (P_DISKIO | P_DISKIO_META)
408 #define P_RdMeta (P_DISKIO | P_DISKIO_META | P_DISKIO_READ)
409 #define P_PgOut (P_DISKIO | P_DISKIO_PAGING)
410 #define P_PgIn (P_DISKIO | P_DISKIO_PAGING | P_DISKIO_READ)
411
412 #define P_CS_Class 0x0a000000 // DBG_CORESTORAGE
413 #define P_CS_Type_Mask 0xfffffff0
414 #define P_CS_IO_Done 0x00000004
415
416 #define P_CS_ReadChunk 0x0a000200 // chopped up request
417 #define P_CS_WriteChunk 0x0a000210
418 #define P_CS_MetaRead 0x0a000300 // meta data
419 #define P_CS_MetaWrite 0x0a000310
420 #define P_CS_TransformRead 0x0a000500 // background transform
421 #define P_CS_TransformWrite 0x0a000510
422 #define P_CS_MigrationRead 0x0a000600 // composite disk block migration
423 #define P_CS_MigrationWrite 0x0a000610
424 #define P_CS_SYNC_DISK 0x0a010000
425
426 #define MSC_map_fd 0x010c00ac
427
428 #define BSC_BASE 0x040C0000
429 #define MSC_BASE 0x010C0000
430
431 // Network related codes
432 #define BSC_recvmsg 0x040C006C
433 #define BSC_sendmsg 0x040C0070
434 #define BSC_recvfrom 0x040C0074
435 #define BSC_accept 0x040C0078
436 #define BSC_select 0x040C0174
437 #define BSC_socket 0x040C0184
438 #define BSC_connect 0x040C0188
439 #define BSC_bind 0x040C01A0
440 #define BSC_listen 0x040C01A8
441 #define BSC_sendto 0x040C0214
442 #define BSC_socketpair 0x040C021C
443 #define BSC_recvmsg_nocancel 0x040c0644
444 #define BSC_sendmsg_nocancel 0x040c0648
445 #define BSC_recvfrom_nocancel 0x040c064c
446 #define BSC_accept_nocancel 0x040c0650
447 #define BSC_connect_nocancel 0x040c0664
448 #define BSC_sendto_nocancel 0x040c0674
449
450 #define BSC_exit 0x040C0004
451 #define BSC_read 0x040C000C
452 #define BSC_write 0x040C0010
453 #define BSC_open 0x040C0014
454 #define BSC_close 0x040C0018
455 #define BSC_link 0x040C0024
456 #define BSC_unlink 0x040C0028
457 #define BSC_chdir 0x040c0030
458 #define BSC_fchdir 0x040c0034
459 #define BSC_mknod 0x040C0038
460 #define BSC_chmod 0x040C003C
461 #define BSC_chown 0x040C0040
462 #define BSC_getfsstat 0x040C0048
463 #define BSC_access 0x040C0084
464 #define BSC_chflags 0x040C0088
465 #define BSC_fchflags 0x040C008C
466 #define BSC_sync 0x040C0090
467 #define BSC_dup 0x040C00A4
468 #define BSC_ioctl 0x040C00D8
469 #define BSC_revoke 0x040C00E0
470 #define BSC_symlink 0x040C00E4
471 #define BSC_readlink 0x040C00E8
472 #define BSC_execve 0x040C00EC
473 #define BSC_umask 0x040C00F0
474 #define BSC_chroot 0x040C00F4
475 #define BSC_msync 0x040C0104
476 #define BSC_dup2 0x040C0168
477 #define BSC_fcntl 0x040C0170
478 #define BSC_fsync 0x040C017C
479 #define BSC_readv 0x040C01E0
480 #define BSC_writev 0x040C01E4
481 #define BSC_fchown 0x040C01EC
482 #define BSC_fchmod 0x040C01F0
483 #define BSC_rename 0x040C0200
484 #define BSC_flock 0x040C020C
485 #define BSC_mkfifo 0x040C0210
486 #define BSC_mkdir 0x040C0220
487 #define BSC_rmdir 0x040C0224
488 #define BSC_utimes 0x040C0228
489 #define BSC_futimes 0x040C022C
490 #define BSC_pread 0x040C0264
491 #define BSC_pwrite 0x040C0268
492 #define BSC_statfs 0x040C0274
493 #define BSC_fstatfs 0x040C0278
494 #define BSC_unmount 0x040C027C
495 #define BSC_mount 0x040C029C
496 #define BSC_fdatasync 0x040C02EC
497 #define BSC_stat 0x040C02F0
498 #define BSC_fstat 0x040C02F4
499 #define BSC_lstat 0x040C02F8
500 #define BSC_pathconf 0x040C02FC
501 #define BSC_fpathconf 0x040C0300
502 #define BSC_getdirentries 0x040C0310
503 #define BSC_mmap 0x040c0314
504 #define BSC_lseek 0x040c031c
505 #define BSC_truncate 0x040C0320
506 #define BSC_ftruncate 0x040C0324
507 #define BSC_undelete 0x040C0334
508 #define BSC_open_dprotected_np 0x040C0360
509 #define BSC_getattrlist 0x040C0370
510 #define BSC_setattrlist 0x040C0374
511 #define BSC_getdirentriesattr 0x040C0378
512 #define BSC_exchangedata 0x040C037C
513 #define BSC_checkuseraccess 0x040C0380
514 #define BSC_searchfs 0x040C0384
515 #define BSC_delete 0x040C0388
516 #define BSC_copyfile 0x040C038C
517 #define BSC_fgetattrlist 0x040C0390
518 #define BSC_fsetattrlist 0x040C0394
519 #define BSC_getxattr 0x040C03A8
520 #define BSC_fgetxattr 0x040C03AC
521 #define BSC_setxattr 0x040C03B0
522 #define BSC_fsetxattr 0x040C03B4
523 #define BSC_removexattr 0x040C03B8
524 #define BSC_fremovexattr 0x040C03BC
525 #define BSC_listxattr 0x040C03C0
526 #define BSC_flistxattr 0x040C03C4
527 #define BSC_fsctl 0x040C03C8
528 #define BSC_posix_spawn 0x040C03D0
529 #define BSC_ffsctl 0x040C03D4
530 #define BSC_open_extended 0x040C0454
531 #define BSC_umask_extended 0x040C0458
532 #define BSC_stat_extended 0x040C045C
533 #define BSC_lstat_extended 0x040C0460
534 #define BSC_fstat_extended 0x040C0464
535 #define BSC_chmod_extended 0x040C0468
536 #define BSC_fchmod_extended 0x040C046C
537 #define BSC_access_extended 0x040C0470
538 #define BSC_mkfifo_extended 0x040C048C
539 #define BSC_mkdir_extended 0x040C0490
540 #define BSC_aio_fsync 0x040C04E4
541 #define BSC_aio_return 0x040C04E8
542 #define BSC_aio_suspend 0x040C04EC
543 #define BSC_aio_cancel 0x040C04F0
544 #define BSC_aio_error 0x040C04F4
545 #define BSC_aio_read 0x040C04F8
546 #define BSC_aio_write 0x040C04FC
547 #define BSC_lio_listio 0x040C0500
548 #define BSC_sendfile 0x040C0544
549 #define BSC_stat64 0x040C0548
550 #define BSC_fstat64 0x040C054C
551 #define BSC_lstat64 0x040C0550
552 #define BSC_stat64_extended 0x040C0554
553 #define BSC_lstat64_extended 0x040C0558
554 #define BSC_fstat64_extended 0x040C055C
555 #define BSC_getdirentries64 0x040C0560
556 #define BSC_statfs64 0x040C0564
557 #define BSC_fstatfs64 0x040C0568
558 #define BSC_getfsstat64 0x040C056C
559 #define BSC_pthread_chdir 0x040C0570
560 #define BSC_pthread_fchdir 0x040C0574
561 #define BSC_lchown 0x040C05B0
562
563 #define BSC_read_nocancel 0x040c0630
564 #define BSC_write_nocancel 0x040c0634
565 #define BSC_open_nocancel 0x040c0638
566 #define BSC_close_nocancel 0x040c063c
567 #define BSC_msync_nocancel 0x040c0654
568 #define BSC_fcntl_nocancel 0x040c0658
569 #define BSC_select_nocancel 0x040c065c
570 #define BSC_fsync_nocancel 0x040c0660
571 #define BSC_readv_nocancel 0x040c066c
572 #define BSC_writev_nocancel 0x040c0670
573 #define BSC_pread_nocancel 0x040c0678
574 #define BSC_pwrite_nocancel 0x040c067c
575 #define BSC_aio_suspend_nocancel 0x40c0694
576 #define BSC_guarded_open_np 0x040c06e4
577 #define BSC_guarded_close_np 0x040c06e8
578
579 #define BSC_fsgetpath 0x040c06ac
580
581 #define BSC_msync_extended 0x040e0104
582 #define BSC_pread_extended 0x040e0264
583 #define BSC_pwrite_extended 0x040e0268
584 #define BSC_mmap_extended 0x040e0314
585 #define BSC_mmap_extended2 0x040f0314
586
587 // Carbon File Manager support
588 #define FILEMGR_PBGETCATALOGINFO 0x1e000020
589 #define FILEMGR_PBGETCATALOGINFOBULK 0x1e000024
590 #define FILEMGR_PBCREATEFILEUNICODE 0x1e000028
591 #define FILEMGR_PBCREATEDIRECTORYUNICODE 0x1e00002c
592 #define FILEMGR_PBCREATEFORK 0x1e000030
593 #define FILEMGR_PBDELETEFORK 0x1e000034
594 #define FILEMGR_PBITERATEFORK 0x1e000038
595 #define FILEMGR_PBOPENFORK 0x1e00003c
596 #define FILEMGR_PBREADFORK 0x1e000040
597 #define FILEMGR_PBWRITEFORK 0x1e000044
598 #define FILEMGR_PBALLOCATEFORK 0x1e000048
599 #define FILEMGR_PBDELETEOBJECT 0x1e00004c
600 #define FILEMGR_PBEXCHANGEOBJECT 0x1e000050
601 #define FILEMGR_PBGETFORKCBINFO 0x1e000054
602 #define FILEMGR_PBGETVOLUMEINFO 0x1e000058
603 #define FILEMGR_PBMAKEFSREF 0x1e00005c
604 #define FILEMGR_PBMAKEFSREFUNICODE 0x1e000060
605 #define FILEMGR_PBMOVEOBJECT 0x1e000064
606 #define FILEMGR_PBOPENITERATOR 0x1e000068
607 #define FILEMGR_PBRENAMEUNICODE 0x1e00006c
608 #define FILEMGR_PBSETCATALOGINFO 0x1e000070
609 #define FILEMGR_PBSETVOLUMEINFO 0x1e000074
610 #define FILEMGR_FSREFMAKEPATH 0x1e000078
611 #define FILEMGR_FSPATHMAKEREF 0x1e00007c
612
613 #define FILEMGR_PBGETCATINFO 0x1e010000
614 #define FILEMGR_PBGETCATINFOLITE 0x1e010004
615 #define FILEMGR_PBHGETFINFO 0x1e010008
616 #define FILEMGR_PBXGETVOLINFO 0x1e01000c
617 #define FILEMGR_PBHCREATE 0x1e010010
618 #define FILEMGR_PBHOPENDF 0x1e010014
619 #define FILEMGR_PBHOPENRF 0x1e010018
620 #define FILEMGR_PBHGETDIRACCESS 0x1e01001c
621 #define FILEMGR_PBHSETDIRACCESS 0x1e010020
622 #define FILEMGR_PBHMAPID 0x1e010024
623 #define FILEMGR_PBHMAPNAME 0x1e010028
624 #define FILEMGR_PBCLOSE 0x1e01002c
625 #define FILEMGR_PBFLUSHFILE 0x1e010030
626 #define FILEMGR_PBGETEOF 0x1e010034
627 #define FILEMGR_PBSETEOF 0x1e010038
628 #define FILEMGR_PBGETFPOS 0x1e01003c
629 #define FILEMGR_PBREAD 0x1e010040
630 #define FILEMGR_PBWRITE 0x1e010044
631 #define FILEMGR_PBGETFCBINFO 0x1e010048
632 #define FILEMGR_PBSETFINFO 0x1e01004c
633 #define FILEMGR_PBALLOCATE 0x1e010050
634 #define FILEMGR_PBALLOCCONTIG 0x1e010054
635 #define FILEMGR_PBSETFPOS 0x1e010058
636 #define FILEMGR_PBSETCATINFO 0x1e01005c
637 #define FILEMGR_PBGETVOLPARMS 0x1e010060
638 #define FILEMGR_PBSETVINFO 0x1e010064
639 #define FILEMGR_PBMAKEFSSPEC 0x1e010068
640 #define FILEMGR_PBHGETVINFO 0x1e01006c
641 #define FILEMGR_PBCREATEFILEIDREF 0x1e010070
642 #define FILEMGR_PBDELETEFILEIDREF 0x1e010074
643 #define FILEMGR_PBRESOLVEFILEIDREF 0x1e010078
644 #define FILEMGR_PBFLUSHVOL 0x1e01007c
645 #define FILEMGR_PBHRENAME 0x1e010080
646 #define FILEMGR_PBCATMOVE 0x1e010084
647 #define FILEMGR_PBEXCHANGEFILES 0x1e010088
648 #define FILEMGR_PBHDELETE 0x1e01008c
649 #define FILEMGR_PBDIRCREATE 0x1e010090
650 #define FILEMGR_PBCATSEARCH 0x1e010094
651 #define FILEMGR_PBHSETFLOCK 0x1e010098
652 #define FILEMGR_PBHRSTFLOCK 0x1e01009c
653 #define FILEMGR_PBLOCKRANGE 0x1e0100a0
654 #define FILEMGR_PBUNLOCKRANGE 0x1e0100a4
655
656
657 #define FILEMGR_CLASS 0x1e
658 #define FILEMGR_BASE 0x1e000000
659
660 #define FMT_DEFAULT 0
661 #define FMT_FD 1
662 #define FMT_FD_IO 2
663 #define FMT_FD_2 3
664 #define FMT_SOCKET 4
665 #define FMT_PGIN 5
666 #define FMT_PGOUT 6
667 #define FMT_CACHEHIT 7
668 #define FMT_DISKIO 8
669 #define FMT_LSEEK 9
670 #define FMT_PREAD 10
671 #define FMT_FTRUNC 11
672 #define FMT_TRUNC 12
673 #define FMT_SELECT 13
674 #define FMT_OPEN 14
675 #define FMT_AIO_FSYNC 15
676 #define FMT_AIO_RETURN 16
677 #define FMT_AIO_SUSPEND 17
678 #define FMT_AIO_CANCEL 18
679 #define FMT_AIO 19
680 #define FMT_LIO_LISTIO 20
681 #define FMT_MSYNC 21
682 #define FMT_FCNTL 22
683 #define FMT_ACCESS 23
684 #define FMT_CHMOD 24
685 #define FMT_FCHMOD 25
686 #define FMT_CHMOD_EXT 26
687 #define FMT_FCHMOD_EXT 27
688 #define FMT_CHFLAGS 28
689 #define FMT_FCHFLAGS 29
690 #define FMT_IOCTL 30
691 #define FMT_MMAP 31
692 #define FMT_UMASK 32
693 #define FMT_SENDFILE 33
694 #define FMT_IOCTL_SYNC 34
695 #define FMT_MOUNT 35
696 #define FMT_UNMOUNT 36
697 #define FMT_DISKIO_CS 37
698 #define FMT_SYNC_DISK_CS 38
699 #define FMT_IOCTL_UNMAP 39
700 #define FMT_UNMAP_INFO 40
701 #define FMT_HFS_update 41
702 #define FMT_FLOCK 42
703
704 #define MAX_BSD_SYSCALL 512
705
706 struct bsd_syscall {
707 char *sc_name;
708 int sc_format;
709 } bsd_syscalls[MAX_BSD_SYSCALL];
710
711
712 int bsd_syscall_types[] = {
713 BSC_recvmsg,
714 BSC_recvmsg_nocancel,
715 BSC_sendmsg,
716 BSC_sendmsg_nocancel,
717 BSC_recvfrom,
718 BSC_recvfrom_nocancel,
719 BSC_accept,
720 BSC_accept_nocancel,
721 BSC_select,
722 BSC_select_nocancel,
723 BSC_socket,
724 BSC_connect,
725 BSC_connect_nocancel,
726 BSC_bind,
727 BSC_listen,
728 BSC_sendto,
729 BSC_sendto_nocancel,
730 BSC_socketpair,
731 BSC_read,
732 BSC_read_nocancel,
733 BSC_write,
734 BSC_write_nocancel,
735 BSC_open,
736 BSC_open_nocancel,
737 BSC_close,
738 BSC_close_nocancel,
739 BSC_link,
740 BSC_unlink,
741 BSC_chdir,
742 BSC_fchdir,
743 BSC_mknod,
744 BSC_chmod,
745 BSC_chown,
746 BSC_access,
747 BSC_chflags,
748 BSC_fchflags,
749 BSC_sync,
750 BSC_dup,
751 BSC_revoke,
752 BSC_symlink,
753 BSC_readlink,
754 BSC_exit,
755 BSC_execve,
756 BSC_posix_spawn,
757 BSC_umask,
758 BSC_chroot,
759 BSC_dup2,
760 BSC_fsync,
761 BSC_fsync_nocancel,
762 BSC_readv,
763 BSC_readv_nocancel,
764 BSC_writev,
765 BSC_writev_nocancel,
766 BSC_fchown,
767 BSC_fchmod,
768 BSC_rename,
769 BSC_mkfifo,
770 BSC_mkdir,
771 BSC_rmdir,
772 BSC_utimes,
773 BSC_futimes,
774 BSC_pread,
775 BSC_pread_nocancel,
776 BSC_pwrite,
777 BSC_pwrite_nocancel,
778 BSC_statfs,
779 BSC_fstatfs,
780 BSC_fdatasync,
781 BSC_stat,
782 BSC_fstat,
783 BSC_lstat,
784 BSC_mount,
785 BSC_unmount,
786 BSC_pathconf,
787 BSC_fpathconf,
788 BSC_getdirentries,
789 BSC_mmap,
790 BSC_lseek,
791 BSC_truncate,
792 BSC_ftruncate,
793 BSC_flock,
794 BSC_undelete,
795 BSC_open_dprotected_np,
796 BSC_getattrlist,
797 BSC_setattrlist,
798 BSC_fgetattrlist,
799 BSC_fsetattrlist,
800 BSC_getdirentriesattr,
801 BSC_exchangedata,
802 BSC_checkuseraccess,
803 BSC_searchfs,
804 BSC_delete,
805 BSC_copyfile,
806 BSC_getxattr,
807 BSC_fgetxattr,
808 BSC_setxattr,
809 BSC_fsetxattr,
810 BSC_removexattr,
811 BSC_fremovexattr,
812 BSC_listxattr,
813 BSC_flistxattr,
814 BSC_fsctl,
815 BSC_ffsctl,
816 BSC_open_extended,
817 BSC_umask_extended,
818 BSC_stat_extended,
819 BSC_lstat_extended,
820 BSC_fstat_extended,
821 BSC_chmod_extended,
822 BSC_fchmod_extended,
823 BSC_access_extended,
824 BSC_mkfifo_extended,
825 BSC_mkdir_extended,
826 BSC_aio_fsync,
827 BSC_aio_return,
828 BSC_aio_suspend,
829 BSC_aio_suspend_nocancel,
830 BSC_aio_cancel,
831 BSC_aio_error,
832 BSC_aio_read,
833 BSC_aio_write,
834 BSC_lio_listio,
835 BSC_lchown,
836 BSC_sendfile,
837 BSC_msync,
838 BSC_msync_nocancel,
839 BSC_fcntl,
840 BSC_fcntl_nocancel,
841 BSC_ioctl,
842 BSC_stat64,
843 BSC_fstat64,
844 BSC_lstat64,
845 BSC_stat64_extended,
846 BSC_lstat64_extended,
847 BSC_fstat64_extended,
848 BSC_getdirentries64,
849 BSC_statfs64,
850 BSC_fstatfs64,
851 BSC_pthread_chdir,
852 BSC_pthread_fchdir,
853 BSC_getfsstat,
854 BSC_getfsstat64,
855 BSC_guarded_open_np,
856 BSC_guarded_close_np,
857 BSC_fsgetpath,
858 0
859 };
860
861
862 #define MAX_FILEMGR 512
863
864 struct filemgr_call {
865 char *fm_name;
866 } filemgr_calls[MAX_FILEMGR];
867
868
869 int filemgr_call_types[] = {
870 FILEMGR_PBGETCATALOGINFO,
871 FILEMGR_PBGETCATALOGINFOBULK,
872 FILEMGR_PBCREATEFILEUNICODE,
873 FILEMGR_PBCREATEDIRECTORYUNICODE,
874 FILEMGR_PBCREATEFORK,
875 FILEMGR_PBDELETEFORK,
876 FILEMGR_PBITERATEFORK,
877 FILEMGR_PBOPENFORK,
878 FILEMGR_PBREADFORK,
879 FILEMGR_PBWRITEFORK,
880 FILEMGR_PBALLOCATEFORK,
881 FILEMGR_PBDELETEOBJECT,
882 FILEMGR_PBEXCHANGEOBJECT,
883 FILEMGR_PBGETFORKCBINFO,
884 FILEMGR_PBGETVOLUMEINFO,
885 FILEMGR_PBMAKEFSREF,
886 FILEMGR_PBMAKEFSREFUNICODE,
887 FILEMGR_PBMOVEOBJECT,
888 FILEMGR_PBOPENITERATOR,
889 FILEMGR_PBRENAMEUNICODE,
890 FILEMGR_PBSETCATALOGINFO,
891 FILEMGR_PBSETVOLUMEINFO,
892 FILEMGR_FSREFMAKEPATH,
893 FILEMGR_FSPATHMAKEREF,
894
895 FILEMGR_PBGETCATINFO,
896 FILEMGR_PBGETCATINFOLITE,
897 FILEMGR_PBHGETFINFO,
898 FILEMGR_PBXGETVOLINFO,
899 FILEMGR_PBHCREATE,
900 FILEMGR_PBHOPENDF,
901 FILEMGR_PBHOPENRF,
902 FILEMGR_PBHGETDIRACCESS,
903 FILEMGR_PBHSETDIRACCESS,
904 FILEMGR_PBHMAPID,
905 FILEMGR_PBHMAPNAME,
906 FILEMGR_PBCLOSE,
907 FILEMGR_PBFLUSHFILE,
908 FILEMGR_PBGETEOF,
909 FILEMGR_PBSETEOF,
910 FILEMGR_PBGETFPOS,
911 FILEMGR_PBREAD,
912 FILEMGR_PBWRITE,
913 FILEMGR_PBGETFCBINFO,
914 FILEMGR_PBSETFINFO,
915 FILEMGR_PBALLOCATE,
916 FILEMGR_PBALLOCCONTIG,
917 FILEMGR_PBSETFPOS,
918 FILEMGR_PBSETCATINFO,
919 FILEMGR_PBGETVOLPARMS,
920 FILEMGR_PBSETVINFO,
921 FILEMGR_PBMAKEFSSPEC,
922 FILEMGR_PBHGETVINFO,
923 FILEMGR_PBCREATEFILEIDREF,
924 FILEMGR_PBDELETEFILEIDREF,
925 FILEMGR_PBRESOLVEFILEIDREF,
926 FILEMGR_PBFLUSHVOL,
927 FILEMGR_PBHRENAME,
928 FILEMGR_PBCATMOVE,
929 FILEMGR_PBEXCHANGEFILES,
930 FILEMGR_PBHDELETE,
931 FILEMGR_PBDIRCREATE,
932 FILEMGR_PBCATSEARCH,
933 FILEMGR_PBHSETFLOCK,
934 FILEMGR_PBHRSTFLOCK,
935 FILEMGR_PBLOCKRANGE,
936 FILEMGR_PBUNLOCKRANGE,
937 0
938 };
939
940
941
942 #define MAX_PIDS 256
943 int pids[MAX_PIDS];
944
945 int num_of_pids = 0;
946 int exclude_pids = 0;
947 int exclude_default_pids = 1;
948
949
950 struct kinfo_proc *kp_buffer = 0;
951 int kp_nentries = 0;
952
953 #define EVENT_BASE 60000
954
955 int num_events = EVENT_BASE;
956
957
958 #define DBG_FUNC_ALL (DBG_FUNC_START | DBG_FUNC_END)
959 #define DBG_FUNC_MASK 0xfffffffc
960
961 double divisor = 0.0; /* Trace divisor converts to microseconds */
962
963 int mib[6];
964 size_t needed;
965 char *my_buffer;
966
967 kbufinfo_t bufinfo = {0, 0, 0, 0, 0};
968
969
970 /* defines for tracking file descriptor state */
971 #define FS_USAGE_FD_SETSIZE 256 /* Initial number of file descriptors per
972 thread that we will track */
973
974 #define FS_USAGE_NFDBITS (sizeof (unsigned long) * 8)
975 #define FS_USAGE_NFDBYTES(n) (((n) / FS_USAGE_NFDBITS) * sizeof (unsigned long))
976
977 int trace_enabled = 0;
978 int set_remove_flag = 1;
979
980 int BC_flag = 0;
981
982 char *RAW_file = (char *)0;
983 int RAW_flag = 0;
984 int RAW_fd = 0;
985
986 uint64_t sample_TOD_secs;
987 uint32_t sample_TOD_usecs;
988
989 double bias_now = 0.0;
990 double start_time = 0.0;
991 double end_time = 999999999999.9;
992
993
994 void set_numbufs();
995 void set_filter();
996 void set_init();
997 void set_enable();
998 void sample_sc();
999 int quit();
1000
1001 /*
1002 * signal handlers
1003 */
1004
1005 void leave() /* exit under normal conditions -- INT handler */
1006 {
1007 int i;
1008 void set_enable();
1009 void set_pidcheck();
1010 void set_pidexclude();
1011 void set_remove();
1012
1013 fflush(0);
1014
1015 set_enable(0);
1016
1017 if (exclude_pids == 0) {
1018 for (i = 0; i < num_of_pids; i++)
1019 set_pidcheck(pids[i], 0);
1020 }
1021 else {
1022 for (i = 0; i < num_of_pids; i++)
1023 set_pidexclude(pids[i], 0);
1024 }
1025 set_remove();
1026
1027 exit(0);
1028 }
1029
1030
1031 int
1032 quit(s)
1033 char *s;
1034 {
1035 if (trace_enabled)
1036 set_enable(0);
1037
1038 /*
1039 * This flag is turned off when calling
1040 * quit() due to a set_remove() failure.
1041 */
1042 if (set_remove_flag)
1043 set_remove();
1044
1045 fprintf(stderr, "fs_usage: ");
1046 if (s)
1047 fprintf(stderr, "%s", s);
1048
1049 exit(1);
1050 }
1051
1052
1053 void get_screenwidth()
1054 {
1055 struct winsize size;
1056
1057 columns = MAXCOLS;
1058
1059 if (isatty(1)) {
1060 if (ioctl(1, TIOCGWINSZ, &size) != -1) {
1061 columns = size.ws_col;
1062
1063 if (columns > MAXWIDTH)
1064 columns = MAXWIDTH;
1065 }
1066 }
1067 }
1068
1069
1070 void sigwinch()
1071 {
1072 if (!wideflag)
1073 get_screenwidth();
1074 }
1075
1076
1077 void getdivisor()
1078 {
1079 struct mach_timebase_info mti;
1080
1081 mach_timebase_info(&mti);
1082
1083 divisor = ((double)mti.denom / (double)mti.numer) * 1000;
1084 }
1085
1086
1087 int
1088 exit_usage(char *myname) {
1089
1090 fprintf(stderr, "Usage: %s [-e] [-w] [-f mode] [-b] [-t seconds] [-R rawfile [-S start_time] [-E end_time]] [pid | cmd [pid | cmd] ...]\n", myname);
1091 fprintf(stderr, " -e exclude the specified list of pids from the sample\n");
1092 fprintf(stderr, " and exclude fs_usage by default\n");
1093 fprintf(stderr, " -w force wider, detailed, output\n");
1094 fprintf(stderr, " -f output is based on the mode provided\n");
1095 fprintf(stderr, " mode = \"network\" Show network-related events\n");
1096 fprintf(stderr, " mode = \"filesys\" Show filesystem-related events\n");
1097 fprintf(stderr, " mode = \"pathname\" Show only pathname-related events\n");
1098 fprintf(stderr, " mode = \"exec\" Show only exec and spawn events\n");
1099 fprintf(stderr, " mode = \"diskio\" Show only disk I/O events\n");
1100 fprintf(stderr, " mode = \"cachehit\" In addition, show cache hits\n");
1101 fprintf(stderr, " -b annotate disk I/O events with BootCache info (if available)\n");
1102 fprintf(stderr, " -t specifies timeout in seconds (for use in automated tools)\n");
1103 fprintf(stderr, " -R specifies a raw trace file to process\n");
1104 fprintf(stderr, " -S if -R is specified, selects a start point in microseconds\n");
1105 fprintf(stderr, " -E if -R is specified, selects an end point in microseconds\n");
1106 fprintf(stderr, " pid selects process(s) to sample\n");
1107 fprintf(stderr, " cmd selects process(s) matching command string to sample\n");
1108 fprintf(stderr, "\n%s will handle a maximum list of %d pids.\n\n", myname, MAX_PIDS);
1109 fprintf(stderr, "By default (no options) the following processes are excluded from the output:\n");
1110 fprintf(stderr, "fs_usage, Terminal, telnetd, sshd, rlogind, tcsh, csh, sh\n\n");
1111
1112 exit(1);
1113 }
1114
1115
1116 int filemgr_index(type) {
1117
1118 if (type & 0x10000)
1119 return (((type >> 2) & 0x3fff) + 256);
1120
1121 return (((type >> 2) & 0x3fff));
1122 }
1123
1124
1125 void init_tables(void)
1126 { int i;
1127 int type;
1128 int code;
1129
1130
1131 for (i = 0; i < MAX_BSD_SYSCALL; i++) {
1132 bsd_syscalls[i].sc_name = NULL;
1133 bsd_syscalls[i].sc_format = FMT_DEFAULT;
1134 }
1135
1136 for (i = 0; i < MAX_FILEMGR; i++) {
1137 filemgr_calls[i].fm_name = NULL;
1138 }
1139
1140 for (i = 0; (type = bsd_syscall_types[i]); i++) {
1141
1142 code = BSC_INDEX(type);
1143
1144 if (code >= MAX_BSD_SYSCALL) {
1145 printf("BSD syscall init (%x): type exceeds table size\n", type);
1146 continue;
1147 }
1148 switch (type) {
1149
1150 case BSC_sendfile:
1151 bsd_syscalls[code].sc_name = "sendfile";
1152 bsd_syscalls[code].sc_format = FMT_FD; /* this should be changed to FMT_SENDFILE */
1153 break; /* once we add an extended info trace event */
1154
1155 case BSC_recvmsg:
1156 case BSC_recvmsg_nocancel:
1157 bsd_syscalls[code].sc_name = "recvmsg";
1158 bsd_syscalls[code].sc_format = FMT_FD_IO;
1159 break;
1160
1161 case BSC_sendmsg:
1162 case BSC_sendmsg_nocancel:
1163 bsd_syscalls[code].sc_name = "sendmsg";
1164 bsd_syscalls[code].sc_format = FMT_FD_IO;
1165 break;
1166
1167 case BSC_recvfrom:
1168 case BSC_recvfrom_nocancel:
1169 bsd_syscalls[code].sc_name = "recvfrom";
1170 bsd_syscalls[code].sc_format = FMT_FD_IO;
1171 break;
1172
1173 case BSC_sendto:
1174 case BSC_sendto_nocancel:
1175 bsd_syscalls[code].sc_name = "sendto";
1176 bsd_syscalls[code].sc_format = FMT_FD_IO;
1177 break;
1178
1179 case BSC_select:
1180 case BSC_select_nocancel:
1181 bsd_syscalls[code].sc_name = "select";
1182 bsd_syscalls[code].sc_format = FMT_SELECT;
1183 break;
1184
1185 case BSC_accept:
1186 case BSC_accept_nocancel:
1187 bsd_syscalls[code].sc_name = "accept";
1188 bsd_syscalls[code].sc_format = FMT_FD_2;
1189 break;
1190
1191 case BSC_socket:
1192 bsd_syscalls[code].sc_name = "socket";
1193 bsd_syscalls[code].sc_format = FMT_SOCKET;
1194 break;
1195
1196 case BSC_connect:
1197 case BSC_connect_nocancel:
1198 bsd_syscalls[code].sc_name = "connect";
1199 bsd_syscalls[code].sc_format = FMT_FD;
1200 break;
1201
1202 case BSC_bind:
1203 bsd_syscalls[code].sc_name = "bind";
1204 bsd_syscalls[code].sc_format = FMT_FD;
1205 break;
1206
1207 case BSC_listen:
1208 bsd_syscalls[code].sc_name = "listen";
1209 bsd_syscalls[code].sc_format = FMT_FD;
1210 break;
1211
1212 case BSC_mmap:
1213 bsd_syscalls[code].sc_name = "mmap";
1214 bsd_syscalls[code].sc_format = FMT_MMAP;
1215 break;
1216
1217 case BSC_socketpair:
1218 bsd_syscalls[code].sc_name = "socketpair";
1219 break;
1220
1221 case BSC_getxattr:
1222 bsd_syscalls[code].sc_name = "getxattr";
1223 break;
1224
1225 case BSC_setxattr:
1226 bsd_syscalls[code].sc_name = "setxattr";
1227 break;
1228
1229 case BSC_removexattr:
1230 bsd_syscalls[code].sc_name = "removexattr";
1231 break;
1232
1233 case BSC_listxattr:
1234 bsd_syscalls[code].sc_name = "listxattr";
1235 break;
1236
1237 case BSC_stat:
1238 bsd_syscalls[code].sc_name = "stat";
1239 break;
1240
1241 case BSC_stat64:
1242 bsd_syscalls[code].sc_name = "stat64";
1243 break;
1244
1245 case BSC_stat_extended:
1246 bsd_syscalls[code].sc_name = "stat_extended";
1247 break;
1248
1249 case BSC_stat64_extended:
1250 bsd_syscalls[code].sc_name = "stat_extended64";
1251 break;
1252
1253 case BSC_mount:
1254 bsd_syscalls[code].sc_name = "mount";
1255 bsd_syscalls[code].sc_format = FMT_MOUNT;
1256 break;
1257
1258 case BSC_unmount:
1259 bsd_syscalls[code].sc_name = "unmount";
1260 bsd_syscalls[code].sc_format = FMT_UNMOUNT;
1261 break;
1262
1263 case BSC_exit:
1264 bsd_syscalls[code].sc_name = "exit";
1265 break;
1266
1267 case BSC_execve:
1268 bsd_syscalls[code].sc_name = "execve";
1269 break;
1270
1271 case BSC_posix_spawn:
1272 bsd_syscalls[code].sc_name = "posix_spawn";
1273 break;
1274
1275 case BSC_open:
1276 case BSC_open_nocancel:
1277 bsd_syscalls[code].sc_name = "open";
1278 bsd_syscalls[code].sc_format = FMT_OPEN;
1279 break;
1280
1281 case BSC_open_extended:
1282 bsd_syscalls[code].sc_name = "open_extended";
1283 bsd_syscalls[code].sc_format = FMT_OPEN;
1284 break;
1285
1286 case BSC_guarded_open_np:
1287 bsd_syscalls[code].sc_name = "guarded_open_np";
1288 bsd_syscalls[code].sc_format = FMT_OPEN;
1289 break;
1290
1291 case BSC_open_dprotected_np:
1292 bsd_syscalls[code].sc_name = "open_dprotected";
1293 bsd_syscalls[code].sc_format = FMT_OPEN;
1294 break;
1295
1296 case BSC_dup:
1297 bsd_syscalls[code].sc_name = "dup";
1298 bsd_syscalls[code].sc_format = FMT_FD_2;
1299 break;
1300
1301 case BSC_dup2:
1302 bsd_syscalls[code].sc_name = "dup2";
1303 bsd_syscalls[code].sc_format = FMT_FD_2;
1304 break;
1305
1306 case BSC_close:
1307 case BSC_close_nocancel:
1308 bsd_syscalls[code].sc_name = "close";
1309 bsd_syscalls[code].sc_format = FMT_FD;
1310 break;
1311
1312 case BSC_guarded_close_np:
1313 bsd_syscalls[code].sc_name = "guarded_close_np";
1314 bsd_syscalls[code].sc_format = FMT_FD;
1315 break;
1316
1317 case BSC_read:
1318 case BSC_read_nocancel:
1319 bsd_syscalls[code].sc_name = "read";
1320 bsd_syscalls[code].sc_format = FMT_FD_IO;
1321 break;
1322
1323 case BSC_write:
1324 case BSC_write_nocancel:
1325 bsd_syscalls[code].sc_name = "write";
1326 bsd_syscalls[code].sc_format = FMT_FD_IO;
1327 break;
1328
1329 case BSC_fgetxattr:
1330 bsd_syscalls[code].sc_name = "fgetxattr";
1331 bsd_syscalls[code].sc_format = FMT_FD;
1332 break;
1333
1334 case BSC_fsetxattr:
1335 bsd_syscalls[code].sc_name = "fsetxattr";
1336 bsd_syscalls[code].sc_format = FMT_FD;
1337 break;
1338
1339 case BSC_fremovexattr:
1340 bsd_syscalls[code].sc_name = "fremovexattr";
1341 bsd_syscalls[code].sc_format = FMT_FD;
1342 break;
1343
1344 case BSC_flistxattr:
1345 bsd_syscalls[code].sc_name = "flistxattr";
1346 bsd_syscalls[code].sc_format = FMT_FD;
1347 break;
1348
1349 case BSC_fstat:
1350 bsd_syscalls[code].sc_name = "fstat";
1351 bsd_syscalls[code].sc_format = FMT_FD;
1352 break;
1353
1354 case BSC_fstat64:
1355 bsd_syscalls[code].sc_name = "fstat64";
1356 bsd_syscalls[code].sc_format = FMT_FD;
1357 break;
1358
1359 case BSC_fstat_extended:
1360 bsd_syscalls[code].sc_name = "fstat_extended";
1361 bsd_syscalls[code].sc_format = FMT_FD;
1362 break;
1363
1364 case BSC_fstat64_extended:
1365 bsd_syscalls[code].sc_name = "fstat64_extended";
1366 bsd_syscalls[code].sc_format = FMT_FD;
1367 break;
1368
1369 case BSC_lstat:
1370 bsd_syscalls[code].sc_name = "lstat";
1371 break;
1372
1373 case BSC_lstat64:
1374 bsd_syscalls[code].sc_name = "lstat64";
1375 break;
1376
1377 case BSC_lstat_extended:
1378 bsd_syscalls[code].sc_name = "lstat_extended";
1379 break;
1380
1381 case BSC_lstat64_extended:
1382 bsd_syscalls[code].sc_name = "lstat_extended64";
1383 break;
1384
1385 case BSC_link:
1386 bsd_syscalls[code].sc_name = "link";
1387 break;
1388
1389 case BSC_unlink:
1390 bsd_syscalls[code].sc_name = "unlink";
1391 break;
1392
1393 case BSC_mknod:
1394 bsd_syscalls[code].sc_name = "mknod";
1395 break;
1396
1397 case BSC_umask:
1398 bsd_syscalls[code].sc_name = "umask";
1399 bsd_syscalls[code].sc_format = FMT_UMASK;
1400 break;
1401
1402 case BSC_umask_extended:
1403 bsd_syscalls[code].sc_name = "umask_extended";
1404 bsd_syscalls[code].sc_format = FMT_UMASK;
1405 break;
1406
1407 case BSC_chmod:
1408 bsd_syscalls[code].sc_name = "chmod";
1409 bsd_syscalls[code].sc_format = FMT_CHMOD;
1410 break;
1411
1412 case BSC_chmod_extended:
1413 bsd_syscalls[code].sc_name = "chmod_extended";
1414 bsd_syscalls[code].sc_format = FMT_CHMOD_EXT;
1415 break;
1416
1417 case BSC_fchmod:
1418 bsd_syscalls[code].sc_name = "fchmod";
1419 bsd_syscalls[code].sc_format = FMT_FCHMOD;
1420 break;
1421
1422 case BSC_fchmod_extended:
1423 bsd_syscalls[code].sc_name = "fchmod_extended";
1424 bsd_syscalls[code].sc_format = FMT_FCHMOD_EXT;
1425 break;
1426
1427 case BSC_chown:
1428 bsd_syscalls[code].sc_name = "chown";
1429 break;
1430
1431 case BSC_lchown:
1432 bsd_syscalls[code].sc_name = "lchown";
1433 break;
1434
1435 case BSC_fchown:
1436 bsd_syscalls[code].sc_name = "fchown";
1437 bsd_syscalls[code].sc_format = FMT_FD;
1438 break;
1439
1440 case BSC_access:
1441 bsd_syscalls[code].sc_name = "access";
1442 bsd_syscalls[code].sc_format = FMT_ACCESS;
1443 break;
1444
1445 case BSC_access_extended:
1446 bsd_syscalls[code].sc_name = "access_extended";
1447 break;
1448
1449 case BSC_chdir:
1450 bsd_syscalls[code].sc_name = "chdir";
1451 break;
1452
1453 case BSC_pthread_chdir:
1454 bsd_syscalls[code].sc_name = "pthread_chdir";
1455 break;
1456
1457 case BSC_chroot:
1458 bsd_syscalls[code].sc_name = "chroot";
1459 break;
1460
1461 case BSC_utimes:
1462 bsd_syscalls[code].sc_name = "utimes";
1463 break;
1464
1465 case BSC_delete:
1466 bsd_syscalls[code].sc_name = "delete-Carbon";
1467 break;
1468
1469 case BSC_undelete:
1470 bsd_syscalls[code].sc_name = "undelete";
1471 break;
1472
1473 case BSC_revoke:
1474 bsd_syscalls[code].sc_name = "revoke";
1475 break;
1476
1477 case BSC_fsctl:
1478 bsd_syscalls[code].sc_name = "fsctl";
1479 break;
1480
1481 case BSC_ffsctl:
1482 bsd_syscalls[code].sc_name = "ffsctl";
1483 bsd_syscalls[code].sc_format = FMT_FD;
1484 break;
1485
1486 case BSC_chflags:
1487 bsd_syscalls[code].sc_name = "chflags";
1488 bsd_syscalls[code].sc_format = FMT_CHFLAGS;
1489 break;
1490
1491 case BSC_fchflags:
1492 bsd_syscalls[code].sc_name = "fchflags";
1493 bsd_syscalls[code].sc_format = FMT_FCHFLAGS;
1494 break;
1495
1496 case BSC_fchdir:
1497 bsd_syscalls[code].sc_name = "fchdir";
1498 bsd_syscalls[code].sc_format = FMT_FD;
1499 break;
1500
1501 case BSC_pthread_fchdir:
1502 bsd_syscalls[code].sc_name = "pthread_fchdir";
1503 bsd_syscalls[code].sc_format = FMT_FD;
1504 break;
1505
1506 case BSC_futimes:
1507 bsd_syscalls[code].sc_name = "futimes";
1508 bsd_syscalls[code].sc_format = FMT_FD;
1509 break;
1510
1511 case BSC_sync:
1512 bsd_syscalls[code].sc_name = "sync";
1513 break;
1514
1515 case BSC_symlink:
1516 bsd_syscalls[code].sc_name = "symlink";
1517 break;
1518
1519 case BSC_readlink:
1520 bsd_syscalls[code].sc_name = "readlink";
1521 break;
1522
1523 case BSC_fsync:
1524 case BSC_fsync_nocancel:
1525 bsd_syscalls[code].sc_name = "fsync";
1526 bsd_syscalls[code].sc_format = FMT_FD;
1527 break;
1528
1529 case BSC_fdatasync:
1530 bsd_syscalls[code].sc_name = "fdatasync";
1531 bsd_syscalls[code].sc_format = FMT_FD;
1532 break;
1533
1534 case BSC_readv:
1535 case BSC_readv_nocancel:
1536 bsd_syscalls[code].sc_name = "readv";
1537 bsd_syscalls[code].sc_format = FMT_FD_IO;
1538 break;
1539
1540 case BSC_writev:
1541 case BSC_writev_nocancel:
1542 bsd_syscalls[code].sc_name = "writev";
1543 bsd_syscalls[code].sc_format = FMT_FD_IO;
1544 break;
1545
1546 case BSC_pread:
1547 case BSC_pread_nocancel:
1548 bsd_syscalls[code].sc_name = "pread";
1549 bsd_syscalls[code].sc_format = FMT_PREAD;
1550 break;
1551
1552 case BSC_pwrite:
1553 case BSC_pwrite_nocancel:
1554 bsd_syscalls[code].sc_name = "pwrite";
1555 bsd_syscalls[code].sc_format = FMT_PREAD;
1556 break;
1557
1558 case BSC_mkdir:
1559 bsd_syscalls[code].sc_name = "mkdir";
1560 break;
1561
1562 case BSC_mkdir_extended:
1563 bsd_syscalls[code].sc_name = "mkdir_extended";
1564 break;
1565
1566 case BSC_mkfifo:
1567 bsd_syscalls[code].sc_name = "mkfifo";
1568 break;
1569
1570 case BSC_mkfifo_extended:
1571 bsd_syscalls[code].sc_name = "mkfifo_extended";
1572 break;
1573
1574 case BSC_rmdir:
1575 bsd_syscalls[code].sc_name = "rmdir";
1576 break;
1577
1578 case BSC_statfs:
1579 bsd_syscalls[code].sc_name = "statfs";
1580 break;
1581
1582 case BSC_statfs64:
1583 bsd_syscalls[code].sc_name = "statfs64";
1584 break;
1585
1586 case BSC_getfsstat:
1587 bsd_syscalls[code].sc_name = "getfsstat";
1588 break;
1589
1590 case BSC_getfsstat64:
1591 bsd_syscalls[code].sc_name = "getfsstat64";
1592 break;
1593
1594 case BSC_fstatfs:
1595 bsd_syscalls[code].sc_name = "fstatfs";
1596 bsd_syscalls[code].sc_format = FMT_FD;
1597 break;
1598
1599 case BSC_fstatfs64:
1600 bsd_syscalls[code].sc_name = "fstatfs64";
1601 bsd_syscalls[code].sc_format = FMT_FD;
1602 break;
1603
1604 case BSC_pathconf:
1605 bsd_syscalls[code].sc_name = "pathconf";
1606 break;
1607
1608 case BSC_fpathconf:
1609 bsd_syscalls[code].sc_name = "fpathconf";
1610 bsd_syscalls[code].sc_format = FMT_FD;
1611 break;
1612
1613 case BSC_getdirentries:
1614 bsd_syscalls[code].sc_name = "getdirentries";
1615 bsd_syscalls[code].sc_format = FMT_FD_IO;
1616 break;
1617
1618 case BSC_getdirentries64:
1619 bsd_syscalls[code].sc_name = "getdirentries64";
1620 bsd_syscalls[code].sc_format = FMT_FD_IO;
1621 break;
1622
1623 case BSC_lseek:
1624 bsd_syscalls[code].sc_name = "lseek";
1625 bsd_syscalls[code].sc_format = FMT_LSEEK;
1626 break;
1627
1628 case BSC_truncate:
1629 bsd_syscalls[code].sc_name = "truncate";
1630 bsd_syscalls[code].sc_format = FMT_TRUNC;
1631 break;
1632
1633 case BSC_ftruncate:
1634 bsd_syscalls[code].sc_name = "ftruncate";
1635 bsd_syscalls[code].sc_format = FMT_FTRUNC;
1636 break;
1637
1638 case BSC_flock:
1639 bsd_syscalls[code].sc_name = "flock";
1640 bsd_syscalls[code].sc_format = FMT_FLOCK;
1641 break;
1642
1643 case BSC_getattrlist:
1644 bsd_syscalls[code].sc_name = "getattrlist";
1645 break;
1646
1647 case BSC_setattrlist:
1648 bsd_syscalls[code].sc_name = "setattrlist";
1649 break;
1650
1651 case BSC_fgetattrlist:
1652 bsd_syscalls[code].sc_name = "fgetattrlist";
1653 bsd_syscalls[code].sc_format = FMT_FD;
1654 break;
1655
1656 case BSC_fsetattrlist:
1657 bsd_syscalls[code].sc_name = "fsetattrlist";
1658 bsd_syscalls[code].sc_format = FMT_FD;
1659 break;
1660
1661 case BSC_getdirentriesattr:
1662 bsd_syscalls[code].sc_name = "getdirentriesattr";
1663 bsd_syscalls[code].sc_format = FMT_FD;
1664 break;
1665
1666 case BSC_exchangedata:
1667 bsd_syscalls[code].sc_name = "exchangedata";
1668 break;
1669
1670 case BSC_rename:
1671 bsd_syscalls[code].sc_name = "rename";
1672 break;
1673
1674 case BSC_copyfile:
1675 bsd_syscalls[code].sc_name = "copyfile";
1676 break;
1677
1678 case BSC_checkuseraccess:
1679 bsd_syscalls[code].sc_name = "checkuseraccess";
1680 break;
1681
1682 case BSC_searchfs:
1683 bsd_syscalls[code].sc_name = "searchfs";
1684 break;
1685
1686 case BSC_aio_fsync:
1687 bsd_syscalls[code].sc_name = "aio_fsync";
1688 bsd_syscalls[code].sc_format = FMT_AIO_FSYNC;
1689 break;
1690
1691 case BSC_aio_return:
1692 bsd_syscalls[code].sc_name = "aio_return";
1693 bsd_syscalls[code].sc_format = FMT_AIO_RETURN;
1694 break;
1695
1696 case BSC_aio_suspend:
1697 case BSC_aio_suspend_nocancel:
1698 bsd_syscalls[code].sc_name = "aio_suspend";
1699 bsd_syscalls[code].sc_format = FMT_AIO_SUSPEND;
1700 break;
1701
1702 case BSC_aio_cancel:
1703 bsd_syscalls[code].sc_name = "aio_cancel";
1704 bsd_syscalls[code].sc_format = FMT_AIO_CANCEL;
1705 break;
1706
1707 case BSC_aio_error:
1708 bsd_syscalls[code].sc_name = "aio_error";
1709 bsd_syscalls[code].sc_format = FMT_AIO;
1710 break;
1711
1712 case BSC_aio_read:
1713 bsd_syscalls[code].sc_name = "aio_read";
1714 bsd_syscalls[code].sc_format = FMT_AIO;
1715 break;
1716
1717 case BSC_aio_write:
1718 bsd_syscalls[code].sc_name = "aio_write";
1719 bsd_syscalls[code].sc_format = FMT_AIO;
1720 break;
1721
1722 case BSC_lio_listio:
1723 bsd_syscalls[code].sc_name = "lio_listio";
1724 bsd_syscalls[code].sc_format = FMT_LIO_LISTIO;
1725 break;
1726
1727 case BSC_msync:
1728 case BSC_msync_nocancel:
1729 bsd_syscalls[code].sc_name = "msync";
1730 bsd_syscalls[code].sc_format = FMT_MSYNC;
1731 break;
1732
1733 case BSC_fcntl:
1734 case BSC_fcntl_nocancel:
1735 bsd_syscalls[code].sc_name = "fcntl";
1736 bsd_syscalls[code].sc_format = FMT_FCNTL;
1737 break;
1738
1739 case BSC_ioctl:
1740 bsd_syscalls[code].sc_name = "ioctl";
1741 bsd_syscalls[code].sc_format = FMT_IOCTL;
1742 break;
1743
1744 case BSC_fsgetpath:
1745 bsd_syscalls[code].sc_name = "fsgetpath";
1746 break;
1747 }
1748 }
1749
1750 for (i = 0; (type = filemgr_call_types[i]); i++) {
1751 char * p;
1752
1753 code = filemgr_index(type);
1754
1755 if (code >= MAX_FILEMGR) {
1756 printf("FILEMGR call init (%x): type exceeds table size\n", type);
1757 continue;
1758 }
1759 switch (type) {
1760
1761 case FILEMGR_PBGETCATALOGINFO:
1762 p = "GetCatalogInfo";
1763 break;
1764
1765 case FILEMGR_PBGETCATALOGINFOBULK:
1766 p = "GetCatalogInfoBulk";
1767 break;
1768
1769 case FILEMGR_PBCREATEFILEUNICODE:
1770 p = "CreateFileUnicode";
1771 break;
1772
1773 case FILEMGR_PBCREATEDIRECTORYUNICODE:
1774 p = "CreateDirectoryUnicode";
1775 break;
1776
1777 case FILEMGR_PBCREATEFORK:
1778 p = "PBCreateFork";
1779 break;
1780
1781 case FILEMGR_PBDELETEFORK:
1782 p = "PBDeleteFork";
1783 break;
1784
1785 case FILEMGR_PBITERATEFORK:
1786 p = "PBIterateFork";
1787 break;
1788
1789 case FILEMGR_PBOPENFORK:
1790 p = "PBOpenFork";
1791 break;
1792
1793 case FILEMGR_PBREADFORK:
1794 p = "PBReadFork";
1795 break;
1796
1797 case FILEMGR_PBWRITEFORK:
1798 p = "PBWriteFork";
1799 break;
1800
1801 case FILEMGR_PBALLOCATEFORK:
1802 p = "PBAllocateFork";
1803 break;
1804
1805 case FILEMGR_PBDELETEOBJECT:
1806 p = "PBDeleteObject";
1807 break;
1808
1809 case FILEMGR_PBEXCHANGEOBJECT:
1810 p = "PBExchangeObject";
1811 break;
1812
1813 case FILEMGR_PBGETFORKCBINFO:
1814 p = "PBGetForkCBInfo";
1815 break;
1816
1817 case FILEMGR_PBGETVOLUMEINFO:
1818 p = "PBGetVolumeInfo";
1819 break;
1820
1821 case FILEMGR_PBMAKEFSREF:
1822 p = "PBMakeFSRef";
1823 break;
1824
1825 case FILEMGR_PBMAKEFSREFUNICODE:
1826 p = "PBMakeFSRefUnicode";
1827 break;
1828
1829 case FILEMGR_PBMOVEOBJECT:
1830 p = "PBMoveObject";
1831 break;
1832
1833 case FILEMGR_PBOPENITERATOR:
1834 p = "PBOpenIterator";
1835 break;
1836
1837 case FILEMGR_PBRENAMEUNICODE:
1838 p = "PBRenameUnicode";
1839 break;
1840
1841 case FILEMGR_PBSETCATALOGINFO:
1842 p = "SetCatalogInfo";
1843 break;
1844
1845 case FILEMGR_PBSETVOLUMEINFO:
1846 p = "SetVolumeInfo";
1847 break;
1848
1849 case FILEMGR_FSREFMAKEPATH:
1850 p = "FSRefMakePath";
1851 break;
1852
1853 case FILEMGR_FSPATHMAKEREF:
1854 p = "FSPathMakeRef";
1855 break;
1856
1857 case FILEMGR_PBGETCATINFO:
1858 p = "GetCatInfo";
1859 break;
1860
1861 case FILEMGR_PBGETCATINFOLITE:
1862 p = "GetCatInfoLite";
1863 break;
1864
1865 case FILEMGR_PBHGETFINFO:
1866 p = "PBHGetFInfo";
1867 break;
1868
1869 case FILEMGR_PBXGETVOLINFO:
1870 p = "PBXGetVolInfo";
1871 break;
1872
1873 case FILEMGR_PBHCREATE:
1874 p = "PBHCreate";
1875 break;
1876
1877 case FILEMGR_PBHOPENDF:
1878 p = "PBHOpenDF";
1879 break;
1880
1881 case FILEMGR_PBHOPENRF:
1882 p = "PBHOpenRF";
1883 break;
1884
1885 case FILEMGR_PBHGETDIRACCESS:
1886 p = "PBHGetDirAccess";
1887 break;
1888
1889 case FILEMGR_PBHSETDIRACCESS:
1890 p = "PBHSetDirAccess";
1891 break;
1892
1893 case FILEMGR_PBHMAPID:
1894 p = "PBHMapID";
1895 break;
1896
1897 case FILEMGR_PBHMAPNAME:
1898 p = "PBHMapName";
1899 break;
1900
1901 case FILEMGR_PBCLOSE:
1902 p = "PBClose";
1903 break;
1904
1905 case FILEMGR_PBFLUSHFILE:
1906 p = "PBFlushFile";
1907 break;
1908
1909 case FILEMGR_PBGETEOF:
1910 p = "PBGetEOF";
1911 break;
1912
1913 case FILEMGR_PBSETEOF:
1914 p = "PBSetEOF";
1915 break;
1916
1917 case FILEMGR_PBGETFPOS:
1918 p = "PBGetFPos";
1919 break;
1920
1921 case FILEMGR_PBREAD:
1922 p = "PBRead";
1923 break;
1924
1925 case FILEMGR_PBWRITE:
1926 p = "PBWrite";
1927 break;
1928
1929 case FILEMGR_PBGETFCBINFO:
1930 p = "PBGetFCBInfo";
1931 break;
1932
1933 case FILEMGR_PBSETFINFO:
1934 p = "PBSetFInfo";
1935 break;
1936
1937 case FILEMGR_PBALLOCATE:
1938 p = "PBAllocate";
1939 break;
1940
1941 case FILEMGR_PBALLOCCONTIG:
1942 p = "PBAllocContig";
1943 break;
1944
1945 case FILEMGR_PBSETFPOS:
1946 p = "PBSetFPos";
1947 break;
1948
1949 case FILEMGR_PBSETCATINFO:
1950 p = "PBSetCatInfo";
1951 break;
1952
1953 case FILEMGR_PBGETVOLPARMS:
1954 p = "PBGetVolParms";
1955 break;
1956
1957 case FILEMGR_PBSETVINFO:
1958 p = "PBSetVInfo";
1959 break;
1960
1961 case FILEMGR_PBMAKEFSSPEC:
1962 p = "PBMakeFSSpec";
1963 break;
1964
1965 case FILEMGR_PBHGETVINFO:
1966 p = "PBHGetVInfo";
1967 break;
1968
1969 case FILEMGR_PBCREATEFILEIDREF:
1970 p = "PBCreateFileIDRef";
1971 break;
1972
1973 case FILEMGR_PBDELETEFILEIDREF:
1974 p = "PBDeleteFileIDRef";
1975 break;
1976
1977 case FILEMGR_PBRESOLVEFILEIDREF:
1978 p = "PBResolveFileIDRef";
1979 break;
1980
1981 case FILEMGR_PBFLUSHVOL:
1982 p = "PBFlushVol";
1983 break;
1984
1985 case FILEMGR_PBHRENAME:
1986 p = "PBHRename";
1987 break;
1988
1989 case FILEMGR_PBCATMOVE:
1990 p = "PBCatMove";
1991 break;
1992
1993 case FILEMGR_PBEXCHANGEFILES:
1994 p = "PBExchangeFiles";
1995 break;
1996
1997 case FILEMGR_PBHDELETE:
1998 p = "PBHDelete";
1999 break;
2000
2001 case FILEMGR_PBDIRCREATE:
2002 p = "PBDirCreate";
2003 break;
2004
2005 case FILEMGR_PBCATSEARCH:
2006 p = "PBCatSearch";
2007 break;
2008
2009 case FILEMGR_PBHSETFLOCK:
2010 p = "PBHSetFlock";
2011 break;
2012
2013 case FILEMGR_PBHRSTFLOCK:
2014 p = "PBHRstFLock";
2015 break;
2016
2017 case FILEMGR_PBLOCKRANGE:
2018 p = "PBLockRange";
2019 break;
2020
2021 case FILEMGR_PBUNLOCKRANGE:
2022 p = "PBUnlockRange";
2023 break;
2024
2025 default:
2026 p = NULL;
2027 break;
2028 }
2029 filemgr_calls[code].fm_name = p;
2030 }
2031 }
2032
2033
2034
2035 int
2036 main(argc, argv)
2037 int argc;
2038 char *argv[];
2039 {
2040 char *myname = "fs_usage";
2041 int i;
2042 char ch;
2043
2044 time_t stop_at_time = 0;
2045
2046 if (0 != reexec_to_match_kernel()) {
2047 fprintf(stderr, "Could not re-execute: %d\n", errno);
2048 exit(1);
2049 }
2050 get_screenwidth();
2051
2052 /*
2053 * get our name
2054 */
2055 if (argc > 0) {
2056 if ((myname = rindex(argv[0], '/')) == 0)
2057 myname = argv[0];
2058 else
2059 myname++;
2060 }
2061
2062 while ((ch = getopt(argc, argv, "bewf:R:S:E:t:")) != EOF) {
2063
2064 switch(ch) {
2065
2066 case 'e':
2067 exclude_pids = 1;
2068 exclude_default_pids = 0;
2069 break;
2070
2071 case 'w':
2072 wideflag = 1;
2073 if ((uint)columns < MAX_WIDE_MODE_COLS)
2074 columns = MAX_WIDE_MODE_COLS;
2075 break;
2076
2077 case 'f':
2078 if (!strcmp(optarg, "network"))
2079 filter_mode |= NETWORK_FILTER;
2080 else if (!strcmp(optarg, "filesys"))
2081 filter_mode |= FILESYS_FILTER;
2082 else if (!strcmp(optarg, "cachehit"))
2083 show_cachehits = TRUE;
2084 else if (!strcmp(optarg, "exec"))
2085 filter_mode |= EXEC_FILTER;
2086 else if (!strcmp(optarg, "pathname"))
2087 filter_mode |= PATHNAME_FILTER;
2088 else if (!strcmp(optarg, "diskio"))
2089 filter_mode |= DISKIO_FILTER;
2090 break;
2091
2092 case 'b':
2093 BC_flag = 1;
2094 break;
2095
2096 case 't':
2097 stop_at_time = time(NULL) + strtoul(optarg, NULL, 10);
2098 break;
2099
2100 case 'R':
2101 RAW_flag = 1;
2102 RAW_file = optarg;
2103 break;
2104
2105 case 'S':
2106 start_time = atof(optarg);
2107 break;
2108
2109 case 'E':
2110 end_time = atof(optarg);
2111 break;
2112
2113 default:
2114 exit_usage(myname);
2115 }
2116 }
2117 if (!RAW_flag) {
2118 if ( geteuid() != 0 ) {
2119 fprintf(stderr, "'fs_usage' must be run as root...\n");
2120 exit(1);
2121 }
2122 }
2123 argc -= optind;
2124 argv += optind;
2125
2126 /*
2127 * when excluding, fs_usage should be the first in line for pids[]
2128 *
2129 * the !exclude_pids && argc == 0 catches the exclude_default_pids
2130 * case below where exclude_pids is later set and the fs_usage PID
2131 * needs to make it into pids[]
2132 */
2133 if (exclude_pids || (!exclude_pids && argc == 0)) {
2134 if (num_of_pids < (MAX_PIDS - 1))
2135 pids[num_of_pids++] = getpid();
2136 }
2137
2138 /*
2139 * If we process any list of pids/cmds, then turn off the defaults
2140 */
2141 if (argc > 0)
2142 exclude_default_pids = 0;
2143
2144 while (argc > 0 && num_of_pids < (MAX_PIDS - 1)) {
2145 select_pid_mode++;
2146 argtopid(argv[0]);
2147 argc--;
2148 argv++;
2149 }
2150 /*
2151 * Exclude a set of default pids
2152 */
2153 if (exclude_default_pids) {
2154 argtopid("Terminal");
2155 argtopid("telnetd");
2156 argtopid("telnet");
2157 argtopid("sshd");
2158 argtopid("rlogind");
2159 argtopid("tcsh");
2160 argtopid("csh");
2161 argtopid("sh");
2162 exclude_pids = 1;
2163 }
2164 #if 0
2165 for (i = 0; i < num_of_pids; i++) {
2166 if (exclude_pids)
2167 fprintf(stderr, "exclude pid %d\n", pids[i]);
2168 else
2169 fprintf(stderr, "pid %d\n", pids[i]);
2170 }
2171 #endif
2172 if (!RAW_flag) {
2173 struct sigaction osa;
2174 int num_cpus;
2175 size_t len;
2176
2177 /* set up signal handlers */
2178 signal(SIGINT, leave);
2179 signal(SIGQUIT, leave);
2180
2181 sigaction(SIGHUP, (struct sigaction *)NULL, &osa);
2182
2183 if (osa.sa_handler == SIG_DFL)
2184 signal(SIGHUP, leave);
2185 signal(SIGTERM, leave);
2186 /*
2187 * grab the number of cpus
2188 */
2189 mib[0] = CTL_HW;
2190 mib[1] = HW_NCPU;
2191 mib[2] = 0;
2192 len = sizeof(num_cpus);
2193
2194 sysctl(mib, 2, &num_cpus, &len, NULL, 0);
2195 num_events = EVENT_BASE * num_cpus;
2196 }
2197 signal(SIGWINCH, sigwinch);
2198
2199 if ((my_buffer = malloc(num_events * sizeof(kd_buf))) == (char *)0)
2200 quit("can't allocate memory for tracing info\n");
2201
2202 if (ReadSharedCacheMap("/var/db/dyld/dyld_shared_cache_i386.map", &framework32, "/var/db/dyld/dyld_shared_cache_i386")) {
2203 ReadSharedCacheMap("/var/db/dyld/dyld_shared_cache_x86_64.map", &framework64, "/var/db/dyld/dyld_shared_cache_x86_64");
2204 } else {
2205 ReadSharedCacheMap("/var/db/dyld/dyld_shared_cache_ppc.map", &framework32, "/var/db/dyld/dyld_shared_cache_ppc");
2206 ReadSharedCacheMap("/var/db/dyld/dyld_shared_cache_ppc64.map", &framework64, "/var/db/dyld/dyld_shared_cache_ppc64");
2207 }
2208 SortFrameworkAddresses();
2209
2210 cache_disk_names();
2211
2212 if (!RAW_flag) {
2213
2214 set_remove();
2215 set_numbufs(num_events);
2216 set_init();
2217
2218 if (exclude_pids == 0) {
2219 for (i = 0; i < num_of_pids; i++)
2220 set_pidcheck(pids[i], 1);
2221 } else {
2222 for (i = 0; i < num_of_pids; i++)
2223 set_pidexclude(pids[i], 1);
2224 }
2225 if (select_pid_mode && !one_good_pid) {
2226 /*
2227 * An attempt to restrict output to a given
2228 * pid or command has failed. Exit gracefully
2229 */
2230 set_remove();
2231 exit_usage(myname);
2232 }
2233
2234 set_filter();
2235
2236 set_enable(1);
2237
2238 init_arguments_buffer();
2239 }
2240 getdivisor();
2241
2242 init_tables();
2243
2244 /*
2245 * main loop
2246 */
2247 while (stop_at_time == 0 || last_time < stop_at_time) {
2248 if (!RAW_flag)
2249 usleep(1000 * usleep_ms);
2250
2251 sample_sc();
2252
2253 last_time = time((long *)0);
2254 }
2255 }
2256
2257
2258 void
2259 find_proc_names()
2260 {
2261 size_t bufSize = 0;
2262 struct kinfo_proc *kp;
2263
2264 mib[0] = CTL_KERN;
2265 mib[1] = KERN_PROC;
2266 mib[2] = KERN_PROC_ALL;
2267 mib[3] = 0;
2268
2269 if (sysctl(mib, 4, NULL, &bufSize, NULL, 0) < 0)
2270 quit("trace facility failure, KERN_PROC_ALL\n");
2271
2272 if ((kp = (struct kinfo_proc *)malloc(bufSize)) == (struct kinfo_proc *)0)
2273 quit("can't allocate memory for proc buffer\n");
2274
2275 if (sysctl(mib, 4, kp, &bufSize, NULL, 0) < 0)
2276 quit("trace facility failure, KERN_PROC_ALL\n");
2277
2278 kp_nentries = bufSize/ sizeof(struct kinfo_proc);
2279 kp_buffer = kp;
2280 }
2281
2282
2283 void
2284 set_enable(int val)
2285 {
2286 mib[0] = CTL_KERN;
2287 mib[1] = KERN_KDEBUG;
2288 mib[2] = KERN_KDENABLE; /* protocol */
2289 mib[3] = val;
2290 mib[4] = 0;
2291 mib[5] = 0; /* no flags */
2292
2293 if (sysctl(mib, 4, NULL, &needed, NULL, 0) < 0)
2294 quit("trace facility failure, KERN_KDENABLE\n");
2295
2296 if (val)
2297 trace_enabled = 1;
2298 else
2299 trace_enabled = 0;
2300 }
2301
2302 void
2303 set_numbufs(int nbufs)
2304 {
2305 mib[0] = CTL_KERN;
2306 mib[1] = KERN_KDEBUG;
2307 mib[2] = KERN_KDSETBUF;
2308 mib[3] = nbufs;
2309 mib[4] = 0;
2310 mib[5] = 0; /* no flags */
2311
2312 if (sysctl(mib, 4, NULL, &needed, NULL, 0) < 0)
2313 quit("trace facility failure, KERN_KDSETBUF\n");
2314
2315 mib[0] = CTL_KERN;
2316 mib[1] = KERN_KDEBUG;
2317 mib[2] = KERN_KDSETUP;
2318 mib[3] = 0;
2319 mib[4] = 0;
2320 mib[5] = 0; /* no flags */
2321
2322 if (sysctl(mib, 3, NULL, &needed, NULL, 0) < 0)
2323 quit("trace facility failure, KERN_KDSETUP\n");
2324 }
2325
2326 #define ENCODE_CSC_LOW(class, subclass) \
2327 ( (uint16_t) ( ((class) & 0xff) << 8 ) | ((subclass) & 0xff) )
2328
2329 void
2330 set_filter(void)
2331 {
2332 uint8_t type_filter_bitmap[KDBG_TYPEFILTER_BITMAP_SIZE];
2333 bzero(type_filter_bitmap, sizeof(type_filter_bitmap));
2334
2335 setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_TRACE,DBG_TRACE_DATA));
2336 setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_TRACE,DBG_TRACE_STRING));
2337
2338 setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_MACH,DBG_MACH_EXCP_SC)); //0x010c
2339 setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_MACH,DBG_MACH_VM)); //0x0130
2340 setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_MACH,DBG_MACH_SCHED)); //0x0140
2341
2342 setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_FSYSTEM,DBG_FSRW)); //0x0301
2343 setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_FSYSTEM,DBG_DKRW)); //0x0302
2344 setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_FSYSTEM,DBG_IOCTL)); //0x0306
2345 setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_FSYSTEM,DBG_BOOTCACHE)); //0x0307
2346
2347 setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_BSD,DBG_BSD_EXCP_SC)); //0x040c
2348 setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_BSD,DBG_BSD_PROC)); //0x0401
2349 setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_BSD,DBG_BSD_SC_EXTENDED_INFO)); //0x040e
2350 setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_BSD,DBG_BSD_SC_EXTENDED_INFO2)); //0x040f
2351
2352 setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_CORESTORAGE,DBG_CS_IO)); //0x0a00
2353 setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_CORESTORAGE, 1)); //0x0a01 for P_SCCS_SYNC_DIS
2354
2355 setbit(type_filter_bitmap, ENCODE_CSC_LOW(FILEMGR_CLASS, 0)); //Carbon File Manager
2356 setbit(type_filter_bitmap, ENCODE_CSC_LOW(FILEMGR_CLASS, 1)); //Carbon File Manager
2357
2358 errno = 0;
2359 int mib[] = { CTL_KERN, KERN_KDEBUG, KERN_KDSET_TYPEFILTER };
2360 size_t needed = KDBG_TYPEFILTER_BITMAP_SIZE;
2361 if(sysctl(mib, 3, type_filter_bitmap, &needed, NULL, 0)) {
2362 quit("trace facility failure, KERN_KDSET_TYPEFILTER\n");
2363 }
2364 }
2365
2366 void
2367 set_pidcheck(int pid, int on_off)
2368 {
2369 kd_regtype kr;
2370
2371 kr.type = KDBG_TYPENONE;
2372 kr.value1 = pid;
2373 kr.value2 = on_off;
2374 needed = sizeof(kd_regtype);
2375 mib[0] = CTL_KERN;
2376 mib[1] = KERN_KDEBUG;
2377 mib[2] = KERN_KDPIDTR;
2378 mib[3] = 0;
2379 mib[4] = 0;
2380 mib[5] = 0;
2381
2382 if (sysctl(mib, 3, &kr, &needed, NULL, 0) < 0) {
2383 if (on_off == 1)
2384 fprintf(stderr, "pid %d does not exist\n", pid);
2385 } else
2386 one_good_pid++;
2387 }
2388
2389 /*
2390 * on_off == 0 turns off pid exclusion
2391 * on_off == 1 turns on pid exclusion
2392 */
2393 void
2394 set_pidexclude(int pid, int on_off)
2395 {
2396 kd_regtype kr;
2397
2398 one_good_pid++;
2399
2400 kr.type = KDBG_TYPENONE;
2401 kr.value1 = pid;
2402 kr.value2 = on_off;
2403 needed = sizeof(kd_regtype);
2404 mib[0] = CTL_KERN;
2405 mib[1] = KERN_KDEBUG;
2406 mib[2] = KERN_KDPIDEX;
2407 mib[3] = 0;
2408 mib[4] = 0;
2409 mib[5] = 0;
2410
2411 if (sysctl(mib, 3, &kr, &needed, NULL, 0) < 0) {
2412 if (on_off == 1)
2413 fprintf(stderr, "pid %d does not exist\n", pid);
2414 }
2415 }
2416
2417 void
2418 get_bufinfo(kbufinfo_t *val)
2419 {
2420 needed = sizeof (*val);
2421 mib[0] = CTL_KERN;
2422 mib[1] = KERN_KDEBUG;
2423 mib[2] = KERN_KDGETBUF;
2424 mib[3] = 0;
2425 mib[4] = 0;
2426 mib[5] = 0; /* no flags */
2427
2428 if (sysctl(mib, 3, val, &needed, 0, 0) < 0)
2429 quit("trace facility failure, KERN_KDGETBUF\n");
2430
2431 }
2432
2433 void
2434 set_remove()
2435 {
2436 errno = 0;
2437
2438 mib[0] = CTL_KERN;
2439 mib[1] = KERN_KDEBUG;
2440 mib[2] = KERN_KDREMOVE; /* protocol */
2441 mib[3] = 0;
2442 mib[4] = 0;
2443 mib[5] = 0; /* no flags */
2444
2445 if (sysctl(mib, 3, NULL, &needed, NULL, 0) < 0) {
2446 set_remove_flag = 0;
2447
2448 if (errno == EBUSY)
2449 quit("the trace facility is currently in use...\n fs_usage, sc_usage, and latency use this feature.\n\n");
2450 else
2451 quit("trace facility failure, KERN_KDREMOVE\n");
2452 }
2453 }
2454
2455 void
2456 set_init()
2457 { kd_regtype kr;
2458
2459 kr.type = KDBG_RANGETYPE;
2460 kr.value1 = 0;
2461 kr.value2 = -1;
2462 needed = sizeof(kd_regtype);
2463
2464 mib[0] = CTL_KERN;
2465 mib[1] = KERN_KDEBUG;
2466 mib[2] = KERN_KDSETREG;
2467 mib[3] = 0;
2468 mib[4] = 0;
2469 mib[5] = 0; /* no flags */
2470
2471 if (sysctl(mib, 3, &kr, &needed, NULL, 0) < 0)
2472 quit("trace facility failure, KERN_KDSETREG\n");
2473
2474 mib[0] = CTL_KERN;
2475 mib[1] = KERN_KDEBUG;
2476 mib[2] = KERN_KDSETUP;
2477 mib[3] = 0;
2478 mib[4] = 0;
2479 mib[5] = 0; /* no flags */
2480
2481 if (sysctl(mib, 3, NULL, &needed, NULL, 0) < 0)
2482 quit("trace facility failure, KERN_KDSETUP\n");
2483 }
2484
2485
2486 void
2487 sample_sc()
2488 {
2489 kd_buf *kd;
2490 int i, count;
2491 size_t needed;
2492 uint32_t my_buffer_size = 0;
2493
2494 if (!RAW_flag)
2495 get_bufinfo(&bufinfo);
2496 else
2497 my_buffer_size = num_events * sizeof(kd_buf);
2498
2499 if (need_new_map) {
2500 read_command_map();
2501 need_new_map = 0;
2502 }
2503 if (!RAW_flag) {
2504 needed = bufinfo.nkdbufs * sizeof(kd_buf);
2505
2506 mib[0] = CTL_KERN;
2507 mib[1] = KERN_KDEBUG;
2508 mib[2] = KERN_KDREADTR;
2509 mib[3] = 0;
2510 mib[4] = 0;
2511 mib[5] = 0; /* no flags */
2512
2513 if (sysctl(mib, 3, my_buffer, &needed, NULL, 0) < 0)
2514 quit("trace facility failure, KERN_KDREADTR\n");
2515 count = needed;
2516
2517 if (count > (num_events / 8)) {
2518 if (usleep_ms > USLEEP_BEHIND)
2519 usleep_ms = USLEEP_BEHIND;
2520 else if (usleep_ms > USLEEP_MIN)
2521 usleep_ms /= 2;
2522
2523 } else if (count < (num_events / 16)) {
2524 if (usleep_ms < USLEEP_MAX)
2525 usleep_ms *= 2;
2526 }
2527
2528 if (bufinfo.flags & KDBG_WRAPPED) {
2529 fprintf(stderr, "fs_usage: buffer overrun, events generated too quickly: %d\n", count);
2530
2531 delete_all_events();
2532
2533 need_new_map = 1;
2534
2535 set_enable(0);
2536 set_enable(1);
2537 }
2538 } else {
2539 int bytes_read;
2540
2541 if ((bytes_read = read(RAW_fd, my_buffer, my_buffer_size)) < sizeof(kd_buf))
2542 exit(0);
2543 count = bytes_read / sizeof(kd_buf);
2544 }
2545 kd = (kd_buf *)my_buffer;
2546 #if 0
2547 fprintf(stderr, "READTR returned %d items\n", count);
2548 #endif
2549 for (i = 0; i < count; i++) {
2550 uint32_t debugid;
2551 uintptr_t thread;
2552 int type;
2553 int index;
2554 uintptr_t *sargptr;
2555 uint64_t now;
2556 long long l_usecs;
2557 int secs;
2558 long curr_time;
2559 th_info_t ti;
2560 struct diskio *dio;
2561
2562
2563 thread = kd[i].arg5;
2564 debugid = kd[i].debugid;
2565 type = kd[i].debugid & DBG_FUNC_MASK;
2566
2567 now = kdbg_get_timestamp(&kd[i]);
2568
2569 if (i == 0 && !RAW_flag) {
2570
2571 curr_time = time((long *)0);
2572 /*
2573 * Compute bias seconds after each trace buffer read.
2574 * This helps resync timestamps with the system clock
2575 * in the event of a system sleep.
2576 */
2577 if (bias_secs == 0 || curr_time < last_time || curr_time > (last_time + 2)) {
2578 l_usecs = (long long)(now / divisor);
2579 secs = l_usecs / 1000000;
2580 bias_secs = curr_time - secs;
2581 }
2582 }
2583 if (RAW_flag && bias_now == 0.0)
2584 bias_now = now;
2585
2586 if ((type & P_DISKIO_MASK) == P_DISKIO) {
2587 insert_diskio(type, kd[i].arg1, kd[i].arg2, kd[i].arg3, kd[i].arg4, thread, (double)now);
2588 continue;
2589 }
2590 if ((type & P_DISKIO_MASK) == P_DISKIO_DONE) {
2591 if ((dio = complete_diskio(kd[i].arg1, kd[i].arg4, kd[i].arg3, thread, (double)now))) {
2592 dio->vnodeid = kd[i].arg2;
2593 print_diskio(dio);
2594 free_diskio(dio);
2595 }
2596 continue;
2597 }
2598
2599 if ((type & CLASS_MASK) == P_CS_Class) {
2600
2601 // the usual DBG_FUNC_START/END does not work for i/o since it will
2602 // return on a different thread, this code uses the P_CS_IO_Done (0x4) bit
2603 // instead. the trace command doesn't know how handle either method
2604 // (unmatched start/end or 0x4) but works a little better this way.
2605
2606 int cs_type = type & P_CS_Type_Mask; // strip out the done bit
2607 bool start = (type & P_CS_IO_Done) != P_CS_IO_Done;
2608
2609 switch (cs_type) {
2610
2611 case P_CS_ReadChunk:
2612 case P_CS_WriteChunk:
2613 case P_CS_MetaRead:
2614 case P_CS_MetaWrite:
2615 if (start) {
2616 insert_diskio(cs_type, kd[i].arg2, kd[i].arg1, kd[i].arg3, kd[i].arg4, thread, (double)now);
2617 } else {
2618 if ((dio = complete_diskio(kd[i].arg2, kd[i].arg4, kd[i].arg3, thread, (double)now))) {
2619 print_diskio(dio);
2620 free_diskio(dio);
2621 }
2622 }
2623 continue;
2624
2625 case P_CS_TransformRead:
2626 case P_CS_TransformWrite:
2627 case P_CS_MigrationRead:
2628 case P_CS_MigrationWrite:
2629 if (start) {
2630 insert_diskio(cs_type, kd[i].arg2, CS_DEV, kd[i].arg3, kd[i].arg4, thread, (double)now);
2631 } else {
2632 if ((dio = complete_diskio(kd[i].arg2, kd[i].arg4, kd[i].arg3, thread, (double)now))) {
2633 print_diskio(dio);
2634 free_diskio(dio);
2635 }
2636 }
2637 continue;
2638
2639 case P_CS_SYNC_DISK:
2640 if (start) {
2641 enter_event(thread, cs_type, &kd[i], NULL, (double)now);
2642 } else {
2643 exit_event(" SyncCacheCS", thread, cs_type, kd[i].arg1, 0, 0, 0, FMT_SYNC_DISK_CS, (double)now);
2644 }
2645 continue;
2646 }
2647
2648 continue; // ignore other cs timestamps
2649 }
2650
2651 switch (type) {
2652
2653 case TRACE_DATA_NEWTHREAD:
2654 if (kd[i].arg1) {
2655 if ((ti = add_event(thread, TRACE_DATA_NEWTHREAD)) == NULL)
2656 continue;
2657 ti->child_thread = kd[i].arg1;
2658 ti->pid = kd[i].arg2;
2659 }
2660 continue;
2661
2662 case TRACE_STRING_NEWTHREAD:
2663 if ((ti = find_event(thread, TRACE_DATA_NEWTHREAD)) == (struct th_info *)0)
2664 continue;
2665
2666 create_map_entry(ti->child_thread, ti->pid, (char *)&kd[i].arg1);
2667
2668 delete_event(ti);
2669 continue;
2670
2671 case TRACE_DATA_EXEC:
2672 if ((ti = add_event(thread, TRACE_DATA_EXEC)) == NULL)
2673 continue;
2674
2675 ti->pid = kd[i].arg1;
2676 continue;
2677
2678 case TRACE_STRING_EXEC:
2679 if ((ti = find_event(thread, BSC_execve))) {
2680 if (ti->lookups[0].pathname[0])
2681 exit_event("execve", thread, BSC_execve, 0, 0, 0, 0, FMT_DEFAULT, (double)now);
2682
2683 } else if ((ti = find_event(thread, BSC_posix_spawn))) {
2684 if (ti->lookups[0].pathname[0])
2685 exit_event("posix_spawn", thread, BSC_posix_spawn, 0, 0, 0, 0, FMT_DEFAULT, (double)now);
2686 }
2687 if ((ti = find_event(thread, TRACE_DATA_EXEC)) == (struct th_info *)0)
2688 continue;
2689
2690 create_map_entry(thread, ti->pid, (char *)&kd[i].arg1);
2691
2692 delete_event(ti);
2693 continue;
2694
2695 case BSC_thread_terminate:
2696 delete_map_entry(thread);
2697 continue;
2698
2699 case BSC_exit:
2700 continue;
2701
2702 case proc_exit:
2703 kd[i].arg1 = kd[i].arg2 >> 8;
2704 type = BSC_exit;
2705 break;
2706
2707 case BSC_mmap:
2708 if (kd[i].arg4 & MAP_ANON)
2709 continue;
2710 break;
2711
2712 case MACH_idle:
2713 case MACH_sched:
2714 case MACH_stkhandoff:
2715 mark_thread_waited(thread);
2716 continue;
2717
2718 case BC_IO_HIT:
2719 case BC_IO_HIT_STALLED:
2720 case BC_IO_MISS:
2721 case BC_IO_MISS_CUT_THROUGH:
2722 case BC_PLAYBACK_IO:
2723 if ((dio = find_diskio(kd[i].arg1)) != NULL)
2724 dio->bc_info = type;
2725 continue;
2726
2727 case HFS_modify_block_end:
2728 if ((ti = find_event(thread, 0))) {
2729 if (ti->nameptr)
2730 add_meta_name(kd[i].arg2, ti->nameptr);
2731 }
2732 continue;
2733
2734 case VFS_ALIAS_VP:
2735 add_vnode_name(kd[i].arg2, find_vnode_name(kd[i].arg1));
2736 continue;
2737
2738 case VFS_LOOKUP:
2739 if ((ti = find_event(thread, 0)) == (struct th_info *)0)
2740 continue;
2741
2742 if (debugid & DBG_FUNC_START) {
2743
2744 if (ti->in_hfs_update) {
2745 ti->pn_work_index = (MAX_PATHNAMES - 1);
2746 } else {
2747 if (ti->pn_scall_index < MAX_SCALL_PATHNAMES)
2748 ti->pn_work_index = ti->pn_scall_index;
2749 else
2750 continue;
2751 }
2752 sargptr = &ti->lookups[ti->pn_work_index].pathname[0];
2753
2754 ti->vnodeid = kd[i].arg1;
2755
2756 *sargptr++ = kd[i].arg2;
2757 *sargptr++ = kd[i].arg3;
2758 *sargptr++ = kd[i].arg4;
2759 /*
2760 * NULL terminate the 'string'
2761 */
2762 *sargptr = 0;
2763
2764 ti->pathptr = sargptr;
2765 } else {
2766 sargptr = ti->pathptr;
2767
2768 /*
2769 * We don't want to overrun our pathname buffer if the
2770 * kernel sends us more VFS_LOOKUP entries than we can
2771 * handle and we only handle 2 pathname lookups for
2772 * a given system call
2773 */
2774 if (sargptr == 0)
2775 continue;
2776
2777 if ((uintptr_t)sargptr < (uintptr_t)&ti->lookups[ti->pn_work_index].pathname[NUMPARMS]) {
2778
2779 *sargptr++ = kd[i].arg1;
2780 *sargptr++ = kd[i].arg2;
2781 *sargptr++ = kd[i].arg3;
2782 *sargptr++ = kd[i].arg4;
2783 /*
2784 * NULL terminate the 'string'
2785 */
2786 *sargptr = 0;
2787 }
2788 }
2789 if (debugid & DBG_FUNC_END) {
2790
2791 ti->nameptr = add_vnode_name(ti->vnodeid, &ti->lookups[ti->pn_work_index].pathname[0]);
2792
2793 if (ti->pn_work_index == ti->pn_scall_index) {
2794
2795 ti->pn_scall_index++;
2796
2797 if (ti->pn_scall_index < MAX_SCALL_PATHNAMES)
2798 ti->pathptr = &ti->lookups[ti->pn_scall_index].pathname[0];
2799 else
2800 ti->pathptr = 0;
2801 }
2802 } else
2803 ti->pathptr = sargptr;
2804
2805 continue;
2806 }
2807
2808 if (debugid & DBG_FUNC_START) {
2809 char * p;
2810
2811 if ((type & CLASS_MASK) == FILEMGR_BASE) {
2812
2813 index = filemgr_index(type);
2814
2815 if (index >= MAX_FILEMGR)
2816 continue;
2817
2818 if ((p = filemgr_calls[index].fm_name) == NULL)
2819 continue;
2820 } else
2821 p = NULL;
2822
2823 enter_event(thread, type, &kd[i], p, (double)now);
2824 continue;
2825 }
2826
2827 switch (type) {
2828
2829 case Throttled:
2830 exit_event(" THROTTLED", thread, type, 0, 0, 0, 0, FMT_DEFAULT, (double)now);
2831 continue;
2832
2833 case HFS_update:
2834 exit_event(" HFS_update", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, FMT_HFS_update, (double)now);
2835 continue;
2836
2837 case SPEC_unmap_info:
2838 if (check_filter_mode(NULL, SPEC_unmap_info, 0, 0, "SPEC_unmap_info"))
2839 format_print(NULL, " TrimExtent", thread, type, kd[i].arg1, kd[i].arg2, kd[i].arg3, 0, FMT_UNMAP_INFO, now, now, 0, "", NULL);
2840 continue;
2841
2842 case SPEC_ioctl:
2843 if (kd[i].arg2 == DKIOCSYNCHRONIZECACHE)
2844 exit_event("IOCTL", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, FMT_IOCTL_SYNC, (double)now);
2845 else if (kd[i].arg2 == DKIOCUNMAP)
2846 exit_event("IOCTL", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, FMT_IOCTL_UNMAP, (double)now);
2847 else {
2848 if ((ti = find_event(thread, type)))
2849 delete_event(ti);
2850 }
2851 continue;
2852
2853 case MACH_pageout:
2854 if (kd[i].arg2)
2855 exit_event("PAGE_OUT_ANON", thread, type, 0, kd[i].arg1, 0, 0, FMT_PGOUT, (double)now);
2856 else
2857 exit_event("PAGE_OUT_FILE", thread, type, 0, kd[i].arg1, 0, 0, FMT_PGOUT, (double)now);
2858 continue;
2859
2860 case MACH_vmfault:
2861 if (kd[i].arg4 == DBG_PAGEIN_FAULT)
2862 exit_event("PAGE_IN", thread, type, 0, kd[i].arg1, kd[i].arg2, 0, FMT_PGIN, (double)now);
2863 else if (kd[i].arg4 == DBG_PAGEINV_FAULT)
2864 exit_event("PAGE_IN_FILE", thread, type, 0, kd[i].arg1, kd[i].arg2, 0, FMT_PGIN, (double)now);
2865 else if (kd[i].arg4 == DBG_PAGEIND_FAULT)
2866 exit_event("PAGE_IN_ANON", thread, type, 0, kd[i].arg1, kd[i].arg2, 0, FMT_PGIN, (double)now);
2867 else if (kd[i].arg4 == DBG_CACHE_HIT_FAULT)
2868 exit_event("CACHE_HIT", thread, type, 0, kd[i].arg1, kd[i].arg2, 0, FMT_CACHEHIT, (double)now);
2869 else {
2870 if ((ti = find_event(thread, type)))
2871 delete_event(ti);
2872 }
2873 continue;
2874
2875 case MSC_map_fd:
2876 exit_event("map_fd", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, FMT_FD, (double)now);
2877 continue;
2878
2879 case BSC_mmap_extended:
2880 case BSC_mmap_extended2:
2881 case BSC_msync_extended:
2882 case BSC_pread_extended:
2883 case BSC_pwrite_extended:
2884 extend_syscall(thread, type, &kd[i]);
2885 continue;
2886 }
2887
2888 if ((type & CSC_MASK) == BSC_BASE) {
2889
2890 if ((index = BSC_INDEX(type)) >= MAX_BSD_SYSCALL)
2891 continue;
2892
2893 if (bsd_syscalls[index].sc_name) {
2894 exit_event(bsd_syscalls[index].sc_name, thread, type, kd[i].arg1, kd[i].arg2, kd[i].arg3, kd[i].arg4,
2895 bsd_syscalls[index].sc_format, (double)now);
2896
2897 if (type == BSC_exit)
2898 delete_map_entry(thread);
2899 }
2900 } else if ((type & CLASS_MASK) == FILEMGR_BASE) {
2901
2902 if ((index = filemgr_index(type)) >= MAX_FILEMGR)
2903 continue;
2904
2905 if (filemgr_calls[index].fm_name) {
2906 exit_event(filemgr_calls[index].fm_name, thread, type, kd[i].arg1, kd[i].arg2, kd[i].arg3, kd[i].arg4,
2907 FMT_DEFAULT, (double)now);
2908 }
2909 }
2910 }
2911 fflush(0);
2912 }
2913
2914
2915 void
2916 enter_event_now(uintptr_t thread, int type, kd_buf *kd, char *name, double now)
2917 {
2918 th_info_t ti;
2919 threadmap_t tme;
2920 int secs;
2921 int usecs;
2922 long long l_usecs;
2923 long curr_time;
2924 int clen = 0;
2925 int tsclen = 0;
2926 int nmclen = 0;
2927 int argsclen = 0;
2928 char buf[MAXWIDTH];
2929
2930 if ((ti = add_event(thread, type)) == NULL)
2931 return;
2932
2933 ti->stime = now;
2934 ti->arg1 = kd->arg1;
2935 ti->arg2 = kd->arg2;
2936 ti->arg3 = kd->arg3;
2937 ti->arg4 = kd->arg4;
2938
2939 switch (type) {
2940
2941 case HFS_update:
2942 ti->in_hfs_update = 1;
2943 break;
2944 }
2945
2946 if ((type & CLASS_MASK) == FILEMGR_BASE &&
2947 (!RAW_flag || (now >= start_time && now <= end_time))) {
2948
2949 filemgr_in_progress++;
2950 ti->in_filemgr = 1;
2951
2952 if (RAW_flag) {
2953 l_usecs = (long long)((now - bias_now) / divisor);
2954 l_usecs += (sample_TOD_secs * 1000000) + sample_TOD_usecs;
2955 } else
2956 l_usecs = (long long)(now / divisor);
2957 secs = l_usecs / 1000000;
2958 curr_time = bias_secs + secs;
2959
2960 sprintf(buf, "%-8.8s", &(ctime(&curr_time)[11]));
2961 tsclen = strlen(buf);
2962
2963 if (columns > MAXCOLS || wideflag) {
2964 usecs = l_usecs - (long long)((long long)secs * 1000000);
2965 sprintf(&buf[tsclen], ".%06ld", (long)usecs);
2966 tsclen = strlen(buf);
2967 }
2968
2969 /*
2970 * Print timestamp column
2971 */
2972 printf("%s", buf);
2973
2974 tme = find_map_entry(thread);
2975 if (tme) {
2976 sprintf(buf, " %-25.25s ", name);
2977 nmclen = strlen(buf);
2978 printf("%s", buf);
2979
2980 sprintf(buf, "(%d, 0x%lx, 0x%lx, 0x%lx)", (short)kd->arg1, kd->arg2, kd->arg3, kd->arg4);
2981 argsclen = strlen(buf);
2982
2983 /*
2984 * Calculate white space out to command
2985 */
2986 if (columns > MAXCOLS || wideflag) {
2987 clen = columns - (tsclen + nmclen + argsclen + 20 + 11);
2988 } else
2989 clen = columns - (tsclen + nmclen + argsclen + 12);
2990
2991 if (clen > 0) {
2992 printf("%s", buf); /* print the kdargs */
2993 memset(buf, ' ', clen);
2994 buf[clen] = '\0';
2995 printf("%s", buf);
2996 }
2997 else if ((argsclen + clen) > 0) {
2998 /*
2999 * no room so wipe out the kdargs
3000 */
3001 memset(buf, ' ', (argsclen + clen));
3002 buf[argsclen + clen] = '\0';
3003 printf("%s", buf);
3004 }
3005 if (columns > MAXCOLS || wideflag)
3006 printf("%s.%d\n", tme->tm_command, (int)thread);
3007 else
3008 printf("%-12.12s\n", tme->tm_command);
3009 } else
3010 printf(" %-24.24s (%5d, %#lx, 0x%lx, 0x%lx)\n", name, (short)kd->arg1, kd->arg2, kd->arg3, kd->arg4);
3011 }
3012 }
3013
3014
3015 void
3016 enter_event(uintptr_t thread, int type, kd_buf *kd, char *name, double now)
3017 {
3018 int index;
3019
3020 switch (type) {
3021
3022 case P_CS_SYNC_DISK:
3023 case MACH_pageout:
3024 case MACH_vmfault:
3025 case MSC_map_fd:
3026 case SPEC_ioctl:
3027 case Throttled:
3028 case HFS_update:
3029 enter_event_now(thread, type, kd, name, now);
3030 return;
3031
3032 }
3033 if ((type & CSC_MASK) == BSC_BASE) {
3034
3035 if ((index = BSC_INDEX(type)) >= MAX_BSD_SYSCALL)
3036 return;
3037
3038 if (bsd_syscalls[index].sc_name)
3039 enter_event_now(thread, type, kd, name, now);
3040 return;
3041 }
3042 if ((type & CLASS_MASK) == FILEMGR_BASE) {
3043
3044 if ((index = filemgr_index(type)) >= MAX_FILEMGR)
3045 return;
3046
3047 if (filemgr_calls[index].fm_name)
3048 enter_event_now(thread, type, kd, name, now);
3049 return;
3050 }
3051 }
3052
3053 /*
3054 * Handle system call extended trace data.
3055 * pread and pwrite:
3056 * Wipe out the kd args that were collected upon syscall_entry
3057 * because it is the extended info that we really want, and it
3058 * is all we really need.
3059 */
3060
3061 void
3062 extend_syscall(uintptr_t thread, int type, kd_buf *kd)
3063 {
3064 th_info_t ti;
3065
3066 switch (type) {
3067 case BSC_mmap_extended:
3068 if ((ti = find_event(thread, BSC_mmap)) == (struct th_info *)0)
3069 return;
3070 ti->arg8 = ti->arg3; /* save protection */
3071 ti->arg1 = kd->arg1; /* the fd */
3072 ti->arg3 = kd->arg2; /* bottom half address */
3073 ti->arg5 = kd->arg3; /* bottom half size */
3074 break;
3075 case BSC_mmap_extended2:
3076 if ((ti = find_event(thread, BSC_mmap)) == (struct th_info *)0)
3077 return;
3078 ti->arg2 = kd->arg1; /* top half address */
3079 ti->arg4 = kd->arg2; /* top half size */
3080 ti->arg6 = kd->arg3; /* top half file offset */
3081 ti->arg7 = kd->arg4; /* bottom half file offset */
3082 break;
3083 case BSC_msync_extended:
3084 if ((ti = find_event(thread, BSC_msync)) == (struct th_info *)0) {
3085 if ((ti = find_event(thread, BSC_msync_nocancel)) == (struct th_info *)0)
3086 return;
3087 }
3088 ti->arg4 = kd->arg1; /* top half address */
3089 ti->arg5 = kd->arg2; /* top half size */
3090 break;
3091 case BSC_pread_extended:
3092 if ((ti = find_event(thread, BSC_pread)) == (struct th_info *)0) {
3093 if ((ti = find_event(thread, BSC_pread_nocancel)) == (struct th_info *)0)
3094 return;
3095 }
3096 ti->arg1 = kd->arg1; /* the fd */
3097 ti->arg2 = kd->arg2; /* nbytes */
3098 ti->arg3 = kd->arg3; /* top half offset */
3099 ti->arg4 = kd->arg4; /* bottom half offset */
3100 break;
3101 case BSC_pwrite_extended:
3102 if ((ti = find_event(thread, BSC_pwrite)) == (struct th_info *)0) {
3103 if ((ti = find_event(thread, BSC_pwrite_nocancel)) == (struct th_info *)0)
3104 return;
3105 }
3106 ti->arg1 = kd->arg1; /* the fd */
3107 ti->arg2 = kd->arg2; /* nbytes */
3108 ti->arg3 = kd->arg3; /* top half offset */
3109 ti->arg4 = kd->arg4; /* bottom half offset */
3110 break;
3111 default:
3112 return;
3113 }
3114 }
3115
3116
3117 void
3118 exit_event(char *sc_name, uintptr_t thread, int type, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, uintptr_t arg4,
3119 int format, double now)
3120 {
3121 th_info_t ti;
3122
3123 if ((ti = find_event(thread, type)) == (struct th_info *)0)
3124 return;
3125
3126 ti->nameptr = 0;
3127
3128 if (check_filter_mode(ti, type, arg1, arg2, sc_name))
3129 format_print(ti, sc_name, thread, type, arg1, arg2, arg3, arg4, format, now, ti->stime, ti->waited, (char *)&ti->lookups[0].pathname[0], NULL);
3130
3131 switch (type) {
3132
3133 case HFS_update:
3134 ti->in_hfs_update = 0;
3135 break;
3136 }
3137 if ((type & CLASS_MASK) == FILEMGR_BASE) {
3138 ti->in_filemgr = 0;
3139
3140 if (filemgr_in_progress > 0)
3141 filemgr_in_progress--;
3142 }
3143 delete_event(ti);
3144 }
3145
3146
3147 void
3148 get_mode_nibble(char * buf, int smode, int special, char x_on, char x_off)
3149 {
3150 if (smode & 04)
3151 buf[0] = 'r';
3152 if (smode & 02)
3153 buf[1] = 'w';
3154 if (smode & 01) {
3155 if (special)
3156 buf[2] = x_on;
3157 else
3158 buf[2] = 'x';
3159 } else {
3160 if (special)
3161 buf[2] = x_off;
3162 }
3163 }
3164
3165
3166 void
3167 get_mode_string(int mode, char *buf)
3168 {
3169 memset(buf, '-', 9);
3170 buf[9] = '\0';
3171
3172 get_mode_nibble(&buf[6], mode, (mode & 01000), 't', 'T');
3173 get_mode_nibble(&buf[3], (mode>>3), (mode & 02000), 's', 'S');
3174 get_mode_nibble(&buf[0], (mode>>6), (mode & 04000), 's', 'S');
3175 }
3176
3177
3178 int clip_64bit(char *s, uint64_t value)
3179 {
3180 int clen = 0;
3181
3182 if ( (value & 0xff00000000000000LL) )
3183 clen = printf("%s0x%16.16qx", s, value);
3184 else if ( (value & 0x00ff000000000000LL) )
3185 clen = printf("%s0x%14.14qx ", s, value);
3186 else if ( (value & 0x0000ff0000000000LL) )
3187 clen = printf("%s0x%12.12qx ", s, value);
3188 else if ( (value & 0x000000ff00000000LL) )
3189 clen = printf("%s0x%10.10qx ", s, value);
3190 else
3191 clen = printf("%s0x%8.8qx ", s, value);
3192
3193 return (clen);
3194 }
3195
3196
3197 void
3198 format_print(struct th_info *ti, char *sc_name, uintptr_t thread, int type, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, uintptr_t arg4,
3199 int format, double now, double stime, int waited, char *pathname, struct diskio *dio)
3200 {
3201 int secs;
3202 int usecs;
3203 int nopadding = 0;
3204 long long l_usecs;
3205 long curr_time;
3206 char *command_name;
3207 int in_filemgr = 0;
3208 int len = 0;
3209 int clen = 0;
3210 int tlen = 0;
3211 int class;
3212 uint64_t user_addr;
3213 uint64_t user_size;
3214 char *framework_name;
3215 char *framework_type;
3216 char *p1;
3217 char *p2;
3218 char buf[MAXWIDTH];
3219 char cs_diskname[32];
3220
3221 static char timestamp[32];
3222 static int last_timestamp = -1;
3223 static int timestamp_len = 0;
3224
3225 command_name = "";
3226
3227 if (RAW_flag) {
3228 l_usecs = (long long)((now - bias_now) / divisor);
3229
3230 if ((double)l_usecs < start_time || (double)l_usecs > end_time)
3231 return;
3232
3233 l_usecs += (sample_TOD_secs * 1000000) + sample_TOD_usecs;
3234 }
3235 else
3236 l_usecs = (long long)(now / divisor);
3237 secs = l_usecs / 1000000;
3238 curr_time = bias_secs + secs;
3239
3240 class = type >> 24;
3241
3242 if (dio)
3243 command_name = dio->issuing_command;
3244 else {
3245 threadmap_t tme;
3246
3247 if ((tme = find_map_entry(thread)))
3248 command_name = tme->tm_command;
3249 }
3250 if (last_timestamp != curr_time) {
3251 timestamp_len = sprintf(timestamp, "%-8.8s", &(ctime(&curr_time)[11]));
3252 last_timestamp = curr_time;
3253 }
3254 if (columns > MAXCOLS || wideflag) {
3255 int usec;
3256
3257 tlen = timestamp_len;
3258 nopadding = 0;
3259 usec = (l_usecs - (long long)((long long)secs * 1000000));
3260
3261 sprintf(&timestamp[tlen], ".%06ld", (long)usec);
3262 tlen += 7;
3263
3264 timestamp[tlen] = '\0';
3265
3266 if (filemgr_in_progress) {
3267 if (class != FILEMGR_CLASS) {
3268 if (find_event(thread, -1))
3269 in_filemgr = 1;
3270 }
3271 }
3272 } else
3273 nopadding = 1;
3274
3275 if ((class == FILEMGR_CLASS) && (columns > MAXCOLS || wideflag))
3276 clen = printf("%s %-20.20s", timestamp, sc_name);
3277 else if (in_filemgr)
3278 clen = printf("%s %-15.15s", timestamp, sc_name);
3279 else
3280 clen = printf("%s %-17.17s", timestamp, sc_name);
3281
3282
3283 framework_name = NULL;
3284
3285 if (columns > MAXCOLS || wideflag) {
3286
3287 off_t offset_reassembled = 0LL;
3288
3289 switch (format) {
3290
3291 case FMT_DEFAULT:
3292 /*
3293 * pathname based system calls or
3294 * calls with no fd or pathname (i.e. sync)
3295 */
3296 if (arg1)
3297 clen += printf(" [%3d] ", arg1);
3298 else
3299 clen += printf(" ");
3300 break;
3301
3302 case FMT_FD:
3303 /*
3304 * fd based system call... no I/O
3305 */
3306 if (arg1)
3307 clen += printf(" F=%-3d[%3d]", ti->arg1, arg1);
3308 else
3309 clen += printf(" F=%-3d", ti->arg1);
3310 break;
3311
3312 case FMT_FD_2:
3313 /*
3314 * accept, dup, dup2
3315 */
3316 if (arg1)
3317 clen += printf(" F=%-3d[%3d]", ti->arg1, arg1);
3318 else
3319 clen += printf(" F=%-3d F=%-3d", ti->arg1, arg2);
3320 break;
3321
3322 case FMT_FD_IO:
3323 /*
3324 * system calls with fd's that return an I/O completion count
3325 */
3326 if (arg1)
3327 clen += printf(" F=%-3d[%3d]", ti->arg1, arg1);
3328 else
3329 clen += printf(" F=%-3d B=0x%-6x", ti->arg1, arg2);
3330 break;
3331
3332 case FMT_PGIN:
3333 /*
3334 * pagein
3335 */
3336 user_addr = ((uint64_t)arg2 << 32) | (uint32_t)arg3;
3337
3338 lookup_name(user_addr, &framework_type, &framework_name);
3339 clen += clip_64bit(" A=", user_addr);
3340 break;
3341
3342 case FMT_CACHEHIT:
3343 /*
3344 * cache hit
3345 */
3346 user_addr = ((uint64_t)arg2 << 32) | (uint32_t)arg3;
3347
3348 lookup_name(user_addr, &framework_type, &framework_name);
3349 clen += clip_64bit(" A=", user_addr);
3350 break;
3351
3352 case FMT_PGOUT:
3353 /*
3354 * pageout
3355 */
3356 clen += printf(" B=0x%-8x", arg2);
3357 break;
3358
3359 case FMT_HFS_update:
3360 {
3361 char sbuf[7];
3362 int sflag = (int)arg2;
3363
3364 memset(sbuf, '_', 6);
3365 sbuf[6] = '\0';
3366
3367
3368 if (sflag & 0x10)
3369 sbuf[0] = 'F';
3370 if (sflag & 0x08)
3371 sbuf[1] = 'M';
3372 if (sflag & 0x20)
3373 sbuf[2] = 'D';
3374 if (sflag & 0x04)
3375 sbuf[3] = 'c';
3376 if (sflag & 0x01)
3377 sbuf[4] = 'a';
3378 if (sflag & 0x02)
3379 sbuf[5] = 'm';
3380
3381 clen += printf(" (%s) ", sbuf);
3382
3383 pathname = find_vnode_name(arg1);
3384 nopadding = 1;
3385
3386 break;
3387 }
3388
3389 case FMT_DISKIO:
3390 /*
3391 * physical disk I/O
3392 */
3393 if (dio->io_errno)
3394 clen += printf(" D=0x%8.8x [%3d]", dio->blkno, dio->io_errno);
3395 else {
3396 if (BC_flag)
3397 clen += printf(" D=0x%8.8x B=0x%-6x BC:%s /dev/%s ", dio->blkno, dio->iosize, BC_STR(dio->bc_info), find_disk_name(dio->dev));
3398 else
3399 clen += printf(" D=0x%8.8x B=0x%-6x /dev/%s ", dio->blkno, dio->iosize, find_disk_name(dio->dev));
3400
3401 if (dio->is_meta)
3402 pathname = find_meta_name(dio->blkno);
3403 else
3404 pathname = find_vnode_name(dio->vnodeid);
3405 nopadding = 1;
3406 }
3407 break;
3408
3409 case FMT_DISKIO_CS:
3410 /*
3411 * physical disk I/O
3412 */
3413 if (dio->io_errno)
3414 clen += printf(" D=0x%8.8x [%3d]", dio->blkno, dio->io_errno);
3415 else
3416 clen += printf(" D=0x%8.8x B=0x%-6x /dev/%s", dio->blkno, dio->iosize, generate_cs_disk_name(dio->dev, &cs_diskname[0]));
3417 break;
3418
3419 case FMT_SYNC_DISK_CS:
3420 /*
3421 * physical disk sync cache
3422 */
3423 clen += printf(" /dev/%s", generate_cs_disk_name(arg1, &cs_diskname[0]));
3424
3425 break;
3426
3427 case FMT_MSYNC:
3428 {
3429 /*
3430 * msync
3431 */
3432 int mlen = 0;
3433
3434 buf[0] = '\0';
3435
3436 if (ti->arg3 & MS_ASYNC)
3437 mlen += sprintf(&buf[mlen], "MS_ASYNC | ");
3438 else
3439 mlen += sprintf(&buf[mlen], "MS_SYNC | ");
3440
3441 if (ti->arg3 & MS_INVALIDATE)
3442 mlen += sprintf(&buf[mlen], "MS_INVALIDATE | ");
3443 if (ti->arg3 & MS_KILLPAGES)
3444 mlen += sprintf(&buf[mlen], "MS_KILLPAGES | ");
3445 if (ti->arg3 & MS_DEACTIVATE)
3446 mlen += sprintf(&buf[mlen], "MS_DEACTIVATE | ");
3447
3448 if (ti->arg3 & ~(MS_ASYNC | MS_SYNC | MS_INVALIDATE | MS_KILLPAGES | MS_DEACTIVATE))
3449 mlen += sprintf(&buf[mlen], "UNKNOWN | ");
3450
3451 if (mlen)
3452 buf[mlen - 3] = '\0';
3453
3454 if (arg1)
3455 clen += printf(" [%3d]", arg1);
3456
3457 user_addr = (((off_t)(unsigned int)(ti->arg4)) << 32) | (unsigned int)(ti->arg1);
3458 clen += clip_64bit(" A=", user_addr);
3459
3460 user_size = (((off_t)(unsigned int)(ti->arg5)) << 32) | (unsigned int)(ti->arg2);
3461
3462 clen += printf(" B=0x%-16qx <%s>", user_size, buf);
3463
3464 break;
3465 }
3466
3467 case FMT_FLOCK:
3468 {
3469 /*
3470 * flock
3471 */
3472 int mlen = 0;
3473
3474 buf[0] = '\0';
3475
3476 if (ti->arg2 & LOCK_SH)
3477 mlen += sprintf(&buf[mlen], "LOCK_SH | ");
3478 if (ti->arg2 & LOCK_EX)
3479 mlen += sprintf(&buf[mlen], "LOCK_EX | ");
3480 if (ti->arg2 & LOCK_NB)
3481 mlen += sprintf(&buf[mlen], "LOCK_NB | ");
3482 if (ti->arg2 & LOCK_UN)
3483 mlen += sprintf(&buf[mlen], "LOCK_UN | ");
3484
3485 if (ti->arg2 & ~(LOCK_SH | LOCK_EX | LOCK_NB | LOCK_UN))
3486 mlen += sprintf(&buf[mlen], "UNKNOWN | ");
3487
3488 if (mlen)
3489 buf[mlen - 3] = '\0';
3490
3491 if (arg1)
3492 clen += printf(" F=%-3d[%3d] <%s>", ti->arg1, arg1, buf);
3493 else
3494 clen += printf(" F=%-3d <%s>", ti->arg1, buf);
3495
3496 break;
3497 }
3498
3499 case FMT_FCNTL:
3500 {
3501 /*
3502 * fcntl
3503 */
3504 char *p = NULL;
3505 int fd = -1;
3506
3507 if (arg1)
3508 clen += printf(" F=%-3d[%3d]", ti->arg1, arg1);
3509 else
3510 clen += printf(" F=%-3d", ti->arg1);
3511
3512 switch(ti->arg2) {
3513
3514 case F_DUPFD:
3515 p = "DUPFD";
3516 break;
3517
3518 case F_GETFD:
3519 p = "GETFD";
3520 break;
3521
3522 case F_SETFD:
3523 p = "SETFD";
3524 break;
3525
3526 case F_GETFL:
3527 p = "GETFL";
3528 break;
3529
3530 case F_SETFL:
3531 p = "SETFL";
3532 break;
3533
3534 case F_GETOWN:
3535 p = "GETOWN";
3536 break;
3537
3538 case F_SETOWN:
3539 p = "SETOWN";
3540 break;
3541
3542 case F_GETLK:
3543 p = "GETLK";
3544 break;
3545
3546 case F_SETLK:
3547 p = "SETLK";
3548 break;
3549
3550 case F_SETLKW:
3551 p = "SETLKW";
3552 break;
3553
3554 case F_PREALLOCATE:
3555 p = "PREALLOCATE";
3556 break;
3557
3558 case F_SETSIZE:
3559 p = "SETSIZE";
3560 break;
3561
3562 case F_RDADVISE:
3563 p = "RDADVISE";
3564 break;
3565
3566 case F_GETPATH:
3567 p = "GETPATH";
3568 break;
3569
3570 case F_FULLFSYNC:
3571 p = "FULLFSYNC";
3572 break;
3573
3574 case F_PATHPKG_CHECK:
3575 p = "PATHPKG_CHECK";
3576 break;
3577
3578 case F_OPENFROM:
3579 p = "OPENFROM";
3580
3581 if (arg1 == 0)
3582 fd = arg2;
3583 break;
3584
3585 case F_UNLINKFROM:
3586 p = "UNLINKFROM";
3587 break;
3588
3589 case F_CHECK_OPENEVT:
3590 p = "CHECK_OPENEVT";
3591 break;
3592
3593 case F_NOCACHE:
3594 if (ti->arg3)
3595 p = "CACHING OFF";
3596 else
3597 p = "CACHING ON";
3598 break;
3599
3600 case F_GLOBAL_NOCACHE:
3601 if (ti->arg3)
3602 p = "CACHING OFF (GLOBAL)";
3603 else
3604 p = "CACHING ON (GLOBAL)";
3605 break;
3606
3607 }
3608 if (p) {
3609 if (fd == -1)
3610 clen += printf(" <%s>", p);
3611 else
3612 clen += printf(" <%s> F=%d", p, fd);
3613 } else
3614 clen += printf(" <CMD=%d>", ti->arg2);
3615
3616 break;
3617 }
3618
3619 case FMT_IOCTL:
3620 {
3621 /*
3622 * ioctl
3623 */
3624 if (arg1)
3625 clen += printf(" F=%-3d[%3d]", ti->arg1, arg1);
3626 else
3627 clen += printf(" F=%-3d", ti->arg1);
3628
3629 clen += printf(" <CMD=0x%x>", ti->arg2);
3630
3631 break;
3632 }
3633
3634 case FMT_IOCTL_SYNC:
3635 {
3636 /*
3637 * ioctl
3638 */
3639 clen += printf(" <DKIOCSYNCHRONIZECACHE> /dev/%s", find_disk_name(arg1));
3640
3641 break;
3642 }
3643
3644 case FMT_IOCTL_UNMAP:
3645 {
3646 /*
3647 * ioctl
3648 */
3649 clen += printf(" <DKIOCUNMAP> /dev/%s", find_disk_name(arg1));
3650
3651 break;
3652 }
3653
3654 case FMT_UNMAP_INFO:
3655 {
3656 clen += printf(" D=0x%8.8x B=0x%-6x /dev/%s", arg2, arg3, find_disk_name(arg1));
3657
3658 break;
3659 }
3660
3661 case FMT_SELECT:
3662 /*
3663 * select
3664 */
3665 if (arg1)
3666 clen += printf(" [%3d]", arg1);
3667 else
3668 clen += printf(" S=%-3d", arg2);
3669
3670 break;
3671
3672 case FMT_LSEEK:
3673 case FMT_PREAD:
3674 /*
3675 * pread, pwrite, lseek
3676 */
3677 clen += printf(" F=%-3d", ti->arg1);
3678
3679 if (arg1)
3680 clen += printf("[%3d] ", arg1);
3681 else {
3682 if (format == FMT_PREAD)
3683 clen += printf(" B=0x%-8x ", arg2);
3684 else
3685 clen += printf(" ");
3686 }
3687 if (format == FMT_PREAD)
3688 offset_reassembled = (((off_t)(unsigned int)(ti->arg3)) << 32) | (unsigned int)(ti->arg4);
3689 else
3690 #ifdef __ppc__
3691 offset_reassembled = (((off_t)(unsigned int)(arg2)) << 32) | (unsigned int)(arg3);
3692 #else
3693 offset_reassembled = (((off_t)(unsigned int)(arg3)) << 32) | (unsigned int)(arg2);
3694 #endif
3695 clen += clip_64bit("O=", offset_reassembled);
3696
3697 if (format == FMT_LSEEK) {
3698 char *mode;
3699
3700 if (ti->arg4 == SEEK_SET)
3701 mode = "SEEK_SET";
3702 else if (ti->arg4 == SEEK_CUR)
3703 mode = "SEEK_CUR";
3704 else if (ti->arg4 == SEEK_END)
3705 mode = "SEEK_END";
3706 else
3707 mode = "UNKNOWN";
3708
3709 clen += printf(" <%s>", mode);
3710 }
3711 break;
3712
3713 case FMT_MMAP:
3714 /*
3715 * mmap
3716 */
3717 clen += printf(" F=%-3d ", ti->arg1);
3718
3719 if (arg1)
3720 clen += printf("[%3d] ", arg1);
3721 else {
3722
3723 user_addr = (((off_t)(unsigned int)(ti->arg2)) << 32) | (unsigned int)(ti->arg3);
3724
3725 clen += clip_64bit("A=", user_addr);
3726
3727 offset_reassembled = (((off_t)(unsigned int)(ti->arg6)) << 32) | (unsigned int)(ti->arg7);
3728
3729 clen += clip_64bit("O=", offset_reassembled);
3730
3731 user_size = (((off_t)(unsigned int)(ti->arg4)) << 32) | (unsigned int)(ti->arg5);
3732
3733 clen += printf("B=0x%-16qx", user_size);
3734
3735 clen += printf(" <");
3736
3737 if (ti->arg8 & PROT_READ)
3738 clen += printf("READ");
3739
3740 if (ti->arg8 & PROT_WRITE)
3741 clen += printf("|WRITE");
3742
3743 if (ti->arg8 & PROT_EXEC)
3744 clen += printf("|EXEC");
3745
3746 clen += printf(">");
3747 }
3748 break;
3749
3750 case FMT_TRUNC:
3751 case FMT_FTRUNC:
3752 /*
3753 * ftruncate, truncate
3754 */
3755 if (format == FMT_FTRUNC)
3756 clen += printf(" F=%-3d", ti->arg1);
3757 else
3758 clen += printf(" ");
3759
3760 if (arg1)
3761 clen += printf("[%3d]", arg1);
3762
3763 #ifdef __ppc__
3764 offset_reassembled = (((off_t)(unsigned int)(ti->arg2)) << 32) | (unsigned int)(ti->arg3);
3765 #else
3766 offset_reassembled = (((off_t)(unsigned int)(ti->arg3)) << 32) | (unsigned int)(ti->arg2);
3767 #endif
3768 clen += clip_64bit(" O=", offset_reassembled);
3769
3770 nopadding = 1;
3771 break;
3772
3773 case FMT_FCHFLAGS:
3774 case FMT_CHFLAGS:
3775 {
3776 /*
3777 * fchflags, chflags
3778 */
3779 int mlen = 0;
3780
3781 if (format == FMT_FCHFLAGS) {
3782 if (arg1)
3783 clen += printf(" F=%-3d[%3d]", ti->arg1, arg1);
3784 else
3785 clen += printf(" F=%-3d", ti->arg1);
3786 } else {
3787 if (arg1)
3788 clen += printf(" [%3d] ", arg1);
3789 }
3790 buf[mlen++] = ' ';
3791 buf[mlen++] = '<';
3792
3793 if (ti->arg2 & UF_NODUMP)
3794 mlen += sprintf(&buf[mlen], "UF_NODUMP | ");
3795 if (ti->arg2 & UF_IMMUTABLE)
3796 mlen += sprintf(&buf[mlen], "UF_IMMUTABLE | ");
3797 if (ti->arg2 & UF_APPEND)
3798 mlen += sprintf(&buf[mlen], "UF_APPEND | ");
3799 if (ti->arg2 & UF_OPAQUE)
3800 mlen += sprintf(&buf[mlen], "UF_OPAQUE | ");
3801 if (ti->arg2 & SF_ARCHIVED)
3802 mlen += sprintf(&buf[mlen], "SF_ARCHIVED | ");
3803 if (ti->arg2 & SF_IMMUTABLE)
3804 mlen += sprintf(&buf[mlen], "SF_IMMUTABLE | ");
3805 if (ti->arg2 & SF_APPEND)
3806 mlen += sprintf(&buf[mlen], "SF_APPEND | ");
3807
3808 if (ti->arg2 == 0)
3809 mlen += sprintf(&buf[mlen], "CLEAR_ALL_FLAGS | ");
3810 else if (ti->arg2 & ~(UF_NODUMP | UF_IMMUTABLE | UF_APPEND | SF_ARCHIVED | SF_IMMUTABLE | SF_APPEND))
3811 mlen += sprintf(&buf[mlen], "UNKNOWN | ");
3812
3813 if (mlen >= 3)
3814 mlen -= 3;
3815
3816 buf[mlen++] = '>';
3817 buf[mlen] = '\0';
3818
3819 if (mlen < 19) {
3820 memset(&buf[mlen], ' ', 19 - mlen);
3821 mlen = 19;
3822 }
3823 clen += printf("%s", buf);
3824
3825 nopadding = 1;
3826 break;
3827 }
3828
3829 case FMT_UMASK:
3830 case FMT_FCHMOD:
3831 case FMT_FCHMOD_EXT:
3832 case FMT_CHMOD:
3833 case FMT_CHMOD_EXT:
3834 {
3835 /*
3836 * fchmod, fchmod_extended, chmod, chmod_extended
3837 */
3838 int mode;
3839
3840 if (format == FMT_FCHMOD || format == FMT_FCHMOD_EXT) {
3841 if (arg1)
3842 clen += printf(" F=%-3d[%3d] ", ti->arg1, arg1);
3843 else
3844 clen += printf(" F=%-3d ", ti->arg1);
3845 } else {
3846 if (arg1)
3847 clen += printf(" [%3d] ", arg1);
3848 else
3849 clen += printf(" ");
3850 }
3851 if (format == FMT_UMASK)
3852 mode = ti->arg1;
3853 else if (format == FMT_FCHMOD || format == FMT_CHMOD)
3854 mode = ti->arg2;
3855 else
3856 mode = ti->arg4;
3857
3858 get_mode_string(mode, &buf[0]);
3859
3860 if (arg1 == 0)
3861 clen += printf("<%s> ", buf);
3862 else
3863 clen += printf("<%s>", buf);
3864 break;
3865 }
3866
3867 case FMT_ACCESS:
3868 {
3869 /*
3870 * access
3871 */
3872 char mode[5];
3873
3874 memset(mode, '_', 4);
3875 mode[4] = '\0';
3876
3877 if (ti->arg2 & R_OK)
3878 mode[0] = 'R';
3879 if (ti->arg2 & W_OK)
3880 mode[1] = 'W';
3881 if (ti->arg2 & X_OK)
3882 mode[2] = 'X';
3883 if (ti->arg2 == F_OK)
3884 mode[3] = 'F';
3885
3886 if (arg1)
3887 clen += printf(" [%3d] (%s) ", arg1, mode);
3888 else
3889 clen += printf(" (%s) ", mode);
3890
3891 nopadding = 1;
3892 break;
3893 }
3894
3895 case FMT_MOUNT:
3896 {
3897 if (arg1)
3898 clen += printf(" [%3d] <FLGS=0x%x> ", arg1, ti->arg3);
3899 else
3900 clen += printf(" <FLGS=0x%x> ", ti->arg3);
3901
3902 nopadding = 1;
3903 break;
3904 }
3905
3906 case FMT_UNMOUNT:
3907 {
3908 char *mountflag;
3909
3910 if (ti->arg2 & MNT_FORCE)
3911 mountflag = "<FORCE>";
3912 else
3913 mountflag = "";
3914
3915 if (arg1)
3916 clen += printf(" [%3d] %s ", arg1, mountflag);
3917 else
3918 clen += printf(" %s ", mountflag);
3919
3920 nopadding = 1;
3921 break;
3922 }
3923
3924 case FMT_OPEN:
3925 {
3926 /*
3927 * open
3928 */
3929 char mode[7];
3930
3931 memset(mode, '_', 6);
3932 mode[6] = '\0';
3933
3934 if (ti->arg2 & O_RDWR) {
3935 mode[0] = 'R';
3936 mode[1] = 'W';
3937 } else if (ti->arg2 & O_WRONLY)
3938 mode[1] = 'W';
3939 else
3940 mode[0] = 'R';
3941
3942 if (ti->arg2 & O_CREAT)
3943 mode[2] = 'C';
3944
3945 if (ti->arg2 & O_APPEND)
3946 mode[3] = 'A';
3947
3948 if (ti->arg2 & O_TRUNC)
3949 mode[4] = 'T';
3950
3951 if (ti->arg2 & O_EXCL)
3952 mode[5] = 'E';
3953
3954 if (arg1)
3955 clen += printf(" [%3d] (%s) ", arg1, mode);
3956 else
3957 clen += printf(" F=%-3d (%s) ", arg2, mode);
3958
3959 nopadding = 1;
3960 break;
3961 }
3962
3963 case FMT_SOCKET:
3964 {
3965 /*
3966 * socket
3967 *
3968 */
3969 char *domain;
3970 char *type;
3971
3972 switch (ti->arg1) {
3973
3974 case AF_UNIX:
3975 domain = "AF_UNIX";
3976 break;
3977
3978 case AF_INET:
3979 domain = "AF_INET";
3980 break;
3981
3982 case AF_ISO:
3983 domain = "AF_ISO";
3984 break;
3985
3986 case AF_NS:
3987 domain = "AF_NS";
3988 break;
3989
3990 case AF_IMPLINK:
3991 domain = "AF_IMPLINK";
3992 break;
3993
3994 default:
3995 domain = "UNKNOWN";
3996 break;
3997 }
3998
3999 switch (ti->arg2) {
4000
4001 case SOCK_STREAM:
4002 type = "SOCK_STREAM";
4003 break;
4004
4005 case SOCK_DGRAM:
4006 type = "SOCK_DGRAM";
4007 break;
4008
4009 case SOCK_RAW:
4010 type = "SOCK_RAW";
4011 break;
4012
4013 case SOCK_SEQPACKET:
4014 type = "SOCK_SEQPACKET";
4015 break;
4016
4017 case SOCK_RDM:
4018 type = "SOCK_RDM";
4019 break;
4020
4021 default:
4022 type = "UNKNOWN";
4023 break;
4024 }
4025
4026 if (arg1)
4027 clen += printf(" [%3d] <%s, %s, 0x%x>", arg1, domain, type, ti->arg3);
4028 else
4029 clen += printf(" F=%-3d <%s, %s, 0x%x>", arg2, domain, type, ti->arg3);
4030 break;
4031 }
4032
4033 case FMT_AIO_FSYNC:
4034 {
4035 /*
4036 * aio_fsync [errno] AIOCBP OP
4037 */
4038 char *op;
4039
4040 if (ti->arg1 == O_SYNC || ti->arg1 == 0)
4041 op = "AIO_FSYNC";
4042 #if O_DSYNC
4043 else if (ti->arg1 == O_DSYNC)
4044 op = "AIO_DSYNC";
4045 #endif
4046 else
4047 op = "UNKNOWN";
4048
4049 if (arg1)
4050 clen += printf(" [%3d] P=0x%8.8x <%s>", arg1, ti->arg2, op);
4051 else
4052 clen += printf(" P=0x%8.8x <%s>", ti->arg2, op);
4053 break;
4054 }
4055
4056 case FMT_AIO_RETURN:
4057 /*
4058 * aio_return [errno] AIOCBP IOSIZE
4059 */
4060 if (arg1)
4061 clen += printf(" [%3d] P=0x%8.8x", arg1, ti->arg1);
4062 else
4063 clen += printf(" P=0x%8.8x B=0x%-8x", ti->arg1, arg2);
4064 break;
4065
4066 case FMT_AIO_SUSPEND:
4067 /*
4068 * aio_suspend [errno] NENTS
4069 */
4070 if (arg1)
4071 clen += printf(" [%3d] N=%d", arg1, ti->arg2);
4072 else
4073 clen += printf(" N=%d", ti->arg2);
4074 break;
4075
4076 case FMT_AIO_CANCEL:
4077 /*
4078 * aio_cancel [errno] FD or AIOCBP (if non-null)
4079 */
4080 if (ti->arg2) {
4081 if (arg1)
4082 clen += printf(" [%3d] P=0x%8.8x", arg1, ti->arg2);
4083 else
4084 clen += printf(" P=0x%8.8x", ti->arg2);
4085 } else {
4086 if (arg1)
4087 clen += printf(" F=%-3d[%3d]", ti->arg1, arg1);
4088 else
4089 clen += printf(" F=%-3d", ti->arg1);
4090 }
4091 break;
4092
4093 case FMT_AIO:
4094 /*
4095 * aio_error, aio_read, aio_write [errno] AIOCBP
4096 */
4097 if (arg1)
4098 clen += printf(" [%3d] P=0x%8.8x", arg1, ti->arg1);
4099 else
4100 clen += printf(" P=0x%8.8x", ti->arg1);
4101 break;
4102
4103 case FMT_LIO_LISTIO:
4104 {
4105 /*
4106 * lio_listio [errno] NENTS MODE
4107 */
4108 char *op;
4109
4110 if (ti->arg1 == LIO_NOWAIT)
4111 op = "LIO_NOWAIT";
4112 else if (ti->arg1 == LIO_WAIT)
4113 op = "LIO_WAIT";
4114 else
4115 op = "UNKNOWN";
4116
4117 if (arg1)
4118 clen += printf(" [%3d] N=%d <%s>", arg1, ti->arg3, op);
4119 else
4120 clen += printf(" N=%d <%s>", ti->arg3, op);
4121 break;
4122 }
4123
4124 }
4125 }
4126
4127 /*
4128 * Calculate space available to print pathname
4129 */
4130 if (columns > MAXCOLS || wideflag)
4131 clen = columns - (clen + 14 + 20 + 11);
4132 else
4133 clen = columns - (clen + 14 + 12);
4134
4135 if (class != FILEMGR_CLASS && !nopadding)
4136 clen -= 3;
4137
4138 if (framework_name)
4139 len = sprintf(&buf[0], " %s %s ", framework_type, framework_name);
4140 else if (*pathname != '\0') {
4141 len = sprintf(&buf[0], " %s ", pathname);
4142
4143 if (format == FMT_MOUNT && ti->lookups[1].pathname[0]) {
4144 int len2;
4145
4146 memset(&buf[len], ' ', 2);
4147
4148 len2 = sprintf(&buf[len+2], " %s ", (char *)&ti->lookups[1].pathname[0]);
4149 len = len + 2 + len2;
4150 }
4151 } else
4152 len = 0;
4153
4154 if (clen > len) {
4155 /*
4156 * Add null padding if column length
4157 * is wider than the pathname length.
4158 */
4159 memset(&buf[len], ' ', clen - len);
4160 buf[clen] = '\0';
4161
4162 pathname = buf;
4163
4164 } else if (clen == len) {
4165 pathname = buf;
4166
4167 } else if ((clen > 0) && (clen < len)) {
4168 /*
4169 * This prints the tail end of the pathname
4170 */
4171 buf[len-clen] = ' ';
4172
4173 pathname = &buf[len - clen];
4174
4175 } else {
4176 pathname = "";
4177 }
4178
4179 /*
4180 * fudge some additional system call overhead
4181 * that currently isn't tracked... this also
4182 * insures that we see a minimum of 1 us for
4183 * an elapsed time
4184 */
4185 usecs = (unsigned long)(((now - stime) + (divisor-1)) / divisor);
4186 secs = usecs / 1000000;
4187 usecs -= secs * 1000000;
4188
4189 if (class != FILEMGR_CLASS && !nopadding)
4190 p1 = " ";
4191 else
4192 p1 = "";
4193
4194 if (waited)
4195 p2 = " W";
4196 else
4197 p2 = " ";
4198
4199 if (columns > MAXCOLS || wideflag)
4200 printf("%s%s %3ld.%06ld%s %s.%d\n", p1, pathname, (unsigned long)secs, (unsigned long)usecs, p2, command_name, (int)thread);
4201 else
4202 printf("%s%s %3ld.%06ld%s %-12.12s\n", p1, pathname, (unsigned long)secs, (unsigned long)usecs, p2, command_name);
4203 }
4204
4205
4206 void
4207 add_meta_name(uint64_t blockno, char *pathname) {
4208 meta_info_t mi;
4209 int hashid;
4210
4211 hashid = blockno & VN_HASH_MASK;
4212
4213 for (mi = m_info_hash[hashid]; mi; mi = mi->m_next) {
4214 if (mi->m_blkno == blockno)
4215 break;
4216 }
4217 if (mi == NULL) {
4218 mi = (meta_info_t)malloc(sizeof(struct meta_info));
4219
4220 mi->m_next = m_info_hash[hashid];
4221 m_info_hash[hashid] = mi;
4222 mi->m_blkno = blockno;
4223 }
4224 mi->m_nameptr = pathname;
4225 }
4226
4227 char *
4228 find_meta_name(uint64_t blockno) {
4229 meta_info_t mi;
4230 int hashid;
4231
4232 hashid = blockno & VN_HASH_MASK;
4233
4234 for (mi = m_info_hash[hashid]; mi; mi = mi->m_next) {
4235 if (mi->m_blkno == blockno)
4236 return (mi->m_nameptr);
4237 }
4238 return ("");
4239 }
4240
4241
4242 char *
4243 add_vnode_name(uint64_t vn_id, char *pathname) {
4244 vnode_info_t vn;
4245 int hashid;
4246
4247 hashid = (vn_id >> VN_HASH_SHIFT) & VN_HASH_MASK;
4248
4249 for (vn = vn_info_hash[hashid]; vn; vn = vn->vn_next) {
4250 if (vn->vn_id == vn_id)
4251 break;
4252 }
4253 if (vn == NULL) {
4254 vn = (vnode_info_t)malloc(sizeof(struct vnode_info));
4255
4256 vn->vn_next = vn_info_hash[hashid];
4257 vn_info_hash[hashid] = vn;
4258 vn->vn_id = vn_id;
4259 }
4260 strcpy(vn->vn_pathname, pathname);
4261
4262 return (&vn->vn_pathname);
4263 }
4264
4265
4266 char *
4267 find_vnode_name(uint64_t vn_id) {
4268 vnode_info_t vn;
4269 int hashid;
4270
4271 hashid = (vn_id >> VN_HASH_SHIFT) & VN_HASH_MASK;
4272
4273 for (vn = vn_info_hash[hashid]; vn; vn = vn->vn_next) {
4274 if (vn->vn_id == vn_id)
4275 return (vn->vn_pathname);
4276 }
4277 return ("");
4278 }
4279
4280
4281 void
4282 delete_event(th_info_t ti_to_delete) {
4283 th_info_t ti;
4284 th_info_t ti_prev;
4285 int hashid;
4286
4287 hashid = ti_to_delete->thread & HASH_MASK;
4288
4289 if ((ti = th_info_hash[hashid])) {
4290 if (ti == ti_to_delete)
4291 th_info_hash[hashid] = ti->next;
4292 else {
4293 ti_prev = ti;
4294
4295 for (ti = ti->next; ti; ti = ti->next) {
4296 if (ti == ti_to_delete) {
4297 ti_prev->next = ti->next;
4298 break;
4299 }
4300 ti_prev = ti;
4301 }
4302 }
4303 if (ti) {
4304 ti->next = th_info_freelist;
4305 th_info_freelist = ti;
4306 }
4307 }
4308 }
4309
4310 th_info_t
4311 add_event(uintptr_t thread, int type) {
4312 th_info_t ti;
4313 int i;
4314 int hashid;
4315
4316 if ((ti = th_info_freelist))
4317 th_info_freelist = ti->next;
4318 else
4319 ti = (th_info_t)malloc(sizeof(struct th_info));
4320
4321 hashid = thread & HASH_MASK;
4322
4323 ti->next = th_info_hash[hashid];
4324 th_info_hash[hashid] = ti;
4325
4326 ti->thread = thread;
4327 ti->type = type;
4328
4329 ti->waited = 0;
4330 ti->in_filemgr = 0;
4331 ti->in_hfs_update = 0;
4332
4333 ti->pathptr = &ti->lookups[0].pathname[0];
4334 ti->pn_scall_index = 0;
4335 ti->pn_work_index = 0;
4336
4337 for (i = 0; i < MAX_PATHNAMES; i++)
4338 ti->lookups[i].pathname[0] = 0;
4339
4340 return (ti);
4341 }
4342
4343 th_info_t
4344 find_event(uintptr_t thread, int type) {
4345 th_info_t ti;
4346 int hashid;
4347
4348 hashid = thread & HASH_MASK;
4349
4350 for (ti = th_info_hash[hashid]; ti; ti = ti->next) {
4351 if (ti->thread == thread) {
4352 if (type == ti->type)
4353 return (ti);
4354 if (ti->in_filemgr) {
4355 if (type == -1)
4356 return (ti);
4357 continue;
4358 }
4359 if (type == 0)
4360 return (ti);
4361 }
4362 }
4363 return ((th_info_t) 0);
4364 }
4365
4366 void
4367 delete_all_events() {
4368 th_info_t ti = 0;
4369 th_info_t ti_next = 0;
4370 int i;
4371
4372 for (i = 0; i < HASH_SIZE; i++) {
4373
4374 for (ti = th_info_hash[i]; ti; ti = ti_next) {
4375 ti_next = ti->next;
4376 ti->next = th_info_freelist;
4377 th_info_freelist = ti;
4378 }
4379 th_info_hash[i] = 0;
4380 }
4381 }
4382
4383
4384 void
4385 mark_thread_waited(uintptr_t thread) {
4386 th_info_t ti;
4387 int hashid;
4388
4389 hashid = thread & HASH_MASK;
4390
4391 for (ti = th_info_hash[hashid]; ti; ti = ti->next) {
4392 if (ti->thread == thread)
4393 ti->waited = 1;
4394 }
4395 }
4396
4397
4398 void read_command_map()
4399 {
4400 size_t size;
4401 int i;
4402 int total_threads = 0;
4403 kd_threadmap *mapptr = 0;
4404
4405 delete_all_map_entries();
4406
4407 if (!RAW_flag) {
4408
4409 total_threads = bufinfo.nkdthreads;
4410 size = bufinfo.nkdthreads * sizeof(kd_threadmap);
4411
4412 if (size) {
4413 if ((mapptr = (kd_threadmap *) malloc(size))) {
4414 int mib[6];
4415
4416 bzero (mapptr, size);
4417 /*
4418 * Now read the threadmap
4419 */
4420 mib[0] = CTL_KERN;
4421 mib[1] = KERN_KDEBUG;
4422 mib[2] = KERN_KDTHRMAP;
4423 mib[3] = 0;
4424 mib[4] = 0;
4425 mib[5] = 0; /* no flags */
4426
4427 if (sysctl(mib, 3, mapptr, &size, NULL, 0) < 0) {
4428 /*
4429 * This is not fatal -- just means I cant map command strings
4430 */
4431 free(mapptr);
4432 return;
4433 }
4434 }
4435 }
4436 } else {
4437 RAW_header header;
4438 off_t offset;
4439
4440 RAW_fd = open(RAW_file, O_RDONLY);
4441
4442 if (RAW_fd < 0) {
4443 perror("Can't open RAW file");
4444 exit(1);
4445 }
4446 if (read(RAW_fd, &header, sizeof(RAW_header)) != sizeof(RAW_header)) {
4447 perror("read failed");
4448 exit(2);
4449 }
4450 if (header.version_no != RAW_VERSION1) {
4451 header.version_no = RAW_VERSION0;
4452 header.TOD_secs = time((long *)0);
4453 header.TOD_usecs = 0;
4454
4455 lseek(RAW_fd, (off_t)0, SEEK_SET);
4456
4457 if (read(RAW_fd, &header.thread_count, sizeof(int)) != sizeof(int)) {
4458 perror("read failed");
4459 exit(2);
4460 }
4461 }
4462 sample_TOD_secs = header.TOD_secs;
4463 sample_TOD_usecs = header.TOD_usecs;
4464
4465 total_threads = header.thread_count;
4466 size = total_threads * sizeof(kd_threadmap);
4467
4468 if (size) {
4469 if ((mapptr = (kd_threadmap *) malloc(size))) {
4470 bzero (mapptr, size);
4471
4472 if (read(RAW_fd, mapptr, size) != size) {
4473 free(mapptr);
4474 return;
4475 }
4476 }
4477 }
4478 if (header.version_no != RAW_VERSION0) {
4479 offset = lseek(RAW_fd, (off_t)0, SEEK_CUR);
4480 offset = (offset + (4095)) & ~4095;
4481
4482 lseek(RAW_fd, offset, SEEK_SET);
4483 }
4484 }
4485 for (i = 0; i < total_threads; i++)
4486 create_map_entry(mapptr[i].thread, mapptr[i].valid, &mapptr[i].command[0]);
4487
4488 free(mapptr);
4489 }
4490
4491
4492 void delete_all_map_entries()
4493 {
4494 threadmap_t tme = 0;
4495 threadmap_t tme_next = 0;
4496 int i;
4497
4498 for (i = 0; i < HASH_SIZE; i++) {
4499
4500 for (tme = threadmap_hash[i]; tme; tme = tme_next) {
4501 if (tme->tm_setptr)
4502 free(tme->tm_setptr);
4503 tme_next = tme->tm_next;
4504 tme->tm_next = threadmap_freelist;
4505 threadmap_freelist = tme;
4506 }
4507 threadmap_hash[i] = 0;
4508 }
4509 }
4510
4511
4512 void create_map_entry(uintptr_t thread, int pid, char *command)
4513 {
4514 threadmap_t tme;
4515 int hashid;
4516
4517 if ((tme = threadmap_freelist))
4518 threadmap_freelist = tme->tm_next;
4519 else
4520 tme = (threadmap_t)malloc(sizeof(struct threadmap));
4521
4522 tme->tm_thread = thread;
4523 tme->tm_setsize = 0;
4524 tme->tm_setptr = 0;
4525
4526 (void)strncpy (tme->tm_command, command, MAXCOMLEN);
4527 tme->tm_command[MAXCOMLEN] = '\0';
4528
4529 hashid = thread & HASH_MASK;
4530
4531 tme->tm_next = threadmap_hash[hashid];
4532 threadmap_hash[hashid] = tme;
4533
4534 if (pid != 0 && pid != 1) {
4535 if (!strncmp(command, "LaunchCFMA", 10))
4536 (void)get_real_command_name(pid, tme->tm_command, MAXCOMLEN);
4537 }
4538 }
4539
4540
4541 threadmap_t
4542 find_map_entry(uintptr_t thread)
4543 {
4544 threadmap_t tme;
4545 int hashid;
4546
4547 hashid = thread & HASH_MASK;
4548
4549 for (tme = threadmap_hash[hashid]; tme; tme = tme->tm_next) {
4550 if (tme->tm_thread == thread)
4551 return (tme);
4552 }
4553 return (0);
4554 }
4555
4556
4557 void
4558 delete_map_entry(uintptr_t thread)
4559 {
4560 threadmap_t tme = 0;
4561 threadmap_t tme_prev;
4562 int hashid;
4563
4564 hashid = thread & HASH_MASK;
4565
4566 if ((tme = threadmap_hash[hashid])) {
4567 if (tme->tm_thread == thread)
4568 threadmap_hash[hashid] = tme->tm_next;
4569 else {
4570 tme_prev = tme;
4571
4572 for (tme = tme->tm_next; tme; tme = tme->tm_next) {
4573 if (tme->tm_thread == thread) {
4574 tme_prev->tm_next = tme->tm_next;
4575 break;
4576 }
4577 tme_prev = tme;
4578 }
4579 }
4580 if (tme) {
4581 if (tme->tm_setptr)
4582 free(tme->tm_setptr);
4583
4584 tme->tm_next = threadmap_freelist;
4585 threadmap_freelist = tme;
4586 }
4587 }
4588 }
4589
4590
4591 void
4592 fs_usage_fd_set(uintptr_t thread, unsigned int fd)
4593 {
4594 threadmap_t tme;
4595
4596 if ((tme = find_map_entry(thread)) == 0)
4597 return;
4598 /*
4599 * If the map is not allocated, then now is the time
4600 */
4601 if (tme->tm_setptr == (unsigned long *)0) {
4602 if ((tme->tm_setptr = (unsigned long *)malloc(FS_USAGE_NFDBYTES(FS_USAGE_FD_SETSIZE))) == 0)
4603 return;
4604
4605 tme->tm_setsize = FS_USAGE_FD_SETSIZE;
4606 bzero(tme->tm_setptr, (FS_USAGE_NFDBYTES(FS_USAGE_FD_SETSIZE)));
4607 }
4608 /*
4609 * If the map is not big enough, then reallocate it
4610 */
4611 while (tme->tm_setsize <= fd) {
4612 int n;
4613
4614 n = tme->tm_setsize * 2;
4615 tme->tm_setptr = (unsigned long *)realloc(tme->tm_setptr, (FS_USAGE_NFDBYTES(n)));
4616
4617 bzero(&tme->tm_setptr[(tme->tm_setsize/FS_USAGE_NFDBITS)], (FS_USAGE_NFDBYTES(tme->tm_setsize)));
4618 tme->tm_setsize = n;
4619 }
4620 /*
4621 * set the bit
4622 */
4623 tme->tm_setptr[fd/FS_USAGE_NFDBITS] |= (1 << ((fd) % FS_USAGE_NFDBITS));
4624 }
4625
4626
4627 /*
4628 * Return values:
4629 * 0 : File Descriptor bit is not set
4630 * 1 : File Descriptor bit is set
4631 */
4632 int
4633 fs_usage_fd_isset(uintptr_t thread, unsigned int fd)
4634 {
4635 threadmap_t tme;
4636 int ret = 0;
4637
4638 if ((tme = find_map_entry(thread))) {
4639 if (tme->tm_setptr && fd < tme->tm_setsize)
4640 ret = tme->tm_setptr[fd/FS_USAGE_NFDBITS] & (1 << (fd % FS_USAGE_NFDBITS));
4641 }
4642 return (ret);
4643 }
4644
4645
4646 void
4647 fs_usage_fd_clear(uintptr_t thread, unsigned int fd)
4648 {
4649 threadmap_t tme;
4650
4651 if ((tme = find_map_entry(thread))) {
4652 if (tme->tm_setptr && fd < tme->tm_setsize)
4653 tme->tm_setptr[fd/FS_USAGE_NFDBITS] &= ~(1 << (fd % FS_USAGE_NFDBITS));
4654 }
4655 }
4656
4657
4658
4659 void
4660 argtopid(char *str)
4661 {
4662 char *cp;
4663 int ret;
4664 int i;
4665
4666 ret = (int)strtol(str, &cp, 10);
4667
4668 if (cp == str || *cp) {
4669 /*
4670 * Assume this is a command string and find matching pids
4671 */
4672 if (!kp_buffer)
4673 find_proc_names();
4674
4675 for (i = 0; i < kp_nentries && num_of_pids < (MAX_PIDS - 1); i++) {
4676 if (kp_buffer[i].kp_proc.p_stat == 0)
4677 continue;
4678 else {
4679 if (!strncmp(str, kp_buffer[i].kp_proc.p_comm,
4680 sizeof(kp_buffer[i].kp_proc.p_comm) -1))
4681 pids[num_of_pids++] = kp_buffer[i].kp_proc.p_pid;
4682 }
4683 }
4684 }
4685 else if (num_of_pids < (MAX_PIDS - 1))
4686 pids[num_of_pids++] = ret;
4687 }
4688
4689
4690
4691 void
4692 lookup_name(uint64_t user_addr, char **type, char **name)
4693 {
4694 int i;
4695 int start, last;
4696
4697 *name = NULL;
4698 *type = NULL;
4699
4700 if (numFrameworks) {
4701
4702 if ((user_addr >= framework32.b_address && user_addr < framework32.e_address) ||
4703 (user_addr >= framework64.b_address && user_addr < framework64.e_address)) {
4704
4705 start = 0;
4706 last = numFrameworks;
4707
4708 for (i = numFrameworks / 2; start < last; i = start + ((last - start) / 2)) {
4709 if (user_addr > frameworkInfo[i].e_address)
4710 start = i+1;
4711 else
4712 last = i;
4713 }
4714 if (start < numFrameworks &&
4715 user_addr >= frameworkInfo[start].b_address && user_addr < frameworkInfo[start].e_address) {
4716 *type = frameworkType[frameworkInfo[start].r_type];
4717 *name = frameworkInfo[start].name;
4718 }
4719 }
4720 }
4721 }
4722
4723
4724 /*
4725 * Comparison routines for sorting
4726 */
4727 static int compareFrameworkAddress(const void *aa, const void *bb)
4728 {
4729 LibraryInfo *a = (LibraryInfo *)aa;
4730 LibraryInfo *b = (LibraryInfo *)bb;
4731
4732 if (a->b_address < b->b_address) return -1;
4733 if (a->b_address == b->b_address) return 0;
4734 return 1;
4735 }
4736
4737
4738 int scanline(char *inputstring, char **argv, int maxtokens)
4739 {
4740 int n = 0;
4741 char **ap = argv, *p, *val;
4742
4743 for (p = inputstring; n < maxtokens && p != NULL; ) {
4744
4745 while ((val = strsep(&p, " \t")) != NULL && *val == '\0');
4746
4747 *ap++ = val;
4748 n++;
4749 }
4750 *ap = 0;
4751
4752 return n;
4753 }
4754
4755
4756 int ReadSharedCacheMap(const char *path, LibraryRange *lr, char *linkedit_name)
4757 {
4758 uint64_t b_address, e_address;
4759 char buf[1024];
4760 char *fnp;
4761 FILE *fd;
4762 char frameworkName[256];
4763 char *tokens[64];
4764 int ntokens;
4765 int type;
4766 int linkedit_found = 0;
4767 char *substring, *ptr;
4768
4769 bzero(buf, sizeof(buf));
4770 bzero(tokens, sizeof(tokens));
4771
4772 lr->b_address = 0;
4773 lr->e_address = 0;
4774
4775 if ((fd = fopen(path, "r")) == 0)
4776 return 0;
4777
4778 while (fgets(buf, 1023, fd)) {
4779 if (strncmp(buf, "mapping", 7))
4780 break;
4781 }
4782 buf[strlen(buf)-1] = 0;
4783
4784 frameworkName[0] = 0;
4785
4786 for (;;) {
4787 /*
4788 * Extract lib name from path name
4789 */
4790 if ((substring = strrchr(buf, '.')))
4791 {
4792 /*
4793 * There is a ".": name is whatever is between the "/" around the "."
4794 */
4795 while ( *substring != '/') /* find "/" before "." */
4796 substring--;
4797 substring++;
4798
4799 strncpy(frameworkName, substring, 256); /* copy path from "/" */
4800 frameworkName[255] = 0;
4801 substring = frameworkName;
4802
4803 while ( *substring != '/' && *substring) /* find "/" after "." and stop string there */
4804 substring++;
4805 *substring = 0;
4806 }
4807 else
4808 {
4809 /*
4810 * No ".": take segment after last "/"
4811 */
4812 ptr = buf;
4813 substring = ptr;
4814
4815 while (*ptr) {
4816 if (*ptr == '/')
4817 substring = ptr + 1;
4818 ptr++;
4819 }
4820 strncpy(frameworkName, substring, 256);
4821 frameworkName[255] = 0;
4822 }
4823 fnp = (char *)malloc(strlen(frameworkName) + 1);
4824 strcpy(fnp, frameworkName);
4825
4826 while (fgets(buf, 1023, fd) && numFrameworks < (MAXINDEX - 2)) {
4827 /*
4828 * Get rid of EOL
4829 */
4830 buf[strlen(buf)-1] = 0;
4831
4832 ntokens = scanline(buf, tokens, 64);
4833
4834 if (ntokens < 4)
4835 continue;
4836
4837 if (strncmp(tokens[0], "__TEXT", 6) == 0)
4838 type = TEXT_R;
4839 else if (strncmp(tokens[0], "__DATA", 6) == 0)
4840 type = DATA_R;
4841 else if (strncmp(tokens[0], "__OBJC", 6) == 0)
4842 type = OBJC_R;
4843 else if (strncmp(tokens[0], "__IMPORT", 8) == 0)
4844 type = IMPORT_R;
4845 else if (strncmp(tokens[0], "__UNICODE", 9) == 0)
4846 type = UNICODE_R;
4847 else if (strncmp(tokens[0], "__IMAGE", 7) == 0)
4848 type = IMAGE_R;
4849 else if (strncmp(tokens[0], "__LINKEDIT", 10) == 0)
4850 type = LINKEDIT_R;
4851 else
4852 type = -1;
4853
4854 if (type == LINKEDIT_R && linkedit_found)
4855 break;
4856
4857 if (type != -1) {
4858 b_address = strtoull(tokens[1], 0, 16);
4859 e_address = strtoull(tokens[3], 0, 16);
4860
4861 frameworkInfo[numFrameworks].b_address = b_address;
4862 frameworkInfo[numFrameworks].e_address = e_address;
4863 frameworkInfo[numFrameworks].r_type = type;
4864
4865 if (type == LINKEDIT_R) {
4866 frameworkInfo[numFrameworks].name = linkedit_name;
4867 linkedit_found = 1;
4868 } else
4869 frameworkInfo[numFrameworks].name = fnp;
4870 #if 0
4871 printf("%s(%d): %qx-%qx\n", frameworkInfo[numFrameworks].name, type, b_address, e_address);
4872 #endif
4873 if (lr->b_address == 0 || b_address < lr->b_address)
4874 lr->b_address = b_address;
4875
4876 if (lr->e_address == 0 || e_address > lr->e_address)
4877 lr->e_address = e_address;
4878
4879 numFrameworks++;
4880 }
4881 if (type == LINKEDIT_R)
4882 break;
4883 }
4884 if (fgets(buf, 1023, fd) == 0)
4885 break;
4886
4887 buf[strlen(buf)-1] = 0;
4888 }
4889 fclose(fd);
4890
4891 #if 0
4892 printf("%s range, %qx-%qx\n", path, lr->b_address, lr->e_address);
4893 #endif
4894 return 1;
4895 }
4896
4897
4898 void
4899 SortFrameworkAddresses()
4900 {
4901
4902 frameworkInfo[numFrameworks].b_address = frameworkInfo[numFrameworks - 1].b_address + 0x800000;
4903 frameworkInfo[numFrameworks].e_address = frameworkInfo[numFrameworks].b_address;
4904 frameworkInfo[numFrameworks].name = (char *)0;
4905
4906 qsort(frameworkInfo, numFrameworks, sizeof(LibraryInfo), compareFrameworkAddress);
4907 }
4908
4909
4910 struct diskio *insert_diskio(int type, int bp, int dev, int blkno, int io_size, uintptr_t thread, double curtime)
4911 {
4912 struct diskio *dio;
4913 threadmap_t tme;
4914
4915 if ((dio = free_diskios))
4916 free_diskios = dio->next;
4917 else {
4918 if ((dio = (struct diskio *)malloc(sizeof(struct diskio))) == NULL)
4919 return (NULL);
4920 }
4921 dio->prev = NULL;
4922
4923 dio->type = type;
4924 dio->bp = bp;
4925 dio->dev = dev;
4926 dio->blkno = blkno;
4927 dio->iosize = io_size;
4928 dio->issued_time = curtime;
4929 dio->issuing_thread = thread;
4930
4931 dio->bc_info = 0x0;
4932
4933 if ((tme = find_map_entry(thread))) {
4934 strncpy(dio->issuing_command, tme->tm_command, MAXCOMLEN);
4935 dio->issuing_command[MAXCOMLEN-1] = '\0';
4936 } else
4937 strcpy(dio->issuing_command, "");
4938
4939 dio->next = busy_diskios;
4940 if (dio->next)
4941 dio->next->prev = dio;
4942 busy_diskios = dio;
4943
4944 return (dio);
4945 }
4946
4947 struct diskio *find_diskio(int bp) {
4948 struct diskio *dio;
4949
4950 for (dio = busy_diskios; dio; dio = dio->next) {
4951 if (dio->bp == bp)
4952 return (dio);
4953 }
4954
4955 return NULL;
4956 }
4957
4958
4959 struct diskio *complete_diskio(int bp, int io_errno, int resid, uintptr_t thread, double curtime)
4960 {
4961 struct diskio *dio;
4962
4963 if ((dio = find_diskio(bp)) == NULL) return NULL;
4964
4965 if (dio == busy_diskios) {
4966 if ((busy_diskios = dio->next))
4967 dio->next->prev = NULL;
4968 } else {
4969 if (dio->next)
4970 dio->next->prev = dio->prev;
4971 dio->prev->next = dio->next;
4972 }
4973
4974 dio->iosize -= resid;
4975 dio->io_errno = io_errno;
4976 dio->completed_time = curtime;
4977 dio->completion_thread = thread;
4978
4979 return dio;
4980 }
4981
4982
4983 void free_diskio(struct diskio *dio)
4984 {
4985 dio->next = free_diskios;
4986 free_diskios = dio;
4987 }
4988
4989
4990 void print_diskio(struct diskio *dio)
4991 {
4992 char *p = NULL;
4993 int len = 0;
4994 int type;
4995 int format = FMT_DISKIO;
4996 char buf[64];
4997
4998 type = dio->type;
4999 dio->is_meta = 0;
5000
5001 if ((type & P_CS_Class) == P_CS_Class) {
5002
5003 switch (type) {
5004
5005 case P_CS_ReadChunk:
5006 p = " RdChunkCS";
5007 len = 13;
5008 format = FMT_DISKIO_CS;
5009 break;
5010 case P_CS_WriteChunk:
5011 p = " WrChunkCS";
5012 len = 13;
5013 format = FMT_DISKIO_CS;
5014 break;
5015 case P_CS_MetaRead:
5016 p = " RdMetaCS";
5017 len = 10;
5018 format = FMT_DISKIO_CS;
5019 break;
5020 case P_CS_MetaWrite:
5021 p = " WrMetaCS";
5022 len = 10;
5023 format = FMT_DISKIO_CS;
5024 break;
5025 case P_CS_TransformRead:
5026 p = " RdBgTfCS";
5027 len = 10;
5028 break;
5029 case P_CS_TransformWrite:
5030 p = " WrBgTfCS";
5031 len = 10;
5032 break;
5033 case P_CS_MigrationRead:
5034 p = " RdBgMigrCS";
5035 len = 12;
5036 break;
5037 case P_CS_MigrationWrite:
5038 p = " WrBgMigrCS";
5039 len = 12;
5040 break;
5041 }
5042 strncpy(buf, p, len);
5043 } else {
5044
5045 switch (type & P_DISKIO_TYPE) {
5046
5047 case P_RdMeta:
5048 dio->is_meta = 1;
5049 p = " RdMeta";
5050 len = 8;
5051 break;
5052 case P_WrMeta:
5053 dio->is_meta = 1;
5054 p = " WrMeta";
5055 len = 8;
5056 break;
5057 case P_RdData:
5058 p = " RdData";
5059 len = 8;
5060 break;
5061 case P_WrData:
5062 p = " WrData";
5063 len = 8;
5064 break;
5065 case P_PgIn:
5066 p = " PgIn";
5067 len = 6;
5068 break;
5069 case P_PgOut:
5070 p = " PgOut";
5071 len = 7;
5072 break;
5073 default:
5074 p = " ";
5075 len = 2;
5076 break;
5077 }
5078 strncpy(buf, p, len);
5079
5080 buf[len++] = '[';
5081
5082 if (type & P_DISKIO_ASYNC)
5083 buf[len++] = 'A';
5084 else
5085 buf[len++] = 'S';
5086
5087 if (type & P_DISKIO_NOCACHE)
5088 buf[len++] = 'N';
5089
5090 int tier = (type & P_DISKIO_TIER_MASK) >> P_DISKIO_TIER_SHIFT;
5091 if (tier > 0) {
5092 buf[len++] = 'T';
5093 if (tier > 0 && tier < 10)
5094 buf[len++] = '0' + tier;
5095 }
5096
5097 if (type & P_DISKIO_PASSIVE)
5098 buf[len++] = 'P';
5099
5100
5101 buf[len++] = ']';
5102 }
5103 buf[len] = 0;
5104
5105 if (check_filter_mode(NULL, type, 0, 0, buf))
5106 format_print(NULL, buf, dio->issuing_thread, type, 0, 0, 0, 0, format, dio->completed_time, dio->issued_time, 1, "", dio);
5107 }
5108
5109
5110 void cache_disk_names()
5111 {
5112 struct stat st;
5113 DIR *dirp = NULL;
5114 struct dirent *dir;
5115 struct diskrec *dnp;
5116
5117
5118 if ((dirp = opendir("/dev")) == NULL)
5119 return;
5120
5121 while ((dir = readdir(dirp)) != NULL) {
5122 char nbuf[MAXPATHLEN];
5123
5124 if (dir->d_namlen < 5 || strncmp("disk", dir->d_name, 4))
5125 continue;
5126
5127 snprintf(nbuf, MAXPATHLEN, "%s/%s", "/dev", dir->d_name);
5128
5129 if (stat(nbuf, &st) < 0)
5130 continue;
5131
5132 if ((dnp = (struct diskrec *)malloc(sizeof(struct diskrec))) == NULL)
5133 continue;
5134
5135 if ((dnp->diskname = (char *)malloc(dir->d_namlen + 1)) == NULL) {
5136 free(dnp);
5137 continue;
5138 }
5139 strncpy(dnp->diskname, dir->d_name, dir->d_namlen);
5140 dnp->diskname[dir->d_namlen] = 0;
5141 dnp->dev = st.st_rdev;
5142
5143 dnp->next = disk_list;
5144 disk_list = dnp;
5145 }
5146 (void) closedir(dirp);
5147 }
5148
5149
5150 void recache_disk_names()
5151 {
5152 struct diskrec *dnp, *next_dnp;
5153
5154 for (dnp = disk_list; dnp; dnp = next_dnp) {
5155 next_dnp = dnp->next;
5156
5157 free(dnp->diskname);
5158 free(dnp);
5159 }
5160 disk_list = NULL;
5161
5162 cache_disk_names();
5163 }
5164
5165
5166 char *find_disk_name(int dev)
5167 {
5168 struct diskrec *dnp;
5169 int i;
5170
5171 if (dev == NFS_DEV)
5172 return ("NFS");
5173
5174 if (dev == CS_DEV)
5175 return ("CS");
5176
5177 for (i = 0; i < 2; i++) {
5178 for (dnp = disk_list; dnp; dnp = dnp->next) {
5179 if (dnp->dev == dev)
5180 return (dnp->diskname);
5181 }
5182 recache_disk_names();
5183 }
5184 return ("NOTFOUND");
5185 }
5186
5187
5188 char *generate_cs_disk_name(int dev, char *s)
5189 {
5190 if (dev == -1)
5191 return ("UNKNOWN");
5192
5193 sprintf(s, "disk%ds%d", (dev >> 16) & 0xffff, dev & 0xffff);
5194
5195 return (s);
5196 }
5197
5198
5199
5200 /*
5201 * ret = 1 means print the entry
5202 * ret = 0 means don't print the entry
5203 */
5204
5205 /*
5206 * meaning of filter flags:
5207 * cachehit turn on display of CACHE_HIT events (which are filtered out by default)
5208 *
5209 * exec show exec/posix_spawn
5210 * pathname show events with a pathname and close()
5211 * diskio show disk I/Os
5212 * filesys show filesystem events
5213 * network show network events
5214 *
5215 * filters may be combined; default is all filters on (except cachehit)
5216 */
5217 int
5218 check_filter_mode(struct th_info *ti, int type, int error, int retval, char *sc_name)
5219 {
5220 int ret = 0;
5221 int network_fd_isset = 0;
5222 unsigned int fd;
5223
5224 /* cachehit is special -- it's not on by default */
5225 if (sc_name[0] == 'C' && !strcmp(sc_name, "CACHE_HIT")) {
5226 if (show_cachehits) return 1;
5227 else return 0;
5228 }
5229
5230 if (filter_mode == DEFAULT_DO_NOT_FILTER)
5231 return(1);
5232
5233 if (filter_mode & DISKIO_FILTER) {
5234 if ((type & P_DISKIO_MASK) == P_DISKIO)
5235 return 1;
5236 }
5237
5238 if (filter_mode & EXEC_FILTER) {
5239 if (type == BSC_execve || type == BSC_posix_spawn)
5240 return(1);
5241 }
5242
5243 if (filter_mode & PATHNAME_FILTER) {
5244 if (ti && ti->lookups[0].pathname[0])
5245 return(1);
5246 if (type == BSC_close || type == BSC_close_nocancel ||
5247 type == BSC_guarded_close_np)
5248 return(1);
5249 }
5250
5251 if (ti == (struct th_info *)0) {
5252 if (filter_mode & FILESYS_FILTER)
5253 return(1);
5254 return(0);
5255 }
5256
5257 switch (type) {
5258
5259 case BSC_close:
5260 case BSC_close_nocancel:
5261 case BSC_guarded_close_np:
5262 fd = ti->arg1;
5263 network_fd_isset = fs_usage_fd_isset(ti->thread, fd);
5264
5265 if (error == 0)
5266 fs_usage_fd_clear(ti->thread,fd);
5267
5268 if (network_fd_isset) {
5269 if (filter_mode & NETWORK_FILTER)
5270 ret = 1;
5271 } else
5272 if (filter_mode & FILESYS_FILTER)
5273 ret = 1;
5274 break;
5275
5276 case BSC_read:
5277 case BSC_write:
5278 case BSC_read_nocancel:
5279 case BSC_write_nocancel:
5280 /*
5281 * we don't care about error in these cases
5282 */
5283 fd = ti->arg1;
5284 network_fd_isset = fs_usage_fd_isset(ti->thread, fd);
5285
5286 if (network_fd_isset) {
5287 if (filter_mode & NETWORK_FILTER)
5288 ret = 1;
5289 } else
5290 if (filter_mode & FILESYS_FILTER)
5291 ret = 1;
5292 break;
5293
5294 case BSC_accept:
5295 case BSC_accept_nocancel:
5296 case BSC_socket:
5297 fd = retval;
5298
5299 if (error == 0)
5300 fs_usage_fd_set(ti->thread, fd);
5301 if (filter_mode & NETWORK_FILTER)
5302 ret = 1;
5303 break;
5304
5305 case BSC_recvfrom:
5306 case BSC_sendto:
5307 case BSC_recvmsg:
5308 case BSC_sendmsg:
5309 case BSC_connect:
5310 case BSC_bind:
5311 case BSC_listen:
5312 case BSC_sendto_nocancel:
5313 case BSC_recvfrom_nocancel:
5314 case BSC_recvmsg_nocancel:
5315 case BSC_sendmsg_nocancel:
5316 case BSC_connect_nocancel:
5317 fd = ti->arg1;
5318
5319 if (error == 0)
5320 fs_usage_fd_set(ti->thread, fd);
5321 if (filter_mode & NETWORK_FILTER)
5322 ret = 1;
5323 break;
5324
5325 case BSC_select:
5326 case BSC_select_nocancel:
5327 case BSC_socketpair:
5328 /*
5329 * Cannot determine info about file descriptors
5330 */
5331 if (filter_mode & NETWORK_FILTER)
5332 ret = 1;
5333 break;
5334
5335 case BSC_dup:
5336 case BSC_dup2:
5337 /*
5338 * We track these cases for fd state only
5339 */
5340 fd = ti->arg1;
5341 network_fd_isset = fs_usage_fd_isset(ti->thread, fd);
5342
5343 if (error == 0 && network_fd_isset) {
5344 /*
5345 * then we are duping a socket descriptor
5346 */
5347 fd = retval; /* the new fd */
5348 fs_usage_fd_set(ti->thread, fd);
5349 }
5350 break;
5351
5352 default:
5353 if (filter_mode & FILESYS_FILTER)
5354 ret = 1;
5355 break;
5356 }
5357
5358 return(ret);
5359 }
5360
5361 /*
5362 * Allocate a buffer that is large enough to hold the maximum arguments
5363 * to execve(). This is used when getting the arguments to programs
5364 * when we see LaunchCFMApps. If this fails, it is not fatal, we will
5365 * simply not resolve the command name.
5366 */
5367
5368 void
5369 init_arguments_buffer()
5370 {
5371 int mib[2];
5372 size_t size;
5373
5374 mib[0] = CTL_KERN;
5375 mib[1] = KERN_ARGMAX;
5376 size = sizeof(argmax);
5377
5378 if (sysctl(mib, 2, &argmax, &size, NULL, 0) == -1)
5379 return;
5380 #if 1
5381 /* Hack to avoid kernel bug. */
5382 if (argmax > 8192) {
5383 argmax = 8192;
5384 }
5385 #endif
5386 arguments = (char *)malloc(argmax);
5387 }
5388
5389
5390 int
5391 get_real_command_name(int pid, char *cbuf, int csize)
5392 {
5393 /*
5394 * Get command and arguments.
5395 */
5396 char *cp;
5397 int mib[4];
5398 char *command_beg, *command, *command_end;
5399
5400 if (cbuf == NULL)
5401 return(0);
5402
5403 if (arguments)
5404 bzero(arguments, argmax);
5405 else
5406 return(0);
5407
5408 /*
5409 * A sysctl() is made to find out the full path that the command
5410 * was called with.
5411 */
5412 mib[0] = CTL_KERN;
5413 mib[1] = KERN_PROCARGS2;
5414 mib[2] = pid;
5415 mib[3] = 0;
5416
5417 if (sysctl(mib, 3, arguments, (size_t *)&argmax, NULL, 0) < 0)
5418 return(0);
5419
5420 /*
5421 * Skip the saved exec_path
5422 */
5423 for (cp = arguments; cp < &arguments[argmax]; cp++) {
5424 if (*cp == '\0') {
5425 /*
5426 * End of exec_path reached
5427 */
5428 break;
5429 }
5430 }
5431 if (cp == &arguments[argmax])
5432 return(0);
5433
5434 /*
5435 * Skip trailing '\0' characters
5436 */
5437 for (; cp < &arguments[argmax]; cp++) {
5438 if (*cp != '\0') {
5439 /*
5440 * Beginning of first argument reached
5441 */
5442 break;
5443 }
5444 }
5445 if (cp == &arguments[argmax])
5446 return(0);
5447
5448 command_beg = cp;
5449 /*
5450 * Make sure that the command is '\0'-terminated. This protects
5451 * against malicious programs; under normal operation this never
5452 * ends up being a problem..
5453 */
5454 for (; cp < &arguments[argmax]; cp++) {
5455 if (*cp == '\0') {
5456 /*
5457 * End of first argument reached
5458 */
5459 break;
5460 }
5461 }
5462 if (cp == &arguments[argmax])
5463 return(0);
5464
5465 command_end = command = cp;
5466
5467 /*
5468 * Get the basename of command
5469 */
5470 for (command--; command >= command_beg; command--) {
5471 if (*command == '/') {
5472 command++;
5473 break;
5474 }
5475 }
5476 (void) strncpy(cbuf, (char *)command, csize);
5477 cbuf[csize-1] = '\0';
5478
5479 return(1);
5480 }