1168404Spjd/* 2168404Spjd * CDDL HEADER START 3168404Spjd * 4168404Spjd * The contents of this file are subject to the terms of the 5168404Spjd * Common Development and Distribution License (the "License"). 6168404Spjd * You may not use this file except in compliance with the License. 7168404Spjd * 8168404Spjd * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9168404Spjd * or http://www.opensolaris.org/os/licensing. 10168404Spjd * See the License for the specific language governing permissions 11168404Spjd * and limitations under the License. 12168404Spjd * 13168404Spjd * When distributing Covered Code, include this CDDL HEADER in each 14168404Spjd * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15168404Spjd * If applicable, add the following below this CDDL HEADER, with the 16168404Spjd * fields enclosed by brackets "[]" replaced with your own identifying 17168404Spjd * information: Portions Copyright [yyyy] [name of copyright owner] 18168404Spjd * 19168404Spjd * CDDL HEADER END 20168404Spjd */ 21168404Spjd/* 22185029Spjd * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23168404Spjd * Use is subject to license terms. 24168404Spjd */ 25168404Spjd 26168404Spjd#pragma ident "%Z%%M% %I% %E% SMI" 27168404Spjd 28168404Spjd#include <sys/zfs_context.h> 29168404Spjd#include <sys/avl.h> 30168404Spjd#include <sys/unique.h> 31168404Spjd 32168404Spjdstatic avl_tree_t unique_avl; 33185029Spjdstatic kmutex_t unique_mtx; 34168404Spjd 35168404Spjdtypedef struct unique { 36168404Spjd avl_node_t un_link; 37168404Spjd uint64_t un_value; 38168404Spjd} unique_t; 39168404Spjd 40168404Spjd#define UNIQUE_MASK ((1ULL << UNIQUE_BITS) - 1) 41168404Spjd 42168404Spjdstatic int 43168404Spjdunique_compare(const void *a, const void *b) 44168404Spjd{ 45168404Spjd const unique_t *una = a; 46168404Spjd const unique_t *unb = b; 47168404Spjd 48168404Spjd if (una->un_value < unb->un_value) 49168404Spjd return (-1); 50168404Spjd if (una->un_value > unb->un_value) 51168404Spjd return (+1); 52168404Spjd return (0); 53168404Spjd} 54168404Spjd 55168404Spjdvoid 56168404Spjdunique_init(void) 57168404Spjd{ 58168404Spjd avl_create(&unique_avl, unique_compare, 59168404Spjd sizeof (unique_t), offsetof(unique_t, un_link)); 60185029Spjd mutex_init(&unique_mtx, NULL, MUTEX_DEFAULT, NULL); 61168404Spjd} 62168404Spjd 63185029Spjdvoid 64185029Spjdunique_fini(void) 65185029Spjd{ 66185029Spjd avl_destroy(&unique_avl); 67185029Spjd mutex_destroy(&unique_mtx); 68185029Spjd} 69185029Spjd 70168404Spjduint64_t 71168404Spjdunique_create(void) 72168404Spjd{ 73185029Spjd uint64_t value = unique_insert(0); 74185029Spjd unique_remove(value); 75185029Spjd return (value); 76168404Spjd} 77168404Spjd 78168404Spjduint64_t 79168404Spjdunique_insert(uint64_t value) 80168404Spjd{ 81168404Spjd avl_index_t idx; 82168404Spjd unique_t *un = kmem_alloc(sizeof (unique_t), KM_SLEEP); 83168404Spjd 84168404Spjd un->un_value = value; 85168404Spjd 86168404Spjd mutex_enter(&unique_mtx); 87168404Spjd while (un->un_value == 0 || un->un_value & ~UNIQUE_MASK || 88168404Spjd avl_find(&unique_avl, un, &idx)) { 89168404Spjd mutex_exit(&unique_mtx); 90168404Spjd (void) random_get_pseudo_bytes((void*)&un->un_value, 91168404Spjd sizeof (un->un_value)); 92168404Spjd un->un_value &= UNIQUE_MASK; 93168404Spjd mutex_enter(&unique_mtx); 94168404Spjd } 95168404Spjd 96168404Spjd avl_insert(&unique_avl, un, idx); 97168404Spjd mutex_exit(&unique_mtx); 98168404Spjd 99168404Spjd return (un->un_value); 100168404Spjd} 101168404Spjd 102168404Spjdvoid 103168404Spjdunique_remove(uint64_t value) 104168404Spjd{ 105168404Spjd unique_t un_tofind; 106168404Spjd unique_t *un; 107168404Spjd 108168404Spjd un_tofind.un_value = value; 109168404Spjd mutex_enter(&unique_mtx); 110168404Spjd un = avl_find(&unique_avl, &un_tofind, NULL); 111168404Spjd if (un != NULL) { 112168404Spjd avl_remove(&unique_avl, un); 113168404Spjd kmem_free(un, sizeof (unique_t)); 114168404Spjd } 115168404Spjd mutex_exit(&unique_mtx); 116168404Spjd} 117