10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*9885SRobert.Mastors@Sun.COM * Common Development and Distribution License (the "License"). 6*9885SRobert.Mastors@Sun.COM * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 22*9885SRobert.Mastors@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate #ifndef _NFS4_DB_IMPL_H 270Sstevel@tonic-gate #define _NFS4_DB_IMPL_H 280Sstevel@tonic-gate 290Sstevel@tonic-gate /* 300Sstevel@tonic-gate * This is a private header file. Applications should not directly include 310Sstevel@tonic-gate * this file. 320Sstevel@tonic-gate */ 330Sstevel@tonic-gate 340Sstevel@tonic-gate #ifdef __cplusplus 350Sstevel@tonic-gate extern "C" { 360Sstevel@tonic-gate #endif 370Sstevel@tonic-gate 380Sstevel@tonic-gate #define SEARCH_DEBUG 0x0001 390Sstevel@tonic-gate #define CREATE_DEBUG 0x0002 400Sstevel@tonic-gate #define CACHED_DEBUG 0x0004 410Sstevel@tonic-gate #define DESTROY_DEBUG 0x0008 420Sstevel@tonic-gate #define REAP_DEBUG 0x0010 430Sstevel@tonic-gate #define OTHER_DEBUG 0x0020 440Sstevel@tonic-gate #define WALK_DEBUG 0x0040 450Sstevel@tonic-gate 460Sstevel@tonic-gate /* 470Sstevel@tonic-gate * A database is made up of a collection of tables. 480Sstevel@tonic-gate * Tables are in turn made up of a collection of 490Sstevel@tonic-gate * entries. Each table may haveone or more indices 500Sstevel@tonic-gate * associtated with it. 510Sstevel@tonic-gate */ 520Sstevel@tonic-gate 530Sstevel@tonic-gate /* Private implementation */ 540Sstevel@tonic-gate typedef struct rfs4_link { 550Sstevel@tonic-gate struct rfs4_link *next; 560Sstevel@tonic-gate struct rfs4_link *prev; 570Sstevel@tonic-gate rfs4_dbe_t *entry; 58*9885SRobert.Mastors@Sun.COM } rfs4_link_t; 590Sstevel@tonic-gate 600Sstevel@tonic-gate struct rfs4_dbe { 61*9885SRobert.Mastors@Sun.COM kmutex_t dbe_lock[1]; /* Exclusive lock for entry */ 62*9885SRobert.Mastors@Sun.COM uint32_t dbe_refcnt; /* # of references */ 63*9885SRobert.Mastors@Sun.COM unsigned dbe_skipsearch:1; /* skip search */ 64*9885SRobert.Mastors@Sun.COM unsigned dbe_invalid:1; /* invalid/"freed" entry */ 65*9885SRobert.Mastors@Sun.COM unsigned dbe_reserved:31; 66*9885SRobert.Mastors@Sun.COM time_t dbe_time_rele; /* Time of last rele */ 67*9885SRobert.Mastors@Sun.COM id_t dbe_id; /* unique identifier */ 68*9885SRobert.Mastors@Sun.COM kcondvar_t dbe_cv[1]; 69*9885SRobert.Mastors@Sun.COM rfs4_entry_t dbe_data; 70*9885SRobert.Mastors@Sun.COM rfs4_table_t *dbe_table; 71*9885SRobert.Mastors@Sun.COM rfs4_link_t dbe_indices[1]; /* Array of indices for entry */ 720Sstevel@tonic-gate }; 730Sstevel@tonic-gate 740Sstevel@tonic-gate typedef struct rfs4_bucket { 75*9885SRobert.Mastors@Sun.COM krwlock_t dbk_lock[1]; /* lock hash chain */ 76*9885SRobert.Mastors@Sun.COM rfs4_link_t *dbk_head; 77*9885SRobert.Mastors@Sun.COM } rfs4_bucket_t; 780Sstevel@tonic-gate 790Sstevel@tonic-gate struct rfs4_index { 80*9885SRobert.Mastors@Sun.COM uint32_t dbi_tblidx; /* which indice in entry */ 81*9885SRobert.Mastors@Sun.COM bool_t dbi_createable; /* Can create entries */ 82*9885SRobert.Mastors@Sun.COM rfs4_table_t *dbi_table; /* Pointer to table */ 83*9885SRobert.Mastors@Sun.COM char *dbi_keyname; /* String rep of key */ 84*9885SRobert.Mastors@Sun.COM rfs4_bucket_t *dbi_buckets; /* Hash buckets */ 85*9885SRobert.Mastors@Sun.COM uint32_t (*dbi_hash)(void *); /* Given key find bucket */ 86*9885SRobert.Mastors@Sun.COM bool_t (*dbi_compare)(rfs4_entry_t, void *); /* Key match entry? */ 87*9885SRobert.Mastors@Sun.COM void *(*dbi_mkkey)(rfs4_entry_t); /* Given data generate a key */ 88*9885SRobert.Mastors@Sun.COM struct rfs4_index *dbi_inext; /* next index on table */ 890Sstevel@tonic-gate }; 900Sstevel@tonic-gate 910Sstevel@tonic-gate struct rfs4_table { 92*9885SRobert.Mastors@Sun.COM rfs4_table_t *dbt_tnext; /* next table in db */ 93*9885SRobert.Mastors@Sun.COM struct rfs4_database *dbt_db; /* db that holds this table */ 94*9885SRobert.Mastors@Sun.COM krwlock_t dbt_t_lock[1]; /* lock table for resize */ 95*9885SRobert.Mastors@Sun.COM kmutex_t dbt_lock[1]; /* mutex for count and cached */ 96*9885SRobert.Mastors@Sun.COM char *dbt_name; /* Table name */ 97*9885SRobert.Mastors@Sun.COM id_space_t *dbt_id_space; /* space for unique entry ids */ 98*9885SRobert.Mastors@Sun.COM time_t dbt_min_cache_time; /* How long to cache entries */ 99*9885SRobert.Mastors@Sun.COM time_t dbt_max_cache_time; /* How long to cache entries */ 100*9885SRobert.Mastors@Sun.COM uint32_t dbt_usize; /* User entry size */ 101*9885SRobert.Mastors@Sun.COM uint32_t dbt_maxentries; /* max # of entries in table */ 102*9885SRobert.Mastors@Sun.COM uint32_t dbt_len; /* # of buckets in table */ 103*9885SRobert.Mastors@Sun.COM uint32_t dbt_count; /* # of entries in table */ 104*9885SRobert.Mastors@Sun.COM uint32_t dbt_idxcnt; /* # of indices in table */ 105*9885SRobert.Mastors@Sun.COM uint32_t dbt_maxcnt; /* max # of indices */ 106*9885SRobert.Mastors@Sun.COM uint32_t dbt_ccnt; /* # of creatable entries */ 107*9885SRobert.Mastors@Sun.COM rfs4_index_t *dbt_indices; /* list of indices */ 1080Sstevel@tonic-gate /* Given entry and data construct entry */ 109*9885SRobert.Mastors@Sun.COM bool_t (*dbt_create)(rfs4_entry_t, void *data); 110*9885SRobert.Mastors@Sun.COM void (*dbt_destroy)(rfs4_entry_t); /* Destroy entry */ 111*9885SRobert.Mastors@Sun.COM bool_t (*dbt_expiry)(rfs4_entry_t); /* Has this entry expired */ 112*9885SRobert.Mastors@Sun.COM kmem_cache_t *dbt_mem_cache; /* Cache for table entries */ 113*9885SRobert.Mastors@Sun.COM uint32_t dbt_debug; /* Debug Flags */ 1140Sstevel@tonic-gate /* set of vars used for managing the reaper thread */ 115*9885SRobert.Mastors@Sun.COM unsigned dbt_reaper_shutdown:1; /* table shutting down? */ 116*9885SRobert.Mastors@Sun.COM kcondvar_t dbt_reaper_wait; /* reaper thread waits here */ 117*9885SRobert.Mastors@Sun.COM kmutex_t dbt_reaper_cv_lock; /* lock used for cpr wait */ 118*9885SRobert.Mastors@Sun.COM callb_cpr_t dbt_reaper_cpr_info; /* cpr the reaper thread */ 1190Sstevel@tonic-gate }; 1200Sstevel@tonic-gate 1210Sstevel@tonic-gate struct rfs4_database { 122*9885SRobert.Mastors@Sun.COM kmutex_t db_lock[1]; 123*9885SRobert.Mastors@Sun.COM uint32_t db_debug_flags; /* Table debug flags to set */ 124*9885SRobert.Mastors@Sun.COM uint32_t db_shutdown_count; /* count to manage shutdown */ 125*9885SRobert.Mastors@Sun.COM kcondvar_t db_shutdown_wait; /* where the shutdown waits */ 126*9885SRobert.Mastors@Sun.COM rfs4_table_t *db_tables; /* list of tables in db */ 1270Sstevel@tonic-gate }; 1280Sstevel@tonic-gate 1290Sstevel@tonic-gate #define RFS4_RECLAIM_PERCENT 10 1300Sstevel@tonic-gate #define RFS4_REAP_INTERVAL 300 1310Sstevel@tonic-gate 132*9885SRobert.Mastors@Sun.COM #define HASH(idx, key) (idx->dbi_hash(key) % idx->dbi_table->dbt_len) 1330Sstevel@tonic-gate 1340Sstevel@tonic-gate #define ENQUEUE(head, l) { \ 1350Sstevel@tonic-gate (l)->prev = NULL; \ 1360Sstevel@tonic-gate (l)->next = (head); \ 1370Sstevel@tonic-gate if ((l)->next) \ 1380Sstevel@tonic-gate (l)->next->prev = (l); \ 1390Sstevel@tonic-gate (head) = (l); \ 1400Sstevel@tonic-gate } 1410Sstevel@tonic-gate 1420Sstevel@tonic-gate #define DEQUEUE(head, l) { \ 1430Sstevel@tonic-gate if ((l)->prev) \ 1440Sstevel@tonic-gate (l)->prev->next = (l)->next; \ 1450Sstevel@tonic-gate else \ 1460Sstevel@tonic-gate (head) = (l)->next; \ 1470Sstevel@tonic-gate if ((l)->next) \ 1480Sstevel@tonic-gate (l)->next->prev = (l)->prev; \ 1490Sstevel@tonic-gate } 1500Sstevel@tonic-gate 1510Sstevel@tonic-gate #define INVALIDATE_ADDR(a) ((a) = (void *)((unsigned long)(a) | 1L)) 1520Sstevel@tonic-gate #define VALIDATE_ADDR(a) ((a) = (void *)((unsigned long)(a) & ~1L)) 1530Sstevel@tonic-gate #define INVALID_ADDR(a) (((unsigned long)(a) & 1L)) 1540Sstevel@tonic-gate #define INVALID_LINK(l) (INVALID_ADDR(l->entry)) 1550Sstevel@tonic-gate 1560Sstevel@tonic-gate #define ENQUEUE_IDX(bp, l) { \ 157*9885SRobert.Mastors@Sun.COM rw_enter((bp)->dbk_lock, RW_WRITER); \ 158*9885SRobert.Mastors@Sun.COM ENQUEUE((bp)->dbk_head, l); \ 1590Sstevel@tonic-gate VALIDATE_ADDR((l)->entry); \ 160*9885SRobert.Mastors@Sun.COM rw_exit((bp)->dbk_lock); \ 1610Sstevel@tonic-gate } 1620Sstevel@tonic-gate 1630Sstevel@tonic-gate #define DEQUEUE_IDX(bp, l) { \ 164*9885SRobert.Mastors@Sun.COM rw_enter((bp)->dbk_lock, RW_WRITER); \ 1650Sstevel@tonic-gate INVALIDATE_ADDR((l)->entry); \ 166*9885SRobert.Mastors@Sun.COM DEQUEUE((bp)->dbk_head, l); \ 167*9885SRobert.Mastors@Sun.COM rw_exit((bp)->dbk_lock); \ 1680Sstevel@tonic-gate } 1690Sstevel@tonic-gate 1700Sstevel@tonic-gate #ifdef __cplusplus 1710Sstevel@tonic-gate } 1720Sstevel@tonic-gate #endif 1730Sstevel@tonic-gate 1740Sstevel@tonic-gate #endif /* _NFS4_DB_IMPL_H */ 175