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, Intel Corporation.
28 * Author: Ned Bass <bass6@llnl.gov>
37 #include <sys/xattr.h>
39 #include <libcfs/util/list.h>
40 #include <lustre/lustreapi.h>
41 #include "lustreapi_internal.h"
44 * Layout component, which contains all attributes of a plain
47 struct llapi_layout_comp {
49 uint64_t llc_stripe_size;
50 uint64_t llc_stripe_count;
51 uint64_t llc_stripe_offset;
52 /* Add 1 so user always gets back a null terminated string. */
53 char llc_pool_name[LOV_MAXPOOLNAME + 1];
54 /** Number of objects in llc_objects array if was initialized. */
55 uint32_t llc_objects_count;
56 struct lov_user_ost_data_v1 *llc_objects;
57 /* fields used only for composite layouts */
58 struct lu_extent llc_extent; /* [start, end) of component */
59 uint32_t llc_id; /* unique ID of component */
60 uint32_t llc_flags; /* LCME_FL_* flags */
61 struct list_head llc_list; /* linked to the llapi_layout
66 * An Opaque data type abstracting the layout of a Lustre file.
69 uint32_t llot_magic; /* LLAPI_LAYOUT_MAGIC */
72 bool llot_is_composite;
73 /* Cursor pointing to one of the components in llot_comp_list */
74 struct llapi_layout_comp *llot_cur_comp;
75 struct list_head llot_comp_list;
79 * Compute the number of elements in the lmm_objects array of \a lum
80 * with size \a lum_size.
82 * \param[in] lum the struct lov_user_md to check
83 * \param[in] lum_size the number of bytes in \a lum
85 * \retval number of elements in array lum->lmm_objects
87 static int llapi_layout_objects_in_lum(struct lov_user_md *lum, size_t lum_size)
92 if (lum_size < lov_user_md_size(0, LOV_MAGIC_V1))
95 if (lum->lmm_magic == __swab32(LOV_MAGIC_V1) ||
96 lum->lmm_magic == __swab32(LOV_MAGIC_V3))
97 magic = __swab32(lum->lmm_magic);
99 magic = lum->lmm_magic;
101 base_size = lov_user_md_size(0, magic);
103 if (lum_size <= base_size)
106 return (lum_size - base_size) / sizeof(lum->lmm_objects[0]);
110 * Byte-swap the fields of struct lov_user_md.
112 * XXX Rather than duplicating swabbing code here, we should eventually
113 * refactor the needed functions in lustre/ptlrpc/pack_generic.c
114 * into a library that can be shared between kernel and user code.
117 llapi_layout_swab_lov_user_md(struct lov_user_md *lum, int lum_size)
119 int i, j, ent_count, obj_count;
120 struct lov_comp_md_v1 *comp_v1 = NULL;
121 struct lov_comp_md_entry_v1 *ent;
122 struct lov_user_ost_data *lod;
124 if (lum->lmm_magic != __swab32(LOV_MAGIC_V1) &&
125 lum->lmm_magic != __swab32(LOV_MAGIC_V3) &&
126 lum->lmm_magic != __swab32(LOV_MAGIC_COMP_V1))
129 if (lum->lmm_magic == __swab32(LOV_MAGIC_COMP_V1))
130 comp_v1 = (struct lov_comp_md_v1 *)lum;
132 if (comp_v1 != NULL) {
133 __swab32s(&comp_v1->lcm_magic);
134 __swab32s(&comp_v1->lcm_size);
135 __swab32s(&comp_v1->lcm_layout_gen);
136 __swab16s(&comp_v1->lcm_flags);
137 __swab16s(&comp_v1->lcm_entry_count);
138 ent_count = comp_v1->lcm_entry_count;
143 for (i = 0; i < ent_count; i++) {
144 if (comp_v1 != NULL) {
145 ent = &comp_v1->lcm_entries[i];
146 __swab32s(&ent->lcme_id);
147 __swab32s(&ent->lcme_flags);
148 __swab64s(&ent->lcme_extent.e_start);
149 __swab64s(&ent->lcme_extent.e_end);
150 __swab32s(&ent->lcme_offset);
151 __swab32s(&ent->lcme_size);
153 lum = (struct lov_user_md *)((char *)comp_v1 +
155 lum_size = ent->lcme_size;
157 obj_count = llapi_layout_objects_in_lum(lum, lum_size);
159 __swab32s(&lum->lmm_magic);
160 __swab32s(&lum->lmm_pattern);
161 __swab32s(&lum->lmm_stripe_size);
162 __swab16s(&lum->lmm_stripe_count);
163 __swab16s(&lum->lmm_stripe_offset);
165 if (lum->lmm_magic != LOV_MAGIC_V1) {
166 struct lov_user_md_v3 *v3;
167 v3 = (struct lov_user_md_v3 *)lum;
168 lod = v3->lmm_objects;
170 lod = lum->lmm_objects;
173 for (j = 0; j < obj_count; j++)
174 __swab32s(&lod[j].l_ost_idx);
179 * (Re-)allocate llc_objects[] to \a num_stripes stripes.
181 * Copy over existing llc_objects[], if any, to the new llc_objects[].
183 * \param[in] layout existing layout to be modified
184 * \param[in] num_stripes number of stripes in new layout
186 * \retval 0 if the objects are re-allocated successfully
187 * \retval -1 on error with errno set
189 static int __llapi_comp_objects_realloc(struct llapi_layout_comp *comp,
190 unsigned int new_stripes)
192 struct lov_user_ost_data_v1 *new_objects;
195 if (new_stripes > LOV_MAX_STRIPE_COUNT) {
200 if (new_stripes == comp->llc_objects_count)
203 if (new_stripes != 0 && new_stripes <= comp->llc_objects_count)
206 new_objects = realloc(comp->llc_objects,
207 sizeof(*new_objects) * new_stripes);
208 if (new_objects == NULL && new_stripes != 0) {
213 for (i = comp->llc_objects_count; i < new_stripes; i++)
214 new_objects[i].l_ost_idx = LLAPI_LAYOUT_IDX_MAX;
216 comp->llc_objects = new_objects;
217 comp->llc_objects_count = new_stripes;
223 * Allocate storage for a llapi_layout_comp with \a num_stripes stripes.
225 * \param[in] num_stripes number of stripes in new layout
227 * \retval valid pointer if allocation succeeds
228 * \retval NULL if allocation fails
230 static struct llapi_layout_comp *__llapi_comp_alloc(unsigned int num_stripes)
232 struct llapi_layout_comp *comp;
234 if (num_stripes > LOV_MAX_STRIPE_COUNT) {
239 comp = calloc(1, sizeof(*comp));
245 comp->llc_objects = NULL;
246 comp->llc_objects_count = 0;
248 if (__llapi_comp_objects_realloc(comp, num_stripes) < 0) {
254 comp->llc_pattern = LLAPI_LAYOUT_DEFAULT;
255 comp->llc_stripe_size = LLAPI_LAYOUT_DEFAULT;
256 comp->llc_stripe_count = LLAPI_LAYOUT_DEFAULT;
257 comp->llc_stripe_offset = LLAPI_LAYOUT_DEFAULT;
258 comp->llc_pool_name[0] = '\0';
259 comp->llc_extent.e_start = 0;
260 comp->llc_extent.e_end = LUSTRE_EOF;
263 INIT_LIST_HEAD(&comp->llc_list);
269 * Free memory allocated for \a comp
271 * \param[in] comp previously allocated by __llapi_comp_alloc()
273 static void __llapi_comp_free(struct llapi_layout_comp *comp)
275 if (comp->llc_objects != NULL)
276 free(comp->llc_objects);
281 * Free memory allocated for \a layout.
283 * \param[in] layout previously allocated by llapi_layout_alloc()
285 void llapi_layout_free(struct llapi_layout *layout)
287 struct llapi_layout_comp *comp, *n;
292 list_for_each_entry_safe(comp, n, &layout->llot_comp_list, llc_list) {
293 list_del_init(&comp->llc_list);
294 __llapi_comp_free(comp);
300 * Allocate and initialize a llapi_layout structure.
302 * \retval valid llapi_layout pointer on success
303 * \retval NULL if memory allocation fails
305 static struct llapi_layout *__llapi_layout_alloc(void)
307 struct llapi_layout *layout;
309 layout = calloc(1, sizeof(*layout));
310 if (layout == NULL) {
316 layout->llot_magic = LLAPI_LAYOUT_MAGIC;
317 layout->llot_gen = 0;
318 layout->llot_flags = 0;
319 layout->llot_is_composite = false;
320 layout->llot_cur_comp = NULL;
321 INIT_LIST_HEAD(&layout->llot_comp_list);
327 * Allocate and initialize a new plain layout.
329 * \retval valid llapi_layout pointer on success
330 * \retval NULL if memory allocation fails
332 struct llapi_layout *llapi_layout_alloc(void)
334 struct llapi_layout_comp *comp;
335 struct llapi_layout *layout;
337 layout = __llapi_layout_alloc();
341 comp = __llapi_comp_alloc(0);
347 list_add_tail(&comp->llc_list, &layout->llot_comp_list);
348 layout->llot_cur_comp = comp;
354 * Convert the data from a lov_user_md to a newly allocated llapi_layout.
355 * The caller is responsible for freeing the returned pointer.
357 * \param[in] lum LOV user metadata structure to copy data from
358 * \param[in] lum_size size the the lum passed in
360 * \retval valid llapi_layout pointer on success
361 * \retval NULL if memory allocation fails
363 static struct llapi_layout *
364 llapi_layout_from_lum(const struct lov_user_md *lum, int lum_size)
366 struct lov_comp_md_v1 *comp_v1 = NULL;
367 struct lov_comp_md_entry_v1 *ent;
368 struct lov_user_md *v1;
369 struct llapi_layout *layout;
370 struct llapi_layout_comp *comp;
371 int i, ent_count = 0, obj_count;
373 layout = __llapi_layout_alloc();
377 if (lum->lmm_magic == LOV_MAGIC_COMP_V1) {
378 comp_v1 = (struct lov_comp_md_v1 *)lum;
379 ent_count = comp_v1->lcm_entry_count;
380 layout->llot_is_composite = true;
381 layout->llot_gen = comp_v1->lcm_layout_gen;
382 layout->llot_flags = comp_v1->lcm_flags;
383 } else if (lum->lmm_magic == LOV_MAGIC_V1 ||
384 lum->lmm_magic == LOV_MAGIC_V3) {
386 layout->llot_is_composite = false;
389 if (ent_count == 0) {
394 v1 = (struct lov_user_md *)lum;
395 for (i = 0; i < ent_count; i++) {
396 if (comp_v1 != NULL) {
397 ent = &comp_v1->lcm_entries[i];
398 v1 = (struct lov_user_md *)((char *)comp_v1 +
400 lum_size = ent->lcme_size;
405 obj_count = llapi_layout_objects_in_lum(v1, lum_size);
406 comp = __llapi_comp_alloc(obj_count);
411 comp->llc_extent.e_start = ent->lcme_extent.e_start;
412 comp->llc_extent.e_end = ent->lcme_extent.e_end;
413 comp->llc_id = ent->lcme_id;
414 comp->llc_flags = ent->lcme_flags;
416 comp->llc_extent.e_start = 0;
417 comp->llc_extent.e_end = LUSTRE_EOF;
422 if (v1->lmm_pattern == LOV_PATTERN_RAID0)
423 comp->llc_pattern = LLAPI_LAYOUT_RAID0;
425 /* Lustre only supports RAID0 for now. */
426 comp->llc_pattern = v1->lmm_pattern;
428 if (v1->lmm_stripe_size == 0)
429 comp->llc_stripe_size = LLAPI_LAYOUT_DEFAULT;
431 comp->llc_stripe_size = v1->lmm_stripe_size;
433 if (v1->lmm_stripe_count == (typeof(v1->lmm_stripe_count))-1)
434 comp->llc_stripe_count = LLAPI_LAYOUT_WIDE;
435 else if (v1->lmm_stripe_count == 0)
436 comp->llc_stripe_count = LLAPI_LAYOUT_DEFAULT;
438 comp->llc_stripe_count = v1->lmm_stripe_count;
440 if (v1->lmm_stripe_offset ==
441 (typeof(v1->lmm_stripe_offset))-1)
442 comp->llc_stripe_offset = LLAPI_LAYOUT_DEFAULT;
444 comp->llc_stripe_offset = v1->lmm_stripe_offset;
446 if (v1->lmm_magic != LOV_USER_MAGIC_V1) {
447 const struct lov_user_md_v3 *lumv3;
448 lumv3 = (struct lov_user_md_v3 *)v1;
449 snprintf(comp->llc_pool_name,
450 sizeof(comp->llc_pool_name),
451 "%s", lumv3->lmm_pool_name);
452 memcpy(comp->llc_objects, lumv3->lmm_objects,
453 obj_count * sizeof(lumv3->lmm_objects[0]));
455 const struct lov_user_md_v1 *lumv1;
456 lumv1 = (struct lov_user_md_v1 *)v1;
457 memcpy(comp->llc_objects, lumv1->lmm_objects,
458 obj_count * sizeof(lumv1->lmm_objects[0]));
462 comp->llc_stripe_offset =
463 comp->llc_objects[0].l_ost_idx;
465 list_add_tail(&comp->llc_list, &layout->llot_comp_list);
466 layout->llot_cur_comp = comp;
471 llapi_layout_free(layout);
476 * Convert the data from a llapi_layout to a newly allocated lov_user_md.
477 * The caller is responsible for freeing the returned pointer.
479 * \param[in] layout the layout to copy from
481 * \retval valid lov_user_md pointer on success
482 * \retval NULL if memory allocation fails or the layout is invalid
484 static struct lov_user_md *
485 llapi_layout_to_lum(const struct llapi_layout *layout)
487 struct llapi_layout_comp *comp;
488 struct lov_comp_md_v1 *comp_v1 = NULL;
489 struct lov_comp_md_entry_v1 *ent;
490 struct lov_user_md *lum = NULL;
495 if (layout == NULL ||
496 list_empty((struct list_head *)&layout->llot_comp_list)) {
501 /* Allocate header of lov_comp_md_v1 if necessary */
502 if (layout->llot_is_composite) {
505 list_for_each_entry(comp, &layout->llot_comp_list, llc_list)
508 lum_size = sizeof(*comp_v1) + comp_cnt * sizeof(*ent);
509 lum = malloc(lum_size);
514 comp_v1 = (struct lov_comp_md_v1 *)lum;
515 comp_v1->lcm_magic = LOV_USER_MAGIC_COMP_V1;
516 comp_v1->lcm_size = lum_size;
517 comp_v1->lcm_layout_gen = 0;
518 comp_v1->lcm_flags = layout->llot_flags;
519 comp_v1->lcm_entry_count = comp_cnt;
520 comp_v1->lcm_mirror_count = 0;
524 list_for_each_entry(comp, &layout->llot_comp_list, llc_list) {
525 struct lov_user_md *blob;
528 int i, obj_count = 0;
529 struct lov_user_ost_data *lmm_objects;
530 uint64_t pattern = comp->llc_pattern;
532 if ((pattern & LLAPI_LAYOUT_SPECIFIC) != 0) {
533 if (comp->llc_objects_count <
534 comp->llc_stripe_count) {
538 magic = LOV_USER_MAGIC_SPECIFIC;
539 obj_count = comp->llc_stripe_count;
540 pattern &= ~LLAPI_LAYOUT_SPECIFIC;
541 } else if (strlen(comp->llc_pool_name) != 0) {
542 magic = LOV_USER_MAGIC_V3;
544 magic = LOV_USER_MAGIC_V1;
546 /* All stripes must be specified when the pattern contains
547 * LLAPI_LAYOUT_SPECIFIC */
548 for (i = 0; i < obj_count; i++) {
549 if (comp->llc_objects[i].l_ost_idx ==
550 LLAPI_LAYOUT_IDX_MAX) {
556 blob_size = lov_user_md_size(obj_count, magic);
557 blob = realloc(lum, lum_size + blob_size);
563 comp_v1 = (struct lov_comp_md_v1 *)lum;
564 blob = (struct lov_user_md *)((char *)lum + lum_size);
565 lum_size += blob_size;
568 blob->lmm_magic = magic;
569 if (pattern == LLAPI_LAYOUT_DEFAULT)
570 blob->lmm_pattern = 0;
571 else if (pattern == LLAPI_LAYOUT_RAID0)
572 blob->lmm_pattern = LOV_PATTERN_RAID0;
573 else if (pattern == LLAPI_LAYOUT_MDT)
574 blob->lmm_pattern = LOV_PATTERN_MDT;
576 blob->lmm_pattern = pattern;
578 if (comp->llc_stripe_size == LLAPI_LAYOUT_DEFAULT)
579 blob->lmm_stripe_size = 0;
581 blob->lmm_stripe_size = comp->llc_stripe_size;
583 if (comp->llc_stripe_count == LLAPI_LAYOUT_DEFAULT)
584 blob->lmm_stripe_count = 0;
585 else if (comp->llc_stripe_count == LLAPI_LAYOUT_WIDE)
586 blob->lmm_stripe_count = LOV_ALL_STRIPES;
588 blob->lmm_stripe_count = comp->llc_stripe_count;
590 if (comp->llc_stripe_offset == LLAPI_LAYOUT_DEFAULT)
591 blob->lmm_stripe_offset = -1;
593 blob->lmm_stripe_offset = comp->llc_stripe_offset;
595 if (magic == LOV_USER_MAGIC_V3 ||
596 magic == LOV_USER_MAGIC_SPECIFIC) {
597 struct lov_user_md_v3 *lumv3 =
598 (struct lov_user_md_v3 *)blob;
600 if (comp->llc_pool_name[0] != '\0') {
601 strncpy(lumv3->lmm_pool_name,
603 sizeof(lumv3->lmm_pool_name));
605 memset(lumv3->lmm_pool_name, 0,
606 sizeof(lumv3->lmm_pool_name));
608 lmm_objects = lumv3->lmm_objects;
610 lmm_objects = blob->lmm_objects;
613 for (i = 0; i < obj_count; i++)
614 lmm_objects[i].l_ost_idx =
615 comp->llc_objects[i].l_ost_idx;
617 if (layout->llot_is_composite) {
618 ent = &comp_v1->lcm_entries[ent_idx];
619 ent->lcme_id = comp->llc_id;
620 ent->lcme_flags = comp->llc_flags;
621 ent->lcme_extent.e_start = comp->llc_extent.e_start;
622 ent->lcme_extent.e_end = comp->llc_extent.e_end;
623 ent->lcme_size = blob_size;
624 ent->lcme_offset = offset;
626 comp_v1->lcm_size += blob_size;
640 * Get the parent directory of a path.
642 * \param[in] path path to get parent of
643 * \param[out] buf buffer in which to store parent path
644 * \param[in] size size in bytes of buffer \a buf
646 static void get_parent_dir(const char *path, char *buf, size_t size)
650 strncpy(buf, path, size);
651 p = strrchr(buf, '/');
655 } else if (size >= 2) {
656 strncpy(buf, ".", 2);
657 buf[size - 1] = '\0';
662 * Substitute unspecified attribute values in \a layout with values
663 * from fs global settings. (lov.stripesize, lov.stripecount,
666 * \param[in] layout layout to inherit values from
667 * \param[in] path file path of the filesystem
669 static void inherit_sys_attributes(struct llapi_layout *layout,
672 struct llapi_layout_comp *comp;
673 unsigned int ssize, scount, soffset;
676 rc = sattr_cache_get_defaults(NULL, path, &scount, &ssize, &soffset);
680 list_for_each_entry(comp, &layout->llot_comp_list, llc_list) {
681 if (comp->llc_pattern == LLAPI_LAYOUT_DEFAULT)
682 comp->llc_pattern = LLAPI_LAYOUT_RAID0;
683 if (comp->llc_stripe_size == LLAPI_LAYOUT_DEFAULT)
684 comp->llc_stripe_size = ssize;
685 if (comp->llc_stripe_count == LLAPI_LAYOUT_DEFAULT)
686 comp->llc_stripe_count = scount;
687 if (comp->llc_stripe_offset == LLAPI_LAYOUT_DEFAULT)
688 comp->llc_stripe_offset = soffset;
693 * Get the current component of \a layout.
695 * \param[in] layout layout to get current component
697 * \retval valid llapi_layout_comp pointer on success
698 * \retval NULL on error
700 static struct llapi_layout_comp *
701 __llapi_layout_cur_comp(const struct llapi_layout *layout)
703 struct llapi_layout_comp *comp;
705 if (layout == NULL || layout->llot_magic != LLAPI_LAYOUT_MAGIC) {
709 if (layout->llot_cur_comp == NULL) {
713 /* Verify data consistency */
714 list_for_each_entry(comp, &layout->llot_comp_list, llc_list)
715 if (comp == layout->llot_cur_comp)
722 * Test if any attributes of \a layout are specified.
724 * \param[in] layout the layout to check
726 * \retval true any attributes are specified
727 * \retval false all attributes are unspecified
729 static bool is_any_specified(const struct llapi_layout *layout)
731 struct llapi_layout_comp *comp;
733 comp = __llapi_layout_cur_comp(layout);
737 if (layout->llot_is_composite)
740 return comp->llc_pattern != LLAPI_LAYOUT_DEFAULT ||
741 comp->llc_stripe_size != LLAPI_LAYOUT_DEFAULT ||
742 comp->llc_stripe_count != LLAPI_LAYOUT_DEFAULT ||
743 comp->llc_stripe_offset != LLAPI_LAYOUT_DEFAULT ||
744 strlen(comp->llc_pool_name);
748 * Check if the given \a lum_size is large enough to hold the required
751 * \param[in] lum the struct lov_user_md to check
752 * \param[in] lum_size the number of bytes in \a lum
754 * \retval true the \a lum_size is too small
755 * \retval false the \a lum_size is large enough
757 static bool llapi_layout_lum_truncated(struct lov_user_md *lum, size_t lum_size)
761 if (lum_size < sizeof(lum->lmm_magic))
764 if (lum->lmm_magic == LOV_MAGIC_V1 ||
765 lum->lmm_magic == __swab32(LOV_MAGIC_V1))
766 magic = LOV_MAGIC_V1;
767 else if (lum->lmm_magic == LOV_MAGIC_V3 ||
768 lum->lmm_magic == __swab32(LOV_MAGIC_V3))
769 magic = LOV_MAGIC_V3;
770 else if (lum->lmm_magic == LOV_MAGIC_COMP_V1 ||
771 lum->lmm_magic == __swab32(LOV_MAGIC_COMP_V1))
772 magic = LOV_MAGIC_COMP_V1;
776 if (magic == LOV_MAGIC_V1 || magic == LOV_MAGIC_V3)
777 return lum_size < lov_user_md_size(0, magic);
779 return lum_size < sizeof(struct lov_comp_md_v1);
782 /* Verify if the objects count in lum is consistent with the
783 * stripe count in lum. It applies to regular file only. */
784 static bool llapi_layout_lum_valid(struct lov_user_md *lum, int lum_size)
786 struct lov_comp_md_v1 *comp_v1 = NULL;
787 int i, ent_count, obj_count;
789 if (lum->lmm_magic == LOV_MAGIC_COMP_V1) {
790 comp_v1 = (struct lov_comp_md_v1 *)lum;
791 ent_count = comp_v1->lcm_entry_count;
792 } else if (lum->lmm_magic == LOV_MAGIC_V1 ||
793 lum->lmm_magic == LOV_MAGIC_V3) {
799 for (i = 0; i < ent_count; i++) {
801 lum = (struct lov_user_md *)((char *)comp_v1 +
802 comp_v1->lcm_entries[i].lcme_offset);
803 lum_size = comp_v1->lcm_entries[i].lcme_size;
805 obj_count = llapi_layout_objects_in_lum(lum, lum_size);
808 if (!(comp_v1->lcm_entries[i].lcme_flags &
809 LCME_FL_INIT) && obj_count != 0)
811 } else if (obj_count != lum->lmm_stripe_count) {
819 * Get the striping layout for the file referenced by file descriptor \a fd.
821 * If the filesystem does not support the "lustre." xattr namespace, the
822 * file must be on a non-Lustre filesystem, so set errno to ENOTTY per
823 * convention. If the file has no "lustre.lov" data, the file will
824 * inherit default values, so return a default layout.
826 * If the kernel gives us back less than the expected amount of data,
827 * we fail with errno set to EINTR.
829 * \param[in] fd open file descriptor
830 * \param[in] flags open file descriptor
832 * \retval valid llapi_layout pointer on success
833 * \retval NULL if an error occurs
835 struct llapi_layout *llapi_layout_get_by_fd(int fd, uint32_t flags)
838 struct lov_user_md *lum;
839 struct llapi_layout *layout = NULL;
843 lum_len = XATTR_SIZE_MAX;
844 lum = malloc(lum_len);
848 bytes_read = fgetxattr(fd, XATTR_LUSTRE_LOV, lum, lum_len);
849 if (bytes_read < 0) {
850 if (errno == EOPNOTSUPP)
852 else if (errno == ENODATA)
853 layout = llapi_layout_alloc();
857 /* Return an error if we got back a partial layout. */
858 if (llapi_layout_lum_truncated(lum, bytes_read)) {
863 llapi_layout_swab_lov_user_md(lum, bytes_read);
865 /* Directories may have a positive non-zero lum->lmm_stripe_count
866 * yet have an empty lum->lmm_objects array. For non-directories the
867 * amount of data returned from the kernel must be consistent
868 * with the stripe count. */
869 if (fstat(fd, &st) < 0)
872 if (!S_ISDIR(st.st_mode) && !llapi_layout_lum_valid(lum, bytes_read)) {
877 layout = llapi_layout_from_lum(lum, bytes_read);
884 * Get the expected striping layout for a file at \a path.
886 * Substitute expected inherited attribute values for unspecified
887 * attributes. Unspecified attributes may belong to directories and
888 * never-written-to files, and indicate that default values will be
889 * assigned when files are created or first written to. A default value
890 * is inherited from the parent directory if the attribute is specified
891 * there, otherwise it is inherited from the filesystem root.
892 * Unspecified attributes normally have the value LLAPI_LAYOUT_DEFAULT.
894 * The complete \a path need not refer to an existing file or directory,
895 * but some leading portion of it must reside within a lustre filesystem.
896 * A use case for this interface would be to obtain the literal striping
897 * values that would be assigned to a new file in a given directory.
899 * \param[in] path path for which to get the expected layout
901 * \retval valid llapi_layout pointer on success
902 * \retval NULL if an error occurs
904 static struct llapi_layout *llapi_layout_expected(const char *path)
906 struct llapi_layout *path_layout = NULL;
907 char donor_path[PATH_MAX];
912 fd = open(path, O_RDONLY);
913 if (fd < 0 && errno != ENOENT)
919 path_layout = llapi_layout_get_by_fd(fd, 0);
925 if (path_layout == NULL) {
926 if (errno != ENODATA && errno != ENOENT)
929 path_layout = llapi_layout_alloc();
930 if (path_layout == NULL)
934 if (is_any_specified(path_layout)) {
935 inherit_sys_attributes(path_layout, path);
939 llapi_layout_free(path_layout);
941 rc = stat(path, &st);
942 if (rc < 0 && errno != ENOENT)
945 /* If path is a not a directory or doesn't exist, inherit layout
946 * from parent directory. */
947 if ((rc == 0 && !S_ISDIR(st.st_mode)) ||
948 (rc < 0 && errno == ENOENT)) {
949 get_parent_dir(path, donor_path, sizeof(donor_path));
950 path_layout = llapi_layout_get_by_path(donor_path, 0);
951 if (path_layout != NULL) {
952 if (is_any_specified(path_layout)) {
953 inherit_sys_attributes(path_layout, donor_path);
956 llapi_layout_free(path_layout);
960 /* Inherit layout from the filesystem root. */
961 rc = llapi_search_mounts(path, 0, donor_path, NULL);
964 path_layout = llapi_layout_get_by_path(donor_path, 0);
965 if (path_layout == NULL)
968 inherit_sys_attributes(path_layout, donor_path);
973 * Get the striping layout for the file at \a path.
975 * If \a flags contains LAYOUT_GET_EXPECTED, substitute
976 * expected inherited attribute values for unspecified attributes. See
977 * llapi_layout_expected().
979 * \param[in] path path for which to get the layout
980 * \param[in] flags flags to control how layout is retrieved
982 * \retval valid llapi_layout pointer on success
983 * \retval NULL if an error occurs
985 struct llapi_layout *llapi_layout_get_by_path(const char *path, uint32_t flags)
987 struct llapi_layout *layout = NULL;
991 if (flags & LAYOUT_GET_EXPECTED)
992 return llapi_layout_expected(path);
994 fd = open(path, O_RDONLY);
998 layout = llapi_layout_get_by_fd(fd, flags);
1007 * Get the layout for the file with FID \a fidstr in filesystem \a lustre_dir.
1009 * \param[in] lustre_dir path within Lustre filesystem containing \a fid
1010 * \param[in] fid Lustre identifier of file to get layout for
1012 * \retval valid llapi_layout pointer on success
1013 * \retval NULL if an error occurs
1015 struct llapi_layout *llapi_layout_get_by_fid(const char *lustre_dir,
1016 const lustre_fid *fid,
1021 int saved_msg_level = llapi_msg_get_level();
1022 struct llapi_layout *layout = NULL;
1024 /* Prevent llapi internal routines from writing to console
1025 * while executing this function, then restore previous message
1027 llapi_msg_set_level(LLAPI_MSG_OFF);
1028 fd = llapi_open_by_fid(lustre_dir, fid, O_RDONLY);
1029 llapi_msg_set_level(saved_msg_level);
1034 layout = llapi_layout_get_by_fd(fd, flags);
1043 * Get the stripe count of \a layout.
1045 * \param[in] layout layout to get stripe count from
1046 * \param[out] count integer to store stripe count in
1048 * \retval 0 on success
1049 * \retval -1 if arguments are invalid
1051 int llapi_layout_stripe_count_get(const struct llapi_layout *layout,
1054 struct llapi_layout_comp *comp;
1056 comp = __llapi_layout_cur_comp(layout);
1060 if (count == NULL) {
1065 *count = comp->llc_stripe_count;
1071 * The llapi_layout API functions have these extra validity checks since
1072 * they use intuitively named macros to denote special behavior, whereas
1073 * the old API uses 0 and -1.
1076 static bool llapi_layout_stripe_count_is_valid(int64_t stripe_count)
1078 return stripe_count == LLAPI_LAYOUT_DEFAULT ||
1079 stripe_count == LLAPI_LAYOUT_WIDE ||
1080 (stripe_count != 0 && stripe_count != -1 &&
1081 llapi_stripe_count_is_valid(stripe_count));
1084 static bool llapi_layout_stripe_size_is_valid(uint64_t stripe_size)
1086 return stripe_size == LLAPI_LAYOUT_DEFAULT ||
1087 (stripe_size != 0 &&
1088 llapi_stripe_size_is_aligned(stripe_size) &&
1089 !llapi_stripe_size_is_too_big(stripe_size));
1092 static bool llapi_layout_stripe_index_is_valid(int64_t stripe_index)
1094 return stripe_index == LLAPI_LAYOUT_DEFAULT ||
1095 (stripe_index >= 0 &&
1096 llapi_stripe_index_is_valid(stripe_index));
1100 * Set the stripe count of \a layout.
1102 * \param[in] layout layout to set stripe count in
1103 * \param[in] count value to be set
1105 * \retval 0 on success
1106 * \retval -1 if arguments are invalid
1108 int llapi_layout_stripe_count_set(struct llapi_layout *layout,
1111 struct llapi_layout_comp *comp;
1113 comp = __llapi_layout_cur_comp(layout);
1117 if (!llapi_layout_stripe_count_is_valid(count)) {
1122 comp->llc_stripe_count = count;
1128 * Get the stripe size of \a layout.
1130 * \param[in] layout layout to get stripe size from
1131 * \param[out] size integer to store stripe size in
1133 * \retval 0 on success
1134 * \retval -1 if arguments are invalid
1136 int llapi_layout_stripe_size_get(const struct llapi_layout *layout,
1139 struct llapi_layout_comp *comp;
1141 comp = __llapi_layout_cur_comp(layout);
1150 *size = comp->llc_stripe_size;
1156 * Set the stripe size of \a layout.
1158 * \param[in] layout layout to set stripe size in
1159 * \param[in] size value to be set
1161 * \retval 0 on success
1162 * \retval -1 if arguments are invalid
1164 int llapi_layout_stripe_size_set(struct llapi_layout *layout,
1167 struct llapi_layout_comp *comp;
1169 comp = __llapi_layout_cur_comp(layout);
1173 if (!llapi_layout_stripe_size_is_valid(size)) {
1178 comp->llc_stripe_size = size;
1184 * Get the RAID pattern of \a layout.
1186 * \param[in] layout layout to get pattern from
1187 * \param[out] pattern integer to store pattern in
1189 * \retval 0 on success
1190 * \retval -1 if arguments are invalid
1192 int llapi_layout_pattern_get(const struct llapi_layout *layout,
1195 struct llapi_layout_comp *comp;
1197 comp = __llapi_layout_cur_comp(layout);
1201 if (pattern == NULL) {
1206 *pattern = comp->llc_pattern;
1212 * Set the pattern of \a layout.
1214 * \param[in] layout layout to set pattern in
1215 * \param[in] pattern value to be set
1217 * \retval 0 on success
1218 * \retval -1 if arguments are invalid or RAID pattern
1221 int llapi_layout_pattern_set(struct llapi_layout *layout, uint64_t pattern)
1223 struct llapi_layout_comp *comp;
1225 comp = __llapi_layout_cur_comp(layout);
1229 if (pattern != LLAPI_LAYOUT_DEFAULT &&
1230 pattern != LLAPI_LAYOUT_RAID0 &&
1231 pattern != LLAPI_LAYOUT_MDT) {
1236 comp->llc_pattern = pattern |
1237 (comp->llc_pattern & LLAPI_LAYOUT_SPECIFIC);
1242 static inline int stripe_number_roundup(int stripe_number)
1244 unsigned int round_up = (stripe_number + 8) & ~7;
1245 return round_up > LOV_MAX_STRIPE_COUNT ?
1246 LOV_MAX_STRIPE_COUNT : round_up;
1250 * Set the OST index of stripe number \a stripe_number to \a ost_index.
1252 * If only the starting stripe's OST index is specified, then this can use
1253 * the normal LOV_MAGIC_{V1,V3} layout type. If multiple OST indices are
1254 * given, then allocate an array to hold the list of indices and ensure that
1255 * the LOV_USER_MAGIC_SPECIFIC layout is used when creating the file.
1257 * \param[in] layout layout to set OST index in
1258 * \param[in] stripe_number stripe number to set index for
1259 * \param[in] ost_index the index to set
1261 * \retval 0 on success
1262 * \retval -1 if arguments are invalid or an unsupported stripe number
1263 * was specified, error returned in errno
1265 int llapi_layout_ost_index_set(struct llapi_layout *layout, int stripe_number,
1268 struct llapi_layout_comp *comp;
1270 comp = __llapi_layout_cur_comp(layout);
1274 if (!llapi_layout_stripe_index_is_valid(ost_index)) {
1279 if (stripe_number == 0 && ost_index == LLAPI_LAYOUT_DEFAULT) {
1280 comp->llc_stripe_offset = ost_index;
1281 comp->llc_pattern &= ~LLAPI_LAYOUT_SPECIFIC;
1282 __llapi_comp_objects_realloc(comp, 0);
1283 } else if (stripe_number >= 0 &&
1284 stripe_number < LOV_MAX_STRIPE_COUNT) {
1285 if (ost_index >= LLAPI_LAYOUT_IDX_MAX) {
1290 /* Preallocate a few more stripes to avoid realloc() overhead.*/
1291 if (__llapi_comp_objects_realloc(comp,
1292 stripe_number_roundup(stripe_number)) < 0)
1295 comp->llc_objects[stripe_number].l_ost_idx = ost_index;
1297 if (stripe_number == 0)
1298 comp->llc_stripe_offset = ost_index;
1300 comp->llc_pattern |= LLAPI_LAYOUT_SPECIFIC;
1302 if (comp->llc_stripe_count == LLAPI_LAYOUT_DEFAULT ||
1303 comp->llc_stripe_count <= stripe_number)
1304 comp->llc_stripe_count = stripe_number + 1;
1314 * Get the OST index associated with stripe \a stripe_number.
1316 * Stripes are indexed starting from zero.
1318 * \param[in] layout layout to get index from
1319 * \param[in] stripe_number stripe number to get index for
1320 * \param[out] index integer to store index in
1322 * \retval 0 on success
1323 * \retval -1 if arguments are invalid
1325 int llapi_layout_ost_index_get(const struct llapi_layout *layout,
1326 uint64_t stripe_number, uint64_t *index)
1328 struct llapi_layout_comp *comp;
1330 comp = __llapi_layout_cur_comp(layout);
1334 if (index == NULL) {
1339 if (stripe_number >= comp->llc_stripe_count ||
1340 stripe_number >= comp->llc_objects_count) {
1345 if (comp->llc_stripe_offset == LLAPI_LAYOUT_DEFAULT)
1346 *index = LLAPI_LAYOUT_DEFAULT;
1348 *index = comp->llc_objects[stripe_number].l_ost_idx;
1355 * Get the pool name of layout \a layout.
1357 * \param[in] layout layout to get pool name from
1358 * \param[out] dest buffer to store pool name in
1359 * \param[in] n size in bytes of buffer \a dest
1361 * \retval 0 on success
1362 * \retval -1 if arguments are invalid
1364 int llapi_layout_pool_name_get(const struct llapi_layout *layout, char *dest,
1367 struct llapi_layout_comp *comp;
1369 comp = __llapi_layout_cur_comp(layout);
1378 strncpy(dest, comp->llc_pool_name, n);
1384 * Set the name of the pool of layout \a layout.
1386 * \param[in] layout layout to set pool name in
1387 * \param[in] pool_name pool name to set
1389 * \retval 0 on success
1390 * \retval -1 if arguments are invalid or pool name is too long
1392 int llapi_layout_pool_name_set(struct llapi_layout *layout,
1393 const char *pool_name)
1395 struct llapi_layout_comp *comp;
1398 comp = __llapi_layout_cur_comp(layout);
1402 if (pool_name == NULL) {
1407 /* Strip off any 'fsname.' portion. */
1408 ptr = strchr(pool_name, '.');
1410 pool_name = ptr + 1;
1412 if (strlen(pool_name) > LOV_MAXPOOLNAME) {
1417 strncpy(comp->llc_pool_name, pool_name, sizeof(comp->llc_pool_name));
1423 * Open and possibly create a file with a given \a layout.
1425 * If \a layout is NULL this function acts as a simple wrapper for
1426 * open(). By convention, ENOTTY is returned in errno if \a path
1427 * refers to a non-Lustre file.
1429 * \param[in] path name of the file to open
1430 * \param[in] open_flags open() flags
1431 * \param[in] mode permissions to create new file with
1432 * \param[in] layout layout to create new file with
1434 * \retval non-negative file descriptor on successful open
1435 * \retval -1 if an error occurred
1437 int llapi_layout_file_open(const char *path, int open_flags, mode_t mode,
1438 const struct llapi_layout *layout)
1443 struct lov_user_md *lum;
1447 (layout != NULL && layout->llot_magic != LLAPI_LAYOUT_MAGIC)) {
1452 /* Object creation must be postponed until after layout attributes
1453 * have been applied. */
1454 if (layout != NULL && (open_flags & O_CREAT))
1455 open_flags |= O_LOV_DELAY_CREATE;
1457 fd = open(path, open_flags, mode);
1459 if (layout == NULL || fd < 0)
1462 lum = llapi_layout_to_lum(layout);
1471 if (lum->lmm_magic == LOV_USER_MAGIC_COMP_V1)
1472 lum_size = ((struct lov_comp_md_v1 *)lum)->lcm_size;
1473 else if (lum->lmm_magic == LOV_USER_MAGIC_SPECIFIC)
1474 lum_size = lov_user_md_size(lum->lmm_stripe_count,
1477 lum_size = lov_user_md_size(0, lum->lmm_magic);
1479 rc = fsetxattr(fd, XATTR_LUSTRE_LOV, lum, lum_size, 0);
1488 errno = errno == EOPNOTSUPP ? ENOTTY : errno;
1494 * Create a file with a given \a layout.
1496 * Force O_CREAT and O_EXCL flags on so caller is assured that file was
1497 * created with the given \a layout on successful function return.
1499 * \param[in] path name of the file to open
1500 * \param[in] open_flags open() flags
1501 * \param[in] mode permissions to create new file with
1502 * \param[in] layout layout to create new file with
1504 * \retval non-negative file descriptor on successful open
1505 * \retval -1 if an error occurred
1507 int llapi_layout_file_create(const char *path, int open_flags, int mode,
1508 const struct llapi_layout *layout)
1510 return llapi_layout_file_open(path, open_flags|O_CREAT|O_EXCL, mode,
1514 int llapi_layout_flags_get(struct llapi_layout *layout, uint32_t *flags)
1516 if (layout->llot_magic != LLAPI_LAYOUT_MAGIC) {
1521 *flags = layout->llot_flags;
1526 * Set flags to the header of a component layout.
1528 int llapi_layout_flags_set(struct llapi_layout *layout, uint32_t flags)
1530 if (layout->llot_magic != LLAPI_LAYOUT_MAGIC) {
1535 layout->llot_flags = flags;
1540 * Fetch the start and end offset of the current layout component.
1542 * \param[in] layout the layout component
1543 * \param[out] start extent start, inclusive
1544 * \param[out] end extent end, exclusive
1546 * \retval 0 on success
1547 * \retval <0 if error occurs
1549 int llapi_layout_comp_extent_get(const struct llapi_layout *layout,
1550 uint64_t *start, uint64_t *end)
1552 struct llapi_layout_comp *comp;
1554 comp = __llapi_layout_cur_comp(layout);
1558 if (start == NULL || end == NULL) {
1563 *start = comp->llc_extent.e_start;
1564 *end = comp->llc_extent.e_end;
1570 * Set the layout extent of a layout.
1572 * \param[in] layout the layout to be set
1573 * \param[in] start extent start, inclusive
1574 * \param[in] end extent end, exclusive
1576 * \retval 0 on success
1577 * \retval <0 if error occurs
1579 int llapi_layout_comp_extent_set(struct llapi_layout *layout,
1580 uint64_t start, uint64_t end)
1582 struct llapi_layout_comp *prev, *next, *comp;
1584 comp = __llapi_layout_cur_comp(layout);
1594 * We need to make sure the extent to be set is valid: the new
1595 * extent must be adjacent with the prev & next component.
1597 if (comp->llc_list.prev != &layout->llot_comp_list) {
1598 prev = list_entry(comp->llc_list.prev, typeof(*prev),
1600 if (start != prev->llc_extent.e_end) {
1606 if (comp->llc_list.next != &layout->llot_comp_list) {
1607 next = list_entry(comp->llc_list.next, typeof(*next),
1609 if (end != next->llc_extent.e_start) {
1615 comp->llc_extent.e_start = start;
1616 comp->llc_extent.e_end = end;
1617 layout->llot_is_composite = true;
1623 * Gets the attribute flags of the current component.
1625 * \param[in] layout the layout component
1626 * \param[out] flags stored the returned component flags
1628 * \retval 0 on success
1629 * \retval <0 if error occurs
1631 int llapi_layout_comp_flags_get(const struct llapi_layout *layout,
1634 struct llapi_layout_comp *comp;
1636 comp = __llapi_layout_cur_comp(layout);
1640 if (flags == NULL) {
1645 *flags = comp->llc_flags;
1651 * Sets the specified flags of the current component leaving other flags as-is.
1653 * \param[in] layout the layout component
1654 * \param[in] flags component flags to be set
1656 * \retval 0 on success
1657 * \retval <0 if error occurs
1659 int llapi_layout_comp_flags_set(struct llapi_layout *layout, uint32_t flags)
1661 struct llapi_layout_comp *comp;
1663 comp = __llapi_layout_cur_comp(layout);
1667 comp->llc_flags |= flags;
1673 * Clears the flags specified in the flags leaving other flags as-is.
1675 * \param[in] layout the layout component
1676 * \param[in] flags component flags to be cleared
1678 * \retval 0 on success
1679 * \retval <0 if error occurs
1681 int llapi_layout_comp_flags_clear(struct llapi_layout *layout,
1684 struct llapi_layout_comp *comp;
1686 comp = __llapi_layout_cur_comp(layout);
1690 comp->llc_flags &= ~flags;
1696 * Fetches the file-unique component ID of the current layout component.
1698 * \param[in] layout the layout component
1699 * \param[out] id stored the returned component ID
1701 * \retval 0 on success
1702 * \retval <0 if error occurs
1704 int llapi_layout_comp_id_get(const struct llapi_layout *layout, uint32_t *id)
1706 struct llapi_layout_comp *comp;
1708 comp = __llapi_layout_cur_comp(layout);
1722 * Return the mirror id of the current layout component.
1724 * \param[in] layout the layout component
1725 * \param[out] id stored the returned mirror ID
1727 * \retval 0 on success
1728 * \retval <0 if error occurs
1730 int llapi_layout_mirror_id_get(const struct llapi_layout *layout, uint32_t *id)
1732 struct llapi_layout_comp *comp;
1734 comp = __llapi_layout_cur_comp(layout);
1743 *id = mirror_id_of(comp->llc_id);
1749 * Adds a component to \a layout, the new component will be added to
1750 * the tail of components list and it'll inherit attributes of existing
1751 * ones. The \a layout will change it's current component pointer to
1752 * the newly added component, and it'll be turned into a composite
1753 * layout if it was not before the adding.
1755 * \param[in] layout existing composite or plain layout
1757 * \retval 0 on success
1758 * \retval <0 if error occurs
1760 int llapi_layout_comp_add(struct llapi_layout *layout)
1762 struct llapi_layout_comp *last, *comp, *new;
1764 comp = __llapi_layout_cur_comp(layout);
1768 new = __llapi_comp_alloc(0);
1772 last = list_entry(layout->llot_comp_list.prev, typeof(*last),
1775 /* Inherit some attributes from existing component */
1776 new->llc_stripe_size = comp->llc_stripe_size;
1777 new->llc_stripe_count = comp->llc_stripe_count;
1778 if (comp->llc_pool_name[0] != '\0')
1779 strncpy(new->llc_pool_name, comp->llc_pool_name,
1780 sizeof(comp->llc_pool_name));
1781 if (new->llc_extent.e_end <= last->llc_extent.e_end) {
1782 __llapi_comp_free(new);
1786 new->llc_extent.e_start = last->llc_extent.e_end;
1788 list_add_tail(&new->llc_list, &layout->llot_comp_list);
1789 layout->llot_cur_comp = new;
1790 layout->llot_is_composite = true;
1796 * Deletes current component from the composite layout. The component
1797 * to be deleted must be the tail of components list, and it can't be
1798 * the only component in the layout.
1800 * \param[in] layout composite layout
1802 * \retval 0 on success
1803 * \retval <0 if error occurs
1805 int llapi_layout_comp_del(struct llapi_layout *layout)
1807 struct llapi_layout_comp *comp;
1809 comp = __llapi_layout_cur_comp(layout);
1813 if (!layout->llot_is_composite) {
1818 /* It must be the tail of the list (for PFL, can be relaxed
1819 * once we get mirrored components) */
1820 if (comp->llc_list.next != &layout->llot_comp_list) {
1824 /* It can't be the only one on the list */
1825 if (comp->llc_list.prev == &layout->llot_comp_list) {
1830 layout->llot_cur_comp =
1831 list_entry(comp->llc_list.prev, typeof(*comp), llc_list);
1832 list_del_init(&comp->llc_list);
1833 __llapi_comp_free(comp);
1839 * Move the current component pointer to the component with
1840 * specified component ID.
1842 * \param[in] layout composite layout
1843 * \param[in] id component ID
1845 * \retval =0 : moved successfully
1846 * \retval <0 if error occurs
1848 int llapi_layout_comp_use_id(struct llapi_layout *layout, uint32_t comp_id)
1850 struct llapi_layout_comp *comp;
1852 comp = __llapi_layout_cur_comp(layout);
1854 return -1; /* use previously set errno */
1856 if (!layout->llot_is_composite) {
1861 if (comp_id == LCME_ID_INVAL) {
1866 list_for_each_entry(comp, &layout->llot_comp_list, llc_list) {
1867 if (comp->llc_id == comp_id) {
1868 layout->llot_cur_comp = comp;
1877 * Move the current component pointer to a specified position.
1879 * \param[in] layout composite layout
1880 * \param[in] pos the position to be moved, it can be:
1881 * LLAPI_LAYOUT_COMP_USE_FIRST: use first component
1882 * LLAPI_LAYOUT_COMP_USE_LAST: use last component
1883 * LLAPI_LAYOUT_COMP_USE_NEXT: use component after current
1884 * LLAPI_LAYOUT_COMP_USE_PREV: use component before current
1886 * \retval =0 : moved successfully
1887 * \retval =1 : at last component with NEXT, at first component with PREV
1888 * \retval <0 if error occurs
1890 int llapi_layout_comp_use(struct llapi_layout *layout,
1891 enum llapi_layout_comp_use pos)
1893 struct llapi_layout_comp *comp, *head, *tail;
1895 comp = __llapi_layout_cur_comp(layout);
1899 if (!layout->llot_is_composite) {
1900 if (pos == LLAPI_LAYOUT_COMP_USE_FIRST ||
1901 pos == LLAPI_LAYOUT_COMP_USE_LAST)
1907 head = list_entry(layout->llot_comp_list.next, typeof(*head), llc_list);
1908 tail = list_entry(layout->llot_comp_list.prev, typeof(*tail), llc_list);
1910 case LLAPI_LAYOUT_COMP_USE_FIRST:
1911 layout->llot_cur_comp = head;
1913 case LLAPI_LAYOUT_COMP_USE_NEXT:
1918 layout->llot_cur_comp = list_entry(comp->llc_list.next,
1919 typeof(*comp), llc_list);
1921 case LLAPI_LAYOUT_COMP_USE_LAST:
1922 layout->llot_cur_comp = tail;
1924 case LLAPI_LAYOUT_COMP_USE_PREV:
1929 layout->llot_cur_comp = list_entry(comp->llc_list.prev,
1930 typeof(*comp), llc_list);
1941 * Add layout component(s) to an existing file.
1943 * \param[in] path The path name of the file
1944 * \param[in] layout The layout component(s) to be added
1946 int llapi_layout_file_comp_add(const char *path,
1947 const struct llapi_layout *layout)
1949 int rc, fd, lum_size, tmp_errno = 0;
1950 struct lov_user_md *lum;
1952 if (path == NULL || layout == NULL ||
1953 layout->llot_magic != LLAPI_LAYOUT_MAGIC) {
1958 lum = llapi_layout_to_lum(layout);
1962 if (lum->lmm_magic != LOV_USER_MAGIC_COMP_V1) {
1967 lum_size = ((struct lov_comp_md_v1 *)lum)->lcm_size;
1969 fd = open(path, O_RDWR);
1976 rc = fsetxattr(fd, XATTR_LUSTRE_LOV".add", lum, lum_size, 0);
1991 * Delete component(s) by the specified component id or component flags
1992 * from an existing file.
1994 * \param[in] path path name of the file
1995 * \param[in] id unique component ID
1996 * \param[in] flags flags: LCME_FL_* or;
1997 * negative flags: (LCME_FL_NEG|LCME_FL_*)
1999 int llapi_layout_file_comp_del(const char *path, uint32_t id, uint32_t flags)
2001 int rc, fd, lum_size;
2002 struct llapi_layout *layout;
2003 struct llapi_layout_comp *comp;
2004 struct lov_user_md *lum;
2006 if (path == NULL || id > LCME_ID_MAX || (flags & ~LCME_KNOWN_FLAGS)) {
2011 /* Can only specify ID or flags, not both. */
2012 if (id != 0 && flags != 0) {
2017 layout = llapi_layout_alloc();
2021 llapi_layout_comp_extent_set(layout, 0, LUSTRE_EOF);
2022 comp = __llapi_layout_cur_comp(layout);
2024 llapi_layout_free(layout);
2029 comp->llc_flags = flags;
2031 lum = llapi_layout_to_lum(layout);
2033 llapi_layout_free(layout);
2036 lum_size = ((struct lov_comp_md_v1 *)lum)->lcm_size;
2038 fd = open(path, O_RDWR);
2044 rc = fsetxattr(fd, XATTR_LUSTRE_LOV".del", lum, lum_size, 0);
2046 int tmp_errno = errno;
2055 llapi_layout_free(layout);
2060 * Change flags or other parameters of the component(s) by component ID of an
2061 * existing file. The component to be modified is specified by the
2062 * comp->lcme_id value, which must be an unique component ID. The new
2063 * attributes are passed in by @comp and @valid is used to specify which
2064 * attributes in the component are going to be changed.
2066 int llapi_layout_file_comp_set(const char *path,
2067 const struct llapi_layout *comp,
2075 * Check if the file layout is composite.
2077 * \param[in] layout the file layout to check
2079 * \retval true composite
2080 * \retval false not composite
2082 bool llapi_layout_is_composite(struct llapi_layout *layout)
2084 return layout->llot_is_composite;