FreeBSD ZFS
The Zettabyte File System

unique.c

Go to the documentation of this file.
00001 /*
00002  * CDDL HEADER START
00003  *
00004  * The contents of this file are subject to the terms of the
00005  * Common Development and Distribution License (the "License").
00006  * You may not use this file except in compliance with the License.
00007  *
00008  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
00009  * or http://www.opensolaris.org/os/licensing.
00010  * See the License for the specific language governing permissions
00011  * and limitations under the License.
00012  *
00013  * When distributing Covered Code, include this CDDL HEADER in each
00014  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
00015  * If applicable, add the following below this CDDL HEADER, with the
00016  * fields enclosed by brackets "[]" replaced with your own identifying
00017  * information: Portions Copyright [yyyy] [name of copyright owner]
00018  *
00019  * CDDL HEADER END
00020  */
00021 /*
00022  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
00023  * Use is subject to license terms.
00024  */
00025 
00026 #pragma ident   "%Z%%M% %I%     %E% SMI"
00027 
00028 #include <sys/zfs_context.h>
00029 #include <sys/avl.h>
00030 #include <sys/unique.h>
00031 
00032 static avl_tree_t unique_avl;
00033 static kmutex_t unique_mtx;
00034 
00035 typedef struct unique {
00036         avl_node_t un_link;
00037         uint64_t un_value;
00038 } unique_t;
00039 
00040 #define UNIQUE_MASK ((1ULL << UNIQUE_BITS) - 1)
00041 
00042 static int
00043 unique_compare(const void *a, const void *b)
00044 {
00045         const unique_t *una = a;
00046         const unique_t *unb = b;
00047 
00048         if (una->un_value < unb->un_value)
00049                 return (-1);
00050         if (una->un_value > unb->un_value)
00051                 return (+1);
00052         return (0);
00053 }
00054 
00055 void
00056 unique_init(void)
00057 {
00058         avl_create(&unique_avl, unique_compare,
00059             sizeof (unique_t), offsetof(unique_t, un_link));
00060         mutex_init(&unique_mtx, NULL, MUTEX_DEFAULT, NULL);
00061 }
00062 
00063 void
00064 unique_fini(void)
00065 {
00066         avl_destroy(&unique_avl);
00067         mutex_destroy(&unique_mtx);
00068 }
00069 
00070 uint64_t
00071 unique_create(void)
00072 {
00073         uint64_t value = unique_insert(0);
00074         unique_remove(value);
00075         return (value);
00076 }
00077 
00078 uint64_t
00079 unique_insert(uint64_t value)
00080 {
00081         avl_index_t idx;
00082         unique_t *un = kmem_alloc(sizeof (unique_t), KM_SLEEP);
00083 
00084         un->un_value = value;
00085 
00086         mutex_enter(&unique_mtx);
00087         while (un->un_value == 0 || un->un_value & ~UNIQUE_MASK ||
00088             avl_find(&unique_avl, un, &idx)) {
00089                 mutex_exit(&unique_mtx);
00090                 (void) random_get_pseudo_bytes((void*)&un->un_value,
00091                     sizeof (un->un_value));
00092                 un->un_value &= UNIQUE_MASK;
00093                 mutex_enter(&unique_mtx);
00094         }
00095 
00096         avl_insert(&unique_avl, un, idx);
00097         mutex_exit(&unique_mtx);
00098 
00099         return (un->un_value);
00100 }
00101 
00102 void
00103 unique_remove(uint64_t value)
00104 {
00105         unique_t un_tofind;
00106         unique_t *un;
00107 
00108         un_tofind.un_value = value;
00109         mutex_enter(&unique_mtx);
00110         un = avl_find(&unique_avl, &un_tofind, NULL);
00111         if (un != NULL) {
00112                 avl_remove(&unique_avl, un);
00113                 kmem_free(un, sizeof (unique_t));
00114         }
00115         mutex_exit(&unique_mtx);
00116 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines