xref: /onnv-gate/usr/src/uts/common/nfs/nfs4_db_impl.h (revision 9885:a3d5e9d9e779)
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