DF-3248 / bufdump.c
/* * DF-3248 bufdump KLD — walks the kernel buffer-cache queues (bufpcpu[], * exported by kern/vfs_bio.c) and prints every buffer whose data contains * the HPFS dirblk magic (0x77E40AAE) with d_freeoff 2048, i.e. our cached * dirblk chunks, together with the exact kernel-virtual b_data addresses. * This measures the chunk layout the de_reclen hop must hit. */ #include <sys/param.h> #include <sys/kernel.h> #include <sys/module.h> #include <sys/systm.h> #include <sys/buf.h> #include <sys/malloc.h> #include <sys/spinlock2.h> #include <vm/vm_page.h> #define BQUEUE_NONE 0 #define BQUEUE_LOCKED 1 #define BQUEUE_CLEAN 2 #define BQUEUE_DIRTY 3 #define BQUEUE_DIRTY_HW 4 #define BQUEUE_EMPTY 5 #define BUFFER_QUEUES 6 struct bqueues; TAILQ_HEAD(bqueues, buf); struct bufpcpu { struct spinlock spin; struct bqueues bufqueues[BUFFER_QUEUES]; } __cachealign; extern struct bufpcpu bufpcpu[MAXCPU]; static void dumpq(int cpu, int q) { struct buf *bp; spin_lock(&bufpcpu[cpu].spin); TAILQ_FOREACH(bp, &bufpcpu[cpu].bufqueues[q], b_freelist) { if (bp->b_data == NULL || bp->b_bcount < 32) continue; /* our crafted dirblks: magic 0x77E40AAE + freeoff 2048 */ if (*(uint32_t *)(bp->b_data) == 0x77E40AAE && *(uint32_t *)(bp->b_data + 4) == 2048) { uint32_t self; memcpy(&self, bp->b_data + 16, 4); kprintf("DF3248 lsn 0x%04x b_data %p bcount %d q%d\n", self, bp->b_data, bp->b_bcount, q); } } spin_unlock(&bufpcpu[cpu].spin); } static int df3248_handler(module_t mod, int what, void *arg) { int cpu, q; switch (what) { case MOD_LOAD: kprintf("DF3248 bufdump start\n"); for (cpu = 0; cpu < ncpus; cpu++) for (q = BQUEUE_LOCKED; q <= BQUEUE_DIRTY_HW; q++) dumpq(cpu, q); kprintf("DF3248 bufdump done\n"); return (0); } return (0); } static moduledata_t df3248_mod = { "df3248mod", df3248_handler, NULL }; DECLARE_MODULE(df3248mod, df3248_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE); MODULE_VERSION(df3248mod, 1); |