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 35extern "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 */ 54typedef struct rfs4_link { 55 struct rfs4_link *next; 56 struct rfs4_link *prev; 57 rfs4_dbe_t *entry; 58} rfs4_link_t; 59 60struct 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 74typedef struct rfs4_bucket { 75 krwlock_t dbk_lock[1]; /* lock hash chain */ 76 rfs4_link_t *dbk_head; 77} rfs4_bucket_t; 78 79struct 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 91struct 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 uint32_t dbt_id_lwat; /* lo wtrmrk; 50% ids in use */ 108 uint32_t dbt_id_hwat; /* hi wtrmrk; 75% ids in use */ 109 time_t dbt_id_reap; /* table's reap interval */ 110 rfs4_index_t *dbt_indices; /* list of indices */ 111 /* Given entry and data construct entry */ 112 bool_t (*dbt_create)(rfs4_entry_t, void *data); 113 void (*dbt_destroy)(rfs4_entry_t); /* Destroy entry */ 114 bool_t (*dbt_expiry)(rfs4_entry_t); /* Has this entry expired */ 115 kmem_cache_t *dbt_mem_cache; /* Cache for table entries */ 116 uint32_t dbt_debug; /* Debug Flags */ 117 /* set of vars used for managing the reaper thread */ 118 unsigned dbt_reaper_shutdown:1; /* table shutting down? */ 119 kcondvar_t dbt_reaper_wait; /* reaper thread waits here */ 120 kmutex_t dbt_reaper_cv_lock; /* lock used for cpr wait */ 121 callb_cpr_t dbt_reaper_cpr_info; /* cpr the reaper thread */ 122}; 123 124struct rfs4_database { 125 kmutex_t db_lock[1]; 126 uint32_t db_debug_flags; /* Table debug flags to set */ 127 uint32_t db_shutdown_count; /* count to manage shutdown */ 128 kcondvar_t db_shutdown_wait; /* where the shutdown waits */ 129 rfs4_table_t *db_tables; /* list of tables in db */ 130}; 131 132#define RFS4_RECLAIM_PERCENT 10 133#define RFS4_REAP_INTERVAL 300 134 135#define HASH(idx, key) (idx->dbi_hash(key) % idx->dbi_table->dbt_len) 136 137#define ENQUEUE(head, l) { \ 138 (l)->prev = NULL; \ 139 (l)->next = (head); \ 140 if ((l)->next) \ 141 (l)->next->prev = (l); \ 142 (head) = (l); \ 143} 144 145#define DEQUEUE(head, l) { \ 146 if ((l)->prev) \ 147 (l)->prev->next = (l)->next; \ 148 else \ 149 (head) = (l)->next; \ 150 if ((l)->next) \ 151 (l)->next->prev = (l)->prev; \ 152} 153 154#define INVALIDATE_ADDR(a) ((a) = (void *)((unsigned long)(a) | 1L)) 155#define VALIDATE_ADDR(a) ((a) = (void *)((unsigned long)(a) & ~1L)) 156#define INVALID_ADDR(a) (((unsigned long)(a) & 1L)) 157#define INVALID_LINK(l) (INVALID_ADDR(l->entry)) 158 159#define ENQUEUE_IDX(bp, l) { \ 160 rw_enter((bp)->dbk_lock, RW_WRITER); \ 161 ENQUEUE((bp)->dbk_head, l); \ 162 VALIDATE_ADDR((l)->entry); \ 163 rw_exit((bp)->dbk_lock); \ 164} 165 166#define DEQUEUE_IDX(bp, l) { \ 167 rw_enter((bp)->dbk_lock, RW_WRITER); \ 168 INVALIDATE_ADDR((l)->entry); \ 169 DEQUEUE((bp)->dbk_head, l); \ 170 rw_exit((bp)->dbk_lock); \ 171} 172 173#ifdef __cplusplus 174} 175#endif 176 177#endif /* _NFS4_DB_IMPL_H */ 178