xref: /onnv-gate/usr/src/uts/common/nfs/nfs4_db_impl.h (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #ifndef	_NFS4_DB_IMPL_H
28*0Sstevel@tonic-gate #define	_NFS4_DB_IMPL_H
29*0Sstevel@tonic-gate 
30*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
31*0Sstevel@tonic-gate 
32*0Sstevel@tonic-gate /*
33*0Sstevel@tonic-gate  * This is a private header file.  Applications should not directly include
34*0Sstevel@tonic-gate  * this file.
35*0Sstevel@tonic-gate  */
36*0Sstevel@tonic-gate 
37*0Sstevel@tonic-gate #ifdef	__cplusplus
38*0Sstevel@tonic-gate extern "C" {
39*0Sstevel@tonic-gate #endif
40*0Sstevel@tonic-gate 
41*0Sstevel@tonic-gate #define	SEARCH_DEBUG	0x0001
42*0Sstevel@tonic-gate #define	CREATE_DEBUG	0x0002
43*0Sstevel@tonic-gate #define	CACHED_DEBUG	0x0004
44*0Sstevel@tonic-gate #define	DESTROY_DEBUG	0x0008
45*0Sstevel@tonic-gate #define	REAP_DEBUG	0x0010
46*0Sstevel@tonic-gate #define	OTHER_DEBUG	0x0020
47*0Sstevel@tonic-gate #define	WALK_DEBUG	0x0040
48*0Sstevel@tonic-gate 
49*0Sstevel@tonic-gate /*
50*0Sstevel@tonic-gate  * A database is made up of a collection of tables.
51*0Sstevel@tonic-gate  * Tables are in turn made up of a collection of
52*0Sstevel@tonic-gate  * entries. Each table may haveone or more indices
53*0Sstevel@tonic-gate  * associtated with it.
54*0Sstevel@tonic-gate  */
55*0Sstevel@tonic-gate 
56*0Sstevel@tonic-gate /* Private implementation */
57*0Sstevel@tonic-gate typedef struct rfs4_link {
58*0Sstevel@tonic-gate 	struct rfs4_link *next;
59*0Sstevel@tonic-gate 	struct rfs4_link *prev;
60*0Sstevel@tonic-gate 	rfs4_dbe_t *entry;
61*0Sstevel@tonic-gate } rfs4_link;
62*0Sstevel@tonic-gate 
63*0Sstevel@tonic-gate struct rfs4_dbe {
64*0Sstevel@tonic-gate 	kmutex_t lock[1];		/* Exclusive lock for entry */
65*0Sstevel@tonic-gate 	uint32_t refcnt;		/* # of references */
66*0Sstevel@tonic-gate 	unsigned skipsearch:1;		/* skip search */
67*0Sstevel@tonic-gate 	unsigned invalid:1;		/* invalid/"freed" entry */
68*0Sstevel@tonic-gate 	unsigned reserved:31;
69*0Sstevel@tonic-gate 	time_t	 time_rele;		/* Time of last rele */
70*0Sstevel@tonic-gate 	id_t	 id;			/* unique identifier */
71*0Sstevel@tonic-gate 	kcondvar_t cv[1];
72*0Sstevel@tonic-gate 	rfs4_entry_t data;
73*0Sstevel@tonic-gate 	rfs4_table_t *table;
74*0Sstevel@tonic-gate 	rfs4_link indices[1];		/* Array of indices for entry */
75*0Sstevel@tonic-gate };
76*0Sstevel@tonic-gate 
77*0Sstevel@tonic-gate typedef struct rfs4_bucket {
78*0Sstevel@tonic-gate 	krwlock_t lock[1];			/* lock hash chain */
79*0Sstevel@tonic-gate 	rfs4_link *head;
80*0Sstevel@tonic-gate } rfs4_bucket;
81*0Sstevel@tonic-gate 
82*0Sstevel@tonic-gate struct rfs4_index {
83*0Sstevel@tonic-gate 	uint32_t tblidx;			/* which indice in entry */
84*0Sstevel@tonic-gate 	bool_t createable;			/* Can create entries */
85*0Sstevel@tonic-gate 	rfs4_table_t *table;			/* Pointer to table */
86*0Sstevel@tonic-gate 	char *keyname;				/* String rep of key */
87*0Sstevel@tonic-gate 	rfs4_bucket *buckets;			/* Hash buckets */
88*0Sstevel@tonic-gate 	uint32_t (*hash)(void *key);		/* Given key find bucket */
89*0Sstevel@tonic-gate 	bool_t (*compare)(rfs4_entry_t, void *key);	/* Key match entry? */
90*0Sstevel@tonic-gate 	void *(*mkkey)(rfs4_entry_t);		/* Given data generate a key */
91*0Sstevel@tonic-gate 	struct rfs4_index *inext;		/* next index on table */
92*0Sstevel@tonic-gate };
93*0Sstevel@tonic-gate 
94*0Sstevel@tonic-gate struct rfs4_table {
95*0Sstevel@tonic-gate 	rfs4_table_t *tnext;			/* next table in db */
96*0Sstevel@tonic-gate 	struct rfs4_database *dbp;		/* db that holds this table */
97*0Sstevel@tonic-gate 	krwlock_t t_lock[1];			/* lock table for resize */
98*0Sstevel@tonic-gate 	kmutex_t lock[1];			/* mutex for count and cached */
99*0Sstevel@tonic-gate 	char *name;				/* Table name */
100*0Sstevel@tonic-gate 	id_space_t *id_space;			/* space for unique entry ids */
101*0Sstevel@tonic-gate 	time_t	min_cache_time;			/* How long to cache entries */
102*0Sstevel@tonic-gate 	time_t	max_cache_time;			/* How long to cache entries */
103*0Sstevel@tonic-gate 	uint32_t usize;				/* User entry size */
104*0Sstevel@tonic-gate 	uint32_t maxentries;			/* max # of entries in table */
105*0Sstevel@tonic-gate 	uint32_t len;				/* # of buckets in table */
106*0Sstevel@tonic-gate 	uint32_t count;				/* # of entries in table */
107*0Sstevel@tonic-gate 	uint32_t idxcnt;			/* # of indices in table */
108*0Sstevel@tonic-gate 	uint32_t maxcnt;			/* max # of indices */
109*0Sstevel@tonic-gate 	uint32_t ccnt;				/* # of creatable entries */
110*0Sstevel@tonic-gate 	rfs4_index_t *indices;			/* list of indices */
111*0Sstevel@tonic-gate 	/* Given entry and data construct entry */
112*0Sstevel@tonic-gate 	bool_t (*create)(rfs4_entry_t, void *data);
113*0Sstevel@tonic-gate 	void (*destroy)(rfs4_entry_t);		/* Destroy entry */
114*0Sstevel@tonic-gate 	bool_t (*expiry)(rfs4_entry_t);		/* Has this entry expired */
115*0Sstevel@tonic-gate 	kmem_cache_t *mem_cache;		/* Cache for table entries */
116*0Sstevel@tonic-gate 	uint32_t debug;				/* Debug Flags */
117*0Sstevel@tonic-gate 	/* set of vars used for managing the reaper thread */
118*0Sstevel@tonic-gate 	unsigned	reaper_shutdown:1;	/* table shutting down? */
119*0Sstevel@tonic-gate 	kcondvar_t reaper_wait;			/* reaper thread waits here */
120*0Sstevel@tonic-gate 	kmutex_t	reaper_cv_lock;		/* lock used for cpr wait */
121*0Sstevel@tonic-gate 	callb_cpr_t	reaper_cpr_info;	/* cpr the reaper thread */
122*0Sstevel@tonic-gate };
123*0Sstevel@tonic-gate 
124*0Sstevel@tonic-gate struct rfs4_database {
125*0Sstevel@tonic-gate 	kmutex_t lock[1];
126*0Sstevel@tonic-gate 	uint32_t debug_flags;			/* Table debug flags to set */
127*0Sstevel@tonic-gate 	uint32_t shutdown_count;		/* count to manage shutdown */
128*0Sstevel@tonic-gate 	kcondvar_t shutdown_wait;		/* where the shutdown waits */
129*0Sstevel@tonic-gate 	rfs4_table_t *tables;			/* list of tables in db */
130*0Sstevel@tonic-gate };
131*0Sstevel@tonic-gate 
132*0Sstevel@tonic-gate #define	RFS4_RECLAIM_PERCENT 10
133*0Sstevel@tonic-gate #define	RFS4_REAP_INTERVAL 300
134*0Sstevel@tonic-gate 
135*0Sstevel@tonic-gate #define	HASH(idx, key) (idx->hash(key) % idx->table->len)
136*0Sstevel@tonic-gate 
137*0Sstevel@tonic-gate #define	ENQUEUE(head, l) { \
138*0Sstevel@tonic-gate 	(l)->prev = NULL; \
139*0Sstevel@tonic-gate 	(l)->next = (head); \
140*0Sstevel@tonic-gate 	if ((l)->next) \
141*0Sstevel@tonic-gate 	    (l)->next->prev = (l); \
142*0Sstevel@tonic-gate 	(head) = (l); \
143*0Sstevel@tonic-gate }
144*0Sstevel@tonic-gate 
145*0Sstevel@tonic-gate #define	DEQUEUE(head, l) { \
146*0Sstevel@tonic-gate 	if ((l)->prev) \
147*0Sstevel@tonic-gate 		(l)->prev->next = (l)->next; \
148*0Sstevel@tonic-gate 	else \
149*0Sstevel@tonic-gate 		(head) = (l)->next; \
150*0Sstevel@tonic-gate 	if ((l)->next) \
151*0Sstevel@tonic-gate 		(l)->next->prev = (l)->prev; \
152*0Sstevel@tonic-gate }
153*0Sstevel@tonic-gate 
154*0Sstevel@tonic-gate #define	INVALIDATE_ADDR(a) ((a) = (void *)((unsigned long)(a) | 1L))
155*0Sstevel@tonic-gate #define	VALIDATE_ADDR(a) ((a) = (void *)((unsigned long)(a) & ~1L))
156*0Sstevel@tonic-gate #define	INVALID_ADDR(a) (((unsigned long)(a) & 1L))
157*0Sstevel@tonic-gate #define	INVALID_LINK(l) (INVALID_ADDR(l->entry))
158*0Sstevel@tonic-gate 
159*0Sstevel@tonic-gate #define	ENQUEUE_IDX(bp, l) { \
160*0Sstevel@tonic-gate 	rw_enter((bp)->lock, RW_WRITER); \
161*0Sstevel@tonic-gate 	ENQUEUE((bp)->head, l); \
162*0Sstevel@tonic-gate 	VALIDATE_ADDR((l)->entry); \
163*0Sstevel@tonic-gate 	rw_exit((bp)->lock); \
164*0Sstevel@tonic-gate }
165*0Sstevel@tonic-gate 
166*0Sstevel@tonic-gate #define	DEQUEUE_IDX(bp, l) { \
167*0Sstevel@tonic-gate 	rw_enter((bp)->lock, RW_WRITER); \
168*0Sstevel@tonic-gate 	INVALIDATE_ADDR((l)->entry); \
169*0Sstevel@tonic-gate 	DEQUEUE((bp)->head, l); \
170*0Sstevel@tonic-gate 	rw_exit((bp)->lock); \
171*0Sstevel@tonic-gate }
172*0Sstevel@tonic-gate 
173*0Sstevel@tonic-gate #ifdef	__cplusplus
174*0Sstevel@tonic-gate }
175*0Sstevel@tonic-gate #endif
176*0Sstevel@tonic-gate 
177*0Sstevel@tonic-gate #endif /* _NFS4_DB_IMPL_H */
178