ReactOS 0.4.15-dev-7928-g68a8619
recovery.c File Reference
#include <time.h>
#include "recovery.h"
#include "delegation.h"
#include "nfs41_callback.h"
#include "nfs41_compound.h"
#include "nfs41_ops.h"
#include "daemon_debug.h"
Include dependency graph for recovery.c:

Go to the source code of this file.

Functions

bool_t nfs41_recovery_start_or_wait (IN nfs41_client *client)
 
void nfs41_recovery_finish (IN nfs41_client *client)
 
int nfs41_recover_session (IN nfs41_session *session, IN bool_t client_state_lost)
 
void nfs41_recover_sequence_flags (IN nfs41_session *session, IN uint32_t flags)
 
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)
 
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)
 
static int recover_open (IN nfs41_session *session, IN nfs41_open_state *open, IN OUT bool_t *grace)
 
static int recover_locks (IN nfs41_session *session, IN nfs41_open_state *open, IN OUT bool_t *grace)
 
static int recover_delegation_want (IN nfs41_session *session, IN nfs41_delegation_state *deleg, IN OUT bool_t *grace)
 
static int recover_delegation_open (IN nfs41_session *session, IN nfs41_delegation_state *deleg, IN OUT bool_t *grace)
 
static int recover_delegation (IN nfs41_session *session, IN nfs41_delegation_state *deleg, IN OUT bool_t *grace, IN OUT bool_t *want_supported)
 
int nfs41_recover_client_state (IN nfs41_session *session, IN nfs41_client *client)
 
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)
 
void nfs41_client_state_revoked (IN nfs41_session *session, IN nfs41_client *client, IN uint32_t revoked)
 
static bool_t recover_stateid_open (IN nfs_argop4 *argop, IN stateid_arg *stateid)
 
static bool_t recover_stateid_lock (IN nfs_argop4 *argop, IN stateid_arg *stateid)
 
static bool_t recover_stateid_delegation (IN nfs_argop4 *argop, IN stateid_arg *stateid)
 
bool_t nfs41_recover_stateid (IN nfs41_session *session, IN nfs_argop4 *argop)
 

Function Documentation

◆ nfs41_client_state_revoked()

void nfs41_client_state_revoked ( IN nfs41_session session,
IN nfs41_client client,
IN uint32_t  revoked 
)

Definition at line 633 of file recovery.c.

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}
#define open
Definition: acwin.h:95
static void list_init(struct list_entry *head)
Definition: list.h:51
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
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_open(IN nfs41_session *session, IN nfs41_open_state *open, IN OUT bool_t *grace)
Definition: recovery.c:202
#define free
Definition: debug_ros.c:5
int nfs41_client_delegation_recovery(IN nfs41_client *client)
Definition: delegation.c:861
#define NULL
Definition: types.h:112
int32_t bool_t
Definition: types.h:101
#define TRUE
Definition: types.h:120
UINT32 uint32_t
Definition: types.h:75
static const WCHAR empty[]
Definition: main.c:47
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLuint GLuint GLsizei count
Definition: gl.h:1545
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
enum nfsstat4 nfs41_free_stateid(IN nfs41_session *session, IN stateid4 *stateid)
Definition: nfs41_ops.c:1870
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
@ STATEID_LOCK
Definition: nfs41_ops.h:277
@ STATEID_DELEG_FILE
Definition: nfs41_ops.h:278
@ STATEID_OPEN
Definition: nfs41_ops.h:276
@ SEQ4_STATUS_EXPIRED_ALL_STATE_REVOKED
Definition: nfs41_ops.h:240
@ SEQ4_STATUS_RECALLABLE_STATE_REVOKED
Definition: nfs41_ops.h:243
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
static FILE * out
Definition: regtests2xml.c:44
static FILE * client
Definition: client.c:41
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: list.h:27
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)

Referenced by nfs41_recover_sequence_flags().

◆ nfs41_recover_client_state()

int nfs41_recover_client_state ( IN nfs41_session session,
IN nfs41_client client 
)

Definition at line 487 of file recovery.c.

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}
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
uint32_t entry
Definition: isohybrid.c:63
#define client_entry(pos)
Definition: namespace.c:33
@ NFS4ERR_BADSESSION
Definition: nfs41_const.h:161
@ NFS4_OK
Definition: nfs41_const.h:87
enum nfsstat4 nfs41_reclaim_complete(IN nfs41_session *session)
Definition: nfs41_ops.c:268
Definition: ps.c:97

Referenced by nfs41_recover_sequence_flags(), and nfs41_recover_session().

◆ nfs41_recover_sequence_flags()

void nfs41_recover_sequence_flags ( IN nfs41_session session,
IN uint32_t  flags 
)

Definition at line 98 of file recovery.c.

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}
void nfs41_client_state_revoked(IN nfs41_session *session, IN nfs41_client *client, IN uint32_t revoked)
Definition: recovery.c:633
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
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
GLbitfield flags
Definition: glext.h:7161
@ 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

Referenced by compound_encode_send_decode().

◆ nfs41_recover_session()

int nfs41_recover_session ( IN nfs41_session session,
IN bool_t  client_state_lost 
)

Definition at line 69 of file recovery.c.

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}
void eprintf(LPCSTR format,...)
Definition: daemon_debug.c:86
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_STALE_CLIENTID
Definition: nfs41_const.h:129

Referenced by compound_encode_send_decode(), and nfs41_recover_sequence_flags().

◆ nfs41_recover_stateid()

bool_t nfs41_recover_stateid ( IN nfs41_session session,
IN nfs_argop4 argop 
)

Definition at line 788 of file recovery.c.

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}
#define read
Definition: acwin.h:96
#define close
Definition: acwin.h:98
#define write
Definition: acwin.h:97
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
static bool_t recover_stateid_lock(IN nfs_argop4 *argop, IN stateid_arg *stateid)
Definition: recovery.c:723
const char * nfs_opnum_to_string(int opnum)
Definition: daemon_debug.c:305
#define FALSE
Definition: types.h:117
BOOL WINAPI SleepConditionVariableCS(PCONDITION_VARIABLE ConditionVariable, PCRITICAL_SECTION CriticalSection, DWORD Timeout)
Definition: sync.c:105
#define INFINITE
Definition: serial.h:102
if(dx< 0)
Definition: linetemp.h:194
@ 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
@ CLAIM_DELEG_CUR_FH
Definition: nfs41_ops.h:598
@ CLAIM_DELEGATE_CUR
Definition: nfs41_ops.h:595
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
stateid_arg * stateid
Definition: nfs41_ops.h:912
enum stateid_type type
Definition: nfs41_ops.h:285
rwlock_t lock
Definition: tcpcore.h:0

Referenced by compound_encode_send_decode().

◆ nfs41_recovery_finish()

void nfs41_recovery_finish ( IN nfs41_client client)

Definition at line 57 of file recovery.c.

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}
VOID WINAPI WakeAllConditionVariable(PCONDITION_VARIABLE ConditionVariable)
Definition: sync.c:137
#define dprintf
Definition: regdump.c:33

Referenced by compound_encode_send_decode(), and nfs41_recover_sequence_flags().

◆ nfs41_recovery_start_or_wait()

bool_t nfs41_recovery_start_or_wait ( IN nfs41_client client)

Definition at line 34 of file recovery.c.

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}

Referenced by compound_encode_send_decode(), and nfs41_recover_sequence_flags().

◆ recover_delegation()

static int recover_delegation ( IN nfs41_session session,
IN nfs41_delegation_state deleg,
IN OUT bool_t grace,
IN OUT bool_t want_supported 
)
static

Definition at line 460 of file recovery.c.

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}
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_delegation_open(IN nfs41_session *session, IN nfs41_delegation_state *deleg, IN OUT bool_t *grace)
Definition: recovery.c:396
@ NFS4ERR_NOTSUPP
Definition: nfs41_const.h:109

Referenced by nfs41_client_state_revoked(), and nfs41_recover_client_state().

◆ recover_delegation_open()

static int recover_delegation_open ( IN nfs41_session session,
IN nfs41_delegation_state deleg,
IN OUT bool_t grace 
)
static

Definition at line 396 of file recovery.c.

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}
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_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
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
__kernel_time_t time_t
Definition: linux.h:252
GLuint GLint GLboolean GLint GLenum access
Definition: glext.h:7866
__u16 time
Definition: mkdosfs.c:8
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
@ NFS4ERR_NO_GRACE
Definition: nfs41_const.h:140
int nfs41_close(IN nfs41_session *session, IN nfs41_path_fh *file, IN stateid_arg *stateid)
Definition: nfs41_ops.c:627
@ 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
@ OPEN_DELEGATE_READ
Definition: nfs41_ops.h:587
@ OPEN_DELEGATE_WRITE
Definition: nfs41_ops.h:588
enum open_delegation_type4 type
Definition: nfs41_types.h:154
unsigned char owner[NFS4_OPAQUE_LIMIT]
Definition: nfs41_types.h:119
uint32_t owner_len
Definition: nfs41_types.h:118
nfs41_open_state * open
Definition: nfs41_ops.h:286
stateid4 stateid
Definition: nfs41_ops.h:284

Referenced by recover_delegation().

◆ recover_delegation_want()

static int recover_delegation_want ( IN nfs41_session session,
IN nfs41_delegation_state deleg,
IN OUT bool_t grace 
)
static

Definition at line 338 of file recovery.c.

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}
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
@ CLAIM_PREVIOUS
Definition: nfs41_ops.h:594
@ CLAIM_DELEG_PREV_FH
Definition: nfs41_ops.h:599
uint32_t claim
Definition: nfs41_ops.h:794
uint32_t prev_delegate_type
Definition: nfs41_ops.h:796

Referenced by recover_delegation().

◆ recover_locks()

static int recover_locks ( IN nfs41_session session,
IN nfs41_open_state open,
IN OUT bool_t grace 
)
static

Definition at line 281 of file recovery.c.

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}
#define open_entry(pos)
Definition: delegation.c:89
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
@ READ_LT
Definition: nfs41_ops.h:399
@ WRITE_LT
Definition: nfs41_ops.h:400

Referenced by nfs41_client_state_revoked(), and nfs41_recover_client_state().

◆ recover_open()

static int recover_open ( IN nfs41_session session,
IN nfs41_open_state open,
IN OUT bool_t grace 
)
static

Definition at line 202 of file recovery.c.

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}
static int list_empty(struct list_entry *head)
Definition: list.h:58
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
@ NFS4ERR_BADHANDLE
Definition: nfs41_const.h:107
open_delegation4 state
Definition: nfs41.h:96

Referenced by nfs41_client_state_revoked(), and nfs41_recover_client_state().

◆ recover_open_grace()

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 
)
static

Definition at line 138 of file recovery.c.

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}
r parent
Definition: btrfs.c:3010
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
@ OPEN4_NOCREATE
Definition: nfs41_ops.h:553
uint32_t claim
Definition: nfs41_ops.h:615
struct __open_claim4::@50::__open_claim_prev prev
union __open_claim4::@50 u
Definition: fci.c:127

Referenced by recover_delegation_open(), and recover_open().

◆ recover_open_no_grace()

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 
)
static

Definition at line 157 of file recovery.c.

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}
@ OPEN_DELEGATE_NONE
Definition: nfs41_ops.h:586
@ CLAIM_NULL
Definition: nfs41_ops.h:593
@ CLAIM_DELEGATE_PREV
Definition: nfs41_ops.h:596
struct __open_claim4::@50::__open_claim_null null
struct __open_claim4::@50::__open_claim_deleg_prev deleg_prev
char name[1]
Definition: fci.c:135

Referenced by recover_delegation_open(), and recover_open().

◆ recover_stateid_delegation()

static bool_t recover_stateid_delegation ( IN nfs_argop4 argop,
IN stateid_arg stateid 
)
static

Definition at line 752 of file recovery.c.

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}
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112

Referenced by nfs41_recover_stateid().

◆ recover_stateid_lock()

static bool_t recover_stateid_lock ( IN nfs_argop4 argop,
IN stateid_arg stateid 
)
static

Definition at line 723 of file recovery.c.

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}

Referenced by nfs41_recover_stateid().

◆ recover_stateid_open()

static bool_t recover_stateid_open ( IN nfs_argop4 argop,
IN stateid_arg stateid 
)
static

Definition at line 703 of file recovery.c.

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}

Referenced by nfs41_recover_stateid().

◆ stateid_array()

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 
)
static

Definition at line 547 of file recovery.c.

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}
@ NFS4ERR_BAD_STATEID
Definition: nfs41_const.h:132
@ STATEID_LAYOUT
Definition: nfs41_ops.h:280
#define calloc
Definition: rosglue.h:14
#define memset(x, y, z)
Definition: compat.h:39

Referenced by nfs41_client_state_revoked(), and nfs41_test_stateid().