Print this page
inet_pton
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/fs/nfs/nfs4_srv_deleg.c
+++ new/usr/src/uts/common/fs/nfs/nfs4_srv_deleg.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 +/*
26 + * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
27 + */
25 28
26 29 #include <sys/systm.h>
27 30 #include <rpc/auth.h>
28 31 #include <rpc/clnt.h>
29 32 #include <nfs/nfs4_kprot.h>
30 33 #include <nfs/nfs4.h>
31 34 #include <nfs/lm.h>
32 35 #include <sys/cmn_err.h>
33 36 #include <sys/disp.h>
34 37 #include <sys/sdt.h>
35 38
36 39 #include <sys/pathname.h>
37 40
38 41 #include <sys/strsubr.h>
39 42 #include <sys/ddi.h>
40 43
41 44 #include <sys/vnode.h>
42 45 #include <sys/sdt.h>
43 46 #include <inet/common.h>
44 47 #include <inet/ip.h>
45 48 #include <inet/ip6.h>
46 49
47 50 #define MAX_READ_DELEGATIONS 5
48 51
49 52 krwlock_t rfs4_deleg_policy_lock;
50 53 srv_deleg_policy_t rfs4_deleg_policy = SRV_NEVER_DELEGATE;
51 54 static int rfs4_deleg_wlp = 5;
52 55 kmutex_t rfs4_deleg_lock;
53 56 static int rfs4_deleg_disabled;
54 57 static int rfs4_max_setup_cb_tries = 5;
55 58
56 59 #ifdef DEBUG
57 60
58 61 static int rfs4_test_cbgetattr_fail = 0;
59 62 int rfs4_cb_null;
60 63 int rfs4_cb_debug;
61 64 int rfs4_deleg_debug;
62 65
63 66 #endif
64 67
65 68 static void rfs4_recall_file(rfs4_file_t *,
66 69 void (*recall)(rfs4_deleg_state_t *, bool_t),
67 70 bool_t, rfs4_client_t *);
68 71 static void rfs4_revoke_file(rfs4_file_t *);
69 72 static void rfs4_cb_chflush(rfs4_cbinfo_t *);
70 73 static CLIENT *rfs4_cb_getch(rfs4_cbinfo_t *);
71 74 static void rfs4_cb_freech(rfs4_cbinfo_t *, CLIENT *, bool_t);
72 75 static rfs4_deleg_state_t *rfs4_deleg_state(rfs4_state_t *,
73 76 open_delegation_type4, int *);
74 77
75 78 /*
76 79 * Convert a universal address to an transport specific
77 80 * address using inet_pton.
78 81 */
79 82 static int
80 83 uaddr2sockaddr(int af, char *ua, void *ap, in_port_t *pp)
81 84 {
82 85 int dots = 0, i, j, len, k;
83 86 unsigned char c;
84 87 in_port_t port = 0;
85 88
86 89 len = strlen(ua);
87 90
88 91 for (i = len-1; i >= 0; i--) {
89 92
90 93 if (ua[i] == '.')
91 94 dots++;
92 95
93 96 if (dots == 2) {
94 97
95 98 ua[i] = '\0';
96 99 /*
97 100 * We use k to remember were to stick '.' back, since
98 101 * ua was kmem_allocateded from the pool len+1.
99 102 */
100 103 k = i;
101 104 if (inet_pton(af, ua, ap) == 1) {
102 105
103 106 c = 0;
104 107
105 108 for (j = i+1; j < len; j++) {
106 109 if (ua[j] == '.') {
107 110 port = c << 8;
108 111 c = 0;
109 112 } else if (ua[j] >= '0' &&
↓ open down ↓ |
75 lines elided |
↑ open up ↑ |
110 113 ua[j] <= '9') {
111 114 c *= 10;
112 115 c += ua[j] - '0';
113 116 } else {
114 117 ua[k] = '.';
115 118 return (EINVAL);
116 119 }
117 120 }
118 121 port += c;
119 122
120 -
121 - /* reset to network order */
122 - if (af == AF_INET) {
123 - *(uint32_t *)ap =
124 - htonl(*(uint32_t *)ap);
125 - *pp = htons(port);
126 - } else {
127 - int ix;
128 - uint16_t *sap;
129 -
130 - for (sap = ap, ix = 0; ix <
131 - sizeof (struct in6_addr) /
132 - sizeof (uint16_t); ix++)
133 - sap[ix] = htons(sap[ix]);
134 -
135 - *pp = htons(port);
136 - }
123 + *pp = htons(port);
137 124
138 125 ua[k] = '.';
139 126 return (0);
140 127 } else {
141 128 ua[k] = '.';
142 129 return (EINVAL);
143 130 }
144 131 }
145 132 }
146 133
147 134 return (EINVAL);
148 135 }
149 136
150 137 /*
151 138 * Update the delegation policy with the
152 139 * value of "new_policy"
153 140 */
154 141 void
155 142 rfs4_set_deleg_policy(srv_deleg_policy_t new_policy)
156 143 {
157 144 rw_enter(&rfs4_deleg_policy_lock, RW_WRITER);
158 145 rfs4_deleg_policy = new_policy;
159 146 rw_exit(&rfs4_deleg_policy_lock);
160 147 }
161 148
162 149 void
163 150 rfs4_hold_deleg_policy(void)
164 151 {
165 152 rw_enter(&rfs4_deleg_policy_lock, RW_READER);
166 153 }
167 154
168 155 void
169 156 rfs4_rele_deleg_policy(void)
170 157 {
171 158 rw_exit(&rfs4_deleg_policy_lock);
172 159 }
173 160
174 161
175 162 /*
176 163 * This free function is to be used when the client struct is being
177 164 * released and nothing at all is needed of the callback info any
178 165 * longer.
179 166 */
180 167 void
181 168 rfs4_cbinfo_free(rfs4_cbinfo_t *cbp)
182 169 {
183 170 char *addr = cbp->cb_callback.cb_location.r_addr;
184 171 char *netid = cbp->cb_callback.cb_location.r_netid;
185 172
186 173 /* Free old address if any */
187 174
188 175 if (addr)
189 176 kmem_free(addr, strlen(addr) + 1);
190 177 if (netid)
191 178 kmem_free(netid, strlen(netid) + 1);
192 179
193 180 addr = cbp->cb_newer.cb_callback.cb_location.r_addr;
194 181 netid = cbp->cb_newer.cb_callback.cb_location.r_netid;
195 182
196 183 if (addr)
197 184 kmem_free(addr, strlen(addr) + 1);
198 185 if (netid)
199 186 kmem_free(netid, strlen(netid) + 1);
200 187
201 188 if (cbp->cb_chc_free) {
202 189 rfs4_cb_chflush(cbp);
203 190 }
204 191 }
205 192
206 193 /*
207 194 * The server uses this to check the callback path supplied by the
208 195 * client. The callback connection is marked "in progress" while this
209 196 * work is going on and then eventually marked either OK or FAILED.
210 197 * This work can be done as part of a separate thread and at the end
211 198 * of this the thread will exit or it may be done such that the caller
212 199 * will continue with other work.
213 200 */
214 201 static void
215 202 rfs4_do_cb_null(rfs4_client_t *cp)
216 203 {
217 204 struct timeval tv;
218 205 CLIENT *ch;
219 206 rfs4_cbstate_t newstate;
220 207 rfs4_cbinfo_t *cbp = &cp->rc_cbinfo;
221 208
222 209 mutex_enter(cbp->cb_lock);
223 210 /* If another thread is doing CB_NULL RPC then return */
224 211 if (cbp->cb_nullcaller == TRUE) {
225 212 mutex_exit(cbp->cb_lock);
226 213 rfs4_client_rele(cp);
227 214 return;
228 215 }
229 216
230 217 /* Mark the cbinfo as having a thread in the NULL callback */
231 218 cbp->cb_nullcaller = TRUE;
232 219
233 220 /*
234 221 * Are there other threads still using the cbinfo client
235 222 * handles? If so, this thread must wait before going and
236 223 * mucking aroiund with the callback information
237 224 */
238 225 while (cbp->cb_refcnt != 0)
239 226 cv_wait(cbp->cb_cv_nullcaller, cbp->cb_lock);
240 227
241 228 /*
242 229 * This thread itself may find that new callback info has
243 230 * arrived and is set up to handle this case and redrive the
244 231 * call to the client's callback server.
245 232 */
246 233 retry:
247 234 if (cbp->cb_newer.cb_new == TRUE &&
248 235 cbp->cb_newer.cb_confirmed == TRUE) {
249 236 char *addr = cbp->cb_callback.cb_location.r_addr;
250 237 char *netid = cbp->cb_callback.cb_location.r_netid;
251 238
252 239 /*
253 240 * Free the old stuff if it exists; may be the first
254 241 * time through this path
255 242 */
256 243 if (addr)
257 244 kmem_free(addr, strlen(addr) + 1);
258 245 if (netid)
259 246 kmem_free(netid, strlen(netid) + 1);
260 247
261 248 /* Move over the addr/netid */
262 249 cbp->cb_callback.cb_location.r_addr =
263 250 cbp->cb_newer.cb_callback.cb_location.r_addr;
264 251 cbp->cb_newer.cb_callback.cb_location.r_addr = NULL;
265 252 cbp->cb_callback.cb_location.r_netid =
266 253 cbp->cb_newer.cb_callback.cb_location.r_netid;
267 254 cbp->cb_newer.cb_callback.cb_location.r_netid = NULL;
268 255
269 256 /* Get the program number */
270 257 cbp->cb_callback.cb_program =
271 258 cbp->cb_newer.cb_callback.cb_program;
272 259 cbp->cb_newer.cb_callback.cb_program = 0;
273 260
274 261 /* Don't forget the protocol's "cb_ident" field */
275 262 cbp->cb_ident = cbp->cb_newer.cb_ident;
276 263 cbp->cb_newer.cb_ident = 0;
277 264
278 265 /* no longer new */
279 266 cbp->cb_newer.cb_new = FALSE;
280 267 cbp->cb_newer.cb_confirmed = FALSE;
281 268
282 269 /* get rid of the old client handles that may exist */
283 270 rfs4_cb_chflush(cbp);
284 271
285 272 cbp->cb_state = CB_NONE;
286 273 cbp->cb_timefailed = 0; /* reset the clock */
287 274 cbp->cb_notified_of_cb_path_down = TRUE;
288 275 }
289 276
290 277 if (cbp->cb_state != CB_NONE) {
291 278 cv_broadcast(cbp->cb_cv); /* let the others know */
292 279 cbp->cb_nullcaller = FALSE;
293 280 mutex_exit(cbp->cb_lock);
294 281 rfs4_client_rele(cp);
295 282 return;
296 283 }
297 284
298 285 /* mark rfs4_client_t as CALLBACK NULL in progress */
299 286 cbp->cb_state = CB_INPROG;
300 287 mutex_exit(cbp->cb_lock);
301 288
302 289 /* get/generate a client handle */
303 290 if ((ch = rfs4_cb_getch(cbp)) == NULL) {
304 291 mutex_enter(cbp->cb_lock);
305 292 cbp->cb_state = CB_BAD;
306 293 cbp->cb_timefailed = gethrestime_sec(); /* observability */
307 294 goto retry;
308 295 }
309 296
310 297
311 298 tv.tv_sec = 30;
312 299 tv.tv_usec = 0;
313 300 if (clnt_call(ch, CB_NULL, xdr_void, NULL, xdr_void, NULL, tv) != 0) {
314 301 newstate = CB_BAD;
315 302 } else {
316 303 newstate = CB_OK;
317 304 #ifdef DEBUG
318 305 rfs4_cb_null++;
319 306 #endif
320 307 }
321 308
322 309 /* Check to see if the client has specified new callback info */
323 310 mutex_enter(cbp->cb_lock);
324 311 rfs4_cb_freech(cbp, ch, TRUE);
325 312 if (cbp->cb_newer.cb_new == TRUE &&
326 313 cbp->cb_newer.cb_confirmed == TRUE) {
327 314 goto retry; /* give the CB_NULL another chance */
328 315 }
329 316
330 317 cbp->cb_state = newstate;
331 318 if (cbp->cb_state == CB_BAD)
332 319 cbp->cb_timefailed = gethrestime_sec(); /* observability */
333 320
334 321 cv_broadcast(cbp->cb_cv); /* start up the other threads */
335 322 cbp->cb_nullcaller = FALSE;
336 323 mutex_exit(cbp->cb_lock);
337 324
338 325 rfs4_client_rele(cp);
339 326 }
340 327
341 328 /*
342 329 * Given a client struct, inspect the callback info to see if the
343 330 * callback path is up and available.
344 331 *
345 332 * If new callback path is available and no one has set it up then
346 333 * try to set it up. If setup is not successful after 5 tries (5 secs)
347 334 * then gives up and returns NULL.
348 335 *
349 336 * If callback path is being initialized, then wait for the CB_NULL RPC
350 337 * call to occur.
351 338 */
352 339 static rfs4_cbinfo_t *
353 340 rfs4_cbinfo_hold(rfs4_client_t *cp)
354 341 {
355 342 rfs4_cbinfo_t *cbp = &cp->rc_cbinfo;
356 343 int retries = 0;
357 344
358 345 mutex_enter(cbp->cb_lock);
359 346
360 347 while (cbp->cb_newer.cb_new == TRUE && cbp->cb_nullcaller == FALSE) {
361 348 /*
362 349 * Looks like a new callback path may be available and
363 350 * noone has set it up.
364 351 */
365 352 mutex_exit(cbp->cb_lock);
366 353 rfs4_dbe_hold(cp->rc_dbe);
367 354 rfs4_do_cb_null(cp); /* caller will release client hold */
368 355
369 356 mutex_enter(cbp->cb_lock);
370 357 /*
371 358 * If callback path is no longer new, or it's being setup
372 359 * then stop and wait for it to be done.
373 360 */
374 361 if (cbp->cb_newer.cb_new == FALSE || cbp->cb_nullcaller == TRUE)
375 362 break;
376 363 mutex_exit(cbp->cb_lock);
377 364
378 365 if (++retries >= rfs4_max_setup_cb_tries)
379 366 return (NULL);
380 367 delay(hz);
381 368 mutex_enter(cbp->cb_lock);
382 369 }
383 370
384 371 /* Is there a thread working on doing the CB_NULL RPC? */
385 372 if (cbp->cb_nullcaller == TRUE)
386 373 cv_wait(cbp->cb_cv, cbp->cb_lock); /* if so, wait on it */
387 374
388 375 /* If the callback path is not okay (up and running), just quit */
389 376 if (cbp->cb_state != CB_OK) {
390 377 mutex_exit(cbp->cb_lock);
391 378 return (NULL);
392 379 }
393 380
394 381 /* Let someone know we are using the current callback info */
395 382 cbp->cb_refcnt++;
396 383 mutex_exit(cbp->cb_lock);
397 384 return (cbp);
398 385 }
399 386
400 387 /*
401 388 * The caller is done with the callback info. It may be that the
402 389 * caller's RPC failed and the NFSv4 client has actually provided new
403 390 * callback information. If so, let the caller know so they can
404 391 * advantage of this and maybe retry the RPC that originally failed.
405 392 */
406 393 static int
407 394 rfs4_cbinfo_rele(rfs4_cbinfo_t *cbp, rfs4_cbstate_t newstate)
408 395 {
409 396 int cb_new = FALSE;
410 397
411 398 mutex_enter(cbp->cb_lock);
412 399
413 400 /* The caller gets a chance to mark the callback info as bad */
414 401 if (newstate != CB_NOCHANGE)
415 402 cbp->cb_state = newstate;
416 403 if (newstate == CB_FAILED) {
417 404 cbp->cb_timefailed = gethrestime_sec(); /* observability */
418 405 cbp->cb_notified_of_cb_path_down = FALSE;
419 406 }
420 407
421 408 cbp->cb_refcnt--; /* no longer using the information */
422 409
423 410 /*
424 411 * A thread may be waiting on this one to finish and if so,
425 412 * let it know that it is okay to do the CB_NULL to the
426 413 * client's callback server.
427 414 */
428 415 if (cbp->cb_refcnt == 0 && cbp->cb_nullcaller)
429 416 cv_broadcast(cbp->cb_cv_nullcaller);
430 417
431 418 /*
432 419 * If this is the last thread to use the callback info and
433 420 * there is new callback information to try and no thread is
434 421 * there ready to do the CB_NULL, then return true to teh
435 422 * caller so they can do the CB_NULL
436 423 */
437 424 if (cbp->cb_refcnt == 0 &&
438 425 cbp->cb_nullcaller == FALSE &&
439 426 cbp->cb_newer.cb_new == TRUE &&
440 427 cbp->cb_newer.cb_confirmed == TRUE)
441 428 cb_new = TRUE;
442 429
443 430 mutex_exit(cbp->cb_lock);
444 431
445 432 return (cb_new);
446 433 }
447 434
448 435 /*
449 436 * Given the information in the callback info struct, create a client
450 437 * handle that can be used by the server for its callback path.
451 438 */
452 439 static CLIENT *
453 440 rfs4_cbch_init(rfs4_cbinfo_t *cbp)
454 441 {
455 442 struct knetconfig knc;
456 443 vnode_t *vp;
457 444 struct sockaddr_in addr4;
458 445 struct sockaddr_in6 addr6;
459 446 void *addr, *taddr;
460 447 in_port_t *pp;
461 448 int af;
462 449 char *devnam;
463 450 struct netbuf nb;
464 451 int size;
465 452 CLIENT *ch = NULL;
466 453 int useresvport = 0;
467 454
468 455 mutex_enter(cbp->cb_lock);
469 456
470 457 if (cbp->cb_callback.cb_location.r_netid == NULL ||
471 458 cbp->cb_callback.cb_location.r_addr == NULL) {
472 459 goto cb_init_out;
473 460 }
474 461
475 462 if (strcmp(cbp->cb_callback.cb_location.r_netid, "tcp") == 0) {
476 463 knc.knc_semantics = NC_TPI_COTS;
477 464 knc.knc_protofmly = "inet";
478 465 knc.knc_proto = "tcp";
479 466 devnam = "/dev/tcp";
480 467 af = AF_INET;
481 468 } else if (strcmp(cbp->cb_callback.cb_location.r_netid, "udp")
482 469 == 0) {
483 470 knc.knc_semantics = NC_TPI_CLTS;
484 471 knc.knc_protofmly = "inet";
485 472 knc.knc_proto = "udp";
486 473 devnam = "/dev/udp";
487 474 af = AF_INET;
488 475 } else if (strcmp(cbp->cb_callback.cb_location.r_netid, "tcp6")
489 476 == 0) {
490 477 knc.knc_semantics = NC_TPI_COTS;
491 478 knc.knc_protofmly = "inet6";
492 479 knc.knc_proto = "tcp";
493 480 devnam = "/dev/tcp6";
494 481 af = AF_INET6;
495 482 } else if (strcmp(cbp->cb_callback.cb_location.r_netid, "udp6")
496 483 == 0) {
497 484 knc.knc_semantics = NC_TPI_CLTS;
498 485 knc.knc_protofmly = "inet6";
499 486 knc.knc_proto = "udp";
500 487 devnam = "/dev/udp6";
501 488 af = AF_INET6;
502 489 } else {
503 490 goto cb_init_out;
504 491 }
505 492
506 493 if (lookupname(devnam, UIO_SYSSPACE, FOLLOW, NULLVPP, &vp) != 0) {
507 494
508 495 goto cb_init_out;
509 496 }
510 497
511 498 if (vp->v_type != VCHR) {
512 499 VN_RELE(vp);
513 500 goto cb_init_out;
514 501 }
515 502
516 503 knc.knc_rdev = vp->v_rdev;
517 504
518 505 VN_RELE(vp);
519 506
520 507 if (af == AF_INET) {
521 508 size = sizeof (addr4);
522 509 bzero(&addr4, size);
523 510 addr4.sin_family = (sa_family_t)af;
524 511 addr = &addr4.sin_addr;
525 512 pp = &addr4.sin_port;
526 513 taddr = &addr4;
527 514 } else /* AF_INET6 */ {
528 515 size = sizeof (addr6);
529 516 bzero(&addr6, size);
530 517 addr6.sin6_family = (sa_family_t)af;
531 518 addr = &addr6.sin6_addr;
532 519 pp = &addr6.sin6_port;
533 520 taddr = &addr6;
534 521 }
535 522
536 523 if (uaddr2sockaddr(af,
537 524 cbp->cb_callback.cb_location.r_addr, addr, pp)) {
538 525
539 526 goto cb_init_out;
540 527 }
541 528
542 529
543 530 nb.maxlen = nb.len = size;
544 531 nb.buf = (char *)taddr;
545 532
546 533 if (clnt_tli_kcreate(&knc, &nb, cbp->cb_callback.cb_program,
547 534 NFS_CB, 0, 0, curthread->t_cred, &ch)) {
548 535
549 536 ch = NULL;
550 537 }
551 538
552 539 /* turn off reserved port usage */
553 540 (void) CLNT_CONTROL(ch, CLSET_BINDRESVPORT, (char *)&useresvport);
554 541
555 542 cb_init_out:
556 543 mutex_exit(cbp->cb_lock);
557 544 return (ch);
558 545 }
559 546
560 547 /*
561 548 * Iterate over the client handle cache and
562 549 * destroy it.
563 550 */
564 551 static void
565 552 rfs4_cb_chflush(rfs4_cbinfo_t *cbp)
566 553 {
567 554 CLIENT *ch;
568 555
569 556 while (cbp->cb_chc_free) {
570 557 cbp->cb_chc_free--;
571 558 ch = cbp->cb_chc[cbp->cb_chc_free];
572 559 cbp->cb_chc[cbp->cb_chc_free] = NULL;
573 560 if (ch) {
574 561 if (ch->cl_auth)
575 562 auth_destroy(ch->cl_auth);
576 563 clnt_destroy(ch);
577 564 }
578 565 }
579 566 }
580 567
581 568 /*
582 569 * Return a client handle, either from a the small
583 570 * rfs4_client_t cache or one that we just created.
584 571 */
585 572 static CLIENT *
586 573 rfs4_cb_getch(rfs4_cbinfo_t *cbp)
587 574 {
588 575 CLIENT *cbch = NULL;
589 576 uint32_t zilch = 0;
590 577
591 578 mutex_enter(cbp->cb_lock);
592 579
593 580 if (cbp->cb_chc_free) {
594 581 cbp->cb_chc_free--;
595 582 cbch = cbp->cb_chc[ cbp->cb_chc_free ];
596 583 mutex_exit(cbp->cb_lock);
597 584 (void) CLNT_CONTROL(cbch, CLSET_XID, (char *)&zilch);
598 585 return (cbch);
599 586 }
600 587
601 588 mutex_exit(cbp->cb_lock);
602 589
603 590 /* none free so make it now */
604 591 cbch = rfs4_cbch_init(cbp);
605 592
606 593 return (cbch);
607 594 }
608 595
609 596 /*
610 597 * Return the client handle to the small cache or
611 598 * destroy it.
612 599 */
613 600 static void
614 601 rfs4_cb_freech(rfs4_cbinfo_t *cbp, CLIENT *ch, bool_t lockheld)
615 602 {
616 603 if (lockheld == FALSE)
617 604 mutex_enter(cbp->cb_lock);
618 605
619 606 if (cbp->cb_chc_free < RFS4_CBCH_MAX) {
620 607 cbp->cb_chc[ cbp->cb_chc_free++ ] = ch;
621 608 if (lockheld == FALSE)
622 609 mutex_exit(cbp->cb_lock);
623 610 return;
624 611 }
625 612 if (lockheld == FALSE)
626 613 mutex_exit(cbp->cb_lock);
627 614
628 615 /*
629 616 * cache maxed out of free entries, obliterate
630 617 * this client handle, destroy it, throw it away.
631 618 */
632 619 if (ch->cl_auth)
633 620 auth_destroy(ch->cl_auth);
634 621 clnt_destroy(ch);
635 622 }
636 623
637 624 /*
638 625 * With the supplied callback information - initialize the client
639 626 * callback data. If there is a callback in progress, save the
640 627 * callback info so that a thread can pick it up in the future.
641 628 */
642 629 void
643 630 rfs4_client_setcb(rfs4_client_t *cp, cb_client4 *cb, uint32_t cb_ident)
644 631 {
645 632 char *addr = NULL;
646 633 char *netid = NULL;
647 634 rfs4_cbinfo_t *cbp = &cp->rc_cbinfo;
648 635 size_t len;
649 636
650 637 /* Set the call back for the client */
651 638 if (cb->cb_location.r_addr && cb->cb_location.r_addr[0] != '\0' &&
652 639 cb->cb_location.r_netid && cb->cb_location.r_netid[0] != '\0') {
653 640 len = strlen(cb->cb_location.r_addr) + 1;
654 641 addr = kmem_alloc(len, KM_SLEEP);
655 642 bcopy(cb->cb_location.r_addr, addr, len);
656 643 len = strlen(cb->cb_location.r_netid) + 1;
657 644 netid = kmem_alloc(len, KM_SLEEP);
658 645 bcopy(cb->cb_location.r_netid, netid, len);
659 646 }
660 647 /* ready to save the new information but first free old, if exists */
661 648 mutex_enter(cbp->cb_lock);
662 649
663 650 cbp->cb_newer.cb_callback.cb_program = cb->cb_program;
664 651
665 652 if (cbp->cb_newer.cb_callback.cb_location.r_addr != NULL)
666 653 kmem_free(cbp->cb_newer.cb_callback.cb_location.r_addr,
667 654 strlen(cbp->cb_newer.cb_callback.cb_location.r_addr) + 1);
668 655 cbp->cb_newer.cb_callback.cb_location.r_addr = addr;
669 656
670 657 if (cbp->cb_newer.cb_callback.cb_location.r_netid != NULL)
671 658 kmem_free(cbp->cb_newer.cb_callback.cb_location.r_netid,
672 659 strlen(cbp->cb_newer.cb_callback.cb_location.r_netid) + 1);
673 660 cbp->cb_newer.cb_callback.cb_location.r_netid = netid;
674 661
675 662 cbp->cb_newer.cb_ident = cb_ident;
676 663
677 664 if (addr && *addr && netid && *netid) {
678 665 cbp->cb_newer.cb_new = TRUE;
679 666 cbp->cb_newer.cb_confirmed = FALSE;
680 667 } else {
681 668 cbp->cb_newer.cb_new = FALSE;
682 669 cbp->cb_newer.cb_confirmed = FALSE;
683 670 }
684 671
685 672 mutex_exit(cbp->cb_lock);
686 673 }
687 674
688 675 /*
689 676 * The server uses this when processing SETCLIENTID_CONFIRM. Callback
690 677 * information may have been provided on SETCLIENTID and this call
691 678 * marks that information as confirmed and then starts a thread to
692 679 * test the callback path.
693 680 */
694 681 void
695 682 rfs4_deleg_cb_check(rfs4_client_t *cp)
696 683 {
697 684 if (cp->rc_cbinfo.cb_newer.cb_new == FALSE)
698 685 return;
699 686
700 687 cp->rc_cbinfo.cb_newer.cb_confirmed = TRUE;
701 688
702 689 rfs4_dbe_hold(cp->rc_dbe); /* hold the client struct for thread */
703 690
704 691 (void) thread_create(NULL, 0, rfs4_do_cb_null, cp, 0, &p0, TS_RUN,
705 692 minclsyspri);
706 693 }
707 694
708 695 static void
709 696 rfs4args_cb_recall_free(nfs_cb_argop4 *argop)
710 697 {
711 698 CB_RECALL4args *rec_argp;
712 699
713 700 rec_argp = &argop->nfs_cb_argop4_u.opcbrecall;
714 701 if (rec_argp->fh.nfs_fh4_val)
715 702 kmem_free(rec_argp->fh.nfs_fh4_val, rec_argp->fh.nfs_fh4_len);
716 703 }
717 704
718 705 /* ARGSUSED */
719 706 static void
720 707 rfs4args_cb_getattr_free(nfs_cb_argop4 *argop)
721 708 {
722 709 CB_GETATTR4args *argp;
723 710
724 711 argp = &argop->nfs_cb_argop4_u.opcbgetattr;
725 712 if (argp->fh.nfs_fh4_val)
726 713 kmem_free(argp->fh.nfs_fh4_val, argp->fh.nfs_fh4_len);
727 714 }
728 715
729 716 static void
730 717 rfs4freeargres(CB_COMPOUND4args *args, CB_COMPOUND4res *resp)
731 718 {
732 719 int i, arglen;
733 720 nfs_cb_argop4 *argop;
734 721
735 722 /*
736 723 * First free any special args alloc'd for specific ops.
737 724 */
738 725 arglen = args->array_len;
739 726 argop = args->array;
740 727 for (i = 0; i < arglen; i++, argop++) {
741 728
742 729 switch (argop->argop) {
743 730 case OP_CB_RECALL:
744 731 rfs4args_cb_recall_free(argop);
745 732 break;
746 733
747 734 case OP_CB_GETATTR:
748 735 rfs4args_cb_getattr_free(argop);
749 736 break;
750 737
751 738 default:
752 739 return;
753 740 }
754 741 }
755 742
756 743 if (args->tag.utf8string_len > 0)
757 744 UTF8STRING_FREE(args->tag)
758 745
759 746 kmem_free(args->array, arglen * sizeof (nfs_cb_argop4));
760 747 if (resp)
761 748 (void) xdr_free(xdr_CB_COMPOUND4res, (caddr_t)resp);
762 749 }
763 750
764 751 /*
765 752 * General callback routine for the server to the client.
766 753 */
767 754 static enum clnt_stat
768 755 rfs4_do_callback(rfs4_client_t *cp, CB_COMPOUND4args *args,
769 756 CB_COMPOUND4res *res, struct timeval timeout)
770 757 {
771 758 rfs4_cbinfo_t *cbp;
772 759 CLIENT *ch;
773 760 /* start with this in case cb_getch() fails */
774 761 enum clnt_stat stat = RPC_FAILED;
775 762
776 763 res->tag.utf8string_val = NULL;
777 764 res->array = NULL;
778 765
779 766 retry:
780 767 cbp = rfs4_cbinfo_hold(cp);
781 768 if (cbp == NULL)
782 769 return (stat);
783 770
784 771 /* get a client handle */
785 772 if ((ch = rfs4_cb_getch(cbp)) != NULL) {
786 773 /*
787 774 * reset the cb_ident since it may have changed in
788 775 * rfs4_cbinfo_hold()
789 776 */
790 777 args->callback_ident = cbp->cb_ident;
791 778
792 779 stat = clnt_call(ch, CB_COMPOUND, xdr_CB_COMPOUND4args_srv,
793 780 (caddr_t)args, xdr_CB_COMPOUND4res,
794 781 (caddr_t)res, timeout);
795 782
796 783 /* free client handle */
797 784 rfs4_cb_freech(cbp, ch, FALSE);
798 785 }
799 786
800 787 /*
801 788 * If the rele says that there may be new callback info then
802 789 * retry this sequence and it may succeed as a result of the
803 790 * new callback path
804 791 */
805 792 if (rfs4_cbinfo_rele(cbp,
806 793 (stat == RPC_SUCCESS ? CB_NOCHANGE : CB_FAILED)) == TRUE)
807 794 goto retry;
808 795
809 796 return (stat);
810 797 }
811 798
812 799 /*
813 800 * Used by the NFSv4 server to get attributes for a file while
814 801 * handling the case where a file has been write delegated. For the
815 802 * time being, VOP_GETATTR() is called and CB_GETATTR processing is
816 803 * not undertaken. This call site is maintained in case the server is
817 804 * updated in the future to handle write delegation space guarantees.
818 805 */
819 806 nfsstat4
820 807 rfs4_vop_getattr(vnode_t *vp, vattr_t *vap, int flag, cred_t *cr)
821 808 {
822 809
823 810 int error;
824 811
825 812 error = VOP_GETATTR(vp, vap, flag, cr, NULL);
826 813 return (puterrno4(error));
827 814 }
828 815
829 816 /*
830 817 * This is used everywhere in the v2/v3 server to allow the
831 818 * integration of all NFS versions and the support of delegation. For
832 819 * now, just call the VOP_GETATTR(). If the NFSv4 server is enhanced
833 820 * in the future to provide space guarantees for write delegations
834 821 * then this call site should be expanded to interact with the client.
835 822 */
836 823 int
837 824 rfs4_delegated_getattr(vnode_t *vp, vattr_t *vap, int flag, cred_t *cr)
838 825 {
839 826 return (VOP_GETATTR(vp, vap, flag, cr, NULL));
840 827 }
841 828
842 829 /*
843 830 * Place the actual cb_recall otw call to client.
844 831 */
845 832 static void
846 833 rfs4_do_cb_recall(rfs4_deleg_state_t *dsp, bool_t trunc)
847 834 {
848 835 CB_COMPOUND4args cb4_args;
849 836 CB_COMPOUND4res cb4_res;
850 837 CB_RECALL4args *rec_argp;
851 838 CB_RECALL4res *rec_resp;
852 839 nfs_cb_argop4 *argop;
853 840 int numops;
854 841 int argoplist_size;
855 842 struct timeval timeout;
856 843 nfs_fh4 *fhp;
857 844 enum clnt_stat call_stat;
858 845
859 846 /*
860 847 * set up the compound args
861 848 */
862 849 numops = 1; /* CB_RECALL only */
863 850
864 851 argoplist_size = numops * sizeof (nfs_cb_argop4);
865 852 argop = kmem_zalloc(argoplist_size, KM_SLEEP);
866 853 argop->argop = OP_CB_RECALL;
867 854 rec_argp = &argop->nfs_cb_argop4_u.opcbrecall;
868 855
869 856 (void) str_to_utf8("cb_recall", &cb4_args.tag);
870 857 cb4_args.minorversion = CB4_MINORVERSION;
871 858 /* cb4_args.callback_ident is set in rfs4_do_callback() */
872 859 cb4_args.array_len = numops;
873 860 cb4_args.array = argop;
874 861
875 862 /*
876 863 * fill in the args struct
877 864 */
878 865 bcopy(&dsp->rds_delegid.stateid, &rec_argp->stateid, sizeof (stateid4));
879 866 rec_argp->truncate = trunc;
880 867
881 868 fhp = &dsp->rds_finfo->rf_filehandle;
882 869 rec_argp->fh.nfs_fh4_val = kmem_alloc(sizeof (char) *
883 870 fhp->nfs_fh4_len, KM_SLEEP);
884 871 nfs_fh4_copy(fhp, &rec_argp->fh);
885 872
886 873 /* Keep track of when we did this for observability */
887 874 dsp->rds_time_recalled = gethrestime_sec();
888 875
889 876 /*
890 877 * Set up the timeout for the callback and make the actual call.
891 878 * Timeout will be 80% of the lease period for this server.
892 879 */
893 880 timeout.tv_sec = (rfs4_lease_time * 80) / 100;
894 881 timeout.tv_usec = 0;
895 882
896 883 DTRACE_NFSV4_3(cb__recall__start, rfs4_client_t *, dsp->rds_client,
897 884 rfs4_deleg_state_t *, dsp, CB_RECALL4args *, rec_argp);
898 885
899 886 call_stat = rfs4_do_callback(dsp->rds_client, &cb4_args, &cb4_res,
900 887 timeout);
901 888
902 889 rec_resp = (cb4_res.array_len == 0) ? NULL :
903 890 &cb4_res.array[0].nfs_cb_resop4_u.opcbrecall;
904 891
905 892 DTRACE_NFSV4_3(cb__recall__done, rfs4_client_t *, dsp->rds_client,
906 893 rfs4_deleg_state_t *, dsp, CB_RECALL4res *, rec_resp);
907 894
908 895 if (call_stat != RPC_SUCCESS || cb4_res.status != NFS4_OK) {
909 896 rfs4_return_deleg(dsp, TRUE);
910 897 }
911 898
912 899 rfs4freeargres(&cb4_args, &cb4_res);
913 900 }
914 901
915 902 struct recall_arg {
916 903 rfs4_deleg_state_t *dsp;
917 904 void (*recall)(rfs4_deleg_state_t *, bool_t trunc);
918 905 bool_t trunc;
919 906 };
920 907
921 908 static void
922 909 do_recall(struct recall_arg *arg)
923 910 {
924 911 rfs4_deleg_state_t *dsp = arg->dsp;
925 912 rfs4_file_t *fp = dsp->rds_finfo;
926 913 callb_cpr_t cpr_info;
927 914 kmutex_t cpr_lock;
928 915
929 916 mutex_init(&cpr_lock, NULL, MUTEX_DEFAULT, NULL);
930 917 CALLB_CPR_INIT(&cpr_info, &cpr_lock, callb_generic_cpr, "nfsv4Recall");
931 918
932 919 /*
933 920 * It is possible that before this thread starts
934 921 * the client has send us a return_delegation, and
935 922 * if that is the case we do not need to send the
936 923 * recall callback.
937 924 */
938 925 if (dsp->rds_dtype != OPEN_DELEGATE_NONE) {
939 926 DTRACE_PROBE3(nfss__i__recall,
940 927 struct recall_arg *, arg,
941 928 struct rfs4_deleg_state_t *, dsp,
942 929 struct rfs4_file_t *, fp);
943 930
944 931 if (arg->recall)
945 932 (void) (*arg->recall)(dsp, arg->trunc);
946 933 }
947 934
948 935 mutex_enter(fp->rf_dinfo.rd_recall_lock);
949 936 /*
950 937 * Recall count may go negative if the parent thread that is
951 938 * creating the individual callback threads does not modify
952 939 * the recall_count field before the callback thread actually
953 940 * gets a response from the CB_RECALL
954 941 */
955 942 fp->rf_dinfo.rd_recall_count--;
956 943 if (fp->rf_dinfo.rd_recall_count == 0)
957 944 cv_signal(fp->rf_dinfo.rd_recall_cv);
958 945 mutex_exit(fp->rf_dinfo.rd_recall_lock);
959 946
960 947 mutex_enter(&cpr_lock);
961 948 CALLB_CPR_EXIT(&cpr_info);
962 949 mutex_destroy(&cpr_lock);
963 950
964 951 rfs4_deleg_state_rele(dsp); /* release the hold for this thread */
965 952
966 953 kmem_free(arg, sizeof (struct recall_arg));
967 954 }
968 955
969 956 struct master_recall_args {
970 957 rfs4_file_t *fp;
971 958 void (*recall)(rfs4_deleg_state_t *, bool_t);
972 959 bool_t trunc;
973 960 };
974 961
975 962 static void
976 963 do_recall_file(struct master_recall_args *map)
977 964 {
978 965 rfs4_file_t *fp = map->fp;
979 966 rfs4_deleg_state_t *dsp;
980 967 struct recall_arg *arg;
981 968 callb_cpr_t cpr_info;
982 969 kmutex_t cpr_lock;
983 970 int32_t recall_count;
984 971
985 972 rfs4_dbe_lock(fp->rf_dbe);
986 973
987 974 /* Recall already in progress ? */
988 975 mutex_enter(fp->rf_dinfo.rd_recall_lock);
989 976 if (fp->rf_dinfo.rd_recall_count != 0) {
990 977 mutex_exit(fp->rf_dinfo.rd_recall_lock);
991 978 rfs4_dbe_rele_nolock(fp->rf_dbe);
992 979 rfs4_dbe_unlock(fp->rf_dbe);
993 980 kmem_free(map, sizeof (struct master_recall_args));
994 981 return;
995 982 }
996 983
997 984 mutex_exit(fp->rf_dinfo.rd_recall_lock);
998 985
999 986 mutex_init(&cpr_lock, NULL, MUTEX_DEFAULT, NULL);
1000 987 CALLB_CPR_INIT(&cpr_info, &cpr_lock, callb_generic_cpr, "v4RecallFile");
1001 988
1002 989 recall_count = 0;
1003 990 for (dsp = list_head(&fp->rf_delegstatelist); dsp != NULL;
1004 991 dsp = list_next(&fp->rf_delegstatelist, dsp)) {
1005 992
1006 993 rfs4_dbe_lock(dsp->rds_dbe);
1007 994 /*
1008 995 * if this delegation state
1009 996 * is being reaped skip it
1010 997 */
1011 998 if (rfs4_dbe_is_invalid(dsp->rds_dbe)) {
1012 999 rfs4_dbe_unlock(dsp->rds_dbe);
1013 1000 continue;
1014 1001 }
1015 1002
1016 1003 /* hold for receiving thread */
1017 1004 rfs4_dbe_hold(dsp->rds_dbe);
1018 1005 rfs4_dbe_unlock(dsp->rds_dbe);
1019 1006
1020 1007 arg = kmem_alloc(sizeof (struct recall_arg), KM_SLEEP);
1021 1008 arg->recall = map->recall;
1022 1009 arg->trunc = map->trunc;
1023 1010 arg->dsp = dsp;
1024 1011
1025 1012 recall_count++;
1026 1013
1027 1014 (void) thread_create(NULL, 0, do_recall, arg, 0, &p0, TS_RUN,
1028 1015 minclsyspri);
1029 1016 }
1030 1017
1031 1018 rfs4_dbe_unlock(fp->rf_dbe);
1032 1019
1033 1020 mutex_enter(fp->rf_dinfo.rd_recall_lock);
1034 1021 /*
1035 1022 * Recall count may go negative if the parent thread that is
1036 1023 * creating the individual callback threads does not modify
1037 1024 * the recall_count field before the callback thread actually
1038 1025 * gets a response from the CB_RECALL
1039 1026 */
1040 1027 fp->rf_dinfo.rd_recall_count += recall_count;
1041 1028 while (fp->rf_dinfo.rd_recall_count)
1042 1029 cv_wait(fp->rf_dinfo.rd_recall_cv, fp->rf_dinfo.rd_recall_lock);
1043 1030
1044 1031 mutex_exit(fp->rf_dinfo.rd_recall_lock);
1045 1032
1046 1033 DTRACE_PROBE1(nfss__i__recall_done, rfs4_file_t *, fp);
1047 1034 rfs4_file_rele(fp);
1048 1035 kmem_free(map, sizeof (struct master_recall_args));
1049 1036 mutex_enter(&cpr_lock);
1050 1037 CALLB_CPR_EXIT(&cpr_info);
1051 1038 mutex_destroy(&cpr_lock);
1052 1039 }
1053 1040
1054 1041 static void
1055 1042 rfs4_recall_file(rfs4_file_t *fp,
1056 1043 void (*recall)(rfs4_deleg_state_t *, bool_t trunc),
1057 1044 bool_t trunc, rfs4_client_t *cp)
1058 1045 {
1059 1046 struct master_recall_args *args;
1060 1047
1061 1048 rfs4_dbe_lock(fp->rf_dbe);
1062 1049 if (fp->rf_dinfo.rd_dtype == OPEN_DELEGATE_NONE) {
1063 1050 rfs4_dbe_unlock(fp->rf_dbe);
1064 1051 return;
1065 1052 }
1066 1053 rfs4_dbe_hold(fp->rf_dbe); /* hold for new thread */
1067 1054
1068 1055 /*
1069 1056 * Mark the time we started the recall processing.
1070 1057 * If it has been previously recalled, do not reset the
1071 1058 * timer since this is used for the revocation decision.
1072 1059 */
1073 1060 if (fp->rf_dinfo.rd_time_recalled == 0)
1074 1061 fp->rf_dinfo.rd_time_recalled = gethrestime_sec();
1075 1062 fp->rf_dinfo.rd_ever_recalled = TRUE; /* used for policy decision */
1076 1063 /* Client causing recall not always available */
1077 1064 if (cp)
1078 1065 fp->rf_dinfo.rd_conflicted_client = cp->rc_clientid;
1079 1066
1080 1067 rfs4_dbe_unlock(fp->rf_dbe);
1081 1068
1082 1069 args = kmem_alloc(sizeof (struct master_recall_args), KM_SLEEP);
1083 1070 args->fp = fp;
1084 1071 args->recall = recall;
1085 1072 args->trunc = trunc;
1086 1073
1087 1074 (void) thread_create(NULL, 0, do_recall_file, args, 0, &p0, TS_RUN,
1088 1075 minclsyspri);
1089 1076 }
1090 1077
1091 1078 void
1092 1079 rfs4_recall_deleg(rfs4_file_t *fp, bool_t trunc, rfs4_client_t *cp)
1093 1080 {
1094 1081 time_t elapsed1, elapsed2;
1095 1082
1096 1083 if (fp->rf_dinfo.rd_time_recalled != 0) {
1097 1084 elapsed1 = gethrestime_sec() - fp->rf_dinfo.rd_time_recalled;
1098 1085 elapsed2 = gethrestime_sec() - fp->rf_dinfo.rd_time_lastwrite;
1099 1086 /* First check to see if a revocation should occur */
1100 1087 if (elapsed1 > rfs4_lease_time &&
1101 1088 elapsed2 > rfs4_lease_time) {
1102 1089 rfs4_revoke_file(fp);
1103 1090 return;
1104 1091 }
1105 1092 /*
1106 1093 * Next check to see if a recall should be done again
1107 1094 * so quickly.
1108 1095 */
1109 1096 if (elapsed1 <= ((rfs4_lease_time * 20) / 100))
1110 1097 return;
1111 1098 }
1112 1099 rfs4_recall_file(fp, rfs4_do_cb_recall, trunc, cp);
1113 1100 }
1114 1101
1115 1102 /*
1116 1103 * rfs4_check_recall is called from rfs4_do_open to determine if the current
1117 1104 * open conflicts with the delegation.
1118 1105 * Return true if we need recall otherwise false.
1119 1106 * Assumes entry locks for sp and sp->rs_finfo are held.
1120 1107 */
1121 1108 bool_t
1122 1109 rfs4_check_recall(rfs4_state_t *sp, uint32_t access)
1123 1110 {
1124 1111 open_delegation_type4 dtype = sp->rs_finfo->rf_dinfo.rd_dtype;
1125 1112
1126 1113 switch (dtype) {
1127 1114 case OPEN_DELEGATE_NONE:
1128 1115 /* Not currently delegated so there is nothing to do */
1129 1116 return (FALSE);
1130 1117 case OPEN_DELEGATE_READ:
1131 1118 /*
1132 1119 * If the access is only asking for READ then there is
1133 1120 * no conflict and nothing to do. If it is asking
1134 1121 * for write, then there will be conflict and the read
1135 1122 * delegation should be recalled.
1136 1123 */
1137 1124 if (access == OPEN4_SHARE_ACCESS_READ)
1138 1125 return (FALSE);
1139 1126 else
1140 1127 return (TRUE);
1141 1128 case OPEN_DELEGATE_WRITE:
1142 1129 /* Check to see if this client has the delegation */
1143 1130 return (rfs4_is_deleg(sp));
1144 1131 }
1145 1132
1146 1133 return (FALSE);
1147 1134 }
1148 1135
1149 1136 /*
1150 1137 * Return the "best" allowable delegation available given the current
1151 1138 * delegation type and the desired access and deny modes on the file.
1152 1139 * At the point that this routine is called we know that the access and
1153 1140 * deny modes are consistent with the file modes.
1154 1141 */
1155 1142 static open_delegation_type4
1156 1143 rfs4_check_delegation(rfs4_state_t *sp, rfs4_file_t *fp)
1157 1144 {
1158 1145 open_delegation_type4 dtype = fp->rf_dinfo.rd_dtype;
1159 1146 uint32_t access = sp->rs_share_access;
1160 1147 uint32_t deny = sp->rs_share_deny;
1161 1148 int readcnt = 0;
1162 1149 int writecnt = 0;
1163 1150
1164 1151 switch (dtype) {
1165 1152 case OPEN_DELEGATE_NONE:
1166 1153 /*
1167 1154 * Determine if more than just this OPEN have the file
1168 1155 * open and if so, no delegation may be provided to
1169 1156 * the client.
1170 1157 */
1171 1158 if (access & OPEN4_SHARE_ACCESS_WRITE)
1172 1159 writecnt++;
1173 1160 if (access & OPEN4_SHARE_ACCESS_READ)
1174 1161 readcnt++;
1175 1162
1176 1163 if (fp->rf_access_read > readcnt ||
1177 1164 fp->rf_access_write > writecnt)
1178 1165 return (OPEN_DELEGATE_NONE);
1179 1166
1180 1167 /*
1181 1168 * If the client is going to write, or if the client
1182 1169 * has exclusive access, return a write delegation.
1183 1170 */
1184 1171 if ((access & OPEN4_SHARE_ACCESS_WRITE) ||
1185 1172 (deny & (OPEN4_SHARE_DENY_READ | OPEN4_SHARE_DENY_WRITE)))
1186 1173 return (OPEN_DELEGATE_WRITE);
1187 1174 /*
1188 1175 * If we don't want to write or we've haven't denied read
1189 1176 * access to others, return a read delegation.
1190 1177 */
1191 1178 if ((access & ~OPEN4_SHARE_ACCESS_WRITE) ||
1192 1179 (deny & ~OPEN4_SHARE_DENY_READ))
1193 1180 return (OPEN_DELEGATE_READ);
1194 1181
1195 1182 /* Shouldn't get here */
1196 1183 return (OPEN_DELEGATE_NONE);
1197 1184
1198 1185 case OPEN_DELEGATE_READ:
1199 1186 /*
1200 1187 * If the file is delegated for read but we wan't to
1201 1188 * write or deny others to read then we can't delegate
1202 1189 * the file. We shouldn't get here since the delegation should
1203 1190 * have been recalled already.
1204 1191 */
1205 1192 if ((access & OPEN4_SHARE_ACCESS_WRITE) ||
1206 1193 (deny & OPEN4_SHARE_DENY_READ))
1207 1194 return (OPEN_DELEGATE_NONE);
1208 1195 return (OPEN_DELEGATE_READ);
1209 1196
1210 1197 case OPEN_DELEGATE_WRITE:
1211 1198 return (OPEN_DELEGATE_WRITE);
1212 1199 }
1213 1200
1214 1201 /* Shouldn't get here */
1215 1202 return (OPEN_DELEGATE_NONE);
1216 1203 }
1217 1204
1218 1205 /*
1219 1206 * Given the desired delegation type and the "history" of the file
1220 1207 * determine the actual delegation type to return.
1221 1208 */
1222 1209 static open_delegation_type4
1223 1210 rfs4_delegation_policy(open_delegation_type4 dtype,
1224 1211 rfs4_dinfo_t *dinfo, clientid4 cid)
1225 1212 {
1226 1213 time_t elapsed;
1227 1214
1228 1215 if (rfs4_deleg_policy != SRV_NORMAL_DELEGATE)
1229 1216 return (OPEN_DELEGATE_NONE);
1230 1217
1231 1218 /*
1232 1219 * Has this file/delegation ever been recalled? If not then
1233 1220 * no further checks for a delegation race need to be done.
1234 1221 * However if a recall has occurred, then check to see if a
1235 1222 * client has caused its own delegation recall to occur. If
1236 1223 * not, then has a delegation for this file been returned
1237 1224 * recently? If so, then do not assign a new delegation to
1238 1225 * avoid a "delegation race" between the original client and
1239 1226 * the new/conflicting client.
1240 1227 */
1241 1228 if (dinfo->rd_ever_recalled == TRUE) {
1242 1229 if (dinfo->rd_conflicted_client != cid) {
1243 1230 elapsed = gethrestime_sec() - dinfo->rd_time_returned;
1244 1231 if (elapsed < rfs4_lease_time)
1245 1232 return (OPEN_DELEGATE_NONE);
1246 1233 }
1247 1234 }
1248 1235
1249 1236 /* Limit the number of read grants */
1250 1237 if (dtype == OPEN_DELEGATE_READ &&
1251 1238 dinfo->rd_rdgrants > MAX_READ_DELEGATIONS)
1252 1239 return (OPEN_DELEGATE_NONE);
1253 1240
1254 1241 /*
1255 1242 * Should consider limiting total number of read/write
1256 1243 * delegations the server will permit.
1257 1244 */
1258 1245
1259 1246 return (dtype);
1260 1247 }
1261 1248
1262 1249 /*
1263 1250 * Try and grant a delegation for an open give the state. The routine
1264 1251 * returns the delegation type granted. This could be OPEN_DELEGATE_NONE.
1265 1252 *
1266 1253 * The state and associate file entry must be locked
1267 1254 */
1268 1255 rfs4_deleg_state_t *
1269 1256 rfs4_grant_delegation(delegreq_t dreq, rfs4_state_t *sp, int *recall)
1270 1257 {
1271 1258 rfs4_file_t *fp = sp->rs_finfo;
1272 1259 open_delegation_type4 dtype;
1273 1260 int no_delegation;
1274 1261
1275 1262 ASSERT(rfs4_dbe_islocked(sp->rs_dbe));
1276 1263 ASSERT(rfs4_dbe_islocked(fp->rf_dbe));
1277 1264
1278 1265 /* Is the server even providing delegations? */
1279 1266 if (rfs4_deleg_policy == SRV_NEVER_DELEGATE || dreq == DELEG_NONE)
1280 1267 return (NULL);
1281 1268
1282 1269 /* Check to see if delegations have been temporarily disabled */
1283 1270 mutex_enter(&rfs4_deleg_lock);
1284 1271 no_delegation = rfs4_deleg_disabled;
1285 1272 mutex_exit(&rfs4_deleg_lock);
1286 1273
1287 1274 if (no_delegation)
1288 1275 return (NULL);
1289 1276
1290 1277 /* Don't grant a delegation if a deletion is impending. */
1291 1278 if (fp->rf_dinfo.rd_hold_grant > 0) {
1292 1279 return (NULL);
1293 1280 }
1294 1281
1295 1282 /*
1296 1283 * Don't grant a delegation if there are any lock manager
1297 1284 * (NFSv2/v3) locks for the file. This is a bit of a hack (e.g.,
1298 1285 * if there are only read locks we should be able to grant a
1299 1286 * read-only delegation), but it's good enough for now.
1300 1287 *
1301 1288 * MT safety: the lock manager checks for conflicting delegations
1302 1289 * before processing a lock request. That check will block until
1303 1290 * we are done here. So if the lock manager acquires a lock after
1304 1291 * we decide to grant the delegation, the delegation will get
1305 1292 * immediately recalled (if there's a conflict), so we're safe.
1306 1293 */
1307 1294 if (lm_vp_active(fp->rf_vp)) {
1308 1295 return (NULL);
1309 1296 }
1310 1297
1311 1298 /*
1312 1299 * Based on the type of delegation request passed in, take the
1313 1300 * appropriate action (DELEG_NONE is handled above)
1314 1301 */
1315 1302 switch (dreq) {
1316 1303
1317 1304 case DELEG_READ:
1318 1305 case DELEG_WRITE:
1319 1306 /*
1320 1307 * The server "must" grant the delegation in this case.
1321 1308 * Client is using open previous
1322 1309 */
1323 1310 dtype = (open_delegation_type4)dreq;
1324 1311 *recall = 1;
1325 1312 break;
1326 1313 case DELEG_ANY:
1327 1314 /*
1328 1315 * If a valid callback path does not exist, no delegation may
1329 1316 * be granted.
1330 1317 */
1331 1318 if (sp->rs_owner->ro_client->rc_cbinfo.cb_state != CB_OK)
1332 1319 return (NULL);
1333 1320
1334 1321 /*
1335 1322 * If the original operation which caused time_rm_delayed
1336 1323 * to be set hasn't been retried and completed for one
1337 1324 * full lease period, clear it and allow delegations to
1338 1325 * get granted again.
1339 1326 */
1340 1327 if (fp->rf_dinfo.rd_time_rm_delayed > 0 &&
1341 1328 gethrestime_sec() >
1342 1329 fp->rf_dinfo.rd_time_rm_delayed + rfs4_lease_time)
1343 1330 fp->rf_dinfo.rd_time_rm_delayed = 0;
1344 1331
1345 1332 /*
1346 1333 * If we are waiting for a delegation to be returned then
1347 1334 * don't delegate this file. We do this for correctness as
1348 1335 * well as if the file is being recalled we would likely
1349 1336 * recall this file again.
1350 1337 */
1351 1338
1352 1339 if (fp->rf_dinfo.rd_time_recalled != 0 ||
1353 1340 fp->rf_dinfo.rd_time_rm_delayed != 0)
1354 1341 return (NULL);
1355 1342
1356 1343 /* Get the "best" delegation candidate */
1357 1344 dtype = rfs4_check_delegation(sp, fp);
1358 1345
1359 1346 if (dtype == OPEN_DELEGATE_NONE)
1360 1347 return (NULL);
1361 1348
1362 1349 /*
1363 1350 * Based on policy and the history of the file get the
1364 1351 * actual delegation.
1365 1352 */
1366 1353 dtype = rfs4_delegation_policy(dtype, &fp->rf_dinfo,
1367 1354 sp->rs_owner->ro_client->rc_clientid);
1368 1355
1369 1356 if (dtype == OPEN_DELEGATE_NONE)
1370 1357 return (NULL);
1371 1358 break;
1372 1359 default:
1373 1360 return (NULL);
1374 1361 }
1375 1362
1376 1363 /* set the delegation for the state */
1377 1364 return (rfs4_deleg_state(sp, dtype, recall));
1378 1365 }
1379 1366
1380 1367 void
1381 1368 rfs4_set_deleg_response(rfs4_deleg_state_t *dsp, open_delegation4 *dp,
1382 1369 nfsace4 *ace, int recall)
1383 1370 {
1384 1371 open_write_delegation4 *wp;
1385 1372 open_read_delegation4 *rp;
1386 1373 nfs_space_limit4 *spl;
1387 1374 nfsace4 nace;
1388 1375
1389 1376 /*
1390 1377 * We need to allocate a new copy of the who string.
1391 1378 * this string will be freed by the rfs4_op_open dis_resfree
1392 1379 * routine. We need to do this allocation since replays will
1393 1380 * be allocated and rfs4_compound can't tell the difference from
1394 1381 * a replay and an inital open. N.B. if an ace is passed in, it
1395 1382 * the caller's responsibility to free it.
1396 1383 */
1397 1384
1398 1385 if (ace == NULL) {
1399 1386 /*
1400 1387 * Default is to deny all access, the client will have
1401 1388 * to contact the server. XXX Do we want to actually
1402 1389 * set a deny for every one, or do we simply want to
1403 1390 * construct an entity that will match no one?
1404 1391 */
1405 1392 nace.type = ACE4_ACCESS_DENIED_ACE_TYPE;
1406 1393 nace.flag = 0;
1407 1394 nace.access_mask = ACE4_VALID_MASK_BITS;
1408 1395 (void) str_to_utf8(ACE4_WHO_EVERYONE, &nace.who);
1409 1396 } else {
1410 1397 nace.type = ace->type;
1411 1398 nace.flag = ace->flag;
1412 1399 nace.access_mask = ace->access_mask;
1413 1400 (void) utf8_copy(&ace->who, &nace.who);
1414 1401 }
1415 1402
1416 1403 dp->delegation_type = dsp->rds_dtype;
1417 1404
1418 1405 switch (dsp->rds_dtype) {
1419 1406 case OPEN_DELEGATE_NONE:
1420 1407 break;
1421 1408 case OPEN_DELEGATE_READ:
1422 1409 rp = &dp->open_delegation4_u.read;
1423 1410 rp->stateid = dsp->rds_delegid.stateid;
1424 1411 rp->recall = (bool_t)recall;
1425 1412 rp->permissions = nace;
1426 1413 break;
1427 1414 case OPEN_DELEGATE_WRITE:
1428 1415 wp = &dp->open_delegation4_u.write;
1429 1416 wp->stateid = dsp->rds_delegid.stateid;
1430 1417 wp->recall = (bool_t)recall;
1431 1418 spl = &wp->space_limit;
1432 1419 spl->limitby = NFS_LIMIT_SIZE;
1433 1420 spl->nfs_space_limit4_u.filesize = 0;
1434 1421 wp->permissions = nace;
1435 1422 break;
1436 1423 }
1437 1424 }
1438 1425
1439 1426 /*
1440 1427 * Check if the file is delegated via the provided file struct.
1441 1428 * Return TRUE if it is delegated. This is intended for use by
1442 1429 * the v4 server. The v2/v3 server code should use rfs4_check_delegated().
1443 1430 *
1444 1431 * Note that if the file is found to have a delegation, it is
1445 1432 * recalled, unless the clientid of the caller matches the clientid of the
1446 1433 * delegation. If the caller has specified, there is a slight delay
1447 1434 * inserted in the hopes that the delegation will be returned quickly.
1448 1435 */
1449 1436 bool_t
1450 1437 rfs4_check_delegated_byfp(int mode, rfs4_file_t *fp,
1451 1438 bool_t trunc, bool_t do_delay, bool_t is_rm, clientid4 *cp)
1452 1439 {
1453 1440 rfs4_deleg_state_t *dsp;
1454 1441
1455 1442 /* Is delegation enabled? */
1456 1443 if (rfs4_deleg_policy == SRV_NEVER_DELEGATE)
1457 1444 return (FALSE);
1458 1445
1459 1446 /* do we have a delegation on this file? */
1460 1447 rfs4_dbe_lock(fp->rf_dbe);
1461 1448 if (fp->rf_dinfo.rd_dtype == OPEN_DELEGATE_NONE) {
1462 1449 if (is_rm)
1463 1450 fp->rf_dinfo.rd_hold_grant++;
1464 1451 rfs4_dbe_unlock(fp->rf_dbe);
1465 1452 return (FALSE);
1466 1453 }
1467 1454 /*
1468 1455 * do we have a write delegation on this file or are we
1469 1456 * requesting write access to a file with any type of existing
1470 1457 * delegation?
1471 1458 */
1472 1459 if (mode == FWRITE || fp->rf_dinfo.rd_dtype == OPEN_DELEGATE_WRITE) {
1473 1460 if (cp != NULL) {
1474 1461 dsp = list_head(&fp->rf_delegstatelist);
1475 1462 if (dsp == NULL) {
1476 1463 rfs4_dbe_unlock(fp->rf_dbe);
1477 1464 return (FALSE);
1478 1465 }
1479 1466 /*
1480 1467 * Does the requestor already own the delegation?
1481 1468 */
1482 1469 if (dsp->rds_client->rc_clientid == *(cp)) {
1483 1470 rfs4_dbe_unlock(fp->rf_dbe);
1484 1471 return (FALSE);
1485 1472 }
1486 1473 }
1487 1474
1488 1475 rfs4_dbe_unlock(fp->rf_dbe);
1489 1476 rfs4_recall_deleg(fp, trunc, NULL);
1490 1477
1491 1478 if (!do_delay) {
1492 1479 rfs4_dbe_lock(fp->rf_dbe);
1493 1480 fp->rf_dinfo.rd_time_rm_delayed = gethrestime_sec();
1494 1481 rfs4_dbe_unlock(fp->rf_dbe);
1495 1482 return (TRUE);
1496 1483 }
1497 1484
1498 1485 delay(NFS4_DELEGATION_CONFLICT_DELAY);
1499 1486
1500 1487 rfs4_dbe_lock(fp->rf_dbe);
1501 1488 if (fp->rf_dinfo.rd_dtype != OPEN_DELEGATE_NONE) {
1502 1489 fp->rf_dinfo.rd_time_rm_delayed = gethrestime_sec();
1503 1490 rfs4_dbe_unlock(fp->rf_dbe);
1504 1491 return (TRUE);
1505 1492 }
1506 1493 }
1507 1494 if (is_rm)
1508 1495 fp->rf_dinfo.rd_hold_grant++;
1509 1496 rfs4_dbe_unlock(fp->rf_dbe);
1510 1497 return (FALSE);
1511 1498 }
1512 1499
1513 1500 /*
1514 1501 * Check if the file is delegated in the case of a v2 or v3 access.
1515 1502 * Return TRUE if it is delegated which in turn means that v2 should
1516 1503 * drop the request and in the case of v3 JUKEBOX should be returned.
1517 1504 */
1518 1505 bool_t
1519 1506 rfs4_check_delegated(int mode, vnode_t *vp, bool_t trunc)
1520 1507 {
1521 1508 rfs4_file_t *fp;
1522 1509 bool_t create = FALSE;
1523 1510 bool_t rc = FALSE;
1524 1511
1525 1512 rfs4_hold_deleg_policy();
1526 1513
1527 1514 /* Is delegation enabled? */
1528 1515 if (rfs4_deleg_policy != SRV_NEVER_DELEGATE) {
1529 1516 fp = rfs4_findfile(vp, NULL, &create);
1530 1517 if (fp != NULL) {
1531 1518 if (rfs4_check_delegated_byfp(mode, fp, trunc,
1532 1519 TRUE, FALSE, NULL)) {
1533 1520 rc = TRUE;
1534 1521 }
1535 1522 rfs4_file_rele(fp);
1536 1523 }
1537 1524 }
1538 1525 rfs4_rele_deleg_policy();
1539 1526 return (rc);
1540 1527 }
1541 1528
1542 1529 /*
1543 1530 * Release a hold on the hold_grant counter which
1544 1531 * prevents delegation from being granted while a remove
1545 1532 * or a rename is in progress.
1546 1533 */
1547 1534 void
1548 1535 rfs4_clear_dont_grant(rfs4_file_t *fp)
1549 1536 {
1550 1537 if (rfs4_deleg_policy == SRV_NEVER_DELEGATE)
1551 1538 return;
1552 1539 rfs4_dbe_lock(fp->rf_dbe);
1553 1540 ASSERT(fp->rf_dinfo.rd_hold_grant > 0);
1554 1541 fp->rf_dinfo.rd_hold_grant--;
1555 1542 fp->rf_dinfo.rd_time_rm_delayed = 0;
1556 1543 rfs4_dbe_unlock(fp->rf_dbe);
1557 1544 }
1558 1545
1559 1546 /*
1560 1547 * State support for delegation.
1561 1548 * Set the state delegation type for this state;
1562 1549 * This routine is called from open via rfs4_grant_delegation and the entry
1563 1550 * locks on sp and sp->rs_finfo are assumed.
1564 1551 */
1565 1552 static rfs4_deleg_state_t *
1566 1553 rfs4_deleg_state(rfs4_state_t *sp, open_delegation_type4 dtype, int *recall)
1567 1554 {
1568 1555 rfs4_file_t *fp = sp->rs_finfo;
1569 1556 bool_t create = TRUE;
1570 1557 rfs4_deleg_state_t *dsp;
1571 1558 vnode_t *vp;
1572 1559 int open_prev = *recall;
1573 1560 int ret;
1574 1561 int fflags = 0;
1575 1562
1576 1563 ASSERT(rfs4_dbe_islocked(sp->rs_dbe));
1577 1564 ASSERT(rfs4_dbe_islocked(fp->rf_dbe));
1578 1565
1579 1566 /* Shouldn't happen */
1580 1567 if (fp->rf_dinfo.rd_recall_count != 0 ||
1581 1568 (fp->rf_dinfo.rd_dtype == OPEN_DELEGATE_READ &&
1582 1569 dtype != OPEN_DELEGATE_READ)) {
1583 1570 return (NULL);
1584 1571 }
1585 1572
1586 1573 /* Unlock to avoid deadlock */
1587 1574 rfs4_dbe_unlock(fp->rf_dbe);
1588 1575 rfs4_dbe_unlock(sp->rs_dbe);
1589 1576
1590 1577 dsp = rfs4_finddeleg(sp, &create);
1591 1578
1592 1579 rfs4_dbe_lock(sp->rs_dbe);
1593 1580 rfs4_dbe_lock(fp->rf_dbe);
1594 1581
1595 1582 if (dsp == NULL)
1596 1583 return (NULL);
1597 1584
1598 1585 /*
1599 1586 * It is possible that since we dropped the lock
1600 1587 * in order to call finddeleg, the rfs4_file_t
1601 1588 * was marked such that we should not grant a
1602 1589 * delegation, if so bail out.
1603 1590 */
1604 1591 if (fp->rf_dinfo.rd_hold_grant > 0) {
1605 1592 rfs4_deleg_state_rele(dsp);
1606 1593 return (NULL);
1607 1594 }
1608 1595
1609 1596 if (create == FALSE) {
1610 1597 if (sp->rs_owner->ro_client == dsp->rds_client &&
1611 1598 dsp->rds_dtype == dtype) {
1612 1599 return (dsp);
1613 1600 } else {
1614 1601 rfs4_deleg_state_rele(dsp);
1615 1602 return (NULL);
1616 1603 }
1617 1604 }
1618 1605
1619 1606 /*
1620 1607 * Check that this file has not been delegated to another
1621 1608 * client
1622 1609 */
1623 1610 if (fp->rf_dinfo.rd_recall_count != 0 ||
1624 1611 fp->rf_dinfo.rd_dtype == OPEN_DELEGATE_WRITE ||
1625 1612 (fp->rf_dinfo.rd_dtype == OPEN_DELEGATE_READ &&
1626 1613 dtype != OPEN_DELEGATE_READ)) {
1627 1614 rfs4_deleg_state_rele(dsp);
1628 1615 return (NULL);
1629 1616 }
1630 1617
1631 1618 vp = fp->rf_vp;
1632 1619 /* vnevent_support returns 0 if file system supports vnevents */
1633 1620 if (vnevent_support(vp, NULL)) {
1634 1621 rfs4_deleg_state_rele(dsp);
1635 1622 return (NULL);
1636 1623 }
1637 1624
1638 1625 /* Calculate the fflags for this OPEN. */
1639 1626 if (sp->rs_share_access & OPEN4_SHARE_ACCESS_READ)
1640 1627 fflags |= FREAD;
1641 1628 if (sp->rs_share_access & OPEN4_SHARE_ACCESS_WRITE)
1642 1629 fflags |= FWRITE;
1643 1630
1644 1631 *recall = 0;
1645 1632 /*
1646 1633 * Before granting a delegation we need to know if anyone else has
1647 1634 * opened the file in a conflicting mode. However, first we need to
1648 1635 * know how we opened the file to check the counts properly.
1649 1636 */
1650 1637 if (dtype == OPEN_DELEGATE_READ) {
1651 1638 if (((fflags & FWRITE) && vn_has_other_opens(vp, V_WRITE)) ||
1652 1639 (((fflags & FWRITE) == 0) && vn_is_opened(vp, V_WRITE)) ||
1653 1640 vn_is_mapped(vp, V_WRITE)) {
1654 1641 if (open_prev) {
1655 1642 *recall = 1;
1656 1643 } else {
1657 1644 rfs4_deleg_state_rele(dsp);
1658 1645 return (NULL);
1659 1646 }
1660 1647 }
1661 1648 ret = fem_install(vp, deleg_rdops, (void *)fp, OPUNIQ,
1662 1649 rfs4_mon_hold, rfs4_mon_rele);
1663 1650 if (((fflags & FWRITE) && vn_has_other_opens(vp, V_WRITE)) ||
1664 1651 (((fflags & FWRITE) == 0) && vn_is_opened(vp, V_WRITE)) ||
1665 1652 vn_is_mapped(vp, V_WRITE)) {
1666 1653 if (open_prev) {
1667 1654 *recall = 1;
1668 1655 } else {
1669 1656 (void) fem_uninstall(vp, deleg_rdops,
1670 1657 (void *)fp);
1671 1658 rfs4_deleg_state_rele(dsp);
1672 1659 return (NULL);
1673 1660 }
1674 1661 }
1675 1662 /*
1676 1663 * Because a client can hold onto a delegation after the
1677 1664 * file has been closed, we need to keep track of the
1678 1665 * access to this file. Otherwise the CIFS server would
1679 1666 * not know about the client accessing the file and could
1680 1667 * inappropriately grant an OPLOCK.
1681 1668 * fem_install() returns EBUSY when asked to install a
1682 1669 * OPUNIQ monitor more than once. Therefore, check the
1683 1670 * return code because we only want this done once.
1684 1671 */
1685 1672 if (ret == 0)
1686 1673 vn_open_upgrade(vp, FREAD);
1687 1674 } else { /* WRITE */
1688 1675 if (((fflags & FWRITE) && vn_has_other_opens(vp, V_WRITE)) ||
1689 1676 (((fflags & FWRITE) == 0) && vn_is_opened(vp, V_WRITE)) ||
1690 1677 ((fflags & FREAD) && vn_has_other_opens(vp, V_READ)) ||
1691 1678 (((fflags & FREAD) == 0) && vn_is_opened(vp, V_READ)) ||
1692 1679 vn_is_mapped(vp, V_RDORWR)) {
1693 1680 if (open_prev) {
1694 1681 *recall = 1;
1695 1682 } else {
1696 1683 rfs4_deleg_state_rele(dsp);
1697 1684 return (NULL);
1698 1685 }
1699 1686 }
1700 1687 ret = fem_install(vp, deleg_wrops, (void *)fp, OPUNIQ,
1701 1688 rfs4_mon_hold, rfs4_mon_rele);
1702 1689 if (((fflags & FWRITE) && vn_has_other_opens(vp, V_WRITE)) ||
1703 1690 (((fflags & FWRITE) == 0) && vn_is_opened(vp, V_WRITE)) ||
1704 1691 ((fflags & FREAD) && vn_has_other_opens(vp, V_READ)) ||
1705 1692 (((fflags & FREAD) == 0) && vn_is_opened(vp, V_READ)) ||
1706 1693 vn_is_mapped(vp, V_RDORWR)) {
1707 1694 if (open_prev) {
1708 1695 *recall = 1;
1709 1696 } else {
1710 1697 (void) fem_uninstall(vp, deleg_wrops,
1711 1698 (void *)fp);
1712 1699 rfs4_deleg_state_rele(dsp);
1713 1700 return (NULL);
1714 1701 }
1715 1702 }
1716 1703 /*
1717 1704 * Because a client can hold onto a delegation after the
1718 1705 * file has been closed, we need to keep track of the
1719 1706 * access to this file. Otherwise the CIFS server would
1720 1707 * not know about the client accessing the file and could
1721 1708 * inappropriately grant an OPLOCK.
1722 1709 * fem_install() returns EBUSY when asked to install a
1723 1710 * OPUNIQ monitor more than once. Therefore, check the
1724 1711 * return code because we only want this done once.
1725 1712 */
1726 1713 if (ret == 0)
1727 1714 vn_open_upgrade(vp, FREAD|FWRITE);
1728 1715 }
1729 1716 /* Place on delegation list for file */
1730 1717 ASSERT(!list_link_active(&dsp->rds_node));
1731 1718 list_insert_tail(&fp->rf_delegstatelist, dsp);
1732 1719
1733 1720 dsp->rds_dtype = fp->rf_dinfo.rd_dtype = dtype;
1734 1721
1735 1722 /* Update delegation stats for this file */
1736 1723 fp->rf_dinfo.rd_time_lastgrant = gethrestime_sec();
1737 1724
1738 1725 /* reset since this is a new delegation */
1739 1726 fp->rf_dinfo.rd_conflicted_client = 0;
1740 1727 fp->rf_dinfo.rd_ever_recalled = FALSE;
1741 1728
1742 1729 if (dtype == OPEN_DELEGATE_READ)
1743 1730 fp->rf_dinfo.rd_rdgrants++;
1744 1731 else
1745 1732 fp->rf_dinfo.rd_wrgrants++;
1746 1733
1747 1734 return (dsp);
1748 1735 }
1749 1736
1750 1737 /*
1751 1738 * State routine for the server when a delegation is returned.
1752 1739 */
1753 1740 void
1754 1741 rfs4_return_deleg(rfs4_deleg_state_t *dsp, bool_t revoked)
1755 1742 {
1756 1743 rfs4_file_t *fp = dsp->rds_finfo;
1757 1744 open_delegation_type4 dtypewas;
1758 1745
1759 1746 rfs4_dbe_lock(fp->rf_dbe);
1760 1747
1761 1748 /* nothing to do if no longer on list */
1762 1749 if (!list_link_active(&dsp->rds_node)) {
1763 1750 rfs4_dbe_unlock(fp->rf_dbe);
1764 1751 return;
1765 1752 }
1766 1753
1767 1754 /* Remove state from recall list */
1768 1755 list_remove(&fp->rf_delegstatelist, dsp);
1769 1756
1770 1757 if (list_is_empty(&fp->rf_delegstatelist)) {
1771 1758 dtypewas = fp->rf_dinfo.rd_dtype;
1772 1759 fp->rf_dinfo.rd_dtype = OPEN_DELEGATE_NONE;
1773 1760 rfs4_dbe_cv_broadcast(fp->rf_dbe);
1774 1761
1775 1762 /* if file system was unshared, the vp will be NULL */
1776 1763 if (fp->rf_vp != NULL) {
1777 1764 /*
1778 1765 * Once a delegation is no longer held by any client,
1779 1766 * the monitor is uninstalled. At this point, the
1780 1767 * client must send OPEN otw, so we don't need the
1781 1768 * reference on the vnode anymore. The open
1782 1769 * downgrade removes the reference put on earlier.
1783 1770 */
1784 1771 if (dtypewas == OPEN_DELEGATE_READ) {
1785 1772 (void) fem_uninstall(fp->rf_vp, deleg_rdops,
1786 1773 (void *)fp);
1787 1774 vn_open_downgrade(fp->rf_vp, FREAD);
1788 1775 } else if (dtypewas == OPEN_DELEGATE_WRITE) {
1789 1776 (void) fem_uninstall(fp->rf_vp, deleg_wrops,
1790 1777 (void *)fp);
1791 1778 vn_open_downgrade(fp->rf_vp, FREAD|FWRITE);
1792 1779 }
1793 1780 }
1794 1781 }
1795 1782
1796 1783 switch (dsp->rds_dtype) {
1797 1784 case OPEN_DELEGATE_READ:
1798 1785 fp->rf_dinfo.rd_rdgrants--;
1799 1786 break;
1800 1787 case OPEN_DELEGATE_WRITE:
1801 1788 fp->rf_dinfo.rd_wrgrants--;
1802 1789 break;
1803 1790 default:
1804 1791 break;
1805 1792 }
1806 1793
1807 1794 /* used in the policy decision */
1808 1795 fp->rf_dinfo.rd_time_returned = gethrestime_sec();
1809 1796
1810 1797 /*
1811 1798 * reset the time_recalled field so future delegations are not
1812 1799 * accidentally revoked
1813 1800 */
1814 1801 if ((fp->rf_dinfo.rd_rdgrants + fp->rf_dinfo.rd_wrgrants) == 0)
1815 1802 fp->rf_dinfo.rd_time_recalled = 0;
1816 1803
1817 1804 rfs4_dbe_unlock(fp->rf_dbe);
1818 1805
1819 1806 rfs4_dbe_lock(dsp->rds_dbe);
1820 1807
1821 1808 dsp->rds_dtype = OPEN_DELEGATE_NONE;
1822 1809
1823 1810 if (revoked == TRUE)
1824 1811 dsp->rds_time_revoked = gethrestime_sec();
1825 1812
1826 1813 rfs4_dbe_invalidate(dsp->rds_dbe);
1827 1814
1828 1815 rfs4_dbe_unlock(dsp->rds_dbe);
1829 1816
1830 1817 if (revoked == TRUE) {
1831 1818 rfs4_dbe_lock(dsp->rds_client->rc_dbe);
1832 1819 dsp->rds_client->rc_deleg_revoked++; /* observability */
1833 1820 rfs4_dbe_unlock(dsp->rds_client->rc_dbe);
1834 1821 }
1835 1822 }
1836 1823
1837 1824 static void
1838 1825 rfs4_revoke_file(rfs4_file_t *fp)
1839 1826 {
1840 1827 rfs4_deleg_state_t *dsp;
1841 1828
1842 1829 /*
1843 1830 * The lock for rfs4_file_t must be held when traversing the
1844 1831 * delegation list but that lock needs to be released to call
1845 1832 * rfs4_return_deleg()
1846 1833 */
1847 1834 rfs4_dbe_lock(fp->rf_dbe);
1848 1835 while (dsp = list_head(&fp->rf_delegstatelist)) {
1849 1836 rfs4_dbe_hold(dsp->rds_dbe);
1850 1837 rfs4_dbe_unlock(fp->rf_dbe);
1851 1838 rfs4_return_deleg(dsp, TRUE);
1852 1839 rfs4_deleg_state_rele(dsp);
1853 1840 rfs4_dbe_lock(fp->rf_dbe);
1854 1841 }
1855 1842 rfs4_dbe_unlock(fp->rf_dbe);
1856 1843 }
1857 1844
1858 1845 /*
1859 1846 * A delegation is assumed to be present on the file associated with
1860 1847 * "sp". Check to see if the delegation matches is associated with
1861 1848 * the same client as referenced by "sp". If it is not, TRUE is
1862 1849 * returned. If the delegation DOES match the client (or no
1863 1850 * delegation is present), return FALSE.
1864 1851 * Assume the state entry and file entry are locked.
1865 1852 */
1866 1853 bool_t
1867 1854 rfs4_is_deleg(rfs4_state_t *sp)
1868 1855 {
1869 1856 rfs4_deleg_state_t *dsp;
1870 1857 rfs4_file_t *fp = sp->rs_finfo;
1871 1858 rfs4_client_t *cp = sp->rs_owner->ro_client;
1872 1859
1873 1860 ASSERT(rfs4_dbe_islocked(fp->rf_dbe));
1874 1861 for (dsp = list_head(&fp->rf_delegstatelist); dsp != NULL;
1875 1862 dsp = list_next(&fp->rf_delegstatelist, dsp)) {
1876 1863 if (cp != dsp->rds_client) {
1877 1864 return (TRUE);
1878 1865 }
1879 1866 }
1880 1867 return (FALSE);
1881 1868 }
1882 1869
1883 1870 void
1884 1871 rfs4_disable_delegation(void)
1885 1872 {
1886 1873 mutex_enter(&rfs4_deleg_lock);
1887 1874 rfs4_deleg_disabled++;
1888 1875 mutex_exit(&rfs4_deleg_lock);
1889 1876 }
1890 1877
1891 1878 void
1892 1879 rfs4_enable_delegation(void)
1893 1880 {
1894 1881 mutex_enter(&rfs4_deleg_lock);
1895 1882 ASSERT(rfs4_deleg_disabled > 0);
1896 1883 rfs4_deleg_disabled--;
1897 1884 mutex_exit(&rfs4_deleg_lock);
1898 1885 }
1899 1886
1900 1887 void
1901 1888 rfs4_mon_hold(void *arg)
1902 1889 {
1903 1890 rfs4_file_t *fp = arg;
1904 1891
1905 1892 rfs4_dbe_hold(fp->rf_dbe);
1906 1893 }
1907 1894
1908 1895 void
1909 1896 rfs4_mon_rele(void *arg)
1910 1897 {
1911 1898 rfs4_file_t *fp = arg;
1912 1899
1913 1900 rfs4_dbe_rele_nolock(fp->rf_dbe);
1914 1901 }
↓ open down ↓ |
1768 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX