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 /* 39 * A database is made up of a collection of tables. 40 * Tables are in turn made up of a collection of 41 * entries. Each table may have one or more indices 42 * associtated with it. 43 */ 44 45 /* Private implementation */ 46 typedef struct rfs4_link { 47 struct rfs4_link *next; 48 struct rfs4_link *prev; 49 rfs4_dbe_t *entry; 50 } rfs4_link_t; 51 52 struct rfs4_dbe { 53 kmutex_t dbe_lock[1]; /* Exclusive lock for entry */ 54 uint32_t dbe_refcnt; /* # of references */ 55 unsigned dbe_skipsearch:1; /* skip search */ 56 unsigned dbe_invalid:1; /* invalid/"freed" entry */ 57 unsigned dbe_reserved:31; 58 time_t dbe_time_rele; /* Time of last rele */ 59 caddr_t dbe_inval_hint; 60 id_t dbe_id; /* unique identifier */ 61 kcondvar_t dbe_cv[1]; 62 rfs4_entry_t dbe_data; 63 rfs4_table_t *dbe_table; 64 rfs4_link_t dbe_indices[1]; /* Array of indices for entry */ 65 }; 66 67 typedef struct rfs4_bucket { 68 krwlock_t dbk_lock[1]; /* lock hash chain */ 69 rfs4_link_t *dbk_head; 70 } rfs4_bucket_t; 71 72 struct rfs4_index { 73 uint32_t dbi_tblidx; /* which indice in entry */ 74 bool_t dbi_createable; /* Can create entries */ 75 rfs4_table_t *dbi_table; /* Pointer to table */ 76 char *dbi_keyname; /* String rep of key */ 77 rfs4_bucket_t *dbi_buckets; /* Hash buckets */ 78 uint32_t (*dbi_hash)(void *); /* Given key find bucket */ 79 bool_t (*dbi_compare)(rfs4_entry_t, void *); /* Key match entry? */ 80 void *(*dbi_mkkey)(rfs4_entry_t); /* Given data generate a key */ 81 struct rfs4_index *dbi_inext; /* next index on table */ 82 }; 83 84 struct rfs4_table { 85 rfs4_table_t *dbt_tnext; /* next table in db */ 86 nfs_server_instance_t *dbt_instp; 87 krwlock_t dbt_t_lock[1]; /* lock table for resize */ 88 kmutex_t dbt_lock[1]; /* mutex for count and cached */ 89 char *dbt_name; /* Table name */ 90 id_space_t *dbt_id_space; /* space for unique entry ids */ 91 time_t dbt_min_cache_time; /* How long to cache entries */ 92 time_t dbt_max_cache_time; /* How long to cache entries */ 93 uint32_t dbt_usize; /* User entry size */ 94 uint32_t dbt_maxentries; /* max # of entries in table */ 95 uint32_t dbt_len; /* # of buckets in table */ 96 uint32_t dbt_count; /* # of entries in table */ 97 uint32_t dbt_idxcnt; /* # of indices in table */ 98 uint32_t dbt_maxcnt; /* max # of indices */ 99 uint32_t dbt_ccnt; /* # of creatable entries */ 100 rfs4_index_t *dbt_indices; /* list of indices */ 101 /* Given entry and data construct entry */ 102 bool_t (*dbt_create)(rfs4_entry_t, void *data); 103 void (*dbt_destroy)(rfs4_entry_t); /* Destroy entry */ 104 bool_t (*dbt_expiry)(rfs4_entry_t); /* Has this entry expired */ 105 kmem_cache_t *dbt_mem_cache; /* Cache for table entries */ 106 uint32_t dbt_debug; /* Debug Flags */ 107 /* set of vars used for managing the reaper thread */ 108 unsigned dbt_reaper_shutdown:1; /* table shutting down? */ 109 kcondvar_t dbt_reaper_wait; /* reaper thread waits here */ 110 kmutex_t dbt_reaper_cv_lock; /* lock used for cpr wait */ 111 callb_cpr_t dbt_reaper_cpr_info; /* cpr the reaper thread */ 112 }; 113 114 struct rfs4_database { 115 kmutex_t db_lock[1]; 116 uint32_t db_shutdown_count; /* count to manage shutdown */ 117 kcondvar_t db_shutdown_wait; /* where the shutdown waits */ 118 rfs4_table_t *db_tables; /* list of tables in db */ 119 nfs_server_instance_t *db_instp; /* just for handy debug */ 120 }; 121 122 #define RFS4_RECLAIM_PERCENT 10 123 #define RFS4_REAP_INTERVAL 300 124 125 #define HASH(idx, key) (idx->dbi_hash(key) % idx->dbi_table->dbt_len) 126 127 #define ENQUEUE(head, l) { \ 128 (l)->prev = NULL; \ 129 (l)->next = (head); \ 130 if ((l)->next) \ 131 (l)->next->prev = (l); \ 132 (head) = (l); \ 133 } 134 135 #define DEQUEUE(head, l) { \ 136 if ((l)->prev) \ 137 (l)->prev->next = (l)->next; \ 138 else \ 139 (head) = (l)->next; \ 140 if ((l)->next) \ 141 (l)->next->prev = (l)->prev; \ 142 } 143 144 #define INVALIDATE_ADDR(a) ((a) = (void *)((unsigned long)(a) | 1L)) 145 #define VALIDATE_ADDR(a) ((a) = (void *)((unsigned long)(a) & ~1L)) 146 #define INVALID_ADDR(a) (((unsigned long)(a) & 1L)) 147 #define INVALID_LINK(l) (INVALID_ADDR(l->entry)) 148 149 #define ENQUEUE_IDX(bp, l) { \ 150 rw_enter((bp)->dbk_lock, RW_WRITER); \ 151 ENQUEUE((bp)->dbk_head, l); \ 152 VALIDATE_ADDR((l)->entry); \ 153 rw_exit((bp)->dbk_lock); \ 154 } 155 156 #define DEQUEUE_IDX(bp, l) { \ 157 rw_enter((bp)->dbk_lock, RW_WRITER); \ 158 INVALIDATE_ADDR((l)->entry); \ 159 DEQUEUE((bp)->dbk_head, l); \ 160 rw_exit((bp)->dbk_lock); \ 161 } 162 163 #ifdef __cplusplus 164 } 165 #endif 166 167 #endif /* _NFS4_DB_IMPL_H */ 168