/* * Files. */ #define BC_BOOT_PLAYLIST "/var/db/BootCache.playlist" #define BC_BOOT_FLAGFILE "/var/db/BootCache.flag" #define BC_BOOT_STATFILE "/tmp/BootCache.statistics" #define BC_BOOT_HISTFILE "/tmp/BootCache.history" #define BC_BOOT_LOGFILE "/tmp/BootCache.log" #define BC_CONTROL_TOOL "/usr/sbin/BootCacheControl" #define BC_KEXTUNLOAD "/sbin/kextunload" #define BC_BUNDLE_ID "com.apple.BootCache" /* * Command stucture, passed via sysctl. */ struct BC_command { /* magic number identifies the structure */ int bc_magic; #define BC_MAGIC_0 0x10102021 /* old version with DEV_BSIZE blocks */ #define BC_MAGIC_1 0x10102021 /* all disk addresses in bytes */ #define BC_MAGIC 0x10102021 /* added flags field to playlist entry */ /* opcode determines function of this command */ int bc_opcode; #define BC_OP_START 0x01 #define BC_OP_STOP 0x02 #define BC_OP_HISTORY 0x03 #define BC_OP_STATS 0x04 #define BC_OP_TAG 0x05 /* optional parameter */ int bc_param; /* user-space data buffer, use varies with opcode */ void *bc_data; size_t bc_length; }; #define BC_SYSCTL "kern.BootCache" /* * BC_OP_START - start the cache engine with an optional playlist. * * If bc_data is not NULL, it points to bc_length bytes of * BC_playlist_entry structures. * * bc_param is set to the blocksize for which the playlist has * been computed. */ /* * On-disk playlist header, also used in the preload case. */ struct BC_playlist_header { int ph_magic; #define PH_MAGIC_0 0xa1b2c3d4 /* old format with no blocksize */ #define PH_MAGIC_1 0xa1b2c3d5 /* blocksize, offsets in bytes */ #define PH_MAGIC 0xa1b2c3d6 /* added flags field */ int ph_entries; int ph_blocksize; }; /* * Playlist entries represent regions of disk to be cached. */ struct BC_playlist_entry { u_int64_t pce_offset; /* block address */ u_int64_t pce_length; /* size */ u_int32_t pce_flags; #define PCE_PREFETCH (1<<0) }; /* number of entries we copyin at a time */ #define BC_PLC_CHUNK 512 /* sanity check for the upper bound on number of entries */ #define BC_MAXENTRIES 100000 /* * BC_OP_STOP - stop the cache engine. * * The history list size (in bytes) is returned in bc_length. If the history * list was truncated, bc_length will be 0 and BC_OP_HISTORY must still be * called to clear the buffer. */ /* * BC_OP_HISTORY - copy out history and clear. * * The kernel's copy of the cache history is copied into the array of * BC_history_entry structures at bc_data. The cache must previously have been * stopped before calling this interface out. */ struct BC_history_entry { u_int64_t he_offset; /* data offset on device */ u_int64_t he_length; /* length of data */ int he_flags; #define BC_HE_MISS 0 /* read was not satisfied from cache */ #define BC_HE_HIT 1 /* read was satisfied from cache */ #define BC_HE_TAG 2 /* userland-set tag */ #define BC_HE_WRITE 3 /* write-through operation */ }; /* * BC_OP_STATS - return statistics. */ struct BC_statistics { /* device */ u_int ss_blocksize; /* underlying device bloksize */ /* readahead */ u_int ss_initiated_reads; /* read operations we initiated */ u_int ss_read_blocks; /* number of blocks read */ u_int ss_read_errors; /* read errors encountered */ u_int ss_error_discards; /* blocks discarded due to read errors */ struct timeval ss_cache_start; /* time reads & cache started */ struct timeval ss_pfetch_stop; /* time prefetch stopped */ struct timeval ss_read_stop; /* time reads stopped */ struct timeval ss_cache_stop; /* time cache stopped */ struct timeval ss_wait_time; /* total time spent blocked for blocks */ /* inbound strategy calls */ u_int ss_strategy_calls; /* total strategy calls we received */ u_int ss_strategy_nonread; /* strategy calls that were not reads */ u_int ss_strategy_bypassed; /* strategy calls we bypassed */ u_int ss_strategy_bypass_active; /* strategy calls we bypassed reading */ u_int ss_strategy_blocked; /* strategy calls that blocked */ u_int ss_strategy_stolen; /* aborts due to pages stolen while blocked */ /* extents */ u_int ss_total_extents; /* number of extents in the cache */ u_int ss_extent_lookups; /* number of extents searched for */ u_int ss_extent_hits; /* number of extents matched */ u_int ss_hit_blkmissing; /* cache hits not filled due to missing blocks */ /* block/page activity */ u_int ss_requested_blocks; u_int ss_hit_blocks; /* number of blocks vacated due to read hits */ u_int ss_write_discards; /* blocks discarded due to overwriting */ u_int ss_spurious_blocks; /* number of blocks not consumed */ u_int ss_spurious_pages; /* number of pages not consumed */ /* history activity */ u_int ss_history_clusters; /* number of allocated history clusters */ /* current status */ u_int ss_cache_flags; /* current cache flags */ }; #ifndef KERNEL /* * Support library functions. */ extern int BC_blocksize; extern int BC_read_playlist(const char *, struct BC_playlist_entry **, int *); extern int BC_write_playlist(const char *, const struct BC_playlist_entry *, int); extern int BC_merge_playlists(struct BC_playlist_entry **, int *, const struct BC_playlist_entry *, int); extern void BC_sort_playlist(struct BC_playlist_entry *, int); extern int BC_coalesce_playlist(struct BC_playlist_entry **, int *); extern int BC_fetch_statistics(struct BC_statistics **); extern int BC_convert_history(const struct BC_history_entry *, struct BC_playlist_entry **, int *); extern int BC_start(struct BC_playlist_entry *, int); extern int BC_stop(struct BC_history_entry **, int *); extern int BC_print_statistics(char *, struct BC_statistics *); extern int BC_print_history(char *, struct BC_history_entry *, int); extern int BC_tag_history(void); extern int BC_unload(void); #endif