ReactOS 0.4.15-dev-7196-g0fe0b40
pnfs_layout.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 <stdio.h>
23
24#include "nfs41_ops.h"
25#include "nfs41_callback.h"
26#include "util.h"
27#include "daemon_debug.h"
28
29
30#define FLLVL 2 /* dprintf level for file layout logging */
31
32
33/* pnfs_layout_list */
37};
38
39#define state_entry(pos) list_container(pos, pnfs_layout_state, entry)
40#define layout_entry(pos) list_container(pos, pnfs_layout, entry)
41#define file_layout_entry(pos) list_container(pos, pnfs_file_layout, layout.entry)
42
44 IN const nfs41_fh *meta_fh,
45 OUT pnfs_layout_state **layout_out)
46{
49
50 layout = calloc(1, sizeof(pnfs_layout_state));
51 if (layout == NULL) {
53 goto out;
54 }
55
56 fh_copy(&layout->meta_fh, meta_fh);
57 list_init(&layout->layouts);
58 list_init(&layout->recalls);
61
62 *layout_out = layout;
63out:
64 return status;
65}
66
67static void file_layout_free(
69{
70 if (layout->device) pnfs_file_device_put(layout->device);
71 free(layout->filehandles.arr);
72 free(layout);
73}
74
77{
78 struct list_entry *entry, *tmp;
79 list_for_each_tmp(entry, tmp, &state->layouts)
81 list_init(&state->layouts);
82}
83
86{
87 struct list_entry *entry, *tmp;
88 list_for_each_tmp(entry, tmp, &state->recalls)
90 list_init(&state->recalls);
91}
92
95{
98 free(state);
99}
100
102 IN const struct list_entry *entry,
103 IN const void *value)
104{
106 const nfs41_fh *meta_fh = (const nfs41_fh*)value;
107 const nfs41_fh *layout_fh = (const nfs41_fh*)&layout->meta_fh;
108 const uint32_t diff = layout_fh->len - meta_fh->len;
109 return diff ? diff : memcmp(layout_fh->fh, meta_fh->fh, meta_fh->len);
110}
111
113 IN struct pnfs_layout_list *layouts,
114 IN const nfs41_fh *meta_fh,
115 OUT struct list_entry **entry_out)
116{
117 *entry_out = list_search(&layouts->head, meta_fh, layout_entry_compare);
118 return *entry_out ? PNFS_SUCCESS : PNFSERR_NO_LAYOUT;
119}
120
122 OUT struct pnfs_layout_list **layouts_out)
123{
124 struct pnfs_layout_list *layouts;
126
127 layouts = calloc(1, sizeof(struct pnfs_layout_list));
128 if (layouts == NULL) {
130 goto out;
131 }
132 list_init(&layouts->head);
134 *layouts_out = layouts;
135out:
136 return status;
137}
138
140 IN struct pnfs_layout_list *layouts)
141{
142 struct list_entry *entry, *tmp;
143
144 EnterCriticalSection(&layouts->lock);
145
146 list_for_each_tmp(entry, tmp, &layouts->head)
148
149 LeaveCriticalSection(&layouts->lock);
150 DeleteCriticalSection(&layouts->lock);
151 free(layouts);
152}
153
155 IN struct pnfs_layout_list *layouts,
156 IN const nfs41_fh *meta_fh,
157 OUT pnfs_layout_state **layout_out)
158{
159 struct list_entry *entry;
160 enum pnfs_status status;
161
162 dprintf(FLLVL, "--> layout_state_find_or_create()\n");
163
164 EnterCriticalSection(&layouts->lock);
165
166 /* search for an existing layout */
167 status = layout_entry_find(layouts, meta_fh, &entry);
168 if (status) {
169 /* create a new layout */
171 status = layout_state_create(meta_fh, &layout);
172 if (status == PNFS_SUCCESS) {
173 /* add it to the list */
174 list_add_head(&layouts->head, &layout->entry);
175 *layout_out = layout;
176
177 dprintf(FLLVL, "<-- layout_state_find_or_create() "
178 "returning new layout %p\n", layout);
179 } else {
180 dprintf(FLLVL, "<-- layout_state_find_or_create() "
181 "returning %s\n", pnfs_error_string(status));
182 }
183 } else {
184 *layout_out = state_entry(entry);
185
186 dprintf(FLLVL, "<-- layout_state_find_or_create() "
187 "returning existing layout %p\n", *layout_out);
188 }
189
190 LeaveCriticalSection(&layouts->lock);
191 return status;
192}
193
195 IN struct pnfs_layout_list *layouts,
196 IN const nfs41_fh *meta_fh)
197{
198 struct list_entry *entry;
199 enum pnfs_status status;
200
201 dprintf(FLLVL, "--> layout_state_find_and_delete()\n");
202
203 EnterCriticalSection(&layouts->lock);
204
205 status = layout_entry_find(layouts, meta_fh, &entry);
206 if (status == PNFS_SUCCESS) {
209 }
210
211 LeaveCriticalSection(&layouts->lock);
212
213 dprintf(FLLVL, "<-- layout_state_find_and_delete() "
214 "returning %s\n", pnfs_error_string(status));
215 return status;
216}
217
218
219/* pnfs_file_layout */
221 IN const pnfs_layout *layout)
222{
223 uint64_t result = layout->offset + layout->length;
224 return result < layout->offset ? NFS4_UINT64_MAX : result;
225}
226
229{
230 /* prevent div/0 */
231 if (layout->layout.length == 0 ||
232 layout->layout.iomode < PNFS_IOMODE_READ ||
233 layout->layout.iomode > PNFS_IOMODE_RW ||
235 return FALSE;
236
237 /* put a cap on layout.length to prevent overflow */
238 layout->layout.length = range_max(&layout->layout) - layout->layout.offset;
239 return TRUE;
240}
241
243 IN const pnfs_file_layout_handles *lhs,
244 IN const pnfs_file_layout_handles *rhs)
245{
246 const uint32_t diff = rhs->count - lhs->count;
247 return diff ? diff : memcmp(rhs->arr, lhs->arr,
248 rhs->count * sizeof(nfs41_path_fh));
249}
250
254{
255 const uint64_t to_max = range_max(&to->layout);
256 const uint64_t from_max = range_max(&from->layout);
257
258 /* cannot merge a segment with itself */
259 if (to == from)
260 return FALSE;
261
262 /* the ranges must meet or overlap */
263 if (to_max < from->layout.offset || from_max < to->layout.offset)
264 return FALSE;
265
266 /* the following fields must match: */
267 if (to->layout.iomode != from->layout.iomode ||
268 to->layout.type != from->layout.type ||
269 layout_filehandles_cmp(&to->filehandles, &from->filehandles) != 0 ||
270 memcmp(to->deviceid, from->deviceid, PNFS_DEVICEID_SIZE) != 0 ||
271 to->pattern_offset != from->pattern_offset ||
272 to->first_index != from->first_index ||
273 to->util != from->util)
274 return FALSE;
275
276 dprintf(FLLVL, "merging layout range {%llu, %llu} with {%llu, %llu}\n",
277 to->layout.offset, to->layout.length,
278 from->layout.offset, from->layout.length);
279
280 /* calculate the union of the two ranges */
281 to->layout.offset = min(to->layout.offset, from->layout.offset);
282 to->layout.length = max(to_max, from_max) - to->layout.offset;
283 return TRUE;
284}
285
289{
290 struct list_entry *entry, *tmp;
293
294 /* attempt to merge the new segment with each existing segment */
295 list_for_each_tmp(entry, tmp, &state->layouts) {
297 if (!layout_merge_segments(to, from))
298 continue;
299
300 /* on success, remove/free the new segment */
301 list_remove(&from->layout.entry);
304
305 /* because the existing segment 'to' has grown, we may
306 * be able to merge it with later segments */
307 from = to;
308
309 /* but if there could be io threads referencing this segment,
310 * we can't free it until io is finished */
311 if (state->io_count)
312 break;
313 }
314 return status;
315}
316
320{
321 struct list_entry *entry;
322 list_for_each(entry, &state->layouts) {
323 pnfs_layout *existing = layout_entry(entry);
324
325 /* maintain an order of increasing offset */
326 if (existing->offset < layout->offset)
327 continue;
328
329 /* when offsets are equal, prefer a longer segment first */
330 if (existing->offset == layout->offset &&
331 existing->length > layout->length)
332 continue;
333
334 list_add(&layout->entry, existing->entry.prev, &existing->entry);
335 return;
336 }
337
338 list_add_tail(&state->layouts, &layout->entry);
339}
340
343 IN const struct list_entry *layouts)
344{
345 struct list_entry *entry, *tmp;
348
349 list_for_each_tmp(entry, tmp, layouts) {
351
352 /* don't know what to do with non-file layouts */
353 if (layout->layout.type != PNFS_LAYOUTTYPE_FILE)
354 continue;
355
358 continue;
359 }
360
361 /* attempt to merge the range with existing segments */
363 if (status) {
364 dprintf(FLLVL, "saving new layout:\n");
366
369 }
370 }
371 return status;
372}
373
376 IN const stateid4 *stateid)
377{
379
380 if (state->stateid.seqid == 0) {
381 /* save a new layout stateid */
382 memcpy(&state->stateid, stateid, sizeof(stateid4));
383 } else if (memcmp(&state->stateid.other, stateid->other,
384 NFS4_STATEID_OTHER) == 0) {
385 /* update an existing layout stateid */
386 state->stateid.seqid = stateid->seqid;
387 } else {
389 }
390 return status;
391}
392
395 IN const pnfs_layoutget_res_ok *layoutget_res)
396{
397 enum pnfs_status status;
398
399 /* update the layout ranges held by the client */
400 status = layout_update_range(state, &layoutget_res->layouts);
401 if (status) {
402 eprintf("LAYOUTGET didn't return any file layouts\n");
403 goto out;
404 }
405 /* update the layout stateid */
406 status = layout_update_stateid(state, &layoutget_res->stateid);
407 if (status) {
408 eprintf("LAYOUTGET returned a new stateid when we already had one\n");
409 goto out;
410 }
411 /* if a previous LAYOUTGET set return_on_close, don't overwrite it */
412 if (!state->return_on_close)
413 state->return_on_close = layoutget_res->return_on_close;
414out:
415 return status;
416}
417
421 IN nfs41_path_fh *meta_file,
422 IN stateid_arg *stateid,
423 IN enum pnfs_iomode iomode,
425 IN uint64_t minlength,
427{
428 pnfs_layoutget_res_ok layoutget_res = { 0 };
429 enum pnfs_status pnfsstat = PNFS_SUCCESS;
430 enum nfsstat4 nfsstat;
431
432 dprintf(FLLVL, "--> file_layout_fetch(%s, seqid=%u)\n",
433 pnfs_iomode_string(iomode), state->stateid.seqid);
434
435 list_init(&layoutget_res.layouts);
436
437 /* drop the lock during the rpc call */
439 nfsstat = pnfs_rpc_layoutget(session, meta_file, stateid,
440 iomode, offset, minlength, length, &layoutget_res);
442
443 if (nfsstat) {
444 dprintf(FLLVL, "pnfs_rpc_layoutget() failed with %s\n",
445 nfs_error_string(nfsstat));
446 pnfsstat = PNFSERR_NOT_SUPPORTED;
447 }
448
449 switch (nfsstat) {
450 case NFS4_OK:
451 /* use the LAYOUTGET results to update our view of the layout */
452 pnfsstat = layout_update(state, &layoutget_res);
453 break;
454
456 /* don't try RW again */
457 if (iomode == PNFS_IOMODE_RW)
458 state->status |= PNFS_LAYOUT_NOT_RW;
459 break;
460
464 /* don't try again at all */
466 break;
467 }
468
469 dprintf(FLLVL, "<-- file_layout_fetch() returning %s\n",
470 pnfs_error_string(pnfsstat));
471 return pnfsstat;
472}
473
474/* returns PNFS_SUCCESS if the client holds valid layouts that cover
475 * the entire range requested. otherwise, returns PNFS_PENDING and
476 * sets 'offset_missing' to the lowest offset that is not covered */
479 IN enum pnfs_iomode iomode,
482 OUT uint64_t *offset_missing)
483{
484 uint64_t position = offset;
485 struct list_entry *entry;
486
487 list_for_each(entry, &state->layouts) {
488 /* if the current position intersects with a compatible
489 * layout, move the position to the end of that layout */
491 if (layout->iomode >= iomode &&
492 layout->offset <= position &&
493 position < layout->offset + layout->length)
494 position = layout->offset + layout->length;
495 }
496
497 if (position >= offset + length)
498 return PNFS_SUCCESS;
499
500 *offset_missing = position;
501 return PNFS_PENDING;
502}
503
507 IN nfs41_path_fh *meta_file,
508 IN stateid_arg *stateid,
509 IN enum pnfs_iomode iomode,
512{
513 stateid_arg layout_stateid = { 0 };
515
516 /* check for previous errors from LAYOUTGET */
517 if ((state->status & PNFS_LAYOUT_UNAVAILABLE) ||
518 ((state->status & PNFS_LAYOUT_NOT_RW) && iomode == PNFS_IOMODE_RW)) {
520 goto out;
521 }
522
523 /* wait for any pending LAYOUTGETs/LAYOUTRETURNs */
524 while (state->pending)
525 SleepConditionVariableSRW(&state->cond, &state->lock, INFINITE, 0);
526 state->pending = TRUE;
527
528 /* if there's an existing layout stateid, use it */
529 if (state->stateid.seqid) {
530 memcpy(&layout_stateid.stateid, &state->stateid, sizeof(stateid4));
531 layout_stateid.type = STATEID_LAYOUT;
532 stateid = &layout_stateid;
533 }
534
535 if ((state->status & PNFS_LAYOUT_NOT_RW) == 0) {
536 /* try to get a RW layout first */
539 }
540
541 if (status && iomode == PNFS_IOMODE_READ) {
542 /* fall back on READ if necessary */
544 stateid, iomode, offset, length, NFS4_UINT64_MAX);
545 }
546
547 state->pending = FALSE;
549out:
550 return status;
551}
552
557 OUT unsigned char *deviceid)
558{
559 struct list_entry *entry;
561
562 list_for_each(entry, &state->layouts) {
564
565 if (layout->device == NULL) {
566 /* copy missing deviceid */
567 memcpy(deviceid, layout->deviceid, PNFS_DEVICEID_SIZE);
569 break;
570 }
571 }
572 return status;
573}
574
575static void device_assign(
577 IN const unsigned char *deviceid,
579{
580 struct list_entry *entry;
581 list_for_each(entry, &state->layouts) {
583
584 /* assign the device to any matching layouts */
585 if (layout->device == NULL &&
586 memcmp(layout->deviceid, deviceid, PNFS_DEVICEID_SIZE) == 0) {
587 layout->device = device;
588
589 /* XXX: only assign the device to a single segment, because
590 * pnfs_file_device_get() only gives us a single reference */
591 break;
592 }
593 }
594}
595
599 IN unsigned char *deviceid)
600{
602 enum pnfs_status status;
603
604 /* drop the layoutstate lock for the rpc call */
607 session->client->devices, deviceid, &device);
609
610 if (status == PNFS_SUCCESS)
611 device_assign(state, deviceid, device);
612 return status;
613}
614
615
616/* nfs41_open_state */
619{
620 enum pnfs_status status;
621 AcquireSRWLockShared(&client->exid_lock);
624 ReleaseSRWLockShared(&client->exid_lock);
625 return status;
626}
627
631{
632 const uint32_t flag = 1 << (type - 1);
633 return (superblock->layout_types & flag) == 0
635}
636
639 OUT pnfs_layout_state **layout_out)
640{
642
643 if (state->layout) {
645 *layout_out = state->layout;
646
647 dprintf(FLLVL, "pnfs_open_state_layout() found "
648 "cached layout %p\n", *layout_out);
649 }
650 return status;
651}
652
655 OUT pnfs_layout_state **layout_out)
656{
657 struct pnfs_layout_list *layouts = state->session->client->layouts;
658 nfs41_session *session = state->session;
660 enum pnfs_status status;
661
662 dprintf(FLLVL, "--> pnfs_layout_state_open()\n");
663
665 if (status)
666 goto out;
667 status = fs_supports_layout(state->file.fh.superblock, PNFS_LAYOUTTYPE_FILE);
668 if (status)
669 goto out;
670
671 /* under shared lock, check open state for cached layouts */
675
676 if (status) {
677 /* under exclusive lock, find or create a layout for this file */
679
681 if (status) {
682 status = layout_state_find_or_create(layouts, &state->file.fh, &layout);
683 if (status == PNFS_SUCCESS) {
684 LONG open_count = InterlockedIncrement(&layout->open_count);
685 state->layout = layout;
686
687 dprintf(FLLVL, "pnfs_layout_state_open() caching layout %p "
688 "(%u opens)\n", state->layout, open_count);
689 }
690 }
691
693
694 if (status)
695 goto out;
696 }
697
698 *layout_out = layout;
699out:
700 dprintf(FLLVL, "<-- pnfs_layout_state_open() returning %s\n",
702 return status;
703}
704
705/* expects caller to hold an exclusive lock on pnfs_layout_state */
709 IN nfs41_path_fh *meta_file,
710 IN stateid_arg *stateid,
711 IN enum pnfs_iomode iomode,
714{
715 unsigned char deviceid[PNFS_DEVICEID_SIZE];
716 struct list_entry *entry;
717 uint64_t missing;
718 enum pnfs_status status;
719
720 /* fail if the range intersects any pending recalls */
721 list_for_each(entry, &state->recalls) {
722 const pnfs_layout *recall = layout_entry(entry);
723 if (offset <= recall->offset + recall->length
724 && recall->offset <= offset + length) {
726 goto out;
727 }
728 }
729
730 /* if part of the given range is not covered by a layout,
731 * attempt to fetch it with LAYOUTGET */
732 status = layout_coverage_status(state, iomode, offset, length, &missing);
733 if (status == PNFS_PENDING) {
734 status = layout_fetch(state, session, meta_file, stateid,
735 iomode, missing, offset + length - missing);
736
737 /* return pending because layout_fetch() dropped the lock */
738 if (status == PNFS_SUCCESS)
740 goto out;
741 }
742
743 /* if any layouts in the range are missing device info,
744 * fetch them with GETDEVICEINFO */
745 status = device_status(state, offset, length, deviceid);
746 if (status == PNFS_PENDING) {
747 status = device_fetch(state, session, deviceid);
748
749 /* return pending because device_fetch() dropped the lock */
750 if (status == PNFS_SUCCESS)
752 goto out;
753 }
754out:
755 return status;
756}
757
760{
761 /* return the layout if we have a stateid */
762 return state->stateid.seqid ? PNFS_SUCCESS : PNFS_PENDING;
763}
764
769{
770 enum pnfs_status status;
771 enum nfsstat4 nfsstat;
772
773 dprintf(FLLVL, "--> file_layout_return()\n");
774
775 /* under shared lock, determine whether we need to return the layout */
779
780 if (status != PNFS_PENDING)
781 goto out;
782
783 /* under exclusive lock, return the layout and reset status flags */
785
786 /* wait for any pending LAYOUTGETs/LAYOUTRETURNs */
787 while (state->pending)
788 SleepConditionVariableSRW(&state->cond, &state->lock, INFINITE, 0);
789 state->pending = TRUE;
790
792 if (status == PNFS_PENDING) {
793 pnfs_layoutreturn_res layoutreturn_res = { 0 };
794 stateid4 stateid;
795 memcpy(&stateid, &state->stateid, sizeof(stateid));
796
797 /* drop the lock during the rpc call */
800 PNFS_IOMODE_ANY, 0, NFS4_UINT64_MAX, &stateid, &layoutreturn_res);
802
803 if (nfsstat) {
804 eprintf("pnfs_rpc_layoutreturn() failed with %s\n",
805 nfs_error_string(nfsstat));
807 } else {
809
810 /* update the layout range held by the client */
812
813 /* 12.5.3. Layout Stateid: Once a client has no more
814 * layouts on a file, the layout stateid is no longer
815 * valid and MUST NOT be used. */
816 ZeroMemory(&state->stateid, sizeof(stateid4));
817 }
818 }
819
820 state->pending = FALSE;
823
824out:
825 dprintf(FLLVL, "<-- file_layout_return() returning %s\n",
827 return status;
828}
829
834{
836 bool_t return_layout;
837 enum pnfs_status status;
838
840 layout = state->layout;
841 state->layout = NULL;
843
844 if (layout) {
845 LONG open_count = InterlockedDecrement(&layout->open_count);
846
848 /* only return on close if it's the last close */
849 return_layout = layout->return_on_close && (open_count <= 0);
851
852 if (return_layout) {
854 if (status)
855 eprintf("file_layout_return() failed with %s\n",
857 }
858 }
859
860 if (remove && session->client->layouts) {
861 /* free the layout when the file is removed */
862 layout_state_find_and_delete(session->client->layouts, &state->file.fh);
863 }
864}
865
866
867/* pnfs_layout_recall */
871};
872#define recall_entry(pos) list_container(pos, struct layout_recall, layout.entry)
873
875 IN const pnfs_layout *layout,
876 IN const pnfs_layout *recall)
877{
878 return layout->type == recall->type
879 && layout->offset <= (recall->offset + recall->length)
880 && recall->offset <= (layout->offset + layout->length)
881 && (recall->iomode == PNFS_IOMODE_ANY ||
882 layout->iomode == recall->iomode);
883}
884
886 IN const pnfs_file_layout *existing)
887{
888 /* allocate a segment to cover the end of the range */
890 if (layout == NULL)
891 goto out;
892
893 memcpy(layout, existing, sizeof(pnfs_file_layout));
894
895 /* XXX: don't use the device from existing layout;
896 * we need to get a reference for ourselves */
897 layout->device = NULL;
898
899 /* allocate a copy of the filehandle array */
900 layout->filehandles.arr = calloc(layout->filehandles.count,
901 sizeof(nfs41_path_fh));
902 if (layout->filehandles.arr == NULL)
903 goto out_free;
904
905 memcpy(layout->filehandles.arr, existing->filehandles.arr,
906 layout->filehandles.count * sizeof(nfs41_path_fh));
907out:
908 return layout;
909
910out_free:
912 layout = NULL;
913 goto out;
914}
915
918 IN const pnfs_layout *recall)
919{
920 struct list_entry *entry, *tmp;
921 list_for_each_tmp(entry, tmp, &state->layouts) {
923 const uint64_t layout_end = layout->layout.offset + layout->layout.length;
924
925 if (!layout_recall_compatible(&layout->layout, recall))
926 continue;
927
928 if (recall->offset > layout->layout.offset) {
929 /* segment starts before recall; shrink length */
930 layout->layout.length = recall->offset - layout->layout.offset;
931
932 if (layout_end > recall->offset + recall->length) {
933 /* middle chunk of the segment is recalled;
934 * allocate a new segment to cover the end */
936 if (remainder == NULL) {
937 /* silently ignore allocation errors here. behave
938 * as if we 'forgot' this last segment */
939 } else {
940 layout->layout.offset = recall->offset + recall->length;
941 layout->layout.length = layout_end - layout->layout.offset;
943 }
944 }
945 } else {
946 /* segment starts after recall */
947 if (layout_end <= recall->offset + recall->length) {
948 /* entire segment is recalled */
949 list_remove(&layout->layout.entry);
951 } else {
952 /* beginning of segment is recalled; shrink offset/length */
953 layout->layout.offset = recall->offset + recall->length;
954 layout->layout.length = layout_end - layout->layout.offset;
955 }
956 }
957 }
958}
959
962{
963 struct list_entry *entry, *tmp;
964 list_for_each_tmp(entry, tmp, &state->recalls) {
965 /* process each deferred layout recall */
966 pnfs_layout *recall = layout_entry(entry);
967 layout_recall_range(state, recall);
968
969 /* remove/free the recall entry */
970 list_remove(&recall->entry);
971 free(recall);
972 }
973}
974
976 OUT struct layout_recall *lrc,
977 IN const struct cb_layoutrecall_args *recall)
978{
979 list_init(&lrc->layout.entry);
980 if (recall->recall.type == PNFS_RETURN_FILE) {
981 lrc->layout.offset = recall->recall.args.file.offset;
982 lrc->layout.length = recall->recall.args.file.length;
983 } else {
984 lrc->layout.offset = 0;
985 lrc->layout.length = NFS4_UINT64_MAX;
986 }
987 lrc->layout.iomode = recall->iomode;
988 lrc->layout.type = PNFS_LAYOUTTYPE_FILE;
989 lrc->changed = recall->changed;
990}
991
993 IN struct list_entry *list,
995{
996 struct list_entry *entry, *tmp;
998
999 /* attempt to merge the new recall with each existing recall */
1002 const uint64_t to_max = to->offset + to->length;
1003 const uint64_t from_max = from->offset + from->length;
1004
1005 /* the ranges must meet or overlap */
1006 if (to_max < from->offset || from_max < to->offset)
1007 continue;
1008
1009 /* the following fields must match: */
1010 if (to->iomode != from->iomode || to->type != from->type)
1011 continue;
1012
1013 dprintf(FLLVL, "merging recalled range {%llu, %llu} with {%llu, %llu}\n",
1014 to->offset, to->length, from->offset, from->length);
1015
1016 /* calculate the union of the two ranges */
1017 to->offset = min(to->offset, from->offset);
1018 to->length = max(to_max, from_max) - to->offset;
1019
1020 /* on success, remove/free the new segment */
1021 list_remove(&from->entry);
1022 free(from);
1024
1025 /* because the existing segment 'to' has grown, we may
1026 * be able to merge it with later segments */
1027 from = to;
1028 }
1029 return status;
1030}
1031
1034 IN const struct cb_layoutrecall_args *recall)
1035{
1036 const stateid4 *stateid = &recall->recall.args.file.stateid;
1038
1039 /* under an exclusive lock, flag the layout as recalled */
1041
1042 if (state->stateid.seqid == 0) {
1043 /* return NOMATCHINGLAYOUT if it wasn't actually granted */
1045 goto out;
1046 }
1047
1048 if (recall->recall.type == PNFS_RETURN_FILE) {
1049 /* detect races between CB_LAYOUTRECALL and LAYOUTGET/LAYOUTRETURN */
1050 if (stateid->seqid > state->stateid.seqid + 1) {
1051 /* the server has processed an outstanding LAYOUTGET or
1052 * LAYOUTRETURN; we must return ERR_DELAY until we get the
1053 * response and update our view of the layout */
1055 goto out;
1056 }
1057
1058 /* save the updated seqid */
1059 state->stateid.seqid = stateid->seqid;
1060 }
1061
1062 if (state->io_count) {
1063 /* save an entry for this recall, and process it once io finishes */
1064 struct layout_recall *lrc = calloc(1, sizeof(struct layout_recall));
1065 if (lrc == NULL) {
1066 /* on failure to allocate, we'll have to respond
1067 * to the CB_LAYOUTRECALL with NFS4ERR_DELAY */
1069 goto out;
1070 }
1071 layout_recall_entry_init(lrc, recall);
1072 if (layout_recall_merge(&state->recalls, &lrc->layout) != PNFS_SUCCESS)
1073 list_add_tail(&state->recalls, &lrc->layout.entry);
1074 } else {
1075 /* if there is no pending io, process the recall immediately */
1076 struct layout_recall lrc = { 0 };
1077 layout_recall_entry_init(&lrc, recall);
1079 }
1080out:
1082 return status;
1083}
1084
1087 IN const struct cb_layoutrecall_args *recall)
1088{
1089 struct list_entry *entry;
1090 enum pnfs_status status;
1091
1092 dprintf(FLLVL, "--> file_layout_recall_file()\n");
1093
1094 EnterCriticalSection(&client->layouts->lock);
1095
1096 status = layout_entry_find(client->layouts, &recall->recall.args.file.fh, &entry);
1097 if (status == PNFS_SUCCESS)
1099
1100 LeaveCriticalSection(&client->layouts->lock);
1101
1102 dprintf(FLLVL, "<-- file_layout_recall_file() returning %s\n",
1104 return status;
1105}
1106
1108 IN const nfs41_fsid *lhs,
1109 IN const nfs41_fsid *rhs)
1110{
1111 return lhs->major == rhs->major && lhs->minor == rhs->minor;
1112}
1113
1116 IN const struct cb_layoutrecall_args *recall)
1117{
1118 struct list_entry *entry;
1120 nfs41_fh *fh;
1122
1123 dprintf(FLLVL, "--> file_layout_recall_fsid(%llu, %llu)\n",
1124 recall->recall.args.fsid.major, recall->recall.args.fsid.minor);
1125
1126 EnterCriticalSection(&client->layouts->lock);
1127
1128 list_for_each(entry, &client->layouts->head) {
1130 /* no locks needed to read layout.meta_fh or superblock.fsid,
1131 * because they are only written once on creation */
1132 fh = &state->meta_fh;
1133 if (fsid_matches(&recall->recall.args.fsid, &fh->superblock->fsid))
1134 status = file_layout_recall(state, recall);
1135 }
1136
1137 LeaveCriticalSection(&client->layouts->lock);
1138
1139 /* bulk recalls require invalidation of cached device info */
1141
1142 dprintf(FLLVL, "<-- file_layout_recall_fsid() returning %s\n",
1144 return status;
1145}
1146
1149 IN const struct cb_layoutrecall_args *recall)
1150{
1151 struct list_entry *entry;
1153
1154 dprintf(FLLVL, "--> file_layout_recall_all()\n");
1155
1156 EnterCriticalSection(&client->layouts->lock);
1157
1158 list_for_each(entry, &client->layouts->head)
1160
1161 LeaveCriticalSection(&client->layouts->lock);
1162
1163 /* bulk recalls require invalidation of cached device info */
1165
1166 dprintf(FLLVL, "<-- file_layout_recall_all() returning %s\n",
1168 return status;
1169}
1170
1173 IN const struct cb_layoutrecall_args *recall)
1174{
1176
1177 dprintf(FLLVL, "--> pnfs_file_layout_recall(%u, %s, %u)\n",
1178 recall->recall.type, pnfs_iomode_string(recall->iomode),
1179 recall->changed);
1180
1181 if (recall->type != PNFS_LAYOUTTYPE_FILE) {
1182 dprintf(FLLVL, "invalid layout type %u (%s)!\n",
1183 recall->type, pnfs_layout_type_string(recall->type));
1185 goto out;
1186 }
1187
1188 switch (recall->recall.type) {
1189 case PNFS_RETURN_FILE:
1191 break;
1192 case PNFS_RETURN_FSID:
1194 break;
1195 case PNFS_RETURN_ALL:
1197 break;
1198
1199 default:
1200 dprintf(FLLVL, "invalid return type %u!\n", recall->recall);
1202 goto out;
1203 }
1204out:
1205 dprintf(FLLVL, "<-- pnfs_file_layout_recall() returning %s\n",
1207 return status;
1208}
1209
1210/* expects caller to hold a shared lock on pnfs_layout_state */
1212 IN const pnfs_layout_state *state,
1213 IN const pnfs_layout *layout)
1214{
1215 struct list_entry *entry;
1217
1218 /* search for a pending recall that intersects with the given segment */
1219 list_for_each(entry, &state->recalls) {
1220 const struct layout_recall *recall = recall_entry(entry);
1221 if (!layout_recall_compatible(layout, &recall->layout))
1222 continue;
1223
1224 if (recall->changed)
1226 else
1228 break;
1229 }
1230 return status;
1231}
1232
1235 IN const pnfs_layout *layout)
1236{
1237 struct layout_recall *lrc = calloc(1, sizeof(struct layout_recall));
1238 if (lrc == NULL)
1239 return;
1240
1242
1243 list_init(&lrc->layout.entry);
1244 lrc->layout.offset = layout->offset;
1245 lrc->layout.length = layout->length;
1246 lrc->layout.iomode = layout->iomode;
1247 lrc->layout.type = layout->type;
1248 lrc->changed = TRUE;
1249
1250 if (layout_recall_merge(&state->recalls, &lrc->layout) != PNFS_SUCCESS)
1251 list_add_tail(&state->recalls, &lrc->layout.entry);
1252
1254}
1255
1256/* expects caller to hold an exclusive lock on pnfs_layout_state */
1259{
1260 /* take a reference on the layout, so that it won't be recalled
1261 * until all io is finished */
1262 state->io_count++;
1263 dprintf(FLLVL, "pnfs_layout_io_start(): count -> %u\n",
1264 state->io_count);
1265}
1266
1269{
1271
1272 /* return the reference to signify that an io request is finished */
1273 state->io_count--;
1274 dprintf(FLLVL, "pnfs_layout_io_finished() count -> %u\n",
1275 state->io_count);
1276
1277 if (state->io_count > 0) /* more io pending */
1278 goto out_unlock;
1279
1280 /* once all io is finished, process any layout recalls */
1282
1283 /* finish any segment merging that was delayed during io */
1284 if (!list_empty(&state->layouts))
1286
1287out_unlock:
1289}
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
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_for_each(entry, head)
Definition: list.h:36
#define list_for_each_tmp(entry, tmp, head)
Definition: list.h:39
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_add(struct list_entry *entry, struct list_entry *prev, struct list_entry *next)
Definition: list.h:64
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 fh_copy(OUT nfs41_fh *dst, IN const nfs41_fh *src)
Definition: util.c:354
Definition: list.h:37
void eprintf(LPCSTR format,...)
Definition: daemon_debug.c:86
const char * nfs_error_string(int status)
Definition: daemon_debug.c:370
const char * pnfs_iomode_string(enum pnfs_iomode iomode)
Definition: pnfs_debug.c:58
void dprint_layout(int level, const struct __pnfs_file_layout *layout)
const char * pnfs_layout_type_string(enum pnfs_layout_type type)
Definition: pnfs_debug.c:48
const char * pnfs_error_string(enum pnfs_status status)
Definition: pnfs_debug.c:28
#define free
Definition: debug_ros.c:5
#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
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
BOOL WINAPI SleepConditionVariableSRW(PCONDITION_VARIABLE ConditionVariable, PSRWLOCK Lock, DWORD Timeout, ULONG Flags)
Definition: sync.c:121
VOID WINAPI InitializeConditionVariable(PCONDITION_VARIABLE ConditionVariable)
Definition: sync.c:68
VOID WINAPI WakeConditionVariable(PCONDITION_VARIABLE ConditionVariable)
Definition: sync.c:144
#define INFINITE
Definition: serial.h:102
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
GLuint64EXT * result
Definition: glext.h:11304
GLintptr offset
Definition: glext.h:5920
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 flag
Definition: glfuncs.h:52
uint32_t entry
Definition: isohybrid.c:63
double __cdecl remainder(double, double)
Definition: remainder.c:75
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static DWORD layout
Definition: bitmap.c:46
#define min(a, b)
Definition: monoChain.cc:55
int remove
Definition: msacm.c:1366
#define NFS4_STATEID_OTHER
Definition: nfs41_const.h:33
nfsstat4
Definition: nfs41_const.h:86
@ NFS4ERR_BADLAYOUT
Definition: nfs41_const.h:159
@ NFS4ERR_BADIOMODE
Definition: nfs41_const.h:158
@ NFS4_OK
Definition: nfs41_const.h:87
@ NFS4ERR_UNKNOWN_LAYOUTTYPE
Definition: nfs41_const.h:171
@ NFS4ERR_LAYOUTUNAVAILABLE
Definition: nfs41_const.h:168
enum nfsstat4 pnfs_rpc_layoutget(IN nfs41_session *session, IN nfs41_path_fh *file, IN stateid_arg *stateid, IN enum pnfs_iomode iomode, IN uint64_t offset, IN uint64_t minlength, IN uint64_t length, OUT pnfs_layoutget_res_ok *layoutget_res_ok)
Definition: nfs41_ops.c:1935
enum nfsstat4 pnfs_rpc_layoutreturn(IN nfs41_session *session, IN nfs41_path_fh *file, IN enum pnfs_layout_type type, IN enum pnfs_iomode iomode, IN uint64_t offset, IN uint64_t length, IN stateid4 *stateid, OUT pnfs_layoutreturn_res *layoutreturn_res)
Definition: nfs41_ops.c:2062
@ EXCHGID4_FLAG_USE_PNFS_MDS
Definition: nfs41_ops.h:101
@ STATEID_LAYOUT
Definition: nfs41_ops.h:280
static const uint64_t NFS4_UINT64_MAX
Definition: nfs41_types.h:32
long LONG
Definition: pedump.c:60
__inline uint32_t layout_unit_size(IN const pnfs_file_layout *layout)
Definition: pnfs.h:315
enum pnfs_status pnfs_file_device_get(IN struct __nfs41_session *session, IN struct pnfs_file_device_list *devices, IN unsigned char *deviceid, OUT pnfs_file_device **device_out)
#define PNFS_DEVICEID_SIZE
Definition: pnfs.h:111
pnfs_status
Definition: pnfs.h:58
@ PNFSERR_NOT_SUPPORTED
Definition: pnfs.h:62
@ PNFS_PENDING
Definition: pnfs.h:60
@ PNFSERR_LAYOUT_CHANGED
Definition: pnfs.h:71
@ PNFSERR_NO_LAYOUT
Definition: pnfs.h:66
@ PNFSERR_RESOURCES
Definition: pnfs.h:69
@ PNFSERR_LAYOUT_RECALLED
Definition: pnfs.h:70
@ PNFS_SUCCESS
Definition: pnfs.h:59
pnfs_iomode
Definition: pnfs.h:80
@ PNFS_IOMODE_ANY
Definition: pnfs.h:83
@ PNFS_IOMODE_READ
Definition: pnfs.h:81
@ PNFS_IOMODE_RW
Definition: pnfs.h:82
pnfs_layout_type
Definition: pnfs.h:74
@ PNFS_LAYOUTTYPE_FILE
Definition: pnfs.h:75
@ PNFS_RETURN_FSID
Definition: pnfs.h:102
@ PNFS_RETURN_ALL
Definition: pnfs.h:103
@ PNFS_RETURN_FILE
Definition: pnfs.h:101
void pnfs_file_device_put(IN pnfs_file_device *device)
Definition: pnfs_device.c:245
@ PNFS_LAYOUT_NOT_RW
Definition: pnfs.h:90
@ PNFS_LAYOUT_UNAVAILABLE
Definition: pnfs.h:88
void pnfs_file_device_list_invalidate(IN struct pnfs_file_device_list *devices)
Definition: pnfs_device.c:159
static enum pnfs_status layout_update(IN OUT pnfs_layout_state *state, IN const pnfs_layoutget_res_ok *layoutget_res)
Definition: pnfs_layout.c:393
void pnfs_layout_io_finished(IN pnfs_layout_state *state)
Definition: pnfs_layout.c:1267
enum pnfs_status pnfs_layout_state_prepare(IN pnfs_layout_state *state, IN nfs41_session *session, IN nfs41_path_fh *meta_file, IN stateid_arg *stateid, IN enum pnfs_iomode iomode, IN uint64_t offset, IN uint64_t length)
Definition: pnfs_layout.c:706
static void device_assign(IN pnfs_layout_state *state, IN const unsigned char *deviceid, IN pnfs_file_device *device)
Definition: pnfs_layout.c:575
static enum pnfs_status layout_state_find_or_create(IN struct pnfs_layout_list *layouts, IN const nfs41_fh *meta_fh, OUT pnfs_layout_state **layout_out)
Definition: pnfs_layout.c:154
static void layout_recall_range(IN pnfs_layout_state *state, IN const pnfs_layout *recall)
Definition: pnfs_layout.c:916
static enum pnfs_status file_layout_fetch(IN OUT pnfs_layout_state *state, IN nfs41_session *session, IN nfs41_path_fh *meta_file, IN stateid_arg *stateid, IN enum pnfs_iomode iomode, IN uint64_t offset, IN uint64_t minlength, IN uint64_t length)
Definition: pnfs_layout.c:418
static enum pnfs_status device_status(IN pnfs_layout_state *state, IN uint64_t offset, IN uint64_t length, OUT unsigned char *deviceid)
Definition: pnfs_layout.c:553
void pnfs_layout_io_start(IN pnfs_layout_state *state)
Definition: pnfs_layout.c:1257
static enum pnfs_status file_layout_recall_file(IN nfs41_client *client, IN const struct cb_layoutrecall_args *recall)
Definition: pnfs_layout.c:1085
static enum pnfs_status client_supports_pnfs(IN nfs41_client *client)
Definition: pnfs_layout.c:617
static pnfs_file_layout * layout_allocate_copy(IN const pnfs_file_layout *existing)
Definition: pnfs_layout.c:885
enum pnfs_status pnfs_layout_list_create(OUT struct pnfs_layout_list **layouts_out)
Definition: pnfs_layout.c:121
static void layout_state_free(IN pnfs_layout_state *state)
Definition: pnfs_layout.c:93
static uint64_t range_max(IN const pnfs_layout *layout)
Definition: pnfs_layout.c:220
static void layout_recall_entry_init(OUT struct layout_recall *lrc, IN const struct cb_layoutrecall_args *recall)
Definition: pnfs_layout.c:975
static enum pnfs_status layout_update_range(IN OUT pnfs_layout_state *state, IN const struct list_entry *layouts)
Definition: pnfs_layout.c:341
static enum pnfs_status layout_update_stateid(IN OUT pnfs_layout_state *state, IN const stateid4 *stateid)
Definition: pnfs_layout.c:374
static enum pnfs_status layout_recall_merge(IN struct list_entry *list, IN pnfs_layout *from)
Definition: pnfs_layout.c:992
void pnfs_layout_recall_fenced(IN pnfs_layout_state *state, IN const pnfs_layout *layout)
Definition: pnfs_layout.c:1233
static bool_t layout_sanity_check(IN pnfs_file_layout *layout)
Definition: pnfs_layout.c:227
static enum pnfs_status file_layout_return(IN nfs41_session *session, IN nfs41_path_fh *file, IN pnfs_layout_state *state)
Definition: pnfs_layout.c:765
static bool_t fsid_matches(IN const nfs41_fsid *lhs, IN const nfs41_fsid *rhs)
Definition: pnfs_layout.c:1107
#define layout_entry(pos)
Definition: pnfs_layout.c:40
void pnfs_layout_state_close(IN nfs41_session *session, IN nfs41_open_state *state, IN bool_t remove)
Definition: pnfs_layout.c:830
void pnfs_layout_list_free(IN struct pnfs_layout_list *layouts)
Definition: pnfs_layout.c:139
static enum pnfs_status layout_state_merge(IN pnfs_layout_state *state, IN pnfs_file_layout *from)
Definition: pnfs_layout.c:286
static enum pnfs_status layout_return_status(IN const pnfs_layout_state *state)
Definition: pnfs_layout.c:758
static enum pnfs_status layout_entry_find(IN struct pnfs_layout_list *layouts, IN const nfs41_fh *meta_fh, OUT struct list_entry **entry_out)
Definition: pnfs_layout.c:112
static enum pnfs_status layout_coverage_status(IN pnfs_layout_state *state, IN enum pnfs_iomode iomode, IN uint64_t offset, IN uint64_t length, OUT uint64_t *offset_missing)
Definition: pnfs_layout.c:477
static void layout_ordered_insert(IN pnfs_layout_state *state, IN pnfs_layout *layout)
Definition: pnfs_layout.c:317
static void layout_state_free_layouts(IN pnfs_layout_state *state)
Definition: pnfs_layout.c:75
#define FLLVL
Definition: pnfs_layout.c:30
static int layout_entry_compare(IN const struct list_entry *entry, IN const void *value)
Definition: pnfs_layout.c:101
static enum pnfs_status file_layout_recall_all(IN nfs41_client *client, IN const struct cb_layoutrecall_args *recall)
Definition: pnfs_layout.c:1147
static void file_layout_free(IN pnfs_file_layout *layout)
Definition: pnfs_layout.c:67
static void layout_state_free_recalls(IN pnfs_layout_state *state)
Definition: pnfs_layout.c:84
static enum pnfs_status open_state_layout_cached(IN nfs41_open_state *state, OUT pnfs_layout_state **layout_out)
Definition: pnfs_layout.c:637
#define state_entry(pos)
Definition: pnfs_layout.c:39
static bool_t layout_recall_compatible(IN const pnfs_layout *layout, IN const pnfs_layout *recall)
Definition: pnfs_layout.c:874
static enum pnfs_status layout_fetch(IN pnfs_layout_state *state, IN nfs41_session *session, IN nfs41_path_fh *meta_file, IN stateid_arg *stateid, IN enum pnfs_iomode iomode, IN uint64_t offset, IN uint64_t length)
Definition: pnfs_layout.c:504
static enum pnfs_status file_layout_recall(IN pnfs_layout_state *state, IN const struct cb_layoutrecall_args *recall)
Definition: pnfs_layout.c:1032
enum pnfs_status pnfs_file_layout_recall(IN nfs41_client *client, IN const struct cb_layoutrecall_args *recall)
Definition: pnfs_layout.c:1171
static enum pnfs_status device_fetch(IN pnfs_layout_state *state, IN nfs41_session *session, IN unsigned char *deviceid)
Definition: pnfs_layout.c:596
#define file_layout_entry(pos)
Definition: pnfs_layout.c:41
enum pnfs_status pnfs_layout_recall_status(IN const pnfs_layout_state *state, IN const pnfs_layout *layout)
Definition: pnfs_layout.c:1211
static enum pnfs_status file_layout_recall_fsid(IN nfs41_client *client, IN const struct cb_layoutrecall_args *recall)
Definition: pnfs_layout.c:1114
static enum pnfs_status layout_state_create(IN const nfs41_fh *meta_fh, OUT pnfs_layout_state **layout_out)
Definition: pnfs_layout.c:43
enum pnfs_status pnfs_layout_state_open(IN nfs41_open_state *state, OUT pnfs_layout_state **layout_out)
Definition: pnfs_layout.c:653
static bool_t layout_merge_segments(IN pnfs_file_layout *to, IN pnfs_file_layout *from)
Definition: pnfs_layout.c:251
static enum pnfs_status fs_supports_layout(IN const nfs41_superblock *superblock, IN enum pnfs_layout_type type)
Definition: pnfs_layout.c:628
static int layout_filehandles_cmp(IN const pnfs_file_layout_handles *lhs, IN const pnfs_file_layout_handles *rhs)
Definition: pnfs_layout.c:242
#define recall_entry(pos)
Definition: pnfs_layout.c:872
static enum pnfs_status layout_state_find_and_delete(IN struct pnfs_layout_list *layouts, IN const nfs41_fh *meta_fh)
Definition: pnfs_layout.c:194
static void layout_state_deferred_recalls(IN pnfs_layout_state *state)
Definition: pnfs_layout.c:960
#define dprintf
Definition: regdump.c:33
static FILE * out
Definition: regtests2xml.c:44
#define calloc
Definition: rosglue.h:14
static FILE * client
Definition: client.c:41
CardRegion * from
Definition: spigame.cpp:19
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 offset
Definition: pnfs.h:166
enum pnfs_layout_type type
Definition: pnfs.h:169
enum pnfs_iomode iomode
Definition: pnfs.h:168
uint64_t length
Definition: pnfs.h:167
struct list_entry entry
Definition: pnfs.h:165
struct list_entry layouts
Definition: nfs41_ops.h:920
uint32_t seqid
Definition: nfs41_types.h:144
enum stateid_type type
Definition: nfs41_ops.h:285
stateid4 stateid
Definition: nfs41_ops.h:284
Definition: devices.h:37
Definition: fci.c:127
bool_t changed
Definition: pnfs_layout.c:870
pnfs_layout layout
Definition: pnfs_layout.c:869
Definition: list.h:27
CRITICAL_SECTION lock
Definition: pnfs_layout.c:36
struct list_entry head
Definition: pnfs_layout.c:35
Definition: ps.c:97
#define max(a, b)
Definition: svc.c:63
VOID WINAPI InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection)
Definition: synch.c:751
#define IN
Definition: typedefs.h:39
#define OUT
Definition: typedefs.h:40
Definition: pdh_main.c:94
#define ZeroMemory
Definition: winbase.h:1712
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
void WINAPI DeleteCriticalSection(PCRITICAL_SECTION)