Mercurial > illumos > illumos-gate
changeset 3713:00e75dc8b749
6527325 want more assertions in space map code
author | ahrens |
---|---|
date | Sun, 25 Feb 2007 23:16:16 -0800 |
parents | 881021ac3355 |
children | dce229b9418d |
files | usr/src/lib/libzpool/common/kernel.c usr/src/lib/libzpool/common/sys/zfs_context.h usr/src/uts/common/fs/zfs/dmu.c usr/src/uts/common/fs/zfs/metaslab.c usr/src/uts/common/fs/zfs/spa_misc.c usr/src/uts/common/fs/zfs/space_map.c usr/src/uts/common/fs/zfs/sys/zfs_debug.h usr/src/uts/common/fs/zfs/zfs_dir.c |
diffstat | 8 files changed, 105 insertions(+), 13 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/lib/libzpool/common/kernel.c Sun Feb 25 14:16:28 2007 -0800 +++ b/usr/src/lib/libzpool/common/kernel.c Sun Feb 25 23:16:16 2007 -0800 @@ -567,6 +567,18 @@ va_end(adx); } +void +vcmn_err(int ce, const char *fmt, va_list adx) +{ + if (ce == CE_PANIC) + vpanic(fmt, adx); + if (ce != CE_NOTE) { /* suppress noise in userland stress testing */ + (void) fprintf(stderr, "%s", ce_prefix[ce]); + (void) vfprintf(stderr, fmt, adx); + (void) fprintf(stderr, "%s", ce_suffix[ce]); + } +} + /*PRINTFLIKE2*/ void cmn_err(int ce, const char *fmt, ...) @@ -574,13 +586,7 @@ va_list adx; va_start(adx, fmt); - if (ce == CE_PANIC) - vpanic(fmt, adx); - if (ce != CE_NOTE) { /* suppress noise in userland stress testing */ - (void) fprintf(stderr, "%s", ce_prefix[ce]); - (void) vfprintf(stderr, fmt, adx); - (void) fprintf(stderr, "%s", ce_suffix[ce]); - } + vcmn_err(ce, fmt, adx); va_end(adx); }
--- a/usr/src/lib/libzpool/common/sys/zfs_context.h Sun Feb 25 14:16:28 2007 -0800 +++ b/usr/src/lib/libzpool/common/sys/zfs_context.h Sun Feb 25 23:16:16 2007 -0800 @@ -96,6 +96,7 @@ #endif /* ZFS_DEBUG */ extern void cmn_err(int, const char *, ...); +extern void vcmn_err(int, const char *, __va_list); extern void panic(const char *, ...); extern void vpanic(const char *, __va_list);
--- a/usr/src/uts/common/fs/zfs/dmu.c Sun Feb 25 14:16:28 2007 -0800 +++ b/usr/src/uts/common/fs/zfs/dmu.c Sun Feb 25 23:16:16 2007 -0800 @@ -181,7 +181,15 @@ nblks = (P2ROUNDUP(offset+length, 1ULL<<blkshift) - P2ALIGN(offset, 1ULL<<blkshift)) >> blkshift; } else { - ASSERT3U(offset + length, <=, dn->dn_datablksz); + if (offset + length > dn->dn_datablksz) { + zfs_panic_recover("zfs: accessing past end of object " + "%llx/%llx (size=%u access=%llu+%llu)", + (longlong_t)dn->dn_objset-> + os_dsl_dataset->ds_object, + (longlong_t)dn->dn_object, dn->dn_datablksz, + (longlong_t)offset, (longlong_t)length); + return (EIO); + } nblks = 1; } dbp = kmem_zalloc(sizeof (dmu_buf_t *) * nblks, KM_SLEEP);
--- a/usr/src/uts/common/fs/zfs/metaslab.c Sun Feb 25 14:16:28 2007 -0800 +++ b/usr/src/uts/common/fs/zfs/metaslab.c Sun Feb 25 23:16:16 2007 -0800 @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -592,6 +592,7 @@ * future allocations have synced. (If we unloaded it now and then * loaded a moment later, the map wouldn't reflect those allocations.) */ +#ifndef ZFS_DEBUG if (sm->sm_loaded && (msp->ms_weight & METASLAB_ACTIVE_MASK) == 0) { int evictable = 1; @@ -602,6 +603,7 @@ if (evictable) space_map_unload(sm); } +#endif metaslab_group_sort(mg, msp, metaslab_weight(msp)); @@ -868,6 +870,43 @@ if (msp->ms_freemap[txg & TXG_MASK].sm_space == 0) vdev_dirty(vd, VDD_METASLAB, msp, txg); space_map_add(&msp->ms_freemap[txg & TXG_MASK], offset, size); + + /* + * verify that this region is actually allocated in + * either a ms_allocmap or the ms_map + */ +#ifdef ZFS_DEBUG + (void) space_map_load(&msp->ms_map, &metaslab_ff_ops, + SM_FREE, &msp->ms_smo, + msp->ms_group->mg_vd->vdev_spa->spa_meta_objset); +#endif + if (msp->ms_map.sm_loaded) { + boolean_t allocd = B_FALSE; + int i; + + if (!space_map_contains(&msp->ms_map, offset, size)) { + allocd = B_TRUE; + } else { + for (i = 0; i < TXG_CONCURRENT_STATES; i++) { + space_map_t *sm = &msp->ms_allocmap + [(txg - i) & TXG_MASK]; + if (space_map_contains(sm, + offset, size)) { + allocd = B_TRUE; + break; + } + } + } + + if (!allocd) { + zfs_panic_recover("freeing free segment " + "(vdev=%llu offset=%llx size=%llx)", + (longlong_t)vdev, (longlong_t)offset, + (longlong_t)size); + } + } + + } mutex_exit(&msp->ms_lock);
--- a/usr/src/uts/common/fs/zfs/spa_misc.c Sun Feb 25 14:16:28 2007 -0800 +++ b/usr/src/uts/common/fs/zfs/spa_misc.c Sun Feb 25 23:16:16 2007 -0800 @@ -187,6 +187,13 @@ int zfs_flags = 0; #endif +/* + * zfs_recover can be set to nonzero to attempt to recover from + * otherwise-fatal errors, typically caused by on-disk corruption. When + * set, calls to zfs_panic_recover() will turn into warning messages. + */ +int zfs_recover = 0; + #define SPA_MINREF 5 /* spa_refcnt for an open-but-idle pool */ /* @@ -840,6 +847,16 @@ txg_wait_synced(spa_get_dsl(spa), freeze_txg); } +void +zfs_panic_recover(const char *fmt, ...) +{ + va_list adx; + + va_start(adx, fmt); + vcmn_err(zfs_recover ? CE_WARN : CE_PANIC, fmt, adx); + va_end(adx); +} + /* * ========================================================================== * Accessor functions
--- a/usr/src/uts/common/fs/zfs/space_map.c Sun Feb 25 14:16:28 2007 -0800 +++ b/usr/src/uts/common/fs/zfs/space_map.c Sun Feb 25 23:16:16 2007 -0800 @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -97,6 +97,13 @@ ssearch.ss_end = end; ss = avl_find(&sm->sm_root, &ssearch, &where); + if (ss != NULL && ss->ss_start <= start && ss->ss_end >= end) { + zfs_panic_recover("zfs: allocating allocated segment" + "(offset=%llu size=%llu)\n", + (longlong_t)start, (longlong_t)size); + return; + } + /* Make sure we don't overlap with either of our neighbors */ VERIFY(ss == NULL); @@ -142,7 +149,12 @@ ss = avl_find(&sm->sm_root, &ssearch, &where); /* Make sure we completely overlap with someone */ - VERIFY(ss != NULL); + if (ss == NULL) { + zfs_panic_recover("zfs: freeing free segment " + "(offset=%llu size=%llu)", + (longlong_t)start, (longlong_t)size); + return; + } VERIFY3U(ss->ss_start, <=, start); VERIFY3U(ss->ss_end, >=, end); VERIFY(sm->sm_space - size <= sm->sm_size);
--- a/usr/src/uts/common/fs/zfs/sys/zfs_debug.h Sun Feb 25 14:16:28 2007 -0800 +++ b/usr/src/uts/common/fs/zfs/sys/zfs_debug.h Sun Feb 25 23:16:16 2007 -0800 @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -66,6 +66,8 @@ #define dprintf(...) ((void)0) #endif /* ZFS_DEBUG */ +extern void zfs_panic_recover(const char *fmt, ...); + #ifdef __cplusplus } #endif
--- a/usr/src/uts/common/fs/zfs/zfs_dir.c Sun Feb 25 14:16:28 2007 -0800 +++ b/usr/src/uts/common/fs/zfs/zfs_dir.c Sun Feb 25 23:16:16 2007 -0800 @@ -591,7 +591,14 @@ vn_vfsunlock(vp); return (EEXIST); } - ASSERT(zp->z_phys->zp_links > zp_is_dir); + if (zp->z_phys->zp_links <= zp_is_dir) { + zfs_panic_recover("zfs: link count on %s is %u, " + "should be at least %u", + zp->z_vnode->v_path ? zp->z_vnode->v_path : + "<unknown>", (int)zp->z_phys->zp_links, + zp_is_dir + 1); + zp->z_phys->zp_links = zp_is_dir + 1; + } if (--zp->z_phys->zp_links == zp_is_dir) { zp->z_unlinked = B_TRUE; zp->z_phys->zp_links = 0;