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
49 * V1/V3/FOREIGN(HSM) layout.
51 struct llapi_layout_comp {
54 struct { /* For plain layout. */
55 uint64_t llc_stripe_size;
56 uint64_t llc_stripe_count;
57 uint64_t llc_stripe_offset;
59 * Add 1 so user always gets back a null terminated
62 char llc_pool_name[LOV_MAXPOOLNAME + 1];
64 * Number of objects in llc_objects array if was
67 uint32_t llc_objects_count;
68 struct lov_user_ost_data_v1 *llc_objects;
70 struct { /* For FOREIGN/HSM layout. */
73 uint32_t llc_hsm_flags;
75 struct lov_hsm_base llc_hsm;
81 /* fields used only for composite layouts */
82 struct lu_extent llc_extent; /* [start, end) of component */
83 uint32_t llc_id; /* unique ID of component */
84 uint32_t llc_flags; /* LCME_FL_* flags */
85 uint64_t llc_timestamp; /* snapshot timestamp */
86 struct list_head llc_list; /* linked to the llapi_layout
91 #define llc_archive_id llc_hsm.lhb_archive_id
92 #define llc_archive_ver llc_hsm.lhb_archive_ver
93 #define llc_uuid llc_hsm.lhb_uuid
96 * An Opaque data type abstracting the layout of a Lustre file.
99 uint32_t llot_magic; /* LLAPI_LAYOUT_MAGIC */
102 bool llot_is_composite;
103 uint16_t llot_mirror_count;
104 /* Cursor pointing to one of the components in llot_comp_list */
105 struct llapi_layout_comp *llot_cur_comp;
106 struct list_head llot_comp_list;
110 * Compute the number of elements in the lmm_objects array of \a lum
111 * with size \a lum_size.
113 * \param[in] lum the struct lov_user_md to check
114 * \param[in] lum_size the number of bytes in \a lum
116 * \retval number of elements in array lum->lmm_objects
118 static int llapi_layout_objects_in_lum(struct lov_user_md *lum, size_t lum_size)
123 if (lum->lmm_magic == __swab32(LOV_MAGIC_FOREIGN))
126 if (lum_size < lov_user_md_size(0, LOV_MAGIC_V1))
129 if (lum->lmm_magic == __swab32(LOV_MAGIC_V1) ||
130 lum->lmm_magic == __swab32(LOV_MAGIC_V3))
131 magic = __swab32(lum->lmm_magic);
133 magic = lum->lmm_magic;
135 base_size = lov_user_md_size(0, magic);
137 if (lum_size <= base_size)
140 return (lum_size - base_size) / sizeof(lum->lmm_objects[0]);
144 * Byte-swap the fields of struct lov_user_md.
146 * XXX Rather than duplicating swabbing code here, we should eventually
147 * refactor the needed functions in lustre/ptlrpc/pack_generic.c
148 * into a library that can be shared between kernel and user code.
151 llapi_layout_swab_lov_user_md(struct lov_user_md *lum, int lum_size)
153 int i, j, ent_count, obj_count;
154 struct lov_comp_md_v1 *comp_v1 = NULL;
155 struct lov_comp_md_entry_v1 *ent;
156 struct lov_user_ost_data *lod;
158 if (lum->lmm_magic != __swab32(LOV_MAGIC_V1) &&
159 lum->lmm_magic != __swab32(LOV_MAGIC_V3) &&
160 lum->lmm_magic != __swab32(LOV_MAGIC_COMP_V1))
163 if (lum->lmm_magic == __swab32(LOV_MAGIC_COMP_V1))
164 comp_v1 = (struct lov_comp_md_v1 *)lum;
166 if (comp_v1 != NULL) {
167 comp_v1->lcm_magic = __swab32(comp_v1->lcm_magic);
168 comp_v1->lcm_size = __swab32(comp_v1->lcm_size);
169 comp_v1->lcm_layout_gen = __swab32(comp_v1->lcm_layout_gen);
170 comp_v1->lcm_flags = __swab16(comp_v1->lcm_flags);
171 comp_v1->lcm_entry_count = __swab16(comp_v1->lcm_entry_count);
172 ent_count = comp_v1->lcm_entry_count;
177 for (i = 0; i < ent_count; i++) {
178 if (comp_v1 != NULL) {
179 ent = &comp_v1->lcm_entries[i];
180 ent->lcme_id = __swab32(ent->lcme_id);
181 ent->lcme_flags = __swab32(ent->lcme_flags);
182 ent->lcme_timestamp = __swab64(ent->lcme_timestamp);
183 ent->lcme_extent.e_start = __swab64(ent->lcme_extent.e_start);
184 ent->lcme_extent.e_end = __swab64(ent->lcme_extent.e_end);
185 ent->lcme_offset = __swab32(ent->lcme_offset);
186 ent->lcme_size = __swab32(ent->lcme_size);
188 lum = (struct lov_user_md *)((char *)comp_v1 +
190 lum_size = ent->lcme_size;
193 lum->lmm_magic = __swab32(lum->lmm_magic);
194 if (lum->lmm_magic == LOV_MAGIC_FOREIGN) {
195 struct lov_hsm_md *lhm;
197 lhm = (struct lov_hsm_md *)lum;
198 lhm->lhm_length = __swab32(lhm->lhm_length);
199 lhm->lhm_type = __swab32(lhm->lhm_type);
200 lhm->lhm_flags = __swab32(lhm->lhm_flags);
201 if (!lov_hsm_type_supported(lhm->lhm_type))
204 lhm->lhm_archive_id = __swab64(lhm->lhm_archive_id);
205 lhm->lhm_archive_ver = __swab64(lhm->lhm_archive_ver);
207 obj_count = llapi_layout_objects_in_lum(lum, lum_size);
209 lum->lmm_pattern = __swab32(lum->lmm_pattern);
210 lum->lmm_stripe_size = __swab32(lum->lmm_stripe_size);
211 lum->lmm_stripe_count = __swab16(lum->lmm_stripe_count);
212 lum->lmm_stripe_offset =
213 __swab16(lum->lmm_stripe_offset);
215 if (lum->lmm_magic != LOV_MAGIC_V1) {
216 struct lov_user_md_v3 *v3;
218 v3 = (struct lov_user_md_v3 *)lum;
219 lod = v3->lmm_objects;
221 lod = lum->lmm_objects;
224 for (j = 0; j < obj_count; j++)
225 lod[j].l_ost_idx = __swab32(lod[j].l_ost_idx);
231 * (Re-)allocate llc_objects[] to \a num_stripes stripes.
233 * Copy over existing llc_objects[], if any, to the new llc_objects[].
235 * \param[in] layout existing layout to be modified
236 * \param[in] num_stripes number of stripes in new layout
238 * \retval 0 if the objects are re-allocated successfully
239 * \retval -1 on error with errno set
241 static int __llapi_comp_objects_realloc(struct llapi_layout_comp *comp,
242 unsigned int new_stripes)
244 struct lov_user_ost_data_v1 *new_objects;
247 if (new_stripes > LOV_MAX_STRIPE_COUNT) {
252 if (new_stripes == comp->llc_objects_count)
255 if (new_stripes != 0 && new_stripes <= comp->llc_objects_count)
258 new_objects = realloc(comp->llc_objects,
259 sizeof(*new_objects) * new_stripes);
260 if (new_objects == NULL && new_stripes != 0) {
265 for (i = comp->llc_objects_count; i < new_stripes; i++)
266 new_objects[i].l_ost_idx = LLAPI_LAYOUT_IDX_MAX;
268 comp->llc_objects = new_objects;
269 comp->llc_objects_count = new_stripes;
275 * Allocate storage for a llapi_layout_comp with \a num_stripes stripes.
277 * \param[in] num_stripes number of stripes in new layout
279 * \retval valid pointer if allocation succeeds
280 * \retval NULL if allocation fails
282 static struct llapi_layout_comp *__llapi_comp_alloc(unsigned int num_stripes)
284 struct llapi_layout_comp *comp;
286 if (num_stripes > LOV_MAX_STRIPE_COUNT) {
291 comp = calloc(1, sizeof(*comp));
297 comp->llc_objects = NULL;
298 comp->llc_objects_count = 0;
300 if (__llapi_comp_objects_realloc(comp, num_stripes) < 0) {
306 comp->llc_pattern = LLAPI_LAYOUT_DEFAULT;
307 comp->llc_stripe_size = LLAPI_LAYOUT_DEFAULT;
308 comp->llc_stripe_count = LLAPI_LAYOUT_DEFAULT;
309 comp->llc_stripe_offset = LLAPI_LAYOUT_DEFAULT;
310 comp->llc_pool_name[0] = '\0';
311 comp->llc_extent.e_start = 0;
312 comp->llc_extent.e_end = LUSTRE_EOF;
315 INIT_LIST_HEAD(&comp->llc_list);
321 * Allocate storage for a HSM component with \a length buffer.
323 * \retval valid pointer if allocation succeeds
324 * \retval NULL if allocate fails
326 static struct llapi_layout_comp *__llapi_comp_hsm_alloc(uint32_t length)
328 struct llapi_layout_comp *comp;
330 if (lov_foreign_md_size(length) > XATTR_SIZE_MAX) {
335 comp = calloc(1, sizeof(*comp));
341 comp->llc_pattern = LLAPI_LAYOUT_FOREIGN;
342 comp->llc_length = length;
343 comp->llc_type = LU_FOREIGN_TYPE_UNKNOWN;
344 comp->llc_hsm_flags = 0;
345 comp->llc_archive_id = 0;
346 comp->llc_archive_ver = 0;
347 comp->llc_extent.e_start = 0;
348 comp->llc_extent.e_end = LUSTRE_EOF;
351 INIT_LIST_HEAD(&comp->llc_list);
357 * Free memory allocated for \a comp
359 * \param[in] comp previously allocated by __llapi_comp_alloc()
361 static void __llapi_comp_free(struct llapi_layout_comp *comp)
363 if (comp->llc_pattern != LLAPI_LAYOUT_FOREIGN &&
364 comp->llc_objects != NULL) {
365 free(comp->llc_objects);
371 * Free memory allocated for \a layout.
373 * \param[in] layout previously allocated by llapi_layout_alloc()
375 void llapi_layout_free(struct llapi_layout *layout)
377 struct llapi_layout_comp *comp, *n;
382 list_for_each_entry_safe(comp, n, &layout->llot_comp_list, llc_list) {
383 list_del_init(&comp->llc_list);
384 __llapi_comp_free(comp);
390 * Allocate and initialize a llapi_layout structure.
392 * \retval valid llapi_layout pointer on success
393 * \retval NULL if memory allocation fails
395 static struct llapi_layout *__llapi_layout_alloc(void)
397 struct llapi_layout *layout;
399 layout = calloc(1, sizeof(*layout));
400 if (layout == NULL) {
406 layout->llot_magic = LLAPI_LAYOUT_MAGIC;
407 layout->llot_gen = 0;
408 layout->llot_flags = 0;
409 layout->llot_is_composite = false;
410 layout->llot_mirror_count = 1;
411 layout->llot_cur_comp = NULL;
412 INIT_LIST_HEAD(&layout->llot_comp_list);
418 * Allocate and initialize a new plain layout.
420 * \retval valid llapi_layout pointer on success
421 * \retval NULL if memory allocation fails
423 struct llapi_layout *llapi_layout_alloc(void)
425 struct llapi_layout_comp *comp;
426 struct llapi_layout *layout;
428 layout = __llapi_layout_alloc();
432 comp = __llapi_comp_alloc(0);
438 list_add_tail(&comp->llc_list, &layout->llot_comp_list);
439 layout->llot_cur_comp = comp;
445 * Check if the given \a lum_size is large enough to hold the required
448 * \param[in] lum the struct lov_user_md to check
449 * \param[in] lum_size the number of bytes in \a lum
451 * \retval true the \a lum_size is too small
452 * \retval false the \a lum_size is large enough
454 static bool llapi_layout_lum_truncated(struct lov_user_md *lum, size_t lum_size)
458 if (lum_size < sizeof(lum->lmm_magic))
461 if (lum->lmm_magic == LOV_MAGIC_V1 ||
462 lum->lmm_magic == __swab32(LOV_MAGIC_V1))
463 magic = LOV_MAGIC_V1;
464 else if (lum->lmm_magic == LOV_MAGIC_V3 ||
465 lum->lmm_magic == __swab32(LOV_MAGIC_V3))
466 magic = LOV_MAGIC_V3;
467 else if (lum->lmm_magic == LOV_MAGIC_COMP_V1 ||
468 lum->lmm_magic == __swab32(LOV_MAGIC_COMP_V1))
469 magic = LOV_MAGIC_COMP_V1;
473 if (magic == LOV_MAGIC_V1 || magic == LOV_MAGIC_V3)
474 return lum_size < lov_user_md_size(0, magic);
476 return lum_size < sizeof(struct lov_comp_md_v1);
479 /* Verify if the objects count in lum is consistent with the
480 * stripe count in lum. It applies to regular file only. */
481 static bool llapi_layout_lum_valid(struct lov_user_md *lum, int lum_size)
483 struct lov_comp_md_v1 *comp_v1 = NULL;
484 int i, ent_count, obj_count;
486 if (lum->lmm_magic == LOV_MAGIC_COMP_V1) {
487 comp_v1 = (struct lov_comp_md_v1 *)lum;
488 ent_count = comp_v1->lcm_entry_count;
489 } else if (lum->lmm_magic == LOV_MAGIC_V1 ||
490 lum->lmm_magic == LOV_MAGIC_V3) {
496 for (i = 0; i < ent_count; i++) {
498 lum = (struct lov_user_md *)((char *)comp_v1 +
499 comp_v1->lcm_entries[i].lcme_offset);
500 lum_size = comp_v1->lcm_entries[i].lcme_size;
502 if (lum->lmm_magic == LOV_MAGIC_FOREIGN)
505 obj_count = llapi_layout_objects_in_lum(lum, lum_size);
508 if (!(comp_v1->lcm_entries[i].lcme_flags &
509 LCME_FL_INIT) && obj_count != 0)
511 } else if (obj_count != lum->lmm_stripe_count) {
519 * Convert the data from a lov_user_md to a newly allocated llapi_layout.
520 * The caller is responsible for freeing the returned pointer.
522 * \param[in] lov_xattr LOV user metadata xattr to copy data from
523 * \param[in] lov_xattr_size size the lov_xattr_size passed in
524 * \param[in] flags flags to control how layout is retrieved
526 * \retval valid llapi_layout pointer on success
527 * \retval NULL if memory allocation fails
529 struct llapi_layout *llapi_layout_get_by_xattr(void *lov_xattr,
530 ssize_t lov_xattr_size,
531 enum llapi_layout_get_flags flags)
533 struct lov_user_md *lum = lov_xattr;
534 struct lov_comp_md_v1 *comp_v1 = NULL;
535 struct lov_comp_md_entry_v1 *ent;
536 struct lov_user_md *v1;
537 struct llapi_layout *layout = NULL;
538 struct llapi_layout_comp *comp;
539 int i, ent_count = 0, obj_count = 0;
541 if (lov_xattr == NULL || lov_xattr_size <= 0) {
546 /* Return an error if we got back a partial layout. */
547 if (llapi_layout_lum_truncated(lov_xattr, lov_xattr_size)) {
552 #if __BYTE_ORDER == __BIG_ENDIAN
553 if (flags & LLAPI_LAYOUT_GET_COPY) {
554 lum = malloc(lov_xattr_size);
559 memcpy(lum, lov_xattr, lov_xattr_size);
563 llapi_layout_swab_lov_user_md(lum, lov_xattr_size);
565 #if LUSTRE_VERSION_CODE > OBD_OCD_VERSION(2, 16, 53, 0)
566 #define LLAPI_LXF_CHECK_OLD 0x0001
567 if (flags & LLAPI_LXF_CHECK_OLD)
568 flags = (flags & ~LLAPI_LXF_CHECK_OLD) | LLAPI_LAYOUT_GET_CHECK;
570 if ((flags & LLAPI_LAYOUT_GET_CHECK) &&
571 !llapi_layout_lum_valid(lum, lov_xattr_size)) {
576 layout = __llapi_layout_alloc();
577 if (layout == NULL) {
582 if (lum->lmm_magic == LOV_MAGIC_COMP_V1) {
583 comp_v1 = (struct lov_comp_md_v1 *)lum;
584 ent_count = comp_v1->lcm_entry_count;
585 layout->llot_gen = comp_v1->lcm_layout_gen;
586 layout->llot_is_composite = true;
587 layout->llot_mirror_count = comp_v1->lcm_mirror_count + 1;
588 layout->llot_gen = comp_v1->lcm_layout_gen;
589 layout->llot_flags = comp_v1->lcm_flags;
590 } else if (lum->lmm_magic == LOV_MAGIC_V1 ||
591 lum->lmm_magic == LOV_MAGIC_V3) {
593 layout->llot_is_composite = false;
595 if (lov_xattr_size <= 0) {
604 if (ent_count == 0) {
609 v1 = (struct lov_user_md *)lum;
610 for (i = 0; i < ent_count; i++) {
611 if (comp_v1 != NULL) {
612 ent = &comp_v1->lcm_entries[i];
613 v1 = (struct lov_user_md *)((char *)comp_v1 +
615 lov_xattr_size = ent->lcme_size;
620 if (v1->lmm_magic == LOV_MAGIC_FOREIGN) {
621 struct lov_hsm_md *lhm;
623 lhm = (struct lov_hsm_md *)v1;
624 if (!lov_hsm_type_supported(lhm->lhm_type))
627 if (lhm->lhm_length != sizeof(struct lov_hsm_base))
630 comp = __llapi_comp_hsm_alloc(lhm->lhm_length);
634 comp->llc_length = lhm->lhm_length;
635 comp->llc_type = lhm->lhm_type;
636 comp->llc_hsm_flags = lhm->lhm_flags;
637 comp->llc_archive_id = lhm->lhm_archive_id;
638 comp->llc_archive_ver = lhm->lhm_archive_ver;
639 memcpy(comp->llc_uuid, lhm->lhm_archive_uuid,
640 sizeof(comp->llc_uuid));
642 obj_count = llapi_layout_objects_in_lum(v1,
644 comp = __llapi_comp_alloc(obj_count);
650 comp->llc_extent.e_start = ent->lcme_extent.e_start;
651 comp->llc_extent.e_end = ent->lcme_extent.e_end;
652 comp->llc_id = ent->lcme_id;
653 comp->llc_flags = ent->lcme_flags;
654 if (comp->llc_flags & LCME_FL_NOSYNC)
655 comp->llc_timestamp = ent->lcme_timestamp;
657 comp->llc_extent.e_start = 0;
658 comp->llc_extent.e_end = LUSTRE_EOF;
663 if (v1->lmm_magic == LOV_MAGIC_FOREIGN) {
664 comp->llc_pattern = LLAPI_LAYOUT_FOREIGN;
668 if (v1->lmm_pattern == LOV_PATTERN_RAID0)
669 comp->llc_pattern = LLAPI_LAYOUT_RAID0;
670 else if (v1->lmm_pattern == (LOV_PATTERN_RAID0 |
671 LOV_PATTERN_OVERSTRIPING))
672 comp->llc_pattern = LLAPI_LAYOUT_OVERSTRIPING;
673 else if (v1->lmm_pattern & LOV_PATTERN_MDT)
674 comp->llc_pattern = LLAPI_LAYOUT_MDT;
676 /* Lustre only supports RAID0, overstripping,
677 * DoM and FOREIGN/HSM for now.
679 comp->llc_pattern = v1->lmm_pattern;
681 if (v1->lmm_stripe_size == 0)
682 comp->llc_stripe_size = LLAPI_LAYOUT_DEFAULT;
684 comp->llc_stripe_size = v1->lmm_stripe_size;
686 if (v1->lmm_stripe_count == (typeof(v1->lmm_stripe_count))-1)
687 comp->llc_stripe_count = LLAPI_LAYOUT_WIDE;
688 else if (v1->lmm_stripe_count == 0)
689 comp->llc_stripe_count = LLAPI_LAYOUT_DEFAULT;
691 comp->llc_stripe_count = v1->lmm_stripe_count;
693 if (v1->lmm_stripe_offset ==
694 (typeof(v1->lmm_stripe_offset))-1)
695 comp->llc_stripe_offset = LLAPI_LAYOUT_DEFAULT;
697 comp->llc_stripe_offset = v1->lmm_stripe_offset;
699 if (v1->lmm_magic != LOV_USER_MAGIC_V1) {
700 const struct lov_user_md_v3 *lumv3;
701 size_t size = sizeof(comp->llc_pool_name);
704 lumv3 = (struct lov_user_md_v3 *)v1;
705 rc = snprintf(comp->llc_pool_name, size,
706 "%s", lumv3->lmm_pool_name);
707 /* Avoid GCC 7 format-truncation warning. */
709 comp->llc_pool_name[size - 1] = 0;
711 memcpy(comp->llc_objects, lumv3->lmm_objects,
712 obj_count * sizeof(lumv3->lmm_objects[0]));
714 const struct lov_user_md_v1 *lumv1;
715 lumv1 = (struct lov_user_md_v1 *)v1;
716 memcpy(comp->llc_objects, lumv1->lmm_objects,
717 obj_count * sizeof(lumv1->lmm_objects[0]));
721 comp->llc_stripe_offset =
722 comp->llc_objects[0].l_ost_idx;
724 comp->llc_ondisk = true;
725 list_add_tail(&comp->llc_list, &layout->llot_comp_list);
726 layout->llot_cur_comp = comp;
730 if (lum != lov_xattr)
734 llapi_layout_free(layout);
739 __u32 llapi_pattern_to_lov(uint64_t pattern)
744 case LLAPI_LAYOUT_DEFAULT:
745 lov_pattern = LOV_PATTERN_RAID0;
747 case LLAPI_LAYOUT_RAID0:
748 lov_pattern = LOV_PATTERN_RAID0;
750 case LLAPI_LAYOUT_MDT:
751 lov_pattern = LOV_PATTERN_MDT;
753 case LLAPI_LAYOUT_FOREIGN:
754 lov_pattern = LOV_PATTERN_FOREIGN;
756 case LLAPI_LAYOUT_OVERSTRIPING:
757 lov_pattern = LOV_PATTERN_OVERSTRIPING | LOV_PATTERN_RAID0;
760 lov_pattern = EINVAL;
767 * Convert the data from a llapi_layout to a newly allocated lov_user_md.
768 * The caller is responsible for freeing the returned pointer.
770 * \param[in] layout the layout to copy from
772 * \retval valid lov_user_md pointer on success
773 * \retval NULL if memory allocation fails or the layout is invalid
775 static struct lov_user_md *
776 llapi_layout_to_lum(const struct llapi_layout *layout)
778 struct llapi_layout_comp *comp;
779 struct lov_comp_md_v1 *comp_v1 = NULL;
780 struct lov_comp_md_entry_v1 *ent;
781 struct lov_user_md *lum = NULL;
786 if (layout == NULL ||
787 list_empty((struct list_head *)&layout->llot_comp_list)) {
792 /* Allocate header of lov_comp_md_v1 if necessary */
793 if (layout->llot_is_composite) {
796 list_for_each_entry(comp, &layout->llot_comp_list, llc_list)
799 lum_size = sizeof(*comp_v1) + comp_cnt * sizeof(*ent);
800 lum = calloc(lum_size, 1);
805 comp_v1 = (struct lov_comp_md_v1 *)lum;
806 comp_v1->lcm_magic = LOV_USER_MAGIC_COMP_V1;
807 comp_v1->lcm_size = lum_size;
808 comp_v1->lcm_layout_gen = 0;
809 comp_v1->lcm_flags = layout->llot_flags;
810 comp_v1->lcm_entry_count = comp_cnt;
811 comp_v1->lcm_mirror_count = layout->llot_mirror_count - 1;
815 list_for_each_entry(comp, &layout->llot_comp_list, llc_list) {
816 struct lov_user_md *blob;
819 int i, obj_count = 0;
820 struct lov_user_ost_data *lmm_objects;
821 uint64_t pattern = comp->llc_pattern;
823 if ((pattern & LLAPI_LAYOUT_SPECIFIC) != 0) {
824 if (comp->llc_objects_count <
825 comp->llc_stripe_count) {
829 magic = LOV_USER_MAGIC_SPECIFIC;
830 obj_count = comp->llc_stripe_count;
831 pattern &= ~LLAPI_LAYOUT_SPECIFIC;
832 } else if (strlen(comp->llc_pool_name) != 0) {
833 magic = LOV_USER_MAGIC_V3;
835 magic = LOV_USER_MAGIC_V1;
837 /* All stripes must be specified when the pattern contains
838 * LLAPI_LAYOUT_SPECIFIC */
839 for (i = 0; i < obj_count; i++) {
840 if (comp->llc_objects[i].l_ost_idx ==
841 LLAPI_LAYOUT_IDX_MAX) {
847 blob_size = lov_user_md_size(obj_count, magic);
848 blob = realloc(lum, lum_size + blob_size);
854 comp_v1 = (struct lov_comp_md_v1 *)lum;
855 blob = (struct lov_user_md *)((char *)lum + lum_size);
856 lum_size += blob_size;
859 blob->lmm_magic = magic;
860 blob->lmm_pattern = llapi_pattern_to_lov(pattern);
861 if (blob->lmm_pattern == EINVAL) {
866 if (comp->llc_stripe_size == LLAPI_LAYOUT_DEFAULT)
867 blob->lmm_stripe_size = 0;
869 blob->lmm_stripe_size = comp->llc_stripe_size;
871 if (comp->llc_stripe_count == LLAPI_LAYOUT_DEFAULT)
872 blob->lmm_stripe_count = 0;
873 else if (comp->llc_stripe_count == LLAPI_LAYOUT_WIDE)
874 blob->lmm_stripe_count = LOV_ALL_STRIPES;
876 blob->lmm_stripe_count = comp->llc_stripe_count;
878 if (comp->llc_stripe_offset == LLAPI_LAYOUT_DEFAULT)
879 blob->lmm_stripe_offset = -1;
881 blob->lmm_stripe_offset = comp->llc_stripe_offset;
883 if (magic == LOV_USER_MAGIC_V3 ||
884 magic == LOV_USER_MAGIC_SPECIFIC) {
885 struct lov_user_md_v3 *lumv3 =
886 (struct lov_user_md_v3 *)blob;
888 if (comp->llc_pool_name[0] != '\0') {
889 strncpy(lumv3->lmm_pool_name,
891 sizeof(lumv3->lmm_pool_name));
893 memset(lumv3->lmm_pool_name, 0,
894 sizeof(lumv3->lmm_pool_name));
896 lmm_objects = lumv3->lmm_objects;
898 lmm_objects = blob->lmm_objects;
901 for (i = 0; i < obj_count; i++)
902 lmm_objects[i].l_ost_idx =
903 comp->llc_objects[i].l_ost_idx;
905 if (layout->llot_is_composite) {
906 ent = &comp_v1->lcm_entries[ent_idx];
907 ent->lcme_id = comp->llc_id;
908 ent->lcme_flags = comp->llc_flags;
909 if (ent->lcme_flags & LCME_FL_NOSYNC)
910 ent->lcme_timestamp = comp->llc_timestamp;
911 ent->lcme_extent.e_start = comp->llc_extent.e_start;
912 ent->lcme_extent.e_end = comp->llc_extent.e_end;
913 ent->lcme_size = blob_size;
914 ent->lcme_offset = offset;
916 comp_v1->lcm_size += blob_size;
930 * Get the parent directory of a path.
932 * \param[in] path path to get parent of
933 * \param[out] buf buffer in which to store parent path
934 * \param[in] size size in bytes of buffer \a buf
936 static void get_parent_dir(const char *path, char *buf, size_t size)
940 strncpy(buf, path, size - 1);
941 p = strrchr(buf, '/');
945 } else if (size >= 2) {
946 strncpy(buf, ".", 2);
947 buf[size - 1] = '\0';
952 * Substitute unspecified attribute values in \a layout with values
953 * from fs global settings. (lov.stripesize, lov.stripecount,
956 * \param[in] layout layout to inherit values from
957 * \param[in] path file path of the filesystem
959 static void inherit_sys_attributes(struct llapi_layout *layout,
962 struct llapi_layout_comp *comp;
963 unsigned int ssize, scount, soffset;
966 rc = sattr_cache_get_defaults(NULL, path, &scount, &ssize, &soffset);
970 list_for_each_entry(comp, &layout->llot_comp_list, llc_list) {
971 if (comp->llc_pattern == LLAPI_LAYOUT_DEFAULT)
972 comp->llc_pattern = LLAPI_LAYOUT_RAID0;
973 if (comp->llc_stripe_size == LLAPI_LAYOUT_DEFAULT)
974 comp->llc_stripe_size = ssize;
975 if (comp->llc_stripe_count == LLAPI_LAYOUT_DEFAULT)
976 comp->llc_stripe_count = scount;
977 if (comp->llc_stripe_offset == LLAPI_LAYOUT_DEFAULT)
978 comp->llc_stripe_offset = soffset;
983 * Get the current component of \a layout.
985 * \param[in] layout layout to get current component
987 * \retval valid llapi_layout_comp pointer on success
988 * \retval NULL on error
990 static struct llapi_layout_comp *
991 __llapi_layout_cur_comp(const struct llapi_layout *layout)
993 struct llapi_layout_comp *comp;
995 if (layout == NULL || layout->llot_magic != LLAPI_LAYOUT_MAGIC) {
999 if (layout->llot_cur_comp == NULL) {
1003 /* Verify data consistency */
1004 list_for_each_entry(comp, &layout->llot_comp_list, llc_list)
1005 if (comp == layout->llot_cur_comp)
1012 * Test if any attributes of \a layout are specified.
1014 * \param[in] layout the layout to check
1016 * \retval true any attributes are specified
1017 * \retval false all attributes are unspecified
1019 static bool is_any_specified(const struct llapi_layout *layout)
1021 struct llapi_layout_comp *comp;
1023 comp = __llapi_layout_cur_comp(layout);
1027 if (layout->llot_is_composite || layout->llot_mirror_count != 1)
1030 return comp->llc_pattern != LLAPI_LAYOUT_DEFAULT ||
1031 comp->llc_stripe_size != LLAPI_LAYOUT_DEFAULT ||
1032 comp->llc_stripe_count != LLAPI_LAYOUT_DEFAULT ||
1033 comp->llc_stripe_offset != LLAPI_LAYOUT_DEFAULT ||
1034 strlen(comp->llc_pool_name);
1038 * Get the striping layout for the file referenced by file descriptor \a fd.
1040 * If the filesystem does not support the "lustre." xattr namespace, the
1041 * file must be on a non-Lustre filesystem, so set errno to ENOTTY per
1042 * convention. If the file has no "lustre.lov" data, the file will
1043 * inherit default values, so return a default layout.
1045 * If the kernel gives us back less than the expected amount of data,
1046 * we fail with errno set to EINTR.
1048 * \param[in] fd open file descriptor
1049 * \param[in] flags open file descriptor
1051 * \retval valid llapi_layout pointer on success
1052 * \retval NULL if an error occurs
1054 struct llapi_layout *llapi_layout_get_by_fd(int fd,
1055 enum llapi_layout_get_flags flags)
1058 struct lov_user_md *lum;
1059 struct llapi_layout *layout = NULL;
1063 lum_len = XATTR_SIZE_MAX;
1064 lum = malloc(lum_len);
1068 bytes_read = fgetxattr(fd, XATTR_LUSTRE_LOV, lum, lum_len);
1069 if (bytes_read < 0) {
1070 if (errno == EOPNOTSUPP)
1072 else if (errno == ENODATA)
1073 layout = llapi_layout_alloc();
1077 /* Directories may have a positive non-zero lum->lmm_stripe_count
1078 * yet have an empty lum->lmm_objects array. For non-directories the
1079 * amount of data returned from the kernel must be consistent
1080 * with the stripe count. */
1081 if (fstat(fd, &st) < 0)
1084 layout = llapi_layout_get_by_xattr(lum, bytes_read,
1085 S_ISDIR(st.st_mode) ? 0 : LLAPI_LAYOUT_GET_CHECK);
1092 * Get the expected striping layout for a file at \a path.
1094 * Substitute expected inherited attribute values for unspecified
1095 * attributes. Unspecified attributes may belong to directories and
1096 * never-written-to files, and indicate that default values will be
1097 * assigned when files are created or first written to. A default value
1098 * is inherited from the parent directory if the attribute is specified
1099 * there, otherwise it is inherited from the filesystem root.
1100 * Unspecified attributes normally have the value LLAPI_LAYOUT_DEFAULT.
1102 * The complete \a path need not refer to an existing file or directory,
1103 * but some leading portion of it must reside within a lustre filesystem.
1104 * A use case for this interface would be to obtain the literal striping
1105 * values that would be assigned to a new file in a given directory.
1107 * \param[in] path path for which to get the expected layout
1109 * \retval valid llapi_layout pointer on success
1110 * \retval NULL if an error occurs
1112 static struct llapi_layout *llapi_layout_expected(const char *path)
1114 struct llapi_layout *path_layout = NULL;
1115 char donor_path[PATH_MAX];
1120 fd = open(path, O_RDONLY);
1121 if (fd < 0 && errno != ENOENT)
1127 path_layout = llapi_layout_get_by_fd(fd, 0);
1133 if (path_layout == NULL) {
1134 if (errno != ENODATA && errno != ENOENT)
1137 path_layout = llapi_layout_alloc();
1138 if (path_layout == NULL)
1142 if (is_any_specified(path_layout)) {
1143 inherit_sys_attributes(path_layout, path);
1147 llapi_layout_free(path_layout);
1149 rc = stat(path, &st);
1150 if (rc < 0 && errno != ENOENT)
1153 /* If path is a not a directory or doesn't exist, inherit layout
1154 * from parent directory. */
1155 if ((rc == 0 && !S_ISDIR(st.st_mode)) ||
1156 (rc < 0 && errno == ENOENT)) {
1157 get_parent_dir(path, donor_path, sizeof(donor_path));
1158 path_layout = llapi_layout_get_by_path(donor_path, 0);
1159 if (path_layout != NULL) {
1160 if (is_any_specified(path_layout)) {
1161 inherit_sys_attributes(path_layout, donor_path);
1164 llapi_layout_free(path_layout);
1168 /* Inherit layout from the filesystem root. */
1169 rc = llapi_search_mounts(path, 0, donor_path, NULL);
1172 path_layout = llapi_layout_get_by_path(donor_path, 0);
1173 if (path_layout == NULL)
1176 inherit_sys_attributes(path_layout, donor_path);
1181 * Get the striping layout for the file at \a path.
1183 * If \a flags contains LLAPI_LAYOUT_GET_EXPECTED, substitute
1184 * expected inherited attribute values for unspecified attributes. See
1185 * llapi_layout_expected().
1187 * \param[in] path path for which to get the layout
1188 * \param[in] flags flags to control how layout is retrieved
1190 * \retval valid llapi_layout pointer on success
1191 * \retval NULL if an error occurs
1193 struct llapi_layout *llapi_layout_get_by_path(const char *path,
1194 enum llapi_layout_get_flags flags)
1196 struct llapi_layout *layout = NULL;
1197 bool failed = false;
1202 if (flags & LLAPI_LAYOUT_GET_EXPECTED)
1203 return llapi_layout_expected(path);
1205 /* Always get layout in O_DIRECT */
1206 /* Allow fetching layout even without the key on encrypted files */
1207 open_flags = O_RDONLY | O_DIRECT | O_CIPHERTEXT;
1209 fd = open(path, open_flags);
1211 if (errno != EINVAL || failed)
1213 /* EINVAL is because a directory cannot be opened in O_DIRECT */
1214 open_flags = O_RDONLY | O_CIPHERTEXT;
1219 layout = llapi_layout_get_by_fd(fd, flags);
1228 * Get the layout for the file with FID \a fidstr in filesystem \a lustre_dir.
1230 * \param[in] lustre_dir path within Lustre filesystem containing \a fid
1231 * \param[in] fid Lustre identifier of file to get layout for
1233 * \retval valid llapi_layout pointer on success
1234 * \retval NULL if an error occurs
1236 struct llapi_layout *llapi_layout_get_by_fid(const char *lustre_dir,
1237 const struct lu_fid *fid,
1238 enum llapi_layout_get_flags flags)
1242 int saved_msg_level = llapi_msg_get_level();
1243 struct llapi_layout *layout = NULL;
1245 /* Prevent llapi internal routines from writing to console
1246 * while executing this function, then restore previous message
1248 llapi_msg_set_level(LLAPI_MSG_OFF);
1249 fd = llapi_open_by_fid(lustre_dir, fid, O_RDONLY);
1250 llapi_msg_set_level(saved_msg_level);
1255 layout = llapi_layout_get_by_fd(fd, flags);
1264 * Get the stripe count of \a layout.
1266 * \param[in] layout layout to get stripe count from
1267 * \param[out] count integer to store stripe count in
1269 * \retval 0 on success
1270 * \retval -1 if arguments are invalid
1272 int llapi_layout_stripe_count_get(const struct llapi_layout *layout,
1275 struct llapi_layout_comp *comp;
1277 comp = __llapi_layout_cur_comp(layout);
1281 if (count == NULL) {
1286 if (comp->llc_pattern == LLAPI_LAYOUT_FOREIGN)
1289 *count = comp->llc_stripe_count;
1295 * The llapi_layout API functions have these extra validity checks since
1296 * they use intuitively named macros to denote special behavior, whereas
1297 * the old API uses 0 and -1.
1300 bool llapi_layout_stripe_count_is_valid(int64_t stripe_count)
1302 return stripe_count == LLAPI_LAYOUT_DEFAULT ||
1303 stripe_count == LLAPI_LAYOUT_WIDE ||
1304 (stripe_count != 0 && stripe_count != -1 &&
1305 llapi_stripe_count_is_valid(stripe_count));
1308 static bool llapi_layout_extension_size_is_valid(uint64_t ext_size)
1310 return (ext_size != 0 &&
1311 llapi_stripe_size_is_aligned(ext_size) &&
1312 !llapi_stripe_size_is_too_big(ext_size));
1315 static bool llapi_layout_stripe_size_is_valid(uint64_t stripe_size)
1317 return stripe_size == LLAPI_LAYOUT_DEFAULT ||
1318 (stripe_size != 0 &&
1319 llapi_stripe_size_is_aligned(stripe_size) &&
1320 !llapi_stripe_size_is_too_big(stripe_size));
1323 static bool llapi_layout_stripe_index_is_valid(int64_t stripe_index)
1325 return stripe_index == LLAPI_LAYOUT_DEFAULT ||
1326 (stripe_index >= 0 &&
1327 llapi_stripe_index_is_valid(stripe_index));
1331 * Set the stripe count of \a layout.
1333 * \param[in] layout layout to set stripe count in
1334 * \param[in] count value to be set
1336 * \retval 0 on success
1337 * \retval -1 if arguments are invalid
1339 int llapi_layout_stripe_count_set(struct llapi_layout *layout,
1342 struct llapi_layout_comp *comp;
1344 comp = __llapi_layout_cur_comp(layout);
1348 if (!llapi_layout_stripe_count_is_valid(count)) {
1353 comp->llc_stripe_count = count;
1359 * Get the stripe/extension size of \a layout.
1361 * \param[in] layout layout to get stripe size from
1362 * \param[out] size integer to store stripe size in
1363 * \param[in] extension flag if extenion size is requested
1365 * \retval 0 on success
1366 * \retval -1 if arguments are invalid
1368 static int layout_stripe_size_get(const struct llapi_layout *layout,
1369 uint64_t *size, bool extension)
1371 struct llapi_layout_comp *comp;
1374 comp = __llapi_layout_cur_comp(layout);
1383 /* FIXME: return a component rather than FOREIGN/HSM component. */
1384 if (comp->llc_pattern == LLAPI_LAYOUT_FOREIGN) {
1389 comp_ext = comp->llc_flags & LCME_FL_EXTENSION;
1390 if ((comp_ext && !extension) || (!comp_ext && extension)) {
1395 *size = comp->llc_stripe_size;
1396 if (comp->llc_flags & LCME_FL_EXTENSION)
1397 *size *= SEL_UNIT_SIZE;
1402 int llapi_layout_stripe_size_get(const struct llapi_layout *layout,
1405 return layout_stripe_size_get(layout, size, false);
1408 int llapi_layout_extension_size_get(const struct llapi_layout *layout,
1411 return layout_stripe_size_get(layout, size, true);
1415 * Set the stripe/extension size of \a layout.
1417 * \param[in] layout layout to set stripe size in
1418 * \param[in] size value to be set
1419 * \param[in] extension flag if extenion size is passed
1421 * \retval 0 on success
1422 * \retval -1 if arguments are invalid
1424 static int layout_stripe_size_set(struct llapi_layout *layout,
1425 uint64_t size, bool extension)
1427 struct llapi_layout_comp *comp;
1430 comp = __llapi_layout_cur_comp(layout);
1434 if (comp->llc_pattern == LLAPI_LAYOUT_FOREIGN) {
1439 comp_ext = comp->llc_flags & LCME_FL_EXTENSION;
1440 if ((comp_ext && !extension) || (!comp_ext && extension)) {
1446 size /= SEL_UNIT_SIZE;
1448 if ((comp_ext && !llapi_layout_extension_size_is_valid(size)) ||
1449 (!comp_ext && !llapi_layout_stripe_size_is_valid(size))) {
1454 comp->llc_stripe_size = size;
1458 int llapi_layout_stripe_size_set(struct llapi_layout *layout,
1461 return layout_stripe_size_set(layout, size, false);
1464 int llapi_layout_extension_size_set(struct llapi_layout *layout,
1467 return layout_stripe_size_set(layout, size, true);
1471 * Get the RAID pattern of \a layout.
1473 * \param[in] layout layout to get pattern from
1474 * \param[out] pattern integer to store pattern in
1476 * \retval 0 on success
1477 * \retval -1 if arguments are invalid
1479 int llapi_layout_pattern_get(const struct llapi_layout *layout,
1482 struct llapi_layout_comp *comp;
1484 comp = __llapi_layout_cur_comp(layout);
1488 if (pattern == NULL) {
1493 *pattern = comp->llc_pattern;
1499 * Set the pattern of \a layout.
1501 * \param[in] layout layout to set pattern in
1502 * \param[in] pattern value to be set
1504 * \retval 0 on success
1505 * \retval -1 if arguments are invalid or RAID pattern
1508 int llapi_layout_pattern_set(struct llapi_layout *layout, uint64_t pattern)
1510 struct llapi_layout_comp *comp;
1512 comp = __llapi_layout_cur_comp(layout);
1516 if (pattern != LLAPI_LAYOUT_DEFAULT &&
1517 pattern != LLAPI_LAYOUT_RAID0 && pattern != LLAPI_LAYOUT_MDT
1518 && pattern != LLAPI_LAYOUT_OVERSTRIPING &&
1519 pattern != LLAPI_LAYOUT_FOREIGN) {
1524 comp->llc_pattern = pattern |
1525 (comp->llc_pattern & LLAPI_LAYOUT_SPECIFIC);
1530 static inline int stripe_number_roundup(int stripe_number)
1532 unsigned int round_up = (stripe_number + 8) & ~7;
1533 return round_up > LOV_MAX_STRIPE_COUNT ?
1534 LOV_MAX_STRIPE_COUNT : round_up;
1538 * Set the OST index of stripe number \a stripe_number to \a ost_index.
1540 * If only the starting stripe's OST index is specified, then this can use
1541 * the normal LOV_MAGIC_{V1,V3} layout type. If multiple OST indices are
1542 * given, then allocate an array to hold the list of indices and ensure that
1543 * the LOV_USER_MAGIC_SPECIFIC layout is used when creating the file.
1545 * \param[in] layout layout to set OST index in
1546 * \param[in] stripe_number stripe number to set index for
1547 * \param[in] ost_index the index to set
1549 * \retval 0 on success
1550 * \retval -1 if arguments are invalid or an unsupported stripe number
1551 * was specified, error returned in errno
1553 int llapi_layout_ost_index_set(struct llapi_layout *layout, int stripe_number,
1556 struct llapi_layout_comp *comp;
1558 comp = __llapi_layout_cur_comp(layout);
1562 if (comp->llc_pattern == LLAPI_LAYOUT_FOREIGN) {
1567 if (!llapi_layout_stripe_index_is_valid(ost_index)) {
1572 if (stripe_number == 0 && ost_index == LLAPI_LAYOUT_DEFAULT) {
1573 comp->llc_stripe_offset = ost_index;
1574 comp->llc_pattern &= ~LLAPI_LAYOUT_SPECIFIC;
1575 __llapi_comp_objects_realloc(comp, 0);
1576 } else if (stripe_number >= 0 &&
1577 stripe_number < LOV_MAX_STRIPE_COUNT) {
1578 if (ost_index >= LLAPI_LAYOUT_IDX_MAX) {
1583 /* Preallocate a few more stripes to avoid realloc() overhead.*/
1584 if (__llapi_comp_objects_realloc(comp,
1585 stripe_number_roundup(stripe_number)) < 0)
1588 comp->llc_objects[stripe_number].l_ost_idx = ost_index;
1590 if (stripe_number == 0)
1591 comp->llc_stripe_offset = ost_index;
1593 comp->llc_pattern |= LLAPI_LAYOUT_SPECIFIC;
1595 if (comp->llc_stripe_count == LLAPI_LAYOUT_DEFAULT ||
1596 comp->llc_stripe_count <= stripe_number)
1597 comp->llc_stripe_count = stripe_number + 1;
1607 * Get the OST index associated with stripe \a stripe_number.
1609 * Stripes are indexed starting from zero.
1611 * \param[in] layout layout to get index from
1612 * \param[in] stripe_number stripe number to get index for
1613 * \param[out] index integer to store index in
1615 * \retval 0 on success
1616 * \retval -1 if arguments are invalid
1618 int llapi_layout_ost_index_get(const struct llapi_layout *layout,
1619 uint64_t stripe_number, uint64_t *index)
1621 struct llapi_layout_comp *comp;
1623 comp = __llapi_layout_cur_comp(layout);
1627 if (comp->llc_pattern == LLAPI_LAYOUT_FOREIGN) {
1632 if (index == NULL) {
1637 if (stripe_number >= comp->llc_stripe_count ||
1638 stripe_number >= comp->llc_objects_count) {
1643 if (comp->llc_stripe_offset == LLAPI_LAYOUT_DEFAULT)
1644 *index = LLAPI_LAYOUT_DEFAULT;
1646 *index = comp->llc_objects[stripe_number].l_ost_idx;
1653 * Get the pool name of layout \a layout.
1655 * \param[in] layout layout to get pool name from
1656 * \param[out] dest buffer to store pool name in
1657 * \param[in] n size in bytes of buffer \a dest
1659 * \retval 0 on success
1660 * \retval -1 if arguments are invalid
1662 int llapi_layout_pool_name_get(const struct llapi_layout *layout, char *dest,
1665 struct llapi_layout_comp *comp;
1667 comp = __llapi_layout_cur_comp(layout);
1676 if (comp->llc_pattern == LLAPI_LAYOUT_FOREIGN) {
1681 strncpy(dest, comp->llc_pool_name, n);
1687 * Set the name of the pool of layout \a layout.
1689 * \param[in] layout layout to set pool name in
1690 * \param[in] pool_name pool name to set
1692 * \retval 0 on success
1693 * \retval -1 if arguments are invalid or pool name is too long
1695 int llapi_layout_pool_name_set(struct llapi_layout *layout,
1696 const char *pool_name)
1698 struct llapi_layout_comp *comp;
1700 comp = __llapi_layout_cur_comp(layout);
1704 if (!llapi_pool_name_is_valid(&pool_name)) {
1709 if (comp->llc_pattern == LLAPI_LAYOUT_FOREIGN) {
1714 strncpy(comp->llc_pool_name, pool_name, sizeof(comp->llc_pool_name));
1719 * Open and possibly create a file with a given \a layout.
1721 * If \a layout is NULL this function acts as a simple wrapper for
1722 * open(). By convention, ENOTTY is returned in errno if \a path
1723 * refers to a non-Lustre file.
1725 * \param[in] path name of the file to open
1726 * \param[in] open_flags open() flags
1727 * \param[in] mode permissions to create file, filtered by umask
1728 * \param[in] layout layout to create new file with
1730 * \retval non-negative file descriptor on successful open
1731 * \retval -1 if an error occurred
1733 int llapi_layout_file_open(const char *path, int open_flags, mode_t mode,
1734 const struct llapi_layout *layout)
1739 struct lov_user_md *lum;
1741 char fsname[MAX_OBD_NAME + 1] = { 0 };
1744 (layout != NULL && layout->llot_magic != LLAPI_LAYOUT_MAGIC)) {
1750 /* Make sure we are on a Lustre file system */
1751 rc = llapi_search_fsname(path, fsname);
1756 rc = llapi_layout_v2_sanity((struct llapi_layout *)layout,
1758 !!(layout->llot_mirror_count > 1),
1761 llapi_layout_sanity_perror(rc);
1766 /* Object creation must be postponed until after layout attributes
1767 * have been applied. */
1768 if (layout != NULL && (open_flags & O_CREAT))
1769 open_flags |= O_LOV_DELAY_CREATE;
1771 fd = open(path, open_flags, mode);
1773 if (layout == NULL || fd < 0)
1776 lum = llapi_layout_to_lum(layout);
1785 if (lum->lmm_magic == LOV_USER_MAGIC_COMP_V1)
1786 lum_size = ((struct lov_comp_md_v1 *)lum)->lcm_size;
1787 else if (lum->lmm_magic == LOV_USER_MAGIC_SPECIFIC)
1788 lum_size = lov_user_md_size(lum->lmm_stripe_count,
1791 lum_size = lov_user_md_size(0, lum->lmm_magic);
1793 rc = fsetxattr(fd, XATTR_LUSTRE_LOV, lum, lum_size, 0);
1802 errno = errno == EOPNOTSUPP ? ENOTTY : errno;
1808 * Create a file with a given \a layout.
1810 * Force O_CREAT and O_EXCL flags on so caller is assured that file was
1811 * created with the given \a layout on successful function return.
1813 * \param[in] path name of the file to open
1814 * \param[in] open_flags open() flags
1815 * \param[in] mode permissions to create new file with
1816 * \param[in] layout layout to create new file with
1818 * \retval non-negative file descriptor on successful open
1819 * \retval -1 if an error occurred
1821 int llapi_layout_file_create(const char *path, int open_flags, int mode,
1822 const struct llapi_layout *layout)
1824 return llapi_layout_file_open(path, open_flags|O_CREAT|O_EXCL, mode,
1828 int llapi_layout_flags_get(struct llapi_layout *layout, uint32_t *flags)
1830 if (layout->llot_magic != LLAPI_LAYOUT_MAGIC) {
1835 *flags = layout->llot_flags;
1840 * Set flags to the header of a component layout.
1842 int llapi_layout_flags_set(struct llapi_layout *layout, uint32_t flags)
1844 if (layout->llot_magic != LLAPI_LAYOUT_MAGIC) {
1849 layout->llot_flags = flags;
1853 const char *llapi_layout_flags_string(uint32_t flags)
1855 switch (flags & LCM_FL_FLR_MASK) {
1858 case LCM_FL_WRITE_PENDING:
1860 case LCM_FL_SYNC_PENDING:
1862 case LCM_FL_RDONLY | LCM_FL_PCC_RDONLY:
1864 case LCM_FL_WRITE_PENDING | LCM_FL_PCC_RDONLY:
1866 case LCM_FL_SYNC_PENDING | LCM_FL_PCC_RDONLY:
1873 __u16 llapi_layout_string_flags(char *string)
1875 if (strncmp(string, "ro", strlen(string)) == 0)
1876 return LCM_FL_RDONLY;
1877 if (strncmp(string, "wp", strlen(string)) == 0)
1878 return LCM_FL_WRITE_PENDING;
1879 if (strncmp(string, "sp", strlen(string)) == 0)
1880 return LCM_FL_SYNC_PENDING;
1886 * llapi_layout_mirror_count_is_valid() - Check the validity of mirror count.
1887 * @count: Mirror count value to be checked.
1889 * This function checks the validity of mirror count.
1891 * Return: true on success or false on failure.
1893 static bool llapi_layout_mirror_count_is_valid(uint16_t count)
1895 return count >= 0 && count <= LUSTRE_MIRROR_COUNT_MAX;
1899 * llapi_layout_mirror_count_get() - Get mirror count from the header of
1901 * @layout: Layout to get mirror count from.
1902 * @count: Returned mirror count value.
1904 * This function gets mirror count from the header of a layout.
1906 * Return: 0 on success or -1 on failure.
1908 int llapi_layout_mirror_count_get(struct llapi_layout *layout,
1911 if (layout->llot_magic != LLAPI_LAYOUT_MAGIC) {
1916 *count = layout->llot_mirror_count;
1921 * llapi_layout_mirror_count_set() - Set mirror count to the header of a layout.
1922 * @layout: Layout to set mirror count in.
1923 * @count: Mirror count value to be set.
1925 * This function sets mirror count to the header of a layout.
1927 * Return: 0 on success or -1 on failure.
1929 int llapi_layout_mirror_count_set(struct llapi_layout *layout,
1932 if (layout->llot_magic != LLAPI_LAYOUT_MAGIC) {
1937 if (!llapi_layout_mirror_count_is_valid(count)) {
1942 layout->llot_mirror_count = count;
1947 * Fetch the start and end offset of the current layout component.
1949 * \param[in] layout the layout component
1950 * \param[out] start extent start, inclusive
1951 * \param[out] end extent end, exclusive
1953 * \retval 0 on success
1954 * \retval <0 if error occurs
1956 int llapi_layout_comp_extent_get(const struct llapi_layout *layout,
1957 uint64_t *start, uint64_t *end)
1959 struct llapi_layout_comp *comp;
1961 comp = __llapi_layout_cur_comp(layout);
1965 if (start == NULL || end == NULL) {
1970 *start = comp->llc_extent.e_start;
1971 *end = comp->llc_extent.e_end;
1977 * Set the layout extent of a layout.
1979 * \param[in] layout the layout to be set
1980 * \param[in] start extent start, inclusive
1981 * \param[in] end extent end, exclusive
1983 * \retval 0 on success
1984 * \retval <0 if error occurs
1986 int llapi_layout_comp_extent_set(struct llapi_layout *layout,
1987 uint64_t start, uint64_t end)
1989 struct llapi_layout_comp *comp;
1991 comp = __llapi_layout_cur_comp(layout);
2000 comp->llc_extent.e_start = start;
2001 comp->llc_extent.e_end = end;
2002 layout->llot_is_composite = true;
2008 * Gets the attribute flags of the current component.
2010 * \param[in] layout the layout component
2011 * \param[out] flags stored the returned component flags
2013 * \retval 0 on success
2014 * \retval <0 if error occurs
2016 int llapi_layout_comp_flags_get(const struct llapi_layout *layout,
2019 struct llapi_layout_comp *comp;
2021 comp = __llapi_layout_cur_comp(layout);
2025 if (flags == NULL) {
2030 *flags = comp->llc_flags;
2036 * Sets the specified flags of the current component leaving other flags as-is.
2038 * \param[in] layout the layout component
2039 * \param[in] flags component flags to be set
2041 * \retval 0 on success
2042 * \retval <0 if error occurs
2044 int llapi_layout_comp_flags_set(struct llapi_layout *layout, uint32_t flags)
2046 struct llapi_layout_comp *comp;
2048 comp = __llapi_layout_cur_comp(layout);
2052 comp->llc_flags |= flags;
2058 * Clears the flags specified in the flags leaving other flags as-is.
2060 * \param[in] layout the layout component
2061 * \param[in] flags component flags to be cleared
2063 * \retval 0 on success
2064 * \retval <0 if error occurs
2066 int llapi_layout_comp_flags_clear(struct llapi_layout *layout,
2069 struct llapi_layout_comp *comp;
2071 comp = __llapi_layout_cur_comp(layout);
2075 comp->llc_flags &= ~flags;
2081 * Fetches the file-unique component ID of the current layout component.
2083 * \param[in] layout the layout component
2084 * \param[out] id stored the returned component ID
2086 * \retval 0 on success
2087 * \retval <0 if error occurs
2089 int llapi_layout_comp_id_get(const struct llapi_layout *layout, uint32_t *id)
2091 struct llapi_layout_comp *comp;
2093 comp = __llapi_layout_cur_comp(layout);
2107 * Return the mirror id of the current layout component.
2109 * \param[in] layout the layout component
2110 * \param[out] id stored the returned mirror ID
2112 * \retval 0 on success
2113 * \retval <0 if error occurs
2115 int llapi_layout_mirror_id_get(const struct llapi_layout *layout, uint32_t *id)
2117 struct llapi_layout_comp *comp;
2119 comp = __llapi_layout_cur_comp(layout);
2128 *id = mirror_id_of(comp->llc_id);
2134 * Adds a component to \a layout, the new component will be added to
2135 * the tail of components list and it'll inherit attributes of existing
2136 * ones. The \a layout will change it's current component pointer to
2137 * the newly added component, and it'll be turned into a composite
2138 * layout if it was not before the adding.
2140 * \param[in] layout existing composite or plain layout
2142 * \retval 0 on success
2143 * \retval <0 if error occurs
2145 int llapi_layout_comp_add(struct llapi_layout *layout)
2147 struct llapi_layout_comp *last, *comp, *new;
2148 bool composite = layout->llot_is_composite;
2150 comp = __llapi_layout_cur_comp(layout);
2154 new = __llapi_comp_alloc(0);
2158 last = list_last_entry(&layout->llot_comp_list, typeof(*last),
2161 list_add_tail(&new->llc_list, &layout->llot_comp_list);
2163 /* We must mark the layout composite for the sanity check, but it may
2164 * not stay that way if the check fails */
2165 layout->llot_is_composite = true;
2166 layout->llot_cur_comp = new;
2168 /* We need to set a temporary non-zero value for "end" when we call
2169 * comp_extent_set, so we use LUSTRE_EOF-1, which is > all allowed
2170 * for the end of the previous component. (If we're adding this
2171 * component, the end of the previous component cannot be EOF.) */
2172 if (llapi_layout_comp_extent_set(layout, last->llc_extent.e_end,
2174 llapi_layout_comp_del(layout);
2175 layout->llot_is_composite = composite;
2182 * Adds a first component of a mirror to \a layout.
2183 * The \a layout will change it's current component pointer to
2184 * the newly added component, and it'll be turned into a composite
2185 * layout if it was not before the adding.
2187 * \param[in] layout existing composite or plain layout
2189 * \retval 0 on success
2190 * \retval <0 if error occurs
2192 int llapi_layout_add_first_comp(struct llapi_layout *layout)
2194 struct llapi_layout_comp *comp, *new;
2196 comp = __llapi_layout_cur_comp(layout);
2200 new = __llapi_comp_alloc(0);
2204 new->llc_extent.e_start = 0;
2206 list_add_tail(&new->llc_list, &layout->llot_comp_list);
2207 layout->llot_cur_comp = new;
2208 layout->llot_is_composite = true;
2214 * Deletes current component from the composite layout. The component
2215 * to be deleted must be the tail of components list, and it can't be
2216 * the only component in the layout.
2218 * \param[in] layout composite layout
2220 * \retval 0 on success
2221 * \retval <0 if error occurs
2223 int llapi_layout_comp_del(struct llapi_layout *layout)
2225 struct llapi_layout_comp *comp;
2227 comp = __llapi_layout_cur_comp(layout);
2231 if (!layout->llot_is_composite) {
2236 /* It must be the tail of the list (for PFL, can be relaxed
2237 * once we get mirrored components) */
2238 if (comp->llc_list.next != &layout->llot_comp_list) {
2242 layout->llot_cur_comp =
2243 list_last_entry(&comp->llc_list, typeof(*comp), llc_list);
2244 if (comp->llc_list.prev == &layout->llot_comp_list)
2245 layout->llot_cur_comp = NULL;
2247 list_del_init(&comp->llc_list);
2248 __llapi_comp_free(comp);
2254 * Move the current component pointer to the component with
2255 * specified component ID.
2257 * \param[in] layout composite layout
2258 * \param[in] id component ID
2260 * \retval =0 : moved successfully
2261 * \retval <0 if error occurs
2263 int llapi_layout_comp_use_id(struct llapi_layout *layout, uint32_t comp_id)
2265 struct llapi_layout_comp *comp;
2267 comp = __llapi_layout_cur_comp(layout);
2269 return -1; /* use previously set errno */
2271 if (!layout->llot_is_composite) {
2276 if (comp_id == LCME_ID_INVAL) {
2281 list_for_each_entry(comp, &layout->llot_comp_list, llc_list) {
2282 if (comp->llc_id == comp_id) {
2283 layout->llot_cur_comp = comp;
2292 * Move the current component pointer to a specified position.
2294 * \param[in] layout composite layout
2295 * \param[in] pos the position to be moved, it can be:
2296 * LLAPI_LAYOUT_COMP_USE_FIRST: use first component
2297 * LLAPI_LAYOUT_COMP_USE_LAST: use last component
2298 * LLAPI_LAYOUT_COMP_USE_NEXT: use component after current
2299 * LLAPI_LAYOUT_COMP_USE_PREV: use component before current
2301 * \retval =0 : moved successfully
2302 * \retval =1 : at last component with NEXT, at first component with PREV
2303 * \retval <0 if error occurs
2305 int llapi_layout_comp_use(struct llapi_layout *layout,
2306 enum llapi_layout_comp_use pos)
2308 struct llapi_layout_comp *comp, *head, *tail;
2310 comp = __llapi_layout_cur_comp(layout);
2314 if (!layout->llot_is_composite) {
2315 if (pos == LLAPI_LAYOUT_COMP_USE_FIRST ||
2316 pos == LLAPI_LAYOUT_COMP_USE_LAST)
2322 head = list_first_entry(&layout->llot_comp_list, typeof(*head),
2324 tail = list_last_entry(&layout->llot_comp_list, typeof(*tail),
2327 case LLAPI_LAYOUT_COMP_USE_FIRST:
2328 layout->llot_cur_comp = head;
2330 case LLAPI_LAYOUT_COMP_USE_NEXT:
2335 layout->llot_cur_comp = list_first_entry(&comp->llc_list,
2339 case LLAPI_LAYOUT_COMP_USE_LAST:
2340 layout->llot_cur_comp = tail;
2342 case LLAPI_LAYOUT_COMP_USE_PREV:
2347 layout->llot_cur_comp = list_last_entry(&comp->llc_list,
2360 * Add layout component(s) to an existing file.
2362 * \param[in] path The path name of the file
2363 * \param[in] layout The layout component(s) to be added
2365 int llapi_layout_file_comp_add(const char *path,
2366 const struct llapi_layout *layout)
2368 int rc, fd = -1, lum_size, tmp_errno = 0;
2369 struct llapi_layout *existing_layout = NULL;
2370 struct lov_user_md *lum = NULL;
2371 char fsname[MAX_OBD_NAME + 1] = { 0 };
2373 if (path == NULL || layout == NULL ||
2374 layout->llot_magic != LLAPI_LAYOUT_MAGIC) {
2379 fd = open(path, O_RDWR);
2386 existing_layout = llapi_layout_get_by_fd(fd, 0);
2387 if (existing_layout == NULL) {
2393 rc = llapi_layout_merge(&existing_layout, layout);
2400 rc = llapi_search_fsname(path, fsname);
2407 rc = llapi_layout_v2_sanity(existing_layout, false, false, fsname);
2410 llapi_layout_sanity_perror(rc);
2415 lum = llapi_layout_to_lum(layout);
2422 if (lum->lmm_magic != LOV_USER_MAGIC_COMP_V1) {
2427 lum_size = ((struct lov_comp_md_v1 *)lum)->lcm_size;
2429 rc = fsetxattr(fd, XATTR_LUSTRE_LOV".add", lum, lum_size, 0);
2439 llapi_layout_free(existing_layout);
2445 * Delete component(s) by the specified component id or component flags
2446 * from an existing file.
2448 * \param[in] path path name of the file
2449 * \param[in] id unique component ID
2450 * \param[in] flags flags: LCME_FL_* or;
2451 * negative flags: (LCME_FL_NEG|LCME_FL_*)
2453 int llapi_layout_file_comp_del(const char *path, uint32_t id, uint32_t flags)
2455 int rc = 0, fd = -1, lum_size, tmp_errno = 0;
2456 struct llapi_layout *layout;
2457 struct llapi_layout_comp *comp, *next;
2458 struct llapi_layout *existing_layout = NULL;
2459 struct lov_user_md *lum = NULL;
2461 if (path == NULL || id > LCME_ID_MAX || (flags & ~LCME_KNOWN_FLAGS)) {
2466 /* Can only specify ID or flags, not both, not none. */
2467 if ((id != LCME_ID_INVAL && flags != 0) ||
2468 (id == LCME_ID_INVAL && flags == 0)) {
2473 layout = llapi_layout_alloc();
2477 llapi_layout_comp_extent_set(layout, 0, LUSTRE_EOF);
2478 comp = __llapi_layout_cur_comp(layout);
2486 comp->llc_flags = flags;
2488 lum = llapi_layout_to_lum(layout);
2494 lum_size = ((struct lov_comp_md_v1 *)lum)->lcm_size;
2496 fd = open(path, O_RDWR);
2503 existing_layout = llapi_layout_get_by_fd(fd, 0);
2504 if (existing_layout == NULL) {
2512 while (rc == 0 && existing_layout->llot_cur_comp != NULL) {
2513 rc = llapi_layout_comp_use(existing_layout, comp ?
2514 LLAPI_LAYOUT_COMP_USE_PREV :
2515 LLAPI_LAYOUT_COMP_USE_LAST);
2520 comp = __llapi_layout_cur_comp(existing_layout);
2526 if (id != LCME_ID_INVAL && id != comp->llc_id)
2528 else if ((flags & LCME_FL_NEG) && (flags & comp->llc_flags))
2530 else if (flags && !(flags & comp->llc_flags))
2533 rc = llapi_layout_comp_del(existing_layout);
2534 /* the layout position is moved to previous one, adjust */
2542 rc = llapi_layout_sanity(existing_layout, false, false);
2545 llapi_layout_sanity_perror(rc);
2550 rc = fsetxattr(fd, XATTR_LUSTRE_LOV".del", lum, lum_size, 0);
2561 llapi_layout_free(layout);
2562 llapi_layout_free(existing_layout);
2568 /* Internal utility function to apply flags for sanity checking */
2569 static void llapi_layout_comp_apply_flags(struct llapi_layout_comp *comp,
2572 if (flags & LCME_FL_NEG)
2573 comp->llc_flags &= ~flags;
2575 comp->llc_flags |= flags;
2578 struct llapi_layout_apply_flags_args {
2580 uint32_t *lfa_flags;
2586 static int llapi_layout_apply_flags_cb(struct llapi_layout *layout,
2589 struct llapi_layout_apply_flags_args *args = arg;
2590 struct llapi_layout_comp *comp;
2593 comp = __llapi_layout_cur_comp(layout);
2596 return LLAPI_LAYOUT_ITER_STOP;
2599 for (i = 0; i < args->lfa_count; i++) {
2600 if (comp->llc_id == args->lfa_ids[i])
2601 llapi_layout_comp_apply_flags(comp, args->lfa_flags[i]);
2604 return LLAPI_LAYOUT_ITER_CONT;
2607 /* Apply flags to the layout for sanity checking */
2608 static int llapi_layout_apply_flags(struct llapi_layout *layout, uint32_t *ids,
2609 uint32_t *flags, int count)
2611 struct llapi_layout_apply_flags_args args;
2614 if (!ids || !flags || count == 0) {
2620 args.lfa_flags = flags;
2621 args.lfa_count = count;
2624 rc = llapi_layout_comp_iterate(layout,
2625 llapi_layout_apply_flags_cb,
2627 if (errno == ENOENT)
2630 if (rc != LLAPI_LAYOUT_ITER_CONT)
2636 * Change flags by component ID of components of an existing file.
2637 * The component to be modified is specified by the comp->lcme_id value,
2638 * which must be a unique component ID.
2640 * \param[in] path path name of the file
2641 * \param[in] ids An array of component IDs
2642 * \param[in] flags flags: LCME_FL_* or;
2643 * negative flags: (LCME_FL_NEG|LCME_FL_*)
2644 * \param[in] count Number of elements in ids and flags array
2646 int llapi_layout_file_comp_set(const char *path, uint32_t *ids, uint32_t *flags,
2649 int rc = -1, fd = -1, i, tmp_errno = 0;
2651 struct llapi_layout *existing_layout = NULL;
2652 struct llapi_layout *layout = NULL;
2653 struct llapi_layout_comp *comp;
2654 struct lov_user_md *lum = NULL;
2655 char fsname[MAX_OBD_NAME + 1] = { 0 };
2665 for (i = 0; i < count; i++) {
2666 if (!ids[i] || !flags[i]) {
2671 if (ids[i] > LCME_ID_MAX || (flags[i] & ~LCME_KNOWN_FLAGS)) {
2676 /* do not allow to set or clear INIT flag */
2677 if (flags[i] & LCME_FL_INIT) {
2683 fd = open(path, O_RDWR);
2690 existing_layout = llapi_layout_get_by_fd(fd, 0);
2691 if (existing_layout == NULL) {
2697 if (llapi_layout_apply_flags(existing_layout, ids, flags, count)) {
2703 rc = llapi_search_fsname(path, fsname);
2710 rc = llapi_layout_v2_sanity(existing_layout, false, false, fsname);
2713 llapi_layout_sanity_perror(rc);
2718 layout = __llapi_layout_alloc();
2719 if (layout == NULL) {
2725 layout->llot_is_composite = true;
2726 for (i = 0; i < count; i++) {
2727 comp = __llapi_comp_alloc(0);
2734 comp->llc_id = ids[i];
2735 comp->llc_flags = flags[i];
2737 list_add_tail(&comp->llc_list, &layout->llot_comp_list);
2738 layout->llot_cur_comp = comp;
2741 lum = llapi_layout_to_lum(layout);
2748 lum_size = ((struct lov_comp_md_v1 *)lum)->lcm_size;
2750 /* flush cached pages from clients */
2751 rc = llapi_file_flush(fd);
2758 rc = fsetxattr(fd, XATTR_LUSTRE_LOV".set.flags", lum, lum_size, 0);
2771 llapi_layout_free(existing_layout);
2772 llapi_layout_free(layout);
2778 * Check if the file layout is composite.
2780 * \param[in] layout the file layout to check
2782 * \retval true composite
2783 * \retval false not composite
2785 bool llapi_layout_is_composite(struct llapi_layout *layout)
2787 return layout->llot_is_composite;
2791 * Iterate every components in the @layout and call callback function @cb.
2793 * \param[in] layout component layout list.
2794 * \param[in] cb callback for each component
2795 * \param[in] cbdata callback data
2797 * \retval < 0 error happens during the iteration
2798 * \retval LLAPI_LAYOUT_ITER_CONT finished the iteration w/o error
2799 * \retval LLAPI_LAYOUT_ITER_STOP got something, stop the iteration
2801 int llapi_layout_comp_iterate(struct llapi_layout *layout,
2802 llapi_layout_iter_cb cb, void *cbdata)
2806 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_FIRST);
2811 * make sure on success llapi_layout_comp_use() API returns 0 with
2817 rc = cb(layout, cbdata);
2818 if (rc != LLAPI_LAYOUT_ITER_CONT)
2821 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_NEXT);
2824 else if (rc == 1) /* reached the last comp */
2825 return LLAPI_LAYOUT_ITER_CONT;
2832 * llapi_layout_merge() - Merge a composite layout into another one.
2833 * @dst_layout: Destination composite layout.
2834 * @src_layout: Source composite layout.
2836 * This function copies all of the components from @src_layout and
2837 * appends them to @dst_layout.
2839 * Return: 0 on success or -1 on failure.
2841 int llapi_layout_merge(struct llapi_layout **dst_layout,
2842 const struct llapi_layout *src_layout)
2844 struct llapi_layout *new_layout = *dst_layout;
2845 struct llapi_layout_comp *new = NULL;
2846 struct llapi_layout_comp *comp = NULL;
2849 if (src_layout == NULL ||
2850 list_empty((struct list_head *)&src_layout->llot_comp_list))
2853 if (new_layout == NULL) {
2854 new_layout = __llapi_layout_alloc();
2855 if (new_layout == NULL) {
2861 list_for_each_entry(comp, &src_layout->llot_comp_list, llc_list) {
2862 new = __llapi_comp_alloc(0);
2868 new->llc_pattern = comp->llc_pattern;
2869 new->llc_stripe_size = comp->llc_stripe_size;
2870 new->llc_stripe_count = comp->llc_stripe_count;
2871 new->llc_stripe_offset = comp->llc_stripe_offset;
2873 if (comp->llc_pool_name[0] != '\0')
2874 strncpy(new->llc_pool_name, comp->llc_pool_name,
2875 sizeof(new->llc_pool_name));
2877 for (i = 0; i < comp->llc_objects_count; i++) {
2878 if (__llapi_comp_objects_realloc(new,
2879 stripe_number_roundup(i)) < 0) {
2881 __llapi_comp_free(new);
2884 new->llc_objects[i].l_ost_idx = \
2885 comp->llc_objects[i].l_ost_idx;
2888 new->llc_objects_count = comp->llc_objects_count;
2889 new->llc_extent.e_start = comp->llc_extent.e_start;
2890 new->llc_extent.e_end = comp->llc_extent.e_end;
2891 new->llc_id = comp->llc_id;
2892 new->llc_flags = comp->llc_flags;
2894 list_add_tail(&new->llc_list, &new_layout->llot_comp_list);
2895 new_layout->llot_cur_comp = new;
2897 new_layout->llot_is_composite = true;
2899 *dst_layout = new_layout;
2902 llapi_layout_free(new_layout);
2907 * Get the last initialized component
2909 * \param[in] layout component layout list.
2912 * \retval -EINVAL not found
2913 * \retval -EISDIR directory layout
2915 int llapi_layout_get_last_init_comp(struct llapi_layout *layout)
2917 struct llapi_layout_comp *comp = NULL, *head = NULL;
2919 if (!layout->llot_is_composite)
2922 head = list_first_entry(&layout->llot_comp_list, typeof(*comp),
2926 if (head->llc_id == 0 && !(head->llc_flags & LCME_FL_INIT))
2930 /* traverse the components from the tail to find the last init one */
2931 comp = list_last_entry(&layout->llot_comp_list, typeof(*comp),
2933 while (comp != head) {
2934 if (comp->llc_flags & LCME_FL_INIT)
2936 comp = list_last_entry(&comp->llc_list, typeof(*comp),
2940 layout->llot_cur_comp = comp;
2942 return comp->llc_flags & LCME_FL_INIT ? 0 : -EINVAL;
2946 * Interit stripe info from the file's component to the mirror
2948 * \param[in] layout file component layout list.
2949 * \param[in] layout mirro component layout list.
2951 * \retval 0 on success
2952 * \retval -EINVAL on error
2954 int llapi_layout_mirror_inherit(struct llapi_layout *f_layout,
2955 struct llapi_layout *m_layout)
2957 struct llapi_layout_comp *m_comp = NULL;
2958 struct llapi_layout_comp *f_comp = NULL;
2961 f_comp = __llapi_layout_cur_comp(f_layout);
2964 m_comp = __llapi_layout_cur_comp(m_layout);
2968 /* DoM component does not inherit stripe size */
2969 if (m_comp->llc_pattern != LLAPI_LAYOUT_MDT)
2970 m_comp->llc_stripe_size = f_comp->llc_stripe_size;
2971 m_comp->llc_stripe_count = f_comp->llc_stripe_count;
2977 * Find all stale components.
2979 * \param[in] layout component layout list.
2980 * \param[out] comp array of stale component info.
2981 * \param[in] comp_size array size of @comp.
2982 * \param[in] mirror_ids array of mirror id that only components
2983 * belonging to these mirror will be collected.
2984 * \param[in] ids_nr number of mirror ids array.
2986 * \retval number of component info collected on success or
2987 * an error code on failure.
2989 int llapi_mirror_find_stale(struct llapi_layout *layout,
2990 struct llapi_resync_comp *comp, size_t comp_size,
2991 __u16 *mirror_ids, int ids_nr)
2996 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_FIRST);
3004 uint64_t start, end;
3006 rc = llapi_layout_comp_flags_get(layout, &flags);
3010 if (!(flags & LCME_FL_STALE))
3013 rc = llapi_layout_mirror_id_get(layout, &mirror_id);
3017 /* the caller only wants stale components from specific
3022 for (j = 0; j < ids_nr; j++) {
3023 if (mirror_ids[j] == mirror_id)
3027 /* not in the specified mirror */
3030 } else if (flags & LCME_FL_NOSYNC) {
3031 /* if not specified mirrors, do not resync "nosync"
3036 rc = llapi_layout_comp_id_get(layout, &id);
3040 rc = llapi_layout_comp_extent_get(layout, &start, &end);
3044 /* pack this component into @comp array */
3045 comp[idx].lrc_id = id;
3046 comp[idx].lrc_mirror_id = mirror_id;
3047 comp[idx].lrc_start = start;
3048 comp[idx].lrc_end = end;
3051 if (idx >= comp_size) {
3057 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_NEXT);
3064 return rc < 0 ? rc : idx;
3067 /* locate @layout to a valid component covering file [file_start, file_end) */
3068 int llapi_mirror_find(struct llapi_layout *layout, uint64_t file_start,
3069 uint64_t file_end, uint64_t *endp)
3071 uint32_t mirror_id = 0;
3074 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_FIRST);
3080 uint64_t start, end;
3081 uint32_t flags, id, rid;
3083 rc = llapi_layout_comp_flags_get(layout, &flags);
3087 if (flags & LCME_FL_STALE)
3090 rc = llapi_layout_mirror_id_get(layout, &rid);
3094 rc = llapi_layout_comp_id_get(layout, &id);
3098 rc = llapi_layout_comp_extent_get(layout, &start, &end);
3102 if (file_start >= start && file_start < end) {
3105 else if (mirror_id != rid || *endp != start)
3108 file_start = *endp = end;
3109 if (end >= file_end)
3114 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_NEXT);
3124 #ifndef NSEC_PER_SEC
3125 # define NSEC_PER_SEC 1000000000UL
3127 #define ONE_MB 0x100000
3128 static struct timespec timespec_sub(struct timespec *before,
3129 struct timespec *after)
3131 struct timespec ret;
3133 ret.tv_sec = after->tv_sec - before->tv_sec;
3134 if (after->tv_nsec < before->tv_nsec) {
3136 ret.tv_nsec = NSEC_PER_SEC + after->tv_nsec - before->tv_nsec;
3138 ret.tv_nsec = after->tv_nsec - before->tv_nsec;
3144 static void stats_log(struct timespec *now, struct timespec *start_time,
3145 ssize_t read_bytes, size_t write_bytes,
3146 off_t file_size_bytes)
3148 struct timespec diff = timespec_sub(start_time, now);
3150 if (file_size_bytes == 0)
3153 if (diff.tv_sec == 0 && diff.tv_nsec == 0)
3156 llapi_printf(LLAPI_MSG_NORMAL,
3157 "- { seconds: %li, rmbps: %5.2g, wmbps: %5.2g, copied: %lu, size: %lu, pct: %lu%% }\n",
3159 (double) read_bytes/((ONE_MB * diff.tv_sec) +
3160 ((ONE_MB * diff.tv_nsec)/NSEC_PER_SEC)),
3161 (double) write_bytes/((ONE_MB * diff.tv_sec) +
3162 ((ONE_MB * diff.tv_nsec)/NSEC_PER_SEC)),
3164 file_size_bytes/ONE_MB,
3165 ((write_bytes*100)/file_size_bytes));
3168 int llapi_mirror_resync_many_params(int fd, struct llapi_layout *layout,
3169 struct llapi_resync_comp *comp_array,
3170 int comp_size, uint64_t start,
3172 unsigned long stats_interval_sec,
3173 unsigned long bandwidth_bytes_sec)
3175 size_t buflen = 64 << 20; /* 64M */
3178 uint64_t pos = start;
3179 uint64_t data_off = pos, data_end = pos;
3180 uint64_t mirror_end = LUSTRE_EOF;
3185 struct timespec start_time;
3186 struct timespec now;
3187 struct timespec last_bw_print;
3188 size_t total_bytes_read = 0;
3189 size_t total_bytes_written = 0;
3190 off_t write_estimation_bytes = 0;
3192 if (bandwidth_bytes_sec > 0 || stats_interval_sec) {
3195 rc = fstat(fd, &st);
3198 write_estimation_bytes = st.st_size * comp_size;
3201 /* limit transfer size to what can be sent in one second */
3202 if (bandwidth_bytes_sec && bandwidth_bytes_sec < buflen)
3203 buflen = (bandwidth_bytes_sec + ONE_MB - 1) & ~(ONE_MB - 1);
3205 page_size = sysconf(_SC_PAGESIZE);
3206 if (page_size < 0) {
3211 rc = posix_memalign(&buf, page_size, buflen);
3215 clock_gettime(CLOCK_MONOTONIC, &start_time);
3216 now = last_bw_print = start_time;
3224 if (pos >= data_end) {
3227 if (pos >= mirror_end || !src) {
3228 rc = llapi_mirror_find(layout, pos, end,
3235 /* restrict mirror end by resync end */
3236 mirror_end = MIN(end, mirror_end);
3239 tmp_off = llapi_mirror_data_seek(fd, src, pos,
3242 /* switch to full copy */
3243 to_read = mirror_end - pos;
3247 data_end = data_off + data_size;
3249 data_off = MIN(data_off, mirror_end);
3250 data_end = MIN(data_end, mirror_end);
3252 /* align by page, if there is data block to copy */
3254 data_off &= ~(page_size - 1);
3257 if (pos < data_off) {
3258 for (i = 0; i < comp_size; i++) {
3261 uint32_t mid = comp_array[i].lrc_mirror_id;
3263 /* skip non-overlapped component */
3264 if (pos >= comp_array[i].lrc_end ||
3265 data_off <= comp_array[i].lrc_start)
3268 if (pos < comp_array[i].lrc_start)
3269 cur_pos = comp_array[i].lrc_start;
3273 if (data_off > comp_array[i].lrc_end)
3274 to_punch = comp_array[i].lrc_end -
3277 to_punch = data_off - cur_pos;
3279 if (comp_array[i].lrc_end == OBD_OBJECT_EOF)
3280 /* the last component can be truncated
3283 rc = llapi_mirror_truncate(fd, mid,
3286 rc = llapi_mirror_punch(fd, mid,
3289 * hole at the end of file, so just truncate up
3292 if (!rc && data_off == data_end && !data_size)
3293 rc = llapi_mirror_truncate(fd,
3295 /* if failed then read failed hole range */
3299 if (pos + to_punch == data_off)
3300 to_read = data_end - pos;
3308 if (pos == mirror_end)
3310 to_read = data_end - pos;
3315 assert(data_end <= mirror_end);
3317 to_read = MIN(buflen, to_read);
3318 to_read = ((to_read - 1) | (page_size - 1)) + 1;
3319 bytes_read = llapi_mirror_read(fd, src, buf, to_read, pos);
3320 if (bytes_read == 0) {
3324 if (bytes_read < 0) {
3328 total_bytes_read += bytes_read;
3330 /* round up to page align to make direct IO happy. */
3331 to_write = ((bytes_read - 1) | (page_size - 1)) + 1;
3333 for (i = 0; i < comp_size; i++) {
3334 unsigned long long write_target;
3335 struct timespec diff;
3338 size_t to_write2 = to_write;
3340 /* skip non-overlapped component */
3341 if (pos >= comp_array[i].lrc_end ||
3342 pos + to_write <= comp_array[i].lrc_start)
3345 if (pos < comp_array[i].lrc_start)
3346 pos2 = comp_array[i].lrc_start;
3348 to_write2 -= pos2 - pos;
3350 if ((pos + to_write) > comp_array[i].lrc_end)
3351 to_write2 -= pos + to_write -
3352 comp_array[i].lrc_end;
3354 written = llapi_mirror_write(fd,
3355 comp_array[i].lrc_mirror_id,
3360 * this component is not written successfully,
3361 * mark it using its lrc_synced, it is supposed
3362 * to be false before getting here.
3364 * And before this function returns, all
3365 * elements of comp_array will reverse their
3366 * lrc_synced flag to reflect their true
3369 comp_array[i].lrc_synced = true;
3370 llapi_error(LLAPI_MSG_ERROR, written,
3371 "component %u not synced",
3372 comp_array[i].lrc_id);
3377 assert(written == to_write2);
3378 total_bytes_written += written;
3380 if (bandwidth_bytes_sec == 0)
3383 clock_gettime(CLOCK_MONOTONIC, &now);
3384 diff = timespec_sub(&start_time, &now);
3385 write_target = ((bandwidth_bytes_sec * diff.tv_sec) +
3386 ((bandwidth_bytes_sec *
3387 diff.tv_nsec)/NSEC_PER_SEC));
3389 if (write_target < total_bytes_written) {
3390 unsigned long long excess;
3391 struct timespec delay = { 0, 0 };
3393 excess = total_bytes_written - write_target;
3398 delay.tv_sec = excess / bandwidth_bytes_sec;
3399 delay.tv_nsec = (excess % bandwidth_bytes_sec) *
3400 NSEC_PER_SEC / bandwidth_bytes_sec;
3403 rc = clock_nanosleep(CLOCK_MONOTONIC, 0,
3405 } while (rc < 0 && errno == EINTR);
3408 llapi_error(LLAPI_MSG_ERROR, rc,
3409 "errors: delay for bandwidth control failed: %s\n",
3415 if (stats_interval_sec) {
3416 clock_gettime(CLOCK_MONOTONIC, &now);
3417 if ((total_bytes_written != end - start) &&
3418 (now.tv_sec >= last_bw_print.tv_sec +
3419 stats_interval_sec)) {
3420 stats_log(&now, &start_time,
3422 total_bytes_written,
3423 write_estimation_bytes);
3424 last_bw_print = now;
3434 /* fatal error happens */
3435 for (i = 0; i < comp_size; i++)
3436 comp_array[i].lrc_synced = false;
3440 /* Output at least one log, regardless of stats_interval */
3441 if (stats_interval_sec) {
3442 clock_gettime(CLOCK_MONOTONIC, &now);
3443 stats_log(&now, &start_time, total_bytes_read,
3444 total_bytes_written,
3445 write_estimation_bytes);
3449 * no fatal error happens, each lrc_synced tells whether the component
3450 * has been resync successfully (note: we'd reverse the value to
3451 * reflect its true meaning.
3453 for (i = 0; i < comp_size; i++) {
3454 comp_array[i].lrc_synced = !comp_array[i].lrc_synced;
3455 if (comp_array[i].lrc_synced && pos & (page_size - 1)) {
3456 rc = llapi_mirror_truncate(fd,
3457 comp_array[i].lrc_mirror_id, pos);
3458 /* Ignore truncate error on encrypted file without the
3459 * key if tried on LUSTRE_ENCRYPTION_UNIT_SIZE boundary.
3461 if (rc < 0 && (rc != -ENOKEY ||
3462 pos & ~LUSTRE_ENCRYPTION_MASK))
3463 comp_array[i].lrc_synced = false;
3468 * returns the first error code for partially successful resync if
3474 int llapi_mirror_resync_many(int fd, struct llapi_layout *layout,
3475 struct llapi_resync_comp *comp_array,
3476 int comp_size, uint64_t start, uint64_t end)
3478 return llapi_mirror_resync_many_params(fd, layout, comp_array,
3479 comp_size, start, end, 0, 0);
3482 enum llapi_layout_comp_sanity_error {
3484 LSE_INCOMPLETE_MIRROR,
3485 LSE_ADJACENT_EXTENSION,
3489 LSE_DOM_EXTENSION_FOLLOWING,
3492 LSE_NOT_ZERO_LENGTH_EXTENDABLE,
3493 LSE_END_NOT_GREATER,
3494 LSE_ZERO_LENGTH_NORMAL,
3495 LSE_NOT_ADJACENT_PREV,
3499 LSE_FOREIGN_EXTENSION,
3503 const char *const llapi_layout_strerror[] =
3506 [LSE_INCOMPLETE_MIRROR] =
3507 "Incomplete mirror - must go to EOF",
3508 [LSE_ADJACENT_EXTENSION] =
3509 "No adjacent extension space components",
3510 [LSE_INIT_EXTENSION] =
3511 "Cannot apply extension flag to init components",
3514 [LSE_DOM_EXTENSION] =
3515 "DoM components can't be extension space",
3516 [LSE_DOM_EXTENSION_FOLLOWING] =
3517 "DoM components cannot be followed by extension space",
3519 "DoM component should be the first one in a file/mirror",
3520 [LSE_SET_COMP_START] =
3521 "Must set previous component extent before adding next",
3522 [LSE_NOT_ZERO_LENGTH_EXTENDABLE] =
3523 "Extendable component must start out zero-length",
3524 [LSE_END_NOT_GREATER] =
3525 "Component end is before end of previous component",
3526 [LSE_ZERO_LENGTH_NORMAL] =
3527 "Zero length components must be followed by extension",
3528 [LSE_NOT_ADJACENT_PREV] =
3529 "Components not adjacent (end != next->start",
3530 [LSE_START_GT_END] =
3531 "Component start is > end",
3533 "The component end must be aligned by the stripe size",
3535 "The extension size must be aligned by the stripe size",
3536 [LSE_FOREIGN_EXTENSION] =
3537 "FOREIGN components can't be extension space",
3540 struct llapi_layout_sanity_args {
3541 bool lsa_incomplete;
3548 /* The component flags can be set by users at creation/modification time. */
3549 #define LCME_USER_COMP_FLAGS (LCME_FL_PREF_RW | LCME_FL_NOSYNC | \
3552 /* Inline function to verify the pool name */
3553 static inline int verify_pool_name(char *fsname, struct llapi_layout *layout)
3555 struct llapi_layout_comp *comp;
3557 if (!fsname || fsname[0] == '\0')
3560 comp = __llapi_layout_cur_comp(layout);
3563 if (comp->llc_pool_name[0] == '\0')
3565 /* check if the pool name exist */
3566 if (llapi_search_ost(fsname, comp->llc_pool_name, NULL) < 0)
3572 * When modified, adjust llapi_stripe_param_verify() if needed as well.
3574 static int llapi_layout_sanity_cb(struct llapi_layout *layout,
3577 struct llapi_layout_comp *comp, *next, *prev;
3578 struct llapi_layout_sanity_args *args = arg;
3579 bool first_comp = false;
3581 comp = __llapi_layout_cur_comp(layout);
3587 if (verify_pool_name(args->fsname, layout) != 0) {
3592 if (comp->llc_list.prev != &layout->llot_comp_list)
3593 prev = list_last_entry(&comp->llc_list, typeof(*prev),
3598 if (comp->llc_list.next != &layout->llot_comp_list)
3599 next = list_first_entry(&comp->llc_list, typeof(*next),
3604 /* Start of zero implies a new mirror */
3605 if (comp->llc_extent.e_start == 0) {
3607 /* Most checks apply only within one mirror, this is an
3609 if (prev && prev->llc_extent.e_end != LUSTRE_EOF) {
3610 args->lsa_rc = LSE_INCOMPLETE_MIRROR;
3617 if (next && next->llc_extent.e_start == 0)
3620 /* Flag sanity checks */
3621 /* No adjacent extension components */
3622 if ((comp->llc_flags & LCME_FL_EXTENSION) && next &&
3623 (next->llc_flags & LCME_FL_EXTENSION)) {
3624 args->lsa_rc = LSE_ADJACENT_EXTENSION;
3628 /* Extension flag cannot be applied to init components and the first
3629 * component of each mirror is automatically init */
3630 if ((comp->llc_flags & LCME_FL_EXTENSION) &&
3631 (comp->llc_flags & LCME_FL_INIT || first_comp)) {
3632 args->lsa_rc = LSE_INIT_EXTENSION;
3636 if (comp->llc_ondisk) {
3637 if (comp->llc_flags & LCME_FL_NEG)
3638 args->lsa_rc = LSE_FLAGS;
3639 } else if (!args->lsa_incomplete) {
3640 if (args->lsa_flr) {
3641 if (comp->llc_flags & ~LCME_USER_COMP_FLAGS)
3642 args->lsa_rc = LSE_FLAGS;
3644 if (comp->llc_flags &
3645 ~(LCME_FL_EXTENSION | LCME_FL_PREF_RW |
3647 args->lsa_rc = LSE_FLAGS;
3653 /* DoM sanity checks */
3654 if (!(comp->llc_pattern & LLAPI_LAYOUT_INVALID) &&
3655 (comp->llc_pattern & (LLAPI_LAYOUT_MDT | LOV_PATTERN_MDT))) {
3656 /* DoM components can't be extension components */
3657 if (comp->llc_flags & LCME_FL_EXTENSION) {
3658 args->lsa_rc = LSE_DOM_EXTENSION;
3661 /* DoM components cannot be followed by an extension comp */
3662 if (next && (next->llc_flags & LCME_FL_EXTENSION)) {
3663 args->lsa_rc = LSE_DOM_EXTENSION_FOLLOWING;
3667 /* DoM should be the first component in a mirror */
3669 args->lsa_rc = LSE_DOM_FIRST;
3675 if (comp->llc_pattern == LLAPI_LAYOUT_FOREIGN ||
3676 comp->llc_pattern == LOV_PATTERN_FOREIGN) {
3677 /* FOREING/HSM components can't be extension components */
3678 if (comp->llc_flags & LCME_FL_EXTENSION) {
3679 args->lsa_rc = LSE_FOREIGN_EXTENSION;
3684 /* Extent sanity checks */
3685 /* Must set previous component extent before adding another */
3686 if (prev && prev->llc_extent.e_start == 0 &&
3687 prev->llc_extent.e_end == 0) {
3688 args->lsa_rc = LSE_SET_COMP_START;
3692 if (!args->lsa_incomplete) {
3693 /* Components followed by extension space (extendable
3694 * components) must be zero length before initialization.
3695 * (Except for first comp, which will be initialized on
3697 if (next && (next->llc_flags & LCME_FL_EXTENSION) &&
3698 !first_comp && !(comp->llc_flags & LCME_FL_INIT) &&
3699 comp->llc_extent.e_start != comp->llc_extent.e_end) {
3700 args->lsa_rc = LSE_NOT_ZERO_LENGTH_EXTENDABLE;
3704 /* End must come after end of previous comp */
3705 if (prev && comp->llc_extent.e_end < prev->llc_extent.e_end) {
3706 args->lsa_rc = LSE_END_NOT_GREATER;
3710 /* Components not followed by ext space must have length > 0. */
3711 if (comp->llc_extent.e_start == comp->llc_extent.e_end &&
3712 (next == NULL || !(next->llc_flags & LCME_FL_EXTENSION))) {
3713 args->lsa_rc = LSE_ZERO_LENGTH_NORMAL;
3717 /* The component end must be aligned by the stripe size */
3718 if ((comp->llc_flags & LCME_FL_EXTENSION) &&
3719 (prev->llc_stripe_size != LLAPI_LAYOUT_DEFAULT)) {
3720 if (comp->llc_extent.e_end != LUSTRE_EOF &&
3721 comp->llc_extent.e_end % prev->llc_stripe_size) {
3722 args->lsa_rc = LSE_ALIGN_END;
3725 if ((comp->llc_stripe_size * SEL_UNIT_SIZE) %
3726 prev->llc_stripe_size) {
3727 args->lsa_rc = LSE_ALIGN_EXT;
3730 } else if (!(comp->llc_flags & LCME_FL_EXTENSION) &&
3731 (comp->llc_stripe_size != LLAPI_LAYOUT_DEFAULT)) {
3732 if (comp->llc_extent.e_end != LUSTRE_EOF &&
3733 comp->llc_extent.e_end !=
3734 comp->llc_extent.e_start &&
3735 comp->llc_extent.e_end % comp->llc_stripe_size) {
3736 args->lsa_rc = LSE_ALIGN_END;
3742 /* Components must have start == prev->end */
3743 if (prev && comp->llc_extent.e_start != 0 &&
3744 comp->llc_extent.e_start != prev->llc_extent.e_end) {
3745 args->lsa_rc = LSE_NOT_ADJACENT_PREV;
3749 /* Components must have start <= end */
3750 if (comp->llc_extent.e_start > comp->llc_extent.e_end) {
3751 args->lsa_rc = LSE_START_GT_END;
3755 return LLAPI_LAYOUT_ITER_CONT;
3758 errno = errno ? errno : EINVAL;
3759 return LLAPI_LAYOUT_ITER_STOP;
3762 /* Print explanation of layout error */
3763 void llapi_layout_sanity_perror(int error)
3765 if (error >= LSE_LAST || error < 0) {
3766 fprintf(stdout, "Invalid layout, unrecognized error: %d\n",
3769 fprintf(stdout, "Invalid layout: %s\n",
3770 llapi_layout_strerror[error]);
3774 /* Walk a layout and enforce sanity checks that apply to > 1 component
3776 * The core idea here is that of sanity checking individual tokens vs semantic
3778 * We cannot check everything at the individual component level ('token'),
3779 * instead we must check whether or not the full layout has a valid meaning.
3781 * An example of a component level check is "is stripe size valid?". That is
3782 * handled when setting stripe size.
3784 * An example of a layout level check is "are the extents of these components
3785 * valid when adjacent to one another", or "can we set these flags on adjacent
3788 * \param[in] layout component layout list.
3789 * \param[in] fname file the layout to be checked for
3790 * \param[in] incomplete if layout is complete or not - some checks can
3791 * only be done on complete layouts.
3792 * \param[in] flr set when this is called from FLR mirror create
3794 * \retval 0, success, positive: various errors, see
3795 * llapi_layout_sanity_perror, -1, failure
3798 int llapi_layout_sanity(struct llapi_layout *layout,
3799 bool incomplete, bool flr)
3801 return llapi_layout_v2_sanity(layout, incomplete, flr, NULL);
3804 /* This function has been introduced to do pool name checking
3805 * on top of llapi_layout_sanity, the file name passed in this
3806 * function is used later to verify if pool exist. The older version
3807 * of the sanity function is passing NULL for the filename
3808 * Input arguments ---
3809 * \param[in] layout component layout list.
3810 * \param[in] fname file the layout to be checked for
3811 * \param[in] incomplete if layout is complete or not - some checks can
3812 * only be done on complete layouts.
3813 * \param[in] flr set when this is called from FLR mirror create
3814 * \param[in] fsname filesystem name is used to check pool name, if
3815 * NULL no pool name check is performed
3817 * \retval 0, success, positive: various errors, see
3820 int llapi_layout_v2_sanity(struct llapi_layout *layout,
3821 bool incomplete, bool flr, char *fsname)
3823 struct llapi_layout_sanity_args args = { 0 };
3824 struct llapi_layout_comp *curr;
3830 curr = layout->llot_cur_comp;
3837 args.lsa_incomplete = incomplete;
3838 args.fsname = fsname;
3840 /* When we modify an existing layout, this tells us if it's FLR */
3841 if (mirror_id_of(curr->llc_id) > 0)
3842 args.lsa_flr = true;
3845 rc = llapi_layout_comp_iterate(layout,
3846 llapi_layout_sanity_cb,
3848 if (errno == ENOENT)
3851 if (rc != LLAPI_LAYOUT_ITER_CONT)
3854 layout->llot_cur_comp = curr;
3859 int llapi_layout_dom_size(struct llapi_layout *layout, uint64_t *size)
3861 uint64_t pattern, start;
3864 if (!layout || !llapi_layout_is_composite(layout)) {
3869 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_FIRST);
3873 rc = llapi_layout_pattern_get(layout, &pattern);
3877 if ((pattern & LLAPI_LAYOUT_INVALID) ||
3878 !(pattern & (LOV_PATTERN_MDT | LLAPI_LAYOUT_MDT))) {
3883 rc = llapi_layout_comp_extent_get(layout, &start, size);
3891 int lov_comp_md_size(struct lov_comp_md_v1 *lcm)
3893 if (lcm->lcm_magic == LOV_MAGIC_V1 || lcm->lcm_magic == LOV_MAGIC_V3) {
3894 struct lov_user_md *lum = (void *)lcm;
3896 return lov_user_md_size(lum->lmm_stripe_count, lum->lmm_magic);
3899 if (lcm->lcm_magic == LOV_MAGIC_FOREIGN) {
3900 struct lov_foreign_md *lfm = (void *)lcm;
3902 return lfm->lfm_length;
3905 if (lcm->lcm_magic != LOV_MAGIC_COMP_V1)
3908 return lcm->lcm_size;
3911 int llapi_get_lum_file_fd(int dir_fd, const char *fname, __u64 *valid,
3912 lstatx_t *statx, struct lov_user_md *lum,
3915 struct lov_user_mds_data *lmd;
3916 char buf[65536 + offsetof(typeof(*lmd), lmd_lmm)];
3920 if (lum && lumsize < sizeof(*lum))
3923 /* If a file name is provided, it is relative to the parent directory */
3929 lmd = (struct lov_user_mds_data *)buf;
3930 rc = get_lmd_info_fd(fname, parent_fd, dir_fd, buf, sizeof(buf),
3936 *valid = lmd->lmd_flags;
3939 memcpy(statx, &lmd->lmd_stx, sizeof(*statx));
3942 if (lmd->lmd_lmmsize > lumsize)
3944 memcpy(lum, &lmd->lmd_lmm, lmd->lmd_lmmsize);
3950 int llapi_get_lum_dir_fd(int dir_fd, __u64 *valid, lstatx_t *statx,
3951 struct lov_user_md *lum, size_t lumsize)
3953 return llapi_get_lum_file_fd(dir_fd, NULL, valid, statx, lum, lumsize);
3956 int llapi_get_lum_file(const char *path, __u64 *valid, lstatx_t *statx,
3957 struct lov_user_md *lum, size_t lumsize)
3959 char parent[PATH_MAX];
3966 tmp = strrchr(path, '/');
3968 strncpy(parent, ".", sizeof(parent) - 1);
3971 strncpy(parent, path, tmp - path);
3972 offset = tmp - path - 1;
3973 parent[tmp - path] = 0;
3978 fname += offset + 2;
3980 dir_fd = open(parent, O_RDONLY);
3983 llapi_error(LLAPI_MSG_ERROR, rc, "cannot open '%s'", path);
3987 rc = llapi_get_lum_file_fd(dir_fd, fname, valid, statx, lum, lumsize);
3992 int llapi_get_lum_dir(const char *path, __u64 *valid, lstatx_t *statx,
3993 struct lov_user_md *lum, size_t lumsize)
3998 dir_fd = open(path, O_RDONLY);
4001 llapi_error(LLAPI_MSG_ERROR, rc, "cannot open '%s'", path);
4005 rc = llapi_get_lum_dir_fd(dir_fd, valid, statx, lum, lumsize);