*/
/*
-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 <sys/disk.h>
-#include <errno.h>
#import <mach/clock_types.h>
#import <mach/mach_time.h>
-#include <err.h>
-#include <libutil.h>
+
+
#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 {
LibraryInfo frameworkInfo[MAXINDEX];
int numFrameworks = 0;
-void lookup_name(uint64_t user_addr, char **type, char **name);
-
/*
- 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(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;
- int in_filemgr;
+ th_info_t next;
uintptr_t thread;
+ uintptr_t child_thread;
+
+ int in_filemgr;
+ int in_hfs_update;
int pid;
int type;
int arg1;
int arg6;
int arg7;
int arg8;
- uintptr_t child_thread;
int waited;
double stime;
+ uint64_t vnodeid;
+ char *nameptr;
uintptr_t *pathptr;
- uintptr_t pathname[NUMPARMS + 1]; /* add room for null terminator */
+ 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];
};
-#define MAX_THREADS 1024
-struct th_info th_state[MAX_THREADS];
-kd_threadmap *last_map = NULL;
-int last_thread = 0;
-int map_is_the_same = 0;
+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];
+};
+
+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];
+
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 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 *, uintptr_t, int, int, int, int, int, int, double, double, int, char *, struct diskio *);
-void enter_syscall_now(uintptr_t, int, kd_buf *, char *, double);
-void enter_syscall(uintptr_t, int, kd_buf *, char *, double);
-void exit_syscall(char *, uintptr_t, int, int, int, int, int, int, double);
-void extend_syscall(uintptr_t, int, kd_buf *);
-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();
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(uintptr_t);
-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 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 kill_thread_map(uintptr_t);
+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_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_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_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_MMAP 31
#define FMT_UMASK 32
#define FMT_SENDFILE 33
-#define FMT_SPEC_IOCTL 34
+#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_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_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;
-int num_cpus;
-
#define EVENT_BASE 60000
int num_events = EVENT_BASE;
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 */
- uintptr_t 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 = 99999999999.9;
+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;
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_name = "lstat_extended64";
break;
- case BSC_lstatv:
- bsd_syscalls[code].sc_name = "lstatv";
- break;
-
case BSC_link:
bsd_syscalls[code].sc_name = "link";
break;
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 = "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_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_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();
+
+ time_t stop_at_time = 0;
if (0 != reexec_to_match_kernel()) {
- fprintf(stderr, "Could not re-execute: %d\n", errno);
- exit(1);
+ 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:R:S:E:")) != EOF) {
+ while ((ch = getopt(argc, argv, "bewf:R:S:E:t:")) != EOF) {
switch(ch) {
else if (!strcmp(optarg, "filesys"))
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;
else if (!strcmp(optarg, "pathname"))
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;
* 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);
if (osa.sa_handler == SIG_DFL)
signal(SIGHUP, leave);
signal(SIGTERM, leave);
-
- /* grab the number of cpus */
- size_t len;
+ /*
+ * grab the number of cpus
+ */
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;
}
for (i = 0; i < num_of_pids; i++)
set_pidexclude(pids[i], 1);
}
-
- if (select_pid_mode && !one_good_pid)
- {
+ if (select_pid_mode && !one_good_pid) {
/*
- An attempt to restrict output to a given
- pid or command has failed. Exit gracefully
- */
+ * 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_tables();
- /* main loop */
-
- while (1) {
+ /*
+ * main loop
+ */
+ while (stop_at_time == 0 || last_time < stop_at_time) {
if (!RAW_flag)
usleep(1000 * usleep_ms);
}
}
+
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(uintptr_t 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(uintptr_t 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()
{
int i, count;
size_t needed;
uint32_t my_buffer_size = 0;
- void read_command_map();
- void create_map_entry();
- if (!RAW_flag) {
- /* Get kernel buffer information */
+ if (!RAW_flag)
get_bufinfo(&bufinfo);
- } else {
+ else
my_buffer_size = num_events * sizeof(kd_buf);
- }
+
if (need_new_map) {
read_command_map();
need_new_map = 0;
}
if (!RAW_flag) {
needed = bufinfo.nkdbufs * sizeof(kd_buf);
+
mib[0] = CTL_KERN;
mib[1] = KERN_KDEBUG;
mib[2] = KERN_KDREADTR;
if (bufinfo.flags & KDBG_WRAPPED) {
fprintf(stderr, "fs_usage: buffer overrun, events generated too quickly: %d\n", count);
- for (i = 0; i <= cur_max; i++) {
- th_state[i].thread = 0;
- th_state[i].pid = 0;
- th_state[i].pathptr = (uintptr_t *)NULL;
- th_state[i].pathname[0] = 0;
- }
- cur_max = 0;
- cur_start = 0;
+ delete_all_events();
+
need_new_map = 1;
- map_is_the_same = 0;
set_enable(0);
set_enable(1);
long long l_usecs;
int secs;
long curr_time;
- struct th_info *ti;
+ th_info_t ti;
struct diskio *dio;
now = kdbg_get_timestamp(&kd[i]);
- 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 (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_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 ((uintptr_t)sargptr >= (uintptr_t)&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 SPEC_ioctl:
- if (kd[i].arg2 == DKIOCSYNCHRONIZECACHE)
- exit_syscall("IOCTL", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, FMT_SPEC_IOCTL, (double)now);
- else {
- if ((ti = find_thread(thread, type))) {
- destroy_thread(ti);
- }
- }
- continue;
-
- case MACH_pageout:
- if (kd[i].arg2)
- exit_syscall("PAGE_OUT_ANON", thread, type, 0, kd[i].arg1, 0, 0, FMT_PGOUT, (double)now);
- else
- exit_syscall("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_syscall("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_syscall("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_syscall("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_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(uintptr_t 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 &&
- (!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 += ((long long)8 * (long long)3600 * (long long)1000000);
- } else
- l_usecs = (long long)(now / divisor);
- secs = l_usecs / 1000000;
- curr_time = bias_secs + secs;
+ 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;
+
+ ti->stime = now;
+ ti->arg1 = kd->arg1;
+ ti->arg2 = kd->arg2;
+ ti->arg3 = kd->arg3;
+ ti->arg4 = kd->arg4;
+
+ 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%lx, 0x%lx, 0x%lx)", (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, %#lx, 0x%lx, 0x%lx)\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 = (uintptr_t *)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(uintptr_t 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;
+ int index;
- if (type == MACH_pageout || type == MACH_vmfault || type == MSC_map_fd || type == SPEC_ioctl) {
- enter_syscall_now(thread, type, kd, name, now);
- return;
- }
- if ((type & CSC_MASK) == BSC_BASE) {
-
- 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(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, uintptr_t 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, uintptr_t 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;
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 = -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 += ((long long)8 * (long long)3600 * (long long)1000000);
- } else
+
+ 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;
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;
+ 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
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_FLOCK:
+ {
+ /*
+ * flock
+ */
+ 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:
{
/*
case FMT_IOCTL:
{
/*
- * fcntl
+ * ioctl
*/
if (arg1)
clen += printf(" F=%-3d[%3d]", ti->arg1, arg1);
break;
}
- case FMT_SPEC_IOCTL:
+ case FMT_IOCTL_SYNC:
{
/*
- * fcntl
+ * ioctl
+ */
+ clen += printf(" <DKIOCSYNCHRONIZECACHE> /dev/%s", find_disk_name(arg1));
+
+ break;
+ }
+
+ case FMT_IOCTL_UNMAP:
+ {
+ /*
+ * ioctl
*/
- clen += printf(" <DKIOCSYNCHRONIZECACHE> /dev/%s", find_disk_name(arg1));
+ 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;
}
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);
/*
* 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);
if (framework_name)
len = sprintf(&buf[0], " %s %s ", framework_type, framework_name);
- else if (*pathname != '\0')
+ 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;
+ hashid = blockno & VN_HASH_MASK;
+
+ for (mi = m_info_hash[hashid]; mi; mi = mi->m_next) {
+ if (mi->m_blkno == blockno)
+ return (mi->m_nameptr);
+ }
+ return ("");
+}
+
+
+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 (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);
+
+ 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 ("");
+}
+
+
+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);
+}
- mach_timebase_info(&mti);
+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;
+ }
+}
- divisor = ((double)mti.denom / (double)mti.numer) * 1000;
+
+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;
+ }
}
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;
-
- if (!RAW_flag) {
-
- 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;
- }
- }
- }
- } else {
- uint32_t count_of_names;
+ size_t size;
+ int i;
+ int total_threads = 0;
+ kd_threadmap *mapptr = 0;
- RAW_fd = open(RAW_file, O_RDONLY);
+ delete_all_map_entries();
- if (RAW_fd < 0) {
- perror("Can't open RAW file");
- exit(1);
- }
- if (read(RAW_fd, &count_of_names, sizeof(uint32_t)) != sizeof(uint32_t)) {
- perror("read of RAW file failed");
- exit(2);
- }
- total_threads = count_of_names;
- size = count_of_names * sizeof(kd_threadmap);
-
- if (size)
- {
- if ((mapptr = (kd_threadmap *) malloc(size)))
- {
- bzero (mapptr, size);
+ if (!RAW_flag) {
- if (read(RAW_fd, mapptr, size) != size) {
+ 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;
- free(mapptr);
- mapptr = 0;
- }
- }
- }
- }
- 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;
- }
+ RAW_fd = open(RAW_file, O_RDONLY);
- 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;
- }
+ 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);
+ }
}
- }
+ for (i = 0; i < total_threads; i++)
+ create_map_entry(mapptr[i].thread, mapptr[i].valid, &mapptr[i].command[0]);
+
+ free(mapptr);
+}
- /* 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_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;
}
- }
}
void create_map_entry(uintptr_t 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 (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;
- }
- }
- }
-
- 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];
- }
- }
- }
-
- 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];
- }
-
- 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;
+ 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;
- }
+}
+
+
+threadmap_t
+find_map_entry(uintptr_t thread)
+{
+ threadmap_t tme;
+ int hashid;
+
+ hashid = thread & HASH_MASK;
- if (pid == 0 || pid == 1)
- return;
- else if (!strncmp(map->command, "LaunchCFMA", 10))
- (void)get_real_command_name(pid, map->command, sizeof(map->command));
+ for (tme = threadmap_hash[hashid]; tme; tme = tme->tm_next) {
+ if (tme->tm_thread == thread)
+ return (tme);
+ }
+ return (0);
}
-kd_threadmap *find_thread_map(uintptr_t 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 && (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(uintptr_t 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 && (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)));
}
- }
- return ((fd_threadmap *)0);
+ /*
+ * 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;
+ }
+ /*
+ * 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(uintptr_t 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;
}
last = numFrameworks;
for (i = numFrameworks / 2; start < last; i = start + ((last - start) / 2)) {
- if (user_addr > frameworkInfo[i].e_address) {
+ if (user_addr > frameworkInfo[i].e_address)
start = i+1;
- } else {
+ else
last = i;
- }
}
if (start < numFrameworks &&
user_addr >= frameworkInfo[start].b_address && user_addr < frameworkInfo[start].e_address) {
*/
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; ) {
+
+ while ((val = strsep(&p, " \t")) != NULL && *val == '\0');
+
+ *ap++ = val;
+ n++;
+ }
+ *ap = 0;
+
+ return n;
}
lr->e_address = 0;
if ((fd = fopen(path, "r")) == 0)
- {
return 0;
- }
+
while (fgets(buf, 1023, fd)) {
if (strncmp(buf, "mapping", 7))
break;
/*
* 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++;
fnp = (char *)malloc(strlen(frameworkName) + 1);
strcpy(fnp, frameworkName);
- while (fgets(buf, 1023, fd) && numFrameworks < (MAXINDEX - 2))
- {
+ while (fgets(buf, 1023, fd) && numFrameworks < (MAXINDEX - 2)) {
/*
* Get rid of EOL
*/
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, 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)
{
- struct diskrec *dnp;
- int i;
+ struct diskrec *dnp;
+ int i;
- if (dev == NFS_DEV)
- return ("NFS");
+ if (dev == NFS_DEV)
+ return ("NFS");
- 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_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)));
+ 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();
}
- 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;
+ return ("NOTFOUND");
}
-/*
- 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;
-
- if(!(fdmap = find_fd_thread_map(thread)))
- return(ret);
- 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));
-
- return (ret);
-}
-
-void
-fs_usage_fd_clear(thread, fd)
- unsigned int thread;
- unsigned int fd;
+char *generate_cs_disk_name(int dev, char *s)
{
- fd_threadmap *map;
-
- if (!(map = find_fd_thread_map(thread)))
- return;
-
- if (map->fd_setptr == (unsigned long *)0)
- return;
+ 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);
+
+ 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;
- default:
- if (filter_mode & FILESYS_FILTER)
- ret = 1;
- break;
- }
+ default:
+ if (filter_mode & FILESYS_FILTER)
+ ret = 1;
+ break;
+ }
- return(ret);
+ 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_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);
- }
-
- /* 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);
}