diff options
author | Ted Unangst <tedu@cvs.openbsd.org> | 2011-07-05 16:36:16 +0000 |
---|---|---|
committer | Ted Unangst <tedu@cvs.openbsd.org> | 2011-07-05 16:36:16 +0000 |
commit | 097154c740b46d3a8c8dbf722433af1590aadad0 (patch) | |
tree | faf15612559f1cfd92dd9192d4e61ddc06e708ac /sys/kern | |
parent | 037453b4d9fe9eb71bfb5b842d9e9fa77e69ad96 (diff) |
when all you have is a hammer, make it a big one. add more checks to pool_chk
and a pool_init flag to aggressively run pool_chk. ok art deraadt
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/subr_pool.c | 64 |
1 files changed, 50 insertions, 14 deletions
diff --git a/sys/kern/subr_pool.c b/sys/kern/subr_pool.c index fcc74a92fd6..29e1bbb6576 100644 --- a/sys/kern/subr_pool.c +++ b/sys/kern/subr_pool.c @@ -1,4 +1,4 @@ -/* $OpenBSD: subr_pool.c,v 1.104 2011/04/18 19:23:46 art Exp $ */ +/* $OpenBSD: subr_pool.c,v 1.105 2011/07/05 16:36:15 tedu Exp $ */ /* $NetBSD: subr_pool.c,v 1.61 2001/09/26 07:14:56 chs Exp $ */ /*- @@ -113,7 +113,7 @@ void *pool_do_get(struct pool *, int); void pool_do_put(struct pool *, void *); void pr_rmpage(struct pool *, struct pool_item_header *, struct pool_pagelist *); -int pool_chk_page(struct pool *, const char *, struct pool_item_header *); +int pool_chk_page(struct pool *, struct pool_item_header *, int); struct pool_item_header *pool_alloc_item_header(struct pool *, caddr_t , int); void *pool_allocator_alloc(struct pool *, int, int *); @@ -468,7 +468,19 @@ pool_get(struct pool *pp, int flags) #endif /* DIAGNOSTIC */ mtx_enter(&pp->pr_mtx); +#ifdef POOL_DEBUG + if (pp->pr_roflags & PR_DEBUGCHK) { + if (pool_chk(pp)) + panic("before pool_get"); + } +#endif v = pool_do_get(pp, flags); +#ifdef POOL_DEBUG + if (pp->pr_roflags & PR_DEBUGCHK) { + if (pool_chk(pp)) + panic("after pool_get"); + } +#endif mtx_leave(&pp->pr_mtx); if (v == NULL) return (v); @@ -692,7 +704,19 @@ pool_put(struct pool *pp, void *v) if (pp->pr_dtor) pp->pr_dtor(pp->pr_arg, v); mtx_enter(&pp->pr_mtx); +#ifdef POOL_DEBUG + if (pp->pr_roflags & PR_DEBUGCHK) { + if (pool_chk(pp)) + panic("before pool_put"); + } +#endif pool_do_put(pp, v); +#ifdef POOL_DEBUG + if (pp->pr_roflags & PR_DEBUGCHK) { + if (pool_chk(pp)) + panic("after pool_put"); + } +#endif mtx_leave(&pp->pr_mtx); pp->pr_nput++; } @@ -1237,12 +1261,12 @@ db_show_all_pools(db_expr_t expr, int haddr, db_expr_t count, char *modif) PRWORD(ovflw, " %*s", 6, 1, maxp); PRWORD(ovflw, " %*lu\n", 5, 1, pp->pr_nidle); - pool_chk(pp, pp->pr_wchan); + pool_chk(pp); } } int -pool_chk_page(struct pool *pp, const char *label, struct pool_item_header *ph) +pool_chk_page(struct pool *pp, struct pool_item_header *ph, int expected) { struct pool_item *pi; caddr_t page; @@ -1250,12 +1274,12 @@ pool_chk_page(struct pool *pp, const char *label, struct pool_item_header *ph) #if defined(DIAGNOSTIC) && defined(POOL_DEBUG) int i, *ip; #endif + const char *label = pp->pr_wchan; page = (caddr_t)((u_long)ph & pp->pr_alloc->pa_pagemask); if (page != ph->ph_page && (pp->pr_roflags & PR_PHINPAGE) != 0) { - if (label != NULL) - printf("%s: ", label); + printf("%s: ", label); printf("pool(%p:%s): page inconsistency: page %p; " "at page head addr %p (p %p)\n", pp, pp->pr_wchan, ph->ph_page, ph, page); @@ -1268,8 +1292,7 @@ pool_chk_page(struct pool *pp, const char *label, struct pool_item_header *ph) #ifdef DIAGNOSTIC if (pi->pi_magic != PI_MAGIC) { - if (label != NULL) - printf("%s: ", label); + printf("%s: ", label); printf("pool(%s): free list modified: " "page %p; item ordinal %d; addr %p " "(p %p); offset 0x%x=0x%x\n", @@ -1297,28 +1320,41 @@ pool_chk_page(struct pool *pp, const char *label, struct pool_item_header *ph) if (page == ph->ph_page) continue; - if (label != NULL) - printf("%s: ", label); + printf("%s: ", label); printf("pool(%p:%s): page inconsistency: page %p;" " item ordinal %d; addr %p (p %p)\n", pp, pp->pr_wchan, ph->ph_page, n, pi, page); return 1; } + if (n + ph->ph_nmissing != pp->pr_itemsperpage) { + printf("pool(%p:%s): page inconsistency: page %p;" + " %d on list, %d missing, %d items per page\n", pp, + pp->pr_wchan, ph->ph_page, n, ph->ph_nmissing, + pp->pr_itemsperpage); + return 1; + } + if (expected >= 0 && n != expected) { + printf("pool(%p:%s): page inconsistency: page %p;" + " %d on list, %d missing, %d expected\n", pp, + pp->pr_wchan, ph->ph_page, n, ph->ph_nmissing, + expected); + return 1; + } return 0; } int -pool_chk(struct pool *pp, const char *label) +pool_chk(struct pool *pp) { struct pool_item_header *ph; int r = 0; LIST_FOREACH(ph, &pp->pr_emptypages, ph_pagelist) - r += pool_chk_page(pp, label, ph); + r += pool_chk_page(pp, ph, pp->pr_itemsperpage); LIST_FOREACH(ph, &pp->pr_fullpages, ph_pagelist) - r += pool_chk_page(pp, label, ph); + r += pool_chk_page(pp, ph, 0); LIST_FOREACH(ph, &pp->pr_partpages, ph_pagelist) - r += pool_chk_page(pp, label, ph); + r += pool_chk_page(pp, ph, -1); return (r); } |