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 59885SRobert.Mastors@Sun.COM * Common Development and Distribution License (the "License"). 69885SRobert.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 /* 229885SRobert.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; 589885SRobert.Mastors@Sun.COM } rfs4_link_t; 590Sstevel@tonic-gate 600Sstevel@tonic-gate struct rfs4_dbe { 619885SRobert.Mastors@Sun.COM kmutex_t dbe_lock[1]; /* Exclusive lock for entry */ 629885SRobert.Mastors@Sun.COM uint32_t dbe_refcnt; /* # of references */ 639885SRobert.Mastors@Sun.COM unsigned dbe_skipsearch:1; /* skip search */ 649885SRobert.Mastors@Sun.COM unsigned dbe_invalid:1; /* invalid/"freed" entry */ 659885SRobert.Mastors@Sun.COM unsigned dbe_reserved:31; 669885SRobert.Mastors@Sun.COM time_t dbe_time_rele; /* Time of last rele */ 679885SRobert.Mastors@Sun.COM id_t dbe_id; /* unique identifier */ 689885SRobert.Mastors@Sun.COM kcondvar_t dbe_cv[1]; 699885SRobert.Mastors@Sun.COM rfs4_entry_t dbe_data; 709885SRobert.Mastors@Sun.COM rfs4_table_t *dbe_table; 719885SRobert.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 { 759885SRobert.Mastors@Sun.COM krwlock_t dbk_lock[1]; /* lock hash chain */ 769885SRobert.Mastors@Sun.COM rfs4_link_t *dbk_head; 779885SRobert.Mastors@Sun.COM } rfs4_bucket_t; 780Sstevel@tonic-gate 790Sstevel@tonic-gate struct rfs4_index { 809885SRobert.Mastors@Sun.COM uint32_t dbi_tblidx; /* which indice in entry */ 819885SRobert.Mastors@Sun.COM bool_t dbi_createable; /* Can create entries */ 829885SRobert.Mastors@Sun.COM rfs4_table_t *dbi_table; /* Pointer to table */ 839885SRobert.Mastors@Sun.COM char *dbi_keyname; /* String rep of key */ 849885SRobert.Mastors@Sun.COM rfs4_bucket_t *dbi_buckets; /* Hash buckets */ 859885SRobert.Mastors@Sun.COM uint32_t (*dbi_hash)(void *); /* Given key find bucket */ 869885SRobert.Mastors@Sun.COM bool_t (*dbi_compare)(rfs4_entry_t, void *); /* Key match entry? */ 879885SRobert.Mastors@Sun.COM void *(*dbi_mkkey)(rfs4_entry_t); /* Given data generate a key */ 889885SRobert.Mastors@Sun.COM struct rfs4_index *dbi_inext; /* next index on table */ 890Sstevel@tonic-gate }; 900Sstevel@tonic-gate 910Sstevel@tonic-gate struct rfs4_table { 929885SRobert.Mastors@Sun.COM rfs4_table_t *dbt_tnext; /* next table in db */ 939885SRobert.Mastors@Sun.COM struct rfs4_database *dbt_db; /* db that holds this table */ 949885SRobert.Mastors@Sun.COM krwlock_t dbt_t_lock[1]; /* lock table for resize */ 959885SRobert.Mastors@Sun.COM kmutex_t dbt_lock[1]; /* mutex for count and cached */ 969885SRobert.Mastors@Sun.COM char *dbt_name; /* Table name */ 979885SRobert.Mastors@Sun.COM id_space_t *dbt_id_space; /* space for unique entry ids */ 989885SRobert.Mastors@Sun.COM time_t dbt_min_cache_time; /* How long to cache entries */ 999885SRobert.Mastors@Sun.COM time_t dbt_max_cache_time; /* How long to cache entries */ 1009885SRobert.Mastors@Sun.COM uint32_t dbt_usize; /* User entry size */ 1019885SRobert.Mastors@Sun.COM uint32_t dbt_maxentries; /* max # of entries in table */ 1029885SRobert.Mastors@Sun.COM uint32_t dbt_len; /* # of buckets in table */ 1039885SRobert.Mastors@Sun.COM uint32_t dbt_count; /* # of entries in table */ 1049885SRobert.Mastors@Sun.COM uint32_t dbt_idxcnt; /* # of indices in table */ 1059885SRobert.Mastors@Sun.COM uint32_t dbt_maxcnt; /* max # of indices */ 1069885SRobert.Mastors@Sun.COM uint32_t dbt_ccnt; /* # of creatable entries */ 107*11171Srick.mesta@sun.com uint32_t dbt_id_lwat; /* lo wtrmrk; 50% ids in use */ 108*11171Srick.mesta@sun.com uint32_t dbt_id_hwat; /* hi wtrmrk; 75% ids in use */ 109*11171Srick.mesta@sun.com time_t dbt_id_reap; /* table's reap interval */ 1109885SRobert.Mastors@Sun.COM rfs4_index_t *dbt_indices; /* list of indices */ 1110Sstevel@tonic-gate /* Given entry and data construct entry */ 1129885SRobert.Mastors@Sun.COM bool_t (*dbt_create)(rfs4_entry_t, void *data); 1139885SRobert.Mastors@Sun.COM void (*dbt_destroy)(rfs4_entry_t); /* Destroy entry */ 1149885SRobert.Mastors@Sun.COM bool_t (*dbt_expiry)(rfs4_entry_t); /* Has this entry expired */ 1159885SRobert.Mastors@Sun.COM kmem_cache_t *dbt_mem_cache; /* Cache for table entries */ 1169885SRobert.Mastors@Sun.COM uint32_t dbt_debug; /* Debug Flags */ 1170Sstevel@tonic-gate /* set of vars used for managing the reaper thread */ 1189885SRobert.Mastors@Sun.COM unsigned dbt_reaper_shutdown:1; /* table shutting down? */ 1199885SRobert.Mastors@Sun.COM kcondvar_t dbt_reaper_wait; /* reaper thread waits here */ 1209885SRobert.Mastors@Sun.COM kmutex_t dbt_reaper_cv_lock; /* lock used for cpr wait */ 1219885SRobert.Mastors@Sun.COM callb_cpr_t dbt_reaper_cpr_info; /* cpr the reaper thread */ 1220Sstevel@tonic-gate }; 1230Sstevel@tonic-gate 1240Sstevel@tonic-gate struct rfs4_database { 1259885SRobert.Mastors@Sun.COM kmutex_t db_lock[1]; 1269885SRobert.Mastors@Sun.COM uint32_t db_debug_flags; /* Table debug flags to set */ 1279885SRobert.Mastors@Sun.COM uint32_t db_shutdown_count; /* count to manage shutdown */ 1289885SRobert.Mastors@Sun.COM kcondvar_t db_shutdown_wait; /* where the shutdown waits */ 1299885SRobert.Mastors@Sun.COM rfs4_table_t *db_tables; /* list of tables in db */ 1300Sstevel@tonic-gate }; 1310Sstevel@tonic-gate 1320Sstevel@tonic-gate #define RFS4_RECLAIM_PERCENT 10 1330Sstevel@tonic-gate #define RFS4_REAP_INTERVAL 300 1340Sstevel@tonic-gate 1359885SRobert.Mastors@Sun.COM #define HASH(idx, key) (idx->dbi_hash(key) % idx->dbi_table->dbt_len) 1360Sstevel@tonic-gate 1370Sstevel@tonic-gate #define ENQUEUE(head, l) { \ 1380Sstevel@tonic-gate (l)->prev = NULL; \ 1390Sstevel@tonic-gate (l)->next = (head); \ 1400Sstevel@tonic-gate if ((l)->next) \ 1410Sstevel@tonic-gate (l)->next->prev = (l); \ 1420Sstevel@tonic-gate (head) = (l); \ 1430Sstevel@tonic-gate } 1440Sstevel@tonic-gate 1450Sstevel@tonic-gate #define DEQUEUE(head, l) { \ 1460Sstevel@tonic-gate if ((l)->prev) \ 1470Sstevel@tonic-gate (l)->prev->next = (l)->next; \ 1480Sstevel@tonic-gate else \ 1490Sstevel@tonic-gate (head) = (l)->next; \ 1500Sstevel@tonic-gate if ((l)->next) \ 1510Sstevel@tonic-gate (l)->next->prev = (l)->prev; \ 1520Sstevel@tonic-gate } 1530Sstevel@tonic-gate 1540Sstevel@tonic-gate #define INVALIDATE_ADDR(a) ((a) = (void *)((unsigned long)(a) | 1L)) 1550Sstevel@tonic-gate #define VALIDATE_ADDR(a) ((a) = (void *)((unsigned long)(a) & ~1L)) 1560Sstevel@tonic-gate #define INVALID_ADDR(a) (((unsigned long)(a) & 1L)) 1570Sstevel@tonic-gate #define INVALID_LINK(l) (INVALID_ADDR(l->entry)) 1580Sstevel@tonic-gate 1590Sstevel@tonic-gate #define ENQUEUE_IDX(bp, l) { \ 1609885SRobert.Mastors@Sun.COM rw_enter((bp)->dbk_lock, RW_WRITER); \ 1619885SRobert.Mastors@Sun.COM ENQUEUE((bp)->dbk_head, l); \ 1620Sstevel@tonic-gate VALIDATE_ADDR((l)->entry); \ 1639885SRobert.Mastors@Sun.COM rw_exit((bp)->dbk_lock); \ 1640Sstevel@tonic-gate } 1650Sstevel@tonic-gate 1660Sstevel@tonic-gate #define DEQUEUE_IDX(bp, l) { \ 1679885SRobert.Mastors@Sun.COM rw_enter((bp)->dbk_lock, RW_WRITER); \ 1680Sstevel@tonic-gate INVALIDATE_ADDR((l)->entry); \ 1699885SRobert.Mastors@Sun.COM DEQUEUE((bp)->dbk_head, l); \ 1709885SRobert.Mastors@Sun.COM rw_exit((bp)->dbk_lock); \ 1710Sstevel@tonic-gate } 1720Sstevel@tonic-gate 1730Sstevel@tonic-gate #ifdef __cplusplus 1740Sstevel@tonic-gate } 1750Sstevel@tonic-gate #endif 1760Sstevel@tonic-gate 1770Sstevel@tonic-gate #endif /* _NFS4_DB_IMPL_H */ 178