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;
1606 static int reset_index_cb(struct llapi_layout *layout, void *cbdata)
1608 int *save_errno = (int *)cbdata;
1611 rc = llapi_layout_ost_index_set(layout, 0, LLAPI_LAYOUT_DEFAULT);
1613 /* save the first error returned, but try to reset all components */
1614 if (rc && !*save_errno)
1615 *save_errno = errno;
1617 return LLAPI_LAYOUT_ITER_CONT;
1621 * Reset the OST index on all components in \a layout to LLAPI_LAYOUT_DEFAULT.
1623 * This is useful when reusing a file layout that was copied from an existing
1624 * file and to be used for a new file (e.g. when mirroring or migrating or
1625 * copying a file), so the objects are allocated on different OSTs.
1627 * \retval 0 Success.
1628 * \retval -ve errno Error with errno set to non-zero value.
1630 int llapi_layout_ost_index_reset(struct llapi_layout *layout)
1635 rc = llapi_layout_comp_iterate(layout, reset_index_cb, &save_errno);
1639 return save_errno ? -save_errno : (rc < 0 ? -errno : 0);
1643 * Get the OST index associated with stripe \a stripe_number.
1645 * Stripes are indexed starting from zero.
1647 * \param[in] layout layout to get index from
1648 * \param[in] stripe_number stripe number to get index for
1649 * \param[out] index integer to store index in
1651 * \retval 0 on success
1652 * \retval -1 if arguments are invalid
1654 int llapi_layout_ost_index_get(const struct llapi_layout *layout,
1655 uint64_t stripe_number, uint64_t *index)
1657 struct llapi_layout_comp *comp;
1659 comp = __llapi_layout_cur_comp(layout);
1663 if (comp->llc_pattern == LLAPI_LAYOUT_FOREIGN) {
1668 if (index == NULL) {
1673 if (stripe_number >= comp->llc_stripe_count ||
1674 stripe_number >= comp->llc_objects_count) {
1679 if (comp->llc_stripe_offset == LLAPI_LAYOUT_DEFAULT)
1680 *index = LLAPI_LAYOUT_DEFAULT;
1682 *index = comp->llc_objects[stripe_number].l_ost_idx;
1689 * Get the pool name of layout \a layout.
1691 * \param[in] layout layout to get pool name from
1692 * \param[out] dest buffer to store pool name in
1693 * \param[in] n size in bytes of buffer \a dest
1695 * \retval 0 on success
1696 * \retval -1 if arguments are invalid
1698 int llapi_layout_pool_name_get(const struct llapi_layout *layout, char *dest,
1701 struct llapi_layout_comp *comp;
1703 comp = __llapi_layout_cur_comp(layout);
1712 if (comp->llc_pattern == LLAPI_LAYOUT_FOREIGN) {
1717 strncpy(dest, comp->llc_pool_name, n);
1723 * Set the name of the pool of layout \a layout.
1725 * \param[in] layout layout to set pool name in
1726 * \param[in] pool_name pool name to set
1728 * \retval 0 on success
1729 * \retval -1 if arguments are invalid or pool name is too long
1731 int llapi_layout_pool_name_set(struct llapi_layout *layout,
1732 const char *pool_name)
1734 struct llapi_layout_comp *comp;
1736 comp = __llapi_layout_cur_comp(layout);
1740 if (!llapi_pool_name_is_valid(&pool_name)) {
1745 if (comp->llc_pattern == LLAPI_LAYOUT_FOREIGN) {
1750 strncpy(comp->llc_pool_name, pool_name, sizeof(comp->llc_pool_name));
1755 * Open and possibly create a file with a given \a layout.
1757 * If \a layout is NULL this function acts as a simple wrapper for
1758 * open(). By convention, ENOTTY is returned in errno if \a path
1759 * refers to a non-Lustre file.
1761 * \param[in] path name of the file to open
1762 * \param[in] open_flags open() flags
1763 * \param[in] mode permissions to create file, filtered by umask
1764 * \param[in] layout layout to create new file with
1766 * \retval non-negative file descriptor on successful open
1767 * \retval -1 if an error occurred
1769 int llapi_layout_file_open(const char *path, int open_flags, mode_t mode,
1770 const struct llapi_layout *layout)
1775 struct lov_user_md *lum;
1777 char fsname[MAX_OBD_NAME + 1] = { 0 };
1778 struct llapi_layout_comp *comp;
1780 comp = __llapi_layout_cur_comp(layout);
1783 (layout != NULL && layout->llot_magic != LLAPI_LAYOUT_MAGIC)) {
1789 /* Make sure we are on a Lustre file system */
1790 if (comp->llc_pool_name[0] != '\0' &&
1791 !lov_pool_is_ignored(comp->llc_pool_name)) {
1792 rc = llapi_search_fsname(path, fsname);
1798 rc = llapi_layout_v2_sanity((struct llapi_layout *)layout,
1800 !!(layout->llot_mirror_count > 1),
1803 llapi_layout_sanity_perror(rc);
1808 /* Object creation must be postponed until after layout attributes
1809 * have been applied. */
1810 if (layout != NULL && (open_flags & O_CREAT))
1811 open_flags |= O_LOV_DELAY_CREATE;
1813 fd = open(path, open_flags, mode);
1815 if (layout == NULL || fd < 0)
1818 lum = llapi_layout_to_lum(layout);
1827 if (lum->lmm_magic == LOV_USER_MAGIC_COMP_V1)
1828 lum_size = ((struct lov_comp_md_v1 *)lum)->lcm_size;
1829 else if (lum->lmm_magic == LOV_USER_MAGIC_SPECIFIC)
1830 lum_size = lov_user_md_size(lum->lmm_stripe_count,
1833 lum_size = lov_user_md_size(0, lum->lmm_magic);
1835 rc = fsetxattr(fd, XATTR_LUSTRE_LOV, lum, lum_size, 0);
1844 errno = errno == EOPNOTSUPP ? ENOTTY : errno;
1850 * Create a file with a given \a layout.
1852 * Force O_CREAT and O_EXCL flags on so caller is assured that file was
1853 * created with the given \a layout on successful function return.
1855 * \param[in] path name of the file to open
1856 * \param[in] open_flags open() flags
1857 * \param[in] mode permissions to create new file with
1858 * \param[in] layout layout to create new file with
1860 * \retval non-negative file descriptor on successful open
1861 * \retval -1 if an error occurred
1863 int llapi_layout_file_create(const char *path, int open_flags, int mode,
1864 const struct llapi_layout *layout)
1866 return llapi_layout_file_open(path, open_flags|O_CREAT|O_EXCL, mode,
1870 int llapi_layout_flags_get(struct llapi_layout *layout, uint32_t *flags)
1872 if (layout->llot_magic != LLAPI_LAYOUT_MAGIC) {
1877 *flags = layout->llot_flags;
1882 * Set flags to the header of a component layout.
1884 int llapi_layout_flags_set(struct llapi_layout *layout, uint32_t flags)
1886 if (layout->llot_magic != LLAPI_LAYOUT_MAGIC) {
1891 layout->llot_flags = flags;
1895 const char *llapi_layout_flags_string(uint32_t flags)
1897 switch (flags & LCM_FL_FLR_MASK) {
1900 case LCM_FL_WRITE_PENDING:
1902 case LCM_FL_SYNC_PENDING:
1904 case LCM_FL_RDONLY | LCM_FL_PCC_RDONLY:
1906 case LCM_FL_WRITE_PENDING | LCM_FL_PCC_RDONLY:
1908 case LCM_FL_SYNC_PENDING | LCM_FL_PCC_RDONLY:
1915 __u16 llapi_layout_string_flags(char *string)
1917 if (strncmp(string, "ro", strlen(string)) == 0)
1918 return LCM_FL_RDONLY;
1919 if (strncmp(string, "wp", strlen(string)) == 0)
1920 return LCM_FL_WRITE_PENDING;
1921 if (strncmp(string, "sp", strlen(string)) == 0)
1922 return LCM_FL_SYNC_PENDING;
1928 * llapi_layout_mirror_count_is_valid() - Check the validity of mirror count.
1929 * @count: Mirror count value to be checked.
1931 * This function checks the validity of mirror count.
1933 * Return: true on success or false on failure.
1935 static bool llapi_layout_mirror_count_is_valid(uint16_t count)
1937 return count >= 0 && count <= LUSTRE_MIRROR_COUNT_MAX;
1941 * llapi_layout_mirror_count_get() - Get mirror count from the header of
1943 * @layout: Layout to get mirror count from.
1944 * @count: Returned mirror count value.
1946 * This function gets mirror count from the header of a layout.
1948 * Return: 0 on success or -1 on failure.
1950 int llapi_layout_mirror_count_get(struct llapi_layout *layout,
1953 if (layout->llot_magic != LLAPI_LAYOUT_MAGIC) {
1958 *count = layout->llot_mirror_count;
1963 * llapi_layout_mirror_count_set() - Set mirror count to the header of a layout.
1964 * @layout: Layout to set mirror count in.
1965 * @count: Mirror count value to be set.
1967 * This function sets mirror count to the header of a layout.
1969 * Return: 0 on success or -1 on failure.
1971 int llapi_layout_mirror_count_set(struct llapi_layout *layout,
1974 if (layout->llot_magic != LLAPI_LAYOUT_MAGIC) {
1979 if (!llapi_layout_mirror_count_is_valid(count)) {
1984 layout->llot_mirror_count = count;
1989 * Fetch the start and end offset of the current layout component.
1991 * \param[in] layout the layout component
1992 * \param[out] start extent start, inclusive
1993 * \param[out] end extent end, exclusive
1995 * \retval 0 on success
1996 * \retval <0 if error occurs
1998 int llapi_layout_comp_extent_get(const struct llapi_layout *layout,
1999 uint64_t *start, uint64_t *end)
2001 struct llapi_layout_comp *comp;
2003 comp = __llapi_layout_cur_comp(layout);
2007 if (start == NULL || end == NULL) {
2012 *start = comp->llc_extent.e_start;
2013 *end = comp->llc_extent.e_end;
2019 * Set the layout extent of a layout.
2021 * \param[in] layout the layout to be set
2022 * \param[in] start extent start, inclusive
2023 * \param[in] end extent end, exclusive
2025 * \retval 0 on success
2026 * \retval <0 if error occurs
2028 int llapi_layout_comp_extent_set(struct llapi_layout *layout,
2029 uint64_t start, uint64_t end)
2031 struct llapi_layout_comp *comp;
2033 comp = __llapi_layout_cur_comp(layout);
2042 comp->llc_extent.e_start = start;
2043 comp->llc_extent.e_end = end;
2044 layout->llot_is_composite = true;
2050 * Gets the attribute flags of the current component.
2052 * \param[in] layout the layout component
2053 * \param[out] flags stored the returned component flags
2055 * \retval 0 on success
2056 * \retval <0 if error occurs
2058 int llapi_layout_comp_flags_get(const struct llapi_layout *layout,
2061 struct llapi_layout_comp *comp;
2063 comp = __llapi_layout_cur_comp(layout);
2067 if (flags == NULL) {
2072 *flags = comp->llc_flags;
2078 * Sets the specified flags of the current component leaving other flags as-is.
2080 * \param[in] layout the layout component
2081 * \param[in] flags component flags to be set
2083 * \retval 0 on success
2084 * \retval <0 if error occurs
2086 int llapi_layout_comp_flags_set(struct llapi_layout *layout, uint32_t flags)
2088 struct llapi_layout_comp *comp;
2090 comp = __llapi_layout_cur_comp(layout);
2094 comp->llc_flags |= flags;
2100 * Clears the flags specified in the flags leaving other flags as-is.
2102 * \param[in] layout the layout component
2103 * \param[in] flags component flags to be cleared
2105 * \retval 0 on success
2106 * \retval <0 if error occurs
2108 int llapi_layout_comp_flags_clear(struct llapi_layout *layout,
2111 struct llapi_layout_comp *comp;
2113 comp = __llapi_layout_cur_comp(layout);
2117 comp->llc_flags &= ~flags;
2123 * Fetches the file-unique component ID of the current layout component.
2125 * \param[in] layout the layout component
2126 * \param[out] id stored the returned component ID
2128 * \retval 0 on success
2129 * \retval <0 if error occurs
2131 int llapi_layout_comp_id_get(const struct llapi_layout *layout, uint32_t *id)
2133 struct llapi_layout_comp *comp;
2135 comp = __llapi_layout_cur_comp(layout);
2149 * Return the mirror id of the current layout component.
2151 * \param[in] layout the layout component
2152 * \param[out] id stored the returned mirror ID
2154 * \retval 0 on success
2155 * \retval <0 if error occurs
2157 int llapi_layout_mirror_id_get(const struct llapi_layout *layout, uint32_t *id)
2159 struct llapi_layout_comp *comp;
2161 comp = __llapi_layout_cur_comp(layout);
2170 *id = mirror_id_of(comp->llc_id);
2176 * Adds a component to \a layout, the new component will be added to
2177 * the tail of components list and it'll inherit attributes of existing
2178 * ones. The \a layout will change it's current component pointer to
2179 * the newly added component, and it'll be turned into a composite
2180 * layout if it was not before the adding.
2182 * \param[in] layout existing composite or plain layout
2184 * \retval 0 on success
2185 * \retval <0 if error occurs
2187 int llapi_layout_comp_add(struct llapi_layout *layout)
2189 struct llapi_layout_comp *last, *comp, *new;
2190 bool composite = layout->llot_is_composite;
2192 comp = __llapi_layout_cur_comp(layout);
2196 new = __llapi_comp_alloc(0);
2200 last = list_last_entry(&layout->llot_comp_list, typeof(*last),
2203 list_add_tail(&new->llc_list, &layout->llot_comp_list);
2205 /* We must mark the layout composite for the sanity check, but it may
2206 * not stay that way if the check fails */
2207 layout->llot_is_composite = true;
2208 layout->llot_cur_comp = new;
2210 /* We need to set a temporary non-zero value for "end" when we call
2211 * comp_extent_set, so we use LUSTRE_EOF-1, which is > all allowed
2212 * for the end of the previous component. (If we're adding this
2213 * component, the end of the previous component cannot be EOF.) */
2214 if (llapi_layout_comp_extent_set(layout, last->llc_extent.e_end,
2216 llapi_layout_comp_del(layout);
2217 layout->llot_is_composite = composite;
2224 * Adds a first component of a mirror to \a layout.
2225 * The \a layout will change it's current component pointer to
2226 * the newly added component, and it'll be turned into a composite
2227 * layout if it was not before the adding.
2229 * \param[in] layout existing composite or plain layout
2231 * \retval 0 on success
2232 * \retval <0 if error occurs
2234 int llapi_layout_add_first_comp(struct llapi_layout *layout)
2236 struct llapi_layout_comp *comp, *new;
2238 comp = __llapi_layout_cur_comp(layout);
2242 new = __llapi_comp_alloc(0);
2246 new->llc_extent.e_start = 0;
2248 list_add_tail(&new->llc_list, &layout->llot_comp_list);
2249 layout->llot_cur_comp = new;
2250 layout->llot_is_composite = true;
2256 * Deletes current component from the composite layout. The component
2257 * to be deleted must be the tail of components list, and it can't be
2258 * the only component in the layout.
2260 * \param[in] layout composite layout
2262 * \retval 0 on success
2263 * \retval <0 if error occurs
2265 int llapi_layout_comp_del(struct llapi_layout *layout)
2267 struct llapi_layout_comp *comp;
2269 comp = __llapi_layout_cur_comp(layout);
2273 if (!layout->llot_is_composite) {
2278 /* It must be the tail of the list (for PFL, can be relaxed
2279 * once we get mirrored components) */
2280 if (comp->llc_list.next != &layout->llot_comp_list) {
2284 layout->llot_cur_comp =
2285 list_last_entry(&comp->llc_list, typeof(*comp), llc_list);
2286 if (comp->llc_list.prev == &layout->llot_comp_list)
2287 layout->llot_cur_comp = NULL;
2289 list_del_init(&comp->llc_list);
2290 __llapi_comp_free(comp);
2296 * Move the current component pointer to the component with
2297 * specified component ID.
2299 * \param[in] layout composite layout
2300 * \param[in] id component ID
2302 * \retval =0 : moved successfully
2303 * \retval <0 if error occurs
2305 int llapi_layout_comp_use_id(struct llapi_layout *layout, uint32_t comp_id)
2307 struct llapi_layout_comp *comp;
2309 comp = __llapi_layout_cur_comp(layout);
2311 return -1; /* use previously set errno */
2313 if (!layout->llot_is_composite) {
2318 if (comp_id == LCME_ID_INVAL) {
2323 list_for_each_entry(comp, &layout->llot_comp_list, llc_list) {
2324 if (comp->llc_id == comp_id) {
2325 layout->llot_cur_comp = comp;
2334 * Move the current component pointer to a specified position.
2336 * \param[in] layout composite layout
2337 * \param[in] pos the position to be moved, it can be:
2338 * LLAPI_LAYOUT_COMP_USE_FIRST: use first component
2339 * LLAPI_LAYOUT_COMP_USE_LAST: use last component
2340 * LLAPI_LAYOUT_COMP_USE_NEXT: use component after current
2341 * LLAPI_LAYOUT_COMP_USE_PREV: use component before current
2343 * \retval =0 : moved successfully
2344 * \retval =1 : at last component with NEXT, at first component with PREV
2345 * \retval <0 if error occurs
2347 int llapi_layout_comp_use(struct llapi_layout *layout,
2348 enum llapi_layout_comp_use pos)
2350 struct llapi_layout_comp *comp, *head, *tail;
2352 comp = __llapi_layout_cur_comp(layout);
2356 if (!layout->llot_is_composite) {
2357 if (pos == LLAPI_LAYOUT_COMP_USE_FIRST ||
2358 pos == LLAPI_LAYOUT_COMP_USE_LAST)
2364 head = list_first_entry(&layout->llot_comp_list, typeof(*head),
2366 tail = list_last_entry(&layout->llot_comp_list, typeof(*tail),
2369 case LLAPI_LAYOUT_COMP_USE_FIRST:
2370 layout->llot_cur_comp = head;
2372 case LLAPI_LAYOUT_COMP_USE_NEXT:
2377 layout->llot_cur_comp = list_first_entry(&comp->llc_list,
2381 case LLAPI_LAYOUT_COMP_USE_LAST:
2382 layout->llot_cur_comp = tail;
2384 case LLAPI_LAYOUT_COMP_USE_PREV:
2389 layout->llot_cur_comp = list_last_entry(&comp->llc_list,
2402 * Add layout component(s) to an existing file.
2404 * \param[in] path The path name of the file
2405 * \param[in] layout The layout component(s) to be added
2407 int llapi_layout_file_comp_add(const char *path,
2408 const struct llapi_layout *layout)
2410 int rc, fd = -1, lum_size, tmp_errno = 0;
2411 struct llapi_layout *existing_layout = NULL;
2412 struct lov_user_md *lum = NULL;
2413 char fsname[MAX_OBD_NAME + 1] = { 0 };
2414 struct llapi_layout_comp *comp;
2416 if (path == NULL || layout == NULL ||
2417 layout->llot_magic != LLAPI_LAYOUT_MAGIC) {
2422 fd = open(path, O_RDWR);
2429 existing_layout = llapi_layout_get_by_fd(fd, 0);
2430 if (existing_layout == NULL) {
2436 rc = llapi_layout_merge(&existing_layout, layout);
2443 comp = __llapi_layout_cur_comp(layout);
2445 if (comp->llc_pool_name[0] != '\0' &&
2446 !lov_pool_is_ignored(comp->llc_pool_name)) {
2447 rc = llapi_search_fsname(path, fsname);
2455 rc = llapi_layout_v2_sanity(existing_layout, false, false, fsname);
2458 llapi_layout_sanity_perror(rc);
2463 lum = llapi_layout_to_lum(layout);
2470 if (lum->lmm_magic != LOV_USER_MAGIC_COMP_V1) {
2475 lum_size = ((struct lov_comp_md_v1 *)lum)->lcm_size;
2477 rc = fsetxattr(fd, XATTR_LUSTRE_LOV".add", lum, lum_size, 0);
2487 llapi_layout_free(existing_layout);
2493 * Delete component(s) by the specified component id or component flags
2494 * from an existing file.
2496 * \param[in] path path name of the file
2497 * \param[in] id unique component ID
2498 * \param[in] flags flags: LCME_FL_* or;
2499 * negative flags: (LCME_FL_NEG|LCME_FL_*)
2501 int llapi_layout_file_comp_del(const char *path, uint32_t id, uint32_t flags)
2503 int rc = 0, fd = -1, lum_size, tmp_errno = 0;
2504 struct llapi_layout *layout;
2505 struct llapi_layout_comp *comp, *next;
2506 struct llapi_layout *existing_layout = NULL;
2507 struct lov_user_md *lum = NULL;
2509 if (path == NULL || id > LCME_ID_MAX || (flags & ~LCME_KNOWN_FLAGS)) {
2514 /* Can only specify ID or flags, not both, not none. */
2515 if ((id != LCME_ID_INVAL && flags != 0) ||
2516 (id == LCME_ID_INVAL && flags == 0)) {
2521 layout = llapi_layout_alloc();
2525 llapi_layout_comp_extent_set(layout, 0, LUSTRE_EOF);
2526 comp = __llapi_layout_cur_comp(layout);
2534 comp->llc_flags = flags;
2536 lum = llapi_layout_to_lum(layout);
2542 lum_size = ((struct lov_comp_md_v1 *)lum)->lcm_size;
2544 fd = open(path, O_RDWR);
2551 existing_layout = llapi_layout_get_by_fd(fd, 0);
2552 if (existing_layout == NULL) {
2560 while (rc == 0 && existing_layout->llot_cur_comp != NULL) {
2561 rc = llapi_layout_comp_use(existing_layout, comp ?
2562 LLAPI_LAYOUT_COMP_USE_PREV :
2563 LLAPI_LAYOUT_COMP_USE_LAST);
2568 comp = __llapi_layout_cur_comp(existing_layout);
2574 if (id != LCME_ID_INVAL && id != comp->llc_id)
2576 else if ((flags & LCME_FL_NEG) && (flags & comp->llc_flags))
2578 else if (flags && !(flags & comp->llc_flags))
2581 rc = llapi_layout_comp_del(existing_layout);
2582 /* the layout position is moved to previous one, adjust */
2590 rc = llapi_layout_sanity(existing_layout, false, false);
2593 llapi_layout_sanity_perror(rc);
2598 rc = fsetxattr(fd, XATTR_LUSTRE_LOV".del", lum, lum_size, 0);
2609 llapi_layout_free(layout);
2610 llapi_layout_free(existing_layout);
2616 /* Internal utility function to apply flags for sanity checking */
2617 static void llapi_layout_comp_apply_flags(struct llapi_layout_comp *comp,
2620 if (flags & LCME_FL_NEG)
2621 comp->llc_flags &= ~flags;
2623 comp->llc_flags |= flags;
2626 struct llapi_layout_apply_flags_args {
2628 uint32_t *lfa_flags;
2634 static int llapi_layout_apply_flags_cb(struct llapi_layout *layout,
2637 struct llapi_layout_apply_flags_args *args = arg;
2638 struct llapi_layout_comp *comp;
2641 comp = __llapi_layout_cur_comp(layout);
2644 return LLAPI_LAYOUT_ITER_STOP;
2647 for (i = 0; i < args->lfa_count; i++) {
2648 if (comp->llc_id == args->lfa_ids[i])
2649 llapi_layout_comp_apply_flags(comp, args->lfa_flags[i]);
2652 return LLAPI_LAYOUT_ITER_CONT;
2655 /* Apply flags to the layout for sanity checking */
2656 static int llapi_layout_apply_flags(struct llapi_layout *layout, uint32_t *ids,
2657 uint32_t *flags, int count)
2659 struct llapi_layout_apply_flags_args args;
2662 if (!ids || !flags || count == 0) {
2668 args.lfa_flags = flags;
2669 args.lfa_count = count;
2672 rc = llapi_layout_comp_iterate(layout,
2673 llapi_layout_apply_flags_cb,
2675 if (errno == ENOENT)
2678 if (rc != LLAPI_LAYOUT_ITER_CONT)
2684 * Change flags by component ID of components of an existing file.
2685 * The component to be modified is specified by the comp->lcme_id value,
2686 * which must be a unique component ID.
2688 * \param[in] path path name of the file
2689 * \param[in] ids An array of component IDs
2690 * \param[in] flags flags: LCME_FL_* or;
2691 * negative flags: (LCME_FL_NEG|LCME_FL_*)
2692 * \param[in] count Number of elements in ids and flags array
2694 int llapi_layout_file_comp_set(const char *path, uint32_t *ids, uint32_t *flags,
2697 int rc = -1, fd = -1, i, tmp_errno = 0;
2699 struct llapi_layout *existing_layout = NULL;
2700 struct llapi_layout *layout = NULL;
2701 struct llapi_layout_comp *comp;
2702 struct lov_user_md *lum = NULL;
2703 char fsname[MAX_OBD_NAME + 1] = { 0 };
2713 for (i = 0; i < count; i++) {
2714 if (!ids[i] || !flags[i]) {
2719 if (ids[i] > LCME_ID_MAX || (flags[i] & ~LCME_KNOWN_FLAGS)) {
2724 /* do not allow to set or clear INIT flag */
2725 if (flags[i] & LCME_FL_INIT) {
2731 fd = open(path, O_RDWR);
2738 existing_layout = llapi_layout_get_by_fd(fd, 0);
2739 if (existing_layout == NULL) {
2745 if (llapi_layout_apply_flags(existing_layout, ids, flags, count)) {
2751 comp = __llapi_layout_cur_comp(layout);
2753 if (comp && comp->llc_pool_name[0] != '\0' &&
2754 !lov_pool_is_ignored(comp->llc_pool_name)) {
2755 rc = llapi_search_fsname(path, fsname);
2763 rc = llapi_layout_v2_sanity(existing_layout, false, false, fsname);
2766 llapi_layout_sanity_perror(rc);
2771 layout = __llapi_layout_alloc();
2772 if (layout == NULL) {
2778 layout->llot_is_composite = true;
2779 for (i = 0; i < count; i++) {
2780 comp = __llapi_comp_alloc(0);
2787 comp->llc_id = ids[i];
2788 comp->llc_flags = flags[i];
2790 list_add_tail(&comp->llc_list, &layout->llot_comp_list);
2791 layout->llot_cur_comp = comp;
2794 lum = llapi_layout_to_lum(layout);
2801 lum_size = ((struct lov_comp_md_v1 *)lum)->lcm_size;
2803 /* flush cached pages from clients */
2804 rc = llapi_file_flush(fd);
2811 rc = fsetxattr(fd, XATTR_LUSTRE_LOV".set.flags", lum, lum_size, 0);
2824 llapi_layout_free(existing_layout);
2825 llapi_layout_free(layout);
2831 * Check if the file layout is composite.
2833 * \param[in] layout the file layout to check
2835 * \retval true composite
2836 * \retval false not composite
2838 bool llapi_layout_is_composite(struct llapi_layout *layout)
2840 return layout->llot_is_composite;
2844 * Iterate every components in the @layout and call callback function @cb.
2846 * \param[in] layout component layout list.
2847 * \param[in] cb callback function called for each component
2848 * \param[in] cbdata callback data passed to the callback function
2850 * \retval < 0 error happens during the iteration
2851 * \retval LLAPI_LAYOUT_ITER_CONT finished the iteration w/o error
2852 * \retval LLAPI_LAYOUT_ITER_STOP got something, stop the iteration
2854 int llapi_layout_comp_iterate(struct llapi_layout *layout,
2855 llapi_layout_iter_cb cb, void *cbdata)
2859 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_FIRST);
2864 * make sure on success llapi_layout_comp_use() API returns 0 with
2870 rc = cb(layout, cbdata);
2871 if (rc != LLAPI_LAYOUT_ITER_CONT)
2874 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_NEXT);
2877 else if (rc == 1) /* reached the last comp */
2878 return LLAPI_LAYOUT_ITER_CONT;
2885 * llapi_layout_merge() - Merge a composite layout into another one.
2886 * @dst_layout: Destination composite layout.
2887 * @src_layout: Source composite layout.
2889 * This function copies all of the components from @src_layout and
2890 * appends them to @dst_layout.
2892 * Return: 0 on success or -1 on failure.
2894 int llapi_layout_merge(struct llapi_layout **dst_layout,
2895 const struct llapi_layout *src_layout)
2897 struct llapi_layout *new_layout = *dst_layout;
2898 struct llapi_layout_comp *new = NULL;
2899 struct llapi_layout_comp *comp = NULL;
2902 if (src_layout == NULL ||
2903 list_empty((struct list_head *)&src_layout->llot_comp_list))
2906 if (new_layout == NULL) {
2907 new_layout = __llapi_layout_alloc();
2908 if (new_layout == NULL) {
2914 list_for_each_entry(comp, &src_layout->llot_comp_list, llc_list) {
2915 new = __llapi_comp_alloc(0);
2921 new->llc_pattern = comp->llc_pattern;
2922 new->llc_stripe_size = comp->llc_stripe_size;
2923 new->llc_stripe_count = comp->llc_stripe_count;
2924 new->llc_stripe_offset = comp->llc_stripe_offset;
2926 if (comp->llc_pool_name[0] != '\0')
2927 strncpy(new->llc_pool_name, comp->llc_pool_name,
2928 sizeof(new->llc_pool_name));
2930 for (i = 0; i < comp->llc_objects_count; i++) {
2931 if (__llapi_comp_objects_realloc(new,
2932 stripe_number_roundup(i)) < 0) {
2934 __llapi_comp_free(new);
2937 new->llc_objects[i].l_ost_idx = \
2938 comp->llc_objects[i].l_ost_idx;
2941 new->llc_objects_count = comp->llc_objects_count;
2942 new->llc_extent.e_start = comp->llc_extent.e_start;
2943 new->llc_extent.e_end = comp->llc_extent.e_end;
2944 new->llc_id = comp->llc_id;
2945 new->llc_flags = comp->llc_flags;
2947 list_add_tail(&new->llc_list, &new_layout->llot_comp_list);
2948 new_layout->llot_cur_comp = new;
2950 new_layout->llot_is_composite = true;
2952 *dst_layout = new_layout;
2955 llapi_layout_free(new_layout);
2960 * Get the last initialized component
2962 * \param[in] layout component layout list.
2965 * \retval -EINVAL not found
2966 * \retval -EISDIR directory layout
2968 int llapi_layout_get_last_init_comp(struct llapi_layout *layout)
2970 struct llapi_layout_comp *comp = NULL, *head = NULL;
2972 if (!layout->llot_is_composite)
2975 head = list_first_entry(&layout->llot_comp_list, typeof(*comp),
2979 if (head->llc_id == 0 && !(head->llc_flags & LCME_FL_INIT))
2983 /* traverse the components from the tail to find the last init one */
2984 comp = list_last_entry(&layout->llot_comp_list, typeof(*comp),
2986 while (comp != head) {
2987 if (comp->llc_flags & LCME_FL_INIT)
2989 comp = list_last_entry(&comp->llc_list, typeof(*comp),
2993 layout->llot_cur_comp = comp;
2995 return comp->llc_flags & LCME_FL_INIT ? 0 : -EINVAL;
2999 * Interit stripe info from the file's component to the mirror
3001 * \param[in] layout file component layout list.
3002 * \param[in] layout mirro component layout list.
3004 * \retval 0 on success
3005 * \retval -EINVAL on error
3007 int llapi_layout_mirror_inherit(struct llapi_layout *f_layout,
3008 struct llapi_layout *m_layout)
3010 struct llapi_layout_comp *m_comp = NULL;
3011 struct llapi_layout_comp *f_comp = NULL;
3014 f_comp = __llapi_layout_cur_comp(f_layout);
3017 m_comp = __llapi_layout_cur_comp(m_layout);
3021 /* DoM component does not inherit stripe size */
3022 if (m_comp->llc_pattern != LLAPI_LAYOUT_MDT)
3023 m_comp->llc_stripe_size = f_comp->llc_stripe_size;
3024 m_comp->llc_stripe_count = f_comp->llc_stripe_count;
3030 * Find all stale components.
3032 * \param[in] layout component layout list.
3033 * \param[out] comp array of stale component info.
3034 * \param[in] comp_size array size of @comp.
3035 * \param[in] mirror_ids array of mirror id that only components
3036 * belonging to these mirror will be collected.
3037 * \param[in] ids_nr number of mirror ids array.
3039 * \retval number of component info collected on success or
3040 * an error code on failure.
3042 int llapi_mirror_find_stale(struct llapi_layout *layout,
3043 struct llapi_resync_comp *comp, size_t comp_size,
3044 __u16 *mirror_ids, int ids_nr)
3049 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_FIRST);
3057 uint64_t start, end;
3059 rc = llapi_layout_comp_flags_get(layout, &flags);
3063 if (!(flags & LCME_FL_STALE))
3066 rc = llapi_layout_mirror_id_get(layout, &mirror_id);
3070 /* the caller only wants stale components from specific
3075 for (j = 0; j < ids_nr; j++) {
3076 if (mirror_ids[j] == mirror_id)
3080 /* not in the specified mirror */
3083 } else if (flags & LCME_FL_NOSYNC) {
3084 /* if not specified mirrors, do not resync "nosync"
3089 rc = llapi_layout_comp_id_get(layout, &id);
3093 rc = llapi_layout_comp_extent_get(layout, &start, &end);
3097 /* pack this component into @comp array */
3098 comp[idx].lrc_id = id;
3099 comp[idx].lrc_mirror_id = mirror_id;
3100 comp[idx].lrc_start = start;
3101 comp[idx].lrc_end = end;
3104 if (idx >= comp_size) {
3110 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_NEXT);
3117 return rc < 0 ? rc : idx;
3120 /* locate @layout to a valid component covering file [file_start, file_end) */
3121 int llapi_mirror_find(struct llapi_layout *layout, uint64_t file_start,
3122 uint64_t file_end, uint64_t *endp)
3124 uint32_t mirror_id = 0;
3127 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_FIRST);
3133 uint64_t start, end;
3134 uint32_t flags, id, rid;
3136 rc = llapi_layout_comp_flags_get(layout, &flags);
3140 if (flags & LCME_FL_STALE)
3143 rc = llapi_layout_mirror_id_get(layout, &rid);
3147 rc = llapi_layout_comp_id_get(layout, &id);
3151 rc = llapi_layout_comp_extent_get(layout, &start, &end);
3155 if (file_start >= start && file_start < end) {
3158 else if (mirror_id != rid || *endp != start)
3161 file_start = *endp = end;
3162 if (end >= file_end)
3167 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_NEXT);
3177 #ifndef NSEC_PER_SEC
3178 # define NSEC_PER_SEC 1000000000UL
3180 #define ONE_MB 0x100000
3181 static struct timespec timespec_sub(struct timespec *before,
3182 struct timespec *after)
3184 struct timespec ret;
3186 ret.tv_sec = after->tv_sec - before->tv_sec;
3187 if (after->tv_nsec < before->tv_nsec) {
3189 ret.tv_nsec = NSEC_PER_SEC + after->tv_nsec - before->tv_nsec;
3191 ret.tv_nsec = after->tv_nsec - before->tv_nsec;
3197 static void stats_log(struct timespec *now, struct timespec *start_time,
3198 ssize_t read_bytes, size_t write_bytes,
3199 off_t file_size_bytes)
3201 struct timespec diff = timespec_sub(start_time, now);
3203 if (file_size_bytes == 0)
3206 if (diff.tv_sec == 0 && diff.tv_nsec == 0)
3209 llapi_printf(LLAPI_MSG_NORMAL,
3210 "- { seconds: %li, rmbps: %5.2g, wmbps: %5.2g, copied: %lu, size: %lu, pct: %lu%% }\n",
3212 (double) read_bytes/((ONE_MB * diff.tv_sec) +
3213 ((ONE_MB * diff.tv_nsec)/NSEC_PER_SEC)),
3214 (double) write_bytes/((ONE_MB * diff.tv_sec) +
3215 ((ONE_MB * diff.tv_nsec)/NSEC_PER_SEC)),
3217 file_size_bytes/ONE_MB,
3218 ((write_bytes*100)/file_size_bytes));
3221 int llapi_mirror_resync_many_params(int fd, struct llapi_layout *layout,
3222 struct llapi_resync_comp *comp_array,
3223 int comp_size, uint64_t start,
3225 unsigned long stats_interval_sec,
3226 unsigned long bandwidth_bytes_sec)
3228 size_t buflen = 64 << 20; /* 64M */
3231 uint64_t pos = start;
3232 uint64_t data_off = pos, data_end = pos;
3233 uint64_t mirror_end = LUSTRE_EOF;
3238 struct timespec start_time;
3239 struct timespec now;
3240 struct timespec last_bw_print;
3241 size_t total_bytes_read = 0;
3242 size_t total_bytes_written = 0;
3243 off_t write_estimation_bytes = 0;
3245 if (bandwidth_bytes_sec > 0 || stats_interval_sec) {
3248 rc = fstat(fd, &st);
3251 write_estimation_bytes = st.st_size * comp_size;
3254 /* limit transfer size to what can be sent in one second */
3255 if (bandwidth_bytes_sec && bandwidth_bytes_sec < buflen)
3256 buflen = (bandwidth_bytes_sec + ONE_MB - 1) & ~(ONE_MB - 1);
3258 page_size = sysconf(_SC_PAGESIZE);
3259 if (page_size < 0) {
3264 rc = posix_memalign(&buf, page_size, buflen);
3268 clock_gettime(CLOCK_MONOTONIC, &start_time);
3269 now = last_bw_print = start_time;
3277 if (pos >= data_end) {
3280 if (pos >= mirror_end || !src) {
3281 rc = llapi_mirror_find(layout, pos, end,
3288 /* restrict mirror end by resync end */
3289 mirror_end = MIN(end, mirror_end);
3292 tmp_off = llapi_mirror_data_seek(fd, src, pos,
3295 /* switch to full copy */
3296 to_read = mirror_end - pos;
3300 data_end = data_off + data_size;
3302 data_off = MIN(data_off, mirror_end);
3303 data_end = MIN(data_end, mirror_end);
3305 /* align by page, if there is data block to copy */
3307 data_off &= ~(page_size - 1);
3310 if (pos < data_off) {
3311 for (i = 0; i < comp_size; i++) {
3314 uint32_t mid = comp_array[i].lrc_mirror_id;
3316 /* skip non-overlapped component */
3317 if (pos >= comp_array[i].lrc_end ||
3318 data_off <= comp_array[i].lrc_start)
3321 if (pos < comp_array[i].lrc_start)
3322 cur_pos = comp_array[i].lrc_start;
3326 if (data_off > comp_array[i].lrc_end)
3327 to_punch = comp_array[i].lrc_end -
3330 to_punch = data_off - cur_pos;
3332 if (comp_array[i].lrc_end == OBD_OBJECT_EOF)
3333 /* the last component can be truncated
3336 rc = llapi_mirror_truncate(fd, mid,
3339 rc = llapi_mirror_punch(fd, mid,
3342 * hole at the end of file, so just truncate up
3345 if (!rc && data_off == data_end && !data_size)
3346 rc = llapi_mirror_truncate(fd,
3348 /* if failed then read failed hole range */
3352 if (pos + to_punch == data_off)
3353 to_read = data_end - pos;
3361 if (pos == mirror_end)
3363 to_read = data_end - pos;
3368 assert(data_end <= mirror_end);
3370 to_read = MIN(buflen, to_read);
3371 to_read = ((to_read - 1) | (page_size - 1)) + 1;
3372 bytes_read = llapi_mirror_read(fd, src, buf, to_read, pos);
3373 if (bytes_read == 0) {
3377 if (bytes_read < 0) {
3381 total_bytes_read += bytes_read;
3383 /* round up to page align to make direct IO happy. */
3384 to_write = ((bytes_read - 1) | (page_size - 1)) + 1;
3386 for (i = 0; i < comp_size; i++) {
3387 unsigned long long write_target;
3388 struct timespec diff;
3391 size_t to_write2 = to_write;
3393 /* skip non-overlapped component */
3394 if (pos >= comp_array[i].lrc_end ||
3395 pos + to_write <= comp_array[i].lrc_start)
3398 if (pos < comp_array[i].lrc_start)
3399 pos2 = comp_array[i].lrc_start;
3401 to_write2 -= pos2 - pos;
3403 if ((pos + to_write) > comp_array[i].lrc_end)
3404 to_write2 -= pos + to_write -
3405 comp_array[i].lrc_end;
3407 written = llapi_mirror_write(fd,
3408 comp_array[i].lrc_mirror_id,
3413 * this component is not written successfully,
3414 * mark it using its lrc_synced, it is supposed
3415 * to be false before getting here.
3417 * And before this function returns, all
3418 * elements of comp_array will reverse their
3419 * lrc_synced flag to reflect their true
3422 comp_array[i].lrc_synced = true;
3423 llapi_error(LLAPI_MSG_ERROR, written,
3424 "component %u not synced",
3425 comp_array[i].lrc_id);
3430 assert(written == to_write2);
3431 total_bytes_written += written;
3433 if (bandwidth_bytes_sec == 0)
3436 clock_gettime(CLOCK_MONOTONIC, &now);
3437 diff = timespec_sub(&start_time, &now);
3438 write_target = ((bandwidth_bytes_sec * diff.tv_sec) +
3439 ((bandwidth_bytes_sec *
3440 diff.tv_nsec)/NSEC_PER_SEC));
3442 if (write_target < total_bytes_written) {
3443 unsigned long long excess;
3444 struct timespec delay = { 0, 0 };
3446 excess = total_bytes_written - write_target;
3451 delay.tv_sec = excess / bandwidth_bytes_sec;
3452 delay.tv_nsec = (excess % bandwidth_bytes_sec) *
3453 NSEC_PER_SEC / bandwidth_bytes_sec;
3456 rc = clock_nanosleep(CLOCK_MONOTONIC, 0,
3458 } while (rc < 0 && errno == EINTR);
3461 llapi_error(LLAPI_MSG_ERROR, rc,
3462 "errors: delay for bandwidth control failed: %s\n",
3468 if (stats_interval_sec) {
3469 clock_gettime(CLOCK_MONOTONIC, &now);
3470 if ((total_bytes_written != end - start) &&
3471 (now.tv_sec >= last_bw_print.tv_sec +
3472 stats_interval_sec)) {
3473 stats_log(&now, &start_time,
3475 total_bytes_written,
3476 write_estimation_bytes);
3477 last_bw_print = now;
3487 /* fatal error happens */
3488 for (i = 0; i < comp_size; i++)
3489 comp_array[i].lrc_synced = false;
3493 /* Output at least one log, regardless of stats_interval */
3494 if (stats_interval_sec) {
3495 clock_gettime(CLOCK_MONOTONIC, &now);
3496 stats_log(&now, &start_time, total_bytes_read,
3497 total_bytes_written,
3498 write_estimation_bytes);
3502 * no fatal error happens, each lrc_synced tells whether the component
3503 * has been resync successfully (note: we'd reverse the value to
3504 * reflect its true meaning.
3506 for (i = 0; i < comp_size; i++) {
3507 comp_array[i].lrc_synced = !comp_array[i].lrc_synced;
3508 if (comp_array[i].lrc_synced && pos & (page_size - 1)) {
3509 rc = llapi_mirror_truncate(fd,
3510 comp_array[i].lrc_mirror_id, pos);
3511 /* Ignore truncate error on encrypted file without the
3512 * key if tried on LUSTRE_ENCRYPTION_UNIT_SIZE boundary.
3514 if (rc < 0 && (rc != -ENOKEY ||
3515 pos & ~LUSTRE_ENCRYPTION_MASK))
3516 comp_array[i].lrc_synced = false;
3521 * returns the first error code for partially successful resync if
3527 int llapi_mirror_resync_many(int fd, struct llapi_layout *layout,
3528 struct llapi_resync_comp *comp_array,
3529 int comp_size, uint64_t start, uint64_t end)
3531 return llapi_mirror_resync_many_params(fd, layout, comp_array,
3532 comp_size, start, end, 0, 0);
3535 enum llapi_layout_comp_sanity_error {
3537 LSE_INCOMPLETE_MIRROR,
3538 LSE_ADJACENT_EXTENSION,
3542 LSE_DOM_EXTENSION_FOLLOWING,
3545 LSE_NOT_ZERO_LENGTH_EXTENDABLE,
3546 LSE_END_NOT_GREATER,
3547 LSE_ZERO_LENGTH_NORMAL,
3548 LSE_NOT_ADJACENT_PREV,
3552 LSE_FOREIGN_EXTENSION,
3556 const char *const llapi_layout_strerror[] =
3559 [LSE_INCOMPLETE_MIRROR] =
3560 "Incomplete mirror - must go to EOF",
3561 [LSE_ADJACENT_EXTENSION] =
3562 "No adjacent extension space components",
3563 [LSE_INIT_EXTENSION] =
3564 "Cannot apply extension flag to init components",
3567 [LSE_DOM_EXTENSION] =
3568 "DoM components can't be extension space",
3569 [LSE_DOM_EXTENSION_FOLLOWING] =
3570 "DoM components cannot be followed by extension space",
3572 "DoM component should be the first one in a file/mirror",
3573 [LSE_SET_COMP_START] =
3574 "Must set previous component extent before adding next",
3575 [LSE_NOT_ZERO_LENGTH_EXTENDABLE] =
3576 "Extendable component must start out zero-length",
3577 [LSE_END_NOT_GREATER] =
3578 "Component end is before end of previous component",
3579 [LSE_ZERO_LENGTH_NORMAL] =
3580 "Zero length components must be followed by extension",
3581 [LSE_NOT_ADJACENT_PREV] =
3582 "Components not adjacent (end != next->start",
3583 [LSE_START_GT_END] =
3584 "Component start is > end",
3586 "The component end must be aligned by the stripe size",
3588 "The extension size must be aligned by the stripe size",
3589 [LSE_FOREIGN_EXTENSION] =
3590 "FOREIGN components can't be extension space",
3593 struct llapi_layout_sanity_args {
3594 bool lsa_incomplete;
3601 /* The component flags can be set by users at creation/modification time. */
3602 #define LCME_USER_COMP_FLAGS (LCME_FL_PREF_RW | LCME_FL_NOSYNC | \
3605 /* Inline function to verify the pool name */
3606 static inline int verify_pool_name(char *fsname, struct llapi_layout *layout)
3608 struct llapi_layout_comp *comp;
3610 if (!fsname || fsname[0] == '\0')
3613 comp = __llapi_layout_cur_comp(layout);
3616 if (comp->llc_pool_name[0] == '\0' ||
3617 lov_pool_is_ignored(comp->llc_pool_name))
3619 /* check if the pool name exist */
3620 if (llapi_search_ost(fsname, comp->llc_pool_name, NULL) < 0)
3626 * When modified, adjust llapi_stripe_param_verify() if needed as well.
3628 static int llapi_layout_sanity_cb(struct llapi_layout *layout,
3631 struct llapi_layout_comp *comp, *next, *prev;
3632 struct llapi_layout_sanity_args *args = arg;
3633 bool first_comp = false;
3635 comp = __llapi_layout_cur_comp(layout);
3641 if (verify_pool_name(args->fsname, layout) != 0) {
3646 if (comp->llc_list.prev != &layout->llot_comp_list)
3647 prev = list_last_entry(&comp->llc_list, typeof(*prev),
3652 if (comp->llc_list.next != &layout->llot_comp_list)
3653 next = list_first_entry(&comp->llc_list, typeof(*next),
3658 /* Start of zero implies a new mirror */
3659 if (comp->llc_extent.e_start == 0) {
3661 /* Most checks apply only within one mirror, this is an
3663 if (prev && prev->llc_extent.e_end != LUSTRE_EOF) {
3664 args->lsa_rc = LSE_INCOMPLETE_MIRROR;
3671 if (next && next->llc_extent.e_start == 0)
3674 /* Flag sanity checks */
3675 /* No adjacent extension components */
3676 if ((comp->llc_flags & LCME_FL_EXTENSION) && next &&
3677 (next->llc_flags & LCME_FL_EXTENSION)) {
3678 args->lsa_rc = LSE_ADJACENT_EXTENSION;
3682 /* Extension flag cannot be applied to init components and the first
3683 * component of each mirror is automatically init */
3684 if ((comp->llc_flags & LCME_FL_EXTENSION) &&
3685 (comp->llc_flags & LCME_FL_INIT || first_comp)) {
3686 args->lsa_rc = LSE_INIT_EXTENSION;
3690 if (comp->llc_ondisk) {
3691 if (comp->llc_flags & LCME_FL_NEG)
3692 args->lsa_rc = LSE_FLAGS;
3693 } else if (!args->lsa_incomplete) {
3694 if (args->lsa_flr) {
3695 if (comp->llc_flags & ~LCME_USER_COMP_FLAGS)
3696 args->lsa_rc = LSE_FLAGS;
3698 if (comp->llc_flags &
3699 ~(LCME_FL_EXTENSION | LCME_FL_PREF_RW |
3701 args->lsa_rc = LSE_FLAGS;
3707 /* DoM sanity checks */
3708 if (!(comp->llc_pattern & LLAPI_LAYOUT_INVALID) &&
3709 (comp->llc_pattern & (LLAPI_LAYOUT_MDT | LOV_PATTERN_MDT))) {
3710 /* DoM components can't be extension components */
3711 if (comp->llc_flags & LCME_FL_EXTENSION) {
3712 args->lsa_rc = LSE_DOM_EXTENSION;
3715 /* DoM components cannot be followed by an extension comp */
3716 if (next && (next->llc_flags & LCME_FL_EXTENSION)) {
3717 args->lsa_rc = LSE_DOM_EXTENSION_FOLLOWING;
3721 /* DoM should be the first component in a mirror */
3723 args->lsa_rc = LSE_DOM_FIRST;
3729 if (comp->llc_pattern == LLAPI_LAYOUT_FOREIGN ||
3730 comp->llc_pattern == LOV_PATTERN_FOREIGN) {
3731 /* FOREING/HSM components can't be extension components */
3732 if (comp->llc_flags & LCME_FL_EXTENSION) {
3733 args->lsa_rc = LSE_FOREIGN_EXTENSION;
3738 /* Extent sanity checks */
3739 /* Must set previous component extent before adding another */
3740 if (prev && prev->llc_extent.e_start == 0 &&
3741 prev->llc_extent.e_end == 0) {
3742 args->lsa_rc = LSE_SET_COMP_START;
3746 if (!args->lsa_incomplete) {
3747 /* Components followed by extension space (extendable
3748 * components) must be zero length before initialization.
3749 * (Except for first comp, which will be initialized on
3751 if (next && (next->llc_flags & LCME_FL_EXTENSION) &&
3752 !first_comp && !(comp->llc_flags & LCME_FL_INIT) &&
3753 comp->llc_extent.e_start != comp->llc_extent.e_end) {
3754 args->lsa_rc = LSE_NOT_ZERO_LENGTH_EXTENDABLE;
3758 /* End must come after end of previous comp */
3759 if (prev && comp->llc_extent.e_end < prev->llc_extent.e_end) {
3760 args->lsa_rc = LSE_END_NOT_GREATER;
3764 /* Components not followed by ext space must have length > 0. */
3765 if (comp->llc_extent.e_start == comp->llc_extent.e_end &&
3766 (next == NULL || !(next->llc_flags & LCME_FL_EXTENSION))) {
3767 args->lsa_rc = LSE_ZERO_LENGTH_NORMAL;
3771 /* The component end must be aligned by the stripe size */
3772 if ((comp->llc_flags & LCME_FL_EXTENSION) &&
3773 (prev->llc_stripe_size != LLAPI_LAYOUT_DEFAULT)) {
3774 if (comp->llc_extent.e_end != LUSTRE_EOF &&
3775 comp->llc_extent.e_end % prev->llc_stripe_size) {
3776 args->lsa_rc = LSE_ALIGN_END;
3779 if ((comp->llc_stripe_size * SEL_UNIT_SIZE) %
3780 prev->llc_stripe_size) {
3781 args->lsa_rc = LSE_ALIGN_EXT;
3784 } else if (!(comp->llc_flags & LCME_FL_EXTENSION) &&
3785 (comp->llc_stripe_size != LLAPI_LAYOUT_DEFAULT)) {
3786 if (comp->llc_extent.e_end != LUSTRE_EOF &&
3787 comp->llc_extent.e_end !=
3788 comp->llc_extent.e_start &&
3789 comp->llc_extent.e_end % comp->llc_stripe_size) {
3790 args->lsa_rc = LSE_ALIGN_END;
3796 /* Components must have start == prev->end */
3797 if (prev && comp->llc_extent.e_start != 0 &&
3798 comp->llc_extent.e_start != prev->llc_extent.e_end) {
3799 args->lsa_rc = LSE_NOT_ADJACENT_PREV;
3803 /* Components must have start <= end */
3804 if (comp->llc_extent.e_start > comp->llc_extent.e_end) {
3805 args->lsa_rc = LSE_START_GT_END;
3809 return LLAPI_LAYOUT_ITER_CONT;
3812 errno = errno ? errno : EINVAL;
3813 return LLAPI_LAYOUT_ITER_STOP;
3816 /* Print explanation of layout error */
3817 void llapi_layout_sanity_perror(int error)
3819 if (error >= LSE_LAST || error < 0) {
3820 fprintf(stdout, "Invalid layout, unrecognized error: %d\n",
3823 fprintf(stdout, "Invalid layout: %s\n",
3824 llapi_layout_strerror[error]);
3828 /* Walk a layout and enforce sanity checks that apply to > 1 component
3830 * The core idea here is that of sanity checking individual tokens vs semantic
3832 * We cannot check everything at the individual component level ('token'),
3833 * instead we must check whether or not the full layout has a valid meaning.
3835 * An example of a component level check is "is stripe size valid?". That is
3836 * handled when setting stripe size.
3838 * An example of a layout level check is "are the extents of these components
3839 * valid when adjacent to one another", or "can we set these flags on adjacent
3842 * \param[in] layout component layout list.
3843 * \param[in] fname file the layout to be checked for
3844 * \param[in] incomplete if layout is complete or not - some checks can
3845 * only be done on complete layouts.
3846 * \param[in] flr set when this is called from FLR mirror create
3848 * \retval 0, success, positive: various errors, see
3849 * llapi_layout_sanity_perror, -1, failure
3852 int llapi_layout_sanity(struct llapi_layout *layout,
3853 bool incomplete, bool flr)
3855 return llapi_layout_v2_sanity(layout, incomplete, flr, NULL);
3858 /* This function has been introduced to do pool name checking
3859 * on top of llapi_layout_sanity, the file name passed in this
3860 * function is used later to verify if pool exist. The older version
3861 * of the sanity function is passing NULL for the filename
3862 * Input arguments ---
3863 * \param[in] layout component layout list.
3864 * \param[in] fname file the layout to be checked for
3865 * \param[in] incomplete if layout is complete or not - some checks can
3866 * only be done on complete layouts.
3867 * \param[in] flr set when this is called from FLR mirror create
3868 * \param[in] fsname filesystem name is used to check pool name, if
3869 * NULL no pool name check is performed
3871 * \retval 0, success, positive: various errors, see
3874 int llapi_layout_v2_sanity(struct llapi_layout *layout,
3875 bool incomplete, bool flr, char *fsname)
3877 struct llapi_layout_sanity_args args = { 0 };
3878 struct llapi_layout_comp *curr;
3884 curr = layout->llot_cur_comp;
3891 args.lsa_incomplete = incomplete;
3892 args.fsname = fsname;
3894 /* When we modify an existing layout, this tells us if it's FLR */
3895 if (mirror_id_of(curr->llc_id) > 0)
3896 args.lsa_flr = true;
3899 rc = llapi_layout_comp_iterate(layout,
3900 llapi_layout_sanity_cb,
3902 if (errno == ENOENT)
3905 if (rc != LLAPI_LAYOUT_ITER_CONT)
3908 layout->llot_cur_comp = curr;
3913 int llapi_layout_dom_size(struct llapi_layout *layout, uint64_t *size)
3915 uint64_t pattern, start;
3918 if (!layout || !llapi_layout_is_composite(layout)) {
3923 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_FIRST);
3927 rc = llapi_layout_pattern_get(layout, &pattern);
3931 if ((pattern & LLAPI_LAYOUT_INVALID) ||
3932 !(pattern & (LOV_PATTERN_MDT | LLAPI_LAYOUT_MDT))) {
3937 rc = llapi_layout_comp_extent_get(layout, &start, size);
3945 int lov_comp_md_size(struct lov_comp_md_v1 *lcm)
3947 if (lcm->lcm_magic == LOV_MAGIC_V1 || lcm->lcm_magic == LOV_MAGIC_V3) {
3948 struct lov_user_md *lum = (void *)lcm;
3950 return lov_user_md_size(lum->lmm_stripe_count, lum->lmm_magic);
3953 if (lcm->lcm_magic == LOV_MAGIC_FOREIGN) {
3954 struct lov_foreign_md *lfm = (void *)lcm;
3956 return lfm->lfm_length;
3959 if (lcm->lcm_magic != LOV_MAGIC_COMP_V1)
3962 return lcm->lcm_size;
3965 int llapi_get_lum_file_fd(int dir_fd, const char *fname, __u64 *valid,
3966 lstatx_t *statx, struct lov_user_md *lum,
3969 struct lov_user_mds_data *lmd;
3970 char buf[65536 + offsetof(typeof(*lmd), lmd_lmm)];
3974 if (lum && lumsize < sizeof(*lum))
3977 /* If a file name is provided, it is relative to the parent directory */
3983 lmd = (struct lov_user_mds_data *)buf;
3984 rc = get_lmd_info_fd(fname, parent_fd, dir_fd, buf, sizeof(buf),
3990 *valid = lmd->lmd_flags;
3993 memcpy(statx, &lmd->lmd_stx, sizeof(*statx));
3996 if (lmd->lmd_lmmsize > lumsize)
3998 memcpy(lum, &lmd->lmd_lmm, lmd->lmd_lmmsize);
4004 int llapi_get_lum_dir_fd(int dir_fd, __u64 *valid, lstatx_t *statx,
4005 struct lov_user_md *lum, size_t lumsize)
4007 return llapi_get_lum_file_fd(dir_fd, NULL, valid, statx, lum, lumsize);
4010 int llapi_get_lum_file(const char *path, __u64 *valid, lstatx_t *statx,
4011 struct lov_user_md *lum, size_t lumsize)
4013 char parent[PATH_MAX];
4020 tmp = strrchr(path, '/');
4022 strncpy(parent, ".", sizeof(parent) - 1);
4025 strncpy(parent, path, tmp - path);
4026 offset = tmp - path - 1;
4027 parent[tmp - path] = 0;
4032 fname += offset + 2;
4034 dir_fd = open(parent, O_RDONLY);
4037 llapi_error(LLAPI_MSG_ERROR, rc, "cannot open '%s'", path);
4041 rc = llapi_get_lum_file_fd(dir_fd, fname, valid, statx, lum, lumsize);
4046 int llapi_get_lum_dir(const char *path, __u64 *valid, lstatx_t *statx,
4047 struct lov_user_md *lum, size_t lumsize)
4052 dir_fd = open(path, O_RDONLY);
4055 llapi_error(LLAPI_MSG_ERROR, rc, "cannot open '%s'", path);
4059 rc = llapi_get_lum_dir_fd(dir_fd, valid, statx, lum, lumsize);