When KMF_AUDIT is set for a cache, the kernel memory allocator maintains a log that records the recent history of its activity. This transaction log records bufctl_audit records. If the KMF_AUDIT and the KMF_CONTENTS flags are both set, the allocator generates a contents log that records portions of the actual contents of allocated and freed buffers. The structure and use of the contents log is outside the scope of this document. The transaction log is discussed in this section.
MDB provides several facilities for displaying the transaction log. The simplest is ::walk kmem_log, which prints out the transaction in the log as a series of bufctl_audit_t pointers:
> ::walk kmem_log 70128340 701282e0 70128280 70128220 701281c0 ... > 70128340$<bufctl_audit 0x70128340: next addr slab 70ac1d40 70bc4ea8 70bb7c00 0x7012834c: cache timestamp thread 70039428 e1bd7abe721 70aacde0 0x7012835c: lastlog contents stackdepth 701282e0 7018f340 4 0x70128368: kmem_cache_free+0x24 nfs3_sync+0x3c vfs_sync+0x84 syssync+4
A more elegant way to view the entire transaction log is by using the ::kmem_log command:
> ::kmem_log CPU ADDR BUFADDR TIMESTAMP THREAD 0 70128340 70bc4ea8 e1bd7abe721 70aacde0 0 701282e0 70bc4ea8 e1bd7aa86fa 70aacde0 0 70128280 70bc4ea8 e1bd7aa27dd 70aacde0 0 70128220 70bc4ea8 e1bd7a98a6e 70aacde0 0 701281c0 70d03738 e1bd7a8e3e0 70aacde0 ... 0 70127140 70cf78a0 e1bd78035ad 70aacde0 0 701270e0 709cf6c0 e1bd6d2573a 40033e60 0 70127080 70cedf20 e1bd6d1e984 40033e60 0 70127020 70b09578 e1bd5fc1791 40033e60 0 70126fc0 70cf78a0 e1bd5fb6b5a 40033e60 0 70126f60 705ed388 e1bd5fb080d 40033e60 0 70126f00 705ed388 e1bd551ff73 70aacde0 ...
The output of ::kmem_log is sorted in descending order by timestamp. The ADDR column is the bufctl_audit structure corresponding to that transaction; BUFADDR points to the actual buffer.
These figures represent transactions on buffers (both allocations and frees). When a particular buffer is corrupted, it can be helpful to locate that buffer in the transaction log, then determine in which other transactions the transacting thread was involved. This can help to assemble a picture of the sequence of events that occurred prior to and after the allocation (or free) of a buffer.
You can employ the ::bufctl command to filter the output of walking the transaction log. The ::bufctl -a command filters the buffers in the transaction log by buffer address. This example filters on buffer 0x70b09578:
> ::walk kmem_log | ::bufctl -a 0x70b09578 ADDR BUFADDR TIMESTAMP THREAD CALLER 70127020 70b09578 e1bd5fc1791 40033e60 biodone+0x108 70126e40 70b09578 e1bd55062da 70aacde0 pageio_setup+0x268 70126de0 70b09578 e1bd52b2317 40033e60 biodone+0x108 70126c00 70b09578 e1bd497ee8e 70aacde0 pageio_setup+0x268 70120480 70b09578 e1bd21c5e2a 70aacde0 elfexec+0x9f0 70120060 70b09578 e1bd20f5ab5 70aacde0 getelfhead+0x100 7011ef20 70b09578 e1bd1e9a1dd 70aacde0 ufs_getpage_miss+0x354 7011d720 70b09578 e1bd1170dc4 70aacde0 pageio_setup+0x268 70117d80 70b09578 e1bcff6ff27 70bc2480 elfexec+0x9f0 70117960 70b09578 e1bcfea4a9f 70bc2480 getelfhead+0x100 ...
This example illustrates that a particular buffer can be used in numerous transactions.
Remember that the kmem transaction log is an incomplete record of the transactions made by the kernel memory allocator. Older entries in the log are evicted as needed in order to keep the size of the log constant.
The ::allocdby and ::freedby dcmds provide a convenient way to summarize transactions associated with a particular thread. Here is an example of listing the recent allocations performed by thread 0x70aacde0:
> 0x70aacde0::allocdby BUFCTL TIMESTAMP CALLER 70d4d8c0 e1edb14511a allocb+0x88 70d4e8a0 e1edb142472 dblk_constructor+0xc 70d4a240 e1edb13dd4f allocb+0x88 70d4e840 e1edb13aeec dblk_constructor+0xc 70d4d860 e1ed8344071 allocb+0x88 70d4e7e0 e1ed8342536 dblk_constructor+0xc 70d4a1e0 e1ed82b3a3c allocb+0x88 70a53f80 e1ed82b0b91 dblk_constructor+0xc 70d4d800 e1e9b663b92 allocb+0x88
By examining bufctl_audit records, you can understand the recent activities of a particular thread.