*/
/*
-cc -I. -DPRIVATE -D__APPLE_PRIVATE -O -o fs_usage fs_usage.c
+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
*/
-#define Default_DELAY 1 /* default delay interval */
-
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <aio.h>
#include <string.h>
#include <dirent.h>
+#include <libc.h>
+#include <termios.h>
+#include <errno.h>
+#include <err.h>
+#include <libutil.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/time.h>
-
-#include <libc.h>
-#include <termios.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/mman.h>
+#include <sys/sysctl.h>
+#include <sys/disk.h>
+#include <sys/file.h>
#ifndef KERNEL_PRIVATE
#define KERNEL_PRIVATE
#include <sys/kdebug.h>
#endif /*KERNEL_PRIVATE*/
-#include <sys/sysctl.h>
-#include <errno.h>
#import <mach/clock_types.h>
#import <mach/mach_time.h>
-#include <err.h>
-extern int errno;
+#define F_OPENFROM 56 /* SPI: open a file relative to fd (must be a dir) */
+#define F_UNLINKFROM 57 /* SPI: open a file relative to fd (must be a dir) */
+#define F_CHECK_OPENEVT 58 /* SPI: if a process is marked OPENEVT, or in O_EVTONLY on opens of this vnode */
+
+
+#ifndef RAW_VERSION1
+typedef struct {
+ int version_no;
+ int thread_count;
+ uint64_t TOD_secs;
+ uint32_t TOD_usecs;
+} RAW_header;
+
+#define RAW_VERSION0 0x55aa0000
+#define RAW_VERSION1 0x55aa0101
+#endif
+
#define MAXINDEX 2048
typedef struct LibraryRange {
- uint64_t b_address;
- uint64_t e_address;
+ uint64_t b_address;
+ uint64_t e_address;
} LibraryRange;
LibraryRange framework32;
LibraryRange framework64;
+#define TEXT_R 0
+#define DATA_R 1
+#define OBJC_R 2
+#define IMPORT_R 3
+#define UNICODE_R 4
+#define IMAGE_R 5
+#define LINKEDIT_R 6
+
+
+char *frameworkType[] = {
+ "<TEXT> ",
+ "<DATA> ",
+ "<OBJC> ",
+ "<IMPORT> ",
+ "<UNICODE> ",
+ "<IMAGE> ",
+ "<LINKEDIT>",
+};
+
+
typedef struct LibraryInfo {
- uint64_t b_address;
- uint64_t e_address;
- char *name;
+ uint64_t b_address;
+ uint64_t e_address;
+ int r_type;
+ char *name;
} LibraryInfo;
LibraryInfo frameworkInfo[MAXINDEX];
int numFrameworks = 0;
-char *lookup_name(uint64_t user_addr);
-
/*
- MAXCOLS controls when extra data kicks in.
- MAX_WIDE_MODE_COLS controls -w mode to get even wider data in path.
- If NUMPARMS changes to match the kernel, it will automatically
- get reflected in the -w mode output.
-*/
+ * MAXCOLS controls when extra data kicks in.
+ * MAX_WIDE_MODE_COLS controls -w mode to get even wider data in path.
+ * If NUMPARMS changes to match the kernel, it will automatically
+ * get reflected in the -w mode output.
+ */
#define NUMPARMS 23
-#define PATHLENGTH (NUMPARMS*sizeof(long))
+#define PATHLENGTH (NUMPARMS*sizeof(uintptr_t))
+
#define MAXCOLS 132
#define MAX_WIDE_MODE_COLS (PATHLENGTH + 80)
#define MAXWIDTH MAX_WIDE_MODE_COLS + 64
+#define MAX_PATHNAMES 3
+#define MAX_SCALL_PATHNAMES 2
+
+typedef struct th_info *th_info_t;
+
+struct lookup {
+ uintptr_t pathname[NUMPARMS + 1]; /* add room for null terminator */
+};
+
struct th_info {
- int my_index;
+ th_info_t next;
+ uintptr_t thread;
+ uintptr_t child_thread;
+
int in_filemgr;
- int thread;
+ int in_hfs_update;
int pid;
int type;
int arg1;
int arg6;
int arg7;
int arg8;
- int child_thread;
int waited;
double stime;
- long *pathptr;
- long pathname[NUMPARMS + 1]; /* add room for null terminator */
+ uint64_t vnodeid;
+ char *nameptr;
+ uintptr_t *pathptr;
+ int pn_scall_index;
+ int pn_work_index;
+ struct lookup lookups[MAX_PATHNAMES];
+};
+
+
+typedef struct threadmap * threadmap_t;
+
+struct threadmap {
+ threadmap_t tm_next;
+
+ uintptr_t tm_thread;
+ unsigned int tm_setsize; /* this is a bit count */
+ unsigned long *tm_setptr; /* file descripter bitmap */
+ char tm_command[MAXCOMLEN + 1];
+};
+
+
+typedef struct vnode_info * vnode_info_t;
+
+struct vnode_info {
+ vnode_info_t vn_next;
+ uint64_t vn_id;
+ uintptr_t vn_pathname[NUMPARMS + 1];
};
-#define MAX_THREADS 512
-struct th_info th_state[MAX_THREADS];
+typedef struct meta_info * meta_info_t;
+
+struct meta_info {
+ meta_info_t m_next;
+ uint64_t m_blkno;
+ char *m_nameptr;
+};
+
+#define HASH_SIZE 1024
+#define HASH_MASK (HASH_SIZE - 1)
+
+th_info_t th_info_hash[HASH_SIZE];
+th_info_t th_info_freelist;
+
+threadmap_t threadmap_hash[HASH_SIZE];
+threadmap_t threadmap_freelist;
+
+
+#define VN_HASH_SHIFT 3
+#define VN_HASH_SIZE 16384
+#define VN_HASH_MASK (VN_HASH_SIZE - 1)
+
+vnode_info_t vn_info_hash[VN_HASH_SIZE];
+meta_info_t m_info_hash[VN_HASH_SIZE];
-kd_threadmap *last_map = NULL;
-int last_thread = 0;
-int map_is_the_same = 0;
int filemgr_in_progress = 0;
-int execs_in_progress = 0;
-int cur_start = 0;
-int cur_max = 0;
int need_new_map = 1;
int bias_secs = 0;
long last_time;
int wideflag = 0;
int columns = 0;
-int select_pid_mode = 0; /* Flag set indicates that output is restricted
- to selected pids or commands */
int one_good_pid = 0; /* Used to fail gracefully when bad pids given */
+int select_pid_mode = 0; /* Flag set indicates that output is restricted
+ to selected pids or commands */
char *arguments = 0;
int argmax = 0;
*/
#define FILESYS_FILTER 0x01
#define NETWORK_FILTER 0x02
-#define CACHEHIT_FILTER 0x04
#define EXEC_FILTER 0x08
#define PATHNAME_FILTER 0x10
+#define DISKIO_FILTER 0x20
#define DEFAULT_DO_NOT_FILTER 0x00
-int filter_mode = CACHEHIT_FILTER;
+int filter_mode = DEFAULT_DO_NOT_FILTER;
+
+boolean_t show_cachehits = FALSE;
#define NFS_DEV -1
+#define CS_DEV -2
struct diskrec {
struct diskrec *next;
int blkno;
int iosize;
int io_errno;
- int issuing_thread;
- int completion_thread;
+ int is_meta;
+ uint64_t vnodeid;
+ uintptr_t issuing_thread;
+ uintptr_t completion_thread;
char issuing_command[MAXCOMLEN];
double issued_time;
double completed_time;
+ uint32_t bc_info;
};
struct diskrec *disk_list = NULL;
struct diskio *busy_diskios = NULL;
-
struct diskio *insert_diskio();
+struct diskio *find_diskio(int);
struct diskio *complete_diskio();
void free_diskio();
void print_diskio();
-void format_print(struct th_info *, char *, int, int, int, int, int, int, int, double, double, int, char *, struct diskio *);
-void exit_syscall(char *, int, int, int, int, int, int, int, double);
-char *find_disk_name();
+
+int check_filter_mode(struct th_info *, int, int, int, char *);
+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 *);
+void enter_event_now(uintptr_t, int, kd_buf *, char *, double);
+void enter_event(uintptr_t, int, kd_buf *, char *, double);
+void exit_event(char *, uintptr_t, int, uintptr_t, uintptr_t, uintptr_t, uintptr_t, int, double);
+void extend_syscall(uintptr_t, int, kd_buf *);
+
+char *generate_cs_disk_name(int, char *s);
+char *find_disk_name(int);
void cache_disk_names();
-int ReadSharedCacheMap(const char *, LibraryRange *);
+void recache_disk_names();
+
+void lookup_name(uint64_t user_addr, char **type, char **name);
+int ReadSharedCacheMap(const char *, LibraryRange *, char *);
void SortFrameworkAddresses();
-void mark_thread_waited(int);
-int check_filter_mode(struct th_info *, int, int, int, char *);
-void fs_usage_fd_set(unsigned int, unsigned int);
-int fs_usage_fd_isset(unsigned int, unsigned int);
-void fs_usage_fd_clear(unsigned int, unsigned int);
+
+void fs_usage_fd_set(uintptr_t, unsigned int);
+int fs_usage_fd_isset(uintptr_t, unsigned int);
+void fs_usage_fd_clear(uintptr_t, unsigned int);
+
void init_arguments_buffer();
int get_real_command_name(int, char *, int);
-void create_map_entry(int, int, char *);
-void enter_syscall();
-void extend_syscall();
-void kill_thread_map();
+void delete_all_events();
+void delete_event(th_info_t);
+th_info_t add_event(uintptr_t, int);
+th_info_t find_event(uintptr_t, int);
+void mark_thread_waited(uintptr_t);
+
+void read_command_map();
+void delete_all_map_entries();
+void create_map_entry(uintptr_t, int, char *);
+void delete_map_entry(uintptr_t);
+threadmap_t find_map_entry(uintptr_t);
+
+char *add_vnode_name(uint64_t, char *);
+char *find_vnode_name(uint64_t);
+char *find_meta_name(uint64_t);
+void add_meta_name(uint64_t, char *);
+
+void getdivisor();
+void argtopid();
+void set_remove();
+void set_pidcheck();
+void set_pidexclude();
+int quit();
+
#define CLASS_MASK 0xff000000
#define CSC_MASK 0xffff0000
#define MACH_pageout 0x01300004
#define MACH_sched 0x01400000
#define MACH_stkhandoff 0x01400008
+#define MACH_idle 0x01400024
#define VFS_LOOKUP 0x03010090
-#define BSC_exit 0x040C0004
+#define VFS_ALIAS_VP 0x03010094
+
+#define BSC_thread_terminate 0x040c05a4
+
+#define HFS_update 0x3018000
+#define HFS_modify_block_end 0x3018004
+
+#define Throttled 0x3010184
+#define SPEC_ioctl 0x3060000
+#define SPEC_unmap_info 0x3060004
+#define proc_exit 0x4010004
+
+#define BC_IO_HIT 0x03070010
+#define BC_IO_HIT_STALLED 0x03070020
+#define BC_IO_MISS 0x03070040
+#define BC_IO_MISS_CUT_THROUGH 0x03070080
+#define BC_PLAYBACK_IO 0x03070100
+#define BC_STR(s) ( \
+ (s == BC_IO_HIT) ? "HIT" : \
+ (s == BC_IO_HIT_STALLED) ? "STALL" : \
+ (s == BC_IO_MISS) ? "MISS" : \
+ (s == BC_IO_MISS_CUT_THROUGH) ? "CUT" : \
+ (s == BC_PLAYBACK_IO) ? "PLBK" : \
+ (s == 0x0) ? "NONE" : "UNKN" )
+
+#ifndef DKIO_NOCACHE
+#define DKIO_NOCACHE 0x80
+#endif
-#define P_DISKIO 0x03020000
-#define P_DISKIO_DONE 0x03020004
+#define P_DISKIO_READ (DKIO_READ << 2)
+#define P_DISKIO_ASYNC (DKIO_ASYNC << 2)
+#define P_DISKIO_META (DKIO_META << 2)
+#define P_DISKIO_PAGING (DKIO_PAGING << 2)
+#define P_DISKIO_THROTTLE (DKIO_THROTTLE << 2)
+#define P_DISKIO_PASSIVE (DKIO_PASSIVE << 2)
+#define P_DISKIO_NOCACHE (DKIO_NOCACHE << 2)
+#define P_DISKIO_TIER_MASK (DKIO_TIER_MASK << 2)
+#define P_DISKIO_TIER_SHIFT (DKIO_TIER_SHIFT + 2)
+
+#define P_DISKIO (FSDBG_CODE(DBG_DKRW, 0))
+#define P_DISKIO_DONE (P_DISKIO | (DKIO_DONE << 2))
+#define P_DISKIO_TYPE (P_DISKIO | P_DISKIO_READ | P_DISKIO_META | P_DISKIO_PAGING)
#define P_DISKIO_MASK (CSC_MASK | 0x4)
-#define P_WrData 0x03020000
-#define P_RdData 0x03020008
-#define P_WrMeta 0x03020020
-#define P_RdMeta 0x03020028
-#define P_PgOut 0x03020040
-#define P_PgIn 0x03020048
-#define P_WrDataAsync 0x03020010
-#define P_RdDataAsync 0x03020018
-#define P_WrMetaAsync 0x03020030
-#define P_RdMetaAsync 0x03020038
-#define P_PgOutAsync 0x03020050
-#define P_PgInAsync 0x03020058
-
-#define P_WrDataDone 0x03020004
-#define P_RdDataDone 0x0302000C
-#define P_WrMetaDone 0x03020024
-#define P_RdMetaDone 0x0302002C
-#define P_PgOutDone 0x03020044
-#define P_PgInDone 0x0302004C
-#define P_WrDataAsyncDone 0x03020014
-#define P_RdDataAsyncDone 0x0302001C
-#define P_WrMetaAsyncDone 0x03020034
-#define P_RdMetaAsyncDone 0x0302003C
-#define P_PgOutAsyncDone 0x03020054
-#define P_PgInAsyncDone 0x0302005C
-
+#define P_WrData (P_DISKIO)
+#define P_RdData (P_DISKIO | P_DISKIO_READ)
+#define P_WrMeta (P_DISKIO | P_DISKIO_META)
+#define P_RdMeta (P_DISKIO | P_DISKIO_META | P_DISKIO_READ)
+#define P_PgOut (P_DISKIO | P_DISKIO_PAGING)
+#define P_PgIn (P_DISKIO | P_DISKIO_PAGING | P_DISKIO_READ)
+
+#define P_CS_Class 0x0a000000 // DBG_CORESTORAGE
+#define P_CS_Type_Mask 0xfffffff0
+#define P_CS_IO_Done 0x00000004
+
+#define P_CS_ReadChunk 0x0a000200 // chopped up request
+#define P_CS_WriteChunk 0x0a000210
+#define P_CS_MetaRead 0x0a000300 // meta data
+#define P_CS_MetaWrite 0x0a000310
+#define P_CS_TransformRead 0x0a000500 // background transform
+#define P_CS_TransformWrite 0x0a000510
+#define P_CS_MigrationRead 0x0a000600 // composite disk block migration
+#define P_CS_MigrationWrite 0x0a000610
+#define P_CS_SYNC_DISK 0x0a010000
#define MSC_map_fd 0x010c00ac
#define BSC_listen 0x040C01A8
#define BSC_sendto 0x040C0214
#define BSC_socketpair 0x040C021C
+#define BSC_recvmsg_nocancel 0x040c0644
+#define BSC_sendmsg_nocancel 0x040c0648
+#define BSC_recvfrom_nocancel 0x040c064c
+#define BSC_accept_nocancel 0x040c0650
+#define BSC_connect_nocancel 0x040c0664
+#define BSC_sendto_nocancel 0x040c0674
+#define BSC_exit 0x040C0004
#define BSC_read 0x040C000C
#define BSC_write 0x040C0010
#define BSC_open 0x040C0014
#define BSC_unlink 0x040C0028
#define BSC_chdir 0x040c0030
#define BSC_fchdir 0x040c0034
-#define BSC_mknod 0x040C0038
-#define BSC_chmod 0x040C003C
-#define BSC_chown 0x040C0040
-#define BSC_access 0x040C0084
-#define BSC_chflags 0x040C0088
+#define BSC_mknod 0x040C0038
+#define BSC_chmod 0x040C003C
+#define BSC_chown 0x040C0040
+#define BSC_getfsstat 0x040C0048
+#define BSC_access 0x040C0084
+#define BSC_chflags 0x040C0088
#define BSC_fchflags 0x040C008C
#define BSC_sync 0x040C0090
#define BSC_dup 0x040C00A4
#define BSC_symlink 0x040C00E4
#define BSC_readlink 0x040C00E8
#define BSC_execve 0x040C00EC
+#define BSC_umask 0x040C00F0
#define BSC_chroot 0x040C00F4
#define BSC_msync 0x040C0104
#define BSC_dup2 0x040C0168
#define BSC_fchown 0x040C01EC
#define BSC_fchmod 0x040C01F0
#define BSC_rename 0x040C0200
-#define BSC_mkfifo 0x040c0210
+#define BSC_flock 0x040C020C
+#define BSC_mkfifo 0x040C0210
#define BSC_mkdir 0x040C0220
#define BSC_rmdir 0x040C0224
#define BSC_utimes 0x040C0228
#define BSC_pread 0x040C0264
#define BSC_pwrite 0x040C0268
#define BSC_statfs 0x040C0274
-#define BSC_fstatfs 0x040C0278
+#define BSC_fstatfs 0x040C0278
+#define BSC_unmount 0x040C027C
+#define BSC_mount 0x040C029C
+#define BSC_fdatasync 0x040C02EC
#define BSC_stat 0x040C02F0
#define BSC_fstat 0x040C02F4
#define BSC_lstat 0x040C02F8
#define BSC_truncate 0x040C0320
#define BSC_ftruncate 0x040C0324
#define BSC_undelete 0x040C0334
-#define BSC_statv 0x040C0364
-#define BSC_lstatv 0x040C0368
-#define BSC_fstatv 0x040C036C
-#define BSC_mkcomplex 0x040C0360
+#define BSC_open_dprotected_np 0x040C0360
#define BSC_getattrlist 0x040C0370
#define BSC_setattrlist 0x040C0374
#define BSC_getdirentriesattr 0x040C0378
#define BSC_searchfs 0x040C0384
#define BSC_delete 0x040C0388
#define BSC_copyfile 0x040C038C
+#define BSC_fgetattrlist 0x040C0390
+#define BSC_fsetattrlist 0x040C0394
#define BSC_getxattr 0x040C03A8
#define BSC_fgetxattr 0x040C03AC
#define BSC_setxattr 0x040C03B0
#define BSC_listxattr 0x040C03C0
#define BSC_flistxattr 0x040C03C4
#define BSC_fsctl 0x040C03C8
+#define BSC_posix_spawn 0x040C03D0
+#define BSC_ffsctl 0x040C03D4
#define BSC_open_extended 0x040C0454
+#define BSC_umask_extended 0x040C0458
#define BSC_stat_extended 0x040C045C
#define BSC_lstat_extended 0x040C0460
#define BSC_fstat_extended 0x040C0464
#define BSC_access_extended 0x040C0470
#define BSC_mkfifo_extended 0x040C048C
#define BSC_mkdir_extended 0x040C0490
-#define BSC_load_shared_file 0x040C04A0
#define BSC_aio_fsync 0x040C04E4
#define BSC_aio_return 0x040C04E8
#define BSC_aio_suspend 0x040C04EC
#define BSC_aio_read 0x040C04F8
#define BSC_aio_write 0x040C04FC
#define BSC_lio_listio 0x040C0500
+#define BSC_sendfile 0x040C0544
+#define BSC_stat64 0x040C0548
+#define BSC_fstat64 0x040C054C
+#define BSC_lstat64 0x040C0550
+#define BSC_stat64_extended 0x040C0554
+#define BSC_lstat64_extended 0x040C0558
+#define BSC_fstat64_extended 0x040C055C
+#define BSC_getdirentries64 0x040C0560
+#define BSC_statfs64 0x040C0564
+#define BSC_fstatfs64 0x040C0568
+#define BSC_getfsstat64 0x040C056C
+#define BSC_pthread_chdir 0x040C0570
+#define BSC_pthread_fchdir 0x040C0574
#define BSC_lchown 0x040C05B0
#define BSC_read_nocancel 0x040c0630
#define BSC_write_nocancel 0x040c0634
#define BSC_open_nocancel 0x040c0638
#define BSC_close_nocancel 0x040c063c
-#define BSC_recvmsg_nocancel 0x040c0644
-#define BSC_sendmsg_nocancel 0x040c0648
-#define BSC_recvfrom_nocancel 0x040c064c
-#define BSC_accept_nocancel 0x040c0650
#define BSC_msync_nocancel 0x040c0654
#define BSC_fcntl_nocancel 0x040c0658
#define BSC_select_nocancel 0x040c065c
#define BSC_fsync_nocancel 0x040c0660
-#define BSC_connect_nocancel 0x040c0664
#define BSC_readv_nocancel 0x040c066c
#define BSC_writev_nocancel 0x040c0670
-#define BSC_sendto_nocancel 0x040c0674
#define BSC_pread_nocancel 0x040c0678
#define BSC_pwrite_nocancel 0x040c067c
#define BSC_aio_suspend_nocancel 0x40c0694
+#define BSC_guarded_open_np 0x040c06e4
+#define BSC_guarded_close_np 0x040c06e8
+
+#define BSC_fsgetpath 0x040c06ac
#define BSC_msync_extended 0x040e0104
#define BSC_pread_extended 0x040e0264
#define FMT_FCHFLAGS 29
#define FMT_IOCTL 30
#define FMT_MMAP 31
+#define FMT_UMASK 32
+#define FMT_SENDFILE 33
+#define FMT_IOCTL_SYNC 34
+#define FMT_MOUNT 35
+#define FMT_UNMOUNT 36
+#define FMT_DISKIO_CS 37
+#define FMT_SYNC_DISK_CS 38
+#define FMT_IOCTL_UNMAP 39
+#define FMT_UNMAP_INFO 40
+#define FMT_HFS_update 41
+#define FMT_FLOCK 42
#define MAX_BSD_SYSCALL 512
BSC_revoke,
BSC_symlink,
BSC_readlink,
+ BSC_exit,
BSC_execve,
+ BSC_posix_spawn,
+ BSC_umask,
BSC_chroot,
BSC_dup2,
BSC_fsync,
BSC_pwrite_nocancel,
BSC_statfs,
BSC_fstatfs,
+ BSC_fdatasync,
BSC_stat,
BSC_fstat,
BSC_lstat,
+ BSC_mount,
+ BSC_unmount,
BSC_pathconf,
BSC_fpathconf,
BSC_getdirentries,
BSC_lseek,
BSC_truncate,
BSC_ftruncate,
+ BSC_flock,
BSC_undelete,
- BSC_statv,
- BSC_lstatv,
- BSC_fstatv,
- BSC_mkcomplex,
+ BSC_open_dprotected_np,
BSC_getattrlist,
BSC_setattrlist,
+ BSC_fgetattrlist,
+ BSC_fsetattrlist,
BSC_getdirentriesattr,
BSC_exchangedata,
BSC_checkuseraccess,
BSC_listxattr,
BSC_flistxattr,
BSC_fsctl,
+ BSC_ffsctl,
BSC_open_extended,
+ BSC_umask_extended,
BSC_stat_extended,
BSC_lstat_extended,
BSC_fstat_extended,
BSC_access_extended,
BSC_mkfifo_extended,
BSC_mkdir_extended,
- BSC_load_shared_file,
BSC_aio_fsync,
BSC_aio_return,
BSC_aio_suspend,
BSC_aio_write,
BSC_lio_listio,
BSC_lchown,
+ BSC_sendfile,
BSC_msync,
BSC_msync_nocancel,
BSC_fcntl,
BSC_fcntl_nocancel,
BSC_ioctl,
+ BSC_stat64,
+ BSC_fstat64,
+ BSC_lstat64,
+ BSC_stat64_extended,
+ BSC_lstat64_extended,
+ BSC_fstat64_extended,
+ BSC_getdirentries64,
+ BSC_statfs64,
+ BSC_fstatfs64,
+ BSC_pthread_chdir,
+ BSC_pthread_fchdir,
+ BSC_getfsstat,
+ BSC_getfsstat64,
+ BSC_guarded_open_np,
+ BSC_guarded_close_np,
+ BSC_fsgetpath,
0
};
struct kinfo_proc *kp_buffer = 0;
int kp_nentries = 0;
-#define SAMPLE_SIZE 100000
-
-int num_cpus;
-
#define EVENT_BASE 60000
int num_events = EVENT_BASE;
-#define DBG_ZERO_FILL_FAULT 1
-#define DBG_PAGEIN_FAULT 2
-#define DBG_COW_FAULT 3
-#define DBG_CACHE_HIT_FAULT 4
#define DBG_FUNC_ALL (DBG_FUNC_START | DBG_FUNC_END)
#define DBG_FUNC_MASK 0xfffffffc
kbufinfo_t bufinfo = {0, 0, 0, 0, 0};
-int total_threads = 0;
-kd_threadmap *mapptr = 0; /* pointer to list of threads */
/* defines for tracking file descriptor state */
#define FS_USAGE_FD_SETSIZE 256 /* Initial number of file descriptors per
#define FS_USAGE_NFDBITS (sizeof (unsigned long) * 8)
#define FS_USAGE_NFDBYTES(n) (((n) / FS_USAGE_NFDBITS) * sizeof (unsigned long))
-typedef struct {
- unsigned int fd_valid; /* set if this is a valid entry */
- unsigned int fd_thread;
- unsigned int fd_setsize; /* this is a bit count */
- unsigned long *fd_setptr; /* file descripter bitmap */
-} fd_threadmap;
-
-fd_threadmap *fdmapptr = 0; /* pointer to list of threads for fd tracking */
-
int trace_enabled = 0;
int set_remove_flag = 1;
+int BC_flag = 0;
+
+char *RAW_file = (char *)0;
+int RAW_flag = 0;
+int RAW_fd = 0;
+
+uint64_t sample_TOD_secs;
+uint32_t sample_TOD_usecs;
+
+double bias_now = 0.0;
+double start_time = 0.0;
+double end_time = 999999999999.9;
+
+
void set_numbufs();
+void set_filter();
void set_init();
void set_enable();
void sample_sc();
set_pidexclude(pids[i], 0);
}
set_remove();
+
exit(0);
}
+int
+quit(s)
+char *s;
+{
+ if (trace_enabled)
+ set_enable(0);
+
+ /*
+ * This flag is turned off when calling
+ * quit() due to a set_remove() failure.
+ */
+ if (set_remove_flag)
+ set_remove();
+
+ fprintf(stderr, "fs_usage: ");
+ if (s)
+ fprintf(stderr, "%s", s);
+
+ exit(1);
+}
+
+
void get_screenwidth()
{
struct winsize size;
get_screenwidth();
}
+
+void getdivisor()
+{
+ struct mach_timebase_info mti;
+
+ mach_timebase_info(&mti);
+
+ divisor = ((double)mti.denom / (double)mti.numer) * 1000;
+}
+
+
int
exit_usage(char *myname) {
- fprintf(stderr, "Usage: %s [-e] [-w] [-f mode] [pid | cmd [pid | cmd]....]\n", myname);
+ 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);
fprintf(stderr, " -e exclude the specified list of pids from the sample\n");
fprintf(stderr, " and exclude fs_usage by default\n");
fprintf(stderr, " -w force wider, detailed, output\n");
- fprintf(stderr, " -f Output is based on the mode provided\n");
- fprintf(stderr, " mode = \"network\" Show only network related output\n");
- fprintf(stderr, " mode = \"filesys\" Show only file system related output\n");
- fprintf(stderr, " mode = \"pathname\" Show only pathname related output\n");
- fprintf(stderr, " mode = \"exec\" Show only execs\n");
- fprintf(stderr, " mode = \"cachehit\" In addition, show cachehits\n");
+ fprintf(stderr, " -f output is based on the mode provided\n");
+ fprintf(stderr, " mode = \"network\" Show network-related events\n");
+ fprintf(stderr, " mode = \"filesys\" Show filesystem-related events\n");
+ fprintf(stderr, " mode = \"pathname\" Show only pathname-related events\n");
+ fprintf(stderr, " mode = \"exec\" Show only exec and spawn events\n");
+ fprintf(stderr, " mode = \"diskio\" Show only disk I/O events\n");
+ fprintf(stderr, " mode = \"cachehit\" In addition, show cache hits\n");
+ fprintf(stderr, " -b annotate disk I/O events with BootCache info (if available)\n");
+ fprintf(stderr, " -t specifies timeout in seconds (for use in automated tools)\n");
+ fprintf(stderr, " -R specifies a raw trace file to process\n");
+ fprintf(stderr, " -S if -R is specified, selects a start point in microseconds\n");
+ fprintf(stderr, " -E if -R is specified, selects an end point in microseconds\n");
fprintf(stderr, " pid selects process(s) to sample\n");
fprintf(stderr, " cmd selects process(s) matching command string to sample\n");
fprintf(stderr, "\n%s will handle a maximum list of %d pids.\n\n", myname, MAX_PIDS);
int type;
int code;
- for (i = 0; i < MAX_THREADS; i++)
- th_state[i].my_index = i;
for (i = 0; i < MAX_BSD_SYSCALL; i++) {
bsd_syscalls[i].sc_name = NULL;
continue;
}
switch (type) {
+
+ case BSC_sendfile:
+ bsd_syscalls[code].sc_name = "sendfile";
+ bsd_syscalls[code].sc_format = FMT_FD; /* this should be changed to FMT_SENDFILE */
+ break; /* once we add an extended info trace event */
case BSC_recvmsg:
case BSC_recvmsg_nocancel:
bsd_syscalls[code].sc_name = "stat";
break;
+ case BSC_stat64:
+ bsd_syscalls[code].sc_name = "stat64";
+ break;
+
case BSC_stat_extended:
bsd_syscalls[code].sc_name = "stat_extended";
break;
+ case BSC_stat64_extended:
+ bsd_syscalls[code].sc_name = "stat_extended64";
+ break;
+
+ case BSC_mount:
+ bsd_syscalls[code].sc_name = "mount";
+ bsd_syscalls[code].sc_format = FMT_MOUNT;
+ break;
+
+ case BSC_unmount:
+ bsd_syscalls[code].sc_name = "unmount";
+ bsd_syscalls[code].sc_format = FMT_UNMOUNT;
+ break;
+
+ case BSC_exit:
+ bsd_syscalls[code].sc_name = "exit";
+ break;
+
case BSC_execve:
bsd_syscalls[code].sc_name = "execve";
break;
- case BSC_load_shared_file:
- bsd_syscalls[code].sc_name = "load_sf";
+ case BSC_posix_spawn:
+ bsd_syscalls[code].sc_name = "posix_spawn";
break;
-
+
case BSC_open:
case BSC_open_nocancel:
bsd_syscalls[code].sc_name = "open";
bsd_syscalls[code].sc_format = FMT_OPEN;
break;
+ case BSC_guarded_open_np:
+ bsd_syscalls[code].sc_name = "guarded_open_np";
+ bsd_syscalls[code].sc_format = FMT_OPEN;
+ break;
+
+ case BSC_open_dprotected_np:
+ bsd_syscalls[code].sc_name = "open_dprotected";
+ bsd_syscalls[code].sc_format = FMT_OPEN;
+ break;
+
case BSC_dup:
bsd_syscalls[code].sc_name = "dup";
bsd_syscalls[code].sc_format = FMT_FD_2;
bsd_syscalls[code].sc_format = FMT_FD;
break;
+ case BSC_guarded_close_np:
+ bsd_syscalls[code].sc_name = "guarded_close_np";
+ bsd_syscalls[code].sc_format = FMT_FD;
+ break;
+
case BSC_read:
case BSC_read_nocancel:
bsd_syscalls[code].sc_name = "read";
bsd_syscalls[code].sc_format = FMT_FD;
break;
+ case BSC_fstat64:
+ bsd_syscalls[code].sc_name = "fstat64";
+ bsd_syscalls[code].sc_format = FMT_FD;
+ break;
+
case BSC_fstat_extended:
bsd_syscalls[code].sc_name = "fstat_extended";
bsd_syscalls[code].sc_format = FMT_FD;
break;
+ case BSC_fstat64_extended:
+ bsd_syscalls[code].sc_name = "fstat64_extended";
+ bsd_syscalls[code].sc_format = FMT_FD;
+ break;
+
case BSC_lstat:
bsd_syscalls[code].sc_name = "lstat";
break;
+ case BSC_lstat64:
+ bsd_syscalls[code].sc_name = "lstat64";
+ break;
+
case BSC_lstat_extended:
bsd_syscalls[code].sc_name = "lstat_extended";
break;
- case BSC_lstatv:
- bsd_syscalls[code].sc_name = "lstatv";
+ case BSC_lstat64_extended:
+ bsd_syscalls[code].sc_name = "lstat_extended64";
break;
case BSC_link:
bsd_syscalls[code].sc_name = "mknod";
break;
+ case BSC_umask:
+ bsd_syscalls[code].sc_name = "umask";
+ bsd_syscalls[code].sc_format = FMT_UMASK;
+ break;
+
+ case BSC_umask_extended:
+ bsd_syscalls[code].sc_name = "umask_extended";
+ bsd_syscalls[code].sc_format = FMT_UMASK;
+ break;
+
case BSC_chmod:
bsd_syscalls[code].sc_name = "chmod";
bsd_syscalls[code].sc_format = FMT_CHMOD;
bsd_syscalls[code].sc_name = "chdir";
break;
+ case BSC_pthread_chdir:
+ bsd_syscalls[code].sc_name = "pthread_chdir";
+ break;
+
case BSC_chroot:
bsd_syscalls[code].sc_name = "chroot";
break;
break;
case BSC_delete:
- bsd_syscalls[code].sc_name = "delete";
+ bsd_syscalls[code].sc_name = "delete-Carbon";
break;
case BSC_undelete:
bsd_syscalls[code].sc_name = "fsctl";
break;
+ case BSC_ffsctl:
+ bsd_syscalls[code].sc_name = "ffsctl";
+ bsd_syscalls[code].sc_format = FMT_FD;
+ break;
+
case BSC_chflags:
bsd_syscalls[code].sc_name = "chflags";
bsd_syscalls[code].sc_format = FMT_CHFLAGS;
bsd_syscalls[code].sc_format = FMT_FD;
break;
+ case BSC_pthread_fchdir:
+ bsd_syscalls[code].sc_name = "pthread_fchdir";
+ bsd_syscalls[code].sc_format = FMT_FD;
+ break;
+
case BSC_futimes:
bsd_syscalls[code].sc_name = "futimes";
bsd_syscalls[code].sc_format = FMT_FD;
bsd_syscalls[code].sc_format = FMT_FD;
break;
+ case BSC_fdatasync:
+ bsd_syscalls[code].sc_name = "fdatasync";
+ bsd_syscalls[code].sc_format = FMT_FD;
+ break;
+
case BSC_readv:
case BSC_readv_nocancel:
bsd_syscalls[code].sc_name = "readv";
bsd_syscalls[code].sc_name = "statfs";
break;
+ case BSC_statfs64:
+ bsd_syscalls[code].sc_name = "statfs64";
+ break;
+
+ case BSC_getfsstat:
+ bsd_syscalls[code].sc_name = "getfsstat";
+ break;
+
+ case BSC_getfsstat64:
+ bsd_syscalls[code].sc_name = "getfsstat64";
+ break;
+
case BSC_fstatfs:
bsd_syscalls[code].sc_name = "fstatfs";
bsd_syscalls[code].sc_format = FMT_FD;
break;
+ case BSC_fstatfs64:
+ bsd_syscalls[code].sc_name = "fstatfs64";
+ bsd_syscalls[code].sc_format = FMT_FD;
+ break;
+
case BSC_pathconf:
bsd_syscalls[code].sc_name = "pathconf";
break;
bsd_syscalls[code].sc_format = FMT_FD_IO;
break;
+ case BSC_getdirentries64:
+ bsd_syscalls[code].sc_name = "getdirentries64";
+ bsd_syscalls[code].sc_format = FMT_FD_IO;
+ break;
+
case BSC_lseek:
bsd_syscalls[code].sc_name = "lseek";
bsd_syscalls[code].sc_format = FMT_LSEEK;
bsd_syscalls[code].sc_format = FMT_FTRUNC;
break;
- case BSC_statv:
- bsd_syscalls[code].sc_name = "statv";
- break;
-
- case BSC_fstatv:
- bsd_syscalls[code].sc_name = "fstatv";
- bsd_syscalls[code].sc_format = FMT_FD;
- break;
-
- case BSC_mkcomplex:
- bsd_syscalls[code].sc_name = "mkcomplex";
+ case BSC_flock:
+ bsd_syscalls[code].sc_name = "flock";
+ bsd_syscalls[code].sc_format = FMT_FLOCK;
break;
case BSC_getattrlist:
bsd_syscalls[code].sc_name = "setattrlist";
break;
+ case BSC_fgetattrlist:
+ bsd_syscalls[code].sc_name = "fgetattrlist";
+ bsd_syscalls[code].sc_format = FMT_FD;
+ break;
+
+ case BSC_fsetattrlist:
+ bsd_syscalls[code].sc_name = "fsetattrlist";
+ bsd_syscalls[code].sc_format = FMT_FD;
+ break;
+
case BSC_getdirentriesattr:
bsd_syscalls[code].sc_name = "getdirentriesattr";
bsd_syscalls[code].sc_format = FMT_FD;
bsd_syscalls[code].sc_name = "ioctl";
bsd_syscalls[code].sc_format = FMT_IOCTL;
break;
+
+ case BSC_fsgetpath:
+ bsd_syscalls[code].sc_name = "fsgetpath";
+ break;
}
}
char *myname = "fs_usage";
int i;
char ch;
- struct sigaction osa;
- void getdivisor();
- void argtopid();
- void set_remove();
- void set_pidcheck();
- void set_pidexclude();
- int quit();
- if ( geteuid() != 0 ) {
- fprintf(stderr, "'fs_usage' must be run as root...\n");
- exit(1);
- }
+ time_t stop_at_time = 0;
+
+ if (0 != reexec_to_match_kernel()) {
+ fprintf(stderr, "Could not re-execute: %d\n", errno);
+ exit(1);
+ }
get_screenwidth();
- /* get our name */
+ /*
+ * get our name
+ */
if (argc > 0) {
- if ((myname = rindex(argv[0], '/')) == 0) {
+ if ((myname = rindex(argv[0], '/')) == 0)
myname = argv[0];
- }
- else {
+ else
myname++;
- }
}
- while ((ch = getopt(argc, argv, "ewf:")) != EOF) {
+ while ((ch = getopt(argc, argv, "bewf:R:S:E:t:")) != EOF) {
+
switch(ch) {
+
case 'e':
exclude_pids = 1;
exclude_default_pids = 0;
break;
+
case 'w':
wideflag = 1;
if ((uint)columns < MAX_WIDE_MODE_COLS)
- columns = MAX_WIDE_MODE_COLS;
+ columns = MAX_WIDE_MODE_COLS;
break;
+
case 'f':
if (!strcmp(optarg, "network"))
- filter_mode |= NETWORK_FILTER;
+ filter_mode |= NETWORK_FILTER;
else if (!strcmp(optarg, "filesys"))
- filter_mode |= FILESYS_FILTER;
+ filter_mode |= FILESYS_FILTER;
else if (!strcmp(optarg, "cachehit"))
- filter_mode &= ~CACHEHIT_FILTER; /* turns on CACHE_HIT */
+ show_cachehits = TRUE;
else if (!strcmp(optarg, "exec"))
- filter_mode |= EXEC_FILTER;
+ filter_mode |= EXEC_FILTER;
else if (!strcmp(optarg, "pathname"))
- filter_mode |= PATHNAME_FILTER;
+ filter_mode |= PATHNAME_FILTER;
+ else if (!strcmp(optarg, "diskio"))
+ filter_mode |= DISKIO_FILTER;
+ break;
+
+ case 'b':
+ BC_flag = 1;
+ break;
+
+ case 't':
+ stop_at_time = time(NULL) + strtoul(optarg, NULL, 10);
+ break;
+
+ case 'R':
+ RAW_flag = 1;
+ RAW_file = optarg;
break;
+ case 'S':
+ start_time = atof(optarg);
+ break;
+
+ case 'E':
+ end_time = atof(optarg);
+ break;
+
default:
exit_usage(myname);
}
- }
-
+ }
+ if (!RAW_flag) {
+ if ( geteuid() != 0 ) {
+ fprintf(stderr, "'fs_usage' must be run as root...\n");
+ exit(1);
+ }
+ }
argc -= optind;
argv += optind;
* case below where exclude_pids is later set and the fs_usage PID
* needs to make it into pids[]
*/
- if (exclude_pids || (!exclude_pids && argc == 0))
- {
- if (num_of_pids < (MAX_PIDS - 1))
- pids[num_of_pids++] = getpid();
- }
+ if (exclude_pids || (!exclude_pids && argc == 0)) {
+ if (num_of_pids < (MAX_PIDS - 1))
+ pids[num_of_pids++] = getpid();
+ }
- /* If we process any list of pids/cmds, then turn off the defaults */
+ /*
+ * If we process any list of pids/cmds, then turn off the defaults
+ */
if (argc > 0)
- exclude_default_pids = 0;
+ exclude_default_pids = 0;
while (argc > 0 && num_of_pids < (MAX_PIDS - 1)) {
- select_pid_mode++;
- argtopid(argv[0]);
- argc--;
- argv++;
+ select_pid_mode++;
+ argtopid(argv[0]);
+ argc--;
+ argv++;
+ }
+ /*
+ * Exclude a set of default pids
+ */
+ if (exclude_default_pids) {
+ argtopid("Terminal");
+ argtopid("telnetd");
+ argtopid("telnet");
+ argtopid("sshd");
+ argtopid("rlogind");
+ argtopid("tcsh");
+ argtopid("csh");
+ argtopid("sh");
+ exclude_pids = 1;
}
-
- /* Exclude a set of default pids */
- if (exclude_default_pids)
- {
- argtopid("Terminal");
- argtopid("telnetd");
- argtopid("telnet");
- argtopid("sshd");
- argtopid("rlogind");
- argtopid("tcsh");
- argtopid("csh");
- argtopid("sh");
- exclude_pids = 1;
- }
-
#if 0
- for (i = 0; i < num_of_pids; i++)
- {
- if (exclude_pids)
- fprintf(stderr, "exclude pid %d\n", pids[i]);
- else
- fprintf(stderr, "pid %d\n", pids[i]);
- }
+ for (i = 0; i < num_of_pids; i++) {
+ if (exclude_pids)
+ fprintf(stderr, "exclude pid %d\n", pids[i]);
+ else
+ fprintf(stderr, "pid %d\n", pids[i]);
+ }
#endif
+ if (!RAW_flag) {
+ struct sigaction osa;
+ int num_cpus;
+ size_t len;
- /* set up signal handlers */
- signal(SIGINT, leave);
- signal(SIGQUIT, leave);
+ /* set up signal handlers */
+ signal(SIGINT, leave);
+ signal(SIGQUIT, leave);
- sigaction(SIGHUP, (struct sigaction *)NULL, &osa);
+ sigaction(SIGHUP, (struct sigaction *)NULL, &osa);
- if (osa.sa_handler == SIG_DFL)
- signal(SIGHUP, leave);
- signal(SIGTERM, leave);
- signal(SIGWINCH, sigwinch);
+ if (osa.sa_handler == SIG_DFL)
+ signal(SIGHUP, leave);
+ signal(SIGTERM, leave);
+ /*
+ * grab the number of cpus
+ */
+ mib[0] = CTL_HW;
+ mib[1] = HW_NCPU;
+ mib[2] = 0;
+ len = sizeof(num_cpus);
- /* grab the number of cpus */
- size_t len;
- mib[0] = CTL_HW;
- mib[1] = HW_NCPU;
- mib[2] = 0;
- len = sizeof(num_cpus);
- sysctl(mib, 2, &num_cpus, &len, NULL, 0);
- num_events = EVENT_BASE * num_cpus;
+ sysctl(mib, 2, &num_cpus, &len, NULL, 0);
+ num_events = EVENT_BASE * num_cpus;
+ }
+ signal(SIGWINCH, sigwinch);
if ((my_buffer = malloc(num_events * sizeof(kd_buf))) == (char *)0)
- quit("can't allocate memory for tracing info\n");
+ quit("can't allocate memory for tracing info\n");
- if (ReadSharedCacheMap("/var/db/dyld/dyld_shared_cache_i386.map", &framework32))
- ReadSharedCacheMap("/var/db/dyld/dyld_shared_cache_x86_64.map", &framework64);
- else {
- ReadSharedCacheMap("/var/db/dyld/dyld_shared_cache_ppc.map", &framework32);
- ReadSharedCacheMap("/var/db/dyld/dyld_shared_cache_ppc64.map", &framework64);
+ if (ReadSharedCacheMap("/var/db/dyld/dyld_shared_cache_i386.map", &framework32, "/var/db/dyld/dyld_shared_cache_i386")) {
+ ReadSharedCacheMap("/var/db/dyld/dyld_shared_cache_x86_64.map", &framework64, "/var/db/dyld/dyld_shared_cache_x86_64");
+ } else {
+ ReadSharedCacheMap("/var/db/dyld/dyld_shared_cache_ppc.map", &framework32, "/var/db/dyld/dyld_shared_cache_ppc");
+ ReadSharedCacheMap("/var/db/dyld/dyld_shared_cache_ppc64.map", &framework64, "/var/db/dyld/dyld_shared_cache_ppc64");
}
SortFrameworkAddresses();
cache_disk_names();
- set_remove();
- set_numbufs(num_events);
- set_init();
+ if (!RAW_flag) {
- if (exclude_pids == 0) {
- for (i = 0; i < num_of_pids; i++)
- set_pidcheck(pids[i], 1);
- } else {
- for (i = 0; i < num_of_pids; i++)
- set_pidexclude(pids[i], 1);
- }
+ set_remove();
+ set_numbufs(num_events);
+ set_init();
- if (select_pid_mode && !one_good_pid)
- {
- /*
- An attempt to restrict output to a given
- pid or command has failed. Exit gracefully
- */
- set_remove();
- exit_usage(myname);
- }
-
- set_enable(1);
+ if (exclude_pids == 0) {
+ for (i = 0; i < num_of_pids; i++)
+ set_pidcheck(pids[i], 1);
+ } else {
+ for (i = 0; i < num_of_pids; i++)
+ set_pidexclude(pids[i], 1);
+ }
+ if (select_pid_mode && !one_good_pid) {
+ /*
+ * An attempt to restrict output to a given
+ * pid or command has failed. Exit gracefully
+ */
+ set_remove();
+ exit_usage(myname);
+ }
+
+ set_filter();
+
+ set_enable(1);
+
+ init_arguments_buffer();
+ }
getdivisor();
- init_arguments_buffer();
init_tables();
- /* main loop */
-
- while (1) {
- usleep(1000 * usleep_ms);
+ /*
+ * main loop
+ */
+ while (stop_at_time == 0 || last_time < stop_at_time) {
+ if (!RAW_flag)
+ usleep(1000 * usleep_ms);
sample_sc();
}
}
+
void
find_proc_names()
{
size_t bufSize = 0;
- struct kinfo_proc *kp;
- int quit();
+ struct kinfo_proc *kp;
mib[0] = CTL_KERN;
mib[1] = KERN_PROC;
if (sysctl(mib, 4, NULL, &bufSize, NULL, 0) < 0)
quit("trace facility failure, KERN_PROC_ALL\n");
- if((kp = (struct kinfo_proc *)malloc(bufSize)) == (struct kinfo_proc *)0)
- quit("can't allocate memory for proc buffer\n");
+ if ((kp = (struct kinfo_proc *)malloc(bufSize)) == (struct kinfo_proc *)0)
+ quit("can't allocate memory for proc buffer\n");
if (sysctl(mib, 4, kp, &bufSize, NULL, 0) < 0)
quit("trace facility failure, KERN_PROC_ALL\n");
}
-void destroy_thread(struct th_info *ti) {
-
- ti->child_thread = 0;
- ti->thread = 0;
- ti->pid = 0;
-
- if (ti->my_index < cur_start)
- cur_start = ti->my_index;
-
- if (ti->my_index == cur_max) {
- while (ti >= &th_state[0]) {
- if (ti->thread)
- break;
- ti--;
- }
- cur_max = ti->my_index;
- }
-}
-
-
-struct th_info *find_empty(void) {
- struct th_info *ti;
-
- for (ti = &th_state[cur_start]; ti < &th_state[MAX_THREADS]; ti++, cur_start++) {
- if (ti->thread == 0) {
- if (cur_start > cur_max)
- cur_max = cur_start;
- cur_start++;
-
- return (ti);
- }
- }
- return ((struct th_info *)0);
-
-}
-
-
-struct th_info *find_thread(int thread, int type) {
- struct th_info *ti;
-
- for (ti = &th_state[0]; ti <= &th_state[cur_max]; ti++) {
- if (ti->thread == thread) {
- if (type == ti->type)
- return(ti);
- if (ti->in_filemgr) {
- if (type == -1)
- return(ti);
- continue;
- }
- if (type == 0)
- return(ti);
- }
- }
- return ((struct th_info *)0);
-}
-
-
-void
-mark_thread_waited(int thread) {
- struct th_info *ti;
-
- for (ti = th_state; ti <= &th_state[cur_max]; ti++) {
- if (ti->thread == thread) {
- ti->waited = 1;
- }
- }
-}
-
-
void
set_enable(int val)
{
mib[3] = val;
mib[4] = 0;
mib[5] = 0; /* no flags */
+
if (sysctl(mib, 4, NULL, &needed, NULL, 0) < 0)
quit("trace facility failure, KERN_KDENABLE\n");
if (val)
- trace_enabled = 1;
+ trace_enabled = 1;
else
- trace_enabled = 0;
+ trace_enabled = 0;
}
void
mib[3] = nbufs;
mib[4] = 0;
mib[5] = 0; /* no flags */
+
if (sysctl(mib, 4, NULL, &needed, NULL, 0) < 0)
quit("trace facility failure, KERN_KDSETBUF\n");
mib[3] = 0;
mib[4] = 0;
mib[5] = 0; /* no flags */
+
if (sysctl(mib, 3, NULL, &needed, NULL, 0) < 0)
quit("trace facility failure, KERN_KDSETUP\n");
}
+#define ENCODE_CSC_LOW(class, subclass) \
+ ( (uint16_t) ( ((class) & 0xff) << 8 ) | ((subclass) & 0xff) )
+
+void
+set_filter(void)
+{
+ uint8_t type_filter_bitmap[KDBG_TYPEFILTER_BITMAP_SIZE];
+ bzero(type_filter_bitmap, sizeof(type_filter_bitmap));
+
+ setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_TRACE,DBG_TRACE_DATA));
+ setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_TRACE,DBG_TRACE_STRING));
+
+ setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_MACH,DBG_MACH_EXCP_SC)); //0x010c
+ setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_MACH,DBG_MACH_VM)); //0x0130
+ setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_MACH,DBG_MACH_SCHED)); //0x0140
+
+ setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_FSYSTEM,DBG_FSRW)); //0x0301
+ setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_FSYSTEM,DBG_DKRW)); //0x0302
+ setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_FSYSTEM,DBG_IOCTL)); //0x0306
+ setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_FSYSTEM,DBG_BOOTCACHE)); //0x0307
+
+ setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_BSD,DBG_BSD_EXCP_SC)); //0x040c
+ setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_BSD,DBG_BSD_PROC)); //0x0401
+ setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_BSD,DBG_BSD_SC_EXTENDED_INFO)); //0x040e
+ setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_BSD,DBG_BSD_SC_EXTENDED_INFO2)); //0x040f
+
+ setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_CORESTORAGE,DBG_CS_IO)); //0x0a00
+ setbit(type_filter_bitmap, ENCODE_CSC_LOW(DBG_CORESTORAGE, 1)); //0x0a01 for P_SCCS_SYNC_DIS
+
+ setbit(type_filter_bitmap, ENCODE_CSC_LOW(FILEMGR_CLASS, 0)); //Carbon File Manager
+ setbit(type_filter_bitmap, ENCODE_CSC_LOW(FILEMGR_CLASS, 1)); //Carbon File Manager
+
+ errno = 0;
+ int mib[] = { CTL_KERN, KERN_KDEBUG, KERN_KDSET_TYPEFILTER };
+ size_t needed = KDBG_TYPEFILTER_BITMAP_SIZE;
+ if(sysctl(mib, 3, type_filter_bitmap, &needed, NULL, 0)) {
+ quit("trace facility failure, KERN_KDSET_TYPEFILTER\n");
+ }
+}
+
void
set_pidcheck(int pid, int on_off)
{
if (sysctl(mib, 3, &kr, &needed, NULL, 0) < 0) {
if (on_off == 1)
fprintf(stderr, "pid %d does not exist\n", pid);
- }
- else {
- one_good_pid++;
- }
+ } else
+ one_good_pid++;
}
/*
- on_off == 0 turns off pid exclusion
- on_off == 1 turns on pid exclusion
-*/
+ * on_off == 0 turns off pid exclusion
+ * on_off == 1 turns on pid exclusion
+ */
void
set_pidexclude(int pid, int on_off)
{
mib[3] = 0;
mib[4] = 0;
mib[5] = 0; /* no flags */
- if (sysctl(mib, 3, NULL, &needed, NULL, 0) < 0)
- {
- set_remove_flag = 0;
-
- if (errno == EBUSY)
- quit("the trace facility is currently in use...\n fs_usage, sc_usage, and latency use this feature.\n\n");
- else
- quit("trace facility failure, KERN_KDREMOVE\n");
- }
+
+ if (sysctl(mib, 3, NULL, &needed, NULL, 0) < 0) {
+ set_remove_flag = 0;
+
+ if (errno == EBUSY)
+ quit("the trace facility is currently in use...\n fs_usage, sc_usage, and latency use this feature.\n\n");
+ else
+ quit("trace facility failure, KERN_KDREMOVE\n");
+ }
}
void
kr.value1 = 0;
kr.value2 = -1;
needed = sizeof(kd_regtype);
+
mib[0] = CTL_KERN;
mib[1] = KERN_KDEBUG;
mib[2] = KERN_KDSETREG;
quit("trace facility failure, KERN_KDSETUP\n");
}
+
void
sample_sc()
{
kd_buf *kd;
int i, count;
size_t needed;
- void read_command_map();
- void create_map_entry();
+ uint32_t my_buffer_size = 0;
- /* Get kernel buffer information */
- get_bufinfo(&bufinfo);
+ if (!RAW_flag)
+ get_bufinfo(&bufinfo);
+ else
+ my_buffer_size = num_events * sizeof(kd_buf);
if (need_new_map) {
read_command_map();
need_new_map = 0;
}
- needed = bufinfo.nkdbufs * sizeof(kd_buf);
- mib[0] = CTL_KERN;
- mib[1] = KERN_KDEBUG;
- mib[2] = KERN_KDREADTR;
- mib[3] = 0;
- mib[4] = 0;
- mib[5] = 0; /* no flags */
-
- if (sysctl(mib, 3, my_buffer, &needed, NULL, 0) < 0)
- quit("trace facility failure, KERN_KDREADTR\n");
- count = needed;
-
- if (count > (SAMPLE_SIZE / 8)) {
- if (usleep_ms > USLEEP_BEHIND)
- usleep_ms = USLEEP_BEHIND;
- else if (usleep_ms > USLEEP_MIN)
- usleep_ms /= 2;
+ if (!RAW_flag) {
+ needed = bufinfo.nkdbufs * sizeof(kd_buf);
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_KDEBUG;
+ mib[2] = KERN_KDREADTR;
+ mib[3] = 0;
+ mib[4] = 0;
+ mib[5] = 0; /* no flags */
+
+ if (sysctl(mib, 3, my_buffer, &needed, NULL, 0) < 0)
+ quit("trace facility failure, KERN_KDREADTR\n");
+ count = needed;
+
+ if (count > (num_events / 8)) {
+ if (usleep_ms > USLEEP_BEHIND)
+ usleep_ms = USLEEP_BEHIND;
+ else if (usleep_ms > USLEEP_MIN)
+ usleep_ms /= 2;
+
+ } else if (count < (num_events / 16)) {
+ if (usleep_ms < USLEEP_MAX)
+ usleep_ms *= 2;
+ }
- } else if (count < (SAMPLE_SIZE / 16)) {
- if (usleep_ms < USLEEP_MAX)
- usleep_ms *= 2;
- }
+ if (bufinfo.flags & KDBG_WRAPPED) {
+ fprintf(stderr, "fs_usage: buffer overrun, events generated too quickly: %d\n", count);
- if (bufinfo.flags & KDBG_WRAPPED) {
- fprintf(stderr, "fs_usage: buffer overrun, events generated too quickly: %d\n", count);
+ delete_all_events();
- for (i = 0; i <= cur_max; i++) {
- th_state[i].thread = 0;
- th_state[i].pid = 0;
- th_state[i].pathptr = (long *)NULL;
- th_state[i].pathname[0] = 0;
- }
- cur_max = 0;
- cur_start = 0;
- need_new_map = 1;
- map_is_the_same = 0;
+ need_new_map = 1;
- set_enable(0);
- set_enable(1);
+ set_enable(0);
+ set_enable(1);
+ }
+ } else {
+ int bytes_read;
+
+ if ((bytes_read = read(RAW_fd, my_buffer, my_buffer_size)) < sizeof(kd_buf))
+ exit(0);
+ count = bytes_read / sizeof(kd_buf);
}
kd = (kd_buf *)my_buffer;
#if 0
fprintf(stderr, "READTR returned %d items\n", count);
#endif
for (i = 0; i < count; i++) {
- int debugid, thread;
+ uint32_t debugid;
+ uintptr_t thread;
int type;
- int index;
- long *sargptr;
+ int index;
+ uintptr_t *sargptr;
uint64_t now;
long long l_usecs;
int secs;
long curr_time;
- struct th_info *ti;
+ th_info_t ti;
struct diskio *dio;
debugid = kd[i].debugid;
type = kd[i].debugid & DBG_FUNC_MASK;
- now = kd[i].timestamp & KDBG_TIMESTAMP_MASK;
+ now = kdbg_get_timestamp(&kd[i]);
- if (i == 0)
- {
- curr_time = time((long *)0);
- /*
- * Compute bias seconds after each trace buffer read.
- * This helps resync timestamps with the system clock
- * in the event of a system sleep.
- */
- if (bias_secs == 0 || curr_time < last_time || curr_time > (last_time + 2)) {
- l_usecs = (long long)(now / divisor);
- secs = l_usecs / 1000000;
- bias_secs = curr_time - secs;
- }
+ if (i == 0 && !RAW_flag) {
+
+ curr_time = time((long *)0);
+ /*
+ * Compute bias seconds after each trace buffer read.
+ * This helps resync timestamps with the system clock
+ * in the event of a system sleep.
+ */
+ if (bias_secs == 0 || curr_time < last_time || curr_time > (last_time + 2)) {
+ l_usecs = (long long)(now / divisor);
+ secs = l_usecs / 1000000;
+ bias_secs = curr_time - secs;
+ }
}
+ if (RAW_flag && bias_now == 0.0)
+ bias_now = now;
if ((type & P_DISKIO_MASK) == P_DISKIO) {
- insert_diskio(type, kd[i].arg1, kd[i].arg2, kd[i].arg3, kd[i].arg4, thread, (double)now);
+ insert_diskio(type, kd[i].arg1, kd[i].arg2, kd[i].arg3, kd[i].arg4, thread, (double)now);
continue;
}
if ((type & P_DISKIO_MASK) == P_DISKIO_DONE) {
- if ((dio = complete_diskio(kd[i].arg1, kd[i].arg4, kd[i].arg3, thread, (double)now))) {
- print_diskio(dio);
+ if ((dio = complete_diskio(kd[i].arg1, kd[i].arg4, kd[i].arg3, thread, (double)now))) {
+ dio->vnodeid = kd[i].arg2;
+ print_diskio(dio);
free_diskio(dio);
}
continue;
}
- switch (type) {
+ if ((type & CLASS_MASK) == P_CS_Class) {
- case TRACE_DATA_NEWTHREAD:
+ // the usual DBG_FUNC_START/END does not work for i/o since it will
+ // return on a different thread, this code uses the P_CS_IO_Done (0x4) bit
+ // instead. the trace command doesn't know how handle either method
+ // (unmatched start/end or 0x4) but works a little better this way.
+
+ int cs_type = type & P_CS_Type_Mask; // strip out the done bit
+ bool start = (type & P_CS_IO_Done) != P_CS_IO_Done;
+
+ switch (cs_type) {
- if ((ti = find_empty()) == NULL)
- continue;
+ case P_CS_ReadChunk:
+ case P_CS_WriteChunk:
+ case P_CS_MetaRead:
+ case P_CS_MetaWrite:
+ if (start) {
+ insert_diskio(cs_type, kd[i].arg2, kd[i].arg1, kd[i].arg3, kd[i].arg4, thread, (double)now);
+ } else {
+ if ((dio = complete_diskio(kd[i].arg2, kd[i].arg4, kd[i].arg3, thread, (double)now))) {
+ print_diskio(dio);
+ free_diskio(dio);
+ }
+ }
+ continue;
- ti->thread = thread;
- ti->child_thread = kd[i].arg1;
- ti->pid = kd[i].arg2;
+ case P_CS_TransformRead:
+ case P_CS_TransformWrite:
+ case P_CS_MigrationRead:
+ case P_CS_MigrationWrite:
+ if (start) {
+ insert_diskio(cs_type, kd[i].arg2, CS_DEV, kd[i].arg3, kd[i].arg4, thread, (double)now);
+ } else {
+ if ((dio = complete_diskio(kd[i].arg2, kd[i].arg4, kd[i].arg3, thread, (double)now))) {
+ print_diskio(dio);
+ free_diskio(dio);
+ }
+ }
+ continue;
+
+ case P_CS_SYNC_DISK:
+ if (start) {
+ enter_event(thread, cs_type, &kd[i], NULL, (double)now);
+ } else {
+ exit_event(" SyncCacheCS", thread, cs_type, kd[i].arg1, 0, 0, 0, FMT_SYNC_DISK_CS, (double)now);
+ }
+ continue;
+ }
+
+ continue; // ignore other cs timestamps
+ }
+
+ switch (type) {
+
+ case TRACE_DATA_NEWTHREAD:
+ if (kd[i].arg1) {
+ if ((ti = add_event(thread, TRACE_DATA_NEWTHREAD)) == NULL)
+ continue;
+ ti->child_thread = kd[i].arg1;
+ ti->pid = kd[i].arg2;
+ }
continue;
case TRACE_STRING_NEWTHREAD:
- if ((ti = find_thread(thread, 0)) == (struct th_info *)0)
- continue;
- if (ti->child_thread == 0)
+ if ((ti = find_event(thread, TRACE_DATA_NEWTHREAD)) == (struct th_info *)0)
continue;
- create_map_entry(ti->child_thread, ti->pid, (char *)&kd[i].arg1);
- destroy_thread(ti);
+ create_map_entry(ti->child_thread, ti->pid, (char *)&kd[i].arg1);
+ delete_event(ti);
continue;
case TRACE_DATA_EXEC:
-
- if ((ti = find_empty()) == NULL)
+ if ((ti = add_event(thread, TRACE_DATA_EXEC)) == NULL)
continue;
- ti->thread = thread;
ti->pid = kd[i].arg1;
continue;
case TRACE_STRING_EXEC:
- if ((ti = find_thread(thread, 0)) == (struct th_info *)0)
- {
- /* this is for backwards compatibility */
- create_map_entry(thread, 0, (char *)&kd[i].arg1);
- }
- else
- {
- create_map_entry(thread, ti->pid, (char *)&kd[i].arg1);
+ if ((ti = find_event(thread, BSC_execve))) {
+ if (ti->lookups[0].pathname[0])
+ exit_event("execve", thread, BSC_execve, 0, 0, 0, 0, FMT_DEFAULT, (double)now);
- destroy_thread(ti);
+ } else if ((ti = find_event(thread, BSC_posix_spawn))) {
+ if (ti->lookups[0].pathname[0])
+ exit_event("posix_spawn", thread, BSC_posix_spawn, 0, 0, 0, 0, FMT_DEFAULT, (double)now);
}
+ if ((ti = find_event(thread, TRACE_DATA_EXEC)) == (struct th_info *)0)
+ continue;
+
+ create_map_entry(thread, ti->pid, (char *)&kd[i].arg1);
+
+ delete_event(ti);
+ continue;
+
+ case BSC_thread_terminate:
+ delete_map_entry(thread);
continue;
case BSC_exit:
- kill_thread_map(thread);
continue;
+ case proc_exit:
+ kd[i].arg1 = kd[i].arg2 >> 8;
+ type = BSC_exit;
+ break;
+
case BSC_mmap:
if (kd[i].arg4 & MAP_ANON)
- continue;
+ continue;
break;
+ case MACH_idle:
case MACH_sched:
case MACH_stkhandoff:
mark_thread_waited(thread);
continue;
+
+ case BC_IO_HIT:
+ case BC_IO_HIT_STALLED:
+ case BC_IO_MISS:
+ case BC_IO_MISS_CUT_THROUGH:
+ case BC_PLAYBACK_IO:
+ if ((dio = find_diskio(kd[i].arg1)) != NULL)
+ dio->bc_info = type;
+ continue;
+
+ case HFS_modify_block_end:
+ if ((ti = find_event(thread, 0))) {
+ if (ti->nameptr)
+ add_meta_name(kd[i].arg2, ti->nameptr);
+ }
+ continue;
+
+ case VFS_ALIAS_VP:
+ add_vnode_name(kd[i].arg2, find_vnode_name(kd[i].arg1));
+ continue;
case VFS_LOOKUP:
- if ((ti = find_thread(thread, 0)) == (struct th_info *)0)
+ if ((ti = find_event(thread, 0)) == (struct th_info *)0)
continue;
- if (ti->pathptr == NULL) {
- sargptr = ti->pathname;
+ if (debugid & DBG_FUNC_START) {
+
+ if (ti->in_hfs_update) {
+ ti->pn_work_index = (MAX_PATHNAMES - 1);
+ } else {
+ if (ti->pn_scall_index < MAX_SCALL_PATHNAMES)
+ ti->pn_work_index = ti->pn_scall_index;
+ else
+ continue;
+ }
+ sargptr = &ti->lookups[ti->pn_work_index].pathname[0];
+
+ ti->vnodeid = kd[i].arg1;
+
*sargptr++ = kd[i].arg2;
*sargptr++ = kd[i].arg3;
*sargptr++ = kd[i].arg4;
* NULL terminate the 'string'
*/
*sargptr = 0;
+
ti->pathptr = sargptr;
} else {
sargptr = ti->pathptr;
- /*
+ /*
* We don't want to overrun our pathname buffer if the
* kernel sends us more VFS_LOOKUP entries than we can
- * handle.
+ * handle and we only handle 2 pathname lookups for
+ * a given system call
*/
- if (sargptr >= &ti->pathname[NUMPARMS]) {
- continue;
+ if (sargptr == 0)
+ continue;
+
+ if ((uintptr_t)sargptr < (uintptr_t)&ti->lookups[ti->pn_work_index].pathname[NUMPARMS]) {
+
+ *sargptr++ = kd[i].arg1;
+ *sargptr++ = kd[i].arg2;
+ *sargptr++ = kd[i].arg3;
+ *sargptr++ = kd[i].arg4;
+ /*
+ * NULL terminate the 'string'
+ */
+ *sargptr = 0;
}
+ }
+ if (debugid & DBG_FUNC_END) {
- /*
- * We need to detect consecutive vfslookup entries.
- * So, if we get here and find a START entry,
- * fake the pathptr so we can bypass all further
- * vfslookup entries.
- */
- if (debugid & DBG_FUNC_START) {
- ti->pathptr = &ti->pathname[NUMPARMS];
- continue;
+ ti->nameptr = add_vnode_name(ti->vnodeid, &ti->lookups[ti->pn_work_index].pathname[0]);
+
+ if (ti->pn_work_index == ti->pn_scall_index) {
+
+ ti->pn_scall_index++;
+
+ if (ti->pn_scall_index < MAX_SCALL_PATHNAMES)
+ ti->pathptr = &ti->lookups[ti->pn_scall_index].pathname[0];
+ else
+ ti->pathptr = 0;
}
- *sargptr++ = kd[i].arg1;
- *sargptr++ = kd[i].arg2;
- *sargptr++ = kd[i].arg3;
- *sargptr++ = kd[i].arg4;
- /*
- * NULL terminate the 'string'
- */
- *sargptr = 0;
+ } else
ti->pathptr = sargptr;
- }
+
continue;
}
continue;
if ((p = filemgr_calls[index].fm_name) == NULL)
- continue;
+ continue;
} else
p = NULL;
- enter_syscall(thread, type, &kd[i], p, (double)now);
+ enter_event(thread, type, &kd[i], p, (double)now);
continue;
}
switch (type) {
- case MACH_pageout:
- if (kd[i].arg2)
- exit_syscall("PAGE_OUT_D", thread, type, 0, kd[i].arg1, 0, 0, FMT_PGOUT, (double)now);
- else
- exit_syscall("PAGE_OUT_V", thread, type, 0, kd[i].arg1, 0, 0, FMT_PGOUT, (double)now);
- continue;
-
- case MACH_vmfault:
- if (kd[i].arg4 == DBG_PAGEIN_FAULT)
- exit_syscall("PAGE_IN", thread, type, 0, kd[i].arg1, kd[i].arg2, 0, FMT_PGIN, (double)now);
- else if (kd[i].arg4 == DBG_CACHE_HIT_FAULT)
- exit_syscall("CACHE_HIT", thread, type, 0, kd[i].arg1, kd[i].arg2, 0, FMT_CACHEHIT, (double)now);
- else {
- if ((ti = find_thread(thread, type))) {
- destroy_thread(ti);
- }
- }
- continue;
-
- case MSC_map_fd:
- exit_syscall("map_fd", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, FMT_FD, (double)now);
- continue;
+ case Throttled:
+ exit_event(" THROTTLED", thread, type, 0, 0, 0, 0, FMT_DEFAULT, (double)now);
+ continue;
+
+ case HFS_update:
+ exit_event(" HFS_update", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, FMT_HFS_update, (double)now);
+ continue;
+
+ case SPEC_unmap_info:
+ if (check_filter_mode(NULL, SPEC_unmap_info, 0, 0, "SPEC_unmap_info"))
+ format_print(NULL, " TrimExtent", thread, type, kd[i].arg1, kd[i].arg2, kd[i].arg3, 0, FMT_UNMAP_INFO, now, now, 0, "", NULL);
+ continue;
+
+ case SPEC_ioctl:
+ if (kd[i].arg2 == DKIOCSYNCHRONIZECACHE)
+ exit_event("IOCTL", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, FMT_IOCTL_SYNC, (double)now);
+ else if (kd[i].arg2 == DKIOCUNMAP)
+ exit_event("IOCTL", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, FMT_IOCTL_UNMAP, (double)now);
+ else {
+ if ((ti = find_event(thread, type)))
+ delete_event(ti);
+ }
+ continue;
+
+ case MACH_pageout:
+ if (kd[i].arg2)
+ exit_event("PAGE_OUT_ANON", thread, type, 0, kd[i].arg1, 0, 0, FMT_PGOUT, (double)now);
+ else
+ exit_event("PAGE_OUT_FILE", thread, type, 0, kd[i].arg1, 0, 0, FMT_PGOUT, (double)now);
+ continue;
+
+ case MACH_vmfault:
+ if (kd[i].arg4 == DBG_PAGEIN_FAULT)
+ exit_event("PAGE_IN", thread, type, 0, kd[i].arg1, kd[i].arg2, 0, FMT_PGIN, (double)now);
+ else if (kd[i].arg4 == DBG_PAGEINV_FAULT)
+ exit_event("PAGE_IN_FILE", thread, type, 0, kd[i].arg1, kd[i].arg2, 0, FMT_PGIN, (double)now);
+ else if (kd[i].arg4 == DBG_PAGEIND_FAULT)
+ exit_event("PAGE_IN_ANON", thread, type, 0, kd[i].arg1, kd[i].arg2, 0, FMT_PGIN, (double)now);
+ else if (kd[i].arg4 == DBG_CACHE_HIT_FAULT)
+ exit_event("CACHE_HIT", thread, type, 0, kd[i].arg1, kd[i].arg2, 0, FMT_CACHEHIT, (double)now);
+ else {
+ if ((ti = find_event(thread, type)))
+ delete_event(ti);
+ }
+ continue;
+
+ case MSC_map_fd:
+ exit_event("map_fd", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, FMT_FD, (double)now);
+ continue;
- case BSC_mmap_extended:
- case BSC_mmap_extended2:
- case BSC_msync_extended:
- case BSC_pread_extended:
- case BSC_pwrite_extended:
- extend_syscall(thread, type, &kd[i]);
- continue;
+ case BSC_mmap_extended:
+ case BSC_mmap_extended2:
+ case BSC_msync_extended:
+ case BSC_pread_extended:
+ case BSC_pwrite_extended:
+ extend_syscall(thread, type, &kd[i]);
+ continue;
}
if ((type & CSC_MASK) == BSC_BASE) {
- index = BSC_INDEX(type);
-
- if (index >= MAX_BSD_SYSCALL)
- continue;
-
- if (bsd_syscalls[index].sc_name == NULL)
+ if ((index = BSC_INDEX(type)) >= MAX_BSD_SYSCALL)
continue;
- if (type == BSC_execve)
- execs_in_progress--;
-
- exit_syscall(bsd_syscalls[index].sc_name, thread, type, kd[i].arg1, kd[i].arg2, kd[i].arg3, kd[i].arg4,
- bsd_syscalls[index].sc_format, (double)now);
-
- continue;
- }
+ if (bsd_syscalls[index].sc_name) {
+ exit_event(bsd_syscalls[index].sc_name, thread, type, kd[i].arg1, kd[i].arg2, kd[i].arg3, kd[i].arg4,
+ bsd_syscalls[index].sc_format, (double)now);
- if ((type & CLASS_MASK) == FILEMGR_BASE) {
+ if (type == BSC_exit)
+ delete_map_entry(thread);
+ }
+ } else if ((type & CLASS_MASK) == FILEMGR_BASE) {
- index = filemgr_index(type);
-
- if (index >= MAX_FILEMGR)
- continue;
-
- if (filemgr_calls[index].fm_name == NULL)
+ if ((index = filemgr_index(type)) >= MAX_FILEMGR)
continue;
- exit_syscall(filemgr_calls[index].fm_name, thread, type, kd[i].arg1, kd[i].arg2, kd[i].arg3, kd[i].arg4,
- FMT_DEFAULT, (double)now);
+ if (filemgr_calls[index].fm_name) {
+ exit_event(filemgr_calls[index].fm_name, thread, type, kd[i].arg1, kd[i].arg2, kd[i].arg3, kd[i].arg4,
+ FMT_DEFAULT, (double)now);
+ }
}
}
fflush(0);
}
-
-
void
-enter_syscall_now(int thread, int type, kd_buf *kd, char *name, double now)
+enter_event_now(uintptr_t thread, int type, kd_buf *kd, char *name, double now)
{
- struct th_info *ti;
- int secs;
- int usecs;
- long long l_usecs;
- long curr_time;
- kd_threadmap *map;
- kd_threadmap *find_thread_map();
- int clen = 0;
- int tsclen = 0;
- int nmclen = 0;
- int argsclen = 0;
- char buf[MAXWIDTH];
-
- if (execs_in_progress) {
- if ((ti = find_thread(thread, BSC_execve))) {
- if (ti->pathptr) {
- exit_syscall("execve", thread, BSC_execve, 0, 0, 0, 0, FMT_DEFAULT, (double)now);
- execs_in_progress--;
- }
- }
- }
- if ((ti = find_empty()) == NULL)
- return;
-
- if ((type & CLASS_MASK) == FILEMGR_BASE) {
+ th_info_t ti;
+ threadmap_t tme;
+ int secs;
+ int usecs;
+ long long l_usecs;
+ long curr_time;
+ int clen = 0;
+ int tsclen = 0;
+ int nmclen = 0;
+ int argsclen = 0;
+ char buf[MAXWIDTH];
+
+ if ((ti = add_event(thread, type)) == NULL)
+ return;
- filemgr_in_progress++;
- ti->in_filemgr = 1;
+ ti->stime = now;
+ ti->arg1 = kd->arg1;
+ ti->arg2 = kd->arg2;
+ ti->arg3 = kd->arg3;
+ ti->arg4 = kd->arg4;
- l_usecs = (long long)(now / divisor);
- secs = l_usecs / 1000000;
- curr_time = bias_secs + secs;
+ switch (type) {
+
+ case HFS_update:
+ ti->in_hfs_update = 1;
+ break;
+ }
+
+ if ((type & CLASS_MASK) == FILEMGR_BASE &&
+ (!RAW_flag || (now >= start_time && now <= end_time))) {
+
+ filemgr_in_progress++;
+ ti->in_filemgr = 1;
+
+ if (RAW_flag) {
+ l_usecs = (long long)((now - bias_now) / divisor);
+ l_usecs += (sample_TOD_secs * 1000000) + sample_TOD_usecs;
+ } else
+ l_usecs = (long long)(now / divisor);
+ secs = l_usecs / 1000000;
+ curr_time = bias_secs + secs;
- sprintf(buf, "%-8.8s", &(ctime(&curr_time)[11]));
- tsclen = strlen(buf);
+ sprintf(buf, "%-8.8s", &(ctime(&curr_time)[11]));
+ tsclen = strlen(buf);
- if (columns > MAXCOLS || wideflag) {
- usecs = l_usecs - (long long)((long long)secs * 1000000);
- sprintf(&buf[tsclen], ".%03ld", (long)usecs / 1000);
- tsclen = strlen(buf);
- }
+ if (columns > MAXCOLS || wideflag) {
+ usecs = l_usecs - (long long)((long long)secs * 1000000);
+ sprintf(&buf[tsclen], ".%06ld", (long)usecs);
+ tsclen = strlen(buf);
+ }
- /*
- * Print timestamp column
- */
- printf("%s", buf);
+ /*
+ * Print timestamp column
+ */
+ printf("%s", buf);
- map = find_thread_map(thread);
- if (map) {
- sprintf(buf, " %-25.25s ", name);
- nmclen = strlen(buf);
- printf("%s", buf);
+ tme = find_map_entry(thread);
+ if (tme) {
+ sprintf(buf, " %-25.25s ", name);
+ nmclen = strlen(buf);
+ printf("%s", buf);
- sprintf(buf, "(%d, 0x%x, 0x%x, 0x%x)", (short)kd->arg1, kd->arg2, kd->arg3, kd->arg4);
- argsclen = strlen(buf);
+ sprintf(buf, "(%d, 0x%lx, 0x%lx, 0x%lx)", (short)kd->arg1, kd->arg2, kd->arg3, kd->arg4);
+ argsclen = strlen(buf);
- /*
- * Calculate white space out to command
- */
- if (columns > MAXCOLS || wideflag) {
- clen = columns - (tsclen + nmclen + argsclen + 20);
- } else
- clen = columns - (tsclen + nmclen + argsclen + 12);
-
- if (clen > 0) {
- printf("%s", buf); /* print the kdargs */
- memset(buf, ' ', clen);
- buf[clen] = '\0';
- printf("%s", buf);
- }
- else if ((argsclen + clen) > 0) {
- /*
- * no room so wipe out the kdargs
- */
- memset(buf, ' ', (argsclen + clen));
- buf[argsclen + clen] = '\0';
- printf("%s", buf);
- }
- if (columns > MAXCOLS || wideflag)
- printf("%-20.20s\n", map->command);
- else
- printf("%-12.12s\n", map->command);
- } else
- printf(" %-24.24s (%5d, %#x, 0x%x, 0x%x)\n", name, (short)kd->arg1, kd->arg2, kd->arg3, kd->arg4);
- }
- ti->thread = thread;
- ti->waited = 0;
- ti->type = type;
- ti->stime = now;
- ti->arg1 = kd->arg1;
- ti->arg2 = kd->arg2;
- ti->arg3 = kd->arg3;
- ti->arg4 = kd->arg4;
- ti->pathptr = (long *)NULL;
- ti->pathname[0] = 0;
+ /*
+ * Calculate white space out to command
+ */
+ if (columns > MAXCOLS || wideflag) {
+ clen = columns - (tsclen + nmclen + argsclen + 20 + 11);
+ } else
+ clen = columns - (tsclen + nmclen + argsclen + 12);
+
+ if (clen > 0) {
+ printf("%s", buf); /* print the kdargs */
+ memset(buf, ' ', clen);
+ buf[clen] = '\0';
+ printf("%s", buf);
+ }
+ else if ((argsclen + clen) > 0) {
+ /*
+ * no room so wipe out the kdargs
+ */
+ memset(buf, ' ', (argsclen + clen));
+ buf[argsclen + clen] = '\0';
+ printf("%s", buf);
+ }
+ if (columns > MAXCOLS || wideflag)
+ printf("%s.%d\n", tme->tm_command, (int)thread);
+ else
+ printf("%-12.12s\n", tme->tm_command);
+ } else
+ printf(" %-24.24s (%5d, %#lx, 0x%lx, 0x%lx)\n", name, (short)kd->arg1, kd->arg2, kd->arg3, kd->arg4);
+ }
}
void
-enter_syscall(int thread, int type, kd_buf *kd, char *name, double now)
+enter_event(uintptr_t thread, int type, kd_buf *kd, char *name, double now)
{
- int index;
-
- if (type == MACH_pageout || type == MACH_vmfault || type == MSC_map_fd) {
- enter_syscall_now(thread, type, kd, name, now);
- return;
- }
- if ((type & CSC_MASK) == BSC_BASE) {
+ int index;
- index = BSC_INDEX(type);
+ switch (type) {
- if (index >= MAX_BSD_SYSCALL)
- return;
+ case P_CS_SYNC_DISK:
+ case MACH_pageout:
+ case MACH_vmfault:
+ case MSC_map_fd:
+ case SPEC_ioctl:
+ case Throttled:
+ case HFS_update:
+ enter_event_now(thread, type, kd, name, now);
+ return;
- if (type == BSC_execve)
- execs_in_progress++;
-
- if (bsd_syscalls[index].sc_name)
- enter_syscall_now(thread, type, kd, name, now);
+ }
+ if ((type & CSC_MASK) == BSC_BASE) {
- return;
- }
- if ((type & CLASS_MASK) == FILEMGR_BASE) {
+ if ((index = BSC_INDEX(type)) >= MAX_BSD_SYSCALL)
+ return;
- index = filemgr_index(type);
+ if (bsd_syscalls[index].sc_name)
+ enter_event_now(thread, type, kd, name, now);
+ return;
+ }
+ if ((type & CLASS_MASK) == FILEMGR_BASE) {
- if (index >= MAX_FILEMGR)
- return;
+ if ((index = filemgr_index(type)) >= MAX_FILEMGR)
+ return;
- if (filemgr_calls[index].fm_name)
- enter_syscall_now(thread, type, kd, name, now);
- }
+ if (filemgr_calls[index].fm_name)
+ enter_event_now(thread, type, kd, name, now);
+ return;
+ }
}
/*
*/
void
-extend_syscall(int thread, int type, kd_buf *kd)
+extend_syscall(uintptr_t thread, int type, kd_buf *kd)
{
- struct th_info *ti;
-
- switch (type) {
- case BSC_mmap_extended:
- if ((ti = find_thread(thread, BSC_mmap)) == (struct th_info *)0)
- return;
- ti->arg8 = ti->arg3; /* save protection */
- ti->arg1 = kd->arg1; /* the fd */
- ti->arg3 = kd->arg2; /* bottom half address */
- ti->arg5 = kd->arg3; /* bottom half size */
- break;
- case BSC_mmap_extended2:
- if ((ti = find_thread(thread, BSC_mmap)) == (struct th_info *)0)
- return;
- ti->arg2 = kd->arg1; /* top half address */
- ti->arg4 = kd->arg2; /* top half size */
- ti->arg6 = kd->arg3; /* top half file offset */
- ti->arg7 = kd->arg4; /* bottom half file offset */
- break;
- case BSC_msync_extended:
- if ((ti = find_thread(thread, BSC_msync)) == (struct th_info *)0) {
- if ((ti = find_thread(thread, BSC_msync_nocancel)) == (struct th_info *)0)
- return;
- }
- ti->arg4 = kd->arg1; /* top half address */
- ti->arg5 = kd->arg2; /* top half size */
- break;
- case BSC_pread_extended:
- if ((ti = find_thread(thread, BSC_pread)) == (struct th_info *)0) {
- if ((ti = find_thread(thread, BSC_pread_nocancel)) == (struct th_info *)0)
- return;
- }
- ti->arg1 = kd->arg1; /* the fd */
- ti->arg2 = kd->arg2; /* nbytes */
- ti->arg3 = kd->arg3; /* top half offset */
- ti->arg4 = kd->arg4; /* bottom half offset */
- break;
- case BSC_pwrite_extended:
- if ((ti = find_thread(thread, BSC_pwrite)) == (struct th_info *)0) {
- if ((ti = find_thread(thread, BSC_pwrite_nocancel)) == (struct th_info *)0)
- return;
- }
- ti->arg1 = kd->arg1; /* the fd */
- ti->arg2 = kd->arg2; /* nbytes */
- ti->arg3 = kd->arg3; /* top half offset */
- ti->arg4 = kd->arg4; /* bottom half offset */
- break;
- default:
- return;
+ th_info_t ti;
+
+ switch (type) {
+ case BSC_mmap_extended:
+ if ((ti = find_event(thread, BSC_mmap)) == (struct th_info *)0)
+ return;
+ ti->arg8 = ti->arg3; /* save protection */
+ ti->arg1 = kd->arg1; /* the fd */
+ ti->arg3 = kd->arg2; /* bottom half address */
+ ti->arg5 = kd->arg3; /* bottom half size */
+ break;
+ case BSC_mmap_extended2:
+ if ((ti = find_event(thread, BSC_mmap)) == (struct th_info *)0)
+ return;
+ ti->arg2 = kd->arg1; /* top half address */
+ ti->arg4 = kd->arg2; /* top half size */
+ ti->arg6 = kd->arg3; /* top half file offset */
+ ti->arg7 = kd->arg4; /* bottom half file offset */
+ break;
+ case BSC_msync_extended:
+ if ((ti = find_event(thread, BSC_msync)) == (struct th_info *)0) {
+ if ((ti = find_event(thread, BSC_msync_nocancel)) == (struct th_info *)0)
+ return;
+ }
+ ti->arg4 = kd->arg1; /* top half address */
+ ti->arg5 = kd->arg2; /* top half size */
+ break;
+ case BSC_pread_extended:
+ if ((ti = find_event(thread, BSC_pread)) == (struct th_info *)0) {
+ if ((ti = find_event(thread, BSC_pread_nocancel)) == (struct th_info *)0)
+ return;
+ }
+ ti->arg1 = kd->arg1; /* the fd */
+ ti->arg2 = kd->arg2; /* nbytes */
+ ti->arg3 = kd->arg3; /* top half offset */
+ ti->arg4 = kd->arg4; /* bottom half offset */
+ break;
+ case BSC_pwrite_extended:
+ if ((ti = find_event(thread, BSC_pwrite)) == (struct th_info *)0) {
+ if ((ti = find_event(thread, BSC_pwrite_nocancel)) == (struct th_info *)0)
+ return;
+ }
+ ti->arg1 = kd->arg1; /* the fd */
+ ti->arg2 = kd->arg2; /* nbytes */
+ ti->arg3 = kd->arg3; /* top half offset */
+ ti->arg4 = kd->arg4; /* bottom half offset */
+ break;
+ default:
+ return;
}
}
void
-exit_syscall(char *sc_name, int thread, int type, int arg1, int arg2, int arg3, int arg4,
- int format, double now)
+exit_event(char *sc_name, uintptr_t thread, int type, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, uintptr_t arg4,
+ int format, double now)
{
- struct th_info *ti;
+ th_info_t ti;
- if ((ti = find_thread(thread, type)) == (struct th_info *)0)
+ if ((ti = find_event(thread, type)) == (struct th_info *)0)
return;
+ ti->nameptr = 0;
+
if (check_filter_mode(ti, type, arg1, arg2, sc_name))
- format_print(ti, sc_name, thread, type, arg1, arg2, arg3, arg4, format, now, ti->stime, ti->waited, (char *)ti->pathname, NULL);
+ format_print(ti, sc_name, thread, type, arg1, arg2, arg3, arg4, format, now, ti->stime, ti->waited, (char *)&ti->lookups[0].pathname[0], NULL);
+
+ switch (type) {
+ case HFS_update:
+ ti->in_hfs_update = 0;
+ break;
+ }
if ((type & CLASS_MASK) == FILEMGR_BASE) {
ti->in_filemgr = 0;
if (filemgr_in_progress > 0)
filemgr_in_progress--;
}
- destroy_thread(ti);
+ delete_event(ti);
}
void
-format_print(struct th_info *ti, char *sc_name, int thread, int type, int arg1, int arg2, int arg3, int arg4,
+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,
int format, double now, double stime, int waited, char *pathname, struct diskio *dio)
{
int secs;
long long l_usecs;
long curr_time;
char *command_name;
- kd_threadmap *map;
- kd_threadmap *find_thread_map();
int in_filemgr = 0;
int len = 0;
int clen = 0;
uint64_t user_addr;
uint64_t user_size;
char *framework_name;
+ char *framework_type;
char *p1;
char *p2;
char buf[MAXWIDTH];
- command_name = "";
- int need_msec_update = 0;
+ char cs_diskname[32];
+
static char timestamp[32];
- static int last_timestamp = 0;
+ static int last_timestamp = -1;
static int timestamp_len = 0;
- static int last_msec = 0;
+ command_name = "";
+
+ if (RAW_flag) {
+ l_usecs = (long long)((now - bias_now) / divisor);
+
+ if ((double)l_usecs < start_time || (double)l_usecs > end_time)
+ return;
+
+ l_usecs += (sample_TOD_secs * 1000000) + sample_TOD_usecs;
+ }
+ else
+ l_usecs = (long long)(now / divisor);
+ secs = l_usecs / 1000000;
+ curr_time = bias_secs + secs;
class = type >> 24;
if (dio)
command_name = dio->issuing_command;
else {
- if (map_is_the_same && thread == last_thread)
- map = last_map;
- else {
- if ((map = find_thread_map(thread))) {
- last_map = map;
- last_thread = thread;
- map_is_the_same = 1;
- }
- }
- if (map)
- command_name = map->command;
- }
- l_usecs = (long long)(now / divisor);
- secs = l_usecs / 1000000;
- curr_time = bias_secs + secs;
+ threadmap_t tme;
+ if ((tme = find_map_entry(thread)))
+ command_name = tme->tm_command;
+ }
if (last_timestamp != curr_time) {
timestamp_len = sprintf(timestamp, "%-8.8s", &(ctime(&curr_time)[11]));
last_timestamp = curr_time;
- need_msec_update = 1;
}
if (columns > MAXCOLS || wideflag) {
- int msec;
+ int usec;
tlen = timestamp_len;
nopadding = 0;
- msec = (l_usecs - (long long)((long long)secs * 1000000)) / 1000;
+ usec = (l_usecs - (long long)((long long)secs * 1000000));
- if (msec != last_msec || need_msec_update) {
- sprintf(×tamp[tlen], ".%03ld", (long)msec);
- last_msec = msec;
- }
- tlen += 4;
+ sprintf(×tamp[tlen], ".%06ld", (long)usec);
+ tlen += 7;
timestamp[tlen] = '\0';
if (filemgr_in_progress) {
if (class != FILEMGR_CLASS) {
- if (find_thread(thread, -1)) {
+ if (find_event(thread, -1))
in_filemgr = 1;
- }
}
}
} else
else
clen = printf("%s %-17.17s", timestamp, sc_name);
- framework_name = (char *)0;
+
+ framework_name = NULL;
if (columns > MAXCOLS || wideflag) {
* pagein
*/
user_addr = ((uint64_t)arg2 << 32) | (uint32_t)arg3;
- framework_name = lookup_name(user_addr);
+
+ lookup_name(user_addr, &framework_type, &framework_name);
clen += clip_64bit(" A=", user_addr);
break;
*/
user_addr = ((uint64_t)arg2 << 32) | (uint32_t)arg3;
- framework_name = lookup_name(user_addr);
+ lookup_name(user_addr, &framework_type, &framework_name);
clen += clip_64bit(" A=", user_addr);
break;
clen += printf(" B=0x%-8x", arg2);
break;
+ case FMT_HFS_update:
+ {
+ char sbuf[7];
+ int sflag = (int)arg2;
+
+ memset(sbuf, '_', 6);
+ sbuf[6] = '\0';
+
+
+ if (sflag & 0x10)
+ sbuf[0] = 'F';
+ if (sflag & 0x08)
+ sbuf[1] = 'M';
+ if (sflag & 0x20)
+ sbuf[2] = 'D';
+ if (sflag & 0x04)
+ sbuf[3] = 'c';
+ if (sflag & 0x01)
+ sbuf[4] = 'a';
+ if (sflag & 0x02)
+ sbuf[5] = 'm';
+
+ clen += printf(" (%s) ", sbuf);
+
+ pathname = find_vnode_name(arg1);
+ nopadding = 1;
+
+ break;
+ }
+
case FMT_DISKIO:
+ /*
+ * physical disk I/O
+ */
+ if (dio->io_errno)
+ clen += printf(" D=0x%8.8x [%3d]", dio->blkno, dio->io_errno);
+ else {
+ if (BC_flag)
+ 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));
+ else
+ clen += printf(" D=0x%8.8x B=0x%-6x /dev/%s ", dio->blkno, dio->iosize, find_disk_name(dio->dev));
+
+ if (dio->is_meta)
+ pathname = find_meta_name(dio->blkno);
+ else
+ pathname = find_vnode_name(dio->vnodeid);
+ nopadding = 1;
+ }
+ break;
+
+ case FMT_DISKIO_CS:
/*
* physical disk I/O
*/
if (dio->io_errno)
clen += printf(" D=0x%8.8x [%3d]", dio->blkno, dio->io_errno);
else
- clen += printf(" D=0x%8.8x B=0x%-6x /dev/%s", dio->blkno, dio->iosize, find_disk_name(dio->dev));
+ clen += printf(" D=0x%8.8x B=0x%-6x /dev/%s", dio->blkno, dio->iosize, generate_cs_disk_name(dio->dev, &cs_diskname[0]));
+ break;
+
+ case FMT_SYNC_DISK_CS:
+ /*
+ * physical disk sync cache
+ */
+ clen += printf(" /dev/%s", generate_cs_disk_name(arg1, &cs_diskname[0]));
+
break;
case FMT_MSYNC:
break;
}
- case FMT_FCNTL:
+ case FMT_FLOCK:
{
/*
- * fcntl
+ * flock
*/
- char *p = NULL;
+ int mlen = 0;
+
+ buf[0] = '\0';
+
+ if (ti->arg2 & LOCK_SH)
+ mlen += sprintf(&buf[mlen], "LOCK_SH | ");
+ if (ti->arg2 & LOCK_EX)
+ mlen += sprintf(&buf[mlen], "LOCK_EX | ");
+ if (ti->arg2 & LOCK_NB)
+ mlen += sprintf(&buf[mlen], "LOCK_NB | ");
+ if (ti->arg2 & LOCK_UN)
+ mlen += sprintf(&buf[mlen], "LOCK_UN | ");
+
+ if (ti->arg2 & ~(LOCK_SH | LOCK_EX | LOCK_NB | LOCK_UN))
+ mlen += sprintf(&buf[mlen], "UNKNOWN | ");
+
+ if (mlen)
+ buf[mlen - 3] = '\0';
+
+ if (arg1)
+ clen += printf(" F=%-3d[%3d] <%s>", ti->arg1, arg1, buf);
+ else
+ clen += printf(" F=%-3d <%s>", ti->arg1, buf);
+
+ break;
+ }
+
+ case FMT_FCNTL:
+ {
+ /*
+ * fcntl
+ */
+ char *p = NULL;
+ int fd = -1;
if (arg1)
clen += printf(" F=%-3d[%3d]", ti->arg1, arg1);
p = "PATHPKG_CHECK";
break;
+ case F_OPENFROM:
+ p = "OPENFROM";
+
+ if (arg1 == 0)
+ fd = arg2;
+ break;
+
+ case F_UNLINKFROM:
+ p = "UNLINKFROM";
+ break;
+
+ case F_CHECK_OPENEVT:
+ p = "CHECK_OPENEVT";
+ break;
+
case F_NOCACHE:
if (ti->arg3)
p = "CACHING OFF";
p = "CACHING ON";
break;
+ case F_GLOBAL_NOCACHE:
+ if (ti->arg3)
+ p = "CACHING OFF (GLOBAL)";
+ else
+ p = "CACHING ON (GLOBAL)";
+ break;
+
}
- if (p)
- clen += printf(" <%s>", p);
- else
+ if (p) {
+ if (fd == -1)
+ clen += printf(" <%s>", p);
+ else
+ clen += printf(" <%s> F=%d", p, fd);
+ } else
clen += printf(" <CMD=%d>", ti->arg2);
break;
case FMT_IOCTL:
{
/*
- * fcntl
+ * ioctl
*/
if (arg1)
clen += printf(" F=%-3d[%3d]", ti->arg1, arg1);
break;
}
+ case FMT_IOCTL_SYNC:
+ {
+ /*
+ * ioctl
+ */
+ clen += printf(" <DKIOCSYNCHRONIZECACHE> /dev/%s", find_disk_name(arg1));
+
+ break;
+ }
+
+ case FMT_IOCTL_UNMAP:
+ {
+ /*
+ * ioctl
+ */
+ clen += printf(" <DKIOCUNMAP> /dev/%s", find_disk_name(arg1));
+
+ break;
+ }
+
+ case FMT_UNMAP_INFO:
+ {
+ clen += printf(" D=0x%8.8x B=0x%-6x /dev/%s", arg2, arg3, find_disk_name(arg1));
+
+ break;
+ }
+
case FMT_SELECT:
/*
* select
buf[mlen++] = '>';
buf[mlen] = '\0';
- if (mlen < 21) {
- memset(&buf[mlen], ' ', 21 - mlen);
- mlen = 21;
+ if (mlen < 19) {
+ memset(&buf[mlen], ' ', 19 - mlen);
+ mlen = 19;
}
clen += printf("%s", buf);
break;
}
+ case FMT_UMASK:
case FMT_FCHMOD:
case FMT_FCHMOD_EXT:
case FMT_CHMOD:
else
clen += printf(" ");
}
- if (format == FMT_FCHMOD || format == FMT_CHMOD)
+ if (format == FMT_UMASK)
+ mode = ti->arg1;
+ else if (format == FMT_FCHMOD || format == FMT_CHMOD)
mode = ti->arg2;
else
mode = ti->arg4;
get_mode_string(mode, &buf[0]);
if (arg1 == 0)
- clen += printf("<%s> ", buf);
+ clen += printf("<%s> ", buf);
else
clen += printf("<%s>", buf);
break;
/*
* access
*/
- char mode[4];
+ char mode[5];
memset(mode, '_', 4);
mode[4] = '\0';
break;
}
+ case FMT_MOUNT:
+ {
+ if (arg1)
+ clen += printf(" [%3d] <FLGS=0x%x> ", arg1, ti->arg3);
+ else
+ clen += printf(" <FLGS=0x%x> ", ti->arg3);
+
+ nopadding = 1;
+ break;
+ }
+
+ case FMT_UNMOUNT:
+ {
+ char *mountflag;
+
+ if (ti->arg2 & MNT_FORCE)
+ mountflag = "<FORCE>";
+ else
+ mountflag = "";
+
+ if (arg1)
+ clen += printf(" [%3d] %s ", arg1, mountflag);
+ else
+ clen += printf(" %s ", mountflag);
+
+ nopadding = 1;
+ break;
+ }
+
case FMT_OPEN:
{
/*
* Calculate space available to print pathname
*/
if (columns > MAXCOLS || wideflag)
- clen = columns - (clen + 14 + 20);
+ clen = columns - (clen + 14 + 20 + 11);
else
clen = columns - (clen + 14 + 12);
clen -= 3;
if (framework_name)
- len = sprintf(&buf[0], " %s ", framework_name);
- else if (*pathname != '\0')
+ len = sprintf(&buf[0], " %s %s ", framework_type, framework_name);
+ else if (*pathname != '\0') {
len = sprintf(&buf[0], " %s ", pathname);
- else
+
+ if (format == FMT_MOUNT && ti->lookups[1].pathname[0]) {
+ int len2;
+
+ memset(&buf[len], ' ', 2);
+
+ len2 = sprintf(&buf[len+2], " %s ", (char *)&ti->lookups[1].pathname[0]);
+ len = len + 2 + len2;
+ }
+ } else
len = 0;
if (clen > len) {
p2 = " ";
if (columns > MAXCOLS || wideflag)
- printf("%s%s %3ld.%06ld%s %-20.20s\n", p1, pathname, (unsigned long)secs, (unsigned long)usecs, p2, command_name);
+ printf("%s%s %3ld.%06ld%s %s.%d\n", p1, pathname, (unsigned long)secs, (unsigned long)usecs, p2, command_name, (int)thread);
else
printf("%s%s %3ld.%06ld%s %-12.12s\n", p1, pathname, (unsigned long)secs, (unsigned long)usecs, p2, command_name);
}
-int
-quit(s)
-char *s;
-{
- if (trace_enabled)
- set_enable(0);
- /*
- * This flag is turned off when calling
- * quit() due to a set_remove() failure.
- */
- if (set_remove_flag)
- set_remove();
+void
+add_meta_name(uint64_t blockno, char *pathname) {
+ meta_info_t mi;
+ int hashid;
- fprintf(stderr, "fs_usage: ");
- if (s)
- fprintf(stderr, "%s", s);
+ hashid = blockno & VN_HASH_MASK;
- exit(1);
+ for (mi = m_info_hash[hashid]; mi; mi = mi->m_next) {
+ if (mi->m_blkno == blockno)
+ break;
+ }
+ if (mi == NULL) {
+ mi = (meta_info_t)malloc(sizeof(struct meta_info));
+
+ mi->m_next = m_info_hash[hashid];
+ m_info_hash[hashid] = mi;
+ mi->m_blkno = blockno;
+ }
+ mi->m_nameptr = pathname;
}
+char *
+find_meta_name(uint64_t blockno) {
+ meta_info_t mi;
+ int hashid;
-void getdivisor()
-{
- struct mach_timebase_info mti;
-
- mach_timebase_info(&mti);
+ hashid = blockno & VN_HASH_MASK;
- divisor = ((double)mti.denom / (double)mti.numer) * 1000;
+ for (mi = m_info_hash[hashid]; mi; mi = mi->m_next) {
+ if (mi->m_blkno == blockno)
+ return (mi->m_nameptr);
+ }
+ return ("");
}
-void read_command_map()
-{
- size_t size;
- int i;
- int prev_total_threads;
- int mib[6];
-
- if (mapptr) {
- free(mapptr);
- mapptr = 0;
- }
-
- prev_total_threads = total_threads;
- total_threads = bufinfo.nkdthreads;
- size = bufinfo.nkdthreads * sizeof(kd_threadmap);
-
- if (size)
- {
- if ((mapptr = (kd_threadmap *) malloc(size)))
- {
- bzero (mapptr, size);
-
- /* Now read the threadmap */
- mib[0] = CTL_KERN;
- mib[1] = KERN_KDEBUG;
- mib[2] = KERN_KDTHRMAP;
- mib[3] = 0;
- mib[4] = 0;
- mib[5] = 0; /* no flags */
- if (sysctl(mib, 3, mapptr, &size, NULL, 0) < 0)
- {
- /* This is not fatal -- just means I cant map command strings */
- free(mapptr);
- mapptr = 0;
- }
+char *
+add_vnode_name(uint64_t vn_id, char *pathname) {
+ vnode_info_t vn;
+ int hashid;
+
+ hashid = (vn_id >> VN_HASH_SHIFT) & VN_HASH_MASK;
+
+ for (vn = vn_info_hash[hashid]; vn; vn = vn->vn_next) {
+ if (vn->vn_id == vn_id)
+ break;
}
- }
-
- if (mapptr && (filter_mode & (NETWORK_FILTER | FILESYS_FILTER)))
- {
- if (fdmapptr)
- {
- /* We accept the fact that we lose file descriptor state if the
- kd_buffer wraps */
- for (i = 0; i < prev_total_threads; i++)
- {
- if (fdmapptr[i].fd_setptr)
- free (fdmapptr[i].fd_setptr);
- }
- free(fdmapptr);
- fdmapptr = 0;
+ if (vn == NULL) {
+ vn = (vnode_info_t)malloc(sizeof(struct vnode_info));
+
+ vn->vn_next = vn_info_hash[hashid];
+ vn_info_hash[hashid] = vn;
+ vn->vn_id = vn_id;
}
+ strcpy(vn->vn_pathname, pathname);
- size = total_threads * sizeof(fd_threadmap);
- if ((fdmapptr = (fd_threadmap *) malloc(size)))
- {
- bzero (fdmapptr, size);
- /* reinitialize file descriptor state map */
- for (i = 0; i < total_threads; i++)
- {
- fdmapptr[i].fd_thread = mapptr[i].thread;
- fdmapptr[i].fd_valid = mapptr[i].valid;
- fdmapptr[i].fd_setsize = 0;
- fdmapptr[i].fd_setptr = 0;
- }
+ return (&vn->vn_pathname);
+}
+
+
+char *
+find_vnode_name(uint64_t vn_id) {
+ vnode_info_t vn;
+ int hashid;
+
+ hashid = (vn_id >> VN_HASH_SHIFT) & VN_HASH_MASK;
+
+ for (vn = vn_info_hash[hashid]; vn; vn = vn->vn_next) {
+ if (vn->vn_id == vn_id)
+ return (vn->vn_pathname);
}
- }
+ return ("");
+}
- /* Resolve any LaunchCFMApp command names */
- if (mapptr && arguments)
- {
- for (i=0; i < total_threads; i++)
- {
- int pid;
- pid = mapptr[i].valid;
-
- if (pid == 0 || pid == 1)
- continue;
- else if (!strncmp(mapptr[i].command,"LaunchCFMA", 10))
- {
- (void)get_real_command_name(pid, mapptr[i].command, sizeof(mapptr[i].command));
- }
+void
+delete_event(th_info_t ti_to_delete) {
+ th_info_t ti;
+ th_info_t ti_prev;
+ int hashid;
+
+ hashid = ti_to_delete->thread & HASH_MASK;
+
+ if ((ti = th_info_hash[hashid])) {
+ if (ti == ti_to_delete)
+ th_info_hash[hashid] = ti->next;
+ else {
+ ti_prev = ti;
+
+ for (ti = ti->next; ti; ti = ti->next) {
+ if (ti == ti_to_delete) {
+ ti_prev->next = ti->next;
+ break;
+ }
+ ti_prev = ti;
+ }
+ }
+ if (ti) {
+ ti->next = th_info_freelist;
+ th_info_freelist = ti;
+ }
+ }
+}
+
+th_info_t
+add_event(uintptr_t thread, int type) {
+ th_info_t ti;
+ int i;
+ int hashid;
+
+ if ((ti = th_info_freelist))
+ th_info_freelist = ti->next;
+ else
+ ti = (th_info_t)malloc(sizeof(struct th_info));
+
+ hashid = thread & HASH_MASK;
+
+ ti->next = th_info_hash[hashid];
+ th_info_hash[hashid] = ti;
+
+ ti->thread = thread;
+ ti->type = type;
+
+ ti->waited = 0;
+ ti->in_filemgr = 0;
+ ti->in_hfs_update = 0;
+
+ ti->pathptr = &ti->lookups[0].pathname[0];
+ ti->pn_scall_index = 0;
+ ti->pn_work_index = 0;
+
+ for (i = 0; i < MAX_PATHNAMES; i++)
+ ti->lookups[i].pathname[0] = 0;
+
+ return (ti);
+}
+
+th_info_t
+find_event(uintptr_t thread, int type) {
+ th_info_t ti;
+ int hashid;
+
+ hashid = thread & HASH_MASK;
+
+ for (ti = th_info_hash[hashid]; ti; ti = ti->next) {
+ if (ti->thread == thread) {
+ if (type == ti->type)
+ return (ti);
+ if (ti->in_filemgr) {
+ if (type == -1)
+ return (ti);
+ continue;
+ }
+ if (type == 0)
+ return (ti);
+ }
}
- }
+ return ((th_info_t) 0);
+}
+
+void
+delete_all_events() {
+ th_info_t ti = 0;
+ th_info_t ti_next = 0;
+ int i;
+
+ for (i = 0; i < HASH_SIZE; i++) {
+
+ for (ti = th_info_hash[i]; ti; ti = ti_next) {
+ ti_next = ti->next;
+ ti->next = th_info_freelist;
+ th_info_freelist = ti;
+ }
+ th_info_hash[i] = 0;
+ }
}
-void create_map_entry(int thread, int pid, char *command)
-{
- int i, n;
- kd_threadmap *map;
- fd_threadmap *fdmap = 0;
-
- if (!mapptr)
- return;
-
- for (i = 0, map = 0; !map && i < total_threads; i++)
- {
- if ((int)mapptr[i].thread == thread )
- {
- map = &mapptr[i]; /* Reuse this entry, the thread has been
- * reassigned */
- if ((filter_mode & (NETWORK_FILTER | FILESYS_FILTER)) && fdmapptr)
- {
- fdmap = &fdmapptr[i];
- if (fdmap->fd_thread != thread) /* This shouldn't happen */
- fdmap = (fd_threadmap *)0;
- }
+void
+mark_thread_waited(uintptr_t thread) {
+ th_info_t ti;
+ int hashid;
+
+ hashid = thread & HASH_MASK;
+
+ for (ti = th_info_hash[hashid]; ti; ti = ti->next) {
+ if (ti->thread == thread)
+ ti->waited = 1;
}
- }
-
- if (!map) /* look for invalid entries that I can reuse*/
- {
- for (i = 0, map = 0; !map && i < total_threads; i++)
- {
- if (mapptr[i].valid == 0 )
- map = &mapptr[i]; /* Reuse this invalid entry */
- if ((filter_mode & (NETWORK_FILTER | FILESYS_FILTER)) && fdmapptr)
- {
- fdmap = &fdmapptr[i];
- }
+}
+
+
+void read_command_map()
+{
+ size_t size;
+ int i;
+ int total_threads = 0;
+ kd_threadmap *mapptr = 0;
+
+ delete_all_map_entries();
+
+ if (!RAW_flag) {
+
+ total_threads = bufinfo.nkdthreads;
+ size = bufinfo.nkdthreads * sizeof(kd_threadmap);
+
+ if (size) {
+ if ((mapptr = (kd_threadmap *) malloc(size))) {
+ int mib[6];
+
+ bzero (mapptr, size);
+ /*
+ * Now read the threadmap
+ */
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_KDEBUG;
+ mib[2] = KERN_KDTHRMAP;
+ mib[3] = 0;
+ mib[4] = 0;
+ mib[5] = 0; /* no flags */
+
+ if (sysctl(mib, 3, mapptr, &size, NULL, 0) < 0) {
+ /*
+ * This is not fatal -- just means I cant map command strings
+ */
+ free(mapptr);
+ return;
+ }
+ }
+ }
+ } else {
+ RAW_header header;
+ off_t offset;
+
+ RAW_fd = open(RAW_file, O_RDONLY);
+
+ if (RAW_fd < 0) {
+ perror("Can't open RAW file");
+ exit(1);
+ }
+ if (read(RAW_fd, &header, sizeof(RAW_header)) != sizeof(RAW_header)) {
+ perror("read failed");
+ exit(2);
+ }
+ if (header.version_no != RAW_VERSION1) {
+ header.version_no = RAW_VERSION0;
+ header.TOD_secs = time((long *)0);
+ header.TOD_usecs = 0;
+
+ lseek(RAW_fd, (off_t)0, SEEK_SET);
+
+ if (read(RAW_fd, &header.thread_count, sizeof(int)) != sizeof(int)) {
+ perror("read failed");
+ exit(2);
+ }
+ }
+ sample_TOD_secs = header.TOD_secs;
+ sample_TOD_usecs = header.TOD_usecs;
+
+ total_threads = header.thread_count;
+ size = total_threads * sizeof(kd_threadmap);
+
+ if (size) {
+ if ((mapptr = (kd_threadmap *) malloc(size))) {
+ bzero (mapptr, size);
+
+ if (read(RAW_fd, mapptr, size) != size) {
+ free(mapptr);
+ return;
+ }
+ }
+ }
+ if (header.version_no != RAW_VERSION0) {
+ offset = lseek(RAW_fd, (off_t)0, SEEK_CUR);
+ offset = (offset + (4095)) & ~4095;
+
+ lseek(RAW_fd, offset, SEEK_SET);
+ }
}
- }
-
- if (!map)
- {
- /*
- * If reach here, then this is a new thread and
- * there are no invalid entries to reuse
- * Double the size of the thread map table.
- */
- n = total_threads * 2;
- mapptr = (kd_threadmap *) realloc(mapptr, n * sizeof(kd_threadmap));
- bzero(&mapptr[total_threads], total_threads*sizeof(kd_threadmap));
- map = &mapptr[total_threads];
-
- if ((filter_mode & (NETWORK_FILTER | FILESYS_FILTER)) && fdmapptr)
- {
- fdmapptr = (fd_threadmap *)realloc(fdmapptr, n * sizeof(fd_threadmap));
- bzero(&fdmapptr[total_threads], total_threads*sizeof(fd_threadmap));
- fdmap = &fdmapptr[total_threads];
+ for (i = 0; i < total_threads; i++)
+ create_map_entry(mapptr[i].thread, mapptr[i].valid, &mapptr[i].command[0]);
+
+ free(mapptr);
+}
+
+
+void delete_all_map_entries()
+{
+ threadmap_t tme = 0;
+ threadmap_t tme_next = 0;
+ int i;
+
+ for (i = 0; i < HASH_SIZE; i++) {
+
+ for (tme = threadmap_hash[i]; tme; tme = tme_next) {
+ if (tme->tm_setptr)
+ free(tme->tm_setptr);
+ tme_next = tme->tm_next;
+ tme->tm_next = threadmap_freelist;
+ threadmap_freelist = tme;
+ }
+ threadmap_hash[i] = 0;
}
-
- total_threads = n;
- }
-
- map->valid = 1;
- map->thread = thread;
- /*
- * The trace entry that returns the command name will hold
- * at most, MAXCOMLEN chars, and in that case, is not
- * guaranteed to be null terminated.
- */
- (void)strncpy (map->command, command, MAXCOMLEN);
- map->command[MAXCOMLEN] = '\0';
-
- if (fdmap)
- {
- fdmap->fd_valid = 1;
- fdmap->fd_thread = thread;
- if (fdmap->fd_setptr)
- {
- free(fdmap->fd_setptr);
- fdmap->fd_setptr = (unsigned long *)0;
+}
+
+
+void create_map_entry(uintptr_t thread, int pid, char *command)
+{
+ threadmap_t tme;
+ int hashid;
+
+ if ((tme = threadmap_freelist))
+ threadmap_freelist = tme->tm_next;
+ else
+ tme = (threadmap_t)malloc(sizeof(struct threadmap));
+
+ tme->tm_thread = thread;
+ tme->tm_setsize = 0;
+ tme->tm_setptr = 0;
+
+ (void)strncpy (tme->tm_command, command, MAXCOMLEN);
+ tme->tm_command[MAXCOMLEN] = '\0';
+
+ hashid = thread & HASH_MASK;
+
+ tme->tm_next = threadmap_hash[hashid];
+ threadmap_hash[hashid] = tme;
+
+ if (pid != 0 && pid != 1) {
+ if (!strncmp(command, "LaunchCFMA", 10))
+ (void)get_real_command_name(pid, tme->tm_command, MAXCOMLEN);
}
- fdmap->fd_setsize = 0;
- }
+}
- if (pid == 0 || pid == 1)
- return;
- else if (!strncmp(map->command, "LaunchCFMA", 10))
- (void)get_real_command_name(pid, map->command, sizeof(map->command));
+
+threadmap_t
+find_map_entry(uintptr_t thread)
+{
+ threadmap_t tme;
+ int hashid;
+
+ hashid = thread & HASH_MASK;
+
+ for (tme = threadmap_hash[hashid]; tme; tme = tme->tm_next) {
+ if (tme->tm_thread == thread)
+ return (tme);
+ }
+ return (0);
}
-kd_threadmap *find_thread_map(int thread)
+void
+delete_map_entry(uintptr_t thread)
{
- int i;
- kd_threadmap *map;
-
- if (!mapptr)
- return((kd_threadmap *)0);
-
- for (i = 0; i < total_threads; i++)
- {
- map = &mapptr[i];
- if (map->valid && ((int)map->thread == thread))
- {
- return(map);
+ threadmap_t tme = 0;
+ threadmap_t tme_prev;
+ int hashid;
+
+ hashid = thread & HASH_MASK;
+
+ if ((tme = threadmap_hash[hashid])) {
+ if (tme->tm_thread == thread)
+ threadmap_hash[hashid] = tme->tm_next;
+ else {
+ tme_prev = tme;
+
+ for (tme = tme->tm_next; tme; tme = tme->tm_next) {
+ if (tme->tm_thread == thread) {
+ tme_prev->tm_next = tme->tm_next;
+ break;
+ }
+ tme_prev = tme;
+ }
+ }
+ if (tme) {
+ if (tme->tm_setptr)
+ free(tme->tm_setptr);
+
+ tme->tm_next = threadmap_freelist;
+ threadmap_freelist = tme;
+ }
}
- }
- return ((kd_threadmap *)0);
}
-fd_threadmap *find_fd_thread_map(int thread)
+
+void
+fs_usage_fd_set(uintptr_t thread, unsigned int fd)
{
- int i;
- fd_threadmap *fdmap = 0;
-
- if (!fdmapptr)
- return((fd_threadmap *)0);
-
- for (i = 0; i < total_threads; i++)
- {
- fdmap = &fdmapptr[i];
- if (fdmap->fd_valid && ((int)fdmap->fd_thread == thread))
- {
- return(fdmap);
+ threadmap_t tme;
+
+ if ((tme = find_map_entry(thread)) == 0)
+ return;
+ /*
+ * If the map is not allocated, then now is the time
+ */
+ if (tme->tm_setptr == (unsigned long *)0) {
+ if ((tme->tm_setptr = (unsigned long *)malloc(FS_USAGE_NFDBYTES(FS_USAGE_FD_SETSIZE))) == 0)
+ return;
+
+ tme->tm_setsize = FS_USAGE_FD_SETSIZE;
+ bzero(tme->tm_setptr, (FS_USAGE_NFDBYTES(FS_USAGE_FD_SETSIZE)));
+ }
+ /*
+ * If the map is not big enough, then reallocate it
+ */
+ while (tme->tm_setsize <= fd) {
+ int n;
+
+ n = tme->tm_setsize * 2;
+ tme->tm_setptr = (unsigned long *)realloc(tme->tm_setptr, (FS_USAGE_NFDBYTES(n)));
+
+ bzero(&tme->tm_setptr[(tme->tm_setsize/FS_USAGE_NFDBITS)], (FS_USAGE_NFDBYTES(tme->tm_setsize)));
+ tme->tm_setsize = n;
}
- }
- return ((fd_threadmap *)0);
+ /*
+ * set the bit
+ */
+ tme->tm_setptr[fd/FS_USAGE_NFDBITS] |= (1 << ((fd) % FS_USAGE_NFDBITS));
}
+/*
+ * Return values:
+ * 0 : File Descriptor bit is not set
+ * 1 : File Descriptor bit is set
+ */
+int
+fs_usage_fd_isset(uintptr_t thread, unsigned int fd)
+{
+ threadmap_t tme;
+ int ret = 0;
+
+ if ((tme = find_map_entry(thread))) {
+ if (tme->tm_setptr && fd < tme->tm_setsize)
+ ret = tme->tm_setptr[fd/FS_USAGE_NFDBITS] & (1 << (fd % FS_USAGE_NFDBITS));
+ }
+ return (ret);
+}
+
+
void
-kill_thread_map(int thread)
+fs_usage_fd_clear(uintptr_t thread, unsigned int fd)
{
- kd_threadmap *map;
- fd_threadmap *fdmap;
-
- if (thread == last_thread)
- map_is_the_same = 0;
-
- if ((map = find_thread_map(thread))) {
- map->valid = 0;
- map->thread = 0;
- map->command[0] = '\0';
- }
-
- if ((filter_mode & (NETWORK_FILTER | FILESYS_FILTER)))
- {
- if ((fdmap = find_fd_thread_map(thread)))
- {
- fdmap->fd_valid = 0;
- fdmap->fd_thread = 0;
- if (fdmap->fd_setptr)
- {
- free (fdmap->fd_setptr);
- fdmap->fd_setptr = (unsigned long *)0;
- }
- fdmap->fd_setsize = 0;
- }
- }
+ threadmap_t tme;
+
+ if ((tme = find_map_entry(thread))) {
+ if (tme->tm_setptr && fd < tme->tm_setsize)
+ tme->tm_setptr[fd/FS_USAGE_NFDBITS] &= ~(1 << (fd % FS_USAGE_NFDBITS));
+ }
}
+
+
void
-argtopid(str)
- char *str;
+argtopid(char *str)
{
char *cp;
int ret;
int i;
ret = (int)strtol(str, &cp, 10);
+
if (cp == str || *cp) {
- /* Assume this is a command string and find matching pids */
+ /*
+ * Assume this is a command string and find matching pids
+ */
if (!kp_buffer)
find_proc_names();
- for (i=0; i < kp_nentries && num_of_pids < (MAX_PIDS - 1); i++) {
- if(kp_buffer[i].kp_proc.p_stat == 0)
- continue;
- else {
- if(!strncmp(str, kp_buffer[i].kp_proc.p_comm,
- sizeof(kp_buffer[i].kp_proc.p_comm) -1))
- pids[num_of_pids++] = kp_buffer[i].kp_proc.p_pid;
- }
+ for (i = 0; i < kp_nentries && num_of_pids < (MAX_PIDS - 1); i++) {
+ if (kp_buffer[i].kp_proc.p_stat == 0)
+ continue;
+ else {
+ if (!strncmp(str, kp_buffer[i].kp_proc.p_comm,
+ sizeof(kp_buffer[i].kp_proc.p_comm) -1))
+ pids[num_of_pids++] = kp_buffer[i].kp_proc.p_pid;
+ }
}
}
else if (num_of_pids < (MAX_PIDS - 1))
pids[num_of_pids++] = ret;
-
- return;
}
-char *lookup_name(uint64_t user_addr)
+void
+lookup_name(uint64_t user_addr, char **type, char **name)
{
- register int i;
- register int start, last;
+ int i;
+ int start, last;
- if (numFrameworks && ((user_addr >= framework32.b_address && user_addr < framework32.e_address) ||
- (user_addr >= framework64.b_address && user_addr < framework64.e_address))) {
-
- start = 0;
- last = numFrameworks;
+ *name = NULL;
+ *type = NULL;
- for (i = numFrameworks / 2; i >= 0 && i < numFrameworks; ) {
+ if (numFrameworks) {
- if (user_addr >= frameworkInfo[i].b_address && user_addr < frameworkInfo[i].e_address)
- return(frameworkInfo[i].name);
+ if ((user_addr >= framework32.b_address && user_addr < framework32.e_address) ||
+ (user_addr >= framework64.b_address && user_addr < framework64.e_address)) {
+
+ start = 0;
+ last = numFrameworks;
- if (user_addr >= frameworkInfo[i].b_address) {
- start = i;
- i = start + ((last - i) / 2);
- } else {
- last = i;
- i = start + ((i - start) / 2);
+ for (i = numFrameworks / 2; start < last; i = start + ((last - start) / 2)) {
+ if (user_addr > frameworkInfo[i].e_address)
+ start = i+1;
+ else
+ last = i;
+ }
+ if (start < numFrameworks &&
+ user_addr >= frameworkInfo[start].b_address && user_addr < frameworkInfo[start].e_address) {
+ *type = frameworkType[frameworkInfo[start].r_type];
+ *name = frameworkInfo[start].name;
}
}
}
- return (0);
}
*/
static int compareFrameworkAddress(const void *aa, const void *bb)
{
- LibraryInfo *a = (LibraryInfo *)aa;
- LibraryInfo *b = (LibraryInfo *)bb;
+ LibraryInfo *a = (LibraryInfo *)aa;
+ LibraryInfo *b = (LibraryInfo *)bb;
- if (a->b_address < b->b_address) return -1;
- if (a->b_address == b->b_address) return 0;
- return 1;
+ if (a->b_address < b->b_address) return -1;
+ if (a->b_address == b->b_address) return 0;
+ return 1;
}
int scanline(char *inputstring, char **argv, int maxtokens)
{
- int n = 0;
- char **ap = argv, *p, *val;
-
- for (p = inputstring; n < maxtokens && p != NULL; )
- {
- while ((val = strsep(&p, " \t")) != NULL && *val == '\0');
- *ap++ = val;
- n++;
- }
- *ap = 0;
- return n;
-}
+ int n = 0;
+ char **ap = argv, *p, *val;
+ for (p = inputstring; n < maxtokens && p != NULL; ) {
-int ReadSharedCacheMap(const char *path, LibraryRange *lr)
-{
- char buf[1024];
+ while ((val = strsep(&p, " \t")) != NULL && *val == '\0');
- FILE *fd;
- uint64_t b_frameworkAddress, b_frameworkDataAddress;
- uint64_t e_frameworkAddress, e_frameworkDataAddress;
- char frameworkName[256];
- char *tokens[64];
- int ntokens;
- char *substring,*ptr;
+ *ap++ = val;
+ n++;
+ }
+ *ap = 0;
+
+ return n;
+}
+int ReadSharedCacheMap(const char *path, LibraryRange *lr, char *linkedit_name)
+{
+ uint64_t b_address, e_address;
+ char buf[1024];
+ char *fnp;
+ FILE *fd;
+ char frameworkName[256];
+ char *tokens[64];
+ int ntokens;
+ int type;
+ int linkedit_found = 0;
+ char *substring, *ptr;
+
bzero(buf, sizeof(buf));
bzero(tokens, sizeof(tokens));
lr->b_address = 0;
lr->e_address = 0;
-
if ((fd = fopen(path, "r")) == 0)
- {
return 0;
- }
+
while (fgets(buf, 1023, fd)) {
if (strncmp(buf, "mapping", 7))
break;
frameworkName[0] = 0;
for (;;) {
- b_frameworkAddress = 0;
- b_frameworkDataAddress = 0;
- e_frameworkAddress = 0;
- e_frameworkDataAddress = 0;
-
/*
* Extract lib name from path name
*/
/*
* There is a ".": name is whatever is between the "/" around the "."
*/
- while ( *substring != '/') { /* find "/" before "." */
+ while ( *substring != '/') /* find "/" before "." */
substring--;
- }
substring++;
+
strncpy(frameworkName, substring, 256); /* copy path from "/" */
frameworkName[255] = 0;
substring = frameworkName;
ptr = buf;
substring = ptr;
- while (*ptr)
- {
+ while (*ptr) {
if (*ptr == '/')
substring = ptr + 1;
ptr++;
strncpy(frameworkName, substring, 256);
frameworkName[255] = 0;
}
- while (fgets(buf, 1023, fd) && numFrameworks < (MAXINDEX - 2))
- {
+ fnp = (char *)malloc(strlen(frameworkName) + 1);
+ strcpy(fnp, frameworkName);
+
+ while (fgets(buf, 1023, fd) && numFrameworks < (MAXINDEX - 2)) {
/*
* Get rid of EOL
*/
if (ntokens < 4)
continue;
- if (strncmp(tokens[0], "__TEXT", 6) == 0) {
- b_frameworkAddress = strtoull(tokens[1], 0, 16);
- e_frameworkAddress = strtoull(tokens[3], 0, 16);
- } else if (strncmp(tokens[0], "__DATA", 6) == 0) {
- b_frameworkDataAddress = strtoull(tokens[1], 0, 16);
- e_frameworkDataAddress = strtoull(tokens[3], 0, 16);
- } else if (strncmp(tokens[0], "__LINKEDIT", 10) == 0)
- break;
- }
- /*
- * Make sure that we have 2 addresses
- */
- if (b_frameworkAddress && b_frameworkDataAddress) {
-
- frameworkInfo[numFrameworks].b_address = b_frameworkAddress;
- frameworkInfo[numFrameworks].e_address = e_frameworkAddress;
+ if (strncmp(tokens[0], "__TEXT", 6) == 0)
+ type = TEXT_R;
+ else if (strncmp(tokens[0], "__DATA", 6) == 0)
+ type = DATA_R;
+ else if (strncmp(tokens[0], "__OBJC", 6) == 0)
+ type = OBJC_R;
+ else if (strncmp(tokens[0], "__IMPORT", 8) == 0)
+ type = IMPORT_R;
+ else if (strncmp(tokens[0], "__UNICODE", 9) == 0)
+ type = UNICODE_R;
+ else if (strncmp(tokens[0], "__IMAGE", 7) == 0)
+ type = IMAGE_R;
+ else if (strncmp(tokens[0], "__LINKEDIT", 10) == 0)
+ type = LINKEDIT_R;
+ else
+ type = -1;
- frameworkInfo[numFrameworks+1].b_address = b_frameworkDataAddress;
- frameworkInfo[numFrameworks+1].e_address = e_frameworkDataAddress;
+ if (type == LINKEDIT_R && linkedit_found)
+ break;
- frameworkInfo[numFrameworks].name = (char *)malloc(strlen(frameworkName) + 1);
- strcpy(frameworkInfo[numFrameworks].name, frameworkName);
- frameworkInfo[numFrameworks+1].name = frameworkInfo[numFrameworks].name;
+ if (type != -1) {
+ b_address = strtoull(tokens[1], 0, 16);
+ e_address = strtoull(tokens[3], 0, 16);
- numFrameworks += 2;
+ frameworkInfo[numFrameworks].b_address = b_address;
+ frameworkInfo[numFrameworks].e_address = e_address;
+ frameworkInfo[numFrameworks].r_type = type;
+
+ if (type == LINKEDIT_R) {
+ frameworkInfo[numFrameworks].name = linkedit_name;
+ linkedit_found = 1;
+ } else
+ frameworkInfo[numFrameworks].name = fnp;
#if 0
- printf("%s: %qx-%qx %qx-%qx\n", frameworkName, b_frameworkAddress, e_frameworkAddress, b_frameworkDataAddress, e_frameworkDataAddress);
+ printf("%s(%d): %qx-%qx\n", frameworkInfo[numFrameworks].name, type, b_address, e_address);
#endif
- if (lr->b_address == 0)
- lr->b_address = b_frameworkAddress;
-
- if (b_frameworkAddress < lr->b_address)
- lr->b_address = b_frameworkAddress;
+ if (lr->b_address == 0 || b_address < lr->b_address)
+ lr->b_address = b_address;
- if (b_frameworkDataAddress < lr->b_address)
- lr->b_address = b_frameworkDataAddress;
+ if (lr->e_address == 0 || e_address > lr->e_address)
+ lr->e_address = e_address;
- if (e_frameworkAddress > lr->e_address)
- lr->e_address = e_frameworkAddress;
-
- if (e_frameworkDataAddress > lr->e_address)
- lr->e_address = e_frameworkDataAddress;
+ numFrameworks++;
+ }
+ if (type == LINKEDIT_R)
+ break;
}
if (fgets(buf, 1023, fd) == 0)
break;
}
fclose(fd);
+#if 0
+ printf("%s range, %qx-%qx\n", path, lr->b_address, lr->e_address);
+#endif
return 1;
}
}
-struct diskio *insert_diskio(int type, int bp, int dev, int blkno, int io_size, int thread, double curtime)
+struct diskio *insert_diskio(int type, int bp, int dev, int blkno, int io_size, uintptr_t thread, double curtime)
{
- register struct diskio *dio;
- register kd_threadmap *map;
-
- if ((dio = free_diskios))
- free_diskios = dio->next;
- else {
- if ((dio = (struct diskio *)malloc(sizeof(struct diskio))) == NULL)
- return (NULL);
- }
- dio->prev = NULL;
+ struct diskio *dio;
+ threadmap_t tme;
- dio->type = type;
- dio->bp = bp;
- dio->dev = dev;
- dio->blkno = blkno;
- dio->iosize = io_size;
- dio->issued_time = curtime;
- dio->issuing_thread = thread;
+ if ((dio = free_diskios))
+ free_diskios = dio->next;
+ else {
+ if ((dio = (struct diskio *)malloc(sizeof(struct diskio))) == NULL)
+ return (NULL);
+ }
+ dio->prev = NULL;
- if ((map = find_thread_map(thread)))
- {
- strncpy(dio->issuing_command, map->command, MAXCOMLEN);
- dio->issuing_command[MAXCOMLEN-1] = '\0';
- }
- else
- strcpy(dio->issuing_command, "");
+ dio->type = type;
+ dio->bp = bp;
+ dio->dev = dev;
+ dio->blkno = blkno;
+ dio->iosize = io_size;
+ dio->issued_time = curtime;
+ dio->issuing_thread = thread;
+
+ dio->bc_info = 0x0;
+
+ if ((tme = find_map_entry(thread))) {
+ strncpy(dio->issuing_command, tme->tm_command, MAXCOMLEN);
+ dio->issuing_command[MAXCOMLEN-1] = '\0';
+ } else
+ strcpy(dio->issuing_command, "");
- dio->next = busy_diskios;
- if (dio->next)
- dio->next->prev = dio;
- busy_diskios = dio;
+ dio->next = busy_diskios;
+ if (dio->next)
+ dio->next->prev = dio;
+ busy_diskios = dio;
- return (dio);
+ return (dio);
+}
+
+struct diskio *find_diskio(int bp) {
+ struct diskio *dio;
+
+ for (dio = busy_diskios; dio; dio = dio->next) {
+ if (dio->bp == bp)
+ return (dio);
+ }
+
+ return NULL;
}
-struct diskio *complete_diskio(int bp, int io_errno, int resid, int thread, double curtime)
+struct diskio *complete_diskio(int bp, int io_errno, int resid, uintptr_t thread, double curtime)
{
- register struct diskio *dio;
-
- for (dio = busy_diskios; dio; dio = dio->next) {
- if (dio->bp == bp) {
-
- if (dio == busy_diskios) {
- if ((busy_diskios = dio->next))
- dio->next->prev = NULL;
- } else {
- if (dio->next)
- dio->next->prev = dio->prev;
- dio->prev->next = dio->next;
- }
- dio->iosize -= resid;
- dio->io_errno = io_errno;
- dio->completed_time = curtime;
- dio->completion_thread = thread;
-
- return (dio);
- }
- }
- return ((struct diskio *)0);
+ struct diskio *dio;
+
+ if ((dio = find_diskio(bp)) == NULL) return NULL;
+
+ if (dio == busy_diskios) {
+ if ((busy_diskios = dio->next))
+ dio->next->prev = NULL;
+ } else {
+ if (dio->next)
+ dio->next->prev = dio->prev;
+ dio->prev->next = dio->next;
+ }
+
+ dio->iosize -= resid;
+ dio->io_errno = io_errno;
+ dio->completed_time = curtime;
+ dio->completion_thread = thread;
+
+ return dio;
}
void free_diskio(struct diskio *dio)
{
- dio->next = free_diskios;
- free_diskios = dio;
+ dio->next = free_diskios;
+ free_diskios = dio;
}
void print_diskio(struct diskio *dio)
{
- register char *p;
-
- switch (dio->type) {
-
- case P_RdMeta:
- p = " RdMeta";
- break;
- case P_WrMeta:
- p = " WrMeta";
- break;
- case P_RdData:
- p = " RdData";
- break;
- case P_WrData:
- p = " WrData";
- break;
- case P_PgIn:
- p = " PgIn";
- break;
- case P_PgOut:
- p = " PgOut";
- break;
- case P_RdMetaAsync:
- p = " RdMeta[async]";
- break;
- case P_WrMetaAsync:
- p = " WrMeta[async]";
- break;
- case P_RdDataAsync:
- p = " RdData[async]";
- break;
- case P_WrDataAsync:
- p = " WrData[async]";
- break;
- case P_PgInAsync:
- p = " PgIn[async]";
- break;
- case P_PgOutAsync:
- p = " PgOut[async]";
- break;
- default:
- p = " ";
- break;
- }
- if (check_filter_mode(NULL, dio->type, 0, 0, p))
- format_print(NULL, p, dio->issuing_thread, dio->type, 0, 0, 0, 0, FMT_DISKIO, dio->completed_time, dio->issued_time, 1, "", dio);
+ char *p = NULL;
+ int len = 0;
+ int type;
+ int format = FMT_DISKIO;
+ char buf[64];
+
+ type = dio->type;
+ dio->is_meta = 0;
+
+ if ((type & P_CS_Class) == P_CS_Class) {
+
+ switch (type) {
+
+ case P_CS_ReadChunk:
+ p = " RdChunkCS";
+ len = 13;
+ format = FMT_DISKIO_CS;
+ break;
+ case P_CS_WriteChunk:
+ p = " WrChunkCS";
+ len = 13;
+ format = FMT_DISKIO_CS;
+ break;
+ case P_CS_MetaRead:
+ p = " RdMetaCS";
+ len = 10;
+ format = FMT_DISKIO_CS;
+ break;
+ case P_CS_MetaWrite:
+ p = " WrMetaCS";
+ len = 10;
+ format = FMT_DISKIO_CS;
+ break;
+ case P_CS_TransformRead:
+ p = " RdBgTfCS";
+ len = 10;
+ break;
+ case P_CS_TransformWrite:
+ p = " WrBgTfCS";
+ len = 10;
+ break;
+ case P_CS_MigrationRead:
+ p = " RdBgMigrCS";
+ len = 12;
+ break;
+ case P_CS_MigrationWrite:
+ p = " WrBgMigrCS";
+ len = 12;
+ break;
+ }
+ strncpy(buf, p, len);
+ } else {
+
+ switch (type & P_DISKIO_TYPE) {
+
+ case P_RdMeta:
+ dio->is_meta = 1;
+ p = " RdMeta";
+ len = 8;
+ break;
+ case P_WrMeta:
+ dio->is_meta = 1;
+ p = " WrMeta";
+ len = 8;
+ break;
+ case P_RdData:
+ p = " RdData";
+ len = 8;
+ break;
+ case P_WrData:
+ p = " WrData";
+ len = 8;
+ break;
+ case P_PgIn:
+ p = " PgIn";
+ len = 6;
+ break;
+ case P_PgOut:
+ p = " PgOut";
+ len = 7;
+ break;
+ default:
+ p = " ";
+ len = 2;
+ break;
+ }
+ strncpy(buf, p, len);
+
+ buf[len++] = '[';
+
+ if (type & P_DISKIO_ASYNC)
+ buf[len++] = 'A';
+ else
+ buf[len++] = 'S';
+
+ if (type & P_DISKIO_NOCACHE)
+ buf[len++] = 'N';
+
+ int tier = (type & P_DISKIO_TIER_MASK) >> P_DISKIO_TIER_SHIFT;
+ if (tier > 0) {
+ buf[len++] = 'T';
+ if (tier > 0 && tier < 10)
+ buf[len++] = '0' + tier;
+ }
+
+ if (type & P_DISKIO_PASSIVE)
+ buf[len++] = 'P';
+
+
+ buf[len++] = ']';
+ }
+ buf[len] = 0;
+
+ if (check_filter_mode(NULL, type, 0, 0, buf))
+ format_print(NULL, buf, dio->issuing_thread, type, 0, 0, 0, 0, format, dio->completed_time, dio->issued_time, 1, "", dio);
}
void cache_disk_names()
{
- struct stat st;
- DIR *dirp = NULL;
- struct dirent *dir;
- struct diskrec *dnp;
+ struct stat st;
+ DIR *dirp = NULL;
+ struct dirent *dir;
+ struct diskrec *dnp;
- if ((dirp = opendir("/dev")) == NULL)
- return;
+ if ((dirp = opendir("/dev")) == NULL)
+ return;
- while ((dir = readdir(dirp)) != NULL) {
- char nbuf[MAXPATHLEN];
+ while ((dir = readdir(dirp)) != NULL) {
+ char nbuf[MAXPATHLEN];
- if (dir->d_namlen < 5 || strncmp("disk", dir->d_name, 4))
- continue;
- snprintf(nbuf, MAXPATHLEN, "%s/%s", "/dev", dir->d_name);
+ if (dir->d_namlen < 5 || strncmp("disk", dir->d_name, 4))
+ continue;
+
+ snprintf(nbuf, MAXPATHLEN, "%s/%s", "/dev", dir->d_name);
- if (stat(nbuf, &st) < 0)
- continue;
+ if (stat(nbuf, &st) < 0)
+ continue;
- if ((dnp = (struct diskrec *)malloc(sizeof(struct diskrec))) == NULL)
- continue;
+ if ((dnp = (struct diskrec *)malloc(sizeof(struct diskrec))) == NULL)
+ continue;
- if ((dnp->diskname = (char *)malloc(dir->d_namlen + 1)) == NULL) {
- free(dnp);
- continue;
- }
- strncpy(dnp->diskname, dir->d_name, dir->d_namlen);
- dnp->diskname[dir->d_namlen] = 0;
- dnp->dev = st.st_rdev;
+ if ((dnp->diskname = (char *)malloc(dir->d_namlen + 1)) == NULL) {
+ free(dnp);
+ continue;
+ }
+ strncpy(dnp->diskname, dir->d_name, dir->d_namlen);
+ dnp->diskname[dir->d_namlen] = 0;
+ dnp->dev = st.st_rdev;
- dnp->next = disk_list;
- disk_list = dnp;
- }
- (void) closedir(dirp);
+ dnp->next = disk_list;
+ disk_list = dnp;
+ }
+ (void) closedir(dirp);
}
-char *find_disk_name(int dev)
+void recache_disk_names()
{
- struct diskrec *dnp;
-
- if (dev == NFS_DEV)
- return ("NFS");
-
- for (dnp = disk_list; dnp; dnp = dnp->next) {
- if (dnp->dev == dev)
- return (dnp->diskname);
- }
- return ("NOTFOUND");
-}
+ struct diskrec *dnp, *next_dnp;
-void
-fs_usage_fd_set(thread, fd)
- unsigned int thread;
- unsigned int fd;
-{
- int n;
- fd_threadmap *fdmap;
-
- if(!(fdmap = find_fd_thread_map(thread)))
- return;
-
- /* If the map is not allocated, then now is the time */
- if (fdmap->fd_setptr == (unsigned long *)0)
- {
- fdmap->fd_setptr = (unsigned long *)malloc(FS_USAGE_NFDBYTES(FS_USAGE_FD_SETSIZE));
- if (fdmap->fd_setptr)
- {
- fdmap->fd_setsize = FS_USAGE_FD_SETSIZE;
- bzero(fdmap->fd_setptr,(FS_USAGE_NFDBYTES(FS_USAGE_FD_SETSIZE)));
- }
- else
- return;
- }
-
- /* If the map is not big enough, then reallocate it */
- while (fdmap->fd_setsize <= fd)
- {
- fprintf(stderr, "reallocating bitmap for threadid %d, fd = %d, setsize = %d\n",
- thread, fd, fdmap->fd_setsize);
- n = fdmap->fd_setsize * 2;
- fdmap->fd_setptr = (unsigned long *)realloc(fdmap->fd_setptr, (FS_USAGE_NFDBYTES(n)));
- bzero(&fdmap->fd_setptr[(fdmap->fd_setsize/FS_USAGE_NFDBITS)], (FS_USAGE_NFDBYTES(fdmap->fd_setsize)));
- fdmap->fd_setsize = n;
- }
-
- /* set the bit */
- fdmap->fd_setptr[fd/FS_USAGE_NFDBITS] |= (1 << ((fd) % FS_USAGE_NFDBITS));
-
- return;
-}
+ for (dnp = disk_list; dnp; dnp = next_dnp) {
+ next_dnp = dnp->next;
-/*
- Return values:
- 0 : File Descriptor bit is not set
- 1 : File Descriptor bit is set
-*/
-
-int
-fs_usage_fd_isset(thread, fd)
- unsigned int thread;
- unsigned int fd;
-{
- int ret = 0;
- fd_threadmap *fdmap;
+ free(dnp->diskname);
+ free(dnp);
+ }
+ disk_list = NULL;
- if(!(fdmap = find_fd_thread_map(thread)))
- return(ret);
+ cache_disk_names();
+}
- if (fdmap->fd_setptr == (unsigned long *)0)
- return (ret);
- if (fd < fdmap->fd_setsize)
- ret = fdmap->fd_setptr[fd/FS_USAGE_NFDBITS] & (1 << (fd % FS_USAGE_NFDBITS));
+char *find_disk_name(int dev)
+{
+ struct diskrec *dnp;
+ int i;
- return (ret);
+ if (dev == NFS_DEV)
+ return ("NFS");
+
+ if (dev == CS_DEV)
+ return ("CS");
+
+ for (i = 0; i < 2; i++) {
+ for (dnp = disk_list; dnp; dnp = dnp->next) {
+ if (dnp->dev == dev)
+ return (dnp->diskname);
+ }
+ recache_disk_names();
+ }
+ return ("NOTFOUND");
}
-
-void
-fs_usage_fd_clear(thread, fd)
- unsigned int thread;
- unsigned int fd;
-{
- fd_threadmap *map;
- if (!(map = find_fd_thread_map(thread)))
- return;
- if (map->fd_setptr == (unsigned long *)0)
- return;
+char *generate_cs_disk_name(int dev, char *s)
+{
+ if (dev == -1)
+ return ("UNKNOWN");
+
+ sprintf(s, "disk%ds%d", (dev >> 16) & 0xffff, dev & 0xffff);
- /* clear the bit */
- if (fd < map->fd_setsize)
- map->fd_setptr[fd/FS_USAGE_NFDBITS] &= ~(1 << (fd % FS_USAGE_NFDBITS));
-
- return;
+ return (s);
}
+
/*
* ret = 1 means print the entry
* ret = 0 means don't print the entry
*/
+
+/*
+ * meaning of filter flags:
+ * cachehit turn on display of CACHE_HIT events (which are filtered out by default)
+ *
+ * exec show exec/posix_spawn
+ * pathname show events with a pathname and close()
+ * diskio show disk I/Os
+ * filesys show filesystem events
+ * network show network events
+ *
+ * filters may be combined; default is all filters on (except cachehit)
+ */
int
-check_filter_mode(struct th_info * ti, int type, int error, int retval, char *sc_name)
+check_filter_mode(struct th_info *ti, int type, int error, int retval, char *sc_name)
{
- int ret = 0;
- int network_fd_isset = 0;
- unsigned int fd;
-
- if (filter_mode == DEFAULT_DO_NOT_FILTER)
- return(1);
-
- if (sc_name[0] == 'C' && !strcmp (sc_name, "CACHE_HIT")) {
- if (filter_mode & CACHEHIT_FILTER)
- /* Do not print if cachehit filter is set */
- return(0);
- return(1);
- }
+ int ret = 0;
+ int network_fd_isset = 0;
+ unsigned int fd;
+
+ /* cachehit is special -- it's not on by default */
+ if (sc_name[0] == 'C' && !strcmp(sc_name, "CACHE_HIT")) {
+ if (show_cachehits) return 1;
+ else return 0;
+ }
+
+ if (filter_mode == DEFAULT_DO_NOT_FILTER)
+ return(1);
- if (filter_mode & EXEC_FILTER)
- {
- if (type == BSC_execve)
- return(1);
- return(0);
- }
+ if (filter_mode & DISKIO_FILTER) {
+ if ((type & P_DISKIO_MASK) == P_DISKIO)
+ return 1;
+ }
+
+ if (filter_mode & EXEC_FILTER) {
+ if (type == BSC_execve || type == BSC_posix_spawn)
+ return(1);
+ }
- if (filter_mode & PATHNAME_FILTER)
- {
- if (ti && ti->pathname[0])
+ if (filter_mode & PATHNAME_FILTER) {
+ if (ti && ti->lookups[0].pathname[0])
return(1);
- if (type == BSC_close || type == BSC_close_nocancel)
+ if (type == BSC_close || type == BSC_close_nocancel ||
+ type == BSC_guarded_close_np)
return(1);
- return(0);
- }
-
- if ( !(filter_mode & (FILESYS_FILTER | NETWORK_FILTER)))
- return(1);
+ }
-
- if (ti == (struct th_info *)0)
- {
- if (filter_mode & FILESYS_FILTER)
- ret = 1;
- else
- ret = 0;
- return(ret);
- }
-
- switch (type) {
- case BSC_close:
- case BSC_close_nocancel:
- fd = ti->arg1;
- network_fd_isset = fs_usage_fd_isset(ti->thread, fd);
- if (error == 0)
- {
- fs_usage_fd_clear(ti->thread,fd);
+ if (ti == (struct th_info *)0) {
+ if (filter_mode & FILESYS_FILTER)
+ return(1);
+ return(0);
}
-
- if (network_fd_isset)
- {
+
+ switch (type) {
+
+ case BSC_close:
+ case BSC_close_nocancel:
+ case BSC_guarded_close_np:
+ fd = ti->arg1;
+ network_fd_isset = fs_usage_fd_isset(ti->thread, fd);
+
+ if (error == 0)
+ fs_usage_fd_clear(ti->thread,fd);
+
+ if (network_fd_isset) {
+ if (filter_mode & NETWORK_FILTER)
+ ret = 1;
+ } else
+ if (filter_mode & FILESYS_FILTER)
+ ret = 1;
+ break;
+
+ case BSC_read:
+ case BSC_write:
+ case BSC_read_nocancel:
+ case BSC_write_nocancel:
+ /*
+ * we don't care about error in these cases
+ */
+ fd = ti->arg1;
+ network_fd_isset = fs_usage_fd_isset(ti->thread, fd);
+
+ if (network_fd_isset) {
+ if (filter_mode & NETWORK_FILTER)
+ ret = 1;
+ } else
+ if (filter_mode & FILESYS_FILTER)
+ ret = 1;
+ break;
+
+ case BSC_accept:
+ case BSC_accept_nocancel:
+ case BSC_socket:
+ fd = retval;
+
+ if (error == 0)
+ fs_usage_fd_set(ti->thread, fd);
if (filter_mode & NETWORK_FILTER)
- ret = 1;
- }
- else if (filter_mode & FILESYS_FILTER)
- ret = 1;
- break;
- case BSC_read:
- case BSC_write:
- case BSC_read_nocancel:
- case BSC_write_nocancel:
- /* we don't care about error in this case */
- fd = ti->arg1;
- network_fd_isset = fs_usage_fd_isset(ti->thread, fd);
- if (network_fd_isset)
- {
+ ret = 1;
+ break;
+
+ case BSC_recvfrom:
+ case BSC_sendto:
+ case BSC_recvmsg:
+ case BSC_sendmsg:
+ case BSC_connect:
+ case BSC_bind:
+ case BSC_listen:
+ case BSC_sendto_nocancel:
+ case BSC_recvfrom_nocancel:
+ case BSC_recvmsg_nocancel:
+ case BSC_sendmsg_nocancel:
+ case BSC_connect_nocancel:
+ fd = ti->arg1;
+
+ if (error == 0)
+ fs_usage_fd_set(ti->thread, fd);
if (filter_mode & NETWORK_FILTER)
- ret = 1;
- }
- else if (filter_mode & FILESYS_FILTER)
- ret = 1;
- break;
- case BSC_accept:
- case BSC_accept_nocancel:
- case BSC_socket:
- fd = retval;
- if (error == 0)
- fs_usage_fd_set(ti->thread, fd);
- if (filter_mode & NETWORK_FILTER)
- ret = 1;
- break;
- case BSC_recvfrom:
- case BSC_sendto:
- case BSC_recvmsg:
- case BSC_sendmsg:
- case BSC_connect:
- case BSC_bind:
- case BSC_listen:
- case BSC_sendto_nocancel:
- case BSC_recvfrom_nocancel:
- case BSC_recvmsg_nocancel:
- case BSC_sendmsg_nocancel:
- case BSC_connect_nocancel:
- fd = ti->arg1;
- if (error == 0)
- fs_usage_fd_set(ti->thread, fd);
- if (filter_mode & NETWORK_FILTER)
- ret = 1;
- break;
- case BSC_select:
- case BSC_select_nocancel:
- case BSC_socketpair:
- /* Cannot determine info about file descriptors */
- if (filter_mode & NETWORK_FILTER)
- ret = 1;
- break;
- case BSC_dup:
- case BSC_dup2:
- ret=0; /* We track these cases for fd state only */
- fd = ti->arg1; /* oldd */
- network_fd_isset = fs_usage_fd_isset(ti->thread, fd);
- if (error == 0 && network_fd_isset)
- {
- /* then we are duping a socket descriptor */
- fd = retval; /* the new fd */
- fs_usage_fd_set(ti->thread, fd);
- }
- break;
+ ret = 1;
+ break;
+
+ case BSC_select:
+ case BSC_select_nocancel:
+ case BSC_socketpair:
+ /*
+ * Cannot determine info about file descriptors
+ */
+ if (filter_mode & NETWORK_FILTER)
+ ret = 1;
+ break;
+
+ case BSC_dup:
+ case BSC_dup2:
+ /*
+ * We track these cases for fd state only
+ */
+ fd = ti->arg1;
+ network_fd_isset = fs_usage_fd_isset(ti->thread, fd);
- default:
- if (filter_mode & FILESYS_FILTER)
- ret = 1;
- break;
- }
+ if (error == 0 && network_fd_isset) {
+ /*
+ * then we are duping a socket descriptor
+ */
+ fd = retval; /* the new fd */
+ fs_usage_fd_set(ti->thread, fd);
+ }
+ break;
- return(ret);
+ default:
+ if (filter_mode & FILESYS_FILTER)
+ ret = 1;
+ break;
+ }
+
+ return(ret);
}
/*
void
init_arguments_buffer()
{
+ int mib[2];
+ size_t size;
- int mib[2];
- size_t size;
-
- mib[0] = CTL_KERN;
- mib[1] = KERN_ARGMAX;
- size = sizeof(argmax);
- if (sysctl(mib, 2, &argmax, &size, NULL, 0) == -1)
- return;
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_ARGMAX;
+ size = sizeof(argmax);
+ if (sysctl(mib, 2, &argmax, &size, NULL, 0) == -1)
+ return;
#if 1
- /* Hack to avoid kernel bug. */
- if (argmax > 8192) {
- argmax = 8192;
- }
+ /* Hack to avoid kernel bug. */
+ if (argmax > 8192) {
+ argmax = 8192;
+ }
#endif
-
- arguments = (char *)malloc(argmax);
-
- return;
+ arguments = (char *)malloc(argmax);
}
int
get_real_command_name(int pid, char *cbuf, int csize)
{
- /*
- * Get command and arguments.
- */
- char *cp;
- int mib[4];
- char *command_beg, *command, *command_end;
-
- if (cbuf == NULL) {
- return(0);
- }
-
- if (arguments)
- bzero(arguments, argmax);
- else
- return(0);
-
- /*
- * A sysctl() is made to find out the full path that the command
- * was called with.
- */
- mib[0] = CTL_KERN;
- mib[1] = KERN_PROCARGS;
- mib[2] = pid;
- mib[3] = 0;
-
- if (sysctl(mib, 3, arguments, (size_t *)&argmax, NULL, 0) < 0) {
- return(0);
- }
-
- /* Skip the saved exec_path. */
- for (cp = arguments; cp < &arguments[argmax]; cp++) {
- if (*cp == '\0') {
- /* End of exec_path reached. */
- break;
- }
- }
- if (cp == &arguments[argmax]) {
- return(0);
- }
-
- /* Skip trailing '\0' characters. */
- for (; cp < &arguments[argmax]; cp++) {
- if (*cp != '\0') {
- /* Beginning of first argument reached. */
- break;
+ /*
+ * Get command and arguments.
+ */
+ char *cp;
+ int mib[4];
+ char *command_beg, *command, *command_end;
+
+ if (cbuf == NULL)
+ return(0);
+
+ if (arguments)
+ bzero(arguments, argmax);
+ else
+ return(0);
+
+ /*
+ * A sysctl() is made to find out the full path that the command
+ * was called with.
+ */
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROCARGS2;
+ mib[2] = pid;
+ mib[3] = 0;
+
+ if (sysctl(mib, 3, arguments, (size_t *)&argmax, NULL, 0) < 0)
+ return(0);
+
+ /*
+ * Skip the saved exec_path
+ */
+ for (cp = arguments; cp < &arguments[argmax]; cp++) {
+ if (*cp == '\0') {
+ /*
+ * End of exec_path reached
+ */
+ break;
+ }
}
- }
- if (cp == &arguments[argmax]) {
- return(0);
- }
- command_beg = cp;
-
- /*
- * Make sure that the command is '\0'-terminated. This protects
- * against malicious programs; under normal operation this never
- * ends up being a problem..
- */
- for (; cp < &arguments[argmax]; cp++) {
- if (*cp == '\0') {
- /* End of first argument reached. */
- break;
+ if (cp == &arguments[argmax])
+ return(0);
+
+ /*
+ * Skip trailing '\0' characters
+ */
+ for (; cp < &arguments[argmax]; cp++) {
+ if (*cp != '\0') {
+ /*
+ * Beginning of first argument reached
+ */
+ break;
+ }
}
- }
- if (cp == &arguments[argmax]) {
- return(0);
- }
- command_end = command = cp;
-
- /* Get the basename of command. */
- for (command--; command >= command_beg; command--) {
- if (*command == '/') {
- command++;
- break;
+ if (cp == &arguments[argmax])
+ return(0);
+
+ command_beg = cp;
+ /*
+ * Make sure that the command is '\0'-terminated. This protects
+ * against malicious programs; under normal operation this never
+ * ends up being a problem..
+ */
+ for (; cp < &arguments[argmax]; cp++) {
+ if (*cp == '\0') {
+ /*
+ * End of first argument reached
+ */
+ break;
+ }
}
- }
+ if (cp == &arguments[argmax])
+ return(0);
- (void) strncpy(cbuf, (char *)command, csize);
- cbuf[csize-1] = '\0';
+ command_end = command = cp;
- return(1);
+ /*
+ * Get the basename of command
+ */
+ for (command--; command >= command_beg; command--) {
+ if (*command == '/') {
+ command++;
+ break;
+ }
+ }
+ (void) strncpy(cbuf, (char *)command, csize);
+ cbuf[csize-1] = '\0';
+
+ return(1);
}