ReactOS 0.4.16-dev-122-g325d74c
delegation.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 "delegation.h"
23#include "nfs41_ops.h"
24#include "name_cache.h"
25#include "util.h"
26#include "daemon_debug.h"
27
28#include <devioctl.h>
29#include "nfs41_driver.h" /* for making downcall to invalidate cache */
30#include "util.h"
31
32#define DGLVL 2 /* dprintf level for delegation logging */
33
34
35/* allocation and reference counting */
37 IN const nfs41_path_fh *parent,
38 IN const nfs41_path_fh *file,
39 IN const open_delegation4 *delegation,
40 OUT nfs41_delegation_state **deleg_out)
41{
43 int status = NO_ERROR;
44
46 if (state == NULL) {
48 goto out;
49 }
50
51 memcpy(&state->state, delegation, sizeof(open_delegation4));
52
53 abs_path_copy(&state->path, file->path);
54 path_fh_init(&state->file, &state->path);
55 fh_copy(&state->file.fh, &file->fh);
56 path_fh_init(&state->parent, &state->path);
57 last_component(state->path.path, state->file.name.name,
58 &state->parent.name);
59 fh_copy(&state->parent.fh, &parent->fh);
60
61 list_init(&state->client_entry);
62 state->status = DELEGATION_GRANTED;
65 state->ref_count = 1;
66 *deleg_out = state;
67out:
68 return status;
69}
70
73{
74 const LONG count = InterlockedIncrement(&state->ref_count);
75 dprintf(DGLVL, "nfs41_delegation_ref(%s) count %d\n",
76 state->path.path, count);
77}
78
81{
82 const LONG count = InterlockedDecrement(&state->ref_count);
83 dprintf(DGLVL, "nfs41_delegation_deref(%s) count %d\n",
84 state->path.path, count);
85 if (count == 0)
86 free(state);
87}
88
89#define open_entry(pos) list_container(pos, nfs41_open_state, client_entry)
90
94{
95 struct list_entry *entry;
96
97 /* remove from the client's list */
98 EnterCriticalSection(&client->state.lock);
99 list_remove(&deleg->client_entry);
100
101 /* remove from each associated open */
102 list_for_each(entry, &client->state.opens) {
105 if (open->delegation.state == deleg) {
106 /* drop the delegation reference */
107 nfs41_delegation_deref(open->delegation.state);
108 open->delegation.state = NULL;
109 }
111 }
112 LeaveCriticalSection(&client->state.lock);
113
114 /* signal threads waiting on delegreturn */
115 AcquireSRWLockExclusive(&deleg->lock);
116 deleg->status = DELEGATION_RETURNED;
117 WakeAllConditionVariable(&deleg->cond);
118 ReleaseSRWLockExclusive(&deleg->lock);
119
120 /* release the client's reference */
122}
123
124
125/* delegation return */
126#define lock_entry(pos) list_container(pos, nfs41_lock_state, open_entry)
127
130{
131 struct list_entry *entry;
132 list_for_each(entry, &open->locks.list) {
133 if (lock_entry(entry)->delegated)
134 return TRUE;
135 }
136 return FALSE;
137}
138
139static int open_deleg_cmp(const struct list_entry *entry, const void *value)
140{
142 int result = -1;
143
144 /* open must match the delegation and have state to reclaim */
146 if (open->delegation.state != value) goto out;
147 if (open->do_close && !has_delegated_locks(open)) goto out;
148 result = 0;
149out:
151 return result;
152}
153
154/* find the first open that needs recovery */
156 IN struct client_state *state,
157 IN const nfs41_delegation_state *deleg)
158{
159 struct list_entry *entry;
161
163 entry = list_search(&state->opens, deleg, open_deleg_cmp);
164 if (entry) {
166 nfs41_open_state_ref(open); /* return a reference */
167 }
169 return open;
170}
171
172/* find the first lock that needs recovery */
175 OUT nfs41_lock_state *lock_out)
176{
177 struct list_entry *entry;
178 bool_t found = FALSE;
179
181 list_for_each(entry, &open->locks.list) {
183 if (lock->delegated) {
184 /* copy offset, length, type */
185 lock_out->offset = lock->offset;
186 lock_out->length = lock->length;
187 lock_out->exclusive = lock->exclusive;
188 lock_out->id = lock->id;
189 found = TRUE;
190 break;
191 }
192 }
194 return found;
195}
196
197/* find the matching lock by id, and reset lock.delegated */
201{
202 struct list_entry *entry;
203
205 list_for_each(entry, &open->locks.list) {
207 if (lock->id == source->id) {
208 lock->delegated = FALSE;
209 break;
210 }
211 }
213}
214
217 IN bool_t try_recovery)
218{
219 stateid_arg stateid;
221 int status = NFS4_OK;
222
223 stateid.open = open;
224 stateid.delegation = NULL;
225
226 /* get the starting open/lock stateid */
228 if (open->locks.stateid.seqid) {
229 memcpy(&stateid.stateid, &open->locks.stateid, sizeof(stateid4));
230 stateid.type = STATEID_LOCK;
231 } else {
232 memcpy(&stateid.stateid, &open->stateid, sizeof(stateid4));
233 stateid.type = STATEID_OPEN;
234 }
236
237 /* send LOCK requests for each delegated lock range */
238 while (deleg_lock_find(open, &lock)) {
239 status = nfs41_lock(open->session, &open->file,
240 &open->owner, lock.exclusive ? WRITE_LT : READ_LT,
241 lock.offset, lock.length, FALSE, try_recovery, &stateid);
242 if (status)
243 break;
245 }
246
247 /* save the updated lock stateid */
248 if (stateid.type == STATEID_LOCK) {
250 if (open->locks.stateid.seqid == 0) {
251 /* if it's a new lock stateid, copy it in */
252 memcpy(&open->locks.stateid, &stateid.stateid, sizeof(stateid4));
253 } else if (stateid.stateid.seqid > open->locks.stateid.seqid) {
254 /* update the seqid if it's more recent */
255 open->locks.stateid.seqid = stateid.stateid.seqid;
256 }
258 }
259 return status;
260}
261
262#pragma warning (disable : 4706) /* assignment within conditional expression */
263
267 IN bool_t truncate,
268 IN bool_t try_recovery)
269{
270 stateid_arg stateid;
272 int status;
273
274 if (deleg->srv_open) {
275 /* make an upcall to the kernel: invalide data cache */
276 HANDLE pipe;
277 unsigned char inbuf[sizeof(HANDLE)], *buffer = inbuf;
278 DWORD inbuf_len = sizeof(HANDLE), outbuf_len, dstatus;
280 dprintf(1, "delegation_return: making a downcall for srv_open=%x\n",
281 deleg->srv_open);
284 if (pipe == INVALID_HANDLE_VALUE) {
285 eprintf("delegation_return: Unable to open downcall pipe %d\n",
286 GetLastError());
287 goto out_downcall;
288 }
289 length = inbuf_len;
290 safe_write(&buffer, &length, &deleg->srv_open, sizeof(HANDLE));
291
292 dstatus = DeviceIoControl(pipe, IOCTL_NFS41_INVALCACHE, inbuf, inbuf_len,
293 NULL, 0, (LPDWORD)&outbuf_len, NULL);
294 if (!dstatus)
295 eprintf("IOCTL_NFS41_INVALCACHE failed %d\n", GetLastError());
296 CloseHandle(pipe);
297 }
298out_downcall:
299
300 /* recover opens and locks associated with the delegation */
301 while (open = deleg_open_find(&client->state, deleg)) {
302 status = nfs41_delegation_to_open(open, try_recovery);
303 if (status == NFS4_OK)
304 status = delegation_flush_locks(open, try_recovery);
306
307 if (status)
308 break;
309 }
310
311 /* return the delegation */
312 stateid.type = STATEID_DELEG_FILE;
313 stateid.open = NULL;
314 stateid.delegation = deleg;
315 AcquireSRWLockShared(&deleg->lock);
316 memcpy(&stateid.stateid, &deleg->state.stateid, sizeof(stateid4));
317 ReleaseSRWLockShared(&deleg->lock);
318
320 &deleg->file, &stateid, try_recovery);
322 goto out;
323
325out:
326 return status;
327}
328
329/* open delegation */
334 IN open_delegation4 *delegation,
335 IN bool_t try_recovery,
336 OUT nfs41_delegation_state **deleg_out)
337{
338 stateid_arg stateid;
339 nfs41_client *client = session->client;
341 int status = NO_ERROR;
342
343 if (delegation->type != OPEN_DELEGATE_READ &&
344 delegation->type != OPEN_DELEGATE_WRITE)
345 goto out;
346
347 if (delegation->recalled) {
349 goto out_return;
350 }
351
352 /* allocate the delegation state */
353 status = delegation_create(parent, file, delegation, &state);
354 if (status)
355 goto out_return;
356
357 /* register the delegation with the client */
358 EnterCriticalSection(&client->state.lock);
359 /* XXX: check for duplicates by fh and stateid? */
360 list_add_tail(&client->state.delegations, &state->client_entry);
361 LeaveCriticalSection(&client->state.lock);
362
363 nfs41_delegation_ref(state); /* return a reference */
364 *deleg_out = state;
365out:
366 return status;
367
368out_return: /* return the delegation on failure */
369 memcpy(&stateid.stateid, &delegation->stateid, sizeof(stateid4));
370 stateid.type = STATEID_DELEG_FILE;
371 stateid.open = NULL;
372 stateid.delegation = NULL;
373 nfs41_delegreturn(session, file, &stateid, try_recovery);
374 goto out;
375}
376
377#define deleg_entry(pos) list_container(pos, nfs41_delegation_state, client_entry)
378
379static int deleg_file_cmp(const struct list_entry *entry, const void *value)
380{
381 const nfs41_fh *lhs = &deleg_entry(entry)->file.fh;
382 const nfs41_fh *rhs = (const nfs41_fh*)value;
383 if (lhs->superblock != rhs->superblock) return -1;
384 if (lhs->fileid != rhs->fileid) return -1;
385 return 0;
386}
387
392 IN uint32_t deny)
393{
394 switch (type) {
396 /* An OPEN_DELEGATE_WRITE delegation allows the client to handle,
397 * on its own, all opens. */
398 return TRUE;
399
401 /* An OPEN_DELEGATE_READ delegation allows a client to handle,
402 * on its own, requests to open a file for reading that do not
403 * deny OPEN4_SHARE_ACCESS_READ access to others. */
404 if (create == OPEN4_CREATE)
405 return FALSE;
407 return FALSE;
408 return TRUE;
409
410 default:
411 return FALSE;
412 }
413}
414
417 IN const void *value,
419 OUT nfs41_delegation_state **deleg_out)
420{
421 struct list_entry *entry;
423
424 EnterCriticalSection(&client->state.lock);
425 entry = list_search(&client->state.delegations, value, cmp);
426 if (entry) {
427 /* return a reference to the delegation */
428 *deleg_out = deleg_entry(entry);
429 nfs41_delegation_ref(*deleg_out);
430
431 /* move to the 'most recently used' end of the list */
433 list_add_tail(&client->state.delegations, entry);
434 status = NFS4_OK;
435 }
436 LeaveCriticalSection(&client->state.lock);
437 return status;
438}
439
443 IN stateid_arg *stateid,
445{
446 nfs41_superblock *superblock = deleg->file.fh.superblock;
447
448 /* use SETATTR to truncate the file */
449 info->attrmask.arr[1] |= FATTR4_WORD1_TIME_CREATE |
451
452 get_nfs_time(&info->time_create);
453 get_nfs_time(&info->time_modify);
454 info->time_delta = &superblock->time_delta;
455
456 /* mask out unsupported attributes */
458
459 return nfs41_setattr(client->session, &deleg->file, stateid, info);
460}
461
465 IN OPTIONAL nfs41_file_info *createattrs,
467{
468 nfs41_client *client = state->session->client;
469 nfs41_path_fh *file = &state->file;
470 uint32_t access = state->share_access;
471 uint32_t deny = state->share_deny;
473 stateid_arg stateid;
474 int status;
475
476 /* search for a delegation with this filehandle */
478 if (status)
479 goto out;
480
482 if (deleg->status != DELEGATION_GRANTED) {
483 /* the delegation is being returned, wait for it to finish */
484 while (deleg->status != DELEGATION_RETURNED)
485 SleepConditionVariableSRW(&deleg->cond, &deleg->lock, INFINITE, 0);
487 }
488 else if (!delegation_compatible(deleg->state.type, create, access, deny)) {
489#ifdef DELEGATION_RETURN_ON_CONFLICT
490 /* this open will conflict, start the delegation return */
493#else
495#endif
496 } else if (create == OPEN4_CREATE) {
497 /* copy the stateid for SETATTR */
498 stateid.open = NULL;
499 stateid.delegation = deleg;
500 stateid.type = STATEID_DELEG_FILE;
501 memcpy(&stateid.stateid, &deleg->state.stateid, sizeof(stateid4));
502 }
503 if (!status) {
504 dprintf(1, "nfs41_delegate_open: updating srv_open from %x to %x\n",
505 deleg->srv_open, state->srv_open);
506 deleg->srv_open = state->srv_open;
507 }
509
511 goto out_return;
512 if (status)
513 goto out_deleg;
514
515 if (create == OPEN4_CREATE) {
516 memcpy(info, createattrs, sizeof(nfs41_file_info));
517
518 /* write delegations allow us to simulate OPEN4_CREATE with SETATTR */
519 status = delegation_truncate(deleg, client, &stateid, info);
520 if (status)
521 goto out_deleg;
522 }
523
524 /* TODO: check access against deleg->state.permissions or send ACCESS */
525
526 state->delegation.state = deleg;
527 status = NFS4_OK;
528out:
529 return status;
530
531out_return:
533
534out_deleg:
536 goto out;
537}
538
541 IN bool_t try_recovery)
542{
543 open_delegation4 ignore;
544 open_claim4 claim;
545 stateid4 open_stateid = { 0 };
546 stateid_arg deleg_stateid;
547 int status = NFS4_OK;
548
550 if (open->delegation.state == NULL) /* no delegation to reclaim */
551 goto out_unlock;
552
553 if (open->do_close) /* already have an open stateid */
554 goto out_unlock;
555
556 /* if another thread is reclaiming the open stateid,
557 * wait for it to finish before returning success */
558 if (open->delegation.reclaim) {
559 do {
560 SleepConditionVariableSRW(&open->delegation.cond, &open->lock,
561 INFINITE, 0);
562 } while (open->delegation.reclaim);
563 if (open->do_close)
564 goto out_unlock;
565 }
566 open->delegation.reclaim = 1;
567
568 AcquireSRWLockShared(&open->delegation.state->lock);
569 deleg_stateid.open = open;
570 deleg_stateid.delegation = NULL;
571 deleg_stateid.type = STATEID_DELEG_FILE;
572 memcpy(&deleg_stateid.stateid, &open->delegation.state->state.stateid,
573 sizeof(stateid4));
574 ReleaseSRWLockShared(&open->delegation.state->lock);
575
577
578 /* send OPEN with CLAIM_DELEGATE_CUR */
580 claim.u.deleg_cur.delegate_stateid = &deleg_stateid;
581 claim.u.deleg_cur.name = &open->file.name;
582
583 status = nfs41_open(open->session, &open->parent, &open->file,
584 &open->owner, &claim, open->share_access, open->share_deny,
585 OPEN4_NOCREATE, 0, NULL, try_recovery, &open_stateid, &ignore, NULL);
586
588 if (status == NFS4_OK) {
589 /* save the new open stateid */
590 memcpy(&open->stateid, &open_stateid, sizeof(stateid4));
591 open->do_close = 1;
592 } else if (open->do_close && (status == NFS4ERR_BAD_STATEID ||
594 /* something triggered client state recovery, and the open stateid
595 * has already been reclaimed; see recover_stateid_delegation() */
596 status = NFS4_OK;
597 }
598 open->delegation.reclaim = 0;
599
600 /* signal anyone waiting on the open stateid */
601 WakeAllConditionVariable(&open->delegation.cond);
602out_unlock:
604 if (status)
605 eprintf("nfs41_delegation_to_open(%p) failed with %s\n",
607 return status;
608}
609
613{
615
616 /* find a delegation for this file */
617 if (delegation_find(session->client, &file->fh, deleg_file_cmp, &deleg))
618 return;
619 dprintf(1, "nfs41_delegation_remove_srvopen: removing reference to "
620 "srv_open=%x\n", deleg->srv_open);
622 deleg->srv_open = NULL;
625}
626
627/* synchronous delegation return */
628#ifdef DELEGATION_RETURN_ON_CONFLICT
632#ifndef __REACTOS__
634#else
635 IN int access,
636#endif
637 IN bool_t truncate)
638{
639 nfs41_client *client = session->client;
641 int status;
642
643 /* find a delegation for this file */
645 if (status)
646 goto out;
647
649 if (deleg->status == DELEGATION_GRANTED) {
650 /* return unless delegation is write and access is read */
651 if (deleg->state.type != OPEN_DELEGATE_WRITE
655 }
656 } else {
657 /* the delegation is being returned, wait for it to finish */
658 while (deleg->status == DELEGATION_RETURNING)
659 SleepConditionVariableSRW(&deleg->cond, &deleg->lock, INFINITE, 0);
661 }
663
665 delegation_return(client, deleg, truncate, TRUE);
666 status = NFS4_OK;
667 }
668
670out:
671 return status;
672}
673#endif
674
675
676/* asynchronous delegation recall */
681};
682
683static unsigned int WINAPI delegation_recall_thread(void *args)
684{
685 struct recall_thread_args *recall = (struct recall_thread_args*)args;
686
687 delegation_return(recall->client, recall->delegation, recall->truncate, TRUE);
688
689 /* clean up thread arguments */
691 nfs41_root_deref(recall->client->root);
692 free(recall);
693 return 0;
694}
695
696static int deleg_stateid_cmp(const struct list_entry *entry, const void *value)
697{
698 const stateid4 *lhs = &deleg_entry(entry)->state.stateid;
699 const stateid4 *rhs = (const stateid4*)value;
700 return memcmp(lhs->other, rhs->other, NFS4_STATEID_OTHER);
701}
702
705 IN nfs41_fh *fh,
706 IN const stateid4 *stateid,
708{
710 struct recall_thread_args *args;
711 int status;
712
713 dprintf(2, "--> nfs41_delegation_recall()\n");
714
715 /* search for the delegation by stateid instead of filehandle;
716 * deleg_file_cmp() relies on a proper superblock and fileid,
717 * which we don't get with CB_RECALL */
718 status = delegation_find(client, stateid, deleg_stateid_cmp, &deleg);
719 if (status)
720 goto out;
721
723 if (deleg->state.recalled) {
724 /* return BADHANDLE if we've already responded to CB_RECALL */
726 } else {
727 deleg->state.recalled = 1;
728
729 if (deleg->status == DELEGATION_GRANTED) {
730 /* start the delegation return */
733 } /* else return NFS4_OK */
734 }
736
738 goto out_deleg;
739
740 /* allocate thread arguments */
741 args = calloc(1, sizeof(struct recall_thread_args));
742 if (args == NULL) {
744 eprintf("nfs41_delegation_recall() failed to allocate arguments\n");
745 goto out_deleg;
746 }
747
748 /* hold a reference on the root */
749 nfs41_root_ref(client->root);
750 args->client = client;
751 args->delegation = deleg;
752 args->truncate = truncate;
753
754 /* the callback thread can't make rpc calls, so spawn a separate thread */
757 eprintf("nfs41_delegation_recall() failed to start thread\n");
758 goto out_args;
759 }
760 status = NFS4_OK;
761out:
762 dprintf(DGLVL, "<-- nfs41_delegation_recall() returning %s\n",
764 return status;
765
766out_args:
767 free(args);
769out_deleg:
771 goto out;
772}
773
774
775static int deleg_fh_cmp(const struct list_entry *entry, const void *value)
776{
777 const nfs41_fh *lhs = &deleg_entry(entry)->file.fh;
778 const nfs41_fh *rhs = (const nfs41_fh*)value;
779 if (lhs->len != rhs->len) return -1;
780 return memcmp(lhs->fh, rhs->fh, lhs->len);
781}
782
785 IN const nfs41_fh *fh,
786 IN const bitmap4 *attr_request,
788{
790 uint64_t fileid;
791 int status;
792
793 dprintf(2, "--> nfs41_delegation_getattr()\n");
794
795 /* search for a delegation on this file handle */
797 if (status)
798 goto out;
799
800 AcquireSRWLockShared(&deleg->lock);
801 fileid = deleg->file.fh.fileid;
802 if (deleg->status != DELEGATION_GRANTED ||
803 deleg->state.type != OPEN_DELEGATE_WRITE) {
805 }
806 ReleaseSRWLockShared(&deleg->lock);
807 if (status)
808 goto out_deleg;
809
811
812 /* find attributes for the given fileid */
814 client_name_cache(client), fileid, info);
815 if (status) {
817 goto out_deleg;
818 }
819out_deleg:
821out:
822 dprintf(DGLVL, "<-- nfs41_delegation_getattr() returning %s\n",
824 return status;
825}
826
827
830{
831 struct list_entry *entry, *tmp;
832
833 EnterCriticalSection(&client->state.lock);
834 list_for_each_tmp (entry, tmp, &client->state.delegations) {
837 }
838 LeaveCriticalSection(&client->state.lock);
839}
840
841
844{
845 int status = NFS4_OK;
846
847 AcquireSRWLockExclusive(&deleg->lock);
848 if (deleg->status == DELEGATION_GRANTED) {
849 if (deleg->revoked) {
850 deleg->status = DELEGATION_RETURNED;
852 } else if (deleg->state.recalled) {
853 deleg->status = DELEGATION_RETURNING;
855 }
856 }
857 ReleaseSRWLockExclusive(&deleg->lock);
858 return status;
859}
860
863{
864 struct list_entry *entry, *tmp;
866 int status = NFS4_OK;
867
868 list_for_each_tmp(entry, tmp, &client->state.delegations) {
870
872 switch (status) {
874 /* the delegation was reclaimed, but flagged as recalled;
875 * return it with try_recovery=FALSE */
877 break;
878
880 /* reclaim failed, so we have no delegation state on the server;
881 * 'forget' the delegation without trying to return it */
883 status = NFS4_OK;
884 break;
885 }
886
888 goto out;
889 }
890
891 /* use DELEGPURGE to indicate that we're done reclaiming delegations */
892 status = nfs41_delegpurge(client->session);
893
894 /* support for DELEGPURGE is optional; ignore any errors but BADSESSION */
896 status = NFS4_OK;
897out:
898 return status;
899}
900
901
904{
905 struct list_entry *entry;
908
909 /* starting from the least recently opened, find and return
910 * the first delegation that's not 'in use' (currently open) */
911
912 /* TODO: use a more robust algorithm, taking into account:
913 * -number of total opens
914 * -time since last operation on an associated open, or
915 * -number of operations/second over last n seconds */
916 EnterCriticalSection(&client->state.lock);
917 list_for_each(entry, &client->state.delegations) {
919
920 /* skip if it's currently in use for an open; note that ref_count
921 * can't go from 1 to 2 without holding client->state.lock */
922 if (state->ref_count > 1)
923 continue;
924
926 if (state->status == DELEGATION_GRANTED) {
927 /* start returning the delegation */
928 state->status = DELEGATION_RETURNING;
930 }
932
934 break;
935 }
936 LeaveCriticalSection(&client->state.lock);
937
940 return status;
941}
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
#define open
Definition: acwin.h:95
static int inbuf
Definition: adnsresfilter.c:73
static int state
Definition: maze.c:121
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
static void list_remove(struct list_entry *entry)
Definition: list.h:90
#define list_container(entry, type, field)
Definition: list.h:33
#define list_for_each(entry, head)
Definition: list.h:36
#define list_for_each_tmp(entry, tmp, head)
Definition: list.h:39
int(* list_compare_fn)(const struct list_entry *, const void *)
Definition: list.h:100
static void list_add_tail(struct list_entry *head, struct list_entry *entry)
Definition: list.h:83
static struct list_entry * list_search(const struct list_entry *head, const void *value, list_compare_fn compare)
Definition: list.h:102
static void list_init(struct list_entry *head)
Definition: list.h:51
void path_fh_init(OUT nfs41_path_fh *file, IN nfs41_abs_path *path)
Definition: util.c:346
bool_t last_component(IN const char *path, IN const char *path_end, OUT nfs41_component *component)
Definition: util.c:317
void get_nfs_time(OUT nfstime4 *nfs_time)
Definition: util.c:210
int safe_write(unsigned char **pos, uint32_t *remaining, void *src, uint32_t src_len)
Definition: util.c:44
void fh_copy(OUT nfs41_fh *dst, IN const nfs41_fh *src)
Definition: util.c:354
void abs_path_copy(OUT nfs41_abs_path *dst, IN const nfs41_abs_path *src)
Definition: util.c:338
void eprintf(LPCSTR format,...)
Definition: daemon_debug.c:86
const char * nfs_error_string(int status)
Definition: daemon_debug.c:370
#define NO_ERROR
Definition: dderror.h:5
#define free
Definition: debug_ros.c:5
static nfs41_open_state * deleg_open_find(IN struct client_state *state, IN const nfs41_delegation_state *deleg)
Definition: delegation.c:155
static int delegation_flush_locks(IN nfs41_open_state *open, IN bool_t try_recovery)
Definition: delegation.c:215
static int deleg_file_cmp(const struct list_entry *entry, const void *value)
Definition: delegation.c:379
int nfs41_delegation_getattr(IN nfs41_client *client, IN const nfs41_fh *fh, IN const bitmap4 *attr_request, OUT nfs41_file_info *info)
Definition: delegation.c:783
void nfs41_client_delegation_free(IN nfs41_client *client)
Definition: delegation.c:828
static int delegation_truncate(IN nfs41_delegation_state *deleg, IN nfs41_client *client, IN stateid_arg *stateid, IN nfs41_file_info *info)
Definition: delegation.c:440
static bool_t delegation_compatible(IN enum open_delegation_type4 type, IN uint32_t create, IN uint32_t access, IN uint32_t deny)
Definition: delegation.c:388
#define deleg_entry(pos)
Definition: delegation.c:377
int nfs41_delegation_to_open(IN nfs41_open_state *open, IN bool_t try_recovery)
Definition: delegation.c:539
#define DGLVL
Definition: delegation.c:32
static int deleg_stateid_cmp(const struct list_entry *entry, const void *value)
Definition: delegation.c:696
static void delegation_remove(IN nfs41_client *client, IN nfs41_delegation_state *deleg)
Definition: delegation.c:91
static int delegation_return(IN nfs41_client *client, IN nfs41_delegation_state *deleg, IN bool_t truncate, IN bool_t try_recovery)
Definition: delegation.c:264
void nfs41_delegation_deref(IN nfs41_delegation_state *state)
Definition: delegation.c:79
static unsigned int WINAPI delegation_recall_thread(void *args)
Definition: delegation.c:683
static int deleg_fh_cmp(const struct list_entry *entry, const void *value)
Definition: delegation.c:775
int nfs41_delegate_open(IN nfs41_open_state *state, IN uint32_t create, IN OPTIONAL nfs41_file_info *createattrs, OUT nfs41_file_info *info)
Definition: delegation.c:462
int nfs41_delegation_return(IN nfs41_session *session, IN nfs41_path_fh *file, IN enum open_delegation_type4 access, IN bool_t truncate)
Definition: delegation.c:629
int nfs41_client_delegation_recovery(IN nfs41_client *client)
Definition: delegation.c:861
int nfs41_delegation_recall(IN nfs41_client *client, IN nfs41_fh *fh, IN const stateid4 *stateid, IN bool_t truncate)
Definition: delegation.c:703
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
static int delegation_create(IN const nfs41_path_fh *parent, IN const nfs41_path_fh *file, IN const open_delegation4 *delegation, OUT nfs41_delegation_state **deleg_out)
Definition: delegation.c:36
static void deleg_lock_update(IN nfs41_open_state *open, IN const nfs41_lock_state *source)
Definition: delegation.c:198
void nfs41_delegation_ref(IN nfs41_delegation_state *state)
Definition: delegation.c:71
static bool_t has_delegated_locks(IN nfs41_open_state *open)
Definition: delegation.c:128
#define open_entry(pos)
Definition: delegation.c:89
static int open_deleg_cmp(const struct list_entry *entry, const void *value)
Definition: delegation.c:139
int nfs41_client_delegation_return_lru(IN nfs41_client *client)
Definition: delegation.c:902
static int delegation_find(IN nfs41_client *client, IN const void *value, IN list_compare_fn cmp, OUT nfs41_delegation_state **deleg_out)
Definition: delegation.c:415
void nfs41_delegation_remove_srvopen(IN nfs41_session *session, IN nfs41_path_fh *file)
Definition: delegation.c:610
#define lock_entry(pos)
Definition: delegation.c:126
static bool_t deleg_lock_find(IN nfs41_open_state *open, OUT nfs41_lock_state *lock_out)
Definition: delegation.c:173
static int delegation_recovery_status(IN nfs41_delegation_state *deleg)
Definition: delegation.c:842
BOOL WINAPI DeviceIoControl(IN HANDLE hDevice, IN DWORD dwIoControlCode, IN LPVOID lpInBuffer OPTIONAL, IN DWORD nInBufferSize OPTIONAL, OUT LPVOID lpOutBuffer OPTIONAL, IN DWORD nOutBufferSize OPTIONAL, OUT LPDWORD lpBytesReturned OPTIONAL, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: deviceio.c:136
#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
UINT64 uint64_t
Definition: types.h:77
#define CloseHandle
Definition: compat.h:739
#define OPEN_EXISTING
Definition: compat.h:775
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define GENERIC_READ
Definition: compat.h:135
#define FILE_SHARE_READ
Definition: compat.h:136
VOID WINAPI ReleaseSRWLockShared(PSRWLOCK Lock)
Definition: sync.c:43
VOID WINAPI AcquireSRWLockExclusive(PSRWLOCK Lock)
Definition: sync.c:8
VOID WINAPI AcquireSRWLockShared(PSRWLOCK Lock)
Definition: sync.c:15
VOID WINAPI ReleaseSRWLockExclusive(PSRWLOCK Lock)
Definition: sync.c:36
VOID WINAPI InitializeSRWLock(PSRWLOCK Lock)
Definition: sync.c:29
VOID WINAPI WakeAllConditionVariable(PCONDITION_VARIABLE ConditionVariable)
Definition: sync.c:91
BOOL WINAPI SleepConditionVariableSRW(PCONDITION_VARIABLE ConditionVariable, PSRWLOCK Lock, DWORD Timeout, ULONG Flags)
Definition: sync.c:75
VOID WINAPI InitializeConditionVariable(PCONDITION_VARIABLE ConditionVariable)
Definition: sync.c:22
r parent
Definition: btrfs.c:3010
#define INFINITE
Definition: serial.h:102
unsigned long DWORD
Definition: ntddk_ex.h:95
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLuint buffer
Definition: glext.h:5915
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
GLuint GLint GLboolean GLint GLenum access
Definition: glext.h:7866
GLuint64EXT * result
Definition: glext.h:11304
uint32_t entry
Definition: isohybrid.c:63
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static const struct access_res create[16]
Definition: package.c:7505
#define cmp(status, error)
Definition: error.c:114
int nfs41_attr_cache_lookup(IN struct nfs41_name_cache *cache, IN uint64_t fileid, OUT nfs41_file_info *info_out)
Definition: name_cache.c:859
static __inline struct nfs41_name_cache * client_name_cache(IN nfs41_client *client)
Definition: name_cache.h:28
void nfs41_root_ref(IN nfs41_root *root)
Definition: namespace.c:92
void nfs41_root_deref(IN nfs41_root *root)
Definition: namespace.c:100
#define client_entry(pos)
Definition: namespace.c:33
static __inline void nfs41_superblock_supported_attrs(IN const nfs41_superblock *superblock, IN OUT bitmap4 *attrs)
Definition: nfs41.h:454
void nfs41_open_state_deref(IN nfs41_open_state *state)
Definition: open.c:104
void nfs41_open_state_ref(IN nfs41_open_state *state)
Definition: open.c:96
@ DELEGATION_RETURNED
Definition: nfs41.h:92
@ DELEGATION_GRANTED
Definition: nfs41.h:90
@ DELEGATION_RETURNING
Definition: nfs41.h:91
@ FATTR4_WORD1_TIME_CREATE
Definition: nfs41_const.h:262
@ FATTR4_WORD1_TIME_MODIFY_SET
Definition: nfs41_const.h:266
#define NFS4_STATEID_OTHER
Definition: nfs41_const.h:33
@ NFS4ERR_BAD_STATEID
Definition: nfs41_const.h:132
@ NFS4ERR_EXPIRED
Definition: nfs41_const.h:116
@ NFS4ERR_DELEG_REVOKED
Definition: nfs41_const.h:196
@ NFS4ERR_BADSESSION
Definition: nfs41_const.h:161
@ NFS4_OK
Definition: nfs41_const.h:87
@ NFS4ERR_STALE_STATEID
Definition: nfs41_const.h:130
@ NFS4ERR_BADHANDLE
Definition: nfs41_const.h:107
@ NFS4ERR_SERVERFAULT
Definition: nfs41_const.h:111
#define IOCTL_NFS41_INVALCACHE
Definition: nfs41_driver.h:50
#define NFS41_USER_DEVICE_NAME_A
Definition: nfs41_driver.h:28
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
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
int nfs41_delegreturn(IN nfs41_session *session, IN nfs41_path_fh *file, IN stateid_arg *stateid, IN bool_t try_recovery)
Definition: nfs41_ops.c:1693
int nfs41_setattr(IN nfs41_session *session, IN nfs41_path_fh *file, IN stateid_arg *stateid, IN nfs41_file_info *info)
Definition: nfs41_ops.c:1351
int nfs41_delegpurge(IN nfs41_session *session)
Definition: nfs41_ops.c:1666
open_delegation_type4
Definition: nfs41_ops.h:585
@ OPEN_DELEGATE_READ
Definition: nfs41_ops.h:587
@ OPEN_DELEGATE_WRITE
Definition: nfs41_ops.h:588
@ READ_LT
Definition: nfs41_ops.h:399
@ WRITE_LT
Definition: nfs41_ops.h:400
@ OPEN4_CREATE
Definition: nfs41_ops.h:554
@ OPEN4_NOCREATE
Definition: nfs41_ops.h:553
@ OPEN4_SHARE_ACCESS_WRITE
Definition: nfs41_ops.h:565
@ OPEN4_SHARE_DENY_READ
Definition: nfs41_ops.h:569
@ STATEID_LOCK
Definition: nfs41_ops.h:277
@ STATEID_DELEG_FILE
Definition: nfs41_ops.h:278
@ STATEID_OPEN
Definition: nfs41_ops.h:276
@ CLAIM_DELEGATE_CUR
Definition: nfs41_ops.h:595
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define GENERIC_WRITE
Definition: nt_native.h:90
long LONG
Definition: pedump.c:60
#define dprintf
Definition: regdump.c:33
static FILE * out
Definition: regtests2xml.c:44
#define calloc
Definition: rosglue.h:14
_CRTIMP uintptr_t __cdecl _beginthreadex(_In_opt_ void *_Security, _In_ unsigned _StackSize, _In_ unsigned(__stdcall *_StartAddress)(void *), _In_opt_ void *_ArgList, _In_ unsigned _InitFlag, _Out_opt_ unsigned *_ThrdAddr)
#define args
Definition: format.c:66
static FILE * client
Definition: client.c:41
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
struct __nfs41_root * root
Definition: nfs41.h:206
enum delegation_status status
Definition: nfs41.h:103
nfs41_path_fh file
Definition: nfs41.h:99
open_delegation4 state
Definition: nfs41.h:96
CONDITION_VARIABLE cond
Definition: nfs41.h:105
struct __nfs41_superblock * superblock
Definition: nfs41_types.h:56
uint32_t len
Definition: nfs41_types.h:54
unsigned char fh[NFS4_FHSIZE]
Definition: nfs41_types.h:53
uint64_t fileid
Definition: nfs41_types.h:55
uint32_t claim
Definition: nfs41_ops.h:615
struct __open_claim4::@44::__open_claim_deleg_cur deleg_cur
union __open_claim4::@44 u
enum open_delegation_type4 type
Definition: nfs41_types.h:154
unsigned char other[NFS4_STATEID_OTHER]
Definition: nfs41_types.h:145
uint32_t seqid
Definition: nfs41_types.h:144
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
Definition: match.c:390
char * name
Definition: compiler.c:66
Definition: fci.c:127
WCHAR * path
Definition: filesystem.c:122
Definition: list.h:27
nfs41_delegation_state * delegation
Definition: delegation.c:679
nfs41_client * client
Definition: delegation.c:678
Definition: ps.c:97
rwlock_t lock
Definition: tcpcore.h:0
PVOID HANDLE
Definition: typedefs.h:73
uint32_t * LPDWORD
Definition: typedefs.h:59
#define IN
Definition: typedefs.h:39
#define OUT
Definition: typedefs.h:40
Definition: pdh_main.c:94
#define ZeroMemory
Definition: winbase.h:1712
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
#define CreateFile
Definition: winbase.h:3749
#define WINAPI
Definition: msvc.h:6