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