1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #ifndef _NFS4_DB_IMPL_H 27 #define _NFS4_DB_IMPL_H 28 29 /* 30 * This is a private header file. Applications should not directly include 31 * this file. 32 */ 33 34 #ifdef __cplusplus 35 extern "C" { 36 #endif 37 38 #define SEARCH_DEBUG 0x0001 39 #define CREATE_DEBUG 0x0002 40 #define CACHED_DEBUG 0x0004 41 #define DESTROY_DEBUG 0x0008 42 #define REAP_DEBUG 0x0010 43 #define OTHER_DEBUG 0x0020 44 #define WALK_DEBUG 0x0040 45 46 /* 47 * A database is made up of a collection of tables. 48 * Tables are in turn made up of a collection of 49 * entries. Each table may haveone or more indices 50 * associtated with it. 51 */ 52 53 /* Private implementation */ 54 typedef struct rfs4_link { 55 struct rfs4_link *next; 56 struct rfs4_link *prev; 57 rfs4_dbe_t *entry; 58 } rfs4_link_t; 59 60 struct rfs4_dbe { 61 kmutex_t dbe_lock[1]; /* Exclusive lock for entry */ 62 uint32_t dbe_refcnt; /* # of references */ 63 unsigned dbe_skipsearch:1; /* skip search */ 64 unsigned dbe_invalid:1; /* invalid/"freed" entry */ 65 unsigned dbe_reserved:31; 66 time_t dbe_time_rele; /* Time of last rele */ 67 id_t dbe_id; /* unique identifier */ 68 kcondvar_t dbe_cv[1]; 69 rfs4_entry_t dbe_data; 70 rfs4_table_t *dbe_table; 71 rfs4_link_t dbe_indices[1]; /* Array of indices for entry */ 72 }; 73 74 typedef struct rfs4_bucket { 75 krwlock_t dbk_lock[1]; /* lock hash chain */ 76 rfs4_link_t *dbk_head; 77 } rfs4_bucket_t; 78 79 struct rfs4_index { 80 uint32_t dbi_tblidx; /* which indice in entry */ 81 bool_t dbi_createable; /* Can create entries */ 82 rfs4_table_t *dbi_table; /* Pointer to table */ 83 char *dbi_keyname; /* String rep of key */ 84 rfs4_bucket_t *dbi_buckets; /* Hash buckets */ 85 uint32_t (*dbi_hash)(void *); /* Given key find bucket */ 86 bool_t (*dbi_compare)(rfs4_entry_t, void *); /* Key match entry? */ 87 void *(*dbi_mkkey)(rfs4_entry_t); /* Given data generate a key */ 88 struct rfs4_index *dbi_inext; /* next index on table */ 89 }; 90 91 struct rfs4_table { 92 rfs4_table_t *dbt_tnext; /* next table in db */ 93 struct rfs4_database *dbt_db; /* db that holds this table */ 94 krwlock_t dbt_t_lock[1]; /* lock table for resize */ 95 kmutex_t dbt_lock[1]; /* mutex for count and cached */ 96 char *dbt_name; /* Table name */ 97 id_space_t *dbt_id_space; /* space for unique entry ids */ 98 time_t dbt_min_cache_time; /* How long to cache entries */ 99 time_t dbt_max_cache_time; /* How long to cache entries */ 100 uint32_t dbt_usize; /* User entry size */ 101 uint32_t dbt_maxentries; /* max # of entries in table */ 102 uint32_t dbt_len; /* # of buckets in table */ 103 uint32_t dbt_count; /* # of entries in table */ 104 uint32_t dbt_idxcnt; /* # of indices in table */ 105 uint32_t dbt_maxcnt; /* max # of indices */ 106 uint32_t dbt_ccnt; /* # of creatable entries */ 107 rfs4_index_t *dbt_indices; /* list of indices */ 108 /* Given entry and data construct entry */ 109 bool_t (*dbt_create)(rfs4_entry_t, void *data); 110 void (*dbt_destroy)(rfs4_entry_t); /* Destroy entry */ 111 bool_t (*dbt_expiry)(rfs4_entry_t); /* Has this entry expired */ 112 kmem_cache_t *dbt_mem_cache; /* Cache for table entries */ 113 uint32_t dbt_debug; /* Debug Flags */ 114 /* set of vars used for managing the reaper thread */ 115 unsigned dbt_reaper_shutdown:1; /* table shutting down? */ 116 kcondvar_t dbt_reaper_wait; /* reaper thread waits here */ 117 kmutex_t dbt_reaper_cv_lock; /* lock used for cpr wait */ 118 callb_cpr_t dbt_reaper_cpr_info; /* cpr the reaper thread */ 119 }; 120 121 struct rfs4_database { 122 kmutex_t db_lock[1]; 123 uint32_t db_debug_flags; /* Table debug flags to set */ 124 uint32_t db_shutdown_count; /* count to manage shutdown */ 125 kcondvar_t db_shutdown_wait; /* where the shutdown waits */ 126 rfs4_table_t *db_tables; /* list of tables in db */ 127 }; 128 129 #define RFS4_RECLAIM_PERCENT 10 130 #define RFS4_REAP_INTERVAL 300 131 132 #define HASH(idx, key) (idx->dbi_hash(key) % idx->dbi_table->dbt_len) 133 134 #define ENQUEUE(head, l) { \ 135 (l)->prev = NULL; \ 136 (l)->next = (head); \ 137 if ((l)->next) \ 138 (l)->next->prev = (l); \ 139 (head) = (l); \ 140 } 141 142 #define DEQUEUE(head, l) { \ 143 if ((l)->prev) \ 144 (l)->prev->next = (l)->next; \ 145 else \ 146 (head) = (l)->next; \ 147 if ((l)->next) \ 148 (l)->next->prev = (l)->prev; \ 149 } 150 151 #define INVALIDATE_ADDR(a) ((a) = (void *)((unsigned long)(a) | 1L)) 152 #define VALIDATE_ADDR(a) ((a) = (void *)((unsigned long)(a) & ~1L)) 153 #define INVALID_ADDR(a) (((unsigned long)(a) & 1L)) 154 #define INVALID_LINK(l) (INVALID_ADDR(l->entry)) 155 156 #define ENQUEUE_IDX(bp, l) { \ 157 rw_enter((bp)->dbk_lock, RW_WRITER); \ 158 ENQUEUE((bp)->dbk_head, l); \ 159 VALIDATE_ADDR((l)->entry); \ 160 rw_exit((bp)->dbk_lock); \ 161 } 162 163 #define DEQUEUE_IDX(bp, l) { \ 164 rw_enter((bp)->dbk_lock, RW_WRITER); \ 165 INVALIDATE_ADDR((l)->entry); \ 166 DEQUEUE((bp)->dbk_head, l); \ 167 rw_exit((bp)->dbk_lock); \ 168 } 169 170 #ifdef __cplusplus 171 } 172 #endif 173 174 #endif /* _NFS4_DB_IMPL_H */ 175