ReactOS 0.4.15-dev-6049-ge54b32b
recovery.c
Go to the documentation of this file.
1/* NFSv4.1 client for Windows
2 * Copyright 2012 The Regents of the University of Michigan
3 *
4 * Olga Kornievskaia <aglo@umich.edu>
5 * Casey Bodley <cbodley@umich.edu>
6 *
7 * This library is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as published by
9 * the Free Software Foundation; either version 2.1 of the License, or (at
10 * your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful, but
13 * without any warranty; without even the implied warranty of merchantability
14 * or fitness for a particular purpose. See the GNU Lesser General Public
15 * License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 */
21
22#include <time.h>
23
24#include "recovery.h"
25#include "delegation.h"
26#include "nfs41_callback.h"
27#include "nfs41_compound.h"
28#include "nfs41_ops.h"
29#include "daemon_debug.h"
30
31
32/* session/client recovery uses a lock and condition variable in nfs41_client
33 * to prevent multiple threads from attempting to recover at the same time */
36{
38
39 EnterCriticalSection(&client->recovery.lock);
40
41 if (!client->recovery.in_recovery) {
42 dprintf(1, "Entering recovery mode for client %llu\n", client->clnt_id);
43 client->recovery.in_recovery = TRUE;
44 } else {
45 status = FALSE;
46 dprintf(1, "Waiting for recovery of client %llu\n", client->clnt_id);
47 while (client->recovery.in_recovery)
48 SleepConditionVariableCS(&client->recovery.cond,
49 &client->recovery.lock, INFINITE);
50 dprintf(1, "Woke up after recovery of client %llu\n", client->clnt_id);
51 }
52
53 LeaveCriticalSection(&client->recovery.lock);
54 return status;
55}
56
59{
60 EnterCriticalSection(&client->recovery.lock);
61 dprintf(1, "Finished recovery for client %llu\n", client->clnt_id);
62 client->recovery.in_recovery = FALSE;
63 WakeAllConditionVariable(&client->recovery.cond);
64 LeaveCriticalSection(&client->recovery.lock);
65}
66
67
68/* session/client/state recovery */
71 IN bool_t client_state_lost)
72{
73 enum nfsstat4 status = NFS4_OK;
74
75restart_recovery:
76 /* recover the session */
78
80 /* recover the client */
81 client_state_lost = TRUE;
83 if (status == NFS4_OK)
84 goto restart_recovery; /* resume session recovery */
85
86 eprintf("nfs41_client_renew() failed with %d\n", status);
87 } else if (status) {
88 eprintf("nfs41_session_renew() failed with %d\n", status);
89 } else if (client_state_lost) {
90 /* recover the client's state */
93 goto restart_recovery;
94 }
95 return status;
96}
97
101{
102 const uint32_t revoked = flags &
107 const uint32_t restarted = flags &
109
110 /* no state recovery needed */
111 if (revoked == 0 && restarted == 0)
112 return;
113
115 return;
116
117 if (revoked) {
118 /* free stateids and attempt to recover them */
119 nfs41_client_state_revoked(session, session->client, revoked);
120
121 /* if RESTART_RECLAIM_NEEDED is also set, just do RECLAIM_COMPLETE */
122 if (restarted) nfs41_reclaim_complete(session);
123
124 } else if (restarted) {
125 /* do server reboot state recovery */
127 if (status == NFS4ERR_BADSESSION) {
128 /* recover the session and finish state recovery */
130 }
131 }
132
134}
135
136
137/* client state recovery for server reboot or lease expiration */
142 IN state_owner4 *owner,
144 IN uint32_t deny,
145 OUT stateid4 *stateid,
146 OUT open_delegation4 *delegation)
147{
148 /* reclaim the open stateid with CLAIM_PREVIOUS */
149 open_claim4 claim;
150 claim.claim = CLAIM_PREVIOUS;
151 claim.u.prev.delegate_type = delegation->type;
152
153 return nfs41_open(session, parent, file, owner, &claim, access, deny,
154 OPEN4_NOCREATE, 0, NULL, FALSE, stateid, delegation, NULL);
155}
156
161 IN state_owner4 *owner,
163 IN uint32_t deny,
164 OUT stateid4 *stateid,
165 OUT open_delegation4 *delegation)
166{
167 open_claim4 claim;
168 int status;
169
170 if (delegation->type != OPEN_DELEGATE_NONE) {
171 /* attempt out-of-grace recovery with CLAIM_DELEGATE_PREV */
173 claim.u.deleg_prev.filename = &file->name;
174
176 &claim, access, deny, OPEN4_NOCREATE, 0, NULL, FALSE,
177 stateid, delegation, NULL);
179 goto out;
180
181 /* server support for CLAIM_DELEGATE_PREV is optional;
182 * fall back to CLAIM_NULL on errors */
183 }
184
185 /* attempt out-of-grace recovery with CLAIM_NULL */
186 claim.claim = CLAIM_NULL;
187 claim.u.null.filename = &file->name;
188
189 /* ask nicely for the delegation we had */
190 if (delegation->type == OPEN_DELEGATE_READ)
192 else if (delegation->type == OPEN_DELEGATE_WRITE)
194
196 &claim, access, deny, OPEN4_NOCREATE, 0, NULL, FALSE,
197 stateid, delegation, NULL);
198out:
199 return status;
200}
201
202static int recover_open(
205 IN OUT bool_t *grace)
206{
207 open_delegation4 delegation = { 0 };
208 stateid4 stateid = { 0 };
210
211 /* check for an associated delegation */
213 if (open->delegation.state) {
214 nfs41_delegation_state *deleg = open->delegation.state;
215 if (deleg->revoked) {
216 /* reclaim the delegation along with the open */
217 AcquireSRWLockShared(&deleg->lock);
218 delegation.type = deleg->state.type;
219 ReleaseSRWLockShared(&deleg->lock);
220 } else if (deleg->state.recalled) {
221 /* we'll need an open stateid regardless */
222 } else if (list_empty(&open->locks.list)) {
223 /* if there are locks, we need an open stateid to
224 * reclaim them; otherwise, the open can be delegated */
225 open->do_close = FALSE;
226 status = NFS4_OK;
227 }
228 }
230
231 if (status == NFS4_OK) /* use existing delegation */
232 goto out;
233
234 if (*grace) {
235 status = recover_open_grace(session, &open->parent, &open->file,
236 &open->owner, open->share_access, open->share_deny,
237 &stateid, &delegation);
238 if (status == NFS4ERR_NO_GRACE) {
239 *grace = FALSE;
240 /* send RECLAIM_COMPLETE before any out-of-grace recovery */
242 }
243 }
244 if (!*grace) {
245 status = recover_open_no_grace(session, &open->parent, &open->file,
246 &open->owner, open->share_access, open->share_deny,
247 &stateid, &delegation);
248 }
249
250 if (status)
251 goto out;
252
254 /* update the open stateid */
255 memcpy(&open->stateid, &stateid, sizeof(stateid4));
256 open->do_close = TRUE;
257
258 if (open->delegation.state) {
259 nfs41_delegation_state *deleg = open->delegation.state;
260 if (deleg->revoked) {
261 /* update delegation state */
263 if (delegation.type != OPEN_DELEGATE_READ &&
264 delegation.type != OPEN_DELEGATE_WRITE) {
265 eprintf("recover_open() got delegation type %u, "
266 "expected %u\n", delegation.type, deleg->state.type);
267 } else {
268 memcpy(&deleg->state, &delegation, sizeof(open_delegation4));
269 deleg->revoked = FALSE;
270 }
272 }
273 } else /* granted a new delegation? */
274 nfs41_delegation_granted(session, &open->parent, &open->file,
275 &delegation, FALSE, &open->delegation.state);
277out:
278 return status;
279}
280
281static int recover_locks(
284 IN OUT bool_t *grace)
285{
286 stateid_arg stateid;
287 struct list_entry *entry;
289 int status = NFS4_OK;
290
292
293 /* initialize the open stateid for the first lock request */
294 memcpy(&stateid.stateid, &open->stateid, sizeof(stateid4));
295 stateid.type = STATEID_OPEN;
296 stateid.open = open;
297 stateid.delegation = NULL;
298
299 /* recover any locks for this open */
300 list_for_each(entry, &open->locks.list) {
302 if (lock->delegated)
303 continue;
304
305 if (*grace) {
306 status = nfs41_lock(session, &open->file, &open->owner,
307 lock->exclusive ? WRITE_LT : READ_LT, lock->offset,
308 lock->length, TRUE, FALSE, &stateid);
309 if (status == NFS4ERR_NO_GRACE) {
310 *grace = FALSE;
311 /* send RECLAIM_COMPLETE before any out-of-grace recovery */
313 }
314 }
315 if (!*grace) {
316 /* attempt out-of-grace recovery with a normal LOCK */
317 status = nfs41_lock(session, &open->file, &open->owner,
318 lock->exclusive ? WRITE_LT : READ_LT, lock->offset,
319 lock->length, FALSE, FALSE, &stateid);
320 }
322 break;
323 }
324
325 if (status != NFS4ERR_BADSESSION) {
326 /* if we got a lock stateid back, save the lock with the open */
327 if (stateid.type == STATEID_LOCK)
328 memcpy(&open->locks.stateid, &stateid.stateid, sizeof(stateid4));
329 else
330 open->locks.stateid.seqid = 0;
331 }
332
334 return status;
335}
336
337/* delegation recovery via WANT_DELEGATION */
341 IN OUT bool_t *grace)
342{
343 deleg_claim4 claim;
344 open_delegation4 delegation = { 0 };
345 uint32_t want_flags = 0;
346 int status = NFS4_OK;
347
348 AcquireSRWLockShared(&deleg->lock);
349 delegation.type = deleg->state.type;
350 ReleaseSRWLockShared(&deleg->lock);
351
352 if (delegation.type == OPEN_DELEGATE_READ)
354 else
356
357 if (*grace) {
358 /* recover the delegation with WANT_DELEGATION/CLAIM_PREVIOUS */
359 claim.claim = CLAIM_PREVIOUS;
360 claim.prev_delegate_type = delegation.type;
361
362 status = nfs41_want_delegation(session, &deleg->file, &claim,
363 want_flags, FALSE, &delegation);
364 if (status == NFS4ERR_NO_GRACE) {
365 *grace = FALSE;
366 /* send RECLAIM_COMPLETE before any out-of-grace recovery */
368 }
369 }
370 if (!*grace) {
371 /* attempt out-of-grace recovery with with CLAIM_DELEG_PREV_FH */
373
374 status = nfs41_want_delegation(session, &deleg->file, &claim,
375 want_flags, FALSE, &delegation);
376 }
377 if (status)
378 goto out;
379
380 /* update delegation state */
381 AcquireSRWLockExclusive(&deleg->lock);
382 if (delegation.type != OPEN_DELEGATE_READ &&
383 delegation.type != OPEN_DELEGATE_WRITE) {
384 eprintf("recover_delegation_want() got delegation type %u, "
385 "expected %u\n", delegation.type, deleg->state.type);
386 } else {
387 memcpy(&deleg->state, &delegation, sizeof(open_delegation4));
388 deleg->revoked = FALSE;
389 }
390 ReleaseSRWLockExclusive(&deleg->lock);
391out:
392 return status;
393}
394
395/* delegation recovery via OPEN (requires corresponding CLOSE) */
399 IN OUT bool_t *grace)
400{
401 state_owner4 owner;
402 open_delegation4 delegation = { 0 };
403 stateid_arg stateid;
406 int status = NFS4_OK;
407
408 /* choose the desired access mode based on delegation type */
409 AcquireSRWLockShared(&deleg->lock);
410 delegation.type = deleg->state.type;
411 if (delegation.type == OPEN_DELEGATE_WRITE)
413 else
415 ReleaseSRWLockShared(&deleg->lock);
416
417 /* construct a temporary open owner by concatenating the time
418 * in seconds with the delegation pointer */
419 time((time_t*)owner.owner);
420 memcpy(owner.owner + sizeof(time_t), deleg, sizeof(deleg));
421 owner.owner_len = sizeof(time_t) + sizeof(deleg);
422
423 if (*grace) {
424 status = recover_open_grace(session, &deleg->parent, &deleg->file,
425 &owner, access, deny, &stateid.stateid, &delegation);
426 if (status == NFS4ERR_NO_GRACE) {
427 *grace = FALSE;
428 /* send RECLAIM_COMPLETE before any out-of-grace recovery */
430 }
431 }
432 if (!*grace) {
433 status = recover_open_no_grace(session, &deleg->parent, &deleg->file,
434 &owner, access, deny, &stateid.stateid, &delegation);
435 }
436 if (status)
437 goto out;
438
439 /* update delegation state */
440 AcquireSRWLockExclusive(&deleg->lock);
441 if (delegation.type != OPEN_DELEGATE_READ &&
442 delegation.type != OPEN_DELEGATE_WRITE) {
443 eprintf("recover_delegation_open() got delegation type %u, "
444 "expected %u\n", delegation.type, deleg->state.type);
445 } else {
446 memcpy(&deleg->state, &delegation, sizeof(open_delegation4));
447 deleg->revoked = FALSE;
448 }
449 ReleaseSRWLockExclusive(&deleg->lock);
450
451 /* send CLOSE to free the open stateid */
452 stateid.open = NULL;
453 stateid.delegation = NULL;
454 stateid.type = STATEID_OPEN;
455 nfs41_close(session, &deleg->file, &stateid);
456out:
457 return status;
458}
459
463 IN OUT bool_t *grace,
464 IN OUT bool_t *want_supported)
465{
466 int status;
467
468 /* 10.2.1. Delegation Recovery
469 * When a client needs to reclaim a delegation and there is no
470 * associated open, the client may use the CLAIM_PREVIOUS variant
471 * of the WANT_DELEGATION operation. However, since the server is
472 * not required to support this operation, an alternative is to
473 * reclaim via a dummy OPEN together with the delegation using an
474 * OPEN of type CLAIM_PREVIOUS. */
475 if (*want_supported)
476 status = recover_delegation_want(session, deleg, grace);
477 else
479
480 if (status == NFS4ERR_NOTSUPP) {
481 *want_supported = FALSE;
482 status = recover_delegation_open(session, deleg, grace);
483 }
484 return status;
485}
486
490{
493 struct client_state *state = &session->client->state;
494 struct list_entry *entry;
497 bool_t grace = TRUE;
498 bool_t want_supported = TRUE;
499 int status = NFS4_OK;
500
502
503 /* flag all delegations as revoked until successful recovery;
504 * recover_open() and recover_delegation_open() will only ask
505 * for delegations when revoked = TRUE */
506 list_for_each(entry, &state->delegations) {
508 deleg->revoked = TRUE;
509 }
510
511 /* recover each of the client's opens and associated delegations */
512 list_for_each(entry, &state->opens) {
514 status = recover_open(session, open, &grace);
515 if (status == NFS4_OK)
516 status = recover_locks(session, open, &grace);
518 goto unlock;
519 }
520
521 /* recover delegations that weren't associated with any opens */
522 list_for_each(entry, &state->delegations) {
524 if (deleg->revoked) {
526 deleg, &grace, &want_supported);
528 goto unlock;
529 }
530 }
531
532 /* return any delegations that were reclaimed as 'recalled' */
534unlock:
536
537 /* revoke all of the client's layouts */
539
540 if (grace && status != NFS4ERR_BADSESSION) {
541 /* send reclaim_complete, but don't fail on errors */
543 }
544 return status;
545}
546
548 IN struct list_entry *delegations,
549 IN struct list_entry *opens,
550 OUT stateid_arg **stateids_out,
551 OUT uint32_t **statuses_out)
552{
553 struct list_entry *entry;
556 stateid_arg *stateids = NULL;
557 uint32_t *statuses = NULL;
558 uint32_t i = 0, count = 0;
559
560 /* count how many stateids the client needs to test */
561 list_for_each(entry, delegations)
562 count++;
563 list_for_each(entry, opens)
564 count += 3; /* open and potentially lock and layout */
565
566 if (count == 0)
567 goto out;
568
569 /* allocate the stateid and status arrays */
570 stateids = calloc(count, sizeof(stateid_arg));
571 if (stateids == NULL)
572 goto out_err;
573 statuses = calloc(count, sizeof(uint32_t));
574 if (statuses == NULL)
575 goto out_err;
576 memset(statuses, NFS4ERR_BAD_STATEID, count * sizeof(uint32_t));
577
578 /* copy stateids into the array */
579 list_for_each(entry, delegations) {
581 AcquireSRWLockShared(&deleg->lock);
582 /* delegation stateid */
583 memcpy(&stateids[i].stateid, &deleg->state.stateid, sizeof(stateid4));
584 stateids[i].type = STATEID_DELEG_FILE;
585 stateids[i].delegation = deleg;
586 i++;
587 ReleaseSRWLockShared(&deleg->lock);
588 }
589
590 list_for_each(entry, opens) {
592
594 /* open stateid */
595 memcpy(&stateids[i].stateid, &open->stateid, sizeof(stateid4));
596 stateids[i].type = STATEID_OPEN;
597 stateids[i].open = open;
598 i++;
599
600 if (open->locks.stateid.seqid) { /* lock stateid? */
601 memcpy(&stateids[i].stateid, &open->locks.stateid, sizeof(stateid4));
602 stateids[i].type = STATEID_LOCK;
603 stateids[i].open = open;
604 i++;
605 }
606
607 if (open->layout) { /* layout stateid? */
608 AcquireSRWLockShared(&open->layout->lock);
609 if (open->layout->stateid.seqid) {
610 memcpy(&stateids[i].stateid, &open->layout->stateid, sizeof(stateid4));
611 stateids[i].type = STATEID_LAYOUT;
612 stateids[i].open = open;
613 i++;
614 }
615 ReleaseSRWLockShared(&open->layout->lock);
616 }
618 }
619
620 count = i;
621 *stateids_out = stateids;
622 *statuses_out = statuses;
623out:
624 return count;
625
626out_err:
627 free(stateids);
628 free(statuses);
629 count = 0;
630 goto out;
631}
632
636 IN uint32_t revoked)
637{
640 struct list_entry empty, *opens;
641 struct client_state *clientstate = &session->client->state;
642 stateid_arg *stateids = NULL;
643 uint32_t *statuses = NULL;
645 bool_t grace = TRUE;
646 bool_t want_supported = TRUE;
647
648 EnterCriticalSection(&clientstate->lock);
649
651 /* only delegations were revoked. use an empty list for opens */
653 opens = &empty;
654 } else {
655 opens = &clientstate->opens;
656 }
657
658 /* get an array of the client's stateids */
659 count = stateid_array(&clientstate->delegations,
660 opens, &stateids, &statuses);
661 if (count == 0)
662 goto out;
663
664 /* determine which stateids were revoked with TEST_STATEID */
665 if ((revoked & SEQ4_STATUS_EXPIRED_ALL_STATE_REVOKED) == 0)
666 nfs41_test_stateid(session, stateids, count, statuses);
667
668 /* free all revoked stateids with FREE_STATEID */
669 for (i = 0; i < count; i++)
670 if (statuses[i])
671 nfs41_free_stateid(session, &stateids[i].stateid);
672
673 /* revoke all of the client's layouts */
675
676 /* recover the revoked stateids */
677 for (i = 0; i < count; i++) {
678 if (statuses[i]) {
679 if (stateids[i].type == STATEID_DELEG_FILE)
680 stateids[i].delegation->revoked = TRUE;
681 else if (stateids[i].type == STATEID_OPEN)
682 recover_open(session, stateids[i].open, &grace);
683 else if (stateids[i].type == STATEID_LOCK)
684 recover_locks(session, stateids[i].open, &grace);
685 }
686 }
687 for (i = 0; i < count; i++) {
688 /* delegations that weren't recovered by recover_open() */
689 if (statuses[i] && stateids[i].type == STATEID_DELEG_FILE
690 && stateids[i].delegation->revoked)
691 recover_delegation(session, stateids[i].delegation,
692 &grace, &want_supported);
693 }
694
696out:
697 LeaveCriticalSection(&clientstate->lock);
698 free(stateids);
699 free(statuses);
700}
701
702
704 IN nfs_argop4 *argop,
705 IN stateid_arg *stateid)
706{
707 bool_t retry = FALSE;
708
709 if (stateid->open) {
710 stateid4 *source = &stateid->open->stateid;
711
712 /* if the source stateid is different, update and retry */
713 AcquireSRWLockShared(&stateid->open->lock);
714 if (memcmp(&stateid->stateid, source, sizeof(stateid4))) {
715 memcpy(&stateid->stateid, source, sizeof(stateid4));
716 retry = TRUE;
717 }
718 ReleaseSRWLockShared(&stateid->open->lock);
719 }
720 return retry;
721}
722
724 IN nfs_argop4 *argop,
725 IN stateid_arg *stateid)
726{
727 bool_t retry = FALSE;
728
729 if (stateid->open) {
730 stateid4 *source = &stateid->open->locks.stateid;
731
732 /* if the source stateid is different, update and retry */
733 AcquireSRWLockShared(&stateid->open->lock);
734 if (memcmp(&stateid->stateid, source, sizeof(stateid4))) {
735 if (argop->op == OP_LOCK && source->seqid == 0) {
736 /* resend LOCK with an open stateid */
737 nfs41_lock_args *lock = (nfs41_lock_args*)argop->arg;
738 lock->locker.new_lock_owner = 1;
739 lock->locker.u.open_owner.open_stateid = stateid;
740 lock->locker.u.open_owner.lock_owner = &stateid->open->owner;
741 source = &stateid->open->stateid;
742 }
743
744 memcpy(&stateid->stateid, source, sizeof(stateid4));
745 retry = TRUE;
746 }
747 ReleaseSRWLockShared(&stateid->open->lock);
748 }
749 return retry;
750}
751
753 IN nfs_argop4 *argop,
754 IN stateid_arg *stateid)
755{
756 bool_t retry = FALSE;
757
758 if (stateid->open) {
759 /* if the source stateid is different, update and retry */
760 AcquireSRWLockShared(&stateid->open->lock);
761 if (argop->op == OP_OPEN && stateid->open->do_close) {
762 /* for nfs41_delegation_to_open(); if we've already reclaimed
763 * an open stateid, just fail this OPEN with BAD_STATEID */
764 } else if (stateid->open->delegation.state) {
765 nfs41_delegation_state *deleg = stateid->open->delegation.state;
766 stateid4 *source = &deleg->state.stateid;
767 AcquireSRWLockShared(&deleg->lock);
768 if (memcmp(&stateid->stateid, source, sizeof(stateid4))) {
769 memcpy(&stateid->stateid, source, sizeof(stateid4));
770 retry = TRUE;
771 }
772 ReleaseSRWLockShared(&deleg->lock);
773 }
774 ReleaseSRWLockShared(&stateid->open->lock);
775 } else if (stateid->delegation) {
776 nfs41_delegation_state *deleg = stateid->delegation;
777 stateid4 *source = &deleg->state.stateid;
778 AcquireSRWLockShared(&deleg->lock);
779 if (memcmp(&stateid->stateid, source, sizeof(stateid4))) {
780 memcpy(&stateid->stateid, source, sizeof(stateid4));
781 retry = TRUE;
782 }
783 ReleaseSRWLockShared(&deleg->lock);
784 }
785 return retry;
786}
787
790 IN nfs_argop4 *argop)
791{
792 stateid_arg *stateid = NULL;
793
794 /* get the stateid_arg from the operation's arguments */
795 if (argop->op == OP_OPEN) {
797 if (open->claim->claim == CLAIM_DELEGATE_CUR)
798 stateid = open->claim->u.deleg_cur.delegate_stateid;
799 else if (open->claim->claim == CLAIM_DELEG_CUR_FH)
800 stateid = open->claim->u.deleg_cur_fh.delegate_stateid;
801 } else if (argop->op == OP_CLOSE) {
803 stateid = close->stateid;
804 } else if (argop->op == OP_READ) {
805 nfs41_read_args *read = (nfs41_read_args*)argop->arg;
806 stateid = read->stateid;
807 } else if (argop->op == OP_WRITE) {
809 stateid = write->stateid;
810 } else if (argop->op == OP_LOCK) {
811 nfs41_lock_args *lock = (nfs41_lock_args*)argop->arg;
812 if (lock->locker.new_lock_owner)
813 stateid = lock->locker.u.open_owner.open_stateid;
814 else
815 stateid = lock->locker.u.lock_owner.lock_stateid;
816 } else if (argop->op == OP_LOCKU) {
817 nfs41_locku_args *locku = (nfs41_locku_args*)argop->arg;
818 stateid = locku->lock_stateid;
819 } else if (argop->op == OP_SETATTR) {
820 nfs41_setattr_args *setattr = (nfs41_setattr_args*)argop->arg;
821 stateid = setattr->stateid;
822 } else if (argop->op == OP_LAYOUTGET) {
823 pnfs_layoutget_args *lget = (pnfs_layoutget_args*)argop->arg;
824 stateid = lget->stateid;
825 } else if (argop->op == OP_DELEGRETURN) {
827 stateid = dr->stateid;
828 }
829 if (stateid == NULL)
830 return FALSE;
831
832 /* if there's recovery in progress, wait for it to finish */
833 EnterCriticalSection(&session->client->recovery.lock);
834 while (session->client->recovery.in_recovery)
835 SleepConditionVariableCS(&session->client->recovery.cond,
836 &session->client->recovery.lock, INFINITE);
837 LeaveCriticalSection(&session->client->recovery.lock);
838
839 switch (stateid->type) {
840 case STATEID_OPEN:
841 return recover_stateid_open(argop, stateid);
842
843 case STATEID_LOCK:
844 return recover_stateid_lock(argop, stateid);
845
847 return recover_stateid_delegation(argop, stateid);
848
849 default:
850 eprintf("%s can't recover stateid type %u\n",
851 nfs_opnum_to_string(argop->op), stateid->type);
852 break;
853 }
854 return FALSE;
855}
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
#define read
Definition: acwin.h:96
#define open
Definition: acwin.h:95
#define close
Definition: acwin.h:98
#define write
Definition: acwin.h:97
static int state
Definition: maze.c:121
#define list_container(entry, type, field)
Definition: list.h:33
#define list_for_each(entry, head)
Definition: list.h:36
static int list_empty(struct list_entry *head)
Definition: list.h:58
static void list_init(struct list_entry *head)
Definition: list.h:51
bool_t nfs41_recover_stateid(IN nfs41_session *session, IN nfs_argop4 *argop)
Definition: recovery.c:788
void nfs41_client_state_revoked(IN nfs41_session *session, IN nfs41_client *client, IN uint32_t revoked)
Definition: recovery.c:633
static uint32_t stateid_array(IN struct list_entry *delegations, IN struct list_entry *opens, OUT stateid_arg **stateids_out, OUT uint32_t **statuses_out)
Definition: recovery.c:547
int nfs41_recover_client_state(IN nfs41_session *session, IN nfs41_client *client)
Definition: recovery.c:487
void nfs41_recovery_finish(IN nfs41_client *client)
Definition: recovery.c:57
static int recover_delegation(IN nfs41_session *session, IN nfs41_delegation_state *deleg, IN OUT bool_t *grace, IN OUT bool_t *want_supported)
Definition: recovery.c:460
static int recover_locks(IN nfs41_session *session, IN nfs41_open_state *open, IN OUT bool_t *grace)
Definition: recovery.c:281
static int recover_delegation_want(IN nfs41_session *session, IN nfs41_delegation_state *deleg, IN OUT bool_t *grace)
Definition: recovery.c:338
static int recover_open_no_grace(IN nfs41_session *session, IN nfs41_path_fh *parent, IN nfs41_path_fh *file, IN state_owner4 *owner, IN uint32_t access, IN uint32_t deny, OUT stateid4 *stateid, OUT open_delegation4 *delegation)
Definition: recovery.c:157
static int recover_open(IN nfs41_session *session, IN nfs41_open_state *open, IN OUT bool_t *grace)
Definition: recovery.c:202
int nfs41_recover_session(IN nfs41_session *session, IN bool_t client_state_lost)
Definition: recovery.c:69
bool_t nfs41_recovery_start_or_wait(IN nfs41_client *client)
Definition: recovery.c:34
static int recover_delegation_open(IN nfs41_session *session, IN nfs41_delegation_state *deleg, IN OUT bool_t *grace)
Definition: recovery.c:396
static int recover_open_grace(IN nfs41_session *session, IN nfs41_path_fh *parent, IN nfs41_path_fh *file, IN state_owner4 *owner, IN uint32_t access, IN uint32_t deny, OUT stateid4 *stateid, OUT open_delegation4 *delegation)
Definition: recovery.c:138
static bool_t recover_stateid_delegation(IN nfs_argop4 *argop, IN stateid_arg *stateid)
Definition: recovery.c:752
static bool_t recover_stateid_open(IN nfs_argop4 *argop, IN stateid_arg *stateid)
Definition: recovery.c:703
void nfs41_recover_sequence_flags(IN nfs41_session *session, IN uint32_t flags)
Definition: recovery.c:98
static bool_t recover_stateid_lock(IN nfs_argop4 *argop, IN stateid_arg *stateid)
Definition: recovery.c:723
void eprintf(LPCSTR format,...)
Definition: daemon_debug.c:86
const char * nfs_opnum_to_string(int opnum)
Definition: daemon_debug.c:305
#define free
Definition: debug_ros.c:5
int nfs41_client_delegation_recovery(IN nfs41_client *client)
Definition: delegation.c:861
int nfs41_delegation_granted(IN nfs41_session *session, IN nfs41_path_fh *parent, IN nfs41_path_fh *file, IN open_delegation4 *delegation, IN bool_t try_recovery, OUT nfs41_delegation_state **deleg_out)
Definition: delegation.c:330
#define open_entry(pos)
Definition: delegation.c:89
#define NULL
Definition: types.h:112
int32_t bool_t
Definition: types.h:101
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
UINT32 uint32_t
Definition: types.h:75
static const WCHAR empty[]
Definition: main.c:47
VOID WINAPI ReleaseSRWLockShared(PSRWLOCK Lock)
Definition: sync.c:89
VOID WINAPI AcquireSRWLockExclusive(PSRWLOCK Lock)
Definition: sync.c:54
VOID WINAPI AcquireSRWLockShared(PSRWLOCK Lock)
Definition: sync.c:61
VOID WINAPI ReleaseSRWLockExclusive(PSRWLOCK Lock)
Definition: sync.c:82
BOOL WINAPI SleepConditionVariableCS(PCONDITION_VARIABLE ConditionVariable, PCRITICAL_SECTION CriticalSection, DWORD Timeout)
Definition: sync.c:105
VOID WINAPI WakeAllConditionVariable(PCONDITION_VARIABLE ConditionVariable)
Definition: sync.c:137
r parent
Definition: btrfs.c:3010
__kernel_time_t time_t
Definition: linux.h:252
#define INFINITE
Definition: serial.h:102
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLbitfield flags
Definition: glext.h:7161
GLuint GLint GLboolean GLint GLenum access
Definition: glext.h:7866
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
uint32_t entry
Definition: isohybrid.c:63
if(dx< 0)
Definition: linetemp.h:194
__u16 time
Definition: mkdosfs.c:8
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define client_entry(pos)
Definition: namespace.c:33
int nfs41_session_renew(IN nfs41_session *session)
int nfs41_client_renew(IN nfs41_client *client)
Definition: nfs41_client.c:168
nfsstat4
Definition: nfs41_const.h:86
@ NFS4ERR_BAD_STATEID
Definition: nfs41_const.h:132
@ NFS4ERR_NOTSUPP
Definition: nfs41_const.h:109
@ NFS4ERR_BADSESSION
Definition: nfs41_const.h:161
@ NFS4ERR_STALE_CLIENTID
Definition: nfs41_const.h:129
@ NFS4_OK
Definition: nfs41_const.h:87
@ NFS4ERR_NO_GRACE
Definition: nfs41_const.h:140
@ NFS4ERR_BADHANDLE
Definition: nfs41_const.h:107
int nfs41_open(IN nfs41_session *session, IN nfs41_path_fh *parent, IN nfs41_path_fh *file, IN state_owner4 *owner, IN open_claim4 *claim, IN uint32_t allow, IN uint32_t deny, IN uint32_t create, IN uint32_t how_mode, IN OPTIONAL nfs41_file_info *createattrs, IN bool_t try_recovery, OUT stateid4 *stateid, OUT open_delegation4 *delegation, OUT OPTIONAL nfs41_file_info *info)
Definition: nfs41_ops.c:366
enum nfsstat4 nfs41_free_stateid(IN nfs41_session *session, IN stateid4 *stateid)
Definition: nfs41_ops.c:1870
int nfs41_lock(IN nfs41_session *session, IN nfs41_path_fh *file, IN state_owner4 *owner, IN uint32_t type, IN uint64_t offset, IN uint64_t length, IN bool_t reclaim, IN bool_t try_recovery, IN OUT stateid_arg *stateid)
Definition: nfs41_ops.c:904
enum nfsstat4 nfs41_test_stateid(IN nfs41_session *session, IN stateid_arg *stateid_array, IN uint32_t count, OUT uint32_t *status_array)
Definition: nfs41_ops.c:1900
enum nfsstat4 nfs41_want_delegation(IN nfs41_session *session, IN nfs41_path_fh *file, IN deleg_claim4 *claim, IN uint32_t want, IN bool_t try_recovery, OUT open_delegation4 *delegation)
Definition: nfs41_ops.c:1624
enum nfsstat4 nfs41_reclaim_complete(IN nfs41_session *session)
Definition: nfs41_ops.c:268
int nfs41_close(IN nfs41_session *session, IN nfs41_path_fh *file, IN stateid_arg *stateid)
Definition: nfs41_ops.c:627
@ OPEN_DELEGATE_NONE
Definition: nfs41_ops.h:586
@ OPEN_DELEGATE_READ
Definition: nfs41_ops.h:587
@ OPEN_DELEGATE_WRITE
Definition: nfs41_ops.h:588
@ OPEN4_NOCREATE
Definition: nfs41_ops.h:553
@ SEQ4_STATUS_EXPIRED_SOME_STATE_REVOKED
Definition: nfs41_ops.h:241
@ SEQ4_STATUS_RESTART_RECLAIM_NEEDED
Definition: nfs41_ops.h:245
@ SEQ4_STATUS_ADMIN_STATE_REVOKED
Definition: nfs41_ops.h:242
@ SEQ4_STATUS_EXPIRED_ALL_STATE_REVOKED
Definition: nfs41_ops.h:240
@ SEQ4_STATUS_RECALLABLE_STATE_REVOKED
Definition: nfs41_ops.h:243
@ OP_WRITE
Definition: nfs41_ops.h:66
@ OP_SETATTR
Definition: nfs41_ops.h:62
@ OP_OPEN
Definition: nfs41_ops.h:46
@ OP_LOCKU
Definition: nfs41_ops.h:42
@ OP_LAYOUTGET
Definition: nfs41_ops.h:80
@ OP_CLOSE
Definition: nfs41_ops.h:32
@ OP_READ
Definition: nfs41_ops.h:53
@ OP_LOCK
Definition: nfs41_ops.h:40
@ OP_DELEGRETURN
Definition: nfs41_ops.h:36
@ STATEID_LAYOUT
Definition: nfs41_ops.h:280
@ STATEID_LOCK
Definition: nfs41_ops.h:277
@ STATEID_DELEG_FILE
Definition: nfs41_ops.h:278
@ STATEID_OPEN
Definition: nfs41_ops.h:276
@ READ_LT
Definition: nfs41_ops.h:399
@ WRITE_LT
Definition: nfs41_ops.h:400
@ OPEN4_SHARE_ACCESS_WANT_READ_DELEG
Definition: nfs41_ops.h:575
@ OPEN4_SHARE_ACCESS_WRITE
Definition: nfs41_ops.h:565
@ OPEN4_SHARE_ACCESS_WANT_WRITE_DELEG
Definition: nfs41_ops.h:576
@ OPEN4_SHARE_DENY_NONE
Definition: nfs41_ops.h:568
@ OPEN4_SHARE_ACCESS_READ
Definition: nfs41_ops.h:564
@ CLAIM_NULL
Definition: nfs41_ops.h:593
@ CLAIM_PREVIOUS
Definition: nfs41_ops.h:594
@ CLAIM_DELEG_CUR_FH
Definition: nfs41_ops.h:598
@ CLAIM_DELEGATE_CUR
Definition: nfs41_ops.h:595
@ CLAIM_DELEGATE_PREV
Definition: nfs41_ops.h:596
@ CLAIM_DELEG_PREV_FH
Definition: nfs41_ops.h:599
enum pnfs_status pnfs_file_layout_recall(IN struct __nfs41_client *client, IN const struct cb_layoutrecall_args *recall)
@ PNFS_IOMODE_ANY
Definition: pnfs.h:83
@ PNFS_LAYOUTTYPE_FILE
Definition: pnfs.h:75
@ PNFS_RETURN_ALL
Definition: pnfs.h:103
#define dprintf
Definition: regdump.c:33
static FILE * out
Definition: regtests2xml.c:44
#define calloc
Definition: rosglue.h:14
#define memset(x, y, z)
Definition: compat.h:39
static FILE * client
Definition: client.c:41
uint32_t claim
Definition: nfs41_ops.h:794
uint32_t prev_delegate_type
Definition: nfs41_ops.h:796
open_delegation4 state
Definition: nfs41.h:96
stateid_arg * stateid
Definition: nfs41_ops.h:377
stateid_arg * lock_stateid
Definition: nfs41_ops.h:478
stateid_arg * stateid
Definition: nfs41_ops.h:782
struct __open_claim4::@41::__open_claim_null null
uint32_t claim
Definition: nfs41_ops.h:615
union __open_claim4::@41 u
struct __open_claim4::@41::__open_claim_deleg_prev deleg_prev
struct __open_claim4::@41::__open_claim_prev prev
enum open_delegation_type4 type
Definition: nfs41_types.h:154
stateid_arg * stateid
Definition: nfs41_ops.h:912
unsigned char owner[NFS4_OPAQUE_LIMIT]
Definition: nfs41_types.h:119
uint32_t owner_len
Definition: nfs41_types.h:118
enum stateid_type type
Definition: nfs41_ops.h:285
nfs41_open_state * open
Definition: nfs41_ops.h:286
stateid4 stateid
Definition: nfs41_ops.h:284
nfs41_delegation_state * delegation
Definition: nfs41_ops.h:287
struct cb_recall recall
CRITICAL_SECTION lock
Definition: nfs41.h:189
struct list_entry opens
Definition: nfs41.h:187
struct list_entry delegations
Definition: nfs41.h:188
Definition: fci.c:127
char name[1]
Definition: fci.c:135
Definition: list.h:27
Definition: ps.c:97
rwlock_t lock
Definition: tcpcore.h:0
#define IN
Definition: typedefs.h:39
#define OUT
Definition: typedefs.h:40
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)