X-Git-Url: https://git.camperquake.de/gitweb.cgi?a=blobdiff_plain;f=module%2Fzfs%2Frefcount.c;h=e43807c8e3f408b8c85ab4d88a14c1cb3d89940b;hb=refs%2Fheads%2Frertzinger%2Ffeature-zpool-get--p;hp=f1b3b23fe2b3b1dc9c8e98fec705ec5f2074ead0;hpb=172bb4bd5e4afef721dd4d2972d8680d983f144b;p=zfs.git diff --git a/module/zfs/refcount.c b/module/zfs/refcount.c index f1b3b23..e43807c 100644 --- a/module/zfs/refcount.c +++ b/module/zfs/refcount.c @@ -19,16 +19,13 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include #include -#if defined(DEBUG) || !defined(_KERNEL) +#ifdef ZFS_DEBUG #ifdef _KERNEL int reference_tracking_enable = FALSE; /* runs out of memory too easily */ @@ -75,13 +72,13 @@ refcount_destroy_many(refcount_t *rc, uint64_t number) reference_t *ref; ASSERT(rc->rc_count == number); - while (ref = list_head(&rc->rc_list)) { + while ((ref = list_head(&rc->rc_list))) { list_remove(&rc->rc_list, ref); kmem_cache_free(reference_cache, ref); } list_destroy(&rc->rc_list); - while (ref = list_head(&rc->rc_removed)) { + while ((ref = list_head(&rc->rc_removed))) { list_remove(&rc->rc_removed, ref); kmem_cache_free(reference_history_cache, ref->ref_removed); kmem_cache_free(reference_cache, ref); @@ -113,11 +110,11 @@ refcount_count(refcount_t *rc) int64_t refcount_add_many(refcount_t *rc, uint64_t number, void *holder) { - reference_t *ref; + reference_t *ref = NULL; int64_t count; if (reference_tracking_enable) { - ref = kmem_cache_alloc(reference_cache, KM_SLEEP); + ref = kmem_cache_alloc(reference_cache, KM_PUSHPAGE); ref->ref_holder = holder; ref->ref_number = number; } @@ -161,7 +158,7 @@ refcount_remove_many(refcount_t *rc, uint64_t number, void *holder) if (reference_history > 0) { ref->ref_removed = kmem_cache_alloc(reference_history_cache, - KM_SLEEP); + KM_PUSHPAGE); list_insert_head(&rc->rc_removed, ref); rc->rc_removed_count++; if (rc->rc_removed_count >= reference_history) { @@ -192,4 +189,35 @@ refcount_remove(refcount_t *rc, void *holder) return (refcount_remove_many(rc, 1, holder)); } -#endif +void +refcount_transfer(refcount_t *dst, refcount_t *src) +{ + int64_t count, removed_count; + list_t list, removed; + + list_create(&list, sizeof (reference_t), + offsetof(reference_t, ref_link)); + list_create(&removed, sizeof (reference_t), + offsetof(reference_t, ref_link)); + + mutex_enter(&src->rc_mtx); + count = src->rc_count; + removed_count = src->rc_removed_count; + src->rc_count = 0; + src->rc_removed_count = 0; + list_move_tail(&list, &src->rc_list); + list_move_tail(&removed, &src->rc_removed); + mutex_exit(&src->rc_mtx); + + mutex_enter(&dst->rc_mtx); + dst->rc_count += count; + dst->rc_removed_count += removed_count; + list_move_tail(&dst->rc_list, &list); + list_move_tail(&dst->rc_removed, &removed); + mutex_exit(&dst->rc_mtx); + + list_destroy(&list); + list_destroy(&removed); +} + +#endif /* ZFS_DEBUG */