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 };
1780 (layout != NULL && layout->llot_magic != LLAPI_LAYOUT_MAGIC)) {
1786 /* Make sure we are on a Lustre file system */
1787 rc = llapi_search_fsname(path, fsname);
1792 rc = llapi_layout_v2_sanity((struct llapi_layout *)layout,
1794 !!(layout->llot_mirror_count > 1),
1797 llapi_layout_sanity_perror(rc);
1802 /* Object creation must be postponed until after layout attributes
1803 * have been applied. */
1804 if (layout != NULL && (open_flags & O_CREAT))
1805 open_flags |= O_LOV_DELAY_CREATE;
1807 fd = open(path, open_flags, mode);
1809 if (layout == NULL || fd < 0)
1812 lum = llapi_layout_to_lum(layout);
1821 if (lum->lmm_magic == LOV_USER_MAGIC_COMP_V1)
1822 lum_size = ((struct lov_comp_md_v1 *)lum)->lcm_size;
1823 else if (lum->lmm_magic == LOV_USER_MAGIC_SPECIFIC)
1824 lum_size = lov_user_md_size(lum->lmm_stripe_count,
1827 lum_size = lov_user_md_size(0, lum->lmm_magic);
1829 rc = fsetxattr(fd, XATTR_LUSTRE_LOV, lum, lum_size, 0);
1838 errno = errno == EOPNOTSUPP ? ENOTTY : errno;
1844 * Create a file with a given \a layout.
1846 * Force O_CREAT and O_EXCL flags on so caller is assured that file was
1847 * created with the given \a layout on successful function return.
1849 * \param[in] path name of the file to open
1850 * \param[in] open_flags open() flags
1851 * \param[in] mode permissions to create new file with
1852 * \param[in] layout layout to create new file with
1854 * \retval non-negative file descriptor on successful open
1855 * \retval -1 if an error occurred
1857 int llapi_layout_file_create(const char *path, int open_flags, int mode,
1858 const struct llapi_layout *layout)
1860 return llapi_layout_file_open(path, open_flags|O_CREAT|O_EXCL, mode,
1864 int llapi_layout_flags_get(struct llapi_layout *layout, uint32_t *flags)
1866 if (layout->llot_magic != LLAPI_LAYOUT_MAGIC) {
1871 *flags = layout->llot_flags;
1876 * Set flags to the header of a component layout.
1878 int llapi_layout_flags_set(struct llapi_layout *layout, uint32_t flags)
1880 if (layout->llot_magic != LLAPI_LAYOUT_MAGIC) {
1885 layout->llot_flags = flags;
1889 const char *llapi_layout_flags_string(uint32_t flags)
1891 switch (flags & LCM_FL_FLR_MASK) {
1894 case LCM_FL_WRITE_PENDING:
1896 case LCM_FL_SYNC_PENDING:
1898 case LCM_FL_RDONLY | LCM_FL_PCC_RDONLY:
1900 case LCM_FL_WRITE_PENDING | LCM_FL_PCC_RDONLY:
1902 case LCM_FL_SYNC_PENDING | LCM_FL_PCC_RDONLY:
1909 __u16 llapi_layout_string_flags(char *string)
1911 if (strncmp(string, "ro", strlen(string)) == 0)
1912 return LCM_FL_RDONLY;
1913 if (strncmp(string, "wp", strlen(string)) == 0)
1914 return LCM_FL_WRITE_PENDING;
1915 if (strncmp(string, "sp", strlen(string)) == 0)
1916 return LCM_FL_SYNC_PENDING;
1922 * llapi_layout_mirror_count_is_valid() - Check the validity of mirror count.
1923 * @count: Mirror count value to be checked.
1925 * This function checks the validity of mirror count.
1927 * Return: true on success or false on failure.
1929 static bool llapi_layout_mirror_count_is_valid(uint16_t count)
1931 return count >= 0 && count <= LUSTRE_MIRROR_COUNT_MAX;
1935 * llapi_layout_mirror_count_get() - Get mirror count from the header of
1937 * @layout: Layout to get mirror count from.
1938 * @count: Returned mirror count value.
1940 * This function gets mirror count from the header of a layout.
1942 * Return: 0 on success or -1 on failure.
1944 int llapi_layout_mirror_count_get(struct llapi_layout *layout,
1947 if (layout->llot_magic != LLAPI_LAYOUT_MAGIC) {
1952 *count = layout->llot_mirror_count;
1957 * llapi_layout_mirror_count_set() - Set mirror count to the header of a layout.
1958 * @layout: Layout to set mirror count in.
1959 * @count: Mirror count value to be set.
1961 * This function sets mirror count to the header of a layout.
1963 * Return: 0 on success or -1 on failure.
1965 int llapi_layout_mirror_count_set(struct llapi_layout *layout,
1968 if (layout->llot_magic != LLAPI_LAYOUT_MAGIC) {
1973 if (!llapi_layout_mirror_count_is_valid(count)) {
1978 layout->llot_mirror_count = count;
1983 * Fetch the start and end offset of the current layout component.
1985 * \param[in] layout the layout component
1986 * \param[out] start extent start, inclusive
1987 * \param[out] end extent end, exclusive
1989 * \retval 0 on success
1990 * \retval <0 if error occurs
1992 int llapi_layout_comp_extent_get(const struct llapi_layout *layout,
1993 uint64_t *start, uint64_t *end)
1995 struct llapi_layout_comp *comp;
1997 comp = __llapi_layout_cur_comp(layout);
2001 if (start == NULL || end == NULL) {
2006 *start = comp->llc_extent.e_start;
2007 *end = comp->llc_extent.e_end;
2013 * Set the layout extent of a layout.
2015 * \param[in] layout the layout to be set
2016 * \param[in] start extent start, inclusive
2017 * \param[in] end extent end, exclusive
2019 * \retval 0 on success
2020 * \retval <0 if error occurs
2022 int llapi_layout_comp_extent_set(struct llapi_layout *layout,
2023 uint64_t start, uint64_t end)
2025 struct llapi_layout_comp *comp;
2027 comp = __llapi_layout_cur_comp(layout);
2036 comp->llc_extent.e_start = start;
2037 comp->llc_extent.e_end = end;
2038 layout->llot_is_composite = true;
2044 * Gets the attribute flags of the current component.
2046 * \param[in] layout the layout component
2047 * \param[out] flags stored the returned component flags
2049 * \retval 0 on success
2050 * \retval <0 if error occurs
2052 int llapi_layout_comp_flags_get(const struct llapi_layout *layout,
2055 struct llapi_layout_comp *comp;
2057 comp = __llapi_layout_cur_comp(layout);
2061 if (flags == NULL) {
2066 *flags = comp->llc_flags;
2072 * Sets the specified flags of the current component leaving other flags as-is.
2074 * \param[in] layout the layout component
2075 * \param[in] flags component flags to be set
2077 * \retval 0 on success
2078 * \retval <0 if error occurs
2080 int llapi_layout_comp_flags_set(struct llapi_layout *layout, uint32_t flags)
2082 struct llapi_layout_comp *comp;
2084 comp = __llapi_layout_cur_comp(layout);
2088 comp->llc_flags |= flags;
2094 * Clears the flags specified in the flags leaving other flags as-is.
2096 * \param[in] layout the layout component
2097 * \param[in] flags component flags to be cleared
2099 * \retval 0 on success
2100 * \retval <0 if error occurs
2102 int llapi_layout_comp_flags_clear(struct llapi_layout *layout,
2105 struct llapi_layout_comp *comp;
2107 comp = __llapi_layout_cur_comp(layout);
2111 comp->llc_flags &= ~flags;
2117 * Fetches the file-unique component ID of the current layout component.
2119 * \param[in] layout the layout component
2120 * \param[out] id stored the returned component ID
2122 * \retval 0 on success
2123 * \retval <0 if error occurs
2125 int llapi_layout_comp_id_get(const struct llapi_layout *layout, uint32_t *id)
2127 struct llapi_layout_comp *comp;
2129 comp = __llapi_layout_cur_comp(layout);
2143 * Return the mirror id of the current layout component.
2145 * \param[in] layout the layout component
2146 * \param[out] id stored the returned mirror ID
2148 * \retval 0 on success
2149 * \retval <0 if error occurs
2151 int llapi_layout_mirror_id_get(const struct llapi_layout *layout, uint32_t *id)
2153 struct llapi_layout_comp *comp;
2155 comp = __llapi_layout_cur_comp(layout);
2164 *id = mirror_id_of(comp->llc_id);
2170 * Adds a component to \a layout, the new component will be added to
2171 * the tail of components list and it'll inherit attributes of existing
2172 * ones. The \a layout will change it's current component pointer to
2173 * the newly added component, and it'll be turned into a composite
2174 * layout if it was not before the adding.
2176 * \param[in] layout existing composite or plain layout
2178 * \retval 0 on success
2179 * \retval <0 if error occurs
2181 int llapi_layout_comp_add(struct llapi_layout *layout)
2183 struct llapi_layout_comp *last, *comp, *new;
2184 bool composite = layout->llot_is_composite;
2186 comp = __llapi_layout_cur_comp(layout);
2190 new = __llapi_comp_alloc(0);
2194 last = list_last_entry(&layout->llot_comp_list, typeof(*last),
2197 list_add_tail(&new->llc_list, &layout->llot_comp_list);
2199 /* We must mark the layout composite for the sanity check, but it may
2200 * not stay that way if the check fails */
2201 layout->llot_is_composite = true;
2202 layout->llot_cur_comp = new;
2204 /* We need to set a temporary non-zero value for "end" when we call
2205 * comp_extent_set, so we use LUSTRE_EOF-1, which is > all allowed
2206 * for the end of the previous component. (If we're adding this
2207 * component, the end of the previous component cannot be EOF.) */
2208 if (llapi_layout_comp_extent_set(layout, last->llc_extent.e_end,
2210 llapi_layout_comp_del(layout);
2211 layout->llot_is_composite = composite;
2218 * Adds a first component of a mirror to \a layout.
2219 * The \a layout will change it's current component pointer to
2220 * the newly added component, and it'll be turned into a composite
2221 * layout if it was not before the adding.
2223 * \param[in] layout existing composite or plain layout
2225 * \retval 0 on success
2226 * \retval <0 if error occurs
2228 int llapi_layout_add_first_comp(struct llapi_layout *layout)
2230 struct llapi_layout_comp *comp, *new;
2232 comp = __llapi_layout_cur_comp(layout);
2236 new = __llapi_comp_alloc(0);
2240 new->llc_extent.e_start = 0;
2242 list_add_tail(&new->llc_list, &layout->llot_comp_list);
2243 layout->llot_cur_comp = new;
2244 layout->llot_is_composite = true;
2250 * Deletes current component from the composite layout. The component
2251 * to be deleted must be the tail of components list, and it can't be
2252 * the only component in the layout.
2254 * \param[in] layout composite layout
2256 * \retval 0 on success
2257 * \retval <0 if error occurs
2259 int llapi_layout_comp_del(struct llapi_layout *layout)
2261 struct llapi_layout_comp *comp;
2263 comp = __llapi_layout_cur_comp(layout);
2267 if (!layout->llot_is_composite) {
2272 /* It must be the tail of the list (for PFL, can be relaxed
2273 * once we get mirrored components) */
2274 if (comp->llc_list.next != &layout->llot_comp_list) {
2278 layout->llot_cur_comp =
2279 list_last_entry(&comp->llc_list, typeof(*comp), llc_list);
2280 if (comp->llc_list.prev == &layout->llot_comp_list)
2281 layout->llot_cur_comp = NULL;
2283 list_del_init(&comp->llc_list);
2284 __llapi_comp_free(comp);
2290 * Move the current component pointer to the component with
2291 * specified component ID.
2293 * \param[in] layout composite layout
2294 * \param[in] id component ID
2296 * \retval =0 : moved successfully
2297 * \retval <0 if error occurs
2299 int llapi_layout_comp_use_id(struct llapi_layout *layout, uint32_t comp_id)
2301 struct llapi_layout_comp *comp;
2303 comp = __llapi_layout_cur_comp(layout);
2305 return -1; /* use previously set errno */
2307 if (!layout->llot_is_composite) {
2312 if (comp_id == LCME_ID_INVAL) {
2317 list_for_each_entry(comp, &layout->llot_comp_list, llc_list) {
2318 if (comp->llc_id == comp_id) {
2319 layout->llot_cur_comp = comp;
2328 * Move the current component pointer to a specified position.
2330 * \param[in] layout composite layout
2331 * \param[in] pos the position to be moved, it can be:
2332 * LLAPI_LAYOUT_COMP_USE_FIRST: use first component
2333 * LLAPI_LAYOUT_COMP_USE_LAST: use last component
2334 * LLAPI_LAYOUT_COMP_USE_NEXT: use component after current
2335 * LLAPI_LAYOUT_COMP_USE_PREV: use component before current
2337 * \retval =0 : moved successfully
2338 * \retval =1 : at last component with NEXT, at first component with PREV
2339 * \retval <0 if error occurs
2341 int llapi_layout_comp_use(struct llapi_layout *layout,
2342 enum llapi_layout_comp_use pos)
2344 struct llapi_layout_comp *comp, *head, *tail;
2346 comp = __llapi_layout_cur_comp(layout);
2350 if (!layout->llot_is_composite) {
2351 if (pos == LLAPI_LAYOUT_COMP_USE_FIRST ||
2352 pos == LLAPI_LAYOUT_COMP_USE_LAST)
2358 head = list_first_entry(&layout->llot_comp_list, typeof(*head),
2360 tail = list_last_entry(&layout->llot_comp_list, typeof(*tail),
2363 case LLAPI_LAYOUT_COMP_USE_FIRST:
2364 layout->llot_cur_comp = head;
2366 case LLAPI_LAYOUT_COMP_USE_NEXT:
2371 layout->llot_cur_comp = list_first_entry(&comp->llc_list,
2375 case LLAPI_LAYOUT_COMP_USE_LAST:
2376 layout->llot_cur_comp = tail;
2378 case LLAPI_LAYOUT_COMP_USE_PREV:
2383 layout->llot_cur_comp = list_last_entry(&comp->llc_list,
2396 * Add layout component(s) to an existing file.
2398 * \param[in] path The path name of the file
2399 * \param[in] layout The layout component(s) to be added
2401 int llapi_layout_file_comp_add(const char *path,
2402 const struct llapi_layout *layout)
2404 int rc, fd = -1, lum_size, tmp_errno = 0;
2405 struct llapi_layout *existing_layout = NULL;
2406 struct lov_user_md *lum = NULL;
2407 char fsname[MAX_OBD_NAME + 1] = { 0 };
2409 if (path == NULL || layout == NULL ||
2410 layout->llot_magic != LLAPI_LAYOUT_MAGIC) {
2415 fd = open(path, O_RDWR);
2422 existing_layout = llapi_layout_get_by_fd(fd, 0);
2423 if (existing_layout == NULL) {
2429 rc = llapi_layout_merge(&existing_layout, layout);
2436 rc = llapi_search_fsname(path, fsname);
2443 rc = llapi_layout_v2_sanity(existing_layout, false, false, fsname);
2446 llapi_layout_sanity_perror(rc);
2451 lum = llapi_layout_to_lum(layout);
2458 if (lum->lmm_magic != LOV_USER_MAGIC_COMP_V1) {
2463 lum_size = ((struct lov_comp_md_v1 *)lum)->lcm_size;
2465 rc = fsetxattr(fd, XATTR_LUSTRE_LOV".add", lum, lum_size, 0);
2475 llapi_layout_free(existing_layout);
2481 * Delete component(s) by the specified component id or component flags
2482 * from an existing file.
2484 * \param[in] path path name of the file
2485 * \param[in] id unique component ID
2486 * \param[in] flags flags: LCME_FL_* or;
2487 * negative flags: (LCME_FL_NEG|LCME_FL_*)
2489 int llapi_layout_file_comp_del(const char *path, uint32_t id, uint32_t flags)
2491 int rc = 0, fd = -1, lum_size, tmp_errno = 0;
2492 struct llapi_layout *layout;
2493 struct llapi_layout_comp *comp, *next;
2494 struct llapi_layout *existing_layout = NULL;
2495 struct lov_user_md *lum = NULL;
2497 if (path == NULL || id > LCME_ID_MAX || (flags & ~LCME_KNOWN_FLAGS)) {
2502 /* Can only specify ID or flags, not both, not none. */
2503 if ((id != LCME_ID_INVAL && flags != 0) ||
2504 (id == LCME_ID_INVAL && flags == 0)) {
2509 layout = llapi_layout_alloc();
2513 llapi_layout_comp_extent_set(layout, 0, LUSTRE_EOF);
2514 comp = __llapi_layout_cur_comp(layout);
2522 comp->llc_flags = flags;
2524 lum = llapi_layout_to_lum(layout);
2530 lum_size = ((struct lov_comp_md_v1 *)lum)->lcm_size;
2532 fd = open(path, O_RDWR);
2539 existing_layout = llapi_layout_get_by_fd(fd, 0);
2540 if (existing_layout == NULL) {
2548 while (rc == 0 && existing_layout->llot_cur_comp != NULL) {
2549 rc = llapi_layout_comp_use(existing_layout, comp ?
2550 LLAPI_LAYOUT_COMP_USE_PREV :
2551 LLAPI_LAYOUT_COMP_USE_LAST);
2556 comp = __llapi_layout_cur_comp(existing_layout);
2562 if (id != LCME_ID_INVAL && id != comp->llc_id)
2564 else if ((flags & LCME_FL_NEG) && (flags & comp->llc_flags))
2566 else if (flags && !(flags & comp->llc_flags))
2569 rc = llapi_layout_comp_del(existing_layout);
2570 /* the layout position is moved to previous one, adjust */
2578 rc = llapi_layout_sanity(existing_layout, false, false);
2581 llapi_layout_sanity_perror(rc);
2586 rc = fsetxattr(fd, XATTR_LUSTRE_LOV".del", lum, lum_size, 0);
2597 llapi_layout_free(layout);
2598 llapi_layout_free(existing_layout);
2604 /* Internal utility function to apply flags for sanity checking */
2605 static void llapi_layout_comp_apply_flags(struct llapi_layout_comp *comp,
2608 if (flags & LCME_FL_NEG)
2609 comp->llc_flags &= ~flags;
2611 comp->llc_flags |= flags;
2614 struct llapi_layout_apply_flags_args {
2616 uint32_t *lfa_flags;
2622 static int llapi_layout_apply_flags_cb(struct llapi_layout *layout,
2625 struct llapi_layout_apply_flags_args *args = arg;
2626 struct llapi_layout_comp *comp;
2629 comp = __llapi_layout_cur_comp(layout);
2632 return LLAPI_LAYOUT_ITER_STOP;
2635 for (i = 0; i < args->lfa_count; i++) {
2636 if (comp->llc_id == args->lfa_ids[i])
2637 llapi_layout_comp_apply_flags(comp, args->lfa_flags[i]);
2640 return LLAPI_LAYOUT_ITER_CONT;
2643 /* Apply flags to the layout for sanity checking */
2644 static int llapi_layout_apply_flags(struct llapi_layout *layout, uint32_t *ids,
2645 uint32_t *flags, int count)
2647 struct llapi_layout_apply_flags_args args;
2650 if (!ids || !flags || count == 0) {
2656 args.lfa_flags = flags;
2657 args.lfa_count = count;
2660 rc = llapi_layout_comp_iterate(layout,
2661 llapi_layout_apply_flags_cb,
2663 if (errno == ENOENT)
2666 if (rc != LLAPI_LAYOUT_ITER_CONT)
2672 * Change flags by component ID of components of an existing file.
2673 * The component to be modified is specified by the comp->lcme_id value,
2674 * which must be a unique component ID.
2676 * \param[in] path path name of the file
2677 * \param[in] ids An array of component IDs
2678 * \param[in] flags flags: LCME_FL_* or;
2679 * negative flags: (LCME_FL_NEG|LCME_FL_*)
2680 * \param[in] count Number of elements in ids and flags array
2682 int llapi_layout_file_comp_set(const char *path, uint32_t *ids, uint32_t *flags,
2685 int rc = -1, fd = -1, i, tmp_errno = 0;
2687 struct llapi_layout *existing_layout = NULL;
2688 struct llapi_layout *layout = NULL;
2689 struct llapi_layout_comp *comp;
2690 struct lov_user_md *lum = NULL;
2691 char fsname[MAX_OBD_NAME + 1] = { 0 };
2701 for (i = 0; i < count; i++) {
2702 if (!ids[i] || !flags[i]) {
2707 if (ids[i] > LCME_ID_MAX || (flags[i] & ~LCME_KNOWN_FLAGS)) {
2712 /* do not allow to set or clear INIT flag */
2713 if (flags[i] & LCME_FL_INIT) {
2719 fd = open(path, O_RDWR);
2726 existing_layout = llapi_layout_get_by_fd(fd, 0);
2727 if (existing_layout == NULL) {
2733 if (llapi_layout_apply_flags(existing_layout, ids, flags, count)) {
2739 rc = llapi_search_fsname(path, fsname);
2746 rc = llapi_layout_v2_sanity(existing_layout, false, false, fsname);
2749 llapi_layout_sanity_perror(rc);
2754 layout = __llapi_layout_alloc();
2755 if (layout == NULL) {
2761 layout->llot_is_composite = true;
2762 for (i = 0; i < count; i++) {
2763 comp = __llapi_comp_alloc(0);
2770 comp->llc_id = ids[i];
2771 comp->llc_flags = flags[i];
2773 list_add_tail(&comp->llc_list, &layout->llot_comp_list);
2774 layout->llot_cur_comp = comp;
2777 lum = llapi_layout_to_lum(layout);
2784 lum_size = ((struct lov_comp_md_v1 *)lum)->lcm_size;
2786 /* flush cached pages from clients */
2787 rc = llapi_file_flush(fd);
2794 rc = fsetxattr(fd, XATTR_LUSTRE_LOV".set.flags", lum, lum_size, 0);
2807 llapi_layout_free(existing_layout);
2808 llapi_layout_free(layout);
2814 * Check if the file layout is composite.
2816 * \param[in] layout the file layout to check
2818 * \retval true composite
2819 * \retval false not composite
2821 bool llapi_layout_is_composite(struct llapi_layout *layout)
2823 return layout->llot_is_composite;
2827 * Iterate every components in the @layout and call callback function @cb.
2829 * \param[in] layout component layout list.
2830 * \param[in] cb callback function called for each component
2831 * \param[in] cbdata callback data passed to the callback function
2833 * \retval < 0 error happens during the iteration
2834 * \retval LLAPI_LAYOUT_ITER_CONT finished the iteration w/o error
2835 * \retval LLAPI_LAYOUT_ITER_STOP got something, stop the iteration
2837 int llapi_layout_comp_iterate(struct llapi_layout *layout,
2838 llapi_layout_iter_cb cb, void *cbdata)
2842 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_FIRST);
2847 * make sure on success llapi_layout_comp_use() API returns 0 with
2853 rc = cb(layout, cbdata);
2854 if (rc != LLAPI_LAYOUT_ITER_CONT)
2857 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_NEXT);
2860 else if (rc == 1) /* reached the last comp */
2861 return LLAPI_LAYOUT_ITER_CONT;
2868 * llapi_layout_merge() - Merge a composite layout into another one.
2869 * @dst_layout: Destination composite layout.
2870 * @src_layout: Source composite layout.
2872 * This function copies all of the components from @src_layout and
2873 * appends them to @dst_layout.
2875 * Return: 0 on success or -1 on failure.
2877 int llapi_layout_merge(struct llapi_layout **dst_layout,
2878 const struct llapi_layout *src_layout)
2880 struct llapi_layout *new_layout = *dst_layout;
2881 struct llapi_layout_comp *new = NULL;
2882 struct llapi_layout_comp *comp = NULL;
2885 if (src_layout == NULL ||
2886 list_empty((struct list_head *)&src_layout->llot_comp_list))
2889 if (new_layout == NULL) {
2890 new_layout = __llapi_layout_alloc();
2891 if (new_layout == NULL) {
2897 list_for_each_entry(comp, &src_layout->llot_comp_list, llc_list) {
2898 new = __llapi_comp_alloc(0);
2904 new->llc_pattern = comp->llc_pattern;
2905 new->llc_stripe_size = comp->llc_stripe_size;
2906 new->llc_stripe_count = comp->llc_stripe_count;
2907 new->llc_stripe_offset = comp->llc_stripe_offset;
2909 if (comp->llc_pool_name[0] != '\0')
2910 strncpy(new->llc_pool_name, comp->llc_pool_name,
2911 sizeof(new->llc_pool_name));
2913 for (i = 0; i < comp->llc_objects_count; i++) {
2914 if (__llapi_comp_objects_realloc(new,
2915 stripe_number_roundup(i)) < 0) {
2917 __llapi_comp_free(new);
2920 new->llc_objects[i].l_ost_idx = \
2921 comp->llc_objects[i].l_ost_idx;
2924 new->llc_objects_count = comp->llc_objects_count;
2925 new->llc_extent.e_start = comp->llc_extent.e_start;
2926 new->llc_extent.e_end = comp->llc_extent.e_end;
2927 new->llc_id = comp->llc_id;
2928 new->llc_flags = comp->llc_flags;
2930 list_add_tail(&new->llc_list, &new_layout->llot_comp_list);
2931 new_layout->llot_cur_comp = new;
2933 new_layout->llot_is_composite = true;
2935 *dst_layout = new_layout;
2938 llapi_layout_free(new_layout);
2943 * Get the last initialized component
2945 * \param[in] layout component layout list.
2948 * \retval -EINVAL not found
2949 * \retval -EISDIR directory layout
2951 int llapi_layout_get_last_init_comp(struct llapi_layout *layout)
2953 struct llapi_layout_comp *comp = NULL, *head = NULL;
2955 if (!layout->llot_is_composite)
2958 head = list_first_entry(&layout->llot_comp_list, typeof(*comp),
2962 if (head->llc_id == 0 && !(head->llc_flags & LCME_FL_INIT))
2966 /* traverse the components from the tail to find the last init one */
2967 comp = list_last_entry(&layout->llot_comp_list, typeof(*comp),
2969 while (comp != head) {
2970 if (comp->llc_flags & LCME_FL_INIT)
2972 comp = list_last_entry(&comp->llc_list, typeof(*comp),
2976 layout->llot_cur_comp = comp;
2978 return comp->llc_flags & LCME_FL_INIT ? 0 : -EINVAL;
2982 * Interit stripe info from the file's component to the mirror
2984 * \param[in] layout file component layout list.
2985 * \param[in] layout mirro component layout list.
2987 * \retval 0 on success
2988 * \retval -EINVAL on error
2990 int llapi_layout_mirror_inherit(struct llapi_layout *f_layout,
2991 struct llapi_layout *m_layout)
2993 struct llapi_layout_comp *m_comp = NULL;
2994 struct llapi_layout_comp *f_comp = NULL;
2997 f_comp = __llapi_layout_cur_comp(f_layout);
3000 m_comp = __llapi_layout_cur_comp(m_layout);
3004 /* DoM component does not inherit stripe size */
3005 if (m_comp->llc_pattern != LLAPI_LAYOUT_MDT)
3006 m_comp->llc_stripe_size = f_comp->llc_stripe_size;
3007 m_comp->llc_stripe_count = f_comp->llc_stripe_count;
3013 * Find all stale components.
3015 * \param[in] layout component layout list.
3016 * \param[out] comp array of stale component info.
3017 * \param[in] comp_size array size of @comp.
3018 * \param[in] mirror_ids array of mirror id that only components
3019 * belonging to these mirror will be collected.
3020 * \param[in] ids_nr number of mirror ids array.
3022 * \retval number of component info collected on success or
3023 * an error code on failure.
3025 int llapi_mirror_find_stale(struct llapi_layout *layout,
3026 struct llapi_resync_comp *comp, size_t comp_size,
3027 __u16 *mirror_ids, int ids_nr)
3032 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_FIRST);
3040 uint64_t start, end;
3042 rc = llapi_layout_comp_flags_get(layout, &flags);
3046 if (!(flags & LCME_FL_STALE))
3049 rc = llapi_layout_mirror_id_get(layout, &mirror_id);
3053 /* the caller only wants stale components from specific
3058 for (j = 0; j < ids_nr; j++) {
3059 if (mirror_ids[j] == mirror_id)
3063 /* not in the specified mirror */
3066 } else if (flags & LCME_FL_NOSYNC) {
3067 /* if not specified mirrors, do not resync "nosync"
3072 rc = llapi_layout_comp_id_get(layout, &id);
3076 rc = llapi_layout_comp_extent_get(layout, &start, &end);
3080 /* pack this component into @comp array */
3081 comp[idx].lrc_id = id;
3082 comp[idx].lrc_mirror_id = mirror_id;
3083 comp[idx].lrc_start = start;
3084 comp[idx].lrc_end = end;
3087 if (idx >= comp_size) {
3093 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_NEXT);
3100 return rc < 0 ? rc : idx;
3103 /* locate @layout to a valid component covering file [file_start, file_end) */
3104 int llapi_mirror_find(struct llapi_layout *layout, uint64_t file_start,
3105 uint64_t file_end, uint64_t *endp)
3107 uint32_t mirror_id = 0;
3110 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_FIRST);
3116 uint64_t start, end;
3117 uint32_t flags, id, rid;
3119 rc = llapi_layout_comp_flags_get(layout, &flags);
3123 if (flags & LCME_FL_STALE)
3126 rc = llapi_layout_mirror_id_get(layout, &rid);
3130 rc = llapi_layout_comp_id_get(layout, &id);
3134 rc = llapi_layout_comp_extent_get(layout, &start, &end);
3138 if (file_start >= start && file_start < end) {
3141 else if (mirror_id != rid || *endp != start)
3144 file_start = *endp = end;
3145 if (end >= file_end)
3150 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_NEXT);
3160 #ifndef NSEC_PER_SEC
3161 # define NSEC_PER_SEC 1000000000UL
3163 #define ONE_MB 0x100000
3164 static struct timespec timespec_sub(struct timespec *before,
3165 struct timespec *after)
3167 struct timespec ret;
3169 ret.tv_sec = after->tv_sec - before->tv_sec;
3170 if (after->tv_nsec < before->tv_nsec) {
3172 ret.tv_nsec = NSEC_PER_SEC + after->tv_nsec - before->tv_nsec;
3174 ret.tv_nsec = after->tv_nsec - before->tv_nsec;
3180 static void stats_log(struct timespec *now, struct timespec *start_time,
3181 ssize_t read_bytes, size_t write_bytes,
3182 off_t file_size_bytes)
3184 struct timespec diff = timespec_sub(start_time, now);
3186 if (file_size_bytes == 0)
3189 if (diff.tv_sec == 0 && diff.tv_nsec == 0)
3192 llapi_printf(LLAPI_MSG_NORMAL,
3193 "- { seconds: %li, rmbps: %5.2g, wmbps: %5.2g, copied: %lu, size: %lu, pct: %lu%% }\n",
3195 (double) read_bytes/((ONE_MB * diff.tv_sec) +
3196 ((ONE_MB * diff.tv_nsec)/NSEC_PER_SEC)),
3197 (double) write_bytes/((ONE_MB * diff.tv_sec) +
3198 ((ONE_MB * diff.tv_nsec)/NSEC_PER_SEC)),
3200 file_size_bytes/ONE_MB,
3201 ((write_bytes*100)/file_size_bytes));
3204 int llapi_mirror_resync_many_params(int fd, struct llapi_layout *layout,
3205 struct llapi_resync_comp *comp_array,
3206 int comp_size, uint64_t start,
3208 unsigned long stats_interval_sec,
3209 unsigned long bandwidth_bytes_sec)
3211 size_t buflen = 64 << 20; /* 64M */
3214 uint64_t pos = start;
3215 uint64_t data_off = pos, data_end = pos;
3216 uint64_t mirror_end = LUSTRE_EOF;
3221 struct timespec start_time;
3222 struct timespec now;
3223 struct timespec last_bw_print;
3224 size_t total_bytes_read = 0;
3225 size_t total_bytes_written = 0;
3226 off_t write_estimation_bytes = 0;
3228 if (bandwidth_bytes_sec > 0 || stats_interval_sec) {
3231 rc = fstat(fd, &st);
3234 write_estimation_bytes = st.st_size * comp_size;
3237 /* limit transfer size to what can be sent in one second */
3238 if (bandwidth_bytes_sec && bandwidth_bytes_sec < buflen)
3239 buflen = (bandwidth_bytes_sec + ONE_MB - 1) & ~(ONE_MB - 1);
3241 page_size = sysconf(_SC_PAGESIZE);
3242 if (page_size < 0) {
3247 rc = posix_memalign(&buf, page_size, buflen);
3251 clock_gettime(CLOCK_MONOTONIC, &start_time);
3252 now = last_bw_print = start_time;
3260 if (pos >= data_end) {
3263 if (pos >= mirror_end || !src) {
3264 rc = llapi_mirror_find(layout, pos, end,
3271 /* restrict mirror end by resync end */
3272 mirror_end = MIN(end, mirror_end);
3275 tmp_off = llapi_mirror_data_seek(fd, src, pos,
3278 /* switch to full copy */
3279 to_read = mirror_end - pos;
3283 data_end = data_off + data_size;
3285 data_off = MIN(data_off, mirror_end);
3286 data_end = MIN(data_end, mirror_end);
3288 /* align by page, if there is data block to copy */
3290 data_off &= ~(page_size - 1);
3293 if (pos < data_off) {
3294 for (i = 0; i < comp_size; i++) {
3297 uint32_t mid = comp_array[i].lrc_mirror_id;
3299 /* skip non-overlapped component */
3300 if (pos >= comp_array[i].lrc_end ||
3301 data_off <= comp_array[i].lrc_start)
3304 if (pos < comp_array[i].lrc_start)
3305 cur_pos = comp_array[i].lrc_start;
3309 if (data_off > comp_array[i].lrc_end)
3310 to_punch = comp_array[i].lrc_end -
3313 to_punch = data_off - cur_pos;
3315 if (comp_array[i].lrc_end == OBD_OBJECT_EOF)
3316 /* the last component can be truncated
3319 rc = llapi_mirror_truncate(fd, mid,
3322 rc = llapi_mirror_punch(fd, mid,
3325 * hole at the end of file, so just truncate up
3328 if (!rc && data_off == data_end && !data_size)
3329 rc = llapi_mirror_truncate(fd,
3331 /* if failed then read failed hole range */
3335 if (pos + to_punch == data_off)
3336 to_read = data_end - pos;
3344 if (pos == mirror_end)
3346 to_read = data_end - pos;
3351 assert(data_end <= mirror_end);
3353 to_read = MIN(buflen, to_read);
3354 to_read = ((to_read - 1) | (page_size - 1)) + 1;
3355 bytes_read = llapi_mirror_read(fd, src, buf, to_read, pos);
3356 if (bytes_read == 0) {
3360 if (bytes_read < 0) {
3364 total_bytes_read += bytes_read;
3366 /* round up to page align to make direct IO happy. */
3367 to_write = ((bytes_read - 1) | (page_size - 1)) + 1;
3369 for (i = 0; i < comp_size; i++) {
3370 unsigned long long write_target;
3371 struct timespec diff;
3374 size_t to_write2 = to_write;
3376 /* skip non-overlapped component */
3377 if (pos >= comp_array[i].lrc_end ||
3378 pos + to_write <= comp_array[i].lrc_start)
3381 if (pos < comp_array[i].lrc_start)
3382 pos2 = comp_array[i].lrc_start;
3384 to_write2 -= pos2 - pos;
3386 if ((pos + to_write) > comp_array[i].lrc_end)
3387 to_write2 -= pos + to_write -
3388 comp_array[i].lrc_end;
3390 written = llapi_mirror_write(fd,
3391 comp_array[i].lrc_mirror_id,
3396 * this component is not written successfully,
3397 * mark it using its lrc_synced, it is supposed
3398 * to be false before getting here.
3400 * And before this function returns, all
3401 * elements of comp_array will reverse their
3402 * lrc_synced flag to reflect their true
3405 comp_array[i].lrc_synced = true;
3406 llapi_error(LLAPI_MSG_ERROR, written,
3407 "component %u not synced",
3408 comp_array[i].lrc_id);
3413 assert(written == to_write2);
3414 total_bytes_written += written;
3416 if (bandwidth_bytes_sec == 0)
3419 clock_gettime(CLOCK_MONOTONIC, &now);
3420 diff = timespec_sub(&start_time, &now);
3421 write_target = ((bandwidth_bytes_sec * diff.tv_sec) +
3422 ((bandwidth_bytes_sec *
3423 diff.tv_nsec)/NSEC_PER_SEC));
3425 if (write_target < total_bytes_written) {
3426 unsigned long long excess;
3427 struct timespec delay = { 0, 0 };
3429 excess = total_bytes_written - write_target;
3434 delay.tv_sec = excess / bandwidth_bytes_sec;
3435 delay.tv_nsec = (excess % bandwidth_bytes_sec) *
3436 NSEC_PER_SEC / bandwidth_bytes_sec;
3439 rc = clock_nanosleep(CLOCK_MONOTONIC, 0,
3441 } while (rc < 0 && errno == EINTR);
3444 llapi_error(LLAPI_MSG_ERROR, rc,
3445 "errors: delay for bandwidth control failed: %s\n",
3451 if (stats_interval_sec) {
3452 clock_gettime(CLOCK_MONOTONIC, &now);
3453 if ((total_bytes_written != end - start) &&
3454 (now.tv_sec >= last_bw_print.tv_sec +
3455 stats_interval_sec)) {
3456 stats_log(&now, &start_time,
3458 total_bytes_written,
3459 write_estimation_bytes);
3460 last_bw_print = now;
3470 /* fatal error happens */
3471 for (i = 0; i < comp_size; i++)
3472 comp_array[i].lrc_synced = false;
3476 /* Output at least one log, regardless of stats_interval */
3477 if (stats_interval_sec) {
3478 clock_gettime(CLOCK_MONOTONIC, &now);
3479 stats_log(&now, &start_time, total_bytes_read,
3480 total_bytes_written,
3481 write_estimation_bytes);
3485 * no fatal error happens, each lrc_synced tells whether the component
3486 * has been resync successfully (note: we'd reverse the value to
3487 * reflect its true meaning.
3489 for (i = 0; i < comp_size; i++) {
3490 comp_array[i].lrc_synced = !comp_array[i].lrc_synced;
3491 if (comp_array[i].lrc_synced && pos & (page_size - 1)) {
3492 rc = llapi_mirror_truncate(fd,
3493 comp_array[i].lrc_mirror_id, pos);
3494 /* Ignore truncate error on encrypted file without the
3495 * key if tried on LUSTRE_ENCRYPTION_UNIT_SIZE boundary.
3497 if (rc < 0 && (rc != -ENOKEY ||
3498 pos & ~LUSTRE_ENCRYPTION_MASK))
3499 comp_array[i].lrc_synced = false;
3504 * returns the first error code for partially successful resync if
3510 int llapi_mirror_resync_many(int fd, struct llapi_layout *layout,
3511 struct llapi_resync_comp *comp_array,
3512 int comp_size, uint64_t start, uint64_t end)
3514 return llapi_mirror_resync_many_params(fd, layout, comp_array,
3515 comp_size, start, end, 0, 0);
3518 enum llapi_layout_comp_sanity_error {
3520 LSE_INCOMPLETE_MIRROR,
3521 LSE_ADJACENT_EXTENSION,
3525 LSE_DOM_EXTENSION_FOLLOWING,
3528 LSE_NOT_ZERO_LENGTH_EXTENDABLE,
3529 LSE_END_NOT_GREATER,
3530 LSE_ZERO_LENGTH_NORMAL,
3531 LSE_NOT_ADJACENT_PREV,
3535 LSE_FOREIGN_EXTENSION,
3539 const char *const llapi_layout_strerror[] =
3542 [LSE_INCOMPLETE_MIRROR] =
3543 "Incomplete mirror - must go to EOF",
3544 [LSE_ADJACENT_EXTENSION] =
3545 "No adjacent extension space components",
3546 [LSE_INIT_EXTENSION] =
3547 "Cannot apply extension flag to init components",
3550 [LSE_DOM_EXTENSION] =
3551 "DoM components can't be extension space",
3552 [LSE_DOM_EXTENSION_FOLLOWING] =
3553 "DoM components cannot be followed by extension space",
3555 "DoM component should be the first one in a file/mirror",
3556 [LSE_SET_COMP_START] =
3557 "Must set previous component extent before adding next",
3558 [LSE_NOT_ZERO_LENGTH_EXTENDABLE] =
3559 "Extendable component must start out zero-length",
3560 [LSE_END_NOT_GREATER] =
3561 "Component end is before end of previous component",
3562 [LSE_ZERO_LENGTH_NORMAL] =
3563 "Zero length components must be followed by extension",
3564 [LSE_NOT_ADJACENT_PREV] =
3565 "Components not adjacent (end != next->start",
3566 [LSE_START_GT_END] =
3567 "Component start is > end",
3569 "The component end must be aligned by the stripe size",
3571 "The extension size must be aligned by the stripe size",
3572 [LSE_FOREIGN_EXTENSION] =
3573 "FOREIGN components can't be extension space",
3576 struct llapi_layout_sanity_args {
3577 bool lsa_incomplete;
3584 /* The component flags can be set by users at creation/modification time. */
3585 #define LCME_USER_COMP_FLAGS (LCME_FL_PREF_RW | LCME_FL_NOSYNC | \
3588 /* Inline function to verify the pool name */
3589 static inline int verify_pool_name(char *fsname, struct llapi_layout *layout)
3591 struct llapi_layout_comp *comp;
3593 if (!fsname || fsname[0] == '\0')
3596 comp = __llapi_layout_cur_comp(layout);
3599 if (comp->llc_pool_name[0] == '\0')
3601 /* check if the pool name exist */
3602 if (llapi_search_ost(fsname, comp->llc_pool_name, NULL) < 0)
3608 * When modified, adjust llapi_stripe_param_verify() if needed as well.
3610 static int llapi_layout_sanity_cb(struct llapi_layout *layout,
3613 struct llapi_layout_comp *comp, *next, *prev;
3614 struct llapi_layout_sanity_args *args = arg;
3615 bool first_comp = false;
3617 comp = __llapi_layout_cur_comp(layout);
3623 if (verify_pool_name(args->fsname, layout) != 0) {
3628 if (comp->llc_list.prev != &layout->llot_comp_list)
3629 prev = list_last_entry(&comp->llc_list, typeof(*prev),
3634 if (comp->llc_list.next != &layout->llot_comp_list)
3635 next = list_first_entry(&comp->llc_list, typeof(*next),
3640 /* Start of zero implies a new mirror */
3641 if (comp->llc_extent.e_start == 0) {
3643 /* Most checks apply only within one mirror, this is an
3645 if (prev && prev->llc_extent.e_end != LUSTRE_EOF) {
3646 args->lsa_rc = LSE_INCOMPLETE_MIRROR;
3653 if (next && next->llc_extent.e_start == 0)
3656 /* Flag sanity checks */
3657 /* No adjacent extension components */
3658 if ((comp->llc_flags & LCME_FL_EXTENSION) && next &&
3659 (next->llc_flags & LCME_FL_EXTENSION)) {
3660 args->lsa_rc = LSE_ADJACENT_EXTENSION;
3664 /* Extension flag cannot be applied to init components and the first
3665 * component of each mirror is automatically init */
3666 if ((comp->llc_flags & LCME_FL_EXTENSION) &&
3667 (comp->llc_flags & LCME_FL_INIT || first_comp)) {
3668 args->lsa_rc = LSE_INIT_EXTENSION;
3672 if (comp->llc_ondisk) {
3673 if (comp->llc_flags & LCME_FL_NEG)
3674 args->lsa_rc = LSE_FLAGS;
3675 } else if (!args->lsa_incomplete) {
3676 if (args->lsa_flr) {
3677 if (comp->llc_flags & ~LCME_USER_COMP_FLAGS)
3678 args->lsa_rc = LSE_FLAGS;
3680 if (comp->llc_flags &
3681 ~(LCME_FL_EXTENSION | LCME_FL_PREF_RW |
3683 args->lsa_rc = LSE_FLAGS;
3689 /* DoM sanity checks */
3690 if (!(comp->llc_pattern & LLAPI_LAYOUT_INVALID) &&
3691 (comp->llc_pattern & (LLAPI_LAYOUT_MDT | LOV_PATTERN_MDT))) {
3692 /* DoM components can't be extension components */
3693 if (comp->llc_flags & LCME_FL_EXTENSION) {
3694 args->lsa_rc = LSE_DOM_EXTENSION;
3697 /* DoM components cannot be followed by an extension comp */
3698 if (next && (next->llc_flags & LCME_FL_EXTENSION)) {
3699 args->lsa_rc = LSE_DOM_EXTENSION_FOLLOWING;
3703 /* DoM should be the first component in a mirror */
3705 args->lsa_rc = LSE_DOM_FIRST;
3711 if (comp->llc_pattern == LLAPI_LAYOUT_FOREIGN ||
3712 comp->llc_pattern == LOV_PATTERN_FOREIGN) {
3713 /* FOREING/HSM components can't be extension components */
3714 if (comp->llc_flags & LCME_FL_EXTENSION) {
3715 args->lsa_rc = LSE_FOREIGN_EXTENSION;
3720 /* Extent sanity checks */
3721 /* Must set previous component extent before adding another */
3722 if (prev && prev->llc_extent.e_start == 0 &&
3723 prev->llc_extent.e_end == 0) {
3724 args->lsa_rc = LSE_SET_COMP_START;
3728 if (!args->lsa_incomplete) {
3729 /* Components followed by extension space (extendable
3730 * components) must be zero length before initialization.
3731 * (Except for first comp, which will be initialized on
3733 if (next && (next->llc_flags & LCME_FL_EXTENSION) &&
3734 !first_comp && !(comp->llc_flags & LCME_FL_INIT) &&
3735 comp->llc_extent.e_start != comp->llc_extent.e_end) {
3736 args->lsa_rc = LSE_NOT_ZERO_LENGTH_EXTENDABLE;
3740 /* End must come after end of previous comp */
3741 if (prev && comp->llc_extent.e_end < prev->llc_extent.e_end) {
3742 args->lsa_rc = LSE_END_NOT_GREATER;
3746 /* Components not followed by ext space must have length > 0. */
3747 if (comp->llc_extent.e_start == comp->llc_extent.e_end &&
3748 (next == NULL || !(next->llc_flags & LCME_FL_EXTENSION))) {
3749 args->lsa_rc = LSE_ZERO_LENGTH_NORMAL;
3753 /* The component end must be aligned by the stripe size */
3754 if ((comp->llc_flags & LCME_FL_EXTENSION) &&
3755 (prev->llc_stripe_size != LLAPI_LAYOUT_DEFAULT)) {
3756 if (comp->llc_extent.e_end != LUSTRE_EOF &&
3757 comp->llc_extent.e_end % prev->llc_stripe_size) {
3758 args->lsa_rc = LSE_ALIGN_END;
3761 if ((comp->llc_stripe_size * SEL_UNIT_SIZE) %
3762 prev->llc_stripe_size) {
3763 args->lsa_rc = LSE_ALIGN_EXT;
3766 } else if (!(comp->llc_flags & LCME_FL_EXTENSION) &&
3767 (comp->llc_stripe_size != LLAPI_LAYOUT_DEFAULT)) {
3768 if (comp->llc_extent.e_end != LUSTRE_EOF &&
3769 comp->llc_extent.e_end !=
3770 comp->llc_extent.e_start &&
3771 comp->llc_extent.e_end % comp->llc_stripe_size) {
3772 args->lsa_rc = LSE_ALIGN_END;
3778 /* Components must have start == prev->end */
3779 if (prev && comp->llc_extent.e_start != 0 &&
3780 comp->llc_extent.e_start != prev->llc_extent.e_end) {
3781 args->lsa_rc = LSE_NOT_ADJACENT_PREV;
3785 /* Components must have start <= end */
3786 if (comp->llc_extent.e_start > comp->llc_extent.e_end) {
3787 args->lsa_rc = LSE_START_GT_END;
3791 return LLAPI_LAYOUT_ITER_CONT;
3794 errno = errno ? errno : EINVAL;
3795 return LLAPI_LAYOUT_ITER_STOP;
3798 /* Print explanation of layout error */
3799 void llapi_layout_sanity_perror(int error)
3801 if (error >= LSE_LAST || error < 0) {
3802 fprintf(stdout, "Invalid layout, unrecognized error: %d\n",
3805 fprintf(stdout, "Invalid layout: %s\n",
3806 llapi_layout_strerror[error]);
3810 /* Walk a layout and enforce sanity checks that apply to > 1 component
3812 * The core idea here is that of sanity checking individual tokens vs semantic
3814 * We cannot check everything at the individual component level ('token'),
3815 * instead we must check whether or not the full layout has a valid meaning.
3817 * An example of a component level check is "is stripe size valid?". That is
3818 * handled when setting stripe size.
3820 * An example of a layout level check is "are the extents of these components
3821 * valid when adjacent to one another", or "can we set these flags on adjacent
3824 * \param[in] layout component layout list.
3825 * \param[in] fname file the layout to be checked for
3826 * \param[in] incomplete if layout is complete or not - some checks can
3827 * only be done on complete layouts.
3828 * \param[in] flr set when this is called from FLR mirror create
3830 * \retval 0, success, positive: various errors, see
3831 * llapi_layout_sanity_perror, -1, failure
3834 int llapi_layout_sanity(struct llapi_layout *layout,
3835 bool incomplete, bool flr)
3837 return llapi_layout_v2_sanity(layout, incomplete, flr, NULL);
3840 /* This function has been introduced to do pool name checking
3841 * on top of llapi_layout_sanity, the file name passed in this
3842 * function is used later to verify if pool exist. The older version
3843 * of the sanity function is passing NULL for the filename
3844 * Input arguments ---
3845 * \param[in] layout component layout list.
3846 * \param[in] fname file the layout to be checked for
3847 * \param[in] incomplete if layout is complete or not - some checks can
3848 * only be done on complete layouts.
3849 * \param[in] flr set when this is called from FLR mirror create
3850 * \param[in] fsname filesystem name is used to check pool name, if
3851 * NULL no pool name check is performed
3853 * \retval 0, success, positive: various errors, see
3856 int llapi_layout_v2_sanity(struct llapi_layout *layout,
3857 bool incomplete, bool flr, char *fsname)
3859 struct llapi_layout_sanity_args args = { 0 };
3860 struct llapi_layout_comp *curr;
3866 curr = layout->llot_cur_comp;
3873 args.lsa_incomplete = incomplete;
3874 args.fsname = fsname;
3876 /* When we modify an existing layout, this tells us if it's FLR */
3877 if (mirror_id_of(curr->llc_id) > 0)
3878 args.lsa_flr = true;
3881 rc = llapi_layout_comp_iterate(layout,
3882 llapi_layout_sanity_cb,
3884 if (errno == ENOENT)
3887 if (rc != LLAPI_LAYOUT_ITER_CONT)
3890 layout->llot_cur_comp = curr;
3895 int llapi_layout_dom_size(struct llapi_layout *layout, uint64_t *size)
3897 uint64_t pattern, start;
3900 if (!layout || !llapi_layout_is_composite(layout)) {
3905 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_FIRST);
3909 rc = llapi_layout_pattern_get(layout, &pattern);
3913 if ((pattern & LLAPI_LAYOUT_INVALID) ||
3914 !(pattern & (LOV_PATTERN_MDT | LLAPI_LAYOUT_MDT))) {
3919 rc = llapi_layout_comp_extent_get(layout, &start, size);
3927 int lov_comp_md_size(struct lov_comp_md_v1 *lcm)
3929 if (lcm->lcm_magic == LOV_MAGIC_V1 || lcm->lcm_magic == LOV_MAGIC_V3) {
3930 struct lov_user_md *lum = (void *)lcm;
3932 return lov_user_md_size(lum->lmm_stripe_count, lum->lmm_magic);
3935 if (lcm->lcm_magic == LOV_MAGIC_FOREIGN) {
3936 struct lov_foreign_md *lfm = (void *)lcm;
3938 return lfm->lfm_length;
3941 if (lcm->lcm_magic != LOV_MAGIC_COMP_V1)
3944 return lcm->lcm_size;
3947 int llapi_get_lum_file_fd(int dir_fd, const char *fname, __u64 *valid,
3948 lstatx_t *statx, struct lov_user_md *lum,
3951 struct lov_user_mds_data *lmd;
3952 char buf[65536 + offsetof(typeof(*lmd), lmd_lmm)];
3956 if (lum && lumsize < sizeof(*lum))
3959 /* If a file name is provided, it is relative to the parent directory */
3965 lmd = (struct lov_user_mds_data *)buf;
3966 rc = get_lmd_info_fd(fname, parent_fd, dir_fd, buf, sizeof(buf),
3972 *valid = lmd->lmd_flags;
3975 memcpy(statx, &lmd->lmd_stx, sizeof(*statx));
3978 if (lmd->lmd_lmmsize > lumsize)
3980 memcpy(lum, &lmd->lmd_lmm, lmd->lmd_lmmsize);
3986 int llapi_get_lum_dir_fd(int dir_fd, __u64 *valid, lstatx_t *statx,
3987 struct lov_user_md *lum, size_t lumsize)
3989 return llapi_get_lum_file_fd(dir_fd, NULL, valid, statx, lum, lumsize);
3992 int llapi_get_lum_file(const char *path, __u64 *valid, lstatx_t *statx,
3993 struct lov_user_md *lum, size_t lumsize)
3995 char parent[PATH_MAX];
4002 tmp = strrchr(path, '/');
4004 strncpy(parent, ".", sizeof(parent) - 1);
4007 strncpy(parent, path, tmp - path);
4008 offset = tmp - path - 1;
4009 parent[tmp - path] = 0;
4014 fname += offset + 2;
4016 dir_fd = open(parent, O_RDONLY);
4019 llapi_error(LLAPI_MSG_ERROR, rc, "cannot open '%s'", path);
4023 rc = llapi_get_lum_file_fd(dir_fd, fname, valid, statx, lum, lumsize);
4028 int llapi_get_lum_dir(const char *path, __u64 *valid, lstatx_t *statx,
4029 struct lov_user_md *lum, size_t lumsize)
4034 dir_fd = open(path, O_RDONLY);
4037 llapi_error(LLAPI_MSG_ERROR, rc, "cannot open '%s'", path);
4041 rc = llapi_get_lum_dir_fd(dir_fd, valid, statx, lum, lumsize);