ReactOS 0.4.15-dev-7788-g1ad9096
name_cache.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 <windows.h>
23#include <strsafe.h>
24#include <time.h>
25#include <assert.h>
26
27#include "nfs41_ops.h"
28#include "nfs41_compound.h"
29#include "name_cache.h"
30#include "util.h"
31#include "tree.h"
32#include "daemon_debug.h"
33
34
35/* dprintf levels for name cache logging */
36enum {
37 NCLVL1 = 2,
38 NCLVL2
39};
40
41
42#define NAME_CACHE_EXPIRATION 20 /* TODO: get from configuration */
43
44/* allow up to 256K of memory for name and attribute cache entries */
45#define NAME_CACHE_MAX_SIZE 262144
46
47/* negative lookup caching
48 *
49 * by caching lookups that result in NOENT, we can avoid sending subsequent
50 * lookups over the wire. a name cache entry is negative when its attributes
51 * pointer is NULL. negative entries are created by three functions:
52 * nfs41_name_cache_remove(), _insert() when called with NULL for the fh and
53 * attributes, and _rename() for the source entry */
54
55/* delegations and cache feedback
56 *
57 * delegations provide a guarantee that no links or attributes will change
58 * without notice. the name cache takes advantage of this by preventing
59 * delegated entries from being removed on NAME_CACHE_EXPIRATION, though
60 * they're still removed when a parent is invalidated. the attribute cache
61 * holds an extra reference on delegated entries to prevent their removal
62 * entirely, until the delegation is returned.
63 * this extra reference presents a problem when the number of delegations
64 * approaches the maximum number of attribute cache entries. when there are
65 * not enough available entries to store the parent directories, every lookup
66 * results in a name cache miss, and cache performance degrades significantly.
67 * the solution is to provide feedback via nfs41_name_cache_insert() when
68 * delegations reach a certain percent of the cache capacity. the error code
69 * ERROR_TOO_MANY_OPEN_FILES, chosen arbitrarily for this case, instructs the
70 * caller to return an outstanding delegation before caching a new one.
71 */
72static __inline bool_t is_delegation(
74{
76}
77
78
79/* attribute cache */
82 struct list_entry free_entry;
83 uint64_t change;
85 uint64_t fileid;
86 int64_t time_access_s;
87 int64_t time_create_s;
88 int64_t time_modify_s;
89 uint32_t time_access_ns;
90 uint32_t time_create_ns;
91 uint32_t time_modify_ns;
92 uint32_t numlinks;
93 unsigned mode : 30;
94 unsigned hidden : 1;
95 unsigned system : 1;
96 unsigned archive : 1;
97 time_t expiration;
98 unsigned ref_count : 26;
99 unsigned type : 4;
100 unsigned invalidated : 1;
101 unsigned delegated : 1;
102};
103#define ATTR_ENTRY_SIZE sizeof(struct attr_cache_entry)
104
106
108 struct attr_tree head;
111};
112
113int attr_cmp(struct attr_cache_entry *lhs, struct attr_cache_entry *rhs)
114{
115 return lhs->fileid < rhs->fileid ? -1 : lhs->fileid > rhs->fileid;
116}
117RB_GENERATE(attr_tree, attr_cache_entry, rbnode, attr_cmp)
118
119
120/* attr_cache_entry */
121#define attr_entry(pos) list_container(pos, struct attr_cache_entry, free_entry)
122
124 IN struct attr_cache *cache,
125 IN uint64_t fileid,
126 OUT struct attr_cache_entry **entry_out)
127{
128 struct attr_cache_entry *entry;
129 int status = NO_ERROR;
130
131 /* get the next entry from free_entries and remove it */
132 if (list_empty(&cache->free_entries)) {
134 goto out;
135 }
136 entry = attr_entry(cache->free_entries.next);
137 list_remove(&entry->free_entry);
138
139 entry->fileid = fileid;
140 entry->invalidated = FALSE;
141 entry->delegated = FALSE;
142 *entry_out = entry;
143out:
144 return status;
145}
146
147static __inline void attr_cache_entry_free(
148 IN struct attr_cache *cache,
149 IN struct attr_cache_entry *entry)
150{
151 dprintf(NCLVL1, "attr_cache_entry_free(%llu)\n", entry->fileid);
152 RB_REMOVE(attr_tree, &cache->head, entry);
153 /* add it back to free_entries */
154 list_add_tail(&cache->free_entries, &entry->free_entry);
155}
156
157static __inline void attr_cache_entry_ref(
158 IN struct attr_cache *cache,
159 IN struct attr_cache_entry *entry)
160{
161 const uint32_t previous = entry->ref_count++;
162 dprintf(NCLVL2, "attr_cache_entry_ref(%llu) %u -> %u\n",
163 entry->fileid, previous, entry->ref_count);
164}
165
166static __inline void attr_cache_entry_deref(
167 IN struct attr_cache *cache,
168 IN struct attr_cache_entry *entry)
169{
170 const uint32_t previous = entry->ref_count--;
171 dprintf(NCLVL2, "attr_cache_entry_deref(%llu) %u -> %u\n",
172 entry->fileid, previous, entry->ref_count);
173
174 if (entry->ref_count == 0)
176}
177
178static __inline int attr_cache_entry_expired(
179 IN const struct attr_cache_entry *entry)
180{
181 return entry->invalidated ||
182 (!entry->delegated && time(NULL) > entry->expiration);
183}
184
185/* attr_cache */
187 IN struct attr_cache *cache,
188 IN uint32_t max_entries)
189{
190 uint32_t i;
191 int status = NO_ERROR;
192
193 /* allocate a pool of entries */
194 cache->pool = calloc(max_entries, ATTR_ENTRY_SIZE);
195 if (cache->pool == NULL) {
197 goto out;
198 }
199
200 /* initialize the list of free entries */
201 list_init(&cache->free_entries);
202 for (i = 0; i < max_entries; i++) {
203 list_init(&cache->pool[i].free_entry);
204 list_add_tail(&cache->free_entries, &cache->pool[i].free_entry);
205 }
206out:
207 return status;
208}
209
210static void attr_cache_free(
211 IN struct attr_cache *cache)
212{
213 /* free the pool */
214 free(cache->pool);
215 cache->pool = NULL;
216 list_init(&cache->free_entries);
217}
218
220 IN struct attr_cache *cache,
221 IN uint64_t fileid)
222{
223 /* find an entry that matches fileid */
224 struct attr_cache_entry tmp;
225 tmp.fileid = fileid;
226 return RB_FIND(attr_tree, &cache->head, &tmp);
227}
228
230 IN struct attr_cache *cache,
231 IN struct attr_cache_entry *entry)
232{
233 int status = NO_ERROR;
234
235 dprintf(NCLVL2, "--> attr_cache_insert(%llu)\n", entry->fileid);
236
237 if (RB_INSERT(attr_tree, &cache->head, entry))
239
240 dprintf(NCLVL2, "<-- attr_cache_insert() returning %d\n", status);
241 return status;
242}
243
245 IN struct attr_cache *cache,
246 IN uint64_t fileid,
247 OUT struct attr_cache_entry **entry_out)
248{
249 struct attr_cache_entry *entry;
250 int status = NO_ERROR;
251
252 dprintf(NCLVL1, "--> attr_cache_find_or_create(%llu)\n", fileid);
253
254 /* look for an existing entry */
255 entry = attr_cache_search(cache, fileid);
256 if (entry == NULL) {
257 /* create and insert */
259 if (status)
260 goto out;
261
263 if (status)
264 goto out_err_free;
265 }
266
267 /* take a reference on success */
269
270out:
271 *entry_out = entry;
272 dprintf(NCLVL1, "<-- attr_cache_find_or_create() returning %d\n",
273 status);
274 return status;
275
276out_err_free:
278 entry = NULL;
279 goto out;
280}
281
283 IN struct attr_cache_entry *entry,
284 IN const nfs41_file_info *info,
285 IN enum open_delegation_type4 delegation)
286{
287 /* update the attributes present in mask */
288 if (info->attrmask.count >= 1) {
289 if (info->attrmask.arr[0] & FATTR4_WORD0_TYPE)
290 entry->type = (unsigned char)(info->type & NFS_FTYPE_MASK);
291 if (info->attrmask.arr[0] & FATTR4_WORD0_CHANGE) {
292 entry->change = info->change;
293 /* revalidate whenever we get a change attribute */
294 entry->invalidated = 0;
295 entry->expiration = time(NULL) + NAME_CACHE_EXPIRATION;
296 }
297 if (info->attrmask.arr[0] & FATTR4_WORD0_SIZE)
298 entry->size = info->size;
299 if (info->attrmask.arr[0] & FATTR4_WORD0_HIDDEN)
300 entry->hidden = info->hidden;
301 if (info->attrmask.arr[0] & FATTR4_WORD0_ARCHIVE)
302 entry->archive = info->archive;
303 }
304 if (info->attrmask.count >= 2) {
305 if (info->attrmask.arr[1] & FATTR4_WORD1_MODE)
306 entry->mode = info->mode;
307 if (info->attrmask.arr[1] & FATTR4_WORD1_NUMLINKS)
308 entry->numlinks = info->numlinks;
309 if (info->attrmask.arr[1] & FATTR4_WORD1_TIME_ACCESS) {
310 entry->time_access_s = info->time_access.seconds;
311 entry->time_access_ns = info->time_access.nseconds;
312 }
313 if (info->attrmask.arr[1] & FATTR4_WORD1_TIME_CREATE) {
314 entry->time_create_s = info->time_create.seconds;
315 entry->time_create_ns = info->time_create.nseconds;
316 }
317 if (info->attrmask.arr[1] & FATTR4_WORD1_TIME_MODIFY) {
318 entry->time_modify_s = info->time_modify.seconds;
319 entry->time_modify_ns = info->time_modify.nseconds;
320 }
321 if (info->attrmask.arr[1] & FATTR4_WORD1_SYSTEM)
322 entry->system = info->system;
323 }
324
325 if (is_delegation(delegation))
326 entry->delegated = TRUE;
327}
328
329static void copy_attrs(
331 IN const struct attr_cache_entry *src)
332{
333 dst->change = src->change;
334 dst->size = src->size;
335 dst->time_access.seconds = src->time_access_s;
336 dst->time_access.nseconds = src->time_access_ns;
337 dst->time_create.seconds = src->time_create_s;
338 dst->time_create.nseconds = src->time_create_ns;
339 dst->time_modify.seconds = src->time_modify_s;
340 dst->time_modify.nseconds = src->time_modify_ns;
341 dst->type = src->type;
342 dst->numlinks = src->numlinks;
343 dst->mode = src->mode;
344 dst->fileid = src->fileid;
345 dst->hidden = src->hidden;
346 dst->system = src->system;
347 dst->archive = src->archive;
348
349 dst->attrmask.count = 2;
350 dst->attrmask.arr[0] = FATTR4_WORD0_TYPE | FATTR4_WORD0_CHANGE
353 dst->attrmask.arr[1] = FATTR4_WORD1_MODE
357}
358
359
360/* name cache */
366 struct name_tree rbchildren;
367 struct attr_cache_entry *attributes;
368 struct name_cache_entry *parent;
369 struct list_entry exp_entry;
370 time_t expiration;
371 unsigned short component_len;
372};
373#define NAME_ENTRY_SIZE sizeof(struct name_cache_entry)
374
375int name_cmp(struct name_cache_entry *lhs, struct name_cache_entry *rhs)
376{
377 const int diff = rhs->component_len - lhs->component_len;
378 return diff ? diff : strncmp(lhs->component, rhs->component, lhs->component_len);
379}
380RB_GENERATE(name_tree, name_cache_entry, rbnode, name_cmp)
381
385 struct attr_cache attributes;
386 struct list_entry exp_entries; /* list of entries by expiry */
392 SRWLOCK lock;
393};
394
395
396/* internal name cache functions used by the public name cache interface;
397 * these functions expect the caller to hold a lock on the cache */
398
399#define name_entry(pos) list_container(pos, struct name_cache_entry, exp_entry)
400
402 IN struct nfs41_name_cache *cache)
403{
404 return cache->expiration > 0;
405}
406
407static __inline void name_cache_entry_rename(
408 OUT struct name_cache_entry *entry,
409 IN const nfs41_component *component)
410{
412 component->name, component->len);
413 entry->component_len = component->len;
414}
415
416static __inline void name_cache_remove(
417 IN struct name_cache_entry *entry,
418 IN struct name_cache_entry *parent)
419{
420 RB_REMOVE(name_tree, &parent->rbchildren, entry);
421 entry->parent = NULL;
422}
423
425 IN struct nfs41_name_cache *cache,
426 IN struct name_cache_entry *parent);
427
428static __inline void name_cache_unlink(
429 IN struct nfs41_name_cache *cache,
430 IN struct name_cache_entry *entry)
431{
432 /* remove the entry from the tree */
433 if (entry->parent)
434 name_cache_remove(entry, entry->parent);
435 else if (entry == cache->root)
436 cache->root = NULL;
437
438 /* unlink all of its children */
440 /* release the cached attributes */
441 if (entry->attributes) {
442 attr_cache_entry_deref(&cache->attributes, entry->attributes);
443 entry->attributes = NULL;
444 }
445 /* move it to the end of exp_entries for scavenging */
446 list_remove(&entry->exp_entry);
447 list_add_tail(&cache->exp_entries, &entry->exp_entry);
448}
449
451 IN struct nfs41_name_cache *cache,
452 IN struct name_cache_entry *parent)
453{
454 struct name_cache_entry *entry, *tmp;
455 RB_FOREACH_SAFE(entry, name_tree, &parent->rbchildren, tmp)
457}
458
460 IN struct nfs41_name_cache *cache,
462 OUT struct name_cache_entry **entry_out)
463{
464 int status = NO_ERROR;
465 struct name_cache_entry *entry;
466
467 if (cache->entries >= cache->max_entries) {
468 /* scavenge the oldest entry */
469 if (list_empty(&cache->exp_entries)) {
471 goto out;
472 }
473 entry = name_entry(cache->exp_entries.prev);
475
476 dprintf(NCLVL2, "name_cache_entry_create('%s') scavenged 0x%p\n",
477 component->name, entry);
478 } else {
479 /* take the next entry in the pool and add it to exp_entries */
480 entry = &cache->pool[cache->entries++];
481 list_init(&entry->exp_entry);
482 list_add_tail(&cache->exp_entries, &entry->exp_entry);
483 }
484
486
487 *entry_out = entry;
488out:
489 return status;
490}
491
493 IN struct nfs41_name_cache *cache,
494 IN struct name_cache_entry *entry)
495{
496 /* move the entry to the front of cache->exp_entries, then do
497 * the same for its parents, which are more costly to evict */
498 while (entry) {
499 /* if entry is delegated, it won't be in the list */
500 if (!list_empty(&entry->exp_entry)) {
501 list_remove(&entry->exp_entry);
502 list_add_head(&cache->exp_entries, &entry->exp_entry);
503 }
504 if (entry == entry->parent)
505 break;
506 entry = entry->parent;
507 }
508}
509
511 IN struct nfs41_name_cache *cache,
512 IN struct name_cache_entry *entry)
513{
514 /* update the expiration timer */
515 entry->expiration = time(NULL) + cache->expiration;
517}
518
520 IN struct nfs41_name_cache *cache,
521 IN struct name_cache_entry *entry,
522 IN OPTIONAL const nfs41_fh *fh,
524 IN enum open_delegation_type4 delegation)
525{
526 int status = NO_ERROR;
527
528 if (fh)
529 fh_copy(&entry->fh, fh);
530 else
531 entry->fh.len = 0;
532
533 if (info) {
534 if (entry->attributes == NULL) {
535 /* negative -> positive entry, create the attributes */
537 info->fileid, &entry->attributes);
538 if (status)
539 goto out;
540 }
541
542 attr_cache_update(entry->attributes, info, delegation);
543
544 /* hold a reference as long as we have the delegation */
545 if (is_delegation(delegation)) {
546 attr_cache_entry_ref(&cache->attributes, entry->attributes);
547 cache->delegations++;
548 }
549
550 /* keep the entry from expiring */
551 if (entry->attributes->delegated)
552 list_remove(&entry->exp_entry);
553 } else if (entry->attributes) {
554 /* positive -> negative entry, deref the attributes */
555 attr_cache_entry_deref(&cache->attributes, entry->attributes);
556 entry->attributes = NULL;
557 }
559out:
560 return status;
561}
562
564 IN struct nfs41_name_cache *cache,
565 IN struct name_cache_entry *entry,
566 IN const change_info4 *cinfo)
567{
568 if (entry->attributes == NULL)
569 return FALSE;
570
571 if (cinfo->after == entry->attributes->change ||
572 (cinfo->atomic && cinfo->before == entry->attributes->change)) {
573 entry->attributes->change = cinfo->after;
575 dprintf(NCLVL1, "name_cache_entry_changed('%s') has not changed. "
576 "updated change=%llu\n", entry->component,
577 entry->attributes->change);
578 return FALSE;
579 } else {
580 dprintf(NCLVL1, "name_cache_entry_changed('%s') has changed: was %llu, "
581 "got before=%llu\n", entry->component,
582 entry->attributes->change, cinfo->before);
583 return TRUE;
584 }
585}
586
588 IN struct nfs41_name_cache *cache,
589 IN struct name_cache_entry *entry)
590{
591 dprintf(NCLVL1, "name_cache_entry_invalidate('%s')\n", entry->component);
592
593 if (entry->attributes) {
594 /* flag attributes so that entry_invis() will return true
595 * if another entry attempts to use them */
596 entry->attributes->invalidated = 1;
597 }
599}
600
602 IN struct nfs41_name_cache *cache,
603 IN struct name_cache_entry *parent,
605{
606 struct name_cache_entry tmp, *entry;
607
608 dprintf(NCLVL2, "--> name_cache_search('%.*s' under '%s')\n",
609 component->len, component->name, parent->component);
610
612 component->name, component->len);
613 tmp.component_len = component->len;
614
615 entry = RB_FIND(name_tree, &parent->rbchildren, &tmp);
616 if (entry)
617 dprintf(NCLVL2, "<-- name_cache_search() "
618 "found existing entry 0x%p\n", entry);
619 else
620 dprintf(NCLVL2, "<-- name_cache_search() returning NULL\n");
621 return entry;
622}
623
624static int entry_invis(
625 IN struct name_cache_entry *entry,
626 OUT OPTIONAL bool_t *is_negative)
627{
628 /* name entry timer expired? */
629 if (!list_empty(&entry->exp_entry) && time(NULL) > entry->expiration) {
630 dprintf(NCLVL2, "name_entry_expired('%s')\n", entry->component);
631 return 1;
632 }
633 /* negative lookup entry? */
634 if (entry->attributes == NULL) {
635 if (is_negative) *is_negative = 1;
636 dprintf(NCLVL2, "name_entry_negative('%s')\n", entry->component);
637 return 1;
638 }
639 /* attribute entry expired? */
640 if (attr_cache_entry_expired(entry->attributes)) {
641 dprintf(NCLVL2, "attr_entry_expired(%llu)\n",
642 entry->attributes->fileid);
643 return 1;
644 }
645 return 0;
646}
647
649 IN struct nfs41_name_cache *cache,
650 IN bool_t skip_invis,
651 IN const char *path,
652 IN const char *path_end,
653 OUT OPTIONAL const char **remaining_path_out,
654 OUT OPTIONAL struct name_cache_entry **parent_out,
655 OUT OPTIONAL struct name_cache_entry **target_out,
656 OUT OPTIONAL bool_t *is_negative)
657{
660 const char *path_pos;
661 int status = NO_ERROR;
662
663 dprintf(NCLVL1, "--> name_cache_lookup('%s')\n", path);
664
665 parent = NULL;
666 target = cache->root;
667 component.name = path_pos = path;
668
669 if (target == NULL || (skip_invis && entry_invis(target, is_negative))) {
670 target = NULL;
672 goto out;
673 }
674
675 while (next_component(path_pos, path_end, &component)) {
676 parent = target;
678 path_pos = component.name + component.len;
679 if (target == NULL || (skip_invis && entry_invis(target, is_negative))) {
680 target = NULL;
681 if (is_last_component(component.name, path_end))
683 else
685 break;
686 }
687 }
688out:
689 if (remaining_path_out) *remaining_path_out = component.name;
690 if (parent_out) *parent_out = parent;
691 if (target_out) *target_out = target;
692 dprintf(NCLVL1, "<-- name_cache_lookup() returning %d\n", status);
693 return status;
694}
695
697 IN struct name_cache_entry *entry,
698 IN struct name_cache_entry *parent)
699{
700 int status = NO_ERROR;
701
702 dprintf(NCLVL2, "--> name_cache_insert('%s')\n", entry->component);
703
704 if (RB_INSERT(name_tree, &parent->rbchildren, entry))
706 entry->parent = parent;
707
708 dprintf(NCLVL2, "<-- name_cache_insert() returning %u\n", status);
709 return status;
710}
711
713 IN struct nfs41_name_cache *cache,
714 IN struct name_cache_entry *parent,
716 OUT struct name_cache_entry **target_out)
717{
718 int status = NO_ERROR;
719
720 dprintf(NCLVL1, "--> name_cache_find_or_create('%.*s' under '%s')\n",
721 component->len, component->name, parent->component);
722
723 *target_out = name_cache_search(cache, parent, component);
724 if (*target_out)
725 goto out;
726
728 if (status)
729 goto out;
730
731 status = name_cache_insert(*target_out, parent);
732 if (status)
733 goto out_err;
734
735out:
736 dprintf(NCLVL1, "<-- name_cache_find_or_create() returning %d\n",
737 status);
738 return status;
739
740out_err:
741 *target_out = NULL;
742 goto out;
743}
744
745
746/* public name cache interface, declared in name_cache.h */
747
748/* assuming no hard links, calculate how many entries will fit in the cache */
749#define SIZE_PER_ENTRY (ATTR_ENTRY_SIZE + NAME_ENTRY_SIZE)
750#define NAME_CACHE_MAX_ENTRIES (NAME_CACHE_MAX_SIZE / SIZE_PER_ENTRY)
751
753 OUT struct nfs41_name_cache **cache_out)
754{
755 struct nfs41_name_cache *cache;
756 int status = NO_ERROR;
757
758 dprintf(NCLVL1, "nfs41_name_cache_create()\n");
759
760 /* allocate the cache */
761 cache = calloc(1, sizeof(struct nfs41_name_cache));
762 if (cache == NULL) {
764 goto out;
765 }
766
767 list_init(&cache->exp_entries);
768 cache->expiration = NAME_CACHE_EXPIRATION;
769 cache->max_entries = NAME_CACHE_MAX_ENTRIES;
770 cache->max_delegations = NAME_CACHE_MAX_ENTRIES / 2;
772
773 /* allocate a pool of entries */
774 cache->pool = calloc(cache->max_entries, NAME_ENTRY_SIZE);
775 if (cache->pool == NULL) {
777 goto out_err_cache;
778 }
779
780 /* initialize the attribute cache */
781 status = attr_cache_init(&cache->attributes, cache->max_entries);
782 if (status)
783 goto out_err_pool;
784
785 *cache_out = cache;
786out:
787 return status;
788
789out_err_pool:
790 free(cache->pool);
791out_err_cache:
792 free(cache);
793 goto out;
794}
795
797 IN struct nfs41_name_cache **cache_out)
798{
799 struct nfs41_name_cache *cache = *cache_out;
800 int status = NO_ERROR;
801
802 dprintf(NCLVL1, "nfs41_name_cache_free()\n");
803
804 /* free the attribute cache */
805 attr_cache_free(&cache->attributes);
806
807 /* free the name entry pool */
808 free(cache->pool);
809 free(cache);
810 *cache_out = NULL;
811 return status;
812}
813
814static __inline void copy_fh(
816 IN OPTIONAL const struct name_cache_entry *src)
817{
818 if (src)
819 fh_copy(dst, &src->fh);
820 else
821 dst->len = 0;
822}
823
825 IN struct nfs41_name_cache *cache,
826 IN const char *path,
827 IN const char *path_end,
828 OUT OPTIONAL const char **remaining_path_out,
829 OUT OPTIONAL nfs41_fh *parent_out,
830 OUT OPTIONAL nfs41_fh *target_out,
831 OUT OPTIONAL nfs41_file_info *info_out,
832 OUT OPTIONAL bool_t *is_negative)
833{
835 const char *path_pos = path;
836 int status;
837
839
842 goto out_unlock;
843 }
844
845 status = name_cache_lookup(cache, 1, path, path_end,
846 &path_pos, &parent, &target, is_negative);
847
848 if (parent_out) copy_fh(parent_out, parent);
849 if (target_out) copy_fh(target_out, target);
850 if (info_out && target && target->attributes)
851 copy_attrs(info_out, target->attributes);
852
853out_unlock:
855 if (remaining_path_out) *remaining_path_out = path_pos;
856 return status;
857}
858
860 IN struct nfs41_name_cache *cache,
861 IN uint64_t fileid,
862 OUT nfs41_file_info *info_out)
863{
864 struct attr_cache_entry *entry;
865 int status = NO_ERROR;
866
867 dprintf(NCLVL1, "--> nfs41_attr_cache_lookup(%llu)\n", fileid);
868
870
873 goto out_unlock;
874 }
875
876 entry = attr_cache_search(&cache->attributes, fileid);
879 goto out_unlock;
880 }
881
882 copy_attrs(info_out, entry);
883
884out_unlock:
886
887 dprintf(NCLVL1, "<-- nfs41_attr_cache_lookup() returning %d\n", status);
888 return status;
889}
890
892 IN struct nfs41_name_cache *cache,
893 IN uint64_t fileid,
894 IN const nfs41_file_info *info)
895{
896 struct attr_cache_entry *entry;
897 int status = NO_ERROR;
898
899 dprintf(NCLVL1, "--> nfs41_attr_cache_update(%llu)\n", fileid);
900
902
905 goto out_unlock;
906 }
907
908 entry = attr_cache_search(&cache->attributes, fileid);
909 if (entry == NULL) {
911 goto out_unlock;
912 }
913
915
916out_unlock:
918
919 dprintf(NCLVL1, "<-- nfs41_attr_cache_update() returning %d\n", status);
920 return status;
921}
922
924 IN struct nfs41_name_cache *cache,
925 IN const char *path,
926 IN const nfs41_component *name,
927 IN OPTIONAL const nfs41_fh *fh,
929 IN OPTIONAL const change_info4 *cinfo,
930 IN enum open_delegation_type4 delegation)
931{
933 int status;
934
935 dprintf(NCLVL1, "--> nfs41_name_cache_insert('%.*s')\n",
936 name->name + name->len - path, path);
937
939
942 goto out_unlock;
943 }
944
945 /* limit the number of delegations to prevent attr cache starvation */
946 if (is_delegation(delegation) &&
947 cache->delegations >= cache->max_delegations) {
949 goto out_unlock;
950 }
951
952 /* an empty path or component implies the root entry */
953 if (path == NULL || name == NULL || name->len == 0) {
954 /* create the root entry if it doesn't exist */
955 if (cache->root == NULL) {
956 const nfs41_component name = { "ROOT", 4 };
958 if (status)
959 goto out_err_deleg;
960 }
961 target = cache->root;
962 } else {
963 /* find/create an entry under its parent */
965 name->name, NULL, NULL, &parent, NULL);
966 if (status)
967 goto out_err_deleg;
968
969 if (cinfo && name_cache_entry_changed(cache, parent, cinfo)) {
971 goto out_err_deleg;
972 }
973
975 if (status)
976 goto out_err_deleg;
977 }
978
979 /* pass in the new fh/attributes */
981 if (status)
982 goto out_err_update;
983
984out_unlock:
986
987 dprintf(NCLVL1, "<-- nfs41_name_cache_insert() returning %d\n",
988 status);
989 return status;
990
991out_err_update:
992 /* a failure in name_cache_entry_update() leaves a negative entry
993 * where there shouldn't be one; remove it from the cache */
995
996out_err_deleg:
997 if (is_delegation(delegation)) {
998 /* we still need a reference to the attributes for the delegation */
999 struct attr_cache_entry *attributes;
1000 status = attr_cache_find_or_create(&cache->attributes,
1001 info->fileid, &attributes);
1002 if (status == NO_ERROR) {
1003 attr_cache_update(attributes, info, delegation);
1004 cache->delegations++;
1005 }
1006 else
1008 }
1009 goto out_unlock;
1010}
1011
1013 IN struct nfs41_name_cache *cache,
1014 IN uint64_t fileid,
1015 IN const char *path,
1016 IN const nfs41_component *name)
1017{
1018 struct name_cache_entry *parent, *target;
1019 struct attr_cache_entry *attributes;
1020 int status;
1021
1022 dprintf(NCLVL1, "--> nfs41_name_cache_delegreturn(%llu, '%s')\n",
1023 fileid, path);
1024
1026
1027 if (!name_cache_enabled(cache)) {
1029 goto out_unlock;
1030 }
1031
1033 name->name + name->len, NULL, &parent, &target, NULL);
1034 if (status == NO_ERROR) {
1035 /* put the name cache entry back on the exp_entries list */
1036 list_add_head(&cache->exp_entries, &target->exp_entry);
1038
1039 attributes = target->attributes;
1040 } else {
1041 /* should still have an attr cache entry */
1042 attributes = attr_cache_search(&cache->attributes, fileid);
1043 }
1044
1045 if (attributes == NULL) {
1047 goto out_unlock;
1048 }
1049
1050 /* release the reference from name_cache_entry_update() */
1051 if (attributes->delegated) {
1052 attributes->delegated = FALSE;
1053 attr_cache_entry_deref(&cache->attributes, attributes);
1054 assert(cache->delegations > 0);
1055 cache->delegations--;
1056 }
1057 status = NO_ERROR;
1058
1059out_unlock:
1061
1062 dprintf(NCLVL1, "<-- nfs41_name_cache_delegreturn() returning %d\n", status);
1063 return status;
1064}
1065
1067 IN struct nfs41_name_cache *cache,
1068 IN const char *path,
1069 IN const nfs41_component *name,
1070 IN uint64_t fileid,
1071 IN const change_info4 *cinfo)
1072{
1073 struct name_cache_entry *parent, *target;
1074 struct attr_cache_entry *attributes = NULL;
1075 int status;
1076
1077 dprintf(NCLVL1, "--> nfs41_name_cache_remove('%s')\n", path);
1078
1080
1081 if (!name_cache_enabled(cache)) {
1083 goto out_unlock;
1084 }
1085
1087 name->name + name->len, NULL, &parent, &target, NULL);
1089 goto out_attributes;
1090
1091 if (cinfo && name_cache_entry_changed(cache, parent, cinfo)) {
1093 goto out_attributes;
1094 }
1095
1097 goto out_attributes;
1098
1099 if (target->attributes)
1100 target->attributes->numlinks--;
1101
1102 /* make this a negative entry and unlink children */
1105
1106out_unlock:
1108
1109 dprintf(NCLVL1, "<-- nfs41_name_cache_remove() returning %d\n", status);
1110 return status;
1111
1112out_attributes:
1113 /* in the presence of other links, we need to update numlinks
1114 * regardless of a failure to find the target entry */
1115 dprintf(NCLVL1, "nfs41_name_cache_remove: need to find attributes for %s\n", path);
1116 attributes = attr_cache_search(&cache->attributes, fileid);
1117 if (attributes)
1118 attributes->numlinks--;
1119 goto out_unlock;
1120}
1121
1123 IN struct nfs41_name_cache *cache,
1124 IN const char *src_path,
1125 IN const nfs41_component *src_name,
1126 IN const change_info4 *src_cinfo,
1127 IN const char *dst_path,
1128 IN const nfs41_component *dst_name,
1129 IN const change_info4 *dst_cinfo)
1130{
1131 struct name_cache_entry *src_parent, *src;
1132 struct name_cache_entry *dst_parent;
1133 int status = NO_ERROR;
1134
1135 dprintf(NCLVL1, "--> nfs41_name_cache_rename('%s' to '%s')\n",
1136 src_path, dst_path);
1137
1139
1140 if (!name_cache_enabled(cache)) {
1142 goto out_unlock;
1143 }
1144
1145 /* look up dst_parent */
1146 status = name_cache_lookup(cache, 0, dst_path,
1147 dst_name->name, NULL, NULL, &dst_parent, NULL);
1148 /* we can't create the dst entry without a parent */
1149 if (status || dst_parent->attributes == NULL) {
1150 /* if src exists, make it negative */
1151 dprintf(NCLVL1, "nfs41_name_cache_rename: adding negative cache "
1152 "entry for %.*s\n", src_name->len, src_name->name);
1153 status = name_cache_lookup(cache, 0, src_path,
1154 src_name->name + src_name->len, NULL, NULL, &src, NULL);
1155 if (status == NO_ERROR) {
1158 }
1160 goto out_unlock;
1161 }
1162
1163 /* look up src_parent and src */
1164 status = name_cache_lookup(cache, 0, src_path,
1165 src_name->name + src_name->len, NULL, &src_parent, &src, NULL);
1166 /* we can't create the dst entry without valid attributes */
1167 if (status || src->attributes == NULL) {
1168 /* remove dst if it exists */
1169 struct name_cache_entry *dst;
1170 dprintf(NCLVL1, "nfs41_name_cache_rename: removing negative cache "
1171 "entry for %.*s\n", dst_name->len, dst_name->name);
1172 dst = name_cache_search(cache, dst_parent, dst_name);
1174 goto out_unlock;
1175 }
1176
1177 if (name_cache_entry_changed(cache, dst_parent, dst_cinfo)) {
1179 /* if dst_parent and src_parent are both gone,
1180 * we no longer have an entry to rename */
1181 if (dst_parent == src_parent)
1182 goto out_unlock;
1183 } else {
1184 struct name_cache_entry *existing;
1185 existing = name_cache_search(cache, dst_parent, dst_name);
1186 if (existing) {
1187 if (existing == src)
1188 goto out_unlock;
1189 /* remove the existing entry, but don't unlink it yet;
1190 * we may reuse it for a negative entry */
1191 name_cache_remove(existing, dst_parent);
1192 }
1193
1194 /* move the src entry under dst_parent */
1195 name_cache_remove(src, src_parent);
1196 name_cache_entry_rename(src, dst_name);
1197 name_cache_insert(src, dst_parent);
1198
1199 if (existing) {
1200 /* recycle 'existing' as the negative entry 'src' */
1201 name_cache_entry_rename(existing, src_name);
1202 name_cache_insert(existing, src_parent);
1203 }
1204 src = existing;
1205 }
1206
1207 if (name_cache_entry_changed(cache, src_parent, src_cinfo)) {
1209 goto out_unlock;
1210 }
1211
1212 /* leave a negative entry where the file used to be */
1213 if (src == NULL) {
1214 /* src was moved, create a new entry in its place */
1215 status = name_cache_find_or_create(cache, src_parent, src_name, &src);
1216 if (status)
1217 goto out_unlock;
1218 }
1221
1222out_unlock:
1224
1225 dprintf(NCLVL1, "<-- nfs41_name_cache_rename() returning %d\n", status);
1226 return status;
1227}
1228
1229/* nfs41_name_cache_resolve_fh() */
1230
1231#define MAX_PUTFH_PER_COMPOUND 16
1232
1234 IN struct nfs41_name_cache *cache,
1236 IN OUT const char **path_pos,
1237 IN uint32_t max_components,
1238 OUT nfs41_path_fh *files,
1240{
1241 struct name_cache_entry *target;
1242 const char *path_end = path->path + path->len;
1244 uint32_t i;
1245 int status;
1246
1247 *count = 0;
1248
1250
1251 /* look up the parent of the first component */
1252 status = name_cache_lookup(cache, 1, path->path,
1253 *path_pos, NULL, NULL, &target, NULL);
1254 if (status)
1255 goto out_unlock;
1256
1257 for (i = 0; i < max_components; i++) {
1258 files[i].path = path;
1259 name = &files[i].name;
1260
1261 if (!next_component(*path_pos, path_end, name))
1262 break;
1263 *path_pos = name->name + name->len;
1264
1266 if (target == NULL || entry_invis(target, NULL)) {
1267 if (is_last_component(name->name, path_end))
1269 else
1271 goto out_unlock;
1272 }
1273 /* make copies for use outside of cache->lock */
1274 fh_copy(&files[i].fh, &target->fh);
1275 (*count)++;
1276 }
1277
1278out_unlock:
1280 return *count && status == 0;
1281}
1282
1285 IN nfs41_path_fh *files,
1287 OUT uint32_t *valid_out)
1288{
1289 nfs41_compound compound;
1292 nfs41_sequence_args sequence_args;
1293 nfs41_sequence_res sequence_res = { 0 };
1295 nfs41_putfh_res putfh_res[MAX_PUTFH_PER_COMPOUND] = { 0 };
1296 uint32_t i;
1297 int status;
1298
1299 *valid_out = 0;
1300
1301 compound_init(&compound, argops, resops, "array_putfh");
1302
1303 compound_add_op(&compound, OP_SEQUENCE, &sequence_args, &sequence_res);
1304 nfs41_session_sequence(&sequence_args, session, 0);
1305
1306 for (i = 0; i < count; i++){
1307 compound_add_op(&compound, OP_PUTFH, &putfh_args[i], &putfh_res[i]);
1308 putfh_args[i].file = &files[i];
1309 putfh_args[i].in_recovery = 1;
1310 }
1311
1313 if (status) goto out;
1314
1315 status = sequence_res.sr_status;
1316 if (status) goto out;
1317
1318 for (i = 0; i < count; i++) {
1319 status = putfh_res[i].status;
1320 if (status) break;
1321 }
1322 *valid_out = i;
1323out:
1324 return status;
1325}
1326
1328 IN struct nfs41_name_cache *cache,
1330 IN const nfs41_abs_path *path,
1332{
1333 struct name_cache_entry *target;
1334 int status;
1335
1336 dprintf(NCLVL1, "--> delete_stale_component('%s')\n",
1337 component->name);
1338
1340
1341 status = name_cache_lookup(cache, 0, path->path,
1342 component->name + component->len, NULL, NULL, &target, NULL);
1343 if (status == NO_ERROR)
1345
1347
1348 dprintf(NCLVL1, "<-- delete_stale_component() returning %d\n", status);
1349 return status;
1350}
1351
1353 IN const nfs41_session *session)
1354{
1355 const uint32_t comps = session->fore_chan_attrs.ca_maxoperations - 1;
1356 return min(comps, MAX_PUTFH_PER_COMPOUND);
1357}
1358
1360 IN struct nfs41_name_cache *cache,
1363{
1365 const char *path_pos = path->path;
1366 const char* const path_end = path->path + path->len;
1367 const uint32_t max_components = max_putfh_components(session);
1369 int status = NO_ERROR;
1370
1372
1373 /* if there's no cache, don't check any components */
1375 path_pos = path_end;
1376
1378
1379 /* hold a lock on the path to protect against rename */
1380 AcquireSRWLockShared(&path->lock);
1381
1382 while (get_path_fhs(cache, path, &path_pos, max_components, files, &count)) {
1384
1387 session, path, &files[index].name);
1388 break;
1389 }
1390 if (status) {
1392 break;
1393 }
1394 }
1395
1396 ReleaseSRWLockShared(&path->lock);
1397
1398 return status;
1399}
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
#define index(s, c)
Definition: various.h:29
static void list_remove(struct list_entry *entry)
Definition: list.h:90
static int list_empty(struct list_entry *head)
Definition: list.h:58
static void list_add_tail(struct list_entry *head, struct list_entry *entry)
Definition: list.h:83
static void list_add_head(struct list_entry *head, struct list_entry *entry)
Definition: list.h:76
static void list_init(struct list_entry *head)
Definition: list.h:51
#define RB_INSERT(name, x, y)
Definition: tree.h:724
#define RB_HEAD(name, type)
Definition: tree.h:294
#define RB_ENTRY(type)
Definition: tree.h:308
#define RB_FOREACH_SAFE(x, name, head, y)
Definition: tree.h:743
#define RB_REMOVE(name, x, y)
Definition: tree.h:725
#define RB_GENERATE(name, type, field, cmp)
Definition: tree.h:398
#define RB_FIND(name, x, y)
Definition: tree.h:726
bool_t is_last_component(IN const char *path, IN const char *path_end)
Definition: util.c:330
void fh_copy(OUT nfs41_fh *dst, IN const nfs41_fh *src)
Definition: util.c:354
int nfs_to_windows_error(int status, int default_error)
Definition: util.c:235
bool_t next_component(IN const char *path, IN const char *path_end, OUT nfs41_component *component)
Definition: util.c:305
#define NO_ERROR
Definition: dderror.h:5
#define free
Definition: debug_ros.c:5
#define ERROR_OUTOFMEMORY
Definition: deptool.c:13
#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
INT64 int64_t
Definition: types.h:72
#define ERROR_NOT_SUPPORTED
Definition: compat.h:100
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
VOID WINAPI InitializeSRWLock(PSRWLOCK Lock)
Definition: sync.c:75
unsigned char
Definition: typeof.h:29
#define assert(x)
Definition: debug.h:53
r parent
Definition: btrfs.c:3010
__kernel_time_t time_t
Definition: linux.h:252
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLsizeiptr size
Definition: glext.h:5919
GLenum src
Definition: glext.h:6340
GLuint index
Definition: glext.h:6031
GLenum mode
Definition: glext.h:6217
GLenum GLenum dst
Definition: glext.h:6340
GLenum target
Definition: glext.h:7315
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
__u32 hidden
Definition: mkdosfs.c:13
__u16 time
Definition: mkdosfs.c:8
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
#define min(a, b)
Definition: monoChain.cc:55
static __inline void name_cache_unlink(IN struct nfs41_name_cache *cache, IN struct name_cache_entry *entry)
Definition: name_cache.c:428
#define NAME_CACHE_MAX_ENTRIES
Definition: name_cache.c:750
int nfs41_name_cache_delegreturn(IN struct nfs41_name_cache *cache, IN uint64_t fileid, IN const char *path, IN const nfs41_component *name)
Definition: name_cache.c:1012
int nfs41_name_cache_lookup(IN struct nfs41_name_cache *cache, IN const char *path, IN const char *path_end, OUT OPTIONAL const char **remaining_path_out, OUT OPTIONAL nfs41_fh *parent_out, OUT OPTIONAL nfs41_fh *target_out, OUT OPTIONAL nfs41_file_info *info_out, OUT OPTIONAL bool_t *is_negative)
Definition: name_cache.c:824
static int name_cache_lookup(IN struct nfs41_name_cache *cache, IN bool_t skip_invis, IN const char *path, IN const char *path_end, OUT OPTIONAL const char **remaining_path_out, OUT OPTIONAL struct name_cache_entry **parent_out, OUT OPTIONAL struct name_cache_entry **target_out, OUT OPTIONAL bool_t *is_negative)
Definition: name_cache.c:648
static __inline int attr_cache_entry_expired(IN const struct attr_cache_entry *entry)
Definition: name_cache.c:178
static void attr_cache_update(IN struct attr_cache_entry *entry, IN const nfs41_file_info *info, IN enum open_delegation_type4 delegation)
Definition: name_cache.c:282
static bool_t get_path_fhs(IN struct nfs41_name_cache *cache, IN nfs41_abs_path *path, IN OUT const char **path_pos, IN uint32_t max_components, OUT nfs41_path_fh *files, OUT uint32_t *count)
Definition: name_cache.c:1233
static __inline void attr_cache_entry_ref(IN struct attr_cache *cache, IN struct attr_cache_entry *entry)
Definition: name_cache.c:157
static void copy_attrs(OUT nfs41_file_info *dst, IN const struct attr_cache_entry *src)
Definition: name_cache.c:329
#define NAME_CACHE_EXPIRATION
Definition: name_cache.c:42
static __inline void attr_cache_entry_free(IN struct attr_cache *cache, IN struct attr_cache_entry *entry)
Definition: name_cache.c:147
static int rpc_array_putfh(IN nfs41_session *session, IN nfs41_path_fh *files, IN uint32_t count, OUT uint32_t *valid_out)
Definition: name_cache.c:1283
static __inline bool_t is_delegation(IN enum open_delegation_type4 type)
Definition: name_cache.c:72
@ NCLVL1
Definition: name_cache.c:37
@ NCLVL2
Definition: name_cache.c:38
static int name_cache_find_or_create(IN struct nfs41_name_cache *cache, IN struct name_cache_entry *parent, IN const nfs41_component *component, OUT struct name_cache_entry **target_out)
Definition: name_cache.c:712
static int attr_cache_entry_create(IN struct attr_cache *cache, IN uint64_t fileid, OUT struct attr_cache_entry **entry_out)
Definition: name_cache.c:123
static int name_cache_entry_create(IN struct nfs41_name_cache *cache, IN const nfs41_component *component, OUT struct name_cache_entry **entry_out)
Definition: name_cache.c:459
static __inline uint32_t max_putfh_components(IN const nfs41_session *session)
Definition: name_cache.c:1352
static __inline bool_t name_cache_enabled(IN struct nfs41_name_cache *cache)
Definition: name_cache.c:401
#define ATTR_ENTRY_SIZE
Definition: name_cache.c:103
static int attr_cache_init(IN struct attr_cache *cache, IN uint32_t max_entries)
Definition: name_cache.c:186
static void attr_cache_free(IN struct attr_cache *cache)
Definition: name_cache.c:210
static int name_cache_insert(IN struct name_cache_entry *entry, IN struct name_cache_entry *parent)
Definition: name_cache.c:696
static __inline void name_cache_remove(IN struct name_cache_entry *entry, IN struct name_cache_entry *parent)
Definition: name_cache.c:416
static __inline void copy_fh(OUT nfs41_fh *dst, IN OPTIONAL const struct name_cache_entry *src)
Definition: name_cache.c:814
int nfs41_name_cache_insert(IN struct nfs41_name_cache *cache, IN const char *path, IN const nfs41_component *name, IN OPTIONAL const nfs41_fh *fh, IN OPTIONAL const nfs41_file_info *info, IN OPTIONAL const change_info4 *cinfo, IN enum open_delegation_type4 delegation)
Definition: name_cache.c:923
static void name_cache_entry_accessed(IN struct nfs41_name_cache *cache, IN struct name_cache_entry *entry)
Definition: name_cache.c:492
static struct attr_cache_entry * attr_cache_search(IN struct attr_cache *cache, IN uint64_t fileid)
Definition: name_cache.c:219
static void name_cache_entry_invalidate(IN struct nfs41_name_cache *cache, IN struct name_cache_entry *entry)
Definition: name_cache.c:587
static int delete_stale_component(IN struct nfs41_name_cache *cache, IN nfs41_session *session, IN const nfs41_abs_path *path, IN const nfs41_component *component)
Definition: name_cache.c:1327
static __inline void attr_cache_entry_deref(IN struct attr_cache *cache, IN struct attr_cache_entry *entry)
Definition: name_cache.c:166
int name_cmp(struct name_cache_entry *lhs, struct name_cache_entry *rhs)
Definition: name_cache.c:375
#define NAME_ENTRY_SIZE
Definition: name_cache.c:373
#define attr_entry(pos)
Definition: name_cache.c:121
int nfs41_name_cache_remove(IN struct nfs41_name_cache *cache, IN const char *path, IN const nfs41_component *name, IN uint64_t fileid, IN const change_info4 *cinfo)
Definition: name_cache.c:1066
int nfs41_name_cache_remove_stale(IN struct nfs41_name_cache *cache, IN nfs41_session *session, IN nfs41_abs_path *path)
Definition: name_cache.c:1359
int attr_cmp(struct attr_cache_entry *lhs, struct attr_cache_entry *rhs)
Definition: name_cache.c:113
static void name_cache_entry_updated(IN struct nfs41_name_cache *cache, IN struct name_cache_entry *entry)
Definition: name_cache.c:510
static int attr_cache_find_or_create(IN struct attr_cache *cache, IN uint64_t fileid, OUT struct attr_cache_entry **entry_out)
Definition: name_cache.c:244
static __inline void name_cache_entry_rename(OUT struct name_cache_entry *entry, IN const nfs41_component *component)
Definition: name_cache.c:407
static int name_cache_entry_update(IN struct nfs41_name_cache *cache, IN struct name_cache_entry *entry, IN OPTIONAL const nfs41_fh *fh, IN OPTIONAL const nfs41_file_info *info, IN enum open_delegation_type4 delegation)
Definition: name_cache.c:519
int nfs41_attr_cache_update(IN struct nfs41_name_cache *cache, IN uint64_t fileid, IN const nfs41_file_info *info)
Definition: name_cache.c:891
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 int attr_cache_insert(IN struct attr_cache *cache, IN struct attr_cache_entry *entry)
Definition: name_cache.c:229
#define MAX_PUTFH_PER_COMPOUND
Definition: name_cache.c:1231
static int entry_invis(IN struct name_cache_entry *entry, OUT OPTIONAL bool_t *is_negative)
Definition: name_cache.c:624
static void name_cache_unlink_children_recursive(IN struct nfs41_name_cache *cache, IN struct name_cache_entry *parent)
Definition: name_cache.c:450
int nfs41_name_cache_create(OUT struct nfs41_name_cache **cache_out)
Definition: name_cache.c:752
static int name_cache_entry_changed(IN struct nfs41_name_cache *cache, IN struct name_cache_entry *entry, IN const change_info4 *cinfo)
Definition: name_cache.c:563
static struct name_cache_entry * name_cache_search(IN struct nfs41_name_cache *cache, IN struct name_cache_entry *parent, IN const nfs41_component *component)
Definition: name_cache.c:601
#define name_entry(pos)
Definition: name_cache.c:399
int nfs41_name_cache_free(IN struct nfs41_name_cache **cache_out)
Definition: name_cache.c:796
int nfs41_name_cache_rename(IN struct nfs41_name_cache *cache, IN const char *src_path, IN const nfs41_component *src_name, IN const change_info4 *src_cinfo, IN const char *dst_path, IN const nfs41_component *dst_name, IN const change_info4 *dst_cinfo)
Definition: name_cache.c:1122
void nfs41_session_sequence(struct __nfs41_sequence_args *args, nfs41_session *session, bool_t cachethis)
void compound_init(nfs41_compound *compound, nfs_argop4 *argops, nfs_resop4 *resops, const char *tag)
int compound_encode_send_decode(nfs41_session *session, nfs41_compound *compound, bool_t try_recovery)
void compound_add_op(nfs41_compound *compound, uint32_t opnum, void *arg, void *res)
@ FATTR4_WORD0_HIDDEN
Definition: nfs41_const.h:237
@ FATTR4_WORD1_TIME_CREATE
Definition: nfs41_const.h:262
@ FATTR4_WORD1_MODE
Definition: nfs41_const.h:245
@ FATTR4_WORD1_TIME_MODIFY
Definition: nfs41_const.h:265
@ FATTR4_WORD0_ARCHIVE
Definition: nfs41_const.h:227
@ FATTR4_WORD1_TIME_ACCESS
Definition: nfs41_const.h:259
@ FATTR4_WORD0_TYPE
Definition: nfs41_const.h:208
@ FATTR4_WORD1_SYSTEM
Definition: nfs41_const.h:258
@ FATTR4_WORD0_CHANGE
Definition: nfs41_const.h:210
@ FATTR4_WORD1_NUMLINKS
Definition: nfs41_const.h:247
@ FATTR4_WORD0_FILEID
Definition: nfs41_const.h:232
@ FATTR4_WORD0_SIZE
Definition: nfs41_const.h:211
@ NFS_FTYPE_MASK
Definition: nfs41_const.h:304
#define NFS41_MAX_COMPONENT_LEN
Definition: nfs41_const.h:45
@ NFS4ERR_FHEXPIRED
Definition: nfs41_const.h:119
@ NFS4ERR_STALE
Definition: nfs41_const.h:106
open_delegation_type4
Definition: nfs41_ops.h:585
@ OPEN_DELEGATE_NONE
Definition: nfs41_ops.h:586
@ OPEN_DELEGATE_READ
Definition: nfs41_ops.h:587
@ OPEN_DELEGATE_WRITE
Definition: nfs41_ops.h:588
@ OP_SEQUENCE
Definition: nfs41_ops.h:83
@ OP_PUTFH
Definition: nfs41_ops.h:50
#define dprintf
Definition: regdump.c:33
static FILE * out
Definition: regtests2xml.c:44
#define calloc
Definition: rosglue.h:14
int __cdecl system(_In_opt_z_ const char *_Command)
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
STRSAFEAPI StringCchCopyNA(STRSAFE_LPSTR pszDest, size_t cchDest, STRSAFE_LPCSTR pszSrc, size_t cchToCopy)
Definition: strsafe.h:230
unsigned char fh[NFS4_FHSIZE]
Definition: nfs41_types.h:53
nfs41_path_fh * file
Definition: nfs41_ops.h:510
uint32_t status
Definition: nfs41_ops.h:515
Definition: name_cache.c:80
struct attr_cache_entry * pool
Definition: name_cache.c:109
struct attr_tree head
Definition: name_cache.c:108
struct list_entry free_entries
Definition: name_cache.c:110
Definition: cache.c:49
HANDLE lock
Definition: cache.c:52
char * name
Definition: compiler.c:66
unsigned int count
Definition: notification.c:64
Definition: list.h:27
Definition: name_cache.c:362
char component[NFS41_MAX_COMPONENT_LEN]
Definition: name_cache.c:363
nfs41_fh fh
Definition: name_cache.c:364
Definition: name.c:39
WCHAR * name
Definition: name.c:42
uint32_t expiration
Definition: name_cache.c:387
struct name_cache_entry * root
Definition: name_cache.c:383
struct name_cache_entry * pool
Definition: name_cache.c:384
uint32_t delegations
Definition: name_cache.c:390
uint32_t max_delegations
Definition: name_cache.c:391
uint32_t entries
Definition: name_cache.c:388
uint32_t max_entries
Definition: name_cache.c:389
Definition: ps.c:97
#define IN
Definition: typedefs.h:39
#define OUT
Definition: typedefs.h:40
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define ERROR_TOO_MANY_OPEN_FILES
Definition: winerror.h:107
#define ERROR_PATH_NOT_FOUND
Definition: winerror.h:106
#define ERROR_FILE_EXISTS
Definition: winerror.h:165