author | calum |
Tue, 18 Jul 2006 04:09:41 -0700 | |
changeset 2390 | ffba0dc9ebeb |
parent 2035 | a29bc457bcb9 |
child 2668 | 1f2fb37babae |
permissions | -rw-r--r-- |
0 | 1 |
/* |
2 |
* CDDL HEADER START |
|
3 |
* |
|
4 |
* The contents of this file are subject to the terms of the |
|
2035
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
5 |
* Common Development and Distribution License (the "License"). |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
6 |
* You may not use this file except in compliance with the License. |
0 | 7 |
* |
8 |
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE |
|
9 |
* or http://www.opensolaris.org/os/licensing. |
|
10 |
* See the License for the specific language governing permissions |
|
11 |
* and limitations under the License. |
|
12 |
* |
|
13 |
* When distributing Covered Code, include this CDDL HEADER in each |
|
14 |
* file and include the License file at usr/src/OPENSOLARIS.LICENSE. |
|
15 |
* If applicable, add the following below this CDDL HEADER, with the |
|
16 |
* fields enclosed by brackets "[]" replaced with your own identifying |
|
17 |
* information: Portions Copyright [yyyy] [name of copyright owner] |
|
18 |
* |
|
19 |
* CDDL HEADER END |
|
20 |
*/ |
|
21 |
/* |
|
2035
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
22 |
* Copyright 2006 Sun Microsystems, Inc. All rights reserved. |
0 | 23 |
* Use is subject to license terms. |
24 |
*/ |
|
25 |
||
26 |
#pragma ident "%Z%%M% %I% %E% SMI" |
|
27 |
||
28 |
#include <sys/systm.h> |
|
29 |
#include <sys/kmem.h> |
|
30 |
#include <sys/cmn_err.h> |
|
31 |
#include <sys/atomic.h> |
|
32 |
#include <sys/clconf.h> |
|
33 |
#include <sys/cladm.h> |
|
34 |
#include <sys/flock.h> |
|
35 |
#include <nfs/export.h> |
|
36 |
#include <nfs/nfs.h> |
|
37 |
#include <nfs/nfs4.h> |
|
38 |
#include <nfs/nfssys.h> |
|
39 |
#include <nfs/lm.h> |
|
40 |
#include <sys/pathname.h> |
|
2035
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
41 |
#include <sys/nvpair.h> |
0 | 42 |
|
43 |
||
44 |
extern time_t rfs4_start_time; |
|
45 |
||
46 |
stateid4 special0 = { |
|
47 |
0, |
|
48 |
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } |
|
49 |
}; |
|
50 |
||
51 |
stateid4 special1 = { |
|
52 |
0xffffffff, |
|
53 |
{ |
|
54 |
(char)0xff, (char)0xff, (char)0xff, (char)0xff, |
|
55 |
(char)0xff, (char)0xff, (char)0xff, (char)0xff, |
|
56 |
(char)0xff, (char)0xff, (char)0xff, (char)0xff |
|
57 |
} |
|
58 |
}; |
|
59 |
||
60 |
||
61 |
#define ISSPECIAL(id) (stateid4_cmp(id, &special0) || \ |
|
62 |
stateid4_cmp(id, &special1)) |
|
63 |
||
64 |
/* For embedding the cluster nodeid into our clientid */ |
|
65 |
#define CLUSTER_NODEID_SHIFT 24 |
|
66 |
#define CLUSTER_MAX_NODEID 255 |
|
67 |
||
68 |
#ifdef DEBUG |
|
69 |
int rfs4_debug; |
|
70 |
#endif |
|
71 |
||
72 |
static uint32_t rfs4_database_debug = 0x00; |
|
73 |
||
2035
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
74 |
static void rfs4_ss_clid_write(rfs4_client_t *cp, char *leaf); |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
75 |
static void rfs4_ss_clid_write_one(rfs4_client_t *cp, char *dir, char *leaf); |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
76 |
static void rfs4_dss_clear_oldstate(rfs4_servinst_t *sip); |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
77 |
static void rfs4_ss_chkclid_sip(rfs4_client_t *cp, rfs4_servinst_t *sip); |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
78 |
|
0 | 79 |
/* |
80 |
* Couple of simple init/destroy functions for a general waiter |
|
81 |
*/ |
|
82 |
void |
|
83 |
rfs4_sw_init(rfs4_state_wait_t *swp) |
|
84 |
{ |
|
85 |
mutex_init(swp->sw_cv_lock, NULL, MUTEX_DEFAULT, NULL); |
|
86 |
cv_init(swp->sw_cv, NULL, CV_DEFAULT, NULL); |
|
87 |
swp->sw_active = FALSE; |
|
88 |
swp->sw_wait_count = 0; |
|
89 |
} |
|
90 |
||
91 |
void |
|
92 |
rfs4_sw_destroy(rfs4_state_wait_t *swp) |
|
93 |
{ |
|
94 |
mutex_destroy(swp->sw_cv_lock); |
|
95 |
cv_destroy(swp->sw_cv); |
|
96 |
} |
|
97 |
||
98 |
void |
|
99 |
rfs4_sw_enter(rfs4_state_wait_t *swp) |
|
100 |
{ |
|
101 |
mutex_enter(swp->sw_cv_lock); |
|
102 |
while (swp->sw_active) { |
|
103 |
swp->sw_wait_count++; |
|
104 |
cv_wait(swp->sw_cv, swp->sw_cv_lock); |
|
105 |
swp->sw_wait_count--; |
|
106 |
} |
|
107 |
ASSERT(swp->sw_active == FALSE); |
|
108 |
swp->sw_active = TRUE; |
|
109 |
mutex_exit(swp->sw_cv_lock); |
|
110 |
} |
|
111 |
||
112 |
void |
|
113 |
rfs4_sw_exit(rfs4_state_wait_t *swp) |
|
114 |
{ |
|
115 |
mutex_enter(swp->sw_cv_lock); |
|
116 |
ASSERT(swp->sw_active == TRUE); |
|
117 |
swp->sw_active = FALSE; |
|
118 |
if (swp->sw_wait_count != 0) |
|
119 |
cv_broadcast(swp->sw_cv); |
|
120 |
mutex_exit(swp->sw_cv_lock); |
|
121 |
} |
|
122 |
||
123 |
/* |
|
124 |
* CPR callback id -- not related to v4 callbacks |
|
125 |
*/ |
|
126 |
static callb_id_t cpr_id = 0; |
|
127 |
||
128 |
static void |
|
129 |
deep_lock_copy(LOCK4res *dres, LOCK4res *sres) |
|
130 |
{ |
|
131 |
lock_owner4 *slo = &sres->LOCK4res_u.denied.owner; |
|
132 |
lock_owner4 *dlo = &dres->LOCK4res_u.denied.owner; |
|
133 |
||
134 |
if (sres->status == NFS4ERR_DENIED) { |
|
135 |
dlo->owner_val = kmem_alloc(slo->owner_len, KM_SLEEP); |
|
136 |
bcopy(slo->owner_val, dlo->owner_val, slo->owner_len); |
|
137 |
} |
|
138 |
} |
|
139 |
||
140 |
static void |
|
141 |
deep_lock_free(LOCK4res *res) |
|
142 |
{ |
|
143 |
lock_owner4 *lo = &res->LOCK4res_u.denied.owner; |
|
144 |
||
145 |
if (res->status == NFS4ERR_DENIED) |
|
146 |
kmem_free(lo->owner_val, lo->owner_len); |
|
147 |
} |
|
148 |
||
149 |
static void |
|
150 |
deep_open_copy(OPEN4res *dres, OPEN4res *sres) |
|
151 |
{ |
|
152 |
nfsace4 *sacep, *dacep; |
|
153 |
||
154 |
if (sres->status != NFS4_OK) { |
|
155 |
return; |
|
156 |
} |
|
157 |
||
158 |
dres->attrset = sres->attrset; |
|
159 |
||
160 |
switch (sres->delegation.delegation_type) { |
|
161 |
case OPEN_DELEGATE_NONE: |
|
162 |
return; |
|
163 |
case OPEN_DELEGATE_READ: |
|
164 |
sacep = &sres->delegation.open_delegation4_u.read.permissions; |
|
165 |
dacep = &dres->delegation.open_delegation4_u.read.permissions; |
|
166 |
break; |
|
167 |
case OPEN_DELEGATE_WRITE: |
|
168 |
sacep = &sres->delegation.open_delegation4_u.write.permissions; |
|
169 |
dacep = &dres->delegation.open_delegation4_u.write.permissions; |
|
170 |
break; |
|
171 |
} |
|
172 |
dacep->who.utf8string_val = |
|
173 |
kmem_alloc(sacep->who.utf8string_len, KM_SLEEP); |
|
174 |
bcopy(sacep->who.utf8string_val, dacep->who.utf8string_val, |
|
175 |
sacep->who.utf8string_len); |
|
176 |
} |
|
177 |
||
178 |
static void |
|
179 |
deep_open_free(OPEN4res *res) |
|
180 |
{ |
|
181 |
nfsace4 *acep; |
|
182 |
if (res->status != NFS4_OK) |
|
183 |
return; |
|
184 |
||
185 |
switch (res->delegation.delegation_type) { |
|
186 |
case OPEN_DELEGATE_NONE: |
|
187 |
return; |
|
188 |
case OPEN_DELEGATE_READ: |
|
189 |
acep = &res->delegation.open_delegation4_u.read.permissions; |
|
190 |
break; |
|
191 |
case OPEN_DELEGATE_WRITE: |
|
192 |
acep = &res->delegation.open_delegation4_u.write.permissions; |
|
193 |
break; |
|
194 |
} |
|
195 |
||
196 |
if (acep->who.utf8string_val) { |
|
197 |
kmem_free(acep->who.utf8string_val, acep->who.utf8string_len); |
|
198 |
acep->who.utf8string_val = NULL; |
|
199 |
} |
|
200 |
} |
|
201 |
||
202 |
void |
|
203 |
rfs4_free_reply(nfs_resop4 *rp) |
|
204 |
{ |
|
205 |
switch (rp->resop) { |
|
206 |
case OP_LOCK: |
|
207 |
deep_lock_free(&rp->nfs_resop4_u.oplock); |
|
208 |
break; |
|
209 |
case OP_OPEN: |
|
210 |
deep_open_free(&rp->nfs_resop4_u.opopen); |
|
211 |
default: |
|
212 |
break; |
|
213 |
} |
|
214 |
} |
|
215 |
||
216 |
void |
|
217 |
rfs4_copy_reply(nfs_resop4 *dst, nfs_resop4 *src) |
|
218 |
{ |
|
219 |
*dst = *src; |
|
220 |
||
221 |
/* Handle responses that need deep copy */ |
|
222 |
switch (src->resop) { |
|
223 |
case OP_LOCK: |
|
224 |
deep_lock_copy(&dst->nfs_resop4_u.oplock, |
|
225 |
&src->nfs_resop4_u.oplock); |
|
226 |
break; |
|
227 |
case OP_OPEN: |
|
228 |
deep_open_copy(&dst->nfs_resop4_u.opopen, |
|
229 |
&src->nfs_resop4_u.opopen); |
|
230 |
break; |
|
231 |
default: |
|
232 |
break; |
|
233 |
}; |
|
234 |
} |
|
235 |
||
236 |
/* |
|
237 |
* This is the implementation of the underlying state engine. The |
|
238 |
* public interface to this engine is described by |
|
239 |
* nfs4_state.h. Callers to the engine should hold no state engine |
|
240 |
* locks when they call in to it. If the protocol needs to lock data |
|
241 |
* structures it should do so after acquiring all references to them |
|
242 |
* first and then follow the following lock order: |
|
243 |
* |
|
244 |
* client > openowner > state > lo_state > lockowner > file. |
|
245 |
* |
|
246 |
* Internally we only allow a thread to hold one hash bucket lock at a |
|
247 |
* time and the lock is higher in the lock order (must be acquired |
|
248 |
* first) than the data structure that is on that hash list. |
|
249 |
* |
|
250 |
* If a new reference was acquired by the caller, that reference needs |
|
251 |
* to be released after releasing all acquired locks with the |
|
252 |
* corresponding rfs4_*_rele routine. |
|
253 |
*/ |
|
254 |
||
255 |
/* |
|
256 |
* This code is some what prototypical for now. Its purpose currently is to |
|
257 |
* implement the interfaces sufficiently to finish the higher protocol |
|
258 |
* elements. This will be replaced by a dynamically resizeable tables |
|
259 |
* backed by kmem_cache allocator. However synchronization is handled |
|
260 |
* correctly (I hope) and will not change by much. The mutexes for |
|
261 |
* the hash buckets that can be used to create new instances of data |
|
262 |
* structures might be good candidates to evolve into reader writer |
|
263 |
* locks. If it has to do a creation, it would be holding the |
|
264 |
* mutex across a kmem_alloc with KM_SLEEP specified. |
|
265 |
*/ |
|
266 |
||
267 |
#ifdef DEBUG |
|
268 |
#define TABSIZE 17 |
|
269 |
#else |
|
270 |
#define TABSIZE 2047 |
|
271 |
#endif |
|
272 |
||
273 |
#define ADDRHASH(key) ((unsigned long)(key) >> 3) |
|
274 |
||
275 |
/* Used to serialize create/destroy of rfs4_server_state database */ |
|
276 |
kmutex_t rfs4_state_lock; |
|
277 |
static rfs4_database_t *rfs4_server_state = NULL; |
|
278 |
||
279 |
/* Used to serialize lookups of clientids */ |
|
280 |
static krwlock_t rfs4_findclient_lock; |
|
281 |
||
282 |
/* |
|
283 |
* For now this "table" is exposed so that the CPR callback |
|
284 |
* function can tromp through it.. |
|
285 |
*/ |
|
286 |
rfs4_table_t *rfs4_client_tab; |
|
287 |
||
288 |
static rfs4_index_t *rfs4_clientid_idx; |
|
289 |
static rfs4_index_t *rfs4_nfsclnt_idx; |
|
290 |
static rfs4_table_t *rfs4_openowner_tab; |
|
291 |
static rfs4_index_t *rfs4_openowner_idx; |
|
292 |
static rfs4_table_t *rfs4_state_tab; |
|
293 |
static rfs4_index_t *rfs4_state_idx; |
|
294 |
static rfs4_index_t *rfs4_state_owner_file_idx; |
|
295 |
static rfs4_index_t *rfs4_state_file_idx; |
|
296 |
static rfs4_table_t *rfs4_lo_state_tab; |
|
297 |
static rfs4_index_t *rfs4_lo_state_idx; |
|
298 |
static rfs4_index_t *rfs4_lo_state_owner_idx; |
|
299 |
static rfs4_table_t *rfs4_lockowner_tab; |
|
300 |
static rfs4_index_t *rfs4_lockowner_idx; |
|
301 |
static rfs4_index_t *rfs4_lockowner_pid_idx; |
|
302 |
static rfs4_table_t *rfs4_file_tab; |
|
303 |
static rfs4_index_t *rfs4_file_idx; |
|
304 |
static rfs4_table_t *rfs4_deleg_state_tab; |
|
305 |
static rfs4_index_t *rfs4_deleg_idx; |
|
306 |
static rfs4_index_t *rfs4_deleg_state_idx; |
|
307 |
||
308 |
#define MAXTABSZ 1024*1024 |
|
309 |
||
310 |
/* The values below are rfs4_lease_time units */ |
|
311 |
||
312 |
#ifdef DEBUG |
|
313 |
#define CLIENT_CACHE_TIME 1 |
|
314 |
#define OPENOWNER_CACHE_TIME 1 |
|
315 |
#define STATE_CACHE_TIME 1 |
|
316 |
#define LO_STATE_CACHE_TIME 1 |
|
317 |
#define LOCKOWNER_CACHE_TIME 1 |
|
318 |
#define FILE_CACHE_TIME 3 |
|
319 |
#define DELEG_STATE_CACHE_TIME 1 |
|
320 |
#else |
|
321 |
#define CLIENT_CACHE_TIME 10 |
|
322 |
#define OPENOWNER_CACHE_TIME 5 |
|
323 |
#define STATE_CACHE_TIME 1 |
|
324 |
#define LO_STATE_CACHE_TIME 1 |
|
325 |
#define LOCKOWNER_CACHE_TIME 3 |
|
326 |
#define FILE_CACHE_TIME 40 |
|
327 |
#define DELEG_STATE_CACHE_TIME 1 |
|
328 |
#endif |
|
329 |
||
330 |
||
331 |
static time_t rfs4_client_cache_time = 0; |
|
332 |
static time_t rfs4_openowner_cache_time = 0; |
|
333 |
static time_t rfs4_state_cache_time = 0; |
|
334 |
static time_t rfs4_lo_state_cache_time = 0; |
|
335 |
static time_t rfs4_lockowner_cache_time = 0; |
|
336 |
static time_t rfs4_file_cache_time = 0; |
|
337 |
static time_t rfs4_deleg_state_cache_time = 0; |
|
338 |
||
339 |
static bool_t rfs4_client_create(rfs4_entry_t, void *); |
|
2035
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
340 |
static void rfs4_dss_remove_cpleaf(rfs4_client_t *); |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
341 |
static void rfs4_dss_remove_leaf(rfs4_servinst_t *, char *, char *); |
0 | 342 |
static void rfs4_client_destroy(rfs4_entry_t); |
343 |
static bool_t rfs4_client_expiry(rfs4_entry_t); |
|
344 |
static uint32_t clientid_hash(void *); |
|
345 |
static bool_t clientid_compare(rfs4_entry_t, void *); |
|
346 |
static void *clientid_mkkey(rfs4_entry_t); |
|
347 |
static uint32_t nfsclnt_hash(void *); |
|
348 |
static bool_t nfsclnt_compare(rfs4_entry_t, void *); |
|
349 |
static void *nfsclnt_mkkey(rfs4_entry_t); |
|
350 |
static bool_t rfs4_openowner_create(rfs4_entry_t, void *); |
|
351 |
static void rfs4_openowner_destroy(rfs4_entry_t); |
|
352 |
static bool_t rfs4_openowner_expiry(rfs4_entry_t); |
|
353 |
static uint32_t openowner_hash(void *); |
|
354 |
static bool_t openowner_compare(rfs4_entry_t, void *); |
|
355 |
static void *openowner_mkkey(rfs4_entry_t); |
|
356 |
static bool_t rfs4_state_create(rfs4_entry_t, void *); |
|
357 |
static void rfs4_state_destroy(rfs4_entry_t); |
|
358 |
static bool_t rfs4_state_expiry(rfs4_entry_t); |
|
359 |
static uint32_t state_hash(void *); |
|
360 |
static bool_t state_compare(rfs4_entry_t, void *); |
|
361 |
static void *state_mkkey(rfs4_entry_t); |
|
362 |
static uint32_t state_owner_file_hash(void *); |
|
363 |
static bool_t state_owner_file_compare(rfs4_entry_t, void *); |
|
364 |
static void *state_owner_file_mkkey(rfs4_entry_t); |
|
365 |
static uint32_t state_file_hash(void *); |
|
366 |
static bool_t state_file_compare(rfs4_entry_t, void *); |
|
367 |
static void *state_file_mkkey(rfs4_entry_t); |
|
368 |
static bool_t rfs4_lo_state_create(rfs4_entry_t, void *); |
|
369 |
static void rfs4_lo_state_destroy(rfs4_entry_t); |
|
370 |
static bool_t rfs4_lo_state_expiry(rfs4_entry_t); |
|
371 |
static uint32_t lo_state_hash(void *); |
|
372 |
static bool_t lo_state_compare(rfs4_entry_t, void *); |
|
373 |
static void *lo_state_mkkey(rfs4_entry_t); |
|
374 |
static uint32_t lo_state_lo_hash(void *); |
|
375 |
static bool_t lo_state_lo_compare(rfs4_entry_t, void *); |
|
376 |
static void *lo_state_lo_mkkey(rfs4_entry_t); |
|
377 |
static bool_t rfs4_lockowner_create(rfs4_entry_t, void *); |
|
378 |
static void rfs4_lockowner_destroy(rfs4_entry_t); |
|
379 |
static bool_t rfs4_lockowner_expiry(rfs4_entry_t); |
|
380 |
static uint32_t lockowner_hash(void *); |
|
381 |
static bool_t lockowner_compare(rfs4_entry_t, void *); |
|
382 |
static void *lockowner_mkkey(rfs4_entry_t); |
|
383 |
static uint32_t pid_hash(void *); |
|
384 |
static bool_t pid_compare(rfs4_entry_t, void *); |
|
385 |
static void *pid_mkkey(rfs4_entry_t); |
|
386 |
static bool_t rfs4_file_create(rfs4_entry_t, void *); |
|
387 |
static void rfs4_file_destroy(rfs4_entry_t); |
|
388 |
static uint32_t file_hash(void *); |
|
389 |
static bool_t file_compare(rfs4_entry_t, void *); |
|
390 |
static void *file_mkkey(rfs4_entry_t); |
|
391 |
static bool_t rfs4_deleg_state_create(rfs4_entry_t, void *); |
|
392 |
static void rfs4_deleg_state_destroy(rfs4_entry_t); |
|
393 |
static bool_t rfs4_deleg_state_expiry(rfs4_entry_t); |
|
394 |
static uint32_t deleg_hash(void *); |
|
395 |
static bool_t deleg_compare(rfs4_entry_t, void *); |
|
396 |
static void *deleg_mkkey(rfs4_entry_t); |
|
397 |
static uint32_t deleg_state_hash(void *); |
|
398 |
static bool_t deleg_state_compare(rfs4_entry_t, void *); |
|
399 |
static void *deleg_state_mkkey(rfs4_entry_t); |
|
400 |
||
401 |
static void rfs4_state_rele_nounlock(rfs4_state_t *); |
|
402 |
||
403 |
static int rfs4_ss_enabled = 0; |
|
404 |
||
405 |
extern void (*rfs4_client_clrst)(struct nfs4clrst_args *); |
|
406 |
||
407 |
void |
|
408 |
rfs4_ss_pnfree(rfs4_ss_pn_t *ss_pn) |
|
409 |
{ |
|
410 |
kmem_free(ss_pn, sizeof (rfs4_ss_pn_t)); |
|
411 |
} |
|
412 |
||
413 |
static rfs4_ss_pn_t * |
|
414 |
rfs4_ss_pnalloc(char *dir, char *leaf) |
|
415 |
{ |
|
416 |
rfs4_ss_pn_t *ss_pn; |
|
417 |
int dir_len, leaf_len; |
|
418 |
||
419 |
/* |
|
420 |
* validate we have a resonable path |
|
421 |
* (account for the '/' and trailing null) |
|
422 |
*/ |
|
423 |
if ((dir_len = strlen(dir)) > MAXPATHLEN || |
|
424 |
(leaf_len = strlen(leaf)) > MAXNAMELEN || |
|
425 |
(dir_len + leaf_len + 2) > MAXPATHLEN) { |
|
426 |
return (NULL); |
|
427 |
} |
|
428 |
||
429 |
ss_pn = kmem_alloc(sizeof (rfs4_ss_pn_t), KM_SLEEP); |
|
430 |
||
431 |
(void) snprintf(ss_pn->pn, MAXPATHLEN, "%s/%s", dir, leaf); |
|
432 |
/* Handy pointer to just the leaf name */ |
|
433 |
ss_pn->leaf = ss_pn->pn + dir_len + 1; |
|
434 |
return (ss_pn); |
|
435 |
} |
|
436 |
||
437 |
||
438 |
/* |
|
439 |
* Move the "leaf" filename from "sdir" directory |
|
440 |
* to the "ddir" directory. Return the pathname of |
|
441 |
* the destination unless the rename fails in which |
|
442 |
* case we need to return the source pathname. |
|
443 |
*/ |
|
444 |
static rfs4_ss_pn_t * |
|
445 |
rfs4_ss_movestate(char *sdir, char *ddir, char *leaf) |
|
446 |
{ |
|
447 |
rfs4_ss_pn_t *src, *dst; |
|
448 |
||
2035
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
449 |
if ((src = rfs4_ss_pnalloc(sdir, leaf)) == NULL) |
0 | 450 |
return (NULL); |
451 |
||
452 |
if ((dst = rfs4_ss_pnalloc(ddir, leaf)) == NULL) { |
|
453 |
rfs4_ss_pnfree(src); |
|
454 |
return (NULL); |
|
455 |
} |
|
456 |
||
457 |
/* |
|
458 |
* If the rename fails we shall return the src |
|
459 |
* pathname and free the dst. Otherwise we need |
|
460 |
* to free the src and return the dst pathanme. |
|
461 |
*/ |
|
462 |
if (vn_rename(src->pn, dst->pn, UIO_SYSSPACE)) { |
|
463 |
rfs4_ss_pnfree(dst); |
|
464 |
return (src); |
|
465 |
} |
|
466 |
rfs4_ss_pnfree(src); |
|
467 |
return (dst); |
|
468 |
} |
|
469 |
||
470 |
||
471 |
static rfs4_oldstate_t * |
|
472 |
rfs4_ss_getstate(vnode_t *dvp, rfs4_ss_pn_t *ss_pn) |
|
473 |
{ |
|
474 |
struct uio uio; |
|
475 |
struct iovec iov[3]; |
|
476 |
||
477 |
rfs4_oldstate_t *cl_ss = NULL; |
|
478 |
vnode_t *vp; |
|
479 |
vattr_t va; |
|
480 |
uint_t id_len; |
|
481 |
int err, kill_file, file_vers; |
|
482 |
||
2035
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
483 |
if (ss_pn == NULL) |
0 | 484 |
return (NULL); |
485 |
||
486 |
/* |
|
487 |
* open the state file. |
|
488 |
*/ |
|
489 |
if (vn_open(ss_pn->pn, UIO_SYSSPACE, FREAD, 0, &vp, 0, 0) != 0) { |
|
490 |
return (NULL); |
|
491 |
} |
|
492 |
||
493 |
if (vp->v_type != VREG) { |
|
494 |
(void) VOP_CLOSE(vp, FREAD, 1, (offset_t)0, CRED()); |
|
495 |
VN_RELE(vp); |
|
496 |
return (NULL); |
|
497 |
} |
|
498 |
||
499 |
err = VOP_ACCESS(vp, VREAD, 0, CRED()); |
|
500 |
if (err) { |
|
501 |
/* |
|
502 |
* We don't have read access? better get the heck out. |
|
503 |
*/ |
|
504 |
(void) VOP_CLOSE(vp, FREAD, 1, (offset_t)0, CRED()); |
|
505 |
VN_RELE(vp); |
|
506 |
return (NULL); |
|
507 |
} |
|
508 |
||
509 |
(void) VOP_RWLOCK(vp, V_WRITELOCK_FALSE, NULL); |
|
510 |
/* |
|
511 |
* get the file size to do some basic validation |
|
512 |
*/ |
|
513 |
va.va_mask = AT_SIZE; |
|
514 |
err = VOP_GETATTR(vp, &va, 0, CRED()); |
|
515 |
||
516 |
kill_file = (va.va_size == 0 || va.va_size < |
|
517 |
(NFS4_VERIFIER_SIZE + sizeof (uint_t)+1)); |
|
518 |
||
519 |
if (err || kill_file) { |
|
520 |
VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, NULL); |
|
521 |
(void) VOP_CLOSE(vp, FREAD, 1, (offset_t)0, CRED()); |
|
522 |
VN_RELE(vp); |
|
523 |
if (kill_file) { |
|
524 |
(void) VOP_REMOVE(dvp, ss_pn->leaf, CRED()); |
|
525 |
} |
|
526 |
return (NULL); |
|
527 |
} |
|
528 |
||
529 |
cl_ss = kmem_alloc(sizeof (rfs4_oldstate_t), KM_SLEEP); |
|
530 |
||
531 |
/* |
|
532 |
* build iovecs to read in the file_version, verifier and id_len |
|
533 |
*/ |
|
534 |
iov[0].iov_base = (caddr_t)&file_vers; |
|
535 |
iov[0].iov_len = sizeof (int); |
|
2035
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
536 |
iov[1].iov_base = (caddr_t)&cl_ss->cl_id4.verifier; |
0 | 537 |
iov[1].iov_len = NFS4_VERIFIER_SIZE; |
538 |
iov[2].iov_base = (caddr_t)&id_len; |
|
539 |
iov[2].iov_len = sizeof (uint_t); |
|
540 |
||
541 |
uio.uio_iov = iov; |
|
542 |
uio.uio_iovcnt = 3; |
|
543 |
uio.uio_segflg = UIO_SYSSPACE; |
|
544 |
uio.uio_loffset = 0; |
|
545 |
uio.uio_resid = sizeof (int) + NFS4_VERIFIER_SIZE + sizeof (uint_t); |
|
546 |
||
547 |
if (err = VOP_READ(vp, &uio, FREAD, CRED(), NULL)) { |
|
548 |
VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, NULL); |
|
549 |
(void) VOP_CLOSE(vp, FREAD, 1, (offset_t)0, CRED()); |
|
550 |
VN_RELE(vp); |
|
551 |
kmem_free(cl_ss, sizeof (rfs4_oldstate_t)); |
|
552 |
return (NULL); |
|
553 |
} |
|
554 |
||
555 |
/* |
|
556 |
* if the file_version doesn't match or if the |
|
557 |
* id_len is zero or the combination of the verifier, |
|
558 |
* id_len and id_val is bigger than the file we have |
|
559 |
* a problem. If so ditch the file. |
|
560 |
*/ |
|
561 |
kill_file = (file_vers != NFS4_SS_VERSION || id_len == 0 || |
|
562 |
(id_len + NFS4_VERIFIER_SIZE + sizeof (uint_t)) > va.va_size); |
|
563 |
||
564 |
if (err || kill_file) { |
|
565 |
VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, NULL); |
|
566 |
(void) VOP_CLOSE(vp, FREAD, 1, (offset_t)0, CRED()); |
|
567 |
VN_RELE(vp); |
|
568 |
kmem_free(cl_ss, sizeof (rfs4_oldstate_t)); |
|
569 |
if (kill_file) { |
|
570 |
(void) VOP_REMOVE(dvp, ss_pn->leaf, CRED()); |
|
571 |
} |
|
572 |
return (NULL); |
|
573 |
} |
|
574 |
||
575 |
/* |
|
576 |
* now get the client id value |
|
577 |
*/ |
|
578 |
cl_ss->cl_id4.id_val = kmem_alloc(id_len, KM_SLEEP); |
|
579 |
iov[0].iov_base = cl_ss->cl_id4.id_val; |
|
580 |
iov[0].iov_len = id_len; |
|
581 |
||
582 |
uio.uio_iov = iov; |
|
583 |
uio.uio_iovcnt = 1; |
|
584 |
uio.uio_segflg = UIO_SYSSPACE; |
|
585 |
uio.uio_resid = cl_ss->cl_id4.id_len = id_len; |
|
586 |
||
587 |
if (err = VOP_READ(vp, &uio, FREAD, CRED(), NULL)) { |
|
588 |
VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, NULL); |
|
589 |
(void) VOP_CLOSE(vp, FREAD, 1, (offset_t)0, CRED()); |
|
590 |
VN_RELE(vp); |
|
591 |
kmem_free(cl_ss->cl_id4.id_val, id_len); |
|
592 |
kmem_free(cl_ss, sizeof (rfs4_oldstate_t)); |
|
593 |
return (NULL); |
|
594 |
} |
|
595 |
||
596 |
VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, NULL); |
|
597 |
(void) VOP_CLOSE(vp, FREAD, 1, (offset_t)0, CRED()); |
|
598 |
VN_RELE(vp); |
|
599 |
return (cl_ss); |
|
600 |
} |
|
601 |
||
602 |
#ifdef nextdp |
|
603 |
#undef nextdp |
|
604 |
#endif |
|
605 |
#define nextdp(dp) ((struct dirent64 *)((char *)(dp) + (dp)->d_reclen)) |
|
606 |
||
607 |
/* |
|
2035
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
608 |
* Add entries from statedir to supplied oldstate list. |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
609 |
* Optionally, move all entries from statedir -> destdir. |
0 | 610 |
*/ |
611 |
void |
|
2035
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
612 |
rfs4_ss_oldstate(rfs4_oldstate_t *oldstate, char *statedir, char *destdir) |
0 | 613 |
{ |
614 |
rfs4_ss_pn_t *ss_pn; |
|
615 |
rfs4_oldstate_t *cl_ss = NULL; |
|
616 |
char *dirt = NULL; |
|
617 |
int err, dir_eof = 0, size = 0; |
|
618 |
vnode_t *dvp; |
|
619 |
struct iovec iov; |
|
620 |
struct uio uio; |
|
621 |
struct dirent64 *dep; |
|
622 |
offset_t dirchunk_offset = 0; |
|
623 |
||
624 |
/* |
|
625 |
* open the state directory |
|
626 |
*/ |
|
2035
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
627 |
if (vn_open(statedir, UIO_SYSSPACE, FREAD, 0, &dvp, 0, 0)) |
0 | 628 |
return; |
2035
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
629 |
|
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
630 |
if (dvp->v_type != VDIR || VOP_ACCESS(dvp, VREAD, 0, CRED())) |
0 | 631 |
goto out; |
632 |
||
633 |
dirt = kmem_alloc(RFS4_SS_DIRSIZE, KM_SLEEP); |
|
634 |
||
635 |
/* |
|
636 |
* Get and process the directory entries |
|
637 |
*/ |
|
638 |
while (!dir_eof) { |
|
639 |
(void) VOP_RWLOCK(dvp, V_WRITELOCK_FALSE, NULL); |
|
640 |
iov.iov_base = dirt; |
|
641 |
iov.iov_len = RFS4_SS_DIRSIZE; |
|
642 |
uio.uio_iov = &iov; |
|
643 |
uio.uio_iovcnt = 1; |
|
644 |
uio.uio_segflg = UIO_SYSSPACE; |
|
645 |
uio.uio_loffset = dirchunk_offset; |
|
646 |
uio.uio_resid = RFS4_SS_DIRSIZE; |
|
647 |
||
648 |
err = VOP_READDIR(dvp, &uio, CRED(), &dir_eof); |
|
649 |
VOP_RWUNLOCK(dvp, V_WRITELOCK_FALSE, NULL); |
|
2035
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
650 |
if (err) |
0 | 651 |
goto out; |
652 |
||
653 |
size = RFS4_SS_DIRSIZE - uio.uio_resid; |
|
654 |
||
655 |
/* |
|
656 |
* Process all the directory entries in this |
|
657 |
* readdir chunk |
|
658 |
*/ |
|
659 |
for (dep = (struct dirent64 *)dirt; size > 0; |
|
660 |
dep = nextdp(dep)) { |
|
661 |
||
662 |
size -= dep->d_reclen; |
|
663 |
dirchunk_offset = dep->d_off; |
|
664 |
||
665 |
/* |
|
666 |
* Skip '.' and '..' |
|
667 |
*/ |
|
2035
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
668 |
if (NFS_IS_DOTNAME(dep->d_name)) |
0 | 669 |
continue; |
2035
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
670 |
|
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
671 |
ss_pn = rfs4_ss_pnalloc(statedir, dep->d_name); |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
672 |
if (ss_pn == NULL) |
0 | 673 |
continue; |
674 |
||
675 |
if (cl_ss = rfs4_ss_getstate(dvp, ss_pn)) { |
|
2035
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
676 |
if (destdir != NULL) { |
0 | 677 |
rfs4_ss_pnfree(ss_pn); |
678 |
cl_ss->ss_pn = rfs4_ss_movestate( |
|
2035
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
679 |
statedir, destdir, dep->d_name); |
0 | 680 |
} else { |
681 |
cl_ss->ss_pn = ss_pn; |
|
682 |
} |
|
2035
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
683 |
insque(cl_ss, oldstate); |
0 | 684 |
} else { |
685 |
rfs4_ss_pnfree(ss_pn); |
|
686 |
} |
|
687 |
} |
|
688 |
} |
|
2035
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
689 |
|
0 | 690 |
out: |
691 |
(void) VOP_CLOSE(dvp, FREAD, 1, (offset_t)0, CRED()); |
|
692 |
VN_RELE(dvp); |
|
693 |
if (dirt) |
|
694 |
kmem_free((caddr_t)dirt, RFS4_SS_DIRSIZE); |
|
695 |
} |
|
696 |
||
697 |
static void |
|
698 |
rfs4_ss_init(void) |
|
699 |
{ |
|
2035
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
700 |
int npaths = 1; |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
701 |
char *default_dss_path = NFS4_DSS_VAR_DIR; |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
702 |
|
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
703 |
/* read the default stable storage state */ |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
704 |
rfs4_dss_readstate(npaths, &default_dss_path); |
0 | 705 |
|
706 |
rfs4_ss_enabled = 1; |
|
707 |
} |
|
708 |
||
709 |
static void |
|
710 |
rfs4_ss_fini(void) |
|
711 |
{ |
|
2035
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
712 |
rfs4_servinst_t *sip; |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
713 |
|
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
714 |
mutex_enter(&rfs4_servinst_lock); |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
715 |
sip = rfs4_cur_servinst; |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
716 |
while (sip != NULL) { |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
717 |
rfs4_dss_clear_oldstate(sip); |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
718 |
sip = sip->next; |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
719 |
} |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
720 |
mutex_exit(&rfs4_servinst_lock); |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
721 |
} |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
722 |
|
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
723 |
/* |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
724 |
* Remove all oldstate files referenced by this servinst. |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
725 |
*/ |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
726 |
static void |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
727 |
rfs4_dss_clear_oldstate(rfs4_servinst_t *sip) |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
728 |
{ |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
729 |
rfs4_oldstate_t *os_head, *osp; |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
730 |
|
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
731 |
rw_enter(&sip->oldstate_lock, RW_WRITER); |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
732 |
os_head = sip->oldstate; |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
733 |
|
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
734 |
if (os_head == NULL) |
0 | 735 |
return; |
2035
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
736 |
|
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
737 |
/* skip dummy entry */ |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
738 |
osp = os_head->next; |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
739 |
while (osp != os_head) { |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
740 |
char *leaf = osp->ss_pn->leaf; |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
741 |
rfs4_oldstate_t *os_next; |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
742 |
|
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
743 |
rfs4_dss_remove_leaf(sip, NFS4_DSS_OLDSTATE_LEAF, leaf); |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
744 |
|
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
745 |
if (osp->cl_id4.id_val) |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
746 |
kmem_free(osp->cl_id4.id_val, osp->cl_id4.id_len); |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
747 |
if (osp->ss_pn) |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
748 |
kmem_free(osp->ss_pn, sizeof (rfs4_ss_pn_t)); |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
749 |
|
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
750 |
os_next = osp->next; |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
751 |
remque(osp); |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
752 |
kmem_free(osp, sizeof (rfs4_oldstate_t)); |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
753 |
osp = os_next; |
0 | 754 |
} |
755 |
||
2035
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
756 |
/* free dummy entry */ |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
757 |
kmem_free(osp, sizeof (rfs4_oldstate_t)); |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
758 |
|
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
759 |
sip->oldstate = NULL; |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
760 |
|
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
761 |
rw_exit(&sip->oldstate_lock); |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
762 |
} |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
763 |
|
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
764 |
/* |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
765 |
* Form the state and oldstate paths, and read in the stable storage files. |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
766 |
*/ |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
767 |
void |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
768 |
rfs4_dss_readstate(int npaths, char **paths) |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
769 |
{ |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
770 |
int i; |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
771 |
char *state, *oldstate; |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
772 |
|
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
773 |
state = kmem_alloc(MAXPATHLEN, KM_SLEEP); |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
774 |
oldstate = kmem_alloc(MAXPATHLEN, KM_SLEEP); |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
775 |
|
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
776 |
for (i = 0; i < npaths; i++) { |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
777 |
char *path = paths[i]; |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
778 |
|
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
779 |
(void) sprintf(state, "%s/%s", path, NFS4_DSS_STATE_LEAF); |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
780 |
(void) sprintf(oldstate, "%s/%s", path, NFS4_DSS_OLDSTATE_LEAF); |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
781 |
|
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
782 |
/* |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
783 |
* Populate the current server instance's oldstate list. |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
784 |
* |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
785 |
* 1. Read stable storage data from old state directory, |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
786 |
* leaving its contents alone. |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
787 |
* |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
788 |
* 2. Read stable storage data from state directory, |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
789 |
* and move the latter's contents to old state |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
790 |
* directory. |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
791 |
*/ |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
792 |
rfs4_ss_oldstate(rfs4_cur_servinst->oldstate, oldstate, NULL); |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
793 |
rfs4_ss_oldstate(rfs4_cur_servinst->oldstate, state, oldstate); |
0 | 794 |
} |
2035
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
795 |
|
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
796 |
kmem_free(state, MAXPATHLEN); |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
797 |
kmem_free(oldstate, MAXPATHLEN); |
0 | 798 |
} |
799 |
||
800 |
||
801 |
/* |
|
802 |
* Check if we are still in grace and if the client can be |
|
803 |
* granted permission to perform reclaims. |
|
804 |
*/ |
|
805 |
void |
|
806 |
rfs4_ss_chkclid(rfs4_client_t *cp) |
|
807 |
{ |
|
2035
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
808 |
rfs4_servinst_t *sip; |
0 | 809 |
|
810 |
/* |
|
2035
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
811 |
* It should be sufficient to check the oldstate data for just |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
812 |
* this client's instance. However, since our per-instance |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
813 |
* client grouping is solely temporal, HA-NFSv4 RG failover |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
814 |
* might result in clients of the same RG being partitioned into |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
815 |
* separate instances. |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
816 |
* |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
817 |
* Until the client grouping is improved, we must check the |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
818 |
* oldstate data for all instances with an active grace period. |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
819 |
* |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
820 |
* This also serves as the mechanism to remove stale oldstate data. |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
821 |
* The first time we check an instance after its grace period has |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
822 |
* expired, the oldstate data should be cleared. |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
823 |
* |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
824 |
* Start at the current instance, and walk the list backwards |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
825 |
* to the first. |
0 | 826 |
*/ |
2035
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
827 |
mutex_enter(&rfs4_servinst_lock); |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
828 |
for (sip = rfs4_cur_servinst; sip != NULL; sip = sip->prev) { |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
829 |
rfs4_ss_chkclid_sip(cp, sip); |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
830 |
|
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
831 |
/* if the above check found this client, we're done */ |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
832 |
if (cp->can_reclaim) |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
833 |
break; |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
834 |
} |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
835 |
mutex_exit(&rfs4_servinst_lock); |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
836 |
} |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
837 |
|
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
838 |
static void |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
839 |
rfs4_ss_chkclid_sip(rfs4_client_t *cp, rfs4_servinst_t *sip) |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
840 |
{ |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
841 |
rfs4_oldstate_t *osp, *os_head; |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
842 |
|
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
843 |
/* short circuit everything if this server instance has no oldstate */ |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
844 |
rw_enter(&sip->oldstate_lock, RW_READER); |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
845 |
os_head = sip->oldstate; |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
846 |
rw_exit(&sip->oldstate_lock); |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
847 |
if (os_head == NULL) |
0 | 848 |
return; |
849 |
||
850 |
/* |
|
2035
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
851 |
* If this server instance is no longer in a grace period then |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
852 |
* the client won't be able to reclaim. No further need for this |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
853 |
* instance's oldstate data, so it can be cleared. |
0 | 854 |
*/ |
2035
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
855 |
if (!rfs4_servinst_in_grace(sip)) |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
856 |
return; |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
857 |
|
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
858 |
/* this instance is still in grace; search for the clientid */ |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
859 |
|
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
860 |
rw_enter(&sip->oldstate_lock, RW_READER); |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
861 |
|
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
862 |
os_head = sip->oldstate; |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
863 |
/* skip dummy entry */ |
0 | 864 |
osp = os_head->next; |
865 |
while (osp != os_head) { |
|
866 |
if (osp->cl_id4.id_len == cp->nfs_client.id_len) { |
|
867 |
if (bcmp(osp->cl_id4.id_val, cp->nfs_client.id_val, |
|
868 |
osp->cl_id4.id_len) == 0) { |
|
869 |
cp->can_reclaim = 1; |
|
870 |
break; |
|
871 |
} |
|
872 |
} |
|
873 |
osp = osp->next; |
|
874 |
} |
|
875 |
||
2035
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
876 |
rw_exit(&sip->oldstate_lock); |
0 | 877 |
} |
878 |
||
879 |
/* |
|
2035
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
880 |
* Place client information into stable storage: 1/3. |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
881 |
* First, generate the leaf filename, from the client's IP address and |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
882 |
* the server-generated short-hand clientid. |
0 | 883 |
*/ |
884 |
void |
|
885 |
rfs4_ss_clid(rfs4_client_t *cp, struct svc_req *req) |
|
886 |
{ |
|
887 |
const char *kinet_ntop6(uchar_t *, char *, size_t); |
|
888 |
char leaf[MAXNAMELEN], buf[INET6_ADDRSTRLEN]; |
|
889 |
struct sockaddr *ca; |
|
890 |
uchar_t *b; |
|
891 |
||
892 |
if (rfs4_ss_enabled == 0) { |
|
893 |
return; |
|
894 |
} |
|
895 |
||
896 |
buf[0] = 0; |
|
897 |
||
898 |
||
899 |
ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf; |
|
900 |
if (ca == NULL) { |
|
901 |
return; |
|
902 |
} |
|
903 |
||
904 |
/* |
|
905 |
* Convert the caller's IP address to a dotted string |
|
906 |
*/ |
|
907 |
if (ca->sa_family == AF_INET) { |
|
908 |
||
909 |
bcopy(svc_getrpccaller(req->rq_xprt)->buf, &cp->cl_addr, |
|
910 |
sizeof (struct sockaddr_in)); |
|
911 |
b = (uchar_t *)&((struct sockaddr_in *)ca)->sin_addr; |
|
912 |
(void) sprintf(buf, "%03d.%03d.%03d.%03d", b[0] & 0xFF, |
|
913 |
b[1] & 0xFF, b[2] & 0xFF, b[3] & 0xFF); |
|
914 |
} else if (ca->sa_family == AF_INET6) { |
|
915 |
struct sockaddr_in6 *sin6; |
|
916 |
||
917 |
sin6 = (struct sockaddr_in6 *)ca; |
|
918 |
bcopy(svc_getrpccaller(req->rq_xprt)->buf, &cp->cl_addr, |
|
919 |
sizeof (struct sockaddr_in6)); |
|
920 |
(void) kinet_ntop6((uchar_t *)&sin6->sin6_addr, |
|
921 |
buf, INET6_ADDRSTRLEN); |
|
922 |
} |
|
923 |
||
924 |
(void) snprintf(leaf, MAXNAMELEN, "%s-%llx", buf, |
|
925 |
(longlong_t)cp->clientid); |
|
2035
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
926 |
rfs4_ss_clid_write(cp, leaf); |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
927 |
} |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
928 |
|
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
929 |
/* |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
930 |
* Place client information into stable storage: 2/3. |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
931 |
* DSS: distributed stable storage: the file may need to be written to |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
932 |
* multiple directories. |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
933 |
*/ |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
934 |
static void |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
935 |
rfs4_ss_clid_write(rfs4_client_t *cp, char *leaf) |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
936 |
{ |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
937 |
rfs4_servinst_t *sip; |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
938 |
|
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
939 |
/* |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
940 |
* It should be sufficient to write the leaf file to (all) DSS paths |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
941 |
* associated with just this client's instance. However, since our |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
942 |
* per-instance client grouping is solely temporal, HA-NFSv4 RG |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
943 |
* failover might result in us losing DSS data. |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
944 |
* |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
945 |
* Until the client grouping is improved, we must write the DSS data |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
946 |
* to all instances' paths. Start at the current instance, and |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
947 |
* walk the list backwards to the first. |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
948 |
*/ |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
949 |
mutex_enter(&rfs4_servinst_lock); |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
950 |
for (sip = rfs4_cur_servinst; sip != NULL; sip = sip->prev) { |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
951 |
int i, npaths = sip->dss_npaths; |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
952 |
|
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
953 |
/* write the leaf file to all DSS paths */ |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
954 |
for (i = 0; i < npaths; i++) { |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
955 |
rfs4_dss_path_t *dss_path = sip->dss_paths[i]; |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
956 |
|
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
957 |
/* HA-NFSv4 path might have been failed-away from us */ |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
958 |
if (dss_path == NULL) |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
959 |
continue; |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
960 |
|
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
961 |
rfs4_ss_clid_write_one(cp, dss_path->path, leaf); |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
962 |
} |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
963 |
} |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
964 |
mutex_exit(&rfs4_servinst_lock); |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
965 |
} |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
966 |
|
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
967 |
/* |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
968 |
* Place client information into stable storage: 3/3. |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
969 |
* Write the stable storage data to the requested file. |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
970 |
*/ |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
971 |
static void |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
972 |
rfs4_ss_clid_write_one(rfs4_client_t *cp, char *dss_path, char *leaf) |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
973 |
{ |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
974 |
int ioflag; |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
975 |
int file_vers = NFS4_SS_VERSION; |
2390 | 976 |
size_t dirlen; |
2035
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
977 |
struct uio uio; |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
978 |
struct iovec iov[4]; |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
979 |
char *dir; |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
980 |
rfs4_ss_pn_t *ss_pn; |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
981 |
vnode_t *vp; |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
982 |
nfs_client_id4 *cl_id4 = &(cp->nfs_client); |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
983 |
|
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
984 |
/* allow 2 extra bytes for '/' & NUL */ |
2390 | 985 |
dirlen = strlen(dss_path) + strlen(NFS4_DSS_STATE_LEAF) + 2; |
986 |
dir = kmem_alloc(dirlen, KM_SLEEP); |
|
2035
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
987 |
(void) sprintf(dir, "%s/%s", dss_path, NFS4_DSS_STATE_LEAF); |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
988 |
|
2390 | 989 |
ss_pn = rfs4_ss_pnalloc(dir, leaf); |
990 |
/* rfs4_ss_pnalloc takes its own copy */ |
|
991 |
kmem_free(dir, dirlen); |
|
992 |
if (ss_pn == NULL) |
|
0 | 993 |
return; |
994 |
||
995 |
if (vn_open(ss_pn->pn, UIO_SYSSPACE, FCREAT|FWRITE, 0600, &vp, |
|
996 |
CRCREAT, 0)) { |
|
997 |
rfs4_ss_pnfree(ss_pn); |
|
998 |
return; |
|
999 |
} |
|
1000 |
||
2035
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1001 |
/* |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1002 |
* We need to record leaf - i.e. the filename - so that we know |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1003 |
* what to remove, in the future. However, the dir part of cp->ss_pn |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1004 |
* should never be referenced directly, since it's potentially only |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1005 |
* one of several paths with this leaf in it. |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1006 |
*/ |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1007 |
if (cp->ss_pn != NULL) { |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1008 |
if (strcmp(cp->ss_pn->leaf, leaf) == 0) { |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1009 |
/* we've already recorded *this* leaf */ |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1010 |
rfs4_ss_pnfree(ss_pn); |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1011 |
} else { |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1012 |
/* replace with this leaf */ |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1013 |
rfs4_ss_pnfree(cp->ss_pn); |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1014 |
cp->ss_pn = ss_pn; |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1015 |
} |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1016 |
} else { |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1017 |
cp->ss_pn = ss_pn; |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1018 |
} |
0 | 1019 |
|
1020 |
/* |
|
1021 |
* Build a scatter list that points to the nfs_client_id4 |
|
1022 |
*/ |
|
1023 |
iov[0].iov_base = (caddr_t)&file_vers; |
|
1024 |
iov[0].iov_len = sizeof (int); |
|
2035
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1025 |
iov[1].iov_base = (caddr_t)&(cl_id4->verifier); |
0 | 1026 |
iov[1].iov_len = NFS4_VERIFIER_SIZE; |
1027 |
iov[2].iov_base = (caddr_t)&(cl_id4->id_len); |
|
1028 |
iov[2].iov_len = sizeof (uint_t); |
|
1029 |
iov[3].iov_base = (caddr_t)cl_id4->id_val; |
|
1030 |
iov[3].iov_len = cl_id4->id_len; |
|
1031 |
||
1032 |
uio.uio_iov = iov; |
|
1033 |
uio.uio_iovcnt = 4; |
|
1034 |
uio.uio_loffset = 0; |
|
1035 |
uio.uio_segflg = UIO_SYSSPACE; |
|
1036 |
uio.uio_llimit = (rlim64_t)MAXOFFSET_T; |
|
1037 |
uio.uio_resid = cl_id4->id_len + sizeof (int) + |
|
1038 |
NFS4_VERIFIER_SIZE + sizeof (uint_t); |
|
1039 |
||
1040 |
ioflag = uio.uio_fmode = (FWRITE|FSYNC); |
|
1041 |
uio.uio_extflg = UIO_COPY_DEFAULT; |
|
1042 |
||
1043 |
(void) VOP_RWLOCK(vp, V_WRITELOCK_TRUE, NULL); |
|
1044 |
/* write the full client id to the file. */ |
|
1045 |
(void) VOP_WRITE(vp, &uio, ioflag, CRED(), NULL); |
|
1046 |
VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, NULL); |
|
1047 |
||
1048 |
(void) VOP_CLOSE(vp, FWRITE, 1, (offset_t)0, CRED()); |
|
1049 |
VN_RELE(vp); |
|
1050 |
} |
|
1051 |
||
1052 |
/* |
|
2035
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1053 |
* DSS: distributed stable storage. |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1054 |
* Unpack the list of paths passed by nfsd. |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1055 |
* Use nvlist_alloc(9F) to manage the data. |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1056 |
* The caller is responsible for allocating and freeing the buffer. |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1057 |
*/ |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1058 |
int |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1059 |
rfs4_dss_setpaths(char *buf, size_t buflen) |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1060 |
{ |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1061 |
int error; |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1062 |
|
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1063 |
/* |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1064 |
* If this is a "warm start", i.e. we previously had DSS paths, |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1065 |
* preserve the old paths. |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1066 |
*/ |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1067 |
if (rfs4_dss_paths != NULL) { |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1068 |
/* |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1069 |
* Before we lose the ptr, destroy the nvlist and pathnames |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1070 |
* array from the warm start before this one. |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1071 |
*/ |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1072 |
if (rfs4_dss_oldpaths) |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1073 |
nvlist_free(rfs4_dss_oldpaths); |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1074 |
rfs4_dss_oldpaths = rfs4_dss_paths; |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1075 |
} |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1076 |
|
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1077 |
/* unpack the buffer into a searchable nvlist */ |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1078 |
error = nvlist_unpack(buf, buflen, &rfs4_dss_paths, KM_SLEEP); |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1079 |
if (error) |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1080 |
return (error); |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1081 |
|
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1082 |
/* |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1083 |
* Search the nvlist for the pathnames nvpair (which is the only nvpair |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1084 |
* in the list, and record its location. |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1085 |
*/ |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1086 |
error = nvlist_lookup_string_array(rfs4_dss_paths, NFS4_DSS_NVPAIR_NAME, |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1087 |
&rfs4_dss_newpaths, &rfs4_dss_numnewpaths); |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1088 |
return (error); |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1089 |
} |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1090 |
|
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1091 |
/* |
0 | 1092 |
* Ultimately the nfssys() call NFS4_CLR_STATE endsup here |
1093 |
* to find and mark the client for forced expire. |
|
1094 |
*/ |
|
1095 |
static void |
|
1096 |
rfs4_client_scrub(rfs4_entry_t ent, void *arg) |
|
1097 |
{ |
|
1098 |
rfs4_client_t *cp = (rfs4_client_t *)ent; |
|
1099 |
struct nfs4clrst_args *clr = arg; |
|
1100 |
struct sockaddr_in6 *ent_sin6; |
|
1101 |
struct in6_addr clr_in6; |
|
1102 |
struct sockaddr_in *ent_sin; |
|
1103 |
struct in_addr clr_in; |
|
1104 |
||
1105 |
if (clr->addr_type != cp->cl_addr.ss_family) { |
|
1106 |
return; |
|
1107 |
} |
|
1108 |
||
1109 |
switch (clr->addr_type) { |
|
1110 |
||
1111 |
case AF_INET6: |
|
1112 |
/* copyin the address from user space */ |
|
1113 |
if (copyin(clr->ap, &clr_in6, sizeof (clr_in6))) { |
|
1114 |
break; |
|
1115 |
} |
|
1116 |
||
1117 |
ent_sin6 = (struct sockaddr_in6 *)&cp->cl_addr; |
|
1118 |
||
1119 |
/* |
|
1120 |
* now compare, and if equivalent mark entry |
|
1121 |
* for forced expiration |
|
1122 |
*/ |
|
1123 |
if (IN6_ARE_ADDR_EQUAL(&ent_sin6->sin6_addr, &clr_in6)) { |
|
1124 |
cp->forced_expire = 1; |
|
1125 |
} |
|
1126 |
break; |
|
1127 |
||
1128 |
case AF_INET: |
|
1129 |
/* copyin the address from user space */ |
|
1130 |
if (copyin(clr->ap, &clr_in, sizeof (clr_in))) { |
|
1131 |
break; |
|
1132 |
} |
|
1133 |
||
1134 |
ent_sin = (struct sockaddr_in *)&cp->cl_addr; |
|
1135 |
||
1136 |
/* |
|
1137 |
* now compare, and if equivalent mark entry |
|
1138 |
* for forced expiration |
|
1139 |
*/ |
|
1140 |
if (ent_sin->sin_addr.s_addr == clr_in.s_addr) { |
|
1141 |
cp->forced_expire = 1; |
|
1142 |
} |
|
1143 |
break; |
|
1144 |
||
1145 |
default: |
|
1146 |
/* force this assert to fail */ |
|
1147 |
ASSERT(clr->addr_type != clr->addr_type); |
|
1148 |
} |
|
1149 |
} |
|
1150 |
||
1151 |
/* |
|
1152 |
* This is called from nfssys() in order to clear server state |
|
1153 |
* for the specified client IP Address. |
|
1154 |
*/ |
|
1155 |
void |
|
1156 |
rfs4_clear_client_state(struct nfs4clrst_args *clr) |
|
1157 |
{ |
|
1158 |
(void) rfs4_dbe_walk(rfs4_client_tab, rfs4_client_scrub, clr); |
|
1159 |
} |
|
1160 |
||
1161 |
/* |
|
1162 |
* Used to initialize the NFSv4 server's state or database. All of |
|
1163 |
* the tables are created and timers are set. Only called when NFSv4 |
|
1164 |
* service is provided. |
|
1165 |
*/ |
|
1166 |
void |
|
1167 |
rfs4_state_init() |
|
1168 |
{ |
|
1169 |
int start_grace; |
|
1170 |
extern boolean_t rfs4_cpr_callb(void *, int); |
|
2035
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1171 |
char *dss_path = NFS4_DSS_VAR_DIR; |
0 | 1172 |
|
1173 |
mutex_enter(&rfs4_state_lock); |
|
1174 |
||
1175 |
/* |
|
1176 |
* If the server state database has already been initialized, |
|
1177 |
* skip it |
|
1178 |
*/ |
|
1179 |
if (rfs4_server_state != NULL) { |
|
1180 |
mutex_exit(&rfs4_state_lock); |
|
1181 |
return; |
|
1182 |
} |
|
1183 |
||
1184 |
rw_init(&rfs4_findclient_lock, NULL, RW_DEFAULT, NULL); |
|
1185 |
||
1186 |
/* |
|
1187 |
* Set the boot time. If the server |
|
1188 |
* has been restarted quickly and has had the opportunity to |
|
1189 |
* service clients, then the start_time needs to be bumped |
|
1190 |
* regardless. A small window but it exists... |
|
1191 |
*/ |
|
1192 |
if (rfs4_start_time != gethrestime_sec()) |
|
1193 |
rfs4_start_time = gethrestime_sec(); |
|
1194 |
else |
|
1195 |
rfs4_start_time++; |
|
1196 |
||
2035
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1197 |
/* DSS: distributed stable storage: initialise served paths list */ |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1198 |
rfs4_dss_pathlist = NULL; |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1199 |
|
0 | 1200 |
/* |
1201 |
* Create the first server instance, or a new one if the server has |
|
1202 |
* been restarted; see above comments on rfs4_start_time. Don't |
|
1203 |
* start its grace period; that will be done later, to maximise the |
|
1204 |
* clients' recovery window. |
|
1205 |
*/ |
|
1206 |
start_grace = 0; |
|
2035
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1207 |
rfs4_servinst_create(start_grace, 1, &dss_path); |
0 | 1208 |
|
1209 |
/* reset the "first NFSv4 request" status */ |
|
1210 |
rfs4_seen_first_compound = 0; |
|
1211 |
||
1212 |
/* |
|
1213 |
* Add a CPR callback so that we can update client |
|
1214 |
* access times to extend the lease after a suspend |
|
1215 |
* and resume (using the same class as rpcmod/connmgr) |
|
1216 |
*/ |
|
1217 |
cpr_id = callb_add(rfs4_cpr_callb, 0, CB_CL_CPR_RPC, "rfs4"); |
|
1218 |
||
1219 |
/* set the various cache timers for table creation */ |
|
1220 |
if (rfs4_client_cache_time == 0) |
|
1221 |
rfs4_client_cache_time = CLIENT_CACHE_TIME; |
|
1222 |
if (rfs4_openowner_cache_time == 0) |
|
1223 |
rfs4_openowner_cache_time = OPENOWNER_CACHE_TIME; |
|
1224 |
if (rfs4_state_cache_time == 0) |
|
1225 |
rfs4_state_cache_time = STATE_CACHE_TIME; |
|
1226 |
if (rfs4_lo_state_cache_time == 0) |
|
1227 |
rfs4_lo_state_cache_time = LO_STATE_CACHE_TIME; |
|
1228 |
if (rfs4_lockowner_cache_time == 0) |
|
1229 |
rfs4_lockowner_cache_time = LOCKOWNER_CACHE_TIME; |
|
1230 |
if (rfs4_file_cache_time == 0) |
|
1231 |
rfs4_file_cache_time = FILE_CACHE_TIME; |
|
1232 |
if (rfs4_deleg_state_cache_time == 0) |
|
1233 |
rfs4_deleg_state_cache_time = DELEG_STATE_CACHE_TIME; |
|
1234 |
||
1235 |
/* Create the overall database to hold all server state */ |
|
1236 |
rfs4_server_state = rfs4_database_create(rfs4_database_debug); |
|
1237 |
||
1238 |
/* Now create the individual tables */ |
|
1239 |
rfs4_client_cache_time *= rfs4_lease_time; |
|
1240 |
rfs4_client_tab = rfs4_table_create(rfs4_server_state, |
|
1241 |
"Client", |
|
1242 |
rfs4_client_cache_time, |
|
1243 |
2, |
|
1244 |
rfs4_client_create, |
|
1245 |
rfs4_client_destroy, |
|
1246 |
rfs4_client_expiry, |
|
1247 |
sizeof (rfs4_client_t), |
|
1248 |
TABSIZE, |
|
1249 |
MAXTABSZ/8, 100); |
|
1250 |
rfs4_nfsclnt_idx = rfs4_index_create(rfs4_client_tab, |
|
1251 |
"nfs_client_id4", nfsclnt_hash, |
|
1252 |
nfsclnt_compare, nfsclnt_mkkey, |
|
1253 |
TRUE); |
|
1254 |
rfs4_clientid_idx = rfs4_index_create(rfs4_client_tab, |
|
1255 |
"client_id", clientid_hash, |
|
1256 |
clientid_compare, clientid_mkkey, |
|
1257 |
FALSE); |
|
1258 |
||
1259 |
rfs4_openowner_cache_time *= rfs4_lease_time; |
|
1260 |
rfs4_openowner_tab = rfs4_table_create(rfs4_server_state, |
|
1261 |
"OpenOwner", |
|
1262 |
rfs4_openowner_cache_time, |
|
1263 |
1, |
|
1264 |
rfs4_openowner_create, |
|
1265 |
rfs4_openowner_destroy, |
|
1266 |
rfs4_openowner_expiry, |
|
1267 |
sizeof (rfs4_openowner_t), |
|
1268 |
TABSIZE, |
|
1269 |
MAXTABSZ, 100); |
|
1270 |
rfs4_openowner_idx = rfs4_index_create(rfs4_openowner_tab, |
|
1271 |
"open_owner4", openowner_hash, |
|
1272 |
openowner_compare, |
|
1273 |
openowner_mkkey, TRUE); |
|
1274 |
||
1275 |
rfs4_state_cache_time *= rfs4_lease_time; |
|
1276 |
rfs4_state_tab = rfs4_table_create(rfs4_server_state, |
|
1277 |
"OpenStateID", |
|
1278 |
rfs4_state_cache_time, |
|
1279 |
3, |
|
1280 |
rfs4_state_create, |
|
1281 |
rfs4_state_destroy, |
|
1282 |
rfs4_state_expiry, |
|
1283 |
sizeof (rfs4_state_t), |
|
1284 |
TABSIZE, |
|
1285 |
MAXTABSZ, 100); |
|
1286 |
rfs4_state_owner_file_idx = rfs4_index_create(rfs4_state_tab, |
|
1287 |
"Openowner-File", |
|
1288 |
state_owner_file_hash, |
|
1289 |
state_owner_file_compare, |
|
1290 |
state_owner_file_mkkey, TRUE); |
|
1291 |
rfs4_state_idx = rfs4_index_create(rfs4_state_tab, |
|
1292 |
"State-id", state_hash, |
|
1293 |
state_compare, state_mkkey, FALSE); |
|
1294 |
rfs4_state_file_idx = rfs4_index_create(rfs4_state_tab, |
|
1295 |
"File", state_file_hash, |
|
1296 |
state_file_compare, state_file_mkkey, |
|
1297 |
FALSE); |
|
1298 |
||
1299 |
rfs4_lo_state_cache_time *= rfs4_lease_time; |
|
1300 |
rfs4_lo_state_tab = rfs4_table_create(rfs4_server_state, |
|
1301 |
"LockStateID", |
|
1302 |
rfs4_lo_state_cache_time, |
|
1303 |
2, |
|
1304 |
rfs4_lo_state_create, |
|
1305 |
rfs4_lo_state_destroy, |
|
1306 |
rfs4_lo_state_expiry, |
|
1307 |
sizeof (rfs4_lo_state_t), |
|
1308 |
TABSIZE, |
|
1309 |
MAXTABSZ, 100); |
|
1310 |
rfs4_lo_state_owner_idx = rfs4_index_create(rfs4_lo_state_tab, |
|
1311 |
"lockownerxstate", |
|
1312 |
lo_state_lo_hash, |
|
1313 |
lo_state_lo_compare, |
|
1314 |
lo_state_lo_mkkey, TRUE); |
|
1315 |
rfs4_lo_state_idx = rfs4_index_create(rfs4_lo_state_tab, |
|
1316 |
"State-id", |
|
1317 |
lo_state_hash, lo_state_compare, |
|
1318 |
lo_state_mkkey, FALSE); |
|
1319 |
||
1320 |
rfs4_lockowner_cache_time *= rfs4_lease_time; |
|
1321 |
rfs4_lockowner_tab = rfs4_table_create(rfs4_server_state, |
|
1322 |
"Lockowner", |
|
1323 |
rfs4_lockowner_cache_time, |
|
1324 |
2, |
|
1325 |
rfs4_lockowner_create, |
|
1326 |
rfs4_lockowner_destroy, |
|
1327 |
rfs4_lockowner_expiry, |
|
1328 |
sizeof (rfs4_lockowner_t), |
|
1329 |
TABSIZE, |
|
1330 |
MAXTABSZ, 100); |
|
1331 |
rfs4_lockowner_idx = rfs4_index_create(rfs4_lockowner_tab, |
|
1332 |
"lock_owner4", lockowner_hash, |
|
1333 |
lockowner_compare, |
|
1334 |
lockowner_mkkey, TRUE); |
|
1335 |
rfs4_lockowner_pid_idx = rfs4_index_create(rfs4_lockowner_tab, |
|
1336 |
"pid", pid_hash, |
|
1337 |
pid_compare, pid_mkkey, |
|
1338 |
FALSE); |
|
1339 |
||
1340 |
rfs4_file_cache_time *= rfs4_lease_time; |
|
1341 |
rfs4_file_tab = rfs4_table_create(rfs4_server_state, |
|
1342 |
"File", |
|
1343 |
rfs4_file_cache_time, |
|
1344 |
1, |
|
1345 |
rfs4_file_create, |
|
1346 |
rfs4_file_destroy, |
|
1347 |
NULL, |
|
1348 |
sizeof (rfs4_file_t), |
|
1349 |
TABSIZE, |
|
1350 |
MAXTABSZ, -1); |
|
1351 |
rfs4_file_idx = rfs4_index_create(rfs4_file_tab, |
|
1352 |
"Filehandle", file_hash, |
|
1353 |
file_compare, file_mkkey, TRUE); |
|
1354 |
||
1355 |
rfs4_deleg_state_cache_time *= rfs4_lease_time; |
|
1356 |
rfs4_deleg_state_tab = rfs4_table_create(rfs4_server_state, |
|
1357 |
"DelegStateID", |
|
1358 |
rfs4_deleg_state_cache_time, |
|
1359 |
2, |
|
1360 |
rfs4_deleg_state_create, |
|
1361 |
rfs4_deleg_state_destroy, |
|
1362 |
rfs4_deleg_state_expiry, |
|
1363 |
sizeof (rfs4_deleg_state_t), |
|
1364 |
TABSIZE, |
|
1365 |
MAXTABSZ, 100); |
|
1366 |
rfs4_deleg_idx = rfs4_index_create(rfs4_deleg_state_tab, |
|
1367 |
"DelegByFileClient", |
|
1368 |
deleg_hash, |
|
1369 |
deleg_compare, |
|
1370 |
deleg_mkkey, TRUE); |
|
1371 |
rfs4_deleg_state_idx = rfs4_index_create(rfs4_deleg_state_tab, |
|
1372 |
"DelegState", |
|
1373 |
deleg_state_hash, |
|
1374 |
deleg_state_compare, |
|
1375 |
deleg_state_mkkey, FALSE); |
|
1376 |
||
1377 |
/* |
|
1378 |
* Init the stable storage. |
|
1379 |
*/ |
|
1380 |
rfs4_ss_init(); |
|
1381 |
||
1382 |
rfs4_client_clrst = rfs4_clear_client_state; |
|
1383 |
||
1384 |
mutex_exit(&rfs4_state_lock); |
|
1385 |
} |
|
1386 |
||
1387 |
||
1388 |
/* |
|
1389 |
* Used at server shutdown to cleanup all of the NFSv4 server's structures |
|
1390 |
* and other state. |
|
1391 |
*/ |
|
1392 |
void |
|
1393 |
rfs4_state_fini() |
|
1394 |
{ |
|
1395 |
rfs4_database_t *dbp; |
|
1396 |
||
1397 |
mutex_enter(&rfs4_state_lock); |
|
1398 |
||
1399 |
if (rfs4_server_state == NULL) { |
|
1400 |
mutex_exit(&rfs4_state_lock); |
|
1401 |
return; |
|
1402 |
} |
|
1403 |
||
1404 |
rfs4_client_clrst = NULL; |
|
1405 |
||
1406 |
rfs4_set_deleg_policy(SRV_NEVER_DELEGATE); |
|
1407 |
dbp = rfs4_server_state; |
|
1408 |
rfs4_server_state = NULL; |
|
1409 |
||
1410 |
/* |
|
1411 |
* Cleanup the CPR callback. |
|
1412 |
*/ |
|
1413 |
if (cpr_id) |
|
1414 |
(void) callb_delete(cpr_id); |
|
1415 |
||
1416 |
rw_destroy(&rfs4_findclient_lock); |
|
1417 |
||
1418 |
/* First stop all of the reaper threads in the database */ |
|
1419 |
rfs4_database_shutdown(dbp); |
|
1420 |
/* clean up any dangling stable storage structures */ |
|
1421 |
rfs4_ss_fini(); |
|
1422 |
/* Now actually destroy/release the database and its tables */ |
|
1423 |
rfs4_database_destroy(dbp); |
|
1424 |
||
1425 |
/* Reset the cache timers for next time */ |
|
1426 |
rfs4_client_cache_time = 0; |
|
1427 |
rfs4_openowner_cache_time = 0; |
|
1428 |
rfs4_state_cache_time = 0; |
|
1429 |
rfs4_lo_state_cache_time = 0; |
|
1430 |
rfs4_lockowner_cache_time = 0; |
|
1431 |
rfs4_file_cache_time = 0; |
|
1432 |
rfs4_deleg_state_cache_time = 0; |
|
1433 |
||
1434 |
mutex_exit(&rfs4_state_lock); |
|
1435 |
||
1436 |
/* destroy server instances and current instance ptr */ |
|
1437 |
rfs4_servinst_destroy_all(); |
|
1438 |
||
1439 |
/* reset the "first NFSv4 request" status */ |
|
1440 |
rfs4_seen_first_compound = 0; |
|
2035
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1441 |
|
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1442 |
/* DSS: distributed stable storage */ |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1443 |
if (rfs4_dss_oldpaths) |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1444 |
nvlist_free(rfs4_dss_oldpaths); |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1445 |
if (rfs4_dss_paths) |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1446 |
nvlist_free(rfs4_dss_paths); |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1447 |
rfs4_dss_paths = rfs4_dss_oldpaths = NULL; |
0 | 1448 |
} |
1449 |
||
1450 |
typedef union { |
|
1451 |
struct { |
|
1452 |
uint32_t start_time; |
|
1453 |
uint32_t c_id; |
|
1454 |
} impl_id; |
|
1455 |
clientid4 id4; |
|
1456 |
} cid; |
|
1457 |
||
1458 |
static int foreign_stateid(stateid_t *id); |
|
1459 |
static int foreign_clientid(cid *cidp); |
|
1460 |
static void embed_nodeid(cid *cidp); |
|
1461 |
||
1462 |
typedef union { |
|
1463 |
struct { |
|
1464 |
uint32_t c_id; |
|
1465 |
uint32_t gen_num; |
|
1466 |
} cv_impl; |
|
1467 |
verifier4 confirm_verf; |
|
1468 |
} scid_confirm_verf; |
|
1469 |
||
1470 |
static uint32_t |
|
1471 |
clientid_hash(void *key) |
|
1472 |
{ |
|
1473 |
cid *idp = key; |
|
1474 |
||
1475 |
return (idp->impl_id.c_id); |
|
1476 |
} |
|
1477 |
||
1478 |
static bool_t |
|
1479 |
clientid_compare(rfs4_entry_t entry, void *key) |
|
1480 |
{ |
|
1481 |
rfs4_client_t *client = (rfs4_client_t *)entry; |
|
1482 |
clientid4 *idp = key; |
|
1483 |
||
1484 |
return (*idp == client->clientid); |
|
1485 |
} |
|
1486 |
||
1487 |
static void * |
|
1488 |
clientid_mkkey(rfs4_entry_t entry) |
|
1489 |
{ |
|
1490 |
rfs4_client_t *client = (rfs4_client_t *)entry; |
|
1491 |
||
1492 |
return (&client->clientid); |
|
1493 |
} |
|
1494 |
||
1495 |
static uint32_t |
|
1496 |
nfsclnt_hash(void *key) |
|
1497 |
{ |
|
1498 |
nfs_client_id4 *client = key; |
|
1499 |
int i; |
|
1500 |
uint32_t hash = 0; |
|
1501 |
||
1502 |
for (i = 0; i < client->id_len; i++) { |
|
1503 |
hash <<= 1; |
|
1504 |
hash += (uint_t)client->id_val[i]; |
|
1505 |
} |
|
1506 |
return (hash); |
|
1507 |
} |
|
1508 |
||
1509 |
||
1510 |
static bool_t |
|
1511 |
nfsclnt_compare(rfs4_entry_t entry, void *key) |
|
1512 |
{ |
|
1513 |
rfs4_client_t *client = (rfs4_client_t *)entry; |
|
1514 |
nfs_client_id4 *nfs_client = key; |
|
1515 |
||
1516 |
if (client->nfs_client.id_len != nfs_client->id_len) |
|
1517 |
return (FALSE); |
|
1518 |
||
1519 |
return (bcmp(client->nfs_client.id_val, nfs_client->id_val, |
|
1520 |
nfs_client->id_len) == 0); |
|
1521 |
} |
|
1522 |
||
1523 |
static void * |
|
1524 |
nfsclnt_mkkey(rfs4_entry_t entry) |
|
1525 |
{ |
|
1526 |
rfs4_client_t *client = (rfs4_client_t *)entry; |
|
1527 |
||
1528 |
return (&client->nfs_client); |
|
1529 |
} |
|
1530 |
||
1531 |
static bool_t |
|
1532 |
rfs4_client_expiry(rfs4_entry_t u_entry) |
|
1533 |
{ |
|
1534 |
rfs4_client_t *cp = (rfs4_client_t *)u_entry; |
|
1535 |
bool_t cp_expired; |
|
1536 |
||
1537 |
if (rfs4_dbe_is_invalid(cp->dbe)) |
|
1538 |
return (TRUE); |
|
1539 |
/* |
|
1540 |
* If the sysadmin has used clear_locks for this |
|
1541 |
* entry then forced_expire will be set and we |
|
1542 |
* want this entry to be reaped. Or the entry |
|
1543 |
* has exceeded its lease period. |
|
1544 |
*/ |
|
1545 |
cp_expired = (cp->forced_expire || |
|
1546 |
(gethrestime_sec() - cp->last_access |
|
1547 |
> rfs4_lease_time)); |
|
2035
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1548 |
|
0 | 1549 |
if (!cp->ss_remove && cp_expired) |
1550 |
cp->ss_remove = 1; |
|
1551 |
return (cp_expired); |
|
1552 |
} |
|
1553 |
||
2035
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1554 |
/* |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1555 |
* Remove the leaf file from all distributed stable storage paths. |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1556 |
*/ |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1557 |
static void |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1558 |
rfs4_dss_remove_cpleaf(rfs4_client_t *cp) |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1559 |
{ |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1560 |
char *leaf = cp->ss_pn->leaf; |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1561 |
|
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1562 |
rfs4_dss_remove_leaf(cp->server_instance, NFS4_DSS_STATE_LEAF, leaf); |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1563 |
} |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1564 |
|
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1565 |
static void |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1566 |
rfs4_dss_remove_leaf(rfs4_servinst_t *sip, char *dir_leaf, char *leaf) |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1567 |
{ |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1568 |
int i, npaths = sip->dss_npaths; |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1569 |
|
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1570 |
for (i = 0; i < npaths; i++) { |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1571 |
rfs4_dss_path_t *dss_path = sip->dss_paths[i]; |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1572 |
char *path, *dir; |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1573 |
size_t pathlen; |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1574 |
|
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1575 |
/* the HA-NFSv4 path might have been failed-over away from us */ |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1576 |
if (dss_path == NULL) |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1577 |
continue; |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1578 |
|
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1579 |
dir = dss_path->path; |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1580 |
|
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1581 |
/* allow 3 extra bytes for two '/' & a NUL */ |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1582 |
pathlen = strlen(dir) + strlen(dir_leaf) + strlen(leaf) + 3; |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1583 |
path = kmem_alloc(pathlen, KM_SLEEP); |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1584 |
(void) sprintf(path, "%s/%s/%s", dir, dir_leaf, leaf); |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1585 |
|
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1586 |
(void) vn_remove(path, UIO_SYSSPACE, RMFILE); |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1587 |
|
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1588 |
kmem_free(path, pathlen); |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1589 |
} |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1590 |
} |
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1591 |
|
0 | 1592 |
static void |
1593 |
rfs4_client_destroy(rfs4_entry_t u_entry) |
|
1594 |
{ |
|
1595 |
rfs4_client_t *cp = (rfs4_client_t *)u_entry; |
|
1596 |
||
1597 |
mutex_destroy(cp->cbinfo.cb_lock); |
|
1598 |
cv_destroy(cp->cbinfo.cb_cv); |
|
1599 |
cv_destroy(cp->cbinfo.cb_cv_nullcaller); |
|
1600 |
||
1601 |
/* free callback info */ |
|
1602 |
rfs4_cbinfo_free(&cp->cbinfo); |
|
1603 |
||
1604 |
if (cp->cp_confirmed) |
|
1605 |
rfs4_client_rele(cp->cp_confirmed); |
|
1606 |
||
1607 |
if (cp->ss_pn) { |
|
2035
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1608 |
/* check if the stable storage files need to be removed */ |
0 | 1609 |
if (cp->ss_remove) |
2035
a29bc457bcb9
PSARC/2006/313 NFSv4: nfsd "-s" distributed stable storage
calum
parents:
0
diff
changeset
|
1610 |
rfs4_dss_remove_cpleaf(cp); |
0 | 1611 |
rfs4_ss_pnfree(cp->ss_pn); |
1612 |
} |
|
1613 |
||
1614 |
/* Free the client supplied client id */ |
|
1615 |
kmem_free(cp->nfs_client.id_val, cp->nfs_client.id_len); |
|
1616 |
||
1617 |
if (cp->sysidt != LM_NOSYSID) |
|
1618 |
lm_free_sysidt(cp->sysidt); |
|
1619 |
} |
|
1620 |
||
1621 |
static bool_t |
|
1622 |
rfs4_client_create(rfs4_entry_t u_entry, void *arg) |
|
1623 |
{ |
|
1624 |
rfs4_client_t *cp = (rfs4_client_t *)u_entry; |
|
1625 |
nfs_client_id4 *client = (nfs_client_id4 *)arg; |
|
1626 |
cid *cidp; |
|
1627 |
scid_confirm_verf *scvp; |
|
1628 |
||
1629 |
/* Get a clientid to give to the client */ |
|
1630 |
cidp = (cid *)&cp->clientid; |
|
1631 |
cidp->impl_id.start_time = rfs4_start_time; |
|
1632 |
cidp->impl_id.c_id = (uint32_t)rfs4_dbe_getid(cp->dbe); |
|
1633 |
||
1634 |
/* If we are booted as a cluster node, embed our nodeid */ |
|
1635 |
if (cluster_bootflags & CLUSTER_BOOTED) |
|
1636 |
embed_nodeid(cidp); |
|
1637 |
||
1638 |
/* Allocate and copy client's client id value */ |
|
1639 |
cp->nfs_client.id_val = kmem_alloc(client->id_len, KM_SLEEP); |
|
1640 |
cp->nfs_client.id_len = client->id_len; |
|
1641 |
bcopy(client->id_val, cp->nfs_client.id_val, client->id_len); |
|
1642 |
cp->nfs_client.verifier = client->verifier; |
|
1643 |
||
1644 |
/* Init the value for the SETCLIENTID_CONFIRM verifier */ |
|
1645 |
scvp = (scid_confirm_verf *)&cp->confirm_verf; |
|
1646 |
scvp->cv_impl.c_id = cidp->impl_id.c_id; |
|
1647 |
scvp->cv_impl.gen_num = 0; |
|
1648 |
||
1649 |
/* An F_UNLKSYS has been done for this client */ |
|
1650 |
cp->unlksys_completed = FALSE; |
|
1651 |
||
1652 |
/* We need the client to ack us */ |
|
1653 |
cp->need_confirm = TRUE; |
|
1654 |
cp->cp_confirmed = NULL; |
|
1655 |
||
1656 |
/* TRUE all the time until the callback path actually fails */ |
|
1657 |
cp->cbinfo.cb_notified_of_cb_path_down = TRUE; |
|
1658 |
||
1659 |
/* Initialize the access time to now */ |
|
1660 |
cp->last_access = gethrestime_sec(); |
|
1661 |
||
1662 |
cp->cr_set = NULL; |
|
1663 |
/* Initialize list for insque/remque */ |
|
1664 |
cp->openownerlist.next = cp->openownerlist.prev = &cp->openownerlist; |
|
1665 |
cp->openownerlist.oop = NULL; /* This is not an openowner */ |
|
1666 |
||
1667 |
cp->sysidt = LM_NOSYSID; |
|
1668 |
||
1669 |
cp->clientdeleglist.next = cp->clientdeleglist.prev = |
|
1670 |
&cp->clientdeleglist; |
|
1671 |
cp->clientdeleglist.dsp = NULL; |
|
1672 |
||
1673 |
/* set up the callback control structure */ |
|
1674 |
cp->cbinfo.cb_state = CB_UNINIT; |
|
1675 |
mutex_init(cp->cbinfo.cb_lock, NULL, MUTEX_DEFAULT, NULL); |
|
1676 |
cv_init(cp->cbinfo.cb_cv, NULL, CV_DEFAULT, NULL); |
|
1677 |
cv_init(cp->cbinfo.cb_cv_nullcaller, NULL, CV_DEFAULT, NULL); |
|
1678 |
||
1679 |
/* |
|
1680 |
* Associate the client_t with the current server instance. |
|
1681 |
* The hold is solely to satisfy the calling requirement of |
|
1682 |
* rfs4_servinst_assign(). In this case it's not strictly necessary. |
|
1683 |
*/ |
|
1684 |
rfs4_dbe_hold(cp->dbe); |
|
1685 |
rfs4_servinst_assign(cp, rfs4_cur_servinst); |
|
1686 |
rfs4_dbe_rele(cp->dbe); |
|
1687 |
||
1688 |
return (TRUE); |
|
1689 |
} |
|
1690 |
||
1691 |
/* |
|
1692 |
* Caller wants to generate/update the setclientid_confirm verifier |
|
1693 |
* associated with a client. This is done during the SETCLIENTID |
|
1694 |
* processing. |
|
1695 |
*/ |
|
1696 |
void |
|
1697 |
rfs4_client_scv_next(rfs4_client_t *cp) |
|
1698 |
{ |
|
1699 |
scid_confirm_verf *scvp; |
|
1700 |
||
1701 |
/* Init the value for the SETCLIENTID_CONFIRM verifier */ |
|
1702 |
scvp = (scid_confirm_verf *)&cp->confirm_verf; |
|
1703 |
scvp->cv_impl.gen_num++; |
|
1704 |
} |
|
1705 |
||
1706 |
void |
|
1707 |
rfs4_client_rele(rfs4_client_t *cp) |
|
1708 |
{ |
|
1709 |
rfs4_dbe_rele(cp->dbe); |
|
1710 |
} |
|
1711 |
||
1712 |
rfs4_client_t * |
|
1713 |
rfs4_findclient(nfs_client_id4 *client, bool_t *create, rfs4_client_t *oldcp) |
|
1714 |
{ |
|
1715 |
rfs4_client_t *cp; |
|
1716 |
||
1717 |
||
1718 |
if (oldcp) { |
|
1719 |
rw_enter(&rfs4_findclient_lock, RW_WRITER); |
|
1720 |
rfs4_dbe_hide(oldcp->dbe); |
|
1721 |
} else { |
|
1722 |
rw_enter(&rfs4_findclient_lock, RW_READER); |
|
1723 |
} |
|
1724 |
||
1725 |
cp = (rfs4_client_t *)rfs4_dbsearch(rfs4_nfsclnt_idx, client, |
|
1726 |
create, (void *)client, RFS4_DBS_VALID); |
|
1727 |
||
1728 |
if (oldcp) |
|
1729 |
rfs4_dbe_unhide(oldcp->dbe); |
|
1730 |
||
1731 |
rw_exit(&rfs4_findclient_lock); |
|
1732 |
||
1733 |
return (cp); |
|
1734 |
} |
|
1735 |
||
1736 |
rfs4_client_t * |
|
1737 |
rfs4_findclient_by_id(clientid4 clientid, bool_t find_unconfirmed) |
|
1738 |
{ |
|
1739 |
rfs4_client_t *cp; |
|
1740 |
bool_t create = FALSE; |
|
1741 |
cid *cidp = (cid *)&clientid; |
|
1742 |
||
1743 |
/* If we're a cluster and the nodeid isn't right, short-circuit */ |
|
1744 |
if (cluster_bootflags & CLUSTER_BOOTED && foreign_clientid(cidp)) |
|
1745 |
return (NULL); |
|
1746 |
||
1747 |
rw_enter(&rfs4_findclient_lock, RW_READER); |
|
1748 |
||
1749 |
cp = (rfs4_client_t *)rfs4_dbsearch(rfs4_clientid_idx, &clientid, |
|
1750 |
&create, NULL, RFS4_DBS_VALID); |
|
1751 |
||
1752 |
rw_exit(&rfs4_findclient_lock); |
|
1753 |
||
1754 |
if (cp && cp->need_confirm && find_unconfirmed == FALSE) { |
|
1755 |
rfs4_client_rele(cp); |
|
1756 |
return (NULL); |
|
1757 |
} else { |
|
1758 |
return (cp); |
|
1759 |
} |
|
1760 |
} |
|
1761 |
||
1762 |
bool_t |
|
1763 |
rfs4_lease_expired(rfs4_client_t *cp) |
|
1764 |
{ |
|
1765 |
bool_t rc; |
|
1766 |
||
1767 |
rfs4_dbe_lock(cp->dbe); |
|
1768 |
||
1769 |
/* |
|
1770 |
* If the admin has executed clear_locks for this |
|
1771 |
* client id, force expire will be set, so no need |
|
1772 |
* to calculate anything because it's "outa here". |
|
1773 |
*/ |
|
1774 |
if (cp->forced_expire) { |
|
1775 |
rc = TRUE; |
|
1776 |
} else { |
|
1777 |
rc = (gethrestime_sec() - cp->last_access > rfs4_lease_time); |
|
1778 |
} |
|
1779 |
||
1780 |
/* |
|
1781 |
* If the lease has expired we will also want |
|
1782 |
* to remove any stable storage state data. So |
|
1783 |
* mark the client id accordingly. |
|
1784 |
*/ |
|
1785 |
if (!cp->ss_remove) |
|
1786 |
cp->ss_remove = (rc == TRUE); |
|
1787 |
||
1788 |
rfs4_dbe_unlock(cp->dbe); |
|
1789 |
||
1790 |
return (rc); |
|
1791 |
} |
|
1792 |
||
1793 |
void |
|
1794 |
rfs4_update_lease(rfs4_client_t *cp) |
|
1795 |
{ |
|
1796 |
rfs4_dbe_lock(cp->dbe); |
|
1797 |
if (!cp->forced_expire) |
|
1798 |
cp->last_access = gethrestime_sec(); |
|
1799 |
rfs4_dbe_unlock(cp->dbe); |
|
1800 |
} |
|
1801 |
||
1802 |
||
1803 |
static bool_t |
|
1804 |
EQOPENOWNER(open_owner4 *a, open_owner4 *b) |
|
1805 |
{ |
|
1806 |
bool_t rc; |
|
1807 |
||
1808 |
if (a->clientid != b->clientid) |
|
1809 |
return (FALSE); |
|
1810 |
||
1811 |
if (a->owner_len != b->owner_len) |
|
1812 |
return (FALSE); |
|
1813 |
||
1814 |
rc = (bcmp(a->owner_val, b->owner_val, a->owner_len) == 0); |
|
1815 |
||
1816 |
return (rc); |
|
1817 |
} |
|
1818 |
||
1819 |
static uint_t |
|
1820 |
openowner_hash(void *key) |
|
1821 |
{ |
|
1822 |
int i; |
|
1823 |
open_owner4 *openowner = key; |
|
1824 |
uint_t hash = 0; |
|
1825 |
||
1826 |
for (i = 0; i < openowner->owner_len; i++) { |
|
1827 |
hash <<= 4; |
|
1828 |
hash += (uint_t)openowner->owner_val[i]; |
|
1829 |
} |
|
1830 |
hash += (uint_t)openowner->clientid; |
|
1831 |
hash |= (openowner->clientid >> 32); |
|
1832 |
||
1833 |
return (hash); |
|
1834 |
} |
|
1835 |
||
1836 |
static bool_t |
|
1837 |
openowner_compare(rfs4_entry_t u_entry, void *key) |
|
1838 |
{ |
|
1839 |
rfs4_openowner_t *op = (rfs4_openowner_t *)u_entry; |
|
1840 |
open_owner4 *arg = key; |
|
1841 |
||
1842 |
return (EQOPENOWNER(&op->owner, arg)); |
|
1843 |
} |
|
1844 |
||
1845 |
void * |
|
1846 |
openowner_mkkey(rfs4_entry_t u_entry) |
|
1847 |
{ |
|
1848 |
rfs4_openowner_t *op = (rfs4_openowner_t *)u_entry; |
|
1849 |
||
1850 |
return (&op->owner); |
|
1851 |
} |
|
1852 |
||
1853 |
static bool_t |
|
1854 |
rfs4_openowner_expiry(rfs4_entry_t u_entry) |
|
1855 |
{ |
|
1856 |
rfs4_openowner_t *op = (rfs4_openowner_t *)u_entry; |
|
1857 |
||
1858 |
if (rfs4_dbe_is_invalid(op->dbe)) |
|
1859 |
return (TRUE); |
|
1860 |
return ((gethrestime_sec() - op->client->last_access |
|
1861 |
> rfs4_lease_time)); |
|
1862 |
} |
|
1863 |
||
1864 |
static void |
|
1865 |
rfs4_openowner_destroy(rfs4_entry_t u_entry) |
|
1866 |
{ |
|
1867 |
rfs4_openowner_t *op = (rfs4_openowner_t *)u_entry; |
|
1868 |
||
1869 |
rfs4_sw_destroy(&op->oo_sw); |
|
1870 |
||
1871 |
/* Remove open owner from client's lists of open owners */ |
|
1872 |
rfs4_dbe_lock(op->client->dbe); |
|
1873 |
||
1874 |
remque(&op->openownerlist); |
|
1875 |
op->openownerlist.next = op->openownerlist.prev = &op->openownerlist; |
|
1876 |
||
1877 |
rfs4_dbe_unlock(op->client->dbe); |
|
1878 |
||
1879 |
/* One less reference to the client */ |
|
1880 |
rfs4_client_rele(op->client); |
|
1881 |
op->client = NULL; |
|
1882 |
||
1883 |
/* Free the last reply for this lock owner */ |
|
1884 |
rfs4_free_reply(op->reply); |
|
1885 |
||
1886 |
if (op->reply_fh.nfs_fh4_val) { |
|
1887 |
kmem_free(op->reply_fh.nfs_fh4_val, op->reply_fh.nfs_fh4_len); |
|
1888 |
op->reply_fh.nfs_fh4_val = NULL; |
|
1889 |
op->reply_fh.nfs_fh4_len = 0; |
|
1890 |
} |
|
1891 |
||
1892 |
/* Free the lock owner id */ |
|
1893 |
kmem_free(op->owner.owner_val, op->owner.owner_len); |
|
1894 |
} |
|
1895 |
||
1896 |
void |
|
1897 |
rfs4_openowner_rele(rfs4_openowner_t *op) |
|
1898 |
{ |
|
1899 |
rfs4_dbe_rele(op->dbe); |
|
1900 |
} |
|
1901 |
||
1902 |
static bool_t |
|
1903 |
rfs4_openowner_create(rfs4_entry_t u_entry, void *arg) |
|
1904 |
{ |
|
1905 |
rfs4_openowner_t *op = (rfs4_openowner_t *)u_entry; |
|
1906 |
rfs4_openowner_t *argp = (rfs4_openowner_t *)arg; |
|
1907 |
open_owner4 *openowner = &argp->owner; |
|
1908 |
seqid4 seqid = argp->open_seqid; |
|
1909 |
rfs4_client_t *cp; |
|
1910 |
bool_t create = FALSE; |
|
1911 |
||
1912 |
rw_enter(&rfs4_findclient_lock, RW_READER); |
|
1913 |
||
1914 |
cp = (rfs4_client_t *)rfs4_dbsearch(rfs4_clientid_idx, |
|
1915 |
&openowner->clientid, |
|
1916 |
&create, NULL, RFS4_DBS_VALID); |
|
1917 |
||
1918 |
rw_exit(&rfs4_findclient_lock); |
|
1919 |
||
1920 |
if (cp == NULL) |
|
1921 |
return (FALSE); |
|
1922 |
||
1923 |
op->reply_fh.nfs_fh4_len = 0; |
|
1924 |
op->reply_fh.nfs_fh4_val = NULL; |
|
1925 |
||
1926 |
op->owner.clientid = openowner->clientid; |
|
1927 |
op->owner.owner_val = |
|
1928 |
kmem_alloc(openowner->owner_len, KM_SLEEP); |
|
1929 |
bcopy(openowner->owner_val, |
|
1930 |
op->owner.owner_val, openowner->owner_len); |
|
1931 |
op->owner.owner_len = openowner->owner_len; |
|
1932 |
||
1933 |
op->need_confirm = TRUE; |
|
1934 |
||
1935 |
rfs4_sw_init(&op->oo_sw); |
|
1936 |
||
1937 |
op->open_seqid = seqid; |
|
1938 |
bzero(op->reply, sizeof (nfs_resop4)); |
|
1939 |
op->client = cp; |
|
1940 |
op->cr_set = NULL; |
|
1941 |
/* Init lists for remque/insque */ |
|
1942 |
op->ownerstateids.next = op->ownerstateids.prev = &op->ownerstateids; |
|
1943 |
op->ownerstateids.sp = NULL; /* NULL since this is the state list */ |
|
1944 |
op->openownerlist.next = op->openownerlist.prev = &op->openownerlist; |
|
1945 |
op->openownerlist.oop = op; /* ourselves */ |
|
1946 |
||
1947 |
/* Insert openowner into client's open owner list */ |
|
1948 |
rfs4_dbe_lock(cp->dbe); |
|
1949 |
||
1950 |
insque(&op->openownerlist, cp->openownerlist.prev); |
|
1951 |
||
1952 |
rfs4_dbe_unlock(cp->dbe); |
|
1953 |
||
1954 |
return (TRUE); |
|
1955 |
} |
|
1956 |
||
1957 |
rfs4_openowner_t * |
|
1958 |
rfs4_findopenowner(open_owner4 *openowner, bool_t *create, seqid4 seqid) |
|
1959 |
{ |
|
1960 |
rfs4_openowner_t *op; |
|
1961 |
rfs4_openowner_t arg; |
|
1962 |
||
1963 |
arg.owner = *openowner; |
|
1964 |
arg.open_seqid = seqid; |
|
1965 |
op = (rfs4_openowner_t *)rfs4_dbsearch(rfs4_openowner_idx, openowner, |
|
1966 |
create, &arg, RFS4_DBS_VALID); |
|
1967 |
||
1968 |
return (op); |
|
1969 |
} |
|
1970 |
||
1971 |
void |
|
1972 |
rfs4_update_open_sequence(rfs4_openowner_t *op) |
|
1973 |
{ |
|
1974 |
||
1975 |
rfs4_dbe_lock(op->dbe); |
|
1976 |
||
1977 |
op->open_seqid++; |
|
1978 |
||
1979 |
rfs4_dbe_unlock(op->dbe); |
|
1980 |
} |
|
1981 |
||
1982 |
void |
|
1983 |
rfs4_update_open_resp(rfs4_openowner_t *op, nfs_resop4 *resp, nfs_fh4 *fh) |
|
1984 |
{ |
|
1985 |
||
1986 |
rfs4_dbe_lock(op->dbe); |
|
1987 |
||
1988 |
rfs4_free_reply(op->reply); |
|
1989 |
||
1990 |
rfs4_copy_reply(op->reply, resp); |
|
1991 |
||
1992 |
/* Save the filehandle if provided and free if not used */ |
|
1993 |
if (resp->nfs_resop4_u.opopen.status == NFS4_OK && |
|
1994 |
fh && fh->nfs_fh4_len) { |
|
1995 |
if (op->reply_fh.nfs_fh4_val == NULL) |
|
1996 |
op->reply_fh.nfs_fh4_val = |
|
1997 |
kmem_alloc(fh->nfs_fh4_len, KM_SLEEP); |
|
1998 |
nfs_fh4_copy(fh, &op->reply_fh); |
|
1999 |
} else { |
|
2000 |
if (op->reply_fh.nfs_fh4_val) { |
|
2001 |
kmem_free(op->reply_fh.nfs_fh4_val, |
|
2002 |
op->reply_fh.nfs_fh4_len); |
|
2003 |
op->reply_fh.nfs_fh4_val = NULL; |
|
2004 |
op->reply_fh.nfs_fh4_len = 0; |
|
2005 |
} |
|
2006 |
} |
|
2007 |
||
2008 |
rfs4_dbe_unlock(op->dbe); |
|
2009 |
} |
|
2010 |
||
2011 |
static bool_t |
|
2012 |
lockowner_compare(rfs4_entry_t u_entry, void *key) |
|
2013 |
{ |
|
2014 |
rfs4_lockowner_t *lo = (rfs4_lockowner_t *)u_entry; |
|
2015 |
lock_owner4 *b = (lock_owner4 *)key; |
|
2016 |
||
2017 |
if (lo->owner.clientid != b->clientid) |
|
2018 |
return (FALSE); |
|
2019 |
||
2020 |
if (lo->owner.owner_len != b->owner_len) |
|
2021 |
return (FALSE); |
|
2022 |
||
2023 |
return (bcmp(lo->owner.owner_val, b->owner_val, |
|
2024 |
lo->owner.owner_len) == 0); |
|
2025 |
} |
|
2026 |
||
2027 |
void * |
|
2028 |
lockowner_mkkey(rfs4_entry_t u_entry) |
|
2029 |
{ |
|
2030 |
rfs4_lockowner_t *lo = (rfs4_lockowner_t *)u_entry; |
|
2031 |
||
2032 |
return (&lo->owner); |
|
2033 |
} |
|
2034 |
||
2035 |
static uint32_t |
|
2036 |
lockowner_hash(void *key) |
|
2037 |
{ |
|
2038 |
int i; |
|
2039 |
lock_owner4 *lockowner = key; |
|
2040 |
uint_t hash = 0; |
|
2041 |
||
2042 |
for (i = 0; i < lockowner->owner_len; i++) { |
|
2043 |
hash <<= 4; |
|
2044 |
hash += (uint_t)lockowner->owner_val[i]; |
|
2045 |
} |
|
2046 |
hash += (uint_t)lockowner->clientid; |
|
2047 |
hash |= (lockowner->clientid >> 32); |
|
2048 |
||
2049 |
return (hash); |
|
2050 |
} |
|
2051 |
||
2052 |
static uint32_t |
|
2053 |
pid_hash(void *key) |
|
2054 |
{ |
|
2055 |
return ((uint32_t)(uintptr_t)key); |
|
2056 |
} |
|
2057 |
||
2058 |
static void * |
|
2059 |
pid_mkkey(rfs4_entry_t u_entry) |
|
2060 |
{ |
|
2061 |
rfs4_lockowner_t *lo = (rfs4_lockowner_t *)u_entry; |
|
2062 |
||
2063 |
return ((void *)(uintptr_t)lo->pid); |
|
2064 |
} |
|
2065 |
||
2066 |
static bool_t |
|
2067 |
pid_compare(rfs4_entry_t u_entry, void *key) |
|
2068 |
{ |
|
2069 |
rfs4_lockowner_t *lo = (rfs4_lockowner_t *)u_entry; |
|
2070 |
||
2071 |
return (lo->pid == (pid_t)(uintptr_t)key); |
|
2072 |
} |
|
2073 |
||
2074 |
static void |
|
2075 |
rfs4_lockowner_destroy(rfs4_entry_t u_entry) |
|
2076 |
{ |
|
2077 |
rfs4_lockowner_t *lo = (rfs4_lockowner_t *)u_entry; |
|
2078 |
||
2079 |
/* Free the lock owner id */ |
|
2080 |
kmem_free(lo->owner.owner_val, lo->owner.owner_len); |
|
2081 |
rfs4_client_rele(lo->client); |
|
2082 |
} |
|
2083 |
||
2084 |
void |
|
2085 |
rfs4_lockowner_rele(rfs4_lockowner_t *lo) |
|
2086 |
{ |
|
2087 |
rfs4_dbe_rele(lo->dbe); |
|
2088 |
} |
|
2089 |
||
2090 |
/* ARGSUSED */ |
|
2091 |
static bool_t |
|
2092 |
rfs4_lockowner_expiry(rfs4_entry_t u_entry) |
|
2093 |
{ |
|
2094 |
/* |
|
2095 |
* Since expiry is called with no other references on |
|
2096 |
* this struct, go ahead and have it removed. |
|
2097 |
*/ |
|
2098 |
return (TRUE); |
|
2099 |
} |
|
2100 |
||
2101 |
static bool_t |
|
2102 |
rfs4_lockowner_create(rfs4_entry_t u_entry, void *arg) |
|
2103 |
{ |
|
2104 |
rfs4_lockowner_t *lo = (rfs4_lockowner_t *)u_entry; |
|
2105 |
lock_owner4 *lockowner = (lock_owner4 *)arg; |
|
2106 |
rfs4_client_t *cp; |
|
2107 |
bool_t create = FALSE; |
|
2108 |
||
2109 |
rw_enter(&rfs4_findclient_lock, RW_READER); |
|
2110 |
||
2111 |
cp = (rfs4_client_t *)rfs4_dbsearch(rfs4_clientid_idx, |
|
2112 |
&lockowner->clientid, |
|
2113 |
&create, NULL, RFS4_DBS_VALID); |
|
2114 |
||
2115 |
rw_exit(&rfs4_findclient_lock); |
|
2116 |
||
2117 |
if (cp == NULL) |
|
2118 |
return (FALSE); |
|
2119 |
||
2120 |
/* Reference client */ |
|
2121 |
lo->client = cp; |
|
2122 |
lo->owner.clientid = lockowner->clientid; |
|
2123 |
lo->owner.owner_val = kmem_alloc(lockowner->owner_len, KM_SLEEP); |
|
2124 |
bcopy(lockowner->owner_val, lo->owner.owner_val, lockowner->owner_len); |
|
2125 |
lo->owner.owner_len = lockowner->owner_len; |
|
2126 |
lo->pid = rfs4_dbe_getid(lo->dbe); |
|
2127 |
||
2128 |
return (TRUE); |
|
2129 |
} |
|
2130 |
||
2131 |
rfs4_lockowner_t * |
|
2132 |
rfs4_findlockowner(lock_owner4 *lockowner, bool_t *create) |
|
2133 |
{ |
|
2134 |
rfs4_lockowner_t *lo; |
|
2135 |
||
2136 |
lo = (rfs4_lockowner_t *)rfs4_dbsearch(rfs4_lockowner_idx, lockowner, |
|
2137 |
create, lockowner, RFS4_DBS_VALID); |
|
2138 |
||
2139 |
return (lo); |
|
2140 |
} |
|
2141 |
||
2142 |
rfs4_lockowner_t * |
|
2143 |
rfs4_findlockowner_by_pid(pid_t pid) |
|
2144 |
{ |
|
2145 |
rfs4_lockowner_t *lo; |
|
2146 |
bool_t create = FALSE; |
|
2147 |
||
2148 |
lo = (rfs4_lockowner_t *)rfs4_dbsearch(rfs4_lockowner_pid_idx, |
|
2149 |
(void *)(uintptr_t)pid, &create, NULL, RFS4_DBS_VALID); |
|
2150 |
||
2151 |
return (lo); |
|
2152 |
} |
|
2153 |
||
2154 |
||
2155 |
static uint32_t |
|
2156 |
file_hash(void *key) |
|
2157 |
{ |
|
2158 |
return (ADDRHASH(key)); |
|
2159 |
} |
|
2160 |
||
2161 |
static void * |
|
2162 |
file_mkkey(rfs4_entry_t u_entry) |
|
2163 |
{ |
|
2164 |
rfs4_file_t *fp = (rfs4_file_t *)u_entry; |
|
2165 |
||
2166 |
return (fp->vp); |
|
2167 |
} |
|
2168 |
||
2169 |
static bool_t |
|
2170 |
file_compare(rfs4_entry_t u_entry, void *key) |
|
2171 |
{ |
|
2172 |
rfs4_file_t *fp = (rfs4_file_t *)u_entry; |
|
2173 |
||
2174 |
return (fp->vp == (vnode_t *)key); |
|
2175 |
} |
|
2176 |
||
2177 |
static void |
|
2178 |
rfs4_file_destroy(rfs4_entry_t u_entry) |
|
2179 |
{ |
|
2180 |
rfs4_file_t *fp = (rfs4_file_t *)u_entry; |
|
2181 |
||
2182 |
ASSERT(fp->delegationlist.next == &fp->delegationlist); |
|
2183 |
if (fp->filehandle.nfs_fh4_val) |
|
2184 |
kmem_free(fp->filehandle.nfs_fh4_val, |
|
2185 |
fp->filehandle.nfs_fh4_len); |
|
2186 |
cv_destroy(fp->dinfo->recall_cv); |
|
2187 |
if (fp->vp) { |
|
2188 |
VN_RELE(fp->vp); |
|
2189 |
fp->vp = NULL; |
|
2190 |
} |
|
2191 |
rw_destroy(&fp->file_rwlock); |
|
2192 |
} |
|
2193 |
||
2194 |
/* |
|
2195 |
* Used to unlock the underlying dbe struct only |
|
2196 |
*/ |
|
2197 |
void |
|
2198 |
rfs4_file_rele(rfs4_file_t *fp) |
|
2199 |
{ |
|
2200 |
rfs4_dbe_rele(fp->dbe); |
|
2201 |
} |
|
2202 |
||
2203 |
/* |
|
2204 |
* Used to unlock the file rw lock and the file's dbe entry |
|
2205 |
* Only used to pair with rfs4_findfile_withlock() |
|
2206 |
*/ |
|
2207 |
void |
|
2208 |
rfs4_file_rele_withunlock(rfs4_file_t *fp) |
|
2209 |
{ |
|
2210 |
rw_exit(&fp->file_rwlock); |
|
2211 |
rfs4_dbe_rele(fp->dbe); |
|
2212 |
} |
|
2213 |
||
2214 |
typedef struct { |
|
2215 |
vnode_t *vp; |
|
2216 |
nfs_fh4 *fh; |
|
2217 |
} rfs4_fcreate_arg; |
|
2218 |
||
2219 |
static bool_t |
|
2220 |
rfs4_file_create(rfs4_entry_t u_entry, void *arg) |
|
2221 |
{ |
|
2222 |
rfs4_file_t *fp = (rfs4_file_t *)u_entry; |
|
2223 |
rfs4_fcreate_arg *ap = (rfs4_fcreate_arg *)arg; |
|
2224 |
vnode_t *vp = ap->vp; |
|
2225 |
nfs_fh4 *fh = ap->fh; |
|
2226 |
||
2227 |
VN_HOLD(vp); |
|
2228 |
||
2229 |
fp->filehandle.nfs_fh4_len = 0; |
|
2230 |
fp->filehandle.nfs_fh4_val = NULL; |
|
2231 |
ASSERT(fh && fh->nfs_fh4_len); |
|
2232 |
if (fh && fh->nfs_fh4_len) { |
|
2233 |
fp->filehandle.nfs_fh4_val = |
|
2234 |
kmem_alloc(fh->nfs_fh4_len, KM_SLEEP); |
|
2235 |
nfs_fh4_copy(fh, &fp->filehandle); |
|
2236 |
} |
|
2237 |
fp->vp = vp; |
|
2238 |
||
2239 |
/* Init list for remque/insque */ |
|
2240 |
fp->delegationlist.next = fp->delegationlist.prev = |
|
2241 |
&fp->delegationlist; |
|
2242 |
fp->delegationlist.dsp = NULL; /* NULL since this is state list */ |
|
2243 |
||
2244 |
fp->share_deny = fp->share_access = fp->access_read = 0; |
|
2245 |
fp->access_write = fp->deny_read = fp->deny_write = 0; |
|
2246 |
||
2247 |
mutex_init(fp->dinfo->recall_lock, NULL, MUTEX_DEFAULT, NULL); |
|
2248 |
cv_init(fp->dinfo->recall_cv, NULL, CV_DEFAULT, NULL); |
|
2249 |
||
2250 |
fp->dinfo->dtype = OPEN_DELEGATE_NONE; |
|
2251 |
||
2252 |
rw_init(&fp->file_rwlock, NULL, RW_DEFAULT, NULL); |
|
2253 |
||
2254 |
return (TRUE); |
|
2255 |
} |
|
2256 |
||
2257 |
rfs4_file_t * |
|
2258 |
rfs4_findfile(vnode_t *vp, nfs_fh4 *fh, bool_t *create) |
|
2259 |
{ |
|
2260 |
rfs4_file_t *fp; |
|
2261 |
rfs4_fcreate_arg arg; |
|
2262 |
||
2263 |
arg.vp = vp; |
|
2264 |
arg.fh = fh; |
|
2265 |
||
2266 |
fp = (rfs4_file_t *)rfs4_dbsearch(rfs4_file_idx, vp, create, |
|
2267 |
&arg, RFS4_DBS_VALID); |
|
2268 |
return (fp); |
|
2269 |
} |
|
2270 |
||
2271 |
/* |
|
2272 |
* Find a file in the db and once it is located, take the rw lock. |
|
2273 |
* Need to check the vnode pointer and if it does not exist (it was |
|
2274 |
* removed between the db location and check) redo the find. This |
|
2275 |
* assumes that a file struct that has a NULL vnode pointer is marked |
|
2276 |
* at 'invalid' and will not be found in the db the second time |
|
2277 |
* around. |
|
2278 |
*/ |
|
2279 |
rfs4_file_t * |
|
2280 |
rfs4_findfile_withlock(vnode_t *vp, nfs_fh4 *fh, bool_t *create) |
|
2281 |
{ |
|
2282 |
rfs4_file_t *fp; |
|
2283 |
rfs4_fcreate_arg arg; |
|
2284 |
bool_t screate = *create; |
|
2285 |
||
2286 |
retry: |
|
2287 |
arg.vp = vp; |
|
2288 |
arg.fh = fh; |
|
2289 |
||
2290 |
fp = (rfs4_file_t *)rfs4_dbsearch(rfs4_file_idx, vp, create, |
|
2291 |
&arg, RFS4_DBS_VALID); |
|
2292 |
if (fp != NULL) { |
|
2293 |
rw_enter(&fp->file_rwlock, RW_WRITER); |
|
2294 |
if (fp->vp == NULL) { |
|
2295 |
rw_exit(&fp->file_rwlock); |
|
2296 |
rfs4_file_rele(fp); |
|
2297 |
*create = screate; |
|
2298 |
goto retry; |
|
2299 |
} |
|
2300 |
} |
|
2301 |
||
2302 |
return (fp); |
|
2303 |
} |
|
2304 |
||
2305 |
static uint32_t |
|
2306 |
lo_state_hash(void *key) |
|
2307 |
{ |
|
2308 |
stateid_t *id = key; |
|
2309 |
||
2310 |
return (id->bits.ident+id->bits.pid); |
|
2311 |
} |
|
2312 |
||
2313 |
static bool_t |
|
2314 |
lo_state_compare(rfs4_entry_t u_entry, void *key) |
|
2315 |
{ |
|
2316 |
rfs4_lo_state_t *lop = (rfs4_lo_state_t *)u_entry; |
|
2317 |
stateid_t *id = key; |
|
2318 |
bool_t rc; |
|
2319 |
||
2320 |
rc = (lop->lockid.bits.boottime == id->bits.boottime && |
|
2321 |
lop->lockid.bits.type == id->bits.type && |
|
2322 |
lop->lockid.bits.ident == id->bits.ident && |
|
2323 |
lop->lockid.bits.pid == id->bits.pid); |
|
2324 |
||
2325 |
return (rc); |
|
2326 |
} |
|
2327 |
||
2328 |
static void * |
|
2329 |
lo_state_mkkey(rfs4_entry_t u_entry) |
|
2330 |
{ |
|
2331 |
rfs4_lo_state_t *lsp = (rfs4_lo_state_t *)u_entry; |
|
2332 |
||
2333 |
return (&lsp->lockid); |
|
2334 |
} |
|
2335 |
||
2336 |
static bool_t |
|
2337 |
rfs4_lo_state_expiry(rfs4_entry_t u_entry) |
|
2338 |
{ |
|
2339 |
rfs4_lo_state_t *lsp = (rfs4_lo_state_t *)u_entry; |
|
2340 |
||
2341 |
if (rfs4_dbe_is_invalid(lsp->dbe)) |
|
2342 |
return (TRUE); |
|
2343 |
if (lsp->state->closed) |
|
2344 |
return (TRUE); |
|
2345 |
return ((gethrestime_sec() - lsp->state->owner->client->last_access |
|
2346 |
> rfs4_lease_time)); |
|
2347 |
} |
|
2348 |
||
2349 |
static void |
|
2350 |
rfs4_lo_state_destroy(rfs4_entry_t u_entry) |
|
2351 |
{ |
|
2352 |
rfs4_lo_state_t *lsp = (rfs4_lo_state_t *)u_entry; |
|
2353 |
||
2354 |
rfs4_sw_destroy(&lsp->ls_sw); |
|
2355 |
||
2356 |
/* Make sure to release the file locks */ |
|
2357 |
if (lsp->locks_cleaned == FALSE) { |
|
2358 |
lsp->locks_cleaned = TRUE; |
|
2359 |
if (lsp->locker->client->sysidt != LM_NOSYSID) { |
|
2360 |
/* Is the PxFS kernel module loaded? */ |
|
2361 |
if (lm_remove_file_locks != NULL) { |
|
2362 |
int new_sysid; |
|
2363 |
||
2364 |
/* Encode the cluster nodeid in new sysid */ |
|
2365 |
new_sysid = lsp->locker->client->sysidt; |
|
2366 |
lm_set_nlmid_flk(&new_sysid); |
|
2367 |
||
2368 |
/* |
|
2369 |
* This PxFS routine removes file locks for a |
|
2370 |
* client over all nodes of a cluster. |
|
2371 |
*/ |
|
2372 |
NFS4_DEBUG(rfs4_debug, (CE_NOTE, |
|
2373 |
"lm_remove_file_locks(sysid=0x%x)\n", |
|
2374 |
new_sysid)); |
|
2375 |
(*lm_remove_file_locks)(new_sysid); |
|
2376 |
} else { |
|
2377 |
(void) cleanlocks(lsp->state->finfo->vp, |
|
2378 |
lsp->locker->pid, |
|
2379 |
lsp->locker->client->sysidt); |
|
2380 |
} |
|
2381 |
} |
|
2382 |
} |
|
2383 |
||
2384 |
rfs4_dbe_lock(lsp->state->dbe); |
|
2385 |
||
2386 |
remque(&lsp->lockownerlist); |
|
2387 |
lsp->lockownerlist.next = lsp->lockownerlist.prev = |
|
2388 |
&lsp->lockownerlist; |
|
2389 |
||
2390 |
rfs4_dbe_unlock(lsp->state->dbe); |
|
2391 |
||
2392 |
/* Free the last reply for this state */ |
|
2393 |
rfs4_free_reply(lsp->reply); |
|
2394 |
||
2395 |
rfs4_lockowner_rele(lsp->locker); |
|
2396 |
lsp->locker = NULL; |
|
2397 |
||
2398 |
rfs4_state_rele_nounlock(lsp->state); |
|
2399 |
lsp->state = NULL; |
|
2400 |
} |
|
2401 |
||
2402 |
static bool_t |
|
2403 |
rfs4_lo_state_create(rfs4_entry_t u_entry, void *arg) |
|
2404 |
{ |
|
2405 |
rfs4_lo_state_t *lsp = (rfs4_lo_state_t *)u_entry; |
|
2406 |
rfs4_lo_state_t *argp = (rfs4_lo_state_t *)arg; |
|
2407 |
rfs4_lockowner_t *lo = argp->locker; |
|
2408 |
rfs4_state_t *sp = argp->state; |
|
2409 |
||
2410 |
lsp->state = sp; |
|
2411 |
||
2412 |
lsp->lockid = sp->stateid; |
|
2413 |
lsp->lockid.bits.type = LOCKID; |
|
2414 |
lsp->lockid.bits.chgseq = 0; |
|
2415 |
lsp->lockid.bits.pid = lo->pid; |
|
2416 |
||
2417 |
lsp->locks_cleaned = FALSE; |
|
2418 |
lsp->lock_completed = FALSE; |
|
2419 |
||
2420 |
rfs4_sw_init(&lsp->ls_sw); |
|
2421 |
||
2422 |
/* Attached the supplied lock owner */ |
|
2423 |
rfs4_dbe_hold(lo->dbe); |
|
2424 |
lsp->locker = lo; |
|
2425 |
||
2426 |
lsp->lockownerlist.next = lsp->lockownerlist.prev = |
|
2427 |
&lsp->lockownerlist; |
|
2428 |
lsp->lockownerlist.lsp = lsp; |
|
2429 |
||
2430 |
rfs4_dbe_lock(sp->dbe); |
|
2431 |
||
2432 |
insque(&lsp->lockownerlist, sp->lockownerlist.prev); |
|
2433 |
||
2434 |
rfs4_dbe_hold(sp->dbe); |
|
2435 |
||
2436 |
rfs4_dbe_unlock(sp->dbe); |
|
2437 |
||
2438 |
return (TRUE); |
|
2439 |
} |
|
2440 |
||
2441 |
void |
|
2442 |
rfs4_lo_state_rele(rfs4_lo_state_t *lsp, bool_t unlock_fp) |
|
2443 |
{ |
|
2444 |
if (unlock_fp == TRUE) |
|
2445 |
rw_exit(&lsp->state->finfo->file_rwlock); |
|
2446 |
rfs4_dbe_rele(lsp->dbe); |
|
2447 |
} |
|
2448 |
||
2449 |
static rfs4_lo_state_t * |
|
2450 |
rfs4_findlo_state(stateid_t *id, bool_t lock_fp) |
|
2451 |
{ |
|
2452 |
rfs4_lo_state_t *lsp; |
|
2453 |
bool_t create = FALSE; |
|
2454 |
||
2455 |
lsp = (rfs4_lo_state_t *)rfs4_dbsearch(rfs4_lo_state_idx, id, |
|
2456 |
&create, NULL, RFS4_DBS_VALID); |
|
2457 |
if (lock_fp == TRUE && lsp != NULL) |
|
2458 |
rw_enter(&lsp->state->finfo->file_rwlock, RW_READER); |
|
2459 |
||
2460 |
return (lsp); |
|
2461 |
} |
|
2462 |
||
2463 |
||
2464 |
static uint32_t |
|
2465 |
lo_state_lo_hash(void *key) |
|
2466 |
{ |
|
2467 |
rfs4_lo_state_t *lop = key; |
|
2468 |
||
2469 |
return (ADDRHASH(lop->locker) ^ ADDRHASH(lop->state)); |
|
2470 |
} |
|
2471 |
||
2472 |
static bool_t |
|
2473 |
lo_state_lo_compare(rfs4_entry_t u_entry, void *key) |
|
2474 |
{ |
|
2475 |
rfs4_lo_state_t *lop = (rfs4_lo_state_t *)u_entry; |
|
2476 |
rfs4_lo_state_t *keyp = key; |
|
2477 |
||
2478 |
return (keyp->locker == lop->locker && keyp->state == lop->state); |
|
2479 |
} |
|
2480 |
||
2481 |
static void * |
|
2482 |
lo_state_lo_mkkey(rfs4_entry_t u_entry) |
|
2483 |
{ |
|
2484 |
return (u_entry); |
|
2485 |
} |
|
2486 |
||
2487 |
rfs4_lo_state_t * |
|
2488 |
rfs4_findlo_state_by_owner(rfs4_lockowner_t *lo, |
|
2489 |
rfs4_state_t *sp, bool_t *create) |
|
2490 |
{ |
|
2491 |
rfs4_lo_state_t *lsp; |
|
2492 |
rfs4_lo_state_t arg; |
|
2493 |
||
2494 |
arg.locker = lo; |
|
2495 |
arg.state = sp; |
|
2496 |
||
2497 |
lsp = (rfs4_lo_state_t *)rfs4_dbsearch(rfs4_lo_state_owner_idx, &arg, |
|
2498 |
create, &arg, RFS4_DBS_VALID); |
|
2499 |
||
2500 |
return (lsp); |
|
2501 |
} |
|
2502 |
||
2503 |
static stateid_t |
|
2504 |
get_stateid(id_t eid) |
|
2505 |
{ |
|
2506 |
stateid_t id; |
|
2507 |
||
2508 |
id.bits.boottime = rfs4_start_time; |
|
2509 |
id.bits.ident = eid; |
|
2510 |
id.bits.chgseq = 0; |
|
2511 |
id.bits.type = 0; |
|
2512 |
id.bits.pid = 0; |
|
2513 |
||
2514 |
/* |
|
2515 |
* If we are booted as a cluster node, embed our nodeid. |
|
2516 |
* We've already done sanity checks in rfs4_client_create() so no |
|
2517 |
* need to repeat them here. |
|
2518 |
*/ |
|
2519 |
id.bits.clnodeid = (cluster_bootflags & CLUSTER_BOOTED) ? |
|
2520 |
clconf_get_nodeid() : 0; |
|
2521 |
||
2522 |
return (id); |
|
2523 |
} |
|
2524 |
||
2525 |
/* |
|
2526 |
* For use only when booted as a cluster node. |
|
2527 |
* Returns TRUE if the embedded nodeid indicates that this stateid was |
|
2528 |
* generated on another node. |
|
2529 |
*/ |
|
2530 |
static int |
|
2531 |
foreign_stateid(stateid_t *id) |
|
2532 |
{ |
|
2533 |
ASSERT(cluster_bootflags & CLUSTER_BOOTED); |
|
2534 |
return (id->bits.clnodeid != (uint32_t)clconf_get_nodeid()); |
|
2535 |
} |
|
2536 |
||
2537 |
/* |
|
2538 |
* For use only when booted as a cluster node. |
|
2539 |
* Returns TRUE if the embedded nodeid indicates that this clientid was |
|
2540 |
* generated on another node. |
|
2541 |
*/ |
|
2542 |
static int |
|
2543 |
foreign_clientid(cid *cidp) |
|
2544 |
{ |
|
2545 |
ASSERT(cluster_bootflags & CLUSTER_BOOTED); |
|
2546 |
return (cidp->impl_id.c_id >> CLUSTER_NODEID_SHIFT != |
|
2547 |
(uint32_t)clconf_get_nodeid()); |
|
2548 |
} |
|
2549 |
||
2550 |
/* |
|
2551 |
* For use only when booted as a cluster node. |
|
2552 |
* Embed our cluster nodeid into the clientid. |
|
2553 |
*/ |
|
2554 |
static void |
|
2555 |
embed_nodeid(cid *cidp) |
|
2556 |
{ |
|
2557 |
int clnodeid; |
|
2558 |
/* |
|
2559 |
* Currently, our state tables are small enough that their |
|
2560 |
* ids will leave enough bits free for the nodeid. If the |
|
2561 |
* tables become larger, we mustn't overwrite the id. |
|
2562 |
* Equally, we only have room for so many bits of nodeid, so |
|
2563 |
* must check that too. |
|
2564 |
*/ |
|
2565 |
ASSERT(cluster_bootflags & CLUSTER_BOOTED); |
|
2566 |
ASSERT(cidp->impl_id.c_id >> CLUSTER_NODEID_SHIFT == 0); |
|
2567 |
clnodeid = clconf_get_nodeid(); |
|
2568 |
ASSERT(clnodeid <= CLUSTER_MAX_NODEID); |
|
2569 |
ASSERT(clnodeid != NODEID_UNKNOWN); |
|
2570 |
cidp->impl_id.c_id |= (clnodeid << CLUSTER_NODEID_SHIFT); |
|
2571 |
} |
|
2572 |
||
2573 |
static uint32_t |
|
2574 |
state_hash(void *key) |
|
2575 |
{ |
|
2576 |
stateid_t *ip = (stateid_t *)key; |
|
2577 |
||
2578 |
return (ip->bits.ident); |
|
2579 |
} |
|
2580 |
||
2581 |
static bool_t |
|
2582 |
state_compare(rfs4_entry_t u_entry, void *key) |
|
2583 |
{ |
|
2584 |
rfs4_state_t *sp = (rfs4_state_t *)u_entry; |
|
2585 |
stateid_t *id = (stateid_t *)key; |
|
2586 |
bool_t rc; |
|
2587 |
||
2588 |
rc = (sp->stateid.bits.boottime == id->bits.boottime && |
|
2589 |
sp->stateid.bits.ident == id->bits.ident); |
|
2590 |
||
2591 |
return (rc); |
|
2592 |
} |
|
2593 |
||
2594 |
static void * |
|
2595 |
state_mkkey(rfs4_entry_t u_entry) |
|
2596 |
{ |
|
2597 |
rfs4_state_t *sp = (rfs4_state_t *)u_entry; |
|
2598 |
||
2599 |
return (&sp->stateid); |
|
2600 |
} |
|
2601 |
||
2602 |
static void |
|
2603 |
rfs4_state_destroy(rfs4_entry_t u_entry) |
|
2604 |
{ |
|
2605 |
rfs4_state_t *sp = (rfs4_state_t *)u_entry; |
|
2606 |
||
2607 |
ASSERT(&sp->lockownerlist == sp->lockownerlist.next); |
|
2608 |
||
2609 |
/* release any share locks for this stateid if it's still open */ |
|
2610 |
if (!sp->closed) |
|
2611 |
rfs4_unshare(sp); |
|
2612 |
||
2613 |
/* Were done with the file */ |
|
2614 |
rfs4_file_rele(sp->finfo); |
|
2615 |
sp->finfo = NULL; |
|
2616 |
||
2617 |
/* And now with the openowner */ |
|
2618 |
rfs4_dbe_lock(sp->owner->dbe); |
|
2619 |
||
2620 |
remque(&sp->ownerstateids); |
|
2621 |
sp->ownerstateids.next = sp->ownerstateids.prev = &sp->ownerstateids; |
|
2622 |
||
2623 |
rfs4_dbe_unlock(sp->owner->dbe); |
|
2624 |
||
2625 |
rfs4_openowner_rele(sp->owner); |
|
2626 |
sp->owner = NULL; |
|
2627 |
} |
|
2628 |
||
2629 |
static void |
|
2630 |
rfs4_state_rele_nounlock(rfs4_state_t *sp) |
|
2631 |
{ |
|
2632 |
rfs4_dbe_rele(sp->dbe); |
|
2633 |
} |
|
2634 |
||
2635 |
void |
|
2636 |
rfs4_state_rele(rfs4_state_t *sp) |
|
2637 |
{ |
|
2638 |
rw_exit(&sp->finfo->file_rwlock); |
|
2639 |
rfs4_dbe_rele(sp->dbe); |
|
2640 |
} |
|
2641 |
||
2642 |
static uint32_t |
|
2643 |
deleg_hash(void *key) |
|
2644 |
{ |
|
2645 |
rfs4_deleg_state_t *dsp = (rfs4_deleg_state_t *)key; |
|
2646 |
||
2647 |
return (ADDRHASH(dsp->client) ^ ADDRHASH(dsp->finfo)); |
|
2648 |
} |
|
2649 |
||
2650 |
static bool_t |
|
2651 |
deleg_compare(rfs4_entry_t u_entry, void *key) |
|
2652 |
{ |
|
2653 |
rfs4_deleg_state_t *dsp = (rfs4_deleg_state_t *)u_entry; |
|
2654 |
rfs4_deleg_state_t *kdsp = (rfs4_deleg_state_t *)key; |
|
2655 |
||
2656 |
return (dsp->client == kdsp->client && dsp->finfo == kdsp->finfo); |
|
2657 |
} |
|
2658 |
||
2659 |
static void * |
|
2660 |
deleg_mkkey(rfs4_entry_t u_entry) |
|
2661 |
{ |
|
2662 |
return (u_entry); |
|
2663 |
} |
|
2664 |
||
2665 |
static uint32_t |
|
2666 |
deleg_state_hash(void *key) |
|
2667 |
{ |
|
2668 |
stateid_t *ip = (stateid_t *)key; |
|
2669 |
||
2670 |
return (ip->bits.ident); |
|
2671 |
} |
|
2672 |
||
2673 |
static bool_t |
|
2674 |
deleg_state_compare(rfs4_entry_t u_entry, void *key) |
|
2675 |
{ |
|
2676 |
rfs4_deleg_state_t *dsp = (rfs4_deleg_state_t *)u_entry; |
|
2677 |
stateid_t *id = (stateid_t *)key; |
|
2678 |
bool_t rc; |
|
2679 |
||
2680 |
if (id->bits.type != DELEGID) |
|
2681 |
return (FALSE); |
|
2682 |
||
2683 |
rc = (dsp->delegid.bits.boottime == id->bits.boottime && |
|
2684 |
dsp->delegid.bits.ident == id->bits.ident); |
|
2685 |
||
2686 |
return (rc); |
|
2687 |
} |
|
2688 |
||
2689 |
static void * |
|
2690 |
deleg_state_mkkey(rfs4_entry_t u_entry) |
|
2691 |
{ |
|
2692 |
rfs4_deleg_state_t *dsp = (rfs4_deleg_state_t *)u_entry; |
|
2693 |
||
2694 |
return (&dsp->delegid); |
|
2695 |
} |
|
2696 |
||
2697 |
static bool_t |
|
2698 |
rfs4_deleg_state_expiry(rfs4_entry_t u_entry) |
|
2699 |
{ |
|
2700 |
rfs4_deleg_state_t *dsp = (rfs4_deleg_state_t *)u_entry; |
|
2701 |
||
2702 |
if (rfs4_dbe_is_invalid(dsp->dbe)) |
|
2703 |
return (TRUE); |
|
2704 |
return ((gethrestime_sec() - dsp->client->last_access |
|
2705 |
> rfs4_lease_time)); |
|
2706 |
||
2707 |
} |
|
2708 |
||
2709 |
static bool_t |
|
2710 |
rfs4_deleg_state_create(rfs4_entry_t u_entry, void *argp) |
|
2711 |
{ |
|
2712 |
rfs4_deleg_state_t *dsp = (rfs4_deleg_state_t *)u_entry; |
|
2713 |
rfs4_file_t *fp = ((rfs4_deleg_state_t *)argp)->finfo; |
|
2714 |
rfs4_client_t *cp = ((rfs4_deleg_state_t *)argp)->client; |
|
2715 |
||
2716 |
rfs4_dbe_hold(fp->dbe); |
|
2717 |
rfs4_dbe_hold(cp->dbe); |
|
2718 |
||
2719 |
dsp->delegid = get_stateid(rfs4_dbe_getid(dsp->dbe)); |
|
2720 |
dsp->delegid.bits.type = DELEGID; |
|
2721 |
dsp->finfo = fp; |
|
2722 |
dsp->client = cp; |
|
2723 |
dsp->dtype = OPEN_DELEGATE_NONE; |
|
2724 |
||
2725 |
dsp->time_granted = gethrestime_sec(); /* observability */ |
|
2726 |
dsp->time_revoked = 0; |
|
2727 |
||
2728 |
/* Init lists for remque/insque */ |
|
2729 |
dsp->delegationlist.next = dsp->delegationlist.prev = |
|
2730 |
&dsp->delegationlist; |
|
2731 |
dsp->delegationlist.dsp = dsp; |
|
2732 |
||
2733 |
dsp->clientdeleglist.next = dsp->clientdeleglist.prev = |
|
2734 |
&dsp->clientdeleglist; |
|
2735 |
dsp->clientdeleglist.dsp = dsp; |
|
2736 |
||
2737 |
/* Insert state on per open owner's list */ |
|
2738 |
rfs4_dbe_lock(cp->dbe); |
|
2739 |
||
2740 |
insque(&dsp->clientdeleglist, cp->clientdeleglist.prev); |
|
2741 |
||
2742 |
rfs4_dbe_unlock(cp->dbe); |
|
2743 |
||
2744 |
return (TRUE); |
|
2745 |
} |
|
2746 |
||
2747 |
static void |
|
2748 |
rfs4_deleg_state_destroy(rfs4_entry_t u_entry) |
|
2749 |
{ |
|
2750 |
rfs4_deleg_state_t *dsp = (rfs4_deleg_state_t *)u_entry; |
|
2751 |
||
2752 |
if (&dsp->delegationlist != dsp->delegationlist.next) |
|
2753 |
rfs4_return_deleg(dsp, FALSE); |
|
2754 |
||
2755 |
/* Were done with the file */ |
|
2756 |
rfs4_file_rele(dsp->finfo); |
|
2757 |
dsp->finfo = NULL; |
|
2758 |
||
2759 |
/* And now with the openowner */ |
|
2760 |
rfs4_dbe_lock(dsp->client->dbe); |
|
2761 |
||
2762 |
remque(&dsp->clientdeleglist); |
|
2763 |
dsp->clientdeleglist.next = dsp->clientdeleglist.prev = |
|
2764 |
&dsp->clientdeleglist; |
|
2765 |
||
2766 |
rfs4_dbe_unlock(dsp->client->dbe); |
|
2767 |
||
2768 |
rfs4_client_rele(dsp->client); |
|
2769 |
dsp->client = NULL; |
|
2770 |
} |
|
2771 |
||
2772 |
rfs4_deleg_state_t * |
|
2773 |
rfs4_finddeleg(rfs4_state_t *sp, bool_t *create) |
|
2774 |
{ |
|
2775 |
rfs4_deleg_state_t ds, *dsp; |
|
2776 |
||
2777 |
ds.client = sp->owner->client; |
|
2778 |
ds.finfo = sp->finfo; |
|
2779 |
||
2780 |
dsp = (rfs4_deleg_state_t *)rfs4_dbsearch(rfs4_deleg_idx, &ds, |
|
2781 |
create, &ds, RFS4_DBS_VALID); |
|
2782 |
||
2783 |
return (dsp); |
|
2784 |
} |
|
2785 |
||
2786 |
rfs4_deleg_state_t * |
|
2787 |
rfs4_finddelegstate(stateid_t *id) |
|
2788 |
{ |
|
2789 |
rfs4_deleg_state_t *dsp; |
|
2790 |
bool_t create = FALSE; |
|
2791 |
||
2792 |
dsp = (rfs4_deleg_state_t *)rfs4_dbsearch(rfs4_deleg_state_idx, id, |
|
2793 |
&create, NULL, RFS4_DBS_VALID); |
|
2794 |
||
2795 |
return (dsp); |
|
2796 |
} |
|
2797 |
||
2798 |
void |
|
2799 |
rfs4_deleg_state_rele(rfs4_deleg_state_t *dsp) |
|
2800 |
{ |
|
2801 |
rfs4_dbe_rele(dsp->dbe); |
|
2802 |
} |
|
2803 |
||
2804 |
void |
|
2805 |
rfs4_update_lock_sequence(rfs4_lo_state_t *lsp) |
|
2806 |
{ |
|
2807 |
||
2808 |
rfs4_dbe_lock(lsp->dbe); |
|
2809 |
||
2810 |
/* |
|
2811 |
* If we are skipping sequence id checking, this means that |
|
2812 |
* this is the first lock request and therefore the sequence |
|
2813 |
* id does not need to be updated. This only happens on the |
|
2814 |
* first lock request for a lockowner |
|
2815 |
*/ |
|
2816 |
if (!lsp->skip_seqid_check) |
|
2817 |
lsp->seqid++; |
|
2818 |
||
2819 |
rfs4_dbe_unlock(lsp->dbe); |
|
2820 |
} |
|
2821 |
||
2822 |
void |
|
2823 |
rfs4_update_lock_resp(rfs4_lo_state_t *lsp, nfs_resop4 *resp) |
|
2824 |
{ |
|
2825 |
||
2826 |
rfs4_dbe_lock(lsp->dbe); |
|
2827 |
||
2828 |
rfs4_free_reply(lsp->reply); |
|
2829 |
||
2830 |
rfs4_copy_reply(lsp->reply, resp); |
|
2831 |
||
2832 |
rfs4_dbe_unlock(lsp->dbe); |
|
2833 |
} |
|
2834 |
||
2835 |
void |
|
2836 |
rfs4_free_opens(rfs4_openowner_t *op, bool_t invalidate, |
|
2837 |
bool_t close_of_client) |
|
2838 |
{ |
|
2839 |
rfs4_state_t *sp; |
|
2840 |
||
2841 |
rfs4_dbe_lock(op->dbe); |
|
2842 |
||
2843 |
for (sp = op->ownerstateids.next->sp; sp != NULL; |
|
2844 |
sp = sp->ownerstateids.next->sp) { |
|
2845 |
rfs4_state_close(sp, FALSE, close_of_client, CRED()); |
|
2846 |
if (invalidate == TRUE) |
|
2847 |
rfs4_dbe_invalidate(sp->dbe); |
|
2848 |
} |
|
2849 |
||
2850 |
rfs4_dbe_unlock(op->dbe); |
|
2851 |
rfs4_dbe_invalidate(op->dbe); |
|
2852 |
} |
|
2853 |
||
2854 |
static uint32_t |
|
2855 |
state_owner_file_hash(void *key) |
|
2856 |
{ |
|
2857 |
rfs4_state_t *sp = key; |
|
2858 |
||
2859 |
return (ADDRHASH(sp->owner) ^ ADDRHASH(sp->finfo)); |
|
2860 |
} |
|
2861 |
||
2862 |
static bool_t |
|
2863 |
state_owner_file_compare(rfs4_entry_t u_entry, void *key) |
|
2864 |
{ |
|
2865 |
rfs4_state_t *sp = (rfs4_state_t *)u_entry; |
|
2866 |
rfs4_state_t *arg = key; |
|
2867 |
||
2868 |
if (sp->closed == TRUE) |
|
2869 |
return (FALSE); |
|
2870 |
||
2871 |
return (arg->owner == sp->owner && arg->finfo == sp->finfo); |
|
2872 |
} |
|
2873 |
||
2874 |
static void * |
|
2875 |
state_owner_file_mkkey(rfs4_entry_t u_entry) |
|
2876 |
{ |
|
2877 |
return (u_entry); |
|
2878 |
} |
|
2879 |
||
2880 |
static uint32_t |
|
2881 |
state_file_hash(void *key) |
|
2882 |
{ |
|
2883 |
return (ADDRHASH(key)); |
|
2884 |
} |
|
2885 |
||
2886 |
static bool_t |
|
2887 |
state_file_compare(rfs4_entry_t u_entry, void *key) |
|
2888 |
{ |
|
2889 |
rfs4_state_t *sp = (rfs4_state_t *)u_entry; |
|
2890 |
rfs4_file_t *fp = key; |
|
2891 |
||
2892 |
if (sp->closed == TRUE) |
|
2893 |
return (FALSE); |
|
2894 |
||
2895 |
return (fp == sp->finfo); |
|
2896 |
} |
|
2897 |
||
2898 |
static void * |
|
2899 |
state_file_mkkey(rfs4_entry_t u_entry) |
|
2900 |
{ |
|
2901 |
rfs4_state_t *sp = (rfs4_state_t *)u_entry; |
|
2902 |
||
2903 |
return (sp->finfo); |
|
2904 |
} |
|
2905 |
||
2906 |
rfs4_state_t * |
|
2907 |
rfs4_findstate_by_owner_file(rfs4_openowner_t *op, rfs4_file_t *file, |
|
2908 |
bool_t *create) |
|
2909 |
{ |
|
2910 |
rfs4_state_t *sp; |
|
2911 |
rfs4_state_t key; |
|
2912 |
||
2913 |
key.owner = op; |
|
2914 |
key.finfo = file; |
|
2915 |
||
2916 |
sp = (rfs4_state_t *)rfs4_dbsearch(rfs4_state_owner_file_idx, &key, |
|
2917 |
create, &key, RFS4_DBS_VALID); |
|
2918 |
||
2919 |
return (sp); |
|
2920 |
} |
|
2921 |
||
2922 |
/* This returns ANY state struct that refers to this file */ |
|
2923 |
static rfs4_state_t * |
|
2924 |
rfs4_findstate_by_file(rfs4_file_t *fp) |
|
2925 |
{ |
|
2926 |
bool_t create = FALSE; |
|
2927 |
||
2928 |
return ((rfs4_state_t *)rfs4_dbsearch(rfs4_state_file_idx, fp, |
|
2929 |
&create, fp, RFS4_DBS_VALID)); |
|
2930 |
} |
|
2931 |
||
2932 |
static bool_t |
|
2933 |
rfs4_state_expiry(rfs4_entry_t u_entry) |
|
2934 |
{ |
|
2935 |
rfs4_state_t *sp = (rfs4_state_t *)u_entry; |
|
2936 |
||
2937 |
if (rfs4_dbe_is_invalid(sp->dbe)) |
|
2938 |
return (TRUE); |
|
2939 |
||
2940 |
if (sp->closed == TRUE && |
|
2941 |
((gethrestime_sec() - rfs4_dbe_get_timerele(sp->dbe)) |
|
2942 |
> rfs4_lease_time)) |
|
2943 |
return (TRUE); |
|
2944 |
||
2945 |
return ((gethrestime_sec() - sp->owner->client->last_access |
|
2946 |
> rfs4_lease_time)); |
|
2947 |
} |
|
2948 |
||
2949 |
static bool_t |
|
2950 |
rfs4_state_create(rfs4_entry_t u_entry, void *argp) |
|
2951 |
{ |
|
2952 |
rfs4_state_t *sp = (rfs4_state_t *)u_entry; |
|
2953 |
rfs4_file_t *fp = ((rfs4_state_t *)argp)->finfo; |
|
2954 |
rfs4_openowner_t *op = ((rfs4_state_t *)argp)->owner; |
|
2955 |
||
2956 |
rfs4_dbe_hold(fp->dbe); |
|
2957 |
rfs4_dbe_hold(op->dbe); |
|
2958 |
sp->stateid = get_stateid(rfs4_dbe_getid(sp->dbe)); |
|
2959 |
sp->stateid.bits.type = OPENID; |
|
2960 |
sp->owner = op; |
|
2961 |
sp->finfo = fp; |
|
2962 |
||
2963 |
/* Init lists for remque/insque */ |
|
2964 |
sp->ownerstateids.next = sp->ownerstateids.prev = &sp->ownerstateids; |
|
2965 |
sp->ownerstateids.sp = sp; |
|
2966 |
sp->lockownerlist.next = sp->lockownerlist.prev = &sp->lockownerlist; |
|
2967 |
sp->lockownerlist.lsp = NULL; |
|
2968 |
||
2969 |
/* Insert state on per open owner's list */ |
|
2970 |
rfs4_dbe_lock(op->dbe); |
|
2971 |
||
2972 |
insque(&sp->ownerstateids, op->ownerstateids.prev); |
|
2973 |
||
2974 |
rfs4_dbe_unlock(op->dbe); |
|
2975 |
||
2976 |
return (TRUE); |
|
2977 |
} |
|
2978 |
||
2979 |
static rfs4_state_t * |
|
2980 |
rfs4_findstate(stateid_t *id, rfs4_dbsearch_type_t find_invalid, |
|
2981 |
bool_t lock_fp) |
|
2982 |
{ |
|
2983 |
rfs4_state_t *sp; |
|
2984 |
bool_t create = FALSE; |
|
2985 |
||
2986 |
sp = (rfs4_state_t *)rfs4_dbsearch(rfs4_state_idx, id, |
|
2987 |
&create, NULL, find_invalid); |
|
2988 |
if (lock_fp == TRUE && sp != NULL) |
|
2989 |
rw_enter(&sp->finfo->file_rwlock, RW_READER); |
|
2990 |
||
2991 |
return (sp); |
|
2992 |
} |
|
2993 |
||
2994 |
void |
|
2995 |
rfs4_state_close(rfs4_state_t *sp, bool_t lock_held, |
|
2996 |
bool_t close_of_client, cred_t *cr) |
|
2997 |
{ |
|
2998 |
/* Remove the associated lo_state owners */ |
|
2999 |
if (!lock_held) |
|
3000 |
rfs4_dbe_lock(sp->dbe); |
|
3001 |
if (sp->closed == FALSE) { |
|
3002 |
sp->closed = TRUE; |
|
3003 |
||
3004 |
rfs4_release_share_lock_state(sp, cr, close_of_client); |
|
3005 |
} |
|
3006 |
if (!lock_held) |
|
3007 |
rfs4_dbe_unlock(sp->dbe); |
|
3008 |
} |
|
3009 |
||
3010 |
/* |
|
3011 |
* Remove all state associated with the given client. |
|
3012 |
*/ |
|
3013 |
void |
|
3014 |
rfs4_client_state_remove(rfs4_client_t *cp) |
|
3015 |
{ |
|
3016 |
rfs4_openowner_t *oop; |
|
3017 |
||
3018 |
rfs4_dbe_lock(cp->dbe); |
|
3019 |
||
3020 |
for (oop = cp->openownerlist.next->oop; oop != NULL; |
|
3021 |
oop = oop->openownerlist.next->oop) { |
|
3022 |
rfs4_free_opens(oop, TRUE, TRUE); |
|
3023 |
} |
|
3024 |
||
3025 |
rfs4_dbe_unlock(cp->dbe); |
|
3026 |
} |
|
3027 |
||
3028 |
void |
|
3029 |
rfs4_client_close(rfs4_client_t *cp) |
|
3030 |
{ |
|
3031 |
/* Mark client as going away. */ |
|
3032 |
rfs4_dbe_lock(cp->dbe); |
|
3033 |
rfs4_dbe_invalidate(cp->dbe); |
|
3034 |
rfs4_dbe_unlock(cp->dbe); |
|
3035 |
||
3036 |
rfs4_client_state_remove(cp); |
|
3037 |
||
3038 |
/* Release the client */ |
|
3039 |
rfs4_client_rele(cp); |
|
3040 |
} |
|
3041 |
||
3042 |
nfsstat4 |
|
3043 |
rfs4_check_clientid(clientid4 *cp, int setclid_confirm) |
|
3044 |
{ |
|
3045 |
cid *cidp = (cid *) cp; |
|
3046 |
||
3047 |
/* |
|
3048 |
* If we are booted as a cluster node, check the embedded nodeid. |
|
3049 |
* If it indicates that this clientid was generated on another node, |
|
3050 |
* inform the client accordingly. |
|
3051 |
*/ |
|
3052 |
if (cluster_bootflags & CLUSTER_BOOTED && foreign_clientid(cidp)) |
|
3053 |
return (NFS4ERR_STALE_CLIENTID); |
|
3054 |
||
3055 |
/* |
|
3056 |
* If the server start time matches the time provided |
|
3057 |
* by the client (via the clientid) and this is NOT a |
|
3058 |
* setclientid_confirm then return EXPIRED. |
|
3059 |
*/ |
|
3060 |
if (!setclid_confirm && cidp->impl_id.start_time == rfs4_start_time) |
|
3061 |
return (NFS4ERR_EXPIRED); |
|
3062 |
||
3063 |
return (NFS4ERR_STALE_CLIENTID); |
|
3064 |
} |
|
3065 |
||
3066 |
/* |
|
3067 |
* This is used when a stateid has not been found amongst the |
|
3068 |
* current server's state. Check the stateid to see if it |
|
3069 |
* was from this server instantiation or not. |
|
3070 |
*/ |
|
3071 |
static nfsstat4 |
|
3072 |
what_stateid_error(stateid_t *id, stateid_type_t type) |
|
3073 |
{ |
|
3074 |
/* If we are booted as a cluster node, was stateid locally generated? */ |
|
3075 |
if ((cluster_bootflags & CLUSTER_BOOTED) && foreign_stateid(id)) |
|
3076 |
return (NFS4ERR_STALE_STATEID); |
|
3077 |
||
3078 |
/* If types don't match then no use checking further */ |
|
3079 |
if (type != id->bits.type) |
|
3080 |
return (NFS4ERR_BAD_STATEID); |
|
3081 |
||
3082 |
/* From a previous server instantiation, return STALE */ |
|
3083 |
if (id->bits.boottime < rfs4_start_time) |
|
3084 |
return (NFS4ERR_STALE_STATEID); |
|
3085 |
||
3086 |
/* |
|
3087 |
* From this server but the state is most likely beyond lease |
|
3088 |
* timeout: return NFS4ERR_EXPIRED. However, there is the |
|
3089 |
* case of a delegation stateid. For delegations, there is a |
|
3090 |
* case where the state can be removed without the client's |
|
3091 |
* knowledge/consent: revocation. In the case of delegation |
|
3092 |
* revocation, the delegation state will be removed and will |
|
3093 |
* not be found. If the client does something like a |
|
3094 |
* DELEGRETURN or even a READ/WRITE with a delegatoin stateid |
|
3095 |
* that has been revoked, the server should return BAD_STATEID |
|
3096 |
* instead of the more common EXPIRED error. |
|
3097 |
*/ |
|
3098 |
if (id->bits.boottime == rfs4_start_time) { |
|
3099 |
if (type == DELEGID) |
|
3100 |
return (NFS4ERR_BAD_STATEID); |
|
3101 |
else |
|
3102 |
return (NFS4ERR_EXPIRED); |
|
3103 |
} |
|
3104 |
||
3105 |
return (NFS4ERR_BAD_STATEID); |
|
3106 |
} |
|
3107 |
||
3108 |
/* |
|
3109 |
* Used later on to find the various state structs. When called from |
|
3110 |
* rfs4_check_stateid()->rfs4_get_all_state(), no file struct lock is |
|
3111 |
* taken (it is not needed) and helps on the read/write path with |
|
3112 |
* respect to performance. |
|
3113 |
*/ |
|
3114 |
static nfsstat4 |
|
3115 |
rfs4_get_state_lockit(stateid4 *stateid, rfs4_state_t **spp, |
|
3116 |
rfs4_dbsearch_type_t find_invalid, bool_t lock_fp) |
|
3117 |
{ |
|
3118 |
stateid_t *id = (stateid_t *)stateid; |
|
3119 |
rfs4_state_t *sp; |
|
3120 |
||
3121 |
*spp = NULL; |
|
3122 |
||
3123 |
/* If we are booted as a cluster node, was stateid locally generated? */ |
|
3124 |
if ((cluster_bootflags & CLUSTER_BOOTED) && foreign_stateid(id)) |
|
3125 |
return (NFS4ERR_STALE_STATEID); |
|
3126 |
||
3127 |
sp = rfs4_findstate(id, find_invalid, lock_fp); |
|
3128 |
if (sp == NULL) { |
|
3129 |
return (what_stateid_error(id, OPENID)); |
|
3130 |
} |
|
3131 |
||
3132 |
if (rfs4_lease_expired(sp->owner->client)) { |
|
3133 |
if (lock_fp == TRUE) |
|
3134 |
rfs4_state_rele(sp); |
|
3135 |
else |
|
3136 |
rfs4_state_rele_nounlock(sp); |
|
3137 |
return (NFS4ERR_EXPIRED); |
|
3138 |
} |
|
3139 |
||
3140 |
*spp = sp; |
|
3141 |
||
3142 |
return (NFS4_OK); |
|
3143 |
} |
|
3144 |
||
3145 |
nfsstat4 |
|
3146 |
rfs4_get_state(stateid4 *stateid, rfs4_state_t **spp, |
|
3147 |
rfs4_dbsearch_type_t find_invalid) |
|
3148 |
{ |
|
3149 |
return (rfs4_get_state_lockit(stateid, spp, find_invalid, TRUE)); |
|
3150 |
} |
|
3151 |
||
3152 |
int |
|
3153 |
rfs4_check_stateid_seqid(rfs4_state_t *sp, stateid4 *stateid) |
|
3154 |
{ |
|
3155 |
stateid_t *id = (stateid_t *)stateid; |
|
3156 |
||
3157 |
if (rfs4_lease_expired(sp->owner->client)) |
|
3158 |
return (NFS4_CHECK_STATEID_EXPIRED); |
|
3159 |
||
3160 |
/* Stateid is some time in the future - that's bad */ |
|
3161 |
if (sp->stateid.bits.chgseq < id->bits.chgseq) |
|
3162 |
return (NFS4_CHECK_STATEID_BAD); |
|
3163 |
||
3164 |
if (sp->stateid.bits.chgseq == id->bits.chgseq + 1) |
|
3165 |
return (NFS4_CHECK_STATEID_REPLAY); |
|
3166 |
||
3167 |
/* Stateid is some time in the past - that's old */ |
|
3168 |
if (sp->stateid.bits.chgseq > id->bits.chgseq) |
|
3169 |
return (NFS4_CHECK_STATEID_OLD); |
|
3170 |
||
3171 |
/* Caller needs to know about confirmation before closure */ |
|
3172 |
if (sp->owner->need_confirm) |
|
3173 |
return (NFS4_CHECK_STATEID_UNCONFIRMED); |
|
3174 |
||
3175 |
if (sp->closed == TRUE) |
|
3176 |
return (NFS4_CHECK_STATEID_CLOSED); |
|
3177 |
||
3178 |
return (NFS4_CHECK_STATEID_OKAY); |
|
3179 |
} |
|
3180 |
||
3181 |
int |
|
3182 |
rfs4_check_lo_stateid_seqid(rfs4_lo_state_t *lsp, stateid4 *stateid) |
|
3183 |
{ |
|
3184 |
stateid_t *id = (stateid_t *)stateid; |
|
3185 |
||
3186 |
if (rfs4_lease_expired(lsp->state->owner->client)) |
|
3187 |
return (NFS4_CHECK_STATEID_EXPIRED); |
|
3188 |
||
3189 |
/* Stateid is some time in the future - that's bad */ |
|
3190 |
if (lsp->lockid.bits.chgseq < id->bits.chgseq) |
|
3191 |
return (NFS4_CHECK_STATEID_BAD); |
|
3192 |
||
3193 |
if (lsp->lockid.bits.chgseq == id->bits.chgseq + 1) |
|
3194 |
return (NFS4_CHECK_STATEID_REPLAY); |
|
3195 |
||
3196 |
/* Stateid is some time in the past - that's old */ |
|
3197 |
if (lsp->lockid.bits.chgseq > id->bits.chgseq) |
|
3198 |
return (NFS4_CHECK_STATEID_OLD); |
|
3199 |
||
3200 |
return (NFS4_CHECK_STATEID_OKAY); |
|
3201 |
} |
|
3202 |
||
3203 |
nfsstat4 |
|
3204 |
rfs4_get_deleg_state(stateid4 *stateid, rfs4_deleg_state_t **dspp) |
|
3205 |
{ |
|
3206 |
stateid_t *id = (stateid_t *)stateid; |
|
3207 |
rfs4_deleg_state_t *dsp; |
|
3208 |
||
3209 |
*dspp = NULL; |
|
3210 |
||
3211 |
/* If we are booted as a cluster node, was stateid locally generated? */ |
|
3212 |
if ((cluster_bootflags & CLUSTER_BOOTED) && foreign_stateid(id)) |
|
3213 |
return (NFS4ERR_STALE_STATEID); |
|
3214 |
||
3215 |
dsp = rfs4_finddelegstate(id); |
|
3216 |
if (dsp == NULL) { |
|
3217 |
return (what_stateid_error(id, DELEGID)); |
|
3218 |
} |
|
3219 |
||
3220 |
if (rfs4_lease_expired(dsp->client)) { |
|
3221 |
rfs4_deleg_state_rele(dsp); |
|
3222 |
return (NFS4ERR_EXPIRED); |
|
3223 |
} |
|
3224 |
||
3225 |
*dspp = dsp; |
|
3226 |
||
3227 |
return (NFS4_OK); |
|
3228 |
} |
|
3229 |
||
3230 |
nfsstat4 |
|
3231 |
rfs4_get_lo_state(stateid4 *stateid, rfs4_lo_state_t **lspp, bool_t lock_fp) |
|
3232 |
{ |
|
3233 |
stateid_t *id = (stateid_t *)stateid; |
|
3234 |
rfs4_lo_state_t *lsp; |
|
3235 |
||
3236 |
*lspp = NULL; |
|
3237 |
||
3238 |
/* If we are booted as a cluster node, was stateid locally generated? */ |
|
3239 |
if ((cluster_bootflags & CLUSTER_BOOTED) && foreign_stateid(id)) |
|
3240 |
return (NFS4ERR_STALE_STATEID); |
|
3241 |
||
3242 |
lsp = rfs4_findlo_state(id, lock_fp); |
|
3243 |
if (lsp == NULL) { |
|
3244 |
return (what_stateid_error(id, LOCKID)); |
|
3245 |
} |
|
3246 |
||
3247 |
if (rfs4_lease_expired(lsp->state->owner->client)) { |
|
3248 |
rfs4_lo_state_rele(lsp, lock_fp); |
|
3249 |
return (NFS4ERR_EXPIRED); |
|
3250 |
} |
|
3251 |
||
3252 |
*lspp = lsp; |
|
3253 |
||
3254 |
return (NFS4_OK); |
|
3255 |
} |
|
3256 |
||
3257 |
static nfsstat4 |
|
3258 |
rfs4_get_all_state(stateid4 *sid, rfs4_state_t **spp, |
|
3259 |
rfs4_deleg_state_t **dspp, rfs4_lo_state_t **lospp) |
|
3260 |
{ |
|
3261 |
rfs4_state_t *sp = NULL; |
|
3262 |
rfs4_deleg_state_t *dsp = NULL; |
|
3263 |
rfs4_lo_state_t *losp = NULL; |
|
3264 |
stateid_t *id; |
|
3265 |
nfsstat4 status; |
|
3266 |
||
3267 |
*spp = NULL; *dspp = NULL; *lospp = NULL; |
|
3268 |
||
3269 |
id = (stateid_t *)sid; |
|
3270 |
switch (id->bits.type) { |
|
3271 |
case OPENID: |
|
3272 |
status = rfs4_get_state_lockit(sid, &sp, FALSE, FALSE); |
|
3273 |
break; |
|
3274 |
case DELEGID: |
|
3275 |
status = rfs4_get_deleg_state(sid, &dsp); |
|
3276 |
break; |
|
3277 |
case LOCKID: |
|
3278 |
status = rfs4_get_lo_state(sid, &losp, FALSE); |
|
3279 |
if (status == NFS4_OK) { |
|
3280 |
sp = losp->state; |
|
3281 |
rfs4_dbe_hold(sp->dbe); |
|
3282 |
} |
|
3283 |
break; |
|
3284 |
default: |
|
3285 |
status = NFS4ERR_BAD_STATEID; |
|
3286 |
} |
|
3287 |
||
3288 |
if (status == NFS4_OK) { |
|
3289 |
*spp = sp; |
|
3290 |
*dspp = dsp; |
|
3291 |
*lospp = losp; |
|
3292 |
} |
|
3293 |
||
3294 |
return (status); |
|
3295 |
} |
|
3296 |
||
3297 |
/* |
|
3298 |
* Given the I/O mode (FREAD or FWRITE), this checks whether the |
|
3299 |
* rfs4_state_t struct has access to do this operation and if so |
|
3300 |
* return NFS4_OK; otherwise the proper NFSv4 error is returned. |
|
3301 |
*/ |
|
3302 |
nfsstat4 |
|
3303 |
rfs4_state_has_access(rfs4_state_t *sp, int mode, vnode_t *vp) |
|
3304 |
{ |
|
3305 |
nfsstat4 stat = NFS4_OK; |
|
3306 |
rfs4_file_t *fp; |
|
3307 |
bool_t create = FALSE; |
|
3308 |
||
3309 |
rfs4_dbe_lock(sp->dbe); |
|
3310 |
if (mode == FWRITE) { |
|
3311 |
if (!(sp->share_access & OPEN4_SHARE_ACCESS_WRITE)) { |
|
3312 |
stat = NFS4ERR_OPENMODE; |
|
3313 |
} |
|
3314 |
} else if (mode == FREAD) { |
|
3315 |
if (!(sp->share_access & OPEN4_SHARE_ACCESS_READ)) { |
|
3316 |
/* |
|
3317 |
* If we have OPENed the file with DENYing access |
|
3318 |
* to both READ and WRITE then no one else could |
|
3319 |
* have OPENed the file, hence no conflicting READ |
|
3320 |
* deny. This check is merely an optimization. |
|
3321 |
*/ |
|
3322 |
if (sp->share_deny == OPEN4_SHARE_DENY_BOTH) |
|
3323 |
goto out; |
|
3324 |
||
3325 |
/* Check against file struct's DENY mode */ |
|
3326 |
fp = rfs4_findfile(vp, NULL, &create); |
|
3327 |
if (fp != NULL) { |
|
3328 |
int deny_read = 0; |
|
3329 |
rfs4_dbe_lock(fp->dbe); |
|
3330 |
/* |
|
3331 |
* Check if any other open owner has the file |
|
3332 |
* OPENed with deny READ. |
|
3333 |
*/ |
|
3334 |
if (sp->share_deny & OPEN4_SHARE_DENY_READ) |
|
3335 |
deny_read = 1; |
|
3336 |
ASSERT(fp->deny_read - deny_read >= 0); |
|
3337 |
if (fp->deny_read - deny_read > 0) |
|
3338 |
stat = NFS4ERR_OPENMODE; |
|
3339 |
rfs4_dbe_unlock(fp->dbe); |
|
3340 |
rfs4_file_rele(fp); |
|
3341 |
} |
|
3342 |
} |
|
3343 |
} else { |
|
3344 |
/* Illegal I/O mode */ |
|
3345 |
stat = NFS4ERR_INVAL; |
|
3346 |
} |
|
3347 |
out: |
|
3348 |
rfs4_dbe_unlock(sp->dbe); |
|
3349 |
return (stat); |
|
3350 |
} |
|
3351 |
||
3352 |
/* |
|
3353 |
* Given the I/O mode (FREAD or FWRITE), the vnode, the stateid and whether |
|
3354 |
* the file is being truncated, return NFS4_OK if allowed or approriate |
|
3355 |
* V4 error if not. Note NFS4ERR_DELAY will be returned and a recall on |
|
3356 |
* the associated file will be done if the I/O is not consistent with any |
|
3357 |
* delegation in effect on the file. Should be holding VOP_RWLOCK, either |
|
3358 |
* as reader or writer as appropriate. rfs4_op_open will accquire the |
|
3359 |
* VOP_RWLOCK as writer when setting up delegation. If the stateid is bad |
|
3360 |
* this routine will return NFS4ERR_BAD_STATEID. In addition, through the |
|
3361 |
* deleg parameter, we will return whether a write delegation is held by |
|
3362 |
* the client associated with this stateid. |
|
3363 |
* If the server instance associated with the relevant client is in its |
|
3364 |
* grace period, return NFS4ERR_GRACE. |
|
3365 |
*/ |
|
3366 |
||
3367 |
nfsstat4 |
|
3368 |
rfs4_check_stateid(int mode, vnode_t *vp, |
|
3369 |
stateid4 *stateid, bool_t trunc, bool_t *deleg, |
|
3370 |
bool_t do_access) |
|
3371 |
{ |
|
3372 |
rfs4_file_t *fp; |
|
3373 |
bool_t create = FALSE; |
|
3374 |
rfs4_state_t *sp; |
|
3375 |
rfs4_deleg_state_t *dsp; |
|
3376 |
rfs4_lo_state_t *lsp; |
|
3377 |
stateid_t *id = (stateid_t *)stateid; |
|
3378 |
nfsstat4 stat = NFS4_OK; |
|
3379 |
||
3380 |
if (ISSPECIAL(stateid)) { |
|
3381 |
fp = rfs4_findfile(vp, NULL, &create); |
|
3382 |
if (fp == NULL) |
|
3383 |
return (NFS4_OK); |
|
3384 |
if (fp->dinfo->dtype == OPEN_DELEGATE_NONE) { |
|
3385 |
rfs4_file_rele(fp); |
|
3386 |
return (NFS4_OK); |
|
3387 |
} |
|
3388 |
if (mode == FWRITE || |
|
3389 |
fp->dinfo->dtype == OPEN_DELEGATE_WRITE) { |
|
3390 |
rfs4_recall_deleg(fp, trunc, NULL); |
|
3391 |
rfs4_file_rele(fp); |
|
3392 |
return (NFS4ERR_DELAY); |
|
3393 |
} |
|
3394 |
rfs4_file_rele(fp); |
|
3395 |
return (NFS4_OK); |
|
3396 |
} else { |
|
3397 |
stat = rfs4_get_all_state(stateid, &sp, &dsp, &lsp); |
|
3398 |
if (stat != NFS4_OK) |
|
3399 |
return (stat); |
|
3400 |
if (lsp != NULL) { |
|
3401 |
/* Is associated server instance in its grace period? */ |
|
3402 |
if (rfs4_clnt_in_grace(lsp->locker->client)) { |
|
3403 |
rfs4_lo_state_rele(lsp, FALSE); |
|
3404 |
if (sp != NULL) |
|
3405 |
rfs4_state_rele_nounlock(sp); |
|
3406 |
return (NFS4ERR_GRACE); |
|
3407 |
} |
|
3408 |
if (id->bits.type == LOCKID) { |
|
3409 |
/* Seqid in the future? - that's bad */ |
|
3410 |
if (lsp->lockid.bits.chgseq < |
|
3411 |
id->bits.chgseq) { |
|
3412 |
rfs4_lo_state_rele(lsp, FALSE); |
|
3413 |
if (sp != NULL) |
|
3414 |
rfs4_state_rele_nounlock(sp); |
|
3415 |
return (NFS4ERR_BAD_STATEID); |
|
3416 |
} |
|
3417 |
/* Seqid in the past? - that's old */ |
|
3418 |
if (lsp->lockid.bits.chgseq > |
|
3419 |
id->bits.chgseq) { |
|
3420 |
rfs4_lo_state_rele(lsp, FALSE); |
|
3421 |
if (sp != NULL) |
|
3422 |
rfs4_state_rele_nounlock(sp); |
|
3423 |
return (NFS4ERR_OLD_STATEID); |
|
3424 |
} |
|
3425 |
/* Ensure specified filehandle matches */ |
|
3426 |
if (lsp->state->finfo->vp != vp) { |
|
3427 |
rfs4_lo_state_rele(lsp, FALSE); |
|
3428 |
if (sp != NULL) |
|
3429 |
rfs4_state_rele_nounlock(sp); |
|
3430 |
return (NFS4ERR_BAD_STATEID); |
|
3431 |
} |
|
3432 |
} |
|
3433 |
rfs4_lo_state_rele(lsp, FALSE); |
|
3434 |
} |
|
3435 |
||
3436 |
/* Stateid provided was an "open" stateid */ |
|
3437 |
if (sp != NULL) { |
|
3438 |
/* Is associated server instance in its grace period? */ |
|
3439 |
if (rfs4_clnt_in_grace(sp->owner->client)) { |
|
3440 |
rfs4_state_rele_nounlock(sp); |
|
3441 |
return (NFS4ERR_GRACE); |
|
3442 |
} |
|
3443 |
if (id->bits.type == OPENID) { |
|
3444 |
/* Seqid in the future? - that's bad */ |
|
3445 |
if (sp->stateid.bits.chgseq < |
|
3446 |
id->bits.chgseq) { |
|
3447 |
rfs4_state_rele_nounlock(sp); |
|
3448 |
return (NFS4ERR_BAD_STATEID); |
|
3449 |
} |
|
3450 |
/* Seqid in the past - that's old */ |
|
3451 |
if (sp->stateid.bits.chgseq > |
|
3452 |
id->bits.chgseq) { |
|
3453 |
rfs4_state_rele_nounlock(sp); |
|
3454 |
return (NFS4ERR_OLD_STATEID); |
|
3455 |
} |
|
3456 |
} |
|
3457 |
/* Ensure specified filehandle matches */ |
|
3458 |
if (sp->finfo->vp != vp) { |
|
3459 |
rfs4_state_rele_nounlock(sp); |
|
3460 |
return (NFS4ERR_BAD_STATEID); |
|
3461 |
} |
|
3462 |
||
3463 |
if (sp->owner->need_confirm) { |
|
3464 |
rfs4_state_rele_nounlock(sp); |
|
3465 |
return (NFS4ERR_BAD_STATEID); |
|
3466 |
} |
|
3467 |
||
3468 |
if (sp->closed == TRUE) { |
|
3469 |
rfs4_state_rele_nounlock(sp); |
|
3470 |
return (NFS4ERR_OLD_STATEID); |
|
3471 |
} |
|
3472 |
||
3473 |
if (do_access) |
|
3474 |
stat = rfs4_state_has_access(sp, mode, vp); |
|
3475 |
else |
|
3476 |
stat = NFS4_OK; |
|
3477 |
||
3478 |
/* |
|
3479 |
* Return whether this state has write |
|
3480 |
* delegation if desired |
|
3481 |
*/ |
|
3482 |
if (deleg && |
|
3483 |
(sp->finfo->dinfo->dtype == OPEN_DELEGATE_WRITE)) |
|
3484 |
*deleg = TRUE; |
|
3485 |
||
3486 |
/* |
|
3487 |
* We got a valid stateid, so we update the |
|
3488 |
* lease on the client. Ideally we would like |
|
3489 |
* to do this after the calling op succeeds, |
|
3490 |
* but for now this will be good |
|
3491 |
* enough. Callers of this routine are |
|
3492 |
* currently insulated from the state stuff. |
|
3493 |
*/ |
|
3494 |
rfs4_update_lease(sp->owner->client); |
|
3495 |
||
3496 |
/* |
|
3497 |
* If a delegation is present on this file and |
|
3498 |
* this is a WRITE, then update the lastwrite |
|
3499 |
* time to indicate that activity is present. |
|
3500 |
*/ |
|
3501 |
if (sp->finfo->dinfo->dtype == OPEN_DELEGATE_WRITE && |
|
3502 |
mode == FWRITE) { |
|
3503 |
sp->finfo->dinfo->time_lastwrite = |
|
3504 |
gethrestime_sec(); |
|
3505 |
} |
|
3506 |
||
3507 |
rfs4_state_rele_nounlock(sp); |
|
3508 |
||
3509 |
return (stat); |
|
3510 |
} |
|
3511 |
||
3512 |
if (dsp != NULL) { |
|
3513 |
/* Is associated server instance in its grace period? */ |
|
3514 |
if (rfs4_clnt_in_grace(dsp->client)) { |
|
3515 |
rfs4_deleg_state_rele(dsp); |
|
3516 |
return (NFS4ERR_GRACE); |
|
3517 |
} |
|
3518 |
if (dsp->delegid.bits.chgseq != id->bits.chgseq) { |
|
3519 |
rfs4_deleg_state_rele(dsp); |
|
3520 |
return (NFS4ERR_BAD_STATEID); |
|
3521 |
} |
|
3522 |
||
3523 |
/* Ensure specified filehandle matches */ |
|
3524 |
if (dsp->finfo->vp != vp) { |
|
3525 |
rfs4_deleg_state_rele(dsp); |
|
3526 |
return (NFS4ERR_BAD_STATEID); |
|
3527 |
} |
|
3528 |
/* |
|
3529 |
* Return whether this state has write |
|
3530 |
* delegation if desired |
|
3531 |
*/ |
|
3532 |
if (deleg && |
|
3533 |
(dsp->finfo->dinfo->dtype == OPEN_DELEGATE_WRITE)) |
|
3534 |
*deleg = TRUE; |
|
3535 |
||
3536 |
rfs4_update_lease(dsp->client); |
|
3537 |
||
3538 |
/* |
|
3539 |
* If a delegation is present on this file and |
|
3540 |
* this is a WRITE, then update the lastwrite |
|
3541 |
* time to indicate that activity is present. |
|
3542 |
*/ |
|
3543 |
if (dsp->finfo->dinfo->dtype == OPEN_DELEGATE_WRITE && |
|
3544 |
mode == FWRITE) { |
|
3545 |
dsp->finfo->dinfo->time_lastwrite = |
|
3546 |
gethrestime_sec(); |
|
3547 |
} |
|
3548 |
||
3549 |
/* |
|
3550 |
* XXX - what happens if this is a WRITE and the |
|
3551 |
* delegation type of for READ. |
|
3552 |
*/ |
|
3553 |
rfs4_deleg_state_rele(dsp); |
|
3554 |
||
3555 |
return (stat); |
|
3556 |
} |
|
3557 |
/* |
|
3558 |
* If we got this far, something bad happened |
|
3559 |
*/ |
|
3560 |
return (NFS4ERR_BAD_STATEID); |
|
3561 |
} |
|
3562 |
} |
|
3563 |
||
3564 |
||
3565 |
/* |
|
3566 |
* This is a special function in that for the file struct provided the |
|
3567 |
* server wants to remove/close all current state associated with the |
|
3568 |
* file. The prime use of this would be with OP_REMOVE to force the |
|
3569 |
* release of state and particularly of file locks. |
|
3570 |
* |
|
3571 |
* There is an assumption that there is no delegations outstanding on |
|
3572 |
* this file at this point. The caller should have waited for those |
|
3573 |
* to be returned or revoked. |
|
3574 |
*/ |
|
3575 |
void |
|
3576 |
rfs4_close_all_state(rfs4_file_t *fp) |
|
3577 |
{ |
|
3578 |
rfs4_state_t *sp; |
|
3579 |
||
3580 |
rfs4_dbe_lock(fp->dbe); |
|
3581 |
||
3582 |
#ifdef DEBUG |
|
3583 |
/* only applies when server is handing out delegations */ |
|
3584 |
if (rfs4_deleg_policy != SRV_NEVER_DELEGATE) |
|
3585 |
ASSERT(fp->dinfo->hold_grant > 0); |
|
3586 |
#endif |
|
3587 |
||
3588 |
/* No delegations for this file */ |
|
3589 |
ASSERT(fp->delegationlist.next == &fp->delegationlist); |
|
3590 |
||
3591 |
/* Make sure that it can not be found */ |
|
3592 |
rfs4_dbe_invalidate(fp->dbe); |
|
3593 |
||
3594 |
if (fp->vp == NULL) { |
|
3595 |
rfs4_dbe_unlock(fp->dbe); |
|
3596 |
return; |
|
3597 |
} |
|
3598 |
rfs4_dbe_unlock(fp->dbe); |
|
3599 |
||
3600 |
/* |
|
3601 |
* Hold as writer to prevent other server threads from |
|
3602 |
* processing requests related to the file while all state is |
|
3603 |
* being removed. |
|
3604 |
*/ |
|
3605 |
rw_enter(&fp->file_rwlock, RW_WRITER); |
|
3606 |
||
3607 |
/* Remove ALL state from the file */ |
|
3608 |
while (sp = rfs4_findstate_by_file(fp)) { |
|
3609 |
rfs4_state_close(sp, FALSE, FALSE, CRED()); |
|
3610 |
rfs4_state_rele_nounlock(sp); |
|
3611 |
} |
|
3612 |
||
3613 |
/* |
|
3614 |
* This is only safe since there are no further references to |
|
3615 |
* the file. |
|
3616 |
*/ |
|
3617 |
rfs4_dbe_lock(fp->dbe); |
|
3618 |
if (fp->vp) { |
|
3619 |
VN_RELE(fp->vp); |
|
3620 |
fp->vp = NULL; |
|
3621 |
} |
|
3622 |
rfs4_dbe_unlock(fp->dbe); |
|
3623 |
||
3624 |
/* Finally let other references to proceed */ |
|
3625 |
rw_exit(&fp->file_rwlock); |
|
3626 |
} |
|
3627 |
||
3628 |
/* |
|
3629 |
* This function is used as a target for the rfs4_dbe_walk() call |
|
3630 |
* below. The purpose of this function is to see if the |
|
3631 |
* lockowner_state refers to a file that resides within the exportinfo |
|
3632 |
* export. If so, then remove the lock_owner state (file locks and |
|
3633 |
* share "locks") for this object since the intent is the server is |
|
3634 |
* unexporting the specified directory. Be sure to invalidate the |
|
3635 |
* object after the state has been released |
|
3636 |
*/ |
|
3637 |
static void |
|
3638 |
rfs4_lo_state_walk_callout(rfs4_entry_t u_entry, void *e) |
|
3639 |
{ |
|
3640 |
rfs4_lo_state_t *lsp = (rfs4_lo_state_t *)u_entry; |
|
3641 |
struct exportinfo *exi = (struct exportinfo *)e; |
|
3642 |
nfs_fh4_fmt_t *exi_fhp, *finfo_fhp; |
|
3643 |
||
3644 |
exi_fhp = (nfs_fh4_fmt_t *)&exi->exi_fh; |
|
3645 |
finfo_fhp = |
|
3646 |
(nfs_fh4_fmt_t *)lsp->state->finfo->filehandle.nfs_fh4_val; |
|
3647 |
||
3648 |
if (EQFSID(&finfo_fhp->fh4_fsid, &exi_fhp->fh4_fsid) && |
|
3649 |
bcmp(&finfo_fhp->fh4_xdata, &exi_fhp->fh4_xdata, |
|
3650 |
exi_fhp->fh4_xlen) == 0) { |
|
3651 |
rfs4_state_close(lsp->state, FALSE, FALSE, CRED()); |
|
3652 |
rfs4_dbe_invalidate(lsp->dbe); |
|
3653 |
rfs4_dbe_invalidate(lsp->state->dbe); |
|
3654 |
} |
|
3655 |
} |
|
3656 |
||
3657 |
/* |
|
3658 |
* This function is used as a target for the rfs4_dbe_walk() call |
|
3659 |
* below. The purpose of this function is to see if the state refers |
|
3660 |
* to a file that resides within the exportinfo export. If so, then |
|
3661 |
* remove the open state for this object since the intent is the |
|
3662 |
* server is unexporting the specified directory. The main result for |
|
3663 |
* this type of entry is to invalidate it such it will not be found in |
|
3664 |
* the future. |
|
3665 |
*/ |
|
3666 |
static void |
|
3667 |
rfs4_state_walk_callout(rfs4_entry_t u_entry, void *e) |
|
3668 |
{ |
|
3669 |
rfs4_state_t *sp = (rfs4_state_t *)u_entry; |
|
3670 |
struct exportinfo *exi = (struct exportinfo *)e; |
|
3671 |
nfs_fh4_fmt_t *exi_fhp, *finfo_fhp; |
|
3672 |
||
3673 |
exi_fhp = (nfs_fh4_fmt_t *)&exi->exi_fh; |
|
3674 |
finfo_fhp = |
|
3675 |
(nfs_fh4_fmt_t *)sp->finfo->filehandle.nfs_fh4_val; |
|
3676 |
||
3677 |
if (EQFSID(&finfo_fhp->fh4_fsid, &exi_fhp->fh4_fsid) && |
|
3678 |
bcmp(&finfo_fhp->fh4_xdata, &exi_fhp->fh4_xdata, |
|
3679 |
exi_fhp->fh4_xlen) == 0) { |
|
3680 |
rfs4_state_close(sp, TRUE, FALSE, CRED()); |
|
3681 |
rfs4_dbe_invalidate(sp->dbe); |
|
3682 |
} |
|
3683 |
} |
|
3684 |
||
3685 |
/* |
|
3686 |
* This function is used as a target for the rfs4_dbe_walk() call |
|
3687 |
* below. The purpose of this function is to see if the state refers |
|
3688 |
* to a file that resides within the exportinfo export. If so, then |
|
3689 |
* remove the deleg state for this object since the intent is the |
|
3690 |
* server is unexporting the specified directory. The main result for |
|
3691 |
* this type of entry is to invalidate it such it will not be found in |
|
3692 |
* the future. |
|
3693 |
*/ |
|
3694 |
static void |
|
3695 |
rfs4_deleg_state_walk_callout(rfs4_entry_t u_entry, void *e) |
|
3696 |
{ |
|
3697 |
rfs4_deleg_state_t *dsp = (rfs4_deleg_state_t *)u_entry; |
|
3698 |
struct exportinfo *exi = (struct exportinfo *)e; |
|
3699 |
nfs_fh4_fmt_t *exi_fhp, *finfo_fhp; |
|
3700 |
||
3701 |
exi_fhp = (nfs_fh4_fmt_t *)&exi->exi_fh; |
|
3702 |
finfo_fhp = |
|
3703 |
(nfs_fh4_fmt_t *)dsp->finfo->filehandle.nfs_fh4_val; |
|
3704 |
||
3705 |
if (EQFSID(&finfo_fhp->fh4_fsid, &exi_fhp->fh4_fsid) && |
|
3706 |
bcmp(&finfo_fhp->fh4_xdata, &exi_fhp->fh4_xdata, |
|
3707 |
exi_fhp->fh4_xlen) == 0) { |
|
3708 |
rfs4_dbe_invalidate(dsp->dbe); |
|
3709 |
} |
|
3710 |
} |
|
3711 |
||
3712 |
/* |
|
3713 |
* This function is used as a target for the rfs4_dbe_walk() call |
|
3714 |
* below. The purpose of this function is to see if the state refers |
|
3715 |
* to a file that resides within the exportinfo export. If so, then |
|
3716 |
* release vnode hold for this object since the intent is the server |
|
3717 |
* is unexporting the specified directory. Invalidation will prevent |
|
3718 |
* this struct from being found in the future. |
|
3719 |
*/ |
|
3720 |
static void |
|
3721 |
rfs4_file_walk_callout(rfs4_entry_t u_entry, void *e) |
|
3722 |
{ |
|
3723 |
rfs4_file_t *fp = (rfs4_file_t *)u_entry; |
|
3724 |
struct exportinfo *exi = (struct exportinfo *)e; |
|
3725 |
nfs_fh4_fmt_t *exi_fhp, *finfo_fhp; |
|
3726 |
||
3727 |
exi_fhp = (nfs_fh4_fmt_t *)&exi->exi_fh; |
|
3728 |
finfo_fhp = (nfs_fh4_fmt_t *)fp->filehandle.nfs_fh4_val; |
|
3729 |
||
3730 |
if (EQFSID(&finfo_fhp->fh4_fsid, &exi_fhp->fh4_fsid) && |
|
3731 |
bcmp(&finfo_fhp->fh4_xdata, &exi_fhp->fh4_xdata, |
|
3732 |
exi_fhp->fh4_xlen) == 0) { |
|
3733 |
if (fp->vp) { |
|
3734 |
/* don't leak monitors */ |
|
3735 |
if (fp->dinfo->dtype == OPEN_DELEGATE_READ) |
|
3736 |
(void) fem_uninstall(fp->vp, deleg_rdops, |
|
3737 |
(void *)fp); |
|
3738 |
else if (fp->dinfo->dtype == OPEN_DELEGATE_WRITE) |
|
3739 |
(void) fem_uninstall(fp->vp, deleg_wrops, |
|
3740 |
(void *)fp); |
|
3741 |
VN_RELE(fp->vp); |
|
3742 |
fp->vp = NULL; |
|
3743 |
} |
|
3744 |
rfs4_dbe_invalidate(fp->dbe); |
|
3745 |
} |
|
3746 |
} |
|
3747 |
||
3748 |
/* |
|
3749 |
* Given a directory that is being unexported, cleanup/release all |
|
3750 |
* state in the server that refers to objects residing underneath this |
|
3751 |
* particular export. The ordering of the release is important. |
|
3752 |
* Lock_owner, then state and then file. |
|
3753 |
*/ |
|
3754 |
void |
|
3755 |
rfs4_clean_state_exi(struct exportinfo *exi) |
|
3756 |
{ |
|
3757 |
mutex_enter(&rfs4_state_lock); |
|
3758 |
||
3759 |
if (rfs4_server_state == NULL) { |
|
3760 |
mutex_exit(&rfs4_state_lock); |
|
3761 |
return; |
|
3762 |
} |
|
3763 |
||
3764 |
rfs4_dbe_walk(rfs4_lo_state_tab, rfs4_lo_state_walk_callout, exi); |
|
3765 |
rfs4_dbe_walk(rfs4_state_tab, rfs4_state_walk_callout, exi); |
|
3766 |
rfs4_dbe_walk(rfs4_deleg_state_tab, rfs4_deleg_state_walk_callout, exi); |
|
3767 |
rfs4_dbe_walk(rfs4_file_tab, rfs4_file_walk_callout, exi); |
|
3768 |
||
3769 |
mutex_exit(&rfs4_state_lock); |
|
3770 |
} |