4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * All rights reserved. This program and the accompanying materials
7 * are made available under the terms of the GNU Lesser General Public License
8 * (LGPL) version 2.1 or (at your discretion) any later version.
9 * (LGPL) version 2.1 accompanies this distribution, and is available at
10 * http://www.gnu.org/licenses/lgpl-2.1.html
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
20 * lustre/utils/liblustreapi_layout.c
22 * lustreapi library for layout calls for interacting with the layout of
23 * Lustre files while hiding details of the internal data structures
26 * Copyright (c) 2016, 2017, Intel Corporation.
28 * Author: Ned Bass <bass6@llnl.gov>
38 #include <sys/xattr.h>
39 #include <sys/param.h>
43 #include <libcfs/util/list.h>
44 #include <lustre/lustreapi.h>
45 #include "lustreapi_internal.h"
48 * Layout component, which contains all attributes of a plain
51 struct llapi_layout_comp {
53 uint64_t llc_stripe_size;
54 uint64_t llc_stripe_count;
55 uint64_t llc_stripe_offset;
56 /* Add 1 so user always gets back a null terminated string. */
57 char llc_pool_name[LOV_MAXPOOLNAME + 1];
58 /** Number of objects in llc_objects array if was initialized. */
59 uint32_t llc_objects_count;
60 struct lov_user_ost_data_v1 *llc_objects;
61 /* fields used only for composite layouts */
62 struct lu_extent llc_extent; /* [start, end) of component */
63 uint32_t llc_id; /* unique ID of component */
64 uint32_t llc_flags; /* LCME_FL_* flags */
65 uint64_t llc_timestamp; /* snapshot timestamp */
66 struct list_head llc_list; /* linked to the llapi_layout
72 * An Opaque data type abstracting the layout of a Lustre file.
75 uint32_t llot_magic; /* LLAPI_LAYOUT_MAGIC */
78 bool llot_is_composite;
79 uint16_t llot_mirror_count;
80 /* Cursor pointing to one of the components in llot_comp_list */
81 struct llapi_layout_comp *llot_cur_comp;
82 struct list_head llot_comp_list;
86 * Compute the number of elements in the lmm_objects array of \a lum
87 * with size \a lum_size.
89 * \param[in] lum the struct lov_user_md to check
90 * \param[in] lum_size the number of bytes in \a lum
92 * \retval number of elements in array lum->lmm_objects
94 static int llapi_layout_objects_in_lum(struct lov_user_md *lum, size_t lum_size)
99 if (lum_size < lov_user_md_size(0, LOV_MAGIC_V1))
102 if (lum->lmm_magic == __swab32(LOV_MAGIC_V1) ||
103 lum->lmm_magic == __swab32(LOV_MAGIC_V3))
104 magic = __swab32(lum->lmm_magic);
106 magic = lum->lmm_magic;
108 base_size = lov_user_md_size(0, magic);
110 if (lum_size <= base_size)
113 return (lum_size - base_size) / sizeof(lum->lmm_objects[0]);
117 * Byte-swap the fields of struct lov_user_md.
119 * XXX Rather than duplicating swabbing code here, we should eventually
120 * refactor the needed functions in lustre/ptlrpc/pack_generic.c
121 * into a library that can be shared between kernel and user code.
124 llapi_layout_swab_lov_user_md(struct lov_user_md *lum, int lum_size)
126 int i, j, ent_count, obj_count;
127 struct lov_comp_md_v1 *comp_v1 = NULL;
128 struct lov_comp_md_entry_v1 *ent;
129 struct lov_user_ost_data *lod;
131 if (lum->lmm_magic != __swab32(LOV_MAGIC_V1) &&
132 lum->lmm_magic != __swab32(LOV_MAGIC_V3) &&
133 lum->lmm_magic != __swab32(LOV_MAGIC_COMP_V1))
136 if (lum->lmm_magic == __swab32(LOV_MAGIC_COMP_V1))
137 comp_v1 = (struct lov_comp_md_v1 *)lum;
139 if (comp_v1 != NULL) {
140 comp_v1->lcm_magic = __swab32(comp_v1->lcm_magic);
141 comp_v1->lcm_size = __swab32(comp_v1->lcm_size);
142 comp_v1->lcm_layout_gen = __swab32(comp_v1->lcm_layout_gen);
143 comp_v1->lcm_flags = __swab16(comp_v1->lcm_flags);
144 comp_v1->lcm_entry_count = __swab16(comp_v1->lcm_entry_count);
145 ent_count = comp_v1->lcm_entry_count;
150 for (i = 0; i < ent_count; i++) {
151 if (comp_v1 != NULL) {
152 ent = &comp_v1->lcm_entries[i];
153 ent->lcme_id = __swab32(ent->lcme_id);
154 ent->lcme_flags = __swab32(ent->lcme_flags);
155 ent->lcme_timestamp = __swab64(ent->lcme_timestamp);
156 ent->lcme_extent.e_start = __swab64(ent->lcme_extent.e_start);
157 ent->lcme_extent.e_end = __swab64(ent->lcme_extent.e_end);
158 ent->lcme_offset = __swab32(ent->lcme_offset);
159 ent->lcme_size = __swab32(ent->lcme_size);
161 lum = (struct lov_user_md *)((char *)comp_v1 +
163 lum_size = ent->lcme_size;
165 obj_count = llapi_layout_objects_in_lum(lum, lum_size);
167 lum->lmm_magic = __swab32(lum->lmm_magic);
168 lum->lmm_pattern = __swab32(lum->lmm_pattern);
169 lum->lmm_stripe_size = __swab32(lum->lmm_stripe_size);
170 lum->lmm_stripe_count = __swab16(lum->lmm_stripe_count);
171 lum->lmm_stripe_offset = __swab16(lum->lmm_stripe_offset);
173 if (lum->lmm_magic != LOV_MAGIC_V1) {
174 struct lov_user_md_v3 *v3;
175 v3 = (struct lov_user_md_v3 *)lum;
176 lod = v3->lmm_objects;
178 lod = lum->lmm_objects;
181 for (j = 0; j < obj_count; j++)
182 lod[j].l_ost_idx = __swab32(lod[j].l_ost_idx);
187 * (Re-)allocate llc_objects[] to \a num_stripes stripes.
189 * Copy over existing llc_objects[], if any, to the new llc_objects[].
191 * \param[in] layout existing layout to be modified
192 * \param[in] num_stripes number of stripes in new layout
194 * \retval 0 if the objects are re-allocated successfully
195 * \retval -1 on error with errno set
197 static int __llapi_comp_objects_realloc(struct llapi_layout_comp *comp,
198 unsigned int new_stripes)
200 struct lov_user_ost_data_v1 *new_objects;
203 if (new_stripes > LOV_MAX_STRIPE_COUNT) {
208 if (new_stripes == comp->llc_objects_count)
211 if (new_stripes != 0 && new_stripes <= comp->llc_objects_count)
214 new_objects = realloc(comp->llc_objects,
215 sizeof(*new_objects) * new_stripes);
216 if (new_objects == NULL && new_stripes != 0) {
221 for (i = comp->llc_objects_count; i < new_stripes; i++)
222 new_objects[i].l_ost_idx = LLAPI_LAYOUT_IDX_MAX;
224 comp->llc_objects = new_objects;
225 comp->llc_objects_count = new_stripes;
231 * Allocate storage for a llapi_layout_comp with \a num_stripes stripes.
233 * \param[in] num_stripes number of stripes in new layout
235 * \retval valid pointer if allocation succeeds
236 * \retval NULL if allocation fails
238 static struct llapi_layout_comp *__llapi_comp_alloc(unsigned int num_stripes)
240 struct llapi_layout_comp *comp;
242 if (num_stripes > LOV_MAX_STRIPE_COUNT) {
247 comp = calloc(1, sizeof(*comp));
253 comp->llc_objects = NULL;
254 comp->llc_objects_count = 0;
256 if (__llapi_comp_objects_realloc(comp, num_stripes) < 0) {
262 comp->llc_pattern = LLAPI_LAYOUT_DEFAULT;
263 comp->llc_stripe_size = LLAPI_LAYOUT_DEFAULT;
264 comp->llc_stripe_count = LLAPI_LAYOUT_DEFAULT;
265 comp->llc_stripe_offset = LLAPI_LAYOUT_DEFAULT;
266 comp->llc_pool_name[0] = '\0';
267 comp->llc_extent.e_start = 0;
268 comp->llc_extent.e_end = LUSTRE_EOF;
271 INIT_LIST_HEAD(&comp->llc_list);
277 * Free memory allocated for \a comp
279 * \param[in] comp previously allocated by __llapi_comp_alloc()
281 static void __llapi_comp_free(struct llapi_layout_comp *comp)
283 if (comp->llc_objects != NULL)
284 free(comp->llc_objects);
289 * Free memory allocated for \a layout.
291 * \param[in] layout previously allocated by llapi_layout_alloc()
293 void llapi_layout_free(struct llapi_layout *layout)
295 struct llapi_layout_comp *comp, *n;
300 list_for_each_entry_safe(comp, n, &layout->llot_comp_list, llc_list) {
301 list_del_init(&comp->llc_list);
302 __llapi_comp_free(comp);
308 * Allocate and initialize a llapi_layout structure.
310 * \retval valid llapi_layout pointer on success
311 * \retval NULL if memory allocation fails
313 static struct llapi_layout *__llapi_layout_alloc(void)
315 struct llapi_layout *layout;
317 layout = calloc(1, sizeof(*layout));
318 if (layout == NULL) {
324 layout->llot_magic = LLAPI_LAYOUT_MAGIC;
325 layout->llot_gen = 0;
326 layout->llot_flags = 0;
327 layout->llot_is_composite = false;
328 layout->llot_mirror_count = 1;
329 layout->llot_cur_comp = NULL;
330 INIT_LIST_HEAD(&layout->llot_comp_list);
336 * Allocate and initialize a new plain layout.
338 * \retval valid llapi_layout pointer on success
339 * \retval NULL if memory allocation fails
341 struct llapi_layout *llapi_layout_alloc(void)
343 struct llapi_layout_comp *comp;
344 struct llapi_layout *layout;
346 layout = __llapi_layout_alloc();
350 comp = __llapi_comp_alloc(0);
356 list_add_tail(&comp->llc_list, &layout->llot_comp_list);
357 layout->llot_cur_comp = comp;
363 * Check if the given \a lum_size is large enough to hold the required
366 * \param[in] lum the struct lov_user_md to check
367 * \param[in] lum_size the number of bytes in \a lum
369 * \retval true the \a lum_size is too small
370 * \retval false the \a lum_size is large enough
372 static bool llapi_layout_lum_truncated(struct lov_user_md *lum, size_t lum_size)
376 if (lum_size < sizeof(lum->lmm_magic))
379 if (lum->lmm_magic == LOV_MAGIC_V1 ||
380 lum->lmm_magic == __swab32(LOV_MAGIC_V1))
381 magic = LOV_MAGIC_V1;
382 else if (lum->lmm_magic == LOV_MAGIC_V3 ||
383 lum->lmm_magic == __swab32(LOV_MAGIC_V3))
384 magic = LOV_MAGIC_V3;
385 else if (lum->lmm_magic == LOV_MAGIC_COMP_V1 ||
386 lum->lmm_magic == __swab32(LOV_MAGIC_COMP_V1))
387 magic = LOV_MAGIC_COMP_V1;
391 if (magic == LOV_MAGIC_V1 || magic == LOV_MAGIC_V3)
392 return lum_size < lov_user_md_size(0, magic);
394 return lum_size < sizeof(struct lov_comp_md_v1);
397 /* Verify if the objects count in lum is consistent with the
398 * stripe count in lum. It applies to regular file only. */
399 static bool llapi_layout_lum_valid(struct lov_user_md *lum, int lum_size)
401 struct lov_comp_md_v1 *comp_v1 = NULL;
402 int i, ent_count, obj_count;
404 if (lum->lmm_magic == LOV_MAGIC_COMP_V1) {
405 comp_v1 = (struct lov_comp_md_v1 *)lum;
406 ent_count = comp_v1->lcm_entry_count;
407 } else if (lum->lmm_magic == LOV_MAGIC_V1 ||
408 lum->lmm_magic == LOV_MAGIC_V3) {
414 for (i = 0; i < ent_count; i++) {
416 lum = (struct lov_user_md *)((char *)comp_v1 +
417 comp_v1->lcm_entries[i].lcme_offset);
418 lum_size = comp_v1->lcm_entries[i].lcme_size;
420 obj_count = llapi_layout_objects_in_lum(lum, lum_size);
423 if (!(comp_v1->lcm_entries[i].lcme_flags &
424 LCME_FL_INIT) && obj_count != 0)
426 } else if (obj_count != lum->lmm_stripe_count) {
434 * Convert the data from a lov_user_md to a newly allocated llapi_layout.
435 * The caller is responsible for freeing the returned pointer.
437 * \param[in] lov_xattr LOV user metadata xattr to copy data from
438 * \param[in] lov_xattr_size size the lov_xattr_size passed in
439 * \param[in] flags flags to control how layout is retrieved
441 * \retval valid llapi_layout pointer on success
442 * \retval NULL if memory allocation fails
444 struct llapi_layout *llapi_layout_get_by_xattr(void *lov_xattr,
445 ssize_t lov_xattr_size,
446 enum llapi_layout_get_flags flags)
448 struct lov_user_md *lum = lov_xattr;
449 struct lov_comp_md_v1 *comp_v1 = NULL;
450 struct lov_comp_md_entry_v1 *ent;
451 struct lov_user_md *v1;
452 struct llapi_layout *layout = NULL;
453 struct llapi_layout_comp *comp;
454 int i, ent_count = 0, obj_count;
456 if (lov_xattr == NULL || lov_xattr_size <= 0) {
461 /* Return an error if we got back a partial layout. */
462 if (llapi_layout_lum_truncated(lov_xattr, lov_xattr_size)) {
467 #if __BYTE_ORDER == __BIG_ENDIAN
468 if (flags & LLAPI_LAYOUT_GET_COPY) {
469 lum = malloc(lov_xattr_size);
474 memcpy(lum, lov_xattr, lov_xattr_size);
478 llapi_layout_swab_lov_user_md(lum, lov_xattr_size);
480 #if LUSTRE_VERSION_CODE > OBD_OCD_VERSION(2, 16, 53, 0)
481 #define LLAPI_LXF_CHECK_OLD 0x0001
482 if (flags & LLAPI_LXF_CHECK_OLD)
483 flags = (flags & ~LLAPI_LXF_CHECK_OLD) | LLAPI_LAYOUT_GET_CHECK;
485 if ((flags & LLAPI_LAYOUT_GET_CHECK) &&
486 !llapi_layout_lum_valid(lum, lov_xattr_size)) {
491 layout = __llapi_layout_alloc();
492 if (layout == NULL) {
497 if (lum->lmm_magic == LOV_MAGIC_COMP_V1) {
498 comp_v1 = (struct lov_comp_md_v1 *)lum;
499 ent_count = comp_v1->lcm_entry_count;
500 layout->llot_gen = comp_v1->lcm_layout_gen;
501 layout->llot_is_composite = true;
502 layout->llot_mirror_count = comp_v1->lcm_mirror_count + 1;
503 layout->llot_gen = comp_v1->lcm_layout_gen;
504 layout->llot_flags = comp_v1->lcm_flags;
505 } else if (lum->lmm_magic == LOV_MAGIC_V1 ||
506 lum->lmm_magic == LOV_MAGIC_V3) {
508 layout->llot_is_composite = false;
510 if (lov_xattr_size <= 0) {
519 if (ent_count == 0) {
524 v1 = (struct lov_user_md *)lum;
525 for (i = 0; i < ent_count; i++) {
526 if (comp_v1 != NULL) {
527 ent = &comp_v1->lcm_entries[i];
528 v1 = (struct lov_user_md *)((char *)comp_v1 +
530 lov_xattr_size = ent->lcme_size;
535 obj_count = llapi_layout_objects_in_lum(v1, lov_xattr_size);
536 comp = __llapi_comp_alloc(obj_count);
541 comp->llc_extent.e_start = ent->lcme_extent.e_start;
542 comp->llc_extent.e_end = ent->lcme_extent.e_end;
543 comp->llc_id = ent->lcme_id;
544 comp->llc_flags = ent->lcme_flags;
545 if (comp->llc_flags & LCME_FL_NOSYNC)
546 comp->llc_timestamp = ent->lcme_timestamp;
548 comp->llc_extent.e_start = 0;
549 comp->llc_extent.e_end = LUSTRE_EOF;
554 if (v1->lmm_pattern == LOV_PATTERN_RAID0)
555 comp->llc_pattern = LLAPI_LAYOUT_RAID0;
556 else if (v1->lmm_pattern == (LOV_PATTERN_RAID0 |
557 LOV_PATTERN_OVERSTRIPING))
558 comp->llc_pattern = LLAPI_LAYOUT_OVERSTRIPING;
559 else if (v1->lmm_pattern & LOV_PATTERN_MDT)
560 comp->llc_pattern = LLAPI_LAYOUT_MDT;
562 /* Lustre only supports RAID0, overstripping
565 comp->llc_pattern = v1->lmm_pattern;
567 if (v1->lmm_stripe_size == 0)
568 comp->llc_stripe_size = LLAPI_LAYOUT_DEFAULT;
570 comp->llc_stripe_size = v1->lmm_stripe_size;
572 if (v1->lmm_stripe_count == (typeof(v1->lmm_stripe_count))-1)
573 comp->llc_stripe_count = LLAPI_LAYOUT_WIDE;
574 else if (v1->lmm_stripe_count == 0)
575 comp->llc_stripe_count = LLAPI_LAYOUT_DEFAULT;
577 comp->llc_stripe_count = v1->lmm_stripe_count;
579 if (v1->lmm_stripe_offset ==
580 (typeof(v1->lmm_stripe_offset))-1)
581 comp->llc_stripe_offset = LLAPI_LAYOUT_DEFAULT;
583 comp->llc_stripe_offset = v1->lmm_stripe_offset;
585 if (v1->lmm_magic != LOV_USER_MAGIC_V1) {
586 const struct lov_user_md_v3 *lumv3;
587 lumv3 = (struct lov_user_md_v3 *)v1;
588 snprintf(comp->llc_pool_name,
589 sizeof(comp->llc_pool_name),
590 "%s", lumv3->lmm_pool_name);
591 memcpy(comp->llc_objects, lumv3->lmm_objects,
592 obj_count * sizeof(lumv3->lmm_objects[0]));
594 const struct lov_user_md_v1 *lumv1;
595 lumv1 = (struct lov_user_md_v1 *)v1;
596 memcpy(comp->llc_objects, lumv1->lmm_objects,
597 obj_count * sizeof(lumv1->lmm_objects[0]));
601 comp->llc_stripe_offset =
602 comp->llc_objects[0].l_ost_idx;
604 comp->llc_ondisk = true;
605 list_add_tail(&comp->llc_list, &layout->llot_comp_list);
606 layout->llot_cur_comp = comp;
610 if (lum != lov_xattr)
614 llapi_layout_free(layout);
619 __u32 llapi_pattern_to_lov(uint64_t pattern)
624 case LLAPI_LAYOUT_DEFAULT:
625 lov_pattern = LOV_PATTERN_RAID0;
627 case LLAPI_LAYOUT_RAID0:
628 lov_pattern = LOV_PATTERN_RAID0;
630 case LLAPI_LAYOUT_MDT:
631 lov_pattern = LOV_PATTERN_MDT;
633 case LLAPI_LAYOUT_OVERSTRIPING:
634 lov_pattern = LOV_PATTERN_OVERSTRIPING | LOV_PATTERN_RAID0;
637 lov_pattern = EINVAL;
644 * Convert the data from a llapi_layout to a newly allocated lov_user_md.
645 * The caller is responsible for freeing the returned pointer.
647 * \param[in] layout the layout to copy from
649 * \retval valid lov_user_md pointer on success
650 * \retval NULL if memory allocation fails or the layout is invalid
652 static struct lov_user_md *
653 llapi_layout_to_lum(const struct llapi_layout *layout)
655 struct llapi_layout_comp *comp;
656 struct lov_comp_md_v1 *comp_v1 = NULL;
657 struct lov_comp_md_entry_v1 *ent;
658 struct lov_user_md *lum = NULL;
663 if (layout == NULL ||
664 list_empty((struct list_head *)&layout->llot_comp_list)) {
669 /* Allocate header of lov_comp_md_v1 if necessary */
670 if (layout->llot_is_composite) {
673 list_for_each_entry(comp, &layout->llot_comp_list, llc_list)
676 lum_size = sizeof(*comp_v1) + comp_cnt * sizeof(*ent);
677 lum = calloc(lum_size, 1);
682 comp_v1 = (struct lov_comp_md_v1 *)lum;
683 comp_v1->lcm_magic = LOV_USER_MAGIC_COMP_V1;
684 comp_v1->lcm_size = lum_size;
685 comp_v1->lcm_layout_gen = 0;
686 comp_v1->lcm_flags = layout->llot_flags;
687 comp_v1->lcm_entry_count = comp_cnt;
688 comp_v1->lcm_mirror_count = layout->llot_mirror_count - 1;
692 list_for_each_entry(comp, &layout->llot_comp_list, llc_list) {
693 struct lov_user_md *blob;
696 int i, obj_count = 0;
697 struct lov_user_ost_data *lmm_objects;
698 uint64_t pattern = comp->llc_pattern;
700 if ((pattern & LLAPI_LAYOUT_SPECIFIC) != 0) {
701 if (comp->llc_objects_count <
702 comp->llc_stripe_count) {
706 magic = LOV_USER_MAGIC_SPECIFIC;
707 obj_count = comp->llc_stripe_count;
708 pattern &= ~LLAPI_LAYOUT_SPECIFIC;
709 } else if (strlen(comp->llc_pool_name) != 0) {
710 magic = LOV_USER_MAGIC_V3;
712 magic = LOV_USER_MAGIC_V1;
714 /* All stripes must be specified when the pattern contains
715 * LLAPI_LAYOUT_SPECIFIC */
716 for (i = 0; i < obj_count; i++) {
717 if (comp->llc_objects[i].l_ost_idx ==
718 LLAPI_LAYOUT_IDX_MAX) {
724 blob_size = lov_user_md_size(obj_count, magic);
725 blob = realloc(lum, lum_size + blob_size);
731 comp_v1 = (struct lov_comp_md_v1 *)lum;
732 blob = (struct lov_user_md *)((char *)lum + lum_size);
733 lum_size += blob_size;
736 blob->lmm_magic = magic;
737 blob->lmm_pattern = llapi_pattern_to_lov(pattern);
738 if (blob->lmm_pattern == EINVAL) {
743 if (comp->llc_stripe_size == LLAPI_LAYOUT_DEFAULT)
744 blob->lmm_stripe_size = 0;
746 blob->lmm_stripe_size = comp->llc_stripe_size;
748 if (comp->llc_stripe_count == LLAPI_LAYOUT_DEFAULT)
749 blob->lmm_stripe_count = 0;
750 else if (comp->llc_stripe_count == LLAPI_LAYOUT_WIDE)
751 blob->lmm_stripe_count = LOV_ALL_STRIPES;
753 blob->lmm_stripe_count = comp->llc_stripe_count;
755 if (comp->llc_stripe_offset == LLAPI_LAYOUT_DEFAULT)
756 blob->lmm_stripe_offset = -1;
758 blob->lmm_stripe_offset = comp->llc_stripe_offset;
760 if (magic == LOV_USER_MAGIC_V3 ||
761 magic == LOV_USER_MAGIC_SPECIFIC) {
762 struct lov_user_md_v3 *lumv3 =
763 (struct lov_user_md_v3 *)blob;
765 if (comp->llc_pool_name[0] != '\0') {
766 strncpy(lumv3->lmm_pool_name,
768 sizeof(lumv3->lmm_pool_name));
770 memset(lumv3->lmm_pool_name, 0,
771 sizeof(lumv3->lmm_pool_name));
773 lmm_objects = lumv3->lmm_objects;
775 lmm_objects = blob->lmm_objects;
778 for (i = 0; i < obj_count; i++)
779 lmm_objects[i].l_ost_idx =
780 comp->llc_objects[i].l_ost_idx;
782 if (layout->llot_is_composite) {
783 ent = &comp_v1->lcm_entries[ent_idx];
784 ent->lcme_id = comp->llc_id;
785 ent->lcme_flags = comp->llc_flags;
786 if (ent->lcme_flags & LCME_FL_NOSYNC)
787 ent->lcme_timestamp = comp->llc_timestamp;
788 ent->lcme_extent.e_start = comp->llc_extent.e_start;
789 ent->lcme_extent.e_end = comp->llc_extent.e_end;
790 ent->lcme_size = blob_size;
791 ent->lcme_offset = offset;
793 comp_v1->lcm_size += blob_size;
807 * Get the parent directory of a path.
809 * \param[in] path path to get parent of
810 * \param[out] buf buffer in which to store parent path
811 * \param[in] size size in bytes of buffer \a buf
813 static void get_parent_dir(const char *path, char *buf, size_t size)
817 strncpy(buf, path, size - 1);
818 p = strrchr(buf, '/');
822 } else if (size >= 2) {
823 strncpy(buf, ".", 2);
824 buf[size - 1] = '\0';
829 * Substitute unspecified attribute values in \a layout with values
830 * from fs global settings. (lov.stripesize, lov.stripecount,
833 * \param[in] layout layout to inherit values from
834 * \param[in] path file path of the filesystem
836 static void inherit_sys_attributes(struct llapi_layout *layout,
839 struct llapi_layout_comp *comp;
840 unsigned int ssize, scount, soffset;
843 rc = sattr_cache_get_defaults(NULL, path, &scount, &ssize, &soffset);
847 list_for_each_entry(comp, &layout->llot_comp_list, llc_list) {
848 if (comp->llc_pattern == LLAPI_LAYOUT_DEFAULT)
849 comp->llc_pattern = LLAPI_LAYOUT_RAID0;
850 if (comp->llc_stripe_size == LLAPI_LAYOUT_DEFAULT)
851 comp->llc_stripe_size = ssize;
852 if (comp->llc_stripe_count == LLAPI_LAYOUT_DEFAULT)
853 comp->llc_stripe_count = scount;
854 if (comp->llc_stripe_offset == LLAPI_LAYOUT_DEFAULT)
855 comp->llc_stripe_offset = soffset;
860 * Get the current component of \a layout.
862 * \param[in] layout layout to get current component
864 * \retval valid llapi_layout_comp pointer on success
865 * \retval NULL on error
867 static struct llapi_layout_comp *
868 __llapi_layout_cur_comp(const struct llapi_layout *layout)
870 struct llapi_layout_comp *comp;
872 if (layout == NULL || layout->llot_magic != LLAPI_LAYOUT_MAGIC) {
876 if (layout->llot_cur_comp == NULL) {
880 /* Verify data consistency */
881 list_for_each_entry(comp, &layout->llot_comp_list, llc_list)
882 if (comp == layout->llot_cur_comp)
889 * Test if any attributes of \a layout are specified.
891 * \param[in] layout the layout to check
893 * \retval true any attributes are specified
894 * \retval false all attributes are unspecified
896 static bool is_any_specified(const struct llapi_layout *layout)
898 struct llapi_layout_comp *comp;
900 comp = __llapi_layout_cur_comp(layout);
904 if (layout->llot_is_composite || layout->llot_mirror_count != 1)
907 return comp->llc_pattern != LLAPI_LAYOUT_DEFAULT ||
908 comp->llc_stripe_size != LLAPI_LAYOUT_DEFAULT ||
909 comp->llc_stripe_count != LLAPI_LAYOUT_DEFAULT ||
910 comp->llc_stripe_offset != LLAPI_LAYOUT_DEFAULT ||
911 strlen(comp->llc_pool_name);
915 * Get the striping layout for the file referenced by file descriptor \a fd.
917 * If the filesystem does not support the "lustre." xattr namespace, the
918 * file must be on a non-Lustre filesystem, so set errno to ENOTTY per
919 * convention. If the file has no "lustre.lov" data, the file will
920 * inherit default values, so return a default layout.
922 * If the kernel gives us back less than the expected amount of data,
923 * we fail with errno set to EINTR.
925 * \param[in] fd open file descriptor
926 * \param[in] flags open file descriptor
928 * \retval valid llapi_layout pointer on success
929 * \retval NULL if an error occurs
931 struct llapi_layout *llapi_layout_get_by_fd(int fd,
932 enum llapi_layout_get_flags flags)
935 struct lov_user_md *lum;
936 struct llapi_layout *layout = NULL;
940 lum_len = XATTR_SIZE_MAX;
941 lum = malloc(lum_len);
945 bytes_read = fgetxattr(fd, XATTR_LUSTRE_LOV, lum, lum_len);
946 if (bytes_read < 0) {
947 if (errno == EOPNOTSUPP)
949 else if (errno == ENODATA)
950 layout = llapi_layout_alloc();
954 /* Directories may have a positive non-zero lum->lmm_stripe_count
955 * yet have an empty lum->lmm_objects array. For non-directories the
956 * amount of data returned from the kernel must be consistent
957 * with the stripe count. */
958 if (fstat(fd, &st) < 0)
961 layout = llapi_layout_get_by_xattr(lum, bytes_read,
962 S_ISDIR(st.st_mode) ? 0 : LLAPI_LAYOUT_GET_CHECK);
969 * Get the expected striping layout for a file at \a path.
971 * Substitute expected inherited attribute values for unspecified
972 * attributes. Unspecified attributes may belong to directories and
973 * never-written-to files, and indicate that default values will be
974 * assigned when files are created or first written to. A default value
975 * is inherited from the parent directory if the attribute is specified
976 * there, otherwise it is inherited from the filesystem root.
977 * Unspecified attributes normally have the value LLAPI_LAYOUT_DEFAULT.
979 * The complete \a path need not refer to an existing file or directory,
980 * but some leading portion of it must reside within a lustre filesystem.
981 * A use case for this interface would be to obtain the literal striping
982 * values that would be assigned to a new file in a given directory.
984 * \param[in] path path for which to get the expected layout
986 * \retval valid llapi_layout pointer on success
987 * \retval NULL if an error occurs
989 static struct llapi_layout *llapi_layout_expected(const char *path)
991 struct llapi_layout *path_layout = NULL;
992 char donor_path[PATH_MAX];
997 fd = open(path, O_RDONLY);
998 if (fd < 0 && errno != ENOENT)
1004 path_layout = llapi_layout_get_by_fd(fd, 0);
1010 if (path_layout == NULL) {
1011 if (errno != ENODATA && errno != ENOENT)
1014 path_layout = llapi_layout_alloc();
1015 if (path_layout == NULL)
1019 if (is_any_specified(path_layout)) {
1020 inherit_sys_attributes(path_layout, path);
1024 llapi_layout_free(path_layout);
1026 rc = stat(path, &st);
1027 if (rc < 0 && errno != ENOENT)
1030 /* If path is a not a directory or doesn't exist, inherit layout
1031 * from parent directory. */
1032 if ((rc == 0 && !S_ISDIR(st.st_mode)) ||
1033 (rc < 0 && errno == ENOENT)) {
1034 get_parent_dir(path, donor_path, sizeof(donor_path));
1035 path_layout = llapi_layout_get_by_path(donor_path, 0);
1036 if (path_layout != NULL) {
1037 if (is_any_specified(path_layout)) {
1038 inherit_sys_attributes(path_layout, donor_path);
1041 llapi_layout_free(path_layout);
1045 /* Inherit layout from the filesystem root. */
1046 rc = llapi_search_mounts(path, 0, donor_path, NULL);
1049 path_layout = llapi_layout_get_by_path(donor_path, 0);
1050 if (path_layout == NULL)
1053 inherit_sys_attributes(path_layout, donor_path);
1058 * Get the striping layout for the file at \a path.
1060 * If \a flags contains LLAPI_LAYOUT_GET_EXPECTED, substitute
1061 * expected inherited attribute values for unspecified attributes. See
1062 * llapi_layout_expected().
1064 * \param[in] path path for which to get the layout
1065 * \param[in] flags flags to control how layout is retrieved
1067 * \retval valid llapi_layout pointer on success
1068 * \retval NULL if an error occurs
1070 struct llapi_layout *llapi_layout_get_by_path(const char *path,
1071 enum llapi_layout_get_flags flags)
1073 struct llapi_layout *layout = NULL;
1074 bool failed = false;
1079 if (flags & LLAPI_LAYOUT_GET_EXPECTED)
1080 return llapi_layout_expected(path);
1082 /* Always get layout in O_DIRECT */
1083 /* Allow fetching layout even without the key on encrypted files */
1084 open_flags = O_RDONLY | O_DIRECT | O_CIPHERTEXT;
1086 fd = open(path, open_flags);
1088 if (errno != EINVAL || failed)
1090 /* EINVAL is because a directory cannot be opened in O_DIRECT */
1091 open_flags = O_RDONLY | O_CIPHERTEXT;
1096 layout = llapi_layout_get_by_fd(fd, flags);
1105 * Get the layout for the file with FID \a fidstr in filesystem \a lustre_dir.
1107 * \param[in] lustre_dir path within Lustre filesystem containing \a fid
1108 * \param[in] fid Lustre identifier of file to get layout for
1110 * \retval valid llapi_layout pointer on success
1111 * \retval NULL if an error occurs
1113 struct llapi_layout *llapi_layout_get_by_fid(const char *lustre_dir,
1114 const struct lu_fid *fid,
1115 enum llapi_layout_get_flags flags)
1119 int saved_msg_level = llapi_msg_get_level();
1120 struct llapi_layout *layout = NULL;
1122 /* Prevent llapi internal routines from writing to console
1123 * while executing this function, then restore previous message
1125 llapi_msg_set_level(LLAPI_MSG_OFF);
1126 fd = llapi_open_by_fid(lustre_dir, fid, O_RDONLY);
1127 llapi_msg_set_level(saved_msg_level);
1132 layout = llapi_layout_get_by_fd(fd, flags);
1141 * Get the stripe count of \a layout.
1143 * \param[in] layout layout to get stripe count from
1144 * \param[out] count integer to store stripe count in
1146 * \retval 0 on success
1147 * \retval -1 if arguments are invalid
1149 int llapi_layout_stripe_count_get(const struct llapi_layout *layout,
1152 struct llapi_layout_comp *comp;
1154 comp = __llapi_layout_cur_comp(layout);
1158 if (count == NULL) {
1163 *count = comp->llc_stripe_count;
1169 * The llapi_layout API functions have these extra validity checks since
1170 * they use intuitively named macros to denote special behavior, whereas
1171 * the old API uses 0 and -1.
1174 bool llapi_layout_stripe_count_is_valid(int64_t stripe_count)
1176 return stripe_count == LLAPI_LAYOUT_DEFAULT ||
1177 stripe_count == LLAPI_LAYOUT_WIDE ||
1178 (stripe_count != 0 && stripe_count != -1 &&
1179 llapi_stripe_count_is_valid(stripe_count));
1182 static bool llapi_layout_extension_size_is_valid(uint64_t ext_size)
1184 return (ext_size != 0 &&
1185 llapi_stripe_size_is_aligned(ext_size) &&
1186 !llapi_stripe_size_is_too_big(ext_size));
1189 static bool llapi_layout_stripe_size_is_valid(uint64_t stripe_size)
1191 return stripe_size == LLAPI_LAYOUT_DEFAULT ||
1192 (stripe_size != 0 &&
1193 llapi_stripe_size_is_aligned(stripe_size) &&
1194 !llapi_stripe_size_is_too_big(stripe_size));
1197 static bool llapi_layout_stripe_index_is_valid(int64_t stripe_index)
1199 return stripe_index == LLAPI_LAYOUT_DEFAULT ||
1200 (stripe_index >= 0 &&
1201 llapi_stripe_index_is_valid(stripe_index));
1205 * Set the stripe count of \a layout.
1207 * \param[in] layout layout to set stripe count in
1208 * \param[in] count value to be set
1210 * \retval 0 on success
1211 * \retval -1 if arguments are invalid
1213 int llapi_layout_stripe_count_set(struct llapi_layout *layout,
1216 struct llapi_layout_comp *comp;
1218 comp = __llapi_layout_cur_comp(layout);
1222 if (!llapi_layout_stripe_count_is_valid(count)) {
1227 comp->llc_stripe_count = count;
1233 * Get the stripe/extension size of \a layout.
1235 * \param[in] layout layout to get stripe size from
1236 * \param[out] size integer to store stripe size in
1237 * \param[in] extension flag if extenion size is requested
1239 * \retval 0 on success
1240 * \retval -1 if arguments are invalid
1242 static int layout_stripe_size_get(const struct llapi_layout *layout,
1243 uint64_t *size, bool extension)
1245 struct llapi_layout_comp *comp;
1248 comp = __llapi_layout_cur_comp(layout);
1257 comp_ext = comp->llc_flags & LCME_FL_EXTENSION;
1258 if ((comp_ext && !extension) || (!comp_ext && extension)) {
1263 *size = comp->llc_stripe_size;
1264 if (comp->llc_flags & LCME_FL_EXTENSION)
1265 *size *= SEL_UNIT_SIZE;
1270 int llapi_layout_stripe_size_get(const struct llapi_layout *layout,
1273 return layout_stripe_size_get(layout, size, false);
1276 int llapi_layout_extension_size_get(const struct llapi_layout *layout,
1279 return layout_stripe_size_get(layout, size, true);
1283 * Set the stripe/extension size of \a layout.
1285 * \param[in] layout layout to set stripe size in
1286 * \param[in] size value to be set
1287 * \param[in] extension flag if extenion size is passed
1289 * \retval 0 on success
1290 * \retval -1 if arguments are invalid
1292 static int layout_stripe_size_set(struct llapi_layout *layout,
1293 uint64_t size, bool extension)
1295 struct llapi_layout_comp *comp;
1298 comp = __llapi_layout_cur_comp(layout);
1302 comp_ext = comp->llc_flags & LCME_FL_EXTENSION;
1303 if ((comp_ext && !extension) || (!comp_ext && extension)) {
1309 size /= SEL_UNIT_SIZE;
1311 if ((comp_ext && !llapi_layout_extension_size_is_valid(size)) ||
1312 (!comp_ext && !llapi_layout_stripe_size_is_valid(size))) {
1317 comp->llc_stripe_size = size;
1321 int llapi_layout_stripe_size_set(struct llapi_layout *layout,
1324 return layout_stripe_size_set(layout, size, false);
1327 int llapi_layout_extension_size_set(struct llapi_layout *layout,
1330 return layout_stripe_size_set(layout, size, true);
1334 * Get the RAID pattern of \a layout.
1336 * \param[in] layout layout to get pattern from
1337 * \param[out] pattern integer to store pattern in
1339 * \retval 0 on success
1340 * \retval -1 if arguments are invalid
1342 int llapi_layout_pattern_get(const struct llapi_layout *layout,
1345 struct llapi_layout_comp *comp;
1347 comp = __llapi_layout_cur_comp(layout);
1351 if (pattern == NULL) {
1356 *pattern = comp->llc_pattern;
1362 * Set the pattern of \a layout.
1364 * \param[in] layout layout to set pattern in
1365 * \param[in] pattern value to be set
1367 * \retval 0 on success
1368 * \retval -1 if arguments are invalid or RAID pattern
1371 int llapi_layout_pattern_set(struct llapi_layout *layout, uint64_t pattern)
1373 struct llapi_layout_comp *comp;
1375 comp = __llapi_layout_cur_comp(layout);
1379 if (pattern != LLAPI_LAYOUT_DEFAULT &&
1380 pattern != LLAPI_LAYOUT_RAID0 && pattern != LLAPI_LAYOUT_MDT
1381 && pattern != LLAPI_LAYOUT_OVERSTRIPING) {
1386 comp->llc_pattern = pattern |
1387 (comp->llc_pattern & LLAPI_LAYOUT_SPECIFIC);
1392 static inline int stripe_number_roundup(int stripe_number)
1394 unsigned int round_up = (stripe_number + 8) & ~7;
1395 return round_up > LOV_MAX_STRIPE_COUNT ?
1396 LOV_MAX_STRIPE_COUNT : round_up;
1400 * Set the OST index of stripe number \a stripe_number to \a ost_index.
1402 * If only the starting stripe's OST index is specified, then this can use
1403 * the normal LOV_MAGIC_{V1,V3} layout type. If multiple OST indices are
1404 * given, then allocate an array to hold the list of indices and ensure that
1405 * the LOV_USER_MAGIC_SPECIFIC layout is used when creating the file.
1407 * \param[in] layout layout to set OST index in
1408 * \param[in] stripe_number stripe number to set index for
1409 * \param[in] ost_index the index to set
1411 * \retval 0 on success
1412 * \retval -1 if arguments are invalid or an unsupported stripe number
1413 * was specified, error returned in errno
1415 int llapi_layout_ost_index_set(struct llapi_layout *layout, int stripe_number,
1418 struct llapi_layout_comp *comp;
1420 comp = __llapi_layout_cur_comp(layout);
1424 if (!llapi_layout_stripe_index_is_valid(ost_index)) {
1429 if (stripe_number == 0 && ost_index == LLAPI_LAYOUT_DEFAULT) {
1430 comp->llc_stripe_offset = ost_index;
1431 comp->llc_pattern &= ~LLAPI_LAYOUT_SPECIFIC;
1432 __llapi_comp_objects_realloc(comp, 0);
1433 } else if (stripe_number >= 0 &&
1434 stripe_number < LOV_MAX_STRIPE_COUNT) {
1435 if (ost_index >= LLAPI_LAYOUT_IDX_MAX) {
1440 /* Preallocate a few more stripes to avoid realloc() overhead.*/
1441 if (__llapi_comp_objects_realloc(comp,
1442 stripe_number_roundup(stripe_number)) < 0)
1445 comp->llc_objects[stripe_number].l_ost_idx = ost_index;
1447 if (stripe_number == 0)
1448 comp->llc_stripe_offset = ost_index;
1450 comp->llc_pattern |= LLAPI_LAYOUT_SPECIFIC;
1452 if (comp->llc_stripe_count == LLAPI_LAYOUT_DEFAULT ||
1453 comp->llc_stripe_count <= stripe_number)
1454 comp->llc_stripe_count = stripe_number + 1;
1464 * Get the OST index associated with stripe \a stripe_number.
1466 * Stripes are indexed starting from zero.
1468 * \param[in] layout layout to get index from
1469 * \param[in] stripe_number stripe number to get index for
1470 * \param[out] index integer to store index in
1472 * \retval 0 on success
1473 * \retval -1 if arguments are invalid
1475 int llapi_layout_ost_index_get(const struct llapi_layout *layout,
1476 uint64_t stripe_number, uint64_t *index)
1478 struct llapi_layout_comp *comp;
1480 comp = __llapi_layout_cur_comp(layout);
1484 if (index == NULL) {
1489 if (stripe_number >= comp->llc_stripe_count ||
1490 stripe_number >= comp->llc_objects_count) {
1495 if (comp->llc_stripe_offset == LLAPI_LAYOUT_DEFAULT)
1496 *index = LLAPI_LAYOUT_DEFAULT;
1498 *index = comp->llc_objects[stripe_number].l_ost_idx;
1505 * Get the pool name of layout \a layout.
1507 * \param[in] layout layout to get pool name from
1508 * \param[out] dest buffer to store pool name in
1509 * \param[in] n size in bytes of buffer \a dest
1511 * \retval 0 on success
1512 * \retval -1 if arguments are invalid
1514 int llapi_layout_pool_name_get(const struct llapi_layout *layout, char *dest,
1517 struct llapi_layout_comp *comp;
1519 comp = __llapi_layout_cur_comp(layout);
1528 strncpy(dest, comp->llc_pool_name, n);
1534 * Set the name of the pool of layout \a layout.
1536 * \param[in] layout layout to set pool name in
1537 * \param[in] pool_name pool name to set
1539 * \retval 0 on success
1540 * \retval -1 if arguments are invalid or pool name is too long
1542 int llapi_layout_pool_name_set(struct llapi_layout *layout,
1543 const char *pool_name)
1545 struct llapi_layout_comp *comp;
1547 comp = __llapi_layout_cur_comp(layout);
1551 if (!llapi_pool_name_is_valid(&pool_name)) {
1556 strncpy(comp->llc_pool_name, pool_name, sizeof(comp->llc_pool_name));
1561 * Open and possibly create a file with a given \a layout.
1563 * If \a layout is NULL this function acts as a simple wrapper for
1564 * open(). By convention, ENOTTY is returned in errno if \a path
1565 * refers to a non-Lustre file.
1567 * \param[in] path name of the file to open
1568 * \param[in] open_flags open() flags
1569 * \param[in] mode permissions to create file, filtered by umask
1570 * \param[in] layout layout to create new file with
1572 * \retval non-negative file descriptor on successful open
1573 * \retval -1 if an error occurred
1575 int llapi_layout_file_open(const char *path, int open_flags, mode_t mode,
1576 const struct llapi_layout *layout)
1581 struct lov_user_md *lum;
1583 char fsname[MAX_OBD_NAME + 1] = { 0 };
1586 (layout != NULL && layout->llot_magic != LLAPI_LAYOUT_MAGIC)) {
1592 /* Make sure we are on a Lustre file system */
1593 rc = llapi_search_fsname(path, fsname);
1598 rc = llapi_layout_v2_sanity((struct llapi_layout *)layout,
1600 !!(layout->llot_mirror_count > 1),
1603 llapi_layout_sanity_perror(rc);
1608 /* Object creation must be postponed until after layout attributes
1609 * have been applied. */
1610 if (layout != NULL && (open_flags & O_CREAT))
1611 open_flags |= O_LOV_DELAY_CREATE;
1613 fd = open(path, open_flags, mode);
1615 if (layout == NULL || fd < 0)
1618 lum = llapi_layout_to_lum(layout);
1627 if (lum->lmm_magic == LOV_USER_MAGIC_COMP_V1)
1628 lum_size = ((struct lov_comp_md_v1 *)lum)->lcm_size;
1629 else if (lum->lmm_magic == LOV_USER_MAGIC_SPECIFIC)
1630 lum_size = lov_user_md_size(lum->lmm_stripe_count,
1633 lum_size = lov_user_md_size(0, lum->lmm_magic);
1635 rc = fsetxattr(fd, XATTR_LUSTRE_LOV, lum, lum_size, 0);
1644 errno = errno == EOPNOTSUPP ? ENOTTY : errno;
1650 * Create a file with a given \a layout.
1652 * Force O_CREAT and O_EXCL flags on so caller is assured that file was
1653 * created with the given \a layout on successful function return.
1655 * \param[in] path name of the file to open
1656 * \param[in] open_flags open() flags
1657 * \param[in] mode permissions to create new file with
1658 * \param[in] layout layout to create new file with
1660 * \retval non-negative file descriptor on successful open
1661 * \retval -1 if an error occurred
1663 int llapi_layout_file_create(const char *path, int open_flags, int mode,
1664 const struct llapi_layout *layout)
1666 return llapi_layout_file_open(path, open_flags|O_CREAT|O_EXCL, mode,
1670 int llapi_layout_flags_get(struct llapi_layout *layout, uint32_t *flags)
1672 if (layout->llot_magic != LLAPI_LAYOUT_MAGIC) {
1677 *flags = layout->llot_flags;
1682 * Set flags to the header of a component layout.
1684 int llapi_layout_flags_set(struct llapi_layout *layout, uint32_t flags)
1686 if (layout->llot_magic != LLAPI_LAYOUT_MAGIC) {
1691 layout->llot_flags = flags;
1695 const char *llapi_layout_flags_string(uint32_t flags)
1697 switch (flags & LCM_FL_FLR_MASK) {
1700 case LCM_FL_WRITE_PENDING:
1702 case LCM_FL_SYNC_PENDING:
1709 __u16 llapi_layout_string_flags(char *string)
1711 if (strncmp(string, "ro", strlen(string)) == 0)
1712 return LCM_FL_RDONLY;
1713 if (strncmp(string, "wp", strlen(string)) == 0)
1714 return LCM_FL_WRITE_PENDING;
1715 if (strncmp(string, "sp", strlen(string)) == 0)
1716 return LCM_FL_SYNC_PENDING;
1722 * llapi_layout_mirror_count_is_valid() - Check the validity of mirror count.
1723 * @count: Mirror count value to be checked.
1725 * This function checks the validity of mirror count.
1727 * Return: true on success or false on failure.
1729 static bool llapi_layout_mirror_count_is_valid(uint16_t count)
1731 return count >= 0 && count <= LUSTRE_MIRROR_COUNT_MAX;
1735 * llapi_layout_mirror_count_get() - Get mirror count from the header of
1737 * @layout: Layout to get mirror count from.
1738 * @count: Returned mirror count value.
1740 * This function gets mirror count from the header of a layout.
1742 * Return: 0 on success or -1 on failure.
1744 int llapi_layout_mirror_count_get(struct llapi_layout *layout,
1747 if (layout->llot_magic != LLAPI_LAYOUT_MAGIC) {
1752 *count = layout->llot_mirror_count;
1757 * llapi_layout_mirror_count_set() - Set mirror count to the header of a layout.
1758 * @layout: Layout to set mirror count in.
1759 * @count: Mirror count value to be set.
1761 * This function sets mirror count to the header of a layout.
1763 * Return: 0 on success or -1 on failure.
1765 int llapi_layout_mirror_count_set(struct llapi_layout *layout,
1768 if (layout->llot_magic != LLAPI_LAYOUT_MAGIC) {
1773 if (!llapi_layout_mirror_count_is_valid(count)) {
1778 layout->llot_mirror_count = count;
1783 * Fetch the start and end offset of the current layout component.
1785 * \param[in] layout the layout component
1786 * \param[out] start extent start, inclusive
1787 * \param[out] end extent end, exclusive
1789 * \retval 0 on success
1790 * \retval <0 if error occurs
1792 int llapi_layout_comp_extent_get(const struct llapi_layout *layout,
1793 uint64_t *start, uint64_t *end)
1795 struct llapi_layout_comp *comp;
1797 comp = __llapi_layout_cur_comp(layout);
1801 if (start == NULL || end == NULL) {
1806 *start = comp->llc_extent.e_start;
1807 *end = comp->llc_extent.e_end;
1813 * Set the layout extent of a layout.
1815 * \param[in] layout the layout to be set
1816 * \param[in] start extent start, inclusive
1817 * \param[in] end extent end, exclusive
1819 * \retval 0 on success
1820 * \retval <0 if error occurs
1822 int llapi_layout_comp_extent_set(struct llapi_layout *layout,
1823 uint64_t start, uint64_t end)
1825 struct llapi_layout_comp *comp;
1827 comp = __llapi_layout_cur_comp(layout);
1836 comp->llc_extent.e_start = start;
1837 comp->llc_extent.e_end = end;
1838 layout->llot_is_composite = true;
1844 * Gets the attribute flags of the current component.
1846 * \param[in] layout the layout component
1847 * \param[out] flags stored the returned component flags
1849 * \retval 0 on success
1850 * \retval <0 if error occurs
1852 int llapi_layout_comp_flags_get(const struct llapi_layout *layout,
1855 struct llapi_layout_comp *comp;
1857 comp = __llapi_layout_cur_comp(layout);
1861 if (flags == NULL) {
1866 *flags = comp->llc_flags;
1872 * Sets the specified flags of the current component leaving other flags as-is.
1874 * \param[in] layout the layout component
1875 * \param[in] flags component flags to be set
1877 * \retval 0 on success
1878 * \retval <0 if error occurs
1880 int llapi_layout_comp_flags_set(struct llapi_layout *layout, uint32_t flags)
1882 struct llapi_layout_comp *comp;
1884 comp = __llapi_layout_cur_comp(layout);
1888 comp->llc_flags |= flags;
1894 * Clears the flags specified in the flags leaving other flags as-is.
1896 * \param[in] layout the layout component
1897 * \param[in] flags component flags to be cleared
1899 * \retval 0 on success
1900 * \retval <0 if error occurs
1902 int llapi_layout_comp_flags_clear(struct llapi_layout *layout,
1905 struct llapi_layout_comp *comp;
1907 comp = __llapi_layout_cur_comp(layout);
1911 comp->llc_flags &= ~flags;
1917 * Fetches the file-unique component ID of the current layout component.
1919 * \param[in] layout the layout component
1920 * \param[out] id stored the returned component ID
1922 * \retval 0 on success
1923 * \retval <0 if error occurs
1925 int llapi_layout_comp_id_get(const struct llapi_layout *layout, uint32_t *id)
1927 struct llapi_layout_comp *comp;
1929 comp = __llapi_layout_cur_comp(layout);
1943 * Return the mirror id of the current layout component.
1945 * \param[in] layout the layout component
1946 * \param[out] id stored the returned mirror ID
1948 * \retval 0 on success
1949 * \retval <0 if error occurs
1951 int llapi_layout_mirror_id_get(const struct llapi_layout *layout, uint32_t *id)
1953 struct llapi_layout_comp *comp;
1955 comp = __llapi_layout_cur_comp(layout);
1964 *id = mirror_id_of(comp->llc_id);
1970 * Adds a component to \a layout, the new component will be added to
1971 * the tail of components list and it'll inherit attributes of existing
1972 * ones. The \a layout will change it's current component pointer to
1973 * the newly added component, and it'll be turned into a composite
1974 * layout if it was not before the adding.
1976 * \param[in] layout existing composite or plain layout
1978 * \retval 0 on success
1979 * \retval <0 if error occurs
1981 int llapi_layout_comp_add(struct llapi_layout *layout)
1983 struct llapi_layout_comp *last, *comp, *new;
1984 bool composite = layout->llot_is_composite;
1986 comp = __llapi_layout_cur_comp(layout);
1990 new = __llapi_comp_alloc(0);
1994 last = list_last_entry(&layout->llot_comp_list, typeof(*last),
1997 list_add_tail(&new->llc_list, &layout->llot_comp_list);
1999 /* We must mark the layout composite for the sanity check, but it may
2000 * not stay that way if the check fails */
2001 layout->llot_is_composite = true;
2002 layout->llot_cur_comp = new;
2004 /* We need to set a temporary non-zero value for "end" when we call
2005 * comp_extent_set, so we use LUSTRE_EOF-1, which is > all allowed
2006 * for the end of the previous component. (If we're adding this
2007 * component, the end of the previous component cannot be EOF.) */
2008 if (llapi_layout_comp_extent_set(layout, last->llc_extent.e_end,
2010 llapi_layout_comp_del(layout);
2011 layout->llot_is_composite = composite;
2018 * Adds a first component of a mirror to \a layout.
2019 * The \a layout will change it's current component pointer to
2020 * the newly added component, and it'll be turned into a composite
2021 * layout if it was not before the adding.
2023 * \param[in] layout existing composite or plain layout
2025 * \retval 0 on success
2026 * \retval <0 if error occurs
2028 int llapi_layout_add_first_comp(struct llapi_layout *layout)
2030 struct llapi_layout_comp *comp, *new;
2032 comp = __llapi_layout_cur_comp(layout);
2036 new = __llapi_comp_alloc(0);
2040 new->llc_extent.e_start = 0;
2042 list_add_tail(&new->llc_list, &layout->llot_comp_list);
2043 layout->llot_cur_comp = new;
2044 layout->llot_is_composite = true;
2050 * Deletes current component from the composite layout. The component
2051 * to be deleted must be the tail of components list, and it can't be
2052 * the only component in the layout.
2054 * \param[in] layout composite layout
2056 * \retval 0 on success
2057 * \retval <0 if error occurs
2059 int llapi_layout_comp_del(struct llapi_layout *layout)
2061 struct llapi_layout_comp *comp;
2063 comp = __llapi_layout_cur_comp(layout);
2067 if (!layout->llot_is_composite) {
2072 /* It must be the tail of the list (for PFL, can be relaxed
2073 * once we get mirrored components) */
2074 if (comp->llc_list.next != &layout->llot_comp_list) {
2078 layout->llot_cur_comp =
2079 list_last_entry(&comp->llc_list, typeof(*comp), llc_list);
2080 if (comp->llc_list.prev == &layout->llot_comp_list)
2081 layout->llot_cur_comp = NULL;
2083 list_del_init(&comp->llc_list);
2084 __llapi_comp_free(comp);
2090 * Move the current component pointer to the component with
2091 * specified component ID.
2093 * \param[in] layout composite layout
2094 * \param[in] id component ID
2096 * \retval =0 : moved successfully
2097 * \retval <0 if error occurs
2099 int llapi_layout_comp_use_id(struct llapi_layout *layout, uint32_t comp_id)
2101 struct llapi_layout_comp *comp;
2103 comp = __llapi_layout_cur_comp(layout);
2105 return -1; /* use previously set errno */
2107 if (!layout->llot_is_composite) {
2112 if (comp_id == LCME_ID_INVAL) {
2117 list_for_each_entry(comp, &layout->llot_comp_list, llc_list) {
2118 if (comp->llc_id == comp_id) {
2119 layout->llot_cur_comp = comp;
2128 * Move the current component pointer to a specified position.
2130 * \param[in] layout composite layout
2131 * \param[in] pos the position to be moved, it can be:
2132 * LLAPI_LAYOUT_COMP_USE_FIRST: use first component
2133 * LLAPI_LAYOUT_COMP_USE_LAST: use last component
2134 * LLAPI_LAYOUT_COMP_USE_NEXT: use component after current
2135 * LLAPI_LAYOUT_COMP_USE_PREV: use component before current
2137 * \retval =0 : moved successfully
2138 * \retval =1 : at last component with NEXT, at first component with PREV
2139 * \retval <0 if error occurs
2141 int llapi_layout_comp_use(struct llapi_layout *layout,
2142 enum llapi_layout_comp_use pos)
2144 struct llapi_layout_comp *comp, *head, *tail;
2146 comp = __llapi_layout_cur_comp(layout);
2150 if (!layout->llot_is_composite) {
2151 if (pos == LLAPI_LAYOUT_COMP_USE_FIRST ||
2152 pos == LLAPI_LAYOUT_COMP_USE_LAST)
2158 head = list_first_entry(&layout->llot_comp_list, typeof(*head),
2160 tail = list_last_entry(&layout->llot_comp_list, typeof(*tail),
2163 case LLAPI_LAYOUT_COMP_USE_FIRST:
2164 layout->llot_cur_comp = head;
2166 case LLAPI_LAYOUT_COMP_USE_NEXT:
2171 layout->llot_cur_comp = list_first_entry(&comp->llc_list,
2175 case LLAPI_LAYOUT_COMP_USE_LAST:
2176 layout->llot_cur_comp = tail;
2178 case LLAPI_LAYOUT_COMP_USE_PREV:
2183 layout->llot_cur_comp = list_last_entry(&comp->llc_list,
2196 * Add layout component(s) to an existing file.
2198 * \param[in] path The path name of the file
2199 * \param[in] layout The layout component(s) to be added
2201 int llapi_layout_file_comp_add(const char *path,
2202 const struct llapi_layout *layout)
2204 int rc, fd = -1, lum_size, tmp_errno = 0;
2205 struct llapi_layout *existing_layout = NULL;
2206 struct lov_user_md *lum = NULL;
2207 char fsname[MAX_OBD_NAME + 1] = { 0 };
2209 if (path == NULL || layout == NULL ||
2210 layout->llot_magic != LLAPI_LAYOUT_MAGIC) {
2215 fd = open(path, O_RDWR);
2222 existing_layout = llapi_layout_get_by_fd(fd, 0);
2223 if (existing_layout == NULL) {
2229 rc = llapi_layout_merge(&existing_layout, layout);
2236 rc = llapi_search_fsname(path, fsname);
2243 rc = llapi_layout_v2_sanity(existing_layout, false, false, fsname);
2246 llapi_layout_sanity_perror(rc);
2251 lum = llapi_layout_to_lum(layout);
2258 if (lum->lmm_magic != LOV_USER_MAGIC_COMP_V1) {
2263 lum_size = ((struct lov_comp_md_v1 *)lum)->lcm_size;
2265 rc = fsetxattr(fd, XATTR_LUSTRE_LOV".add", lum, lum_size, 0);
2275 llapi_layout_free(existing_layout);
2281 * Delete component(s) by the specified component id or component flags
2282 * from an existing file.
2284 * \param[in] path path name of the file
2285 * \param[in] id unique component ID
2286 * \param[in] flags flags: LCME_FL_* or;
2287 * negative flags: (LCME_FL_NEG|LCME_FL_*)
2289 int llapi_layout_file_comp_del(const char *path, uint32_t id, uint32_t flags)
2291 int rc = 0, fd = -1, lum_size, tmp_errno = 0;
2292 struct llapi_layout *layout;
2293 struct llapi_layout_comp *comp, *next;
2294 struct llapi_layout *existing_layout = NULL;
2295 struct lov_user_md *lum = NULL;
2297 if (path == NULL || id > LCME_ID_MAX || (flags & ~LCME_KNOWN_FLAGS)) {
2302 /* Can only specify ID or flags, not both, not none. */
2303 if ((id != LCME_ID_INVAL && flags != 0) ||
2304 (id == LCME_ID_INVAL && flags == 0)) {
2309 layout = llapi_layout_alloc();
2313 llapi_layout_comp_extent_set(layout, 0, LUSTRE_EOF);
2314 comp = __llapi_layout_cur_comp(layout);
2322 comp->llc_flags = flags;
2324 lum = llapi_layout_to_lum(layout);
2330 lum_size = ((struct lov_comp_md_v1 *)lum)->lcm_size;
2332 fd = open(path, O_RDWR);
2339 existing_layout = llapi_layout_get_by_fd(fd, 0);
2340 if (existing_layout == NULL) {
2348 while (rc == 0 && existing_layout->llot_cur_comp != NULL) {
2349 rc = llapi_layout_comp_use(existing_layout, comp ?
2350 LLAPI_LAYOUT_COMP_USE_PREV :
2351 LLAPI_LAYOUT_COMP_USE_LAST);
2356 comp = __llapi_layout_cur_comp(existing_layout);
2362 if (id != LCME_ID_INVAL && id != comp->llc_id)
2364 else if ((flags & LCME_FL_NEG) && (flags & comp->llc_flags))
2366 else if (flags && !(flags & comp->llc_flags))
2369 rc = llapi_layout_comp_del(existing_layout);
2370 /* the layout position is moved to previous one, adjust */
2378 rc = llapi_layout_sanity(existing_layout, false, false);
2381 llapi_layout_sanity_perror(rc);
2386 rc = fsetxattr(fd, XATTR_LUSTRE_LOV".del", lum, lum_size, 0);
2397 llapi_layout_free(layout);
2398 llapi_layout_free(existing_layout);
2404 /* Internal utility function to apply flags for sanity checking */
2405 static void llapi_layout_comp_apply_flags(struct llapi_layout_comp *comp,
2408 if (flags & LCME_FL_NEG)
2409 comp->llc_flags &= ~flags;
2411 comp->llc_flags |= flags;
2414 struct llapi_layout_apply_flags_args {
2416 uint32_t *lfa_flags;
2422 static int llapi_layout_apply_flags_cb(struct llapi_layout *layout,
2425 struct llapi_layout_apply_flags_args *args = arg;
2426 struct llapi_layout_comp *comp;
2429 comp = __llapi_layout_cur_comp(layout);
2432 return LLAPI_LAYOUT_ITER_STOP;
2435 for (i = 0; i < args->lfa_count; i++) {
2436 if (comp->llc_id == args->lfa_ids[i])
2437 llapi_layout_comp_apply_flags(comp, args->lfa_flags[i]);
2440 return LLAPI_LAYOUT_ITER_CONT;
2443 /* Apply flags to the layout for sanity checking */
2444 static int llapi_layout_apply_flags(struct llapi_layout *layout, uint32_t *ids,
2445 uint32_t *flags, int count)
2447 struct llapi_layout_apply_flags_args args;
2450 if (!ids || !flags || count == 0) {
2456 args.lfa_flags = flags;
2457 args.lfa_count = count;
2460 rc = llapi_layout_comp_iterate(layout,
2461 llapi_layout_apply_flags_cb,
2463 if (errno == ENOENT)
2466 if (rc != LLAPI_LAYOUT_ITER_CONT)
2472 * Change flags by component ID of components of an existing file.
2473 * The component to be modified is specified by the comp->lcme_id value,
2474 * which must be a unique component ID.
2476 * \param[in] path path name of the file
2477 * \param[in] ids An array of component IDs
2478 * \param[in] flags flags: LCME_FL_* or;
2479 * negative flags: (LCME_FL_NEG|LCME_FL_*)
2480 * \param[in] count Number of elements in ids and flags array
2482 int llapi_layout_file_comp_set(const char *path, uint32_t *ids, uint32_t *flags,
2485 int rc = -1, fd = -1, i, tmp_errno = 0;
2487 struct llapi_layout *existing_layout = NULL;
2488 struct llapi_layout *layout = NULL;
2489 struct llapi_layout_comp *comp;
2490 struct lov_user_md *lum = NULL;
2491 char fsname[MAX_OBD_NAME + 1] = { 0 };
2501 for (i = 0; i < count; i++) {
2502 if (!ids[i] || !flags[i]) {
2507 if (ids[i] > LCME_ID_MAX || (flags[i] & ~LCME_KNOWN_FLAGS)) {
2512 /* do not allow to set or clear INIT flag */
2513 if (flags[i] & LCME_FL_INIT) {
2519 fd = open(path, O_RDWR);
2526 existing_layout = llapi_layout_get_by_fd(fd, 0);
2527 if (existing_layout == NULL) {
2533 if (llapi_layout_apply_flags(existing_layout, ids, flags, count)) {
2539 rc = llapi_search_fsname(path, fsname);
2546 rc = llapi_layout_v2_sanity(existing_layout, false, false, fsname);
2549 llapi_layout_sanity_perror(rc);
2554 layout = __llapi_layout_alloc();
2555 if (layout == NULL) {
2561 layout->llot_is_composite = true;
2562 for (i = 0; i < count; i++) {
2563 comp = __llapi_comp_alloc(0);
2570 comp->llc_id = ids[i];
2571 comp->llc_flags = flags[i];
2573 list_add_tail(&comp->llc_list, &layout->llot_comp_list);
2574 layout->llot_cur_comp = comp;
2577 lum = llapi_layout_to_lum(layout);
2584 lum_size = ((struct lov_comp_md_v1 *)lum)->lcm_size;
2586 /* flush cached pages from clients */
2587 rc = llapi_file_flush(fd);
2594 rc = fsetxattr(fd, XATTR_LUSTRE_LOV".set.flags", lum, lum_size, 0);
2607 llapi_layout_free(existing_layout);
2608 llapi_layout_free(layout);
2614 * Check if the file layout is composite.
2616 * \param[in] layout the file layout to check
2618 * \retval true composite
2619 * \retval false not composite
2621 bool llapi_layout_is_composite(struct llapi_layout *layout)
2623 return layout->llot_is_composite;
2627 * Iterate every components in the @layout and call callback function @cb.
2629 * \param[in] layout component layout list.
2630 * \param[in] cb callback for each component
2631 * \param[in] cbdata callback data
2633 * \retval < 0 error happens during the iteration
2634 * \retval LLAPI_LAYOUT_ITER_CONT finished the iteration w/o error
2635 * \retval LLAPI_LAYOUT_ITER_STOP got something, stop the iteration
2637 int llapi_layout_comp_iterate(struct llapi_layout *layout,
2638 llapi_layout_iter_cb cb, void *cbdata)
2642 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_FIRST);
2647 * make sure on success llapi_layout_comp_use() API returns 0 with
2653 rc = cb(layout, cbdata);
2654 if (rc != LLAPI_LAYOUT_ITER_CONT)
2657 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_NEXT);
2660 else if (rc == 1) /* reached the last comp */
2661 return LLAPI_LAYOUT_ITER_CONT;
2668 * llapi_layout_merge() - Merge a composite layout into another one.
2669 * @dst_layout: Destination composite layout.
2670 * @src_layout: Source composite layout.
2672 * This function copies all of the components from @src_layout and
2673 * appends them to @dst_layout.
2675 * Return: 0 on success or -1 on failure.
2677 int llapi_layout_merge(struct llapi_layout **dst_layout,
2678 const struct llapi_layout *src_layout)
2680 struct llapi_layout *new_layout = *dst_layout;
2681 struct llapi_layout_comp *new = NULL;
2682 struct llapi_layout_comp *comp = NULL;
2685 if (src_layout == NULL ||
2686 list_empty((struct list_head *)&src_layout->llot_comp_list))
2689 if (new_layout == NULL) {
2690 new_layout = __llapi_layout_alloc();
2691 if (new_layout == NULL) {
2697 list_for_each_entry(comp, &src_layout->llot_comp_list, llc_list) {
2698 new = __llapi_comp_alloc(0);
2704 new->llc_pattern = comp->llc_pattern;
2705 new->llc_stripe_size = comp->llc_stripe_size;
2706 new->llc_stripe_count = comp->llc_stripe_count;
2707 new->llc_stripe_offset = comp->llc_stripe_offset;
2709 if (comp->llc_pool_name[0] != '\0')
2710 strncpy(new->llc_pool_name, comp->llc_pool_name,
2711 sizeof(new->llc_pool_name));
2713 for (i = 0; i < comp->llc_objects_count; i++) {
2714 if (__llapi_comp_objects_realloc(new,
2715 stripe_number_roundup(i)) < 0) {
2717 __llapi_comp_free(new);
2720 new->llc_objects[i].l_ost_idx = \
2721 comp->llc_objects[i].l_ost_idx;
2724 new->llc_objects_count = comp->llc_objects_count;
2725 new->llc_extent.e_start = comp->llc_extent.e_start;
2726 new->llc_extent.e_end = comp->llc_extent.e_end;
2727 new->llc_id = comp->llc_id;
2728 new->llc_flags = comp->llc_flags;
2730 list_add_tail(&new->llc_list, &new_layout->llot_comp_list);
2731 new_layout->llot_cur_comp = new;
2733 new_layout->llot_is_composite = true;
2735 *dst_layout = new_layout;
2738 llapi_layout_free(new_layout);
2743 * Get the last initialized component
2745 * \param[in] layout component layout list.
2748 * \retval -EINVAL not found
2749 * \retval -EISDIR directory layout
2751 int llapi_layout_get_last_init_comp(struct llapi_layout *layout)
2753 struct llapi_layout_comp *comp = NULL, *head = NULL;
2755 if (!layout->llot_is_composite)
2758 head = list_first_entry(&layout->llot_comp_list, typeof(*comp),
2762 if (head->llc_id == 0 && !(head->llc_flags & LCME_FL_INIT))
2766 /* traverse the components from the tail to find the last init one */
2767 comp = list_last_entry(&layout->llot_comp_list, typeof(*comp),
2769 while (comp != head) {
2770 if (comp->llc_flags & LCME_FL_INIT)
2772 comp = list_last_entry(&comp->llc_list, typeof(*comp),
2776 layout->llot_cur_comp = comp;
2778 return comp->llc_flags & LCME_FL_INIT ? 0 : -EINVAL;
2782 * Interit stripe info from the file's component to the mirror
2784 * \param[in] layout file component layout list.
2785 * \param[in] layout mirro component layout list.
2787 * \retval 0 on success
2788 * \retval -EINVAL on error
2790 int llapi_layout_mirror_inherit(struct llapi_layout *f_layout,
2791 struct llapi_layout *m_layout)
2793 struct llapi_layout_comp *m_comp = NULL;
2794 struct llapi_layout_comp *f_comp = NULL;
2797 f_comp = __llapi_layout_cur_comp(f_layout);
2800 m_comp = __llapi_layout_cur_comp(m_layout);
2804 /* DoM component does not inherit stripe size */
2805 if (m_comp->llc_pattern != LLAPI_LAYOUT_MDT)
2806 m_comp->llc_stripe_size = f_comp->llc_stripe_size;
2807 m_comp->llc_stripe_count = f_comp->llc_stripe_count;
2813 * Find all stale components.
2815 * \param[in] layout component layout list.
2816 * \param[out] comp array of stale component info.
2817 * \param[in] comp_size array size of @comp.
2818 * \param[in] mirror_ids array of mirror id that only components
2819 * belonging to these mirror will be collected.
2820 * \param[in] ids_nr number of mirror ids array.
2822 * \retval number of component info collected on success or
2823 * an error code on failure.
2825 int llapi_mirror_find_stale(struct llapi_layout *layout,
2826 struct llapi_resync_comp *comp, size_t comp_size,
2827 __u16 *mirror_ids, int ids_nr)
2832 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_FIRST);
2840 uint64_t start, end;
2842 rc = llapi_layout_comp_flags_get(layout, &flags);
2846 if (!(flags & LCME_FL_STALE))
2849 rc = llapi_layout_mirror_id_get(layout, &mirror_id);
2853 /* the caller only wants stale components from specific
2858 for (j = 0; j < ids_nr; j++) {
2859 if (mirror_ids[j] == mirror_id)
2863 /* not in the specified mirror */
2866 } else if (flags & LCME_FL_NOSYNC) {
2867 /* if not specified mirrors, do not resync "nosync"
2872 rc = llapi_layout_comp_id_get(layout, &id);
2876 rc = llapi_layout_comp_extent_get(layout, &start, &end);
2880 /* pack this component into @comp array */
2881 comp[idx].lrc_id = id;
2882 comp[idx].lrc_mirror_id = mirror_id;
2883 comp[idx].lrc_start = start;
2884 comp[idx].lrc_end = end;
2887 if (idx >= comp_size) {
2893 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_NEXT);
2900 return rc < 0 ? rc : idx;
2903 /* locate @layout to a valid component covering file [file_start, file_end) */
2904 int llapi_mirror_find(struct llapi_layout *layout, uint64_t file_start,
2905 uint64_t file_end, uint64_t *endp)
2907 uint32_t mirror_id = 0;
2910 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_FIRST);
2916 uint64_t start, end;
2917 uint32_t flags, id, rid;
2919 rc = llapi_layout_comp_flags_get(layout, &flags);
2923 if (flags & LCME_FL_STALE)
2926 rc = llapi_layout_mirror_id_get(layout, &rid);
2930 rc = llapi_layout_comp_id_get(layout, &id);
2934 rc = llapi_layout_comp_extent_get(layout, &start, &end);
2938 if (file_start >= start && file_start < end) {
2941 else if (mirror_id != rid || *endp != start)
2944 file_start = *endp = end;
2945 if (end >= file_end)
2950 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_NEXT);
2960 #ifndef NSEC_PER_SEC
2961 # define NSEC_PER_SEC 1000000000UL
2963 #define ONE_MB 0x100000
2964 static struct timespec timespec_sub(struct timespec *before,
2965 struct timespec *after)
2967 struct timespec ret;
2969 ret.tv_sec = after->tv_sec - before->tv_sec;
2970 if (after->tv_nsec < before->tv_nsec) {
2972 ret.tv_nsec = NSEC_PER_SEC + after->tv_nsec - before->tv_nsec;
2974 ret.tv_nsec = after->tv_nsec - before->tv_nsec;
2980 static void stats_log(struct timespec *now, struct timespec *start_time,
2981 ssize_t read_bytes, size_t write_bytes,
2982 off_t file_size_bytes)
2984 struct timespec diff = timespec_sub(start_time, now);
2986 if (file_size_bytes == 0)
2989 if (diff.tv_sec == 0 && diff.tv_nsec == 0)
2992 llapi_printf(LLAPI_MSG_NORMAL,
2993 "- { seconds: %li, rmbps: %5.2g, wmbps: %5.2g, copied: %lu, size: %lu, pct: %lu%% }\n",
2995 (double) read_bytes/((ONE_MB * diff.tv_sec) +
2996 ((ONE_MB * diff.tv_nsec)/NSEC_PER_SEC)),
2997 (double) write_bytes/((ONE_MB * diff.tv_sec) +
2998 ((ONE_MB * diff.tv_nsec)/NSEC_PER_SEC)),
3000 file_size_bytes/ONE_MB,
3001 ((write_bytes*100)/file_size_bytes));
3004 int llapi_mirror_resync_many_params(int fd, struct llapi_layout *layout,
3005 struct llapi_resync_comp *comp_array,
3006 int comp_size, uint64_t start,
3008 unsigned long stats_interval_sec,
3009 unsigned long bandwidth_bytes_sec)
3011 size_t page_size = sysconf(_SC_PAGESIZE);
3012 size_t buflen = 64 << 20; /* 64M */
3014 uint64_t pos = start;
3015 uint64_t data_off = pos, data_end = pos;
3016 uint64_t mirror_end = LUSTRE_EOF;
3021 struct timespec start_time;
3022 struct timespec now;
3023 struct timespec last_bw_print;
3024 size_t total_bytes_read = 0;
3025 size_t total_bytes_written = 0;
3026 off_t write_estimation_bytes = 0;
3028 if (bandwidth_bytes_sec > 0 || stats_interval_sec) {
3031 rc = fstat(fd, &st);
3034 write_estimation_bytes = st.st_size * comp_size;
3037 /* limit transfer size to what can be sent in one second */
3038 if (bandwidth_bytes_sec && bandwidth_bytes_sec < buflen)
3039 buflen = (bandwidth_bytes_sec + ONE_MB - 1) & ~(ONE_MB - 1);
3040 rc = posix_memalign(&buf, page_size, buflen);
3044 clock_gettime(CLOCK_MONOTONIC, &start_time);
3045 now = last_bw_print = start_time;
3053 if (pos >= data_end) {
3056 if (pos >= mirror_end || !src) {
3057 rc = llapi_mirror_find(layout, pos, end,
3064 /* restrict mirror end by resync end */
3065 mirror_end = MIN(end, mirror_end);
3068 tmp_off = llapi_mirror_data_seek(fd, src, pos,
3071 /* switch to full copy */
3072 to_read = mirror_end - pos;
3076 data_end = data_off + data_size;
3078 data_off = MIN(data_off, mirror_end);
3079 data_end = MIN(data_end, mirror_end);
3081 /* align by page, if there is data block to copy */
3083 data_off &= ~(page_size - 1);
3086 if (pos < data_off) {
3087 for (i = 0; i < comp_size; i++) {
3090 uint32_t mid = comp_array[i].lrc_mirror_id;
3092 /* skip non-overlapped component */
3093 if (pos >= comp_array[i].lrc_end ||
3094 data_off <= comp_array[i].lrc_start)
3097 if (pos < comp_array[i].lrc_start)
3098 cur_pos = comp_array[i].lrc_start;
3102 if (data_off > comp_array[i].lrc_end)
3103 to_punch = comp_array[i].lrc_end -
3106 to_punch = data_off - cur_pos;
3108 if (comp_array[i].lrc_end == OBD_OBJECT_EOF)
3109 /* the last component can be truncated
3112 rc = llapi_mirror_truncate(fd, mid,
3115 rc = llapi_mirror_punch(fd, mid,
3118 * hole at the end of file, so just truncate up
3121 if (!rc && data_off == data_end && !data_size)
3122 rc = llapi_mirror_truncate(fd,
3124 /* if failed then read failed hole range */
3128 if (pos + to_punch == data_off)
3129 to_read = data_end - pos;
3137 if (pos == mirror_end)
3139 to_read = data_end - pos;
3144 assert(data_end <= mirror_end);
3146 to_read = MIN(buflen, to_read);
3147 to_read = ((to_read - 1) | (page_size - 1)) + 1;
3148 bytes_read = llapi_mirror_read(fd, src, buf, to_read, pos);
3149 if (bytes_read == 0) {
3153 if (bytes_read < 0) {
3157 total_bytes_read += bytes_read;
3159 /* round up to page align to make direct IO happy. */
3160 to_write = ((bytes_read - 1) | (page_size - 1)) + 1;
3162 for (i = 0; i < comp_size; i++) {
3163 unsigned long long write_target;
3164 struct timespec diff;
3167 size_t to_write2 = to_write;
3169 /* skip non-overlapped component */
3170 if (pos >= comp_array[i].lrc_end ||
3171 pos + to_write <= comp_array[i].lrc_start)
3174 if (pos < comp_array[i].lrc_start)
3175 pos2 = comp_array[i].lrc_start;
3177 to_write2 -= pos2 - pos;
3179 if ((pos + to_write) > comp_array[i].lrc_end)
3180 to_write2 -= pos + to_write -
3181 comp_array[i].lrc_end;
3183 written = llapi_mirror_write(fd,
3184 comp_array[i].lrc_mirror_id,
3189 * this component is not written successfully,
3190 * mark it using its lrc_synced, it is supposed
3191 * to be false before getting here.
3193 * And before this function returns, all
3194 * elements of comp_array will reverse their
3195 * lrc_synced flag to reflect their true
3198 comp_array[i].lrc_synced = true;
3199 llapi_error(LLAPI_MSG_ERROR, written,
3200 "component %u not synced",
3201 comp_array[i].lrc_id);
3206 assert(written == to_write2);
3207 total_bytes_written += written;
3209 if (bandwidth_bytes_sec == 0)
3212 clock_gettime(CLOCK_MONOTONIC, &now);
3213 diff = timespec_sub(&start_time, &now);
3214 write_target = ((bandwidth_bytes_sec * diff.tv_sec) +
3215 ((bandwidth_bytes_sec *
3216 diff.tv_nsec)/NSEC_PER_SEC));
3218 if (write_target < total_bytes_written) {
3219 unsigned long long excess;
3220 struct timespec delay = { 0, 0 };
3222 excess = total_bytes_written - write_target;
3227 delay.tv_sec = excess / bandwidth_bytes_sec;
3228 delay.tv_nsec = (excess % bandwidth_bytes_sec) *
3229 NSEC_PER_SEC / bandwidth_bytes_sec;
3232 rc = clock_nanosleep(CLOCK_MONOTONIC, 0,
3234 } while (rc < 0 && errno == EINTR);
3237 llapi_error(LLAPI_MSG_ERROR, rc,
3238 "errors: delay for bandwidth control failed: %s\n",
3244 if (stats_interval_sec) {
3245 clock_gettime(CLOCK_MONOTONIC, &now);
3246 if ((total_bytes_written != end - start) &&
3247 (now.tv_sec >= last_bw_print.tv_sec +
3248 stats_interval_sec)) {
3249 stats_log(&now, &start_time,
3251 total_bytes_written,
3252 write_estimation_bytes);
3253 last_bw_print = now;
3263 /* fatal error happens */
3264 for (i = 0; i < comp_size; i++)
3265 comp_array[i].lrc_synced = false;
3269 /* Output at least one log, regardless of stats_interval */
3270 if (stats_interval_sec) {
3271 clock_gettime(CLOCK_MONOTONIC, &now);
3272 stats_log(&now, &start_time, total_bytes_read,
3273 total_bytes_written,
3274 write_estimation_bytes);
3278 * no fatal error happens, each lrc_synced tells whether the component
3279 * has been resync successfully (note: we'd reverse the value to
3280 * reflect its true meaning.
3282 for (i = 0; i < comp_size; i++) {
3283 comp_array[i].lrc_synced = !comp_array[i].lrc_synced;
3284 if (comp_array[i].lrc_synced && pos & (page_size - 1)) {
3285 rc = llapi_mirror_truncate(fd,
3286 comp_array[i].lrc_mirror_id, pos);
3287 /* Ignore truncate error on encrypted file without the
3288 * key if tried on LUSTRE_ENCRYPTION_UNIT_SIZE boundary.
3290 if (rc < 0 && (rc != -ENOKEY ||
3291 pos & ~LUSTRE_ENCRYPTION_MASK))
3292 comp_array[i].lrc_synced = false;
3297 * returns the first error code for partially successful resync if
3303 int llapi_mirror_resync_many(int fd, struct llapi_layout *layout,
3304 struct llapi_resync_comp *comp_array,
3305 int comp_size, uint64_t start, uint64_t end)
3307 return llapi_mirror_resync_many_params(fd, layout, comp_array,
3308 comp_size, start, end, 0, 0);
3311 enum llapi_layout_comp_sanity_error {
3313 LSE_INCOMPLETE_MIRROR,
3314 LSE_ADJACENT_EXTENSION,
3318 LSE_DOM_EXTENSION_FOLLOWING,
3321 LSE_NOT_ZERO_LENGTH_EXTENDABLE,
3322 LSE_END_NOT_GREATER,
3323 LSE_ZERO_LENGTH_NORMAL,
3324 LSE_NOT_ADJACENT_PREV,
3331 const char *const llapi_layout_strerror[] =
3334 [LSE_INCOMPLETE_MIRROR] =
3335 "Incomplete mirror - must go to EOF",
3336 [LSE_ADJACENT_EXTENSION] =
3337 "No adjacent extension space components",
3338 [LSE_INIT_EXTENSION] =
3339 "Cannot apply extension flag to init components",
3342 [LSE_DOM_EXTENSION] =
3343 "DoM components can't be extension space",
3344 [LSE_DOM_EXTENSION_FOLLOWING] =
3345 "DoM components cannot be followed by extension space",
3347 "DoM component should be the first one in a file/mirror",
3348 [LSE_SET_COMP_START] =
3349 "Must set previous component extent before adding next",
3350 [LSE_NOT_ZERO_LENGTH_EXTENDABLE] =
3351 "Extendable component must start out zero-length",
3352 [LSE_END_NOT_GREATER] =
3353 "Component end is before end of previous component",
3354 [LSE_ZERO_LENGTH_NORMAL] =
3355 "Zero length components must be followed by extension",
3356 [LSE_NOT_ADJACENT_PREV] =
3357 "Components not adjacent (end != next->start",
3358 [LSE_START_GT_END] =
3359 "Component start is > end",
3361 "The component end must be aligned by the stripe size",
3363 "The extension size must be aligned by the stripe size",
3366 struct llapi_layout_sanity_args {
3367 bool lsa_incomplete;
3374 /* The component flags can be set by users at creation/modification time. */
3375 #define LCME_USER_COMP_FLAGS (LCME_FL_PREF_RW | LCME_FL_NOSYNC | \
3378 /* Inline function to verify the pool name */
3379 static inline int verify_pool_name(char *fsname, struct llapi_layout *layout)
3381 struct llapi_layout_comp *comp;
3383 if (!fsname || fsname[0] == '\0')
3386 comp = __llapi_layout_cur_comp(layout);
3389 if (comp->llc_pool_name[0] == '\0')
3391 /* check if the pool name exist */
3392 if (llapi_search_ost(fsname, comp->llc_pool_name, NULL) < 0)
3398 * When modified, adjust llapi_stripe_param_verify() if needed as well.
3400 static int llapi_layout_sanity_cb(struct llapi_layout *layout,
3403 struct llapi_layout_comp *comp, *next, *prev;
3404 struct llapi_layout_sanity_args *args = arg;
3405 bool first_comp = false;
3407 comp = __llapi_layout_cur_comp(layout);
3413 if (verify_pool_name(args->fsname, layout) != 0) {
3418 if (comp->llc_list.prev != &layout->llot_comp_list)
3419 prev = list_last_entry(&comp->llc_list, typeof(*prev),
3424 if (comp->llc_list.next != &layout->llot_comp_list)
3425 next = list_first_entry(&comp->llc_list, typeof(*next),
3430 /* Start of zero implies a new mirror */
3431 if (comp->llc_extent.e_start == 0) {
3433 /* Most checks apply only within one mirror, this is an
3435 if (prev && prev->llc_extent.e_end != LUSTRE_EOF) {
3436 args->lsa_rc = LSE_INCOMPLETE_MIRROR;
3443 if (next && next->llc_extent.e_start == 0)
3446 /* Flag sanity checks */
3447 /* No adjacent extension components */
3448 if ((comp->llc_flags & LCME_FL_EXTENSION) && next &&
3449 (next->llc_flags & LCME_FL_EXTENSION)) {
3450 args->lsa_rc = LSE_ADJACENT_EXTENSION;
3454 /* Extension flag cannot be applied to init components and the first
3455 * component of each mirror is automatically init */
3456 if ((comp->llc_flags & LCME_FL_EXTENSION) &&
3457 (comp->llc_flags & LCME_FL_INIT || first_comp)) {
3458 args->lsa_rc = LSE_INIT_EXTENSION;
3462 if (comp->llc_ondisk) {
3463 if (comp->llc_flags & LCME_FL_NEG)
3464 args->lsa_rc = LSE_FLAGS;
3465 } else if (!args->lsa_incomplete) {
3466 if (args->lsa_flr) {
3467 if (comp->llc_flags & ~LCME_USER_COMP_FLAGS)
3468 args->lsa_rc = LSE_FLAGS;
3470 if (comp->llc_flags &
3471 ~(LCME_FL_EXTENSION | LCME_FL_PREF_RW))
3472 args->lsa_rc = LSE_FLAGS;
3478 /* DoM sanity checks */
3479 if (!(comp->llc_pattern & LLAPI_LAYOUT_INVALID) &&
3480 (comp->llc_pattern & (LLAPI_LAYOUT_MDT | LOV_PATTERN_MDT))) {
3481 /* DoM components can't be extension components */
3482 if (comp->llc_flags & LCME_FL_EXTENSION) {
3483 args->lsa_rc = LSE_DOM_EXTENSION;
3486 /* DoM components cannot be followed by an extension comp */
3487 if (next && (next->llc_flags & LCME_FL_EXTENSION)) {
3488 args->lsa_rc = LSE_DOM_EXTENSION_FOLLOWING;
3492 /* DoM should be the first component in a mirror */
3494 args->lsa_rc = LSE_DOM_FIRST;
3500 /* Extent sanity checks */
3501 /* Must set previous component extent before adding another */
3502 if (prev && prev->llc_extent.e_start == 0 &&
3503 prev->llc_extent.e_end == 0) {
3504 args->lsa_rc = LSE_SET_COMP_START;
3508 if (!args->lsa_incomplete) {
3509 /* Components followed by extension space (extendable
3510 * components) must be zero length before initialization.
3511 * (Except for first comp, which will be initialized on
3513 if (next && (next->llc_flags & LCME_FL_EXTENSION) &&
3514 !first_comp && !(comp->llc_flags & LCME_FL_INIT) &&
3515 comp->llc_extent.e_start != comp->llc_extent.e_end) {
3516 args->lsa_rc = LSE_NOT_ZERO_LENGTH_EXTENDABLE;
3520 /* End must come after end of previous comp */
3521 if (prev && comp->llc_extent.e_end < prev->llc_extent.e_end) {
3522 args->lsa_rc = LSE_END_NOT_GREATER;
3526 /* Components not followed by ext space must have length > 0. */
3527 if (comp->llc_extent.e_start == comp->llc_extent.e_end &&
3528 (next == NULL || !(next->llc_flags & LCME_FL_EXTENSION))) {
3529 args->lsa_rc = LSE_ZERO_LENGTH_NORMAL;
3533 /* The component end must be aligned by the stripe size */
3534 if ((comp->llc_flags & LCME_FL_EXTENSION) &&
3535 (prev->llc_stripe_size != LLAPI_LAYOUT_DEFAULT)) {
3536 if (comp->llc_extent.e_end != LUSTRE_EOF &&
3537 comp->llc_extent.e_end % prev->llc_stripe_size) {
3538 args->lsa_rc = LSE_ALIGN_END;
3541 if ((comp->llc_stripe_size * SEL_UNIT_SIZE) %
3542 prev->llc_stripe_size) {
3543 args->lsa_rc = LSE_ALIGN_EXT;
3546 } else if (!(comp->llc_flags & LCME_FL_EXTENSION) &&
3547 (comp->llc_stripe_size != LLAPI_LAYOUT_DEFAULT)) {
3548 if (comp->llc_extent.e_end != LUSTRE_EOF &&
3549 comp->llc_extent.e_end !=
3550 comp->llc_extent.e_start &&
3551 comp->llc_extent.e_end % comp->llc_stripe_size) {
3552 args->lsa_rc = LSE_ALIGN_END;
3558 /* Components must have start == prev->end */
3559 if (prev && comp->llc_extent.e_start != 0 &&
3560 comp->llc_extent.e_start != prev->llc_extent.e_end) {
3561 args->lsa_rc = LSE_NOT_ADJACENT_PREV;
3565 /* Components must have start <= end */
3566 if (comp->llc_extent.e_start > comp->llc_extent.e_end) {
3567 args->lsa_rc = LSE_START_GT_END;
3571 return LLAPI_LAYOUT_ITER_CONT;
3574 errno = errno ? errno : EINVAL;
3575 return LLAPI_LAYOUT_ITER_STOP;
3578 /* Print explanation of layout error */
3579 void llapi_layout_sanity_perror(int error)
3581 if (error >= LSE_LAST || error < 0) {
3582 fprintf(stdout, "Invalid layout, unrecognized error: %d\n",
3585 fprintf(stdout, "Invalid layout: %s\n",
3586 llapi_layout_strerror[error]);
3590 /* Walk a layout and enforce sanity checks that apply to > 1 component
3592 * The core idea here is that of sanity checking individual tokens vs semantic
3594 * We cannot check everything at the individual component level ('token'),
3595 * instead we must check whether or not the full layout has a valid meaning.
3597 * An example of a component level check is "is stripe size valid?". That is
3598 * handled when setting stripe size.
3600 * An example of a layout level check is "are the extents of these components
3601 * valid when adjacent to one another", or "can we set these flags on adjacent
3604 * \param[in] layout component layout list.
3605 * \param[in] fname file the layout to be checked for
3606 * \param[in] incomplete if layout is complete or not - some checks can
3607 * only be done on complete layouts.
3608 * \param[in] flr set when this is called from FLR mirror create
3610 * \retval 0, success, positive: various errors, see
3611 * llapi_layout_sanity_perror, -1, failure
3614 int llapi_layout_sanity(struct llapi_layout *layout,
3615 bool incomplete, bool flr)
3617 return llapi_layout_v2_sanity(layout, incomplete, flr, NULL);
3620 /* This function has been introduced to do pool name checking
3621 * on top of llapi_layout_sanity, the file name passed in this
3622 * function is used later to verify if pool exist. The older version
3623 * of the sanity function is passing NULL for the filename
3624 * Input arguments ---
3625 * \param[in] layout component layout list.
3626 * \param[in] fname file the layout to be checked for
3627 * \param[in] incomplete if layout is complete or not - some checks can
3628 * only be done on complete layouts.
3629 * \param[in] flr set when this is called from FLR mirror create
3630 * \param[in] fsname filesystem name is used to check pool name, if
3631 * NULL no pool name check is performed
3633 * \retval 0, success, positive: various errors, see
3636 int llapi_layout_v2_sanity(struct llapi_layout *layout,
3637 bool incomplete, bool flr, char *fsname)
3639 struct llapi_layout_sanity_args args = { 0 };
3640 struct llapi_layout_comp *curr;
3646 curr = layout->llot_cur_comp;
3653 args.lsa_incomplete = incomplete;
3654 args.fsname = fsname;
3656 /* When we modify an existing layout, this tells us if it's FLR */
3657 if (mirror_id_of(curr->llc_id) > 0)
3658 args.lsa_flr = true;
3661 rc = llapi_layout_comp_iterate(layout,
3662 llapi_layout_sanity_cb,
3664 if (errno == ENOENT)
3667 if (rc != LLAPI_LAYOUT_ITER_CONT)
3670 layout->llot_cur_comp = curr;
3675 int llapi_layout_dom_size(struct llapi_layout *layout, uint64_t *size)
3677 uint64_t pattern, start;
3680 if (!layout || !llapi_layout_is_composite(layout)) {
3685 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_FIRST);
3689 rc = llapi_layout_pattern_get(layout, &pattern);
3693 if ((pattern & LLAPI_LAYOUT_INVALID) ||
3694 !(pattern & (LOV_PATTERN_MDT | LLAPI_LAYOUT_MDT))) {
3699 rc = llapi_layout_comp_extent_get(layout, &start, size);
3707 int lov_comp_md_size(struct lov_comp_md_v1 *lcm)
3709 if (lcm->lcm_magic == LOV_MAGIC_V1 || lcm->lcm_magic == LOV_MAGIC_V3) {
3710 struct lov_user_md *lum = (void *)lcm;
3712 return lov_user_md_size(lum->lmm_stripe_count, lum->lmm_magic);
3715 if (lcm->lcm_magic == LOV_MAGIC_FOREIGN) {
3716 struct lov_foreign_md *lfm = (void *)lcm;
3718 return lfm->lfm_length;
3721 if (lcm->lcm_magic != LOV_MAGIC_COMP_V1)
3724 return lcm->lcm_size;
3727 int llapi_get_lum_file_fd(int dir_fd, const char *fname, __u64 *valid,
3728 lstatx_t *statx, struct lov_user_md *lum,
3731 struct lov_user_mds_data *lmd;
3732 char buf[65536 + offsetof(typeof(*lmd), lmd_lmm)];
3736 if (lum && lumsize < sizeof(*lum))
3739 /* If a file name is provided, it is relative to the parent directory */
3745 lmd = (struct lov_user_mds_data *)buf;
3746 rc = get_lmd_info_fd(fname, parent_fd, dir_fd, buf, sizeof(buf),
3752 *valid = lmd->lmd_flags;
3755 memcpy(statx, &lmd->lmd_stx, sizeof(*statx));
3758 if (lmd->lmd_lmmsize > lumsize)
3760 memcpy(lum, &lmd->lmd_lmm, lmd->lmd_lmmsize);
3766 int llapi_get_lum_dir_fd(int dir_fd, __u64 *valid, lstatx_t *statx,
3767 struct lov_user_md *lum, size_t lumsize)
3769 return llapi_get_lum_file_fd(dir_fd, NULL, valid, statx, lum, lumsize);
3772 int llapi_get_lum_file(const char *path, __u64 *valid, lstatx_t *statx,
3773 struct lov_user_md *lum, size_t lumsize)
3775 char parent[PATH_MAX];
3782 tmp = strrchr(path, '/');
3784 strncpy(parent, ".", sizeof(parent) - 1);
3787 strncpy(parent, path, tmp - path);
3788 offset = tmp - path - 1;
3789 parent[tmp - path] = 0;
3794 fname += offset + 2;
3796 dir_fd = open(parent, O_RDONLY);
3799 llapi_error(LLAPI_MSG_ERROR, rc, "cannot open '%s'", path);
3803 rc = llapi_get_lum_file_fd(dir_fd, fname, valid, statx, lum, lumsize);
3808 int llapi_get_lum_dir(const char *path, __u64 *valid, lstatx_t *statx,
3809 struct lov_user_md *lum, size_t lumsize)
3814 dir_fd = open(path, O_RDONLY);
3817 llapi_error(LLAPI_MSG_ERROR, rc, "cannot open '%s'", path);
3821 rc = llapi_get_lum_dir_fd(dir_fd, valid, statx, lum, lumsize);