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 <lustre/lustre_idl.h>
42 #include "lustreapi_internal.h"
45 * Layout component, which contains all attributes of a plain
48 struct llapi_layout_comp {
50 uint64_t llc_stripe_size;
51 uint64_t llc_stripe_count;
52 uint64_t llc_stripe_offset;
53 /* Add 1 so user always gets back a null terminated string. */
54 char llc_pool_name[LOV_MAXPOOLNAME + 1];
55 /** Number of objects in llc_objects array if was initialized. */
56 uint32_t llc_objects_count;
57 struct lov_user_ost_data_v1 *llc_objects;
58 /* fields used only for composite layouts */
59 struct lu_extent llc_extent; /* [start, end) of component */
60 uint32_t llc_id; /* unique ID of component */
61 uint32_t llc_flags; /* LCME_FL_* flags */
62 struct list_head llc_list; /* linked to the llapi_layout
67 * An Opaque data type abstracting the layout of a Lustre file.
70 uint32_t llot_magic; /* LLAPI_LAYOUT_MAGIC */
73 bool llot_is_composite;
74 /* Cursor pointing to one of the components in llot_comp_list */
75 struct llapi_layout_comp *llot_cur_comp;
76 struct list_head llot_comp_list;
80 * Compute the number of elements in the lmm_objects array of \a lum
81 * with size \a lum_size.
83 * \param[in] lum the struct lov_user_md to check
84 * \param[in] lum_size the number of bytes in \a lum
86 * \retval number of elements in array lum->lmm_objects
88 static int llapi_layout_objects_in_lum(struct lov_user_md *lum, size_t lum_size)
93 if (lum_size < lov_user_md_size(0, LOV_MAGIC_V1))
96 if (lum->lmm_magic == __swab32(LOV_MAGIC_V1) ||
97 lum->lmm_magic == __swab32(LOV_MAGIC_V3))
98 magic = __swab32(lum->lmm_magic);
100 magic = lum->lmm_magic;
102 base_size = lov_user_md_size(0, magic);
104 if (lum_size <= base_size)
107 return (lum_size - base_size) / sizeof(lum->lmm_objects[0]);
111 * Byte-swap the fields of struct lov_user_md.
113 * XXX Rather than duplicating swabbing code here, we should eventually
114 * refactor the needed functions in lustre/ptlrpc/pack_generic.c
115 * into a library that can be shared between kernel and user code.
118 llapi_layout_swab_lov_user_md(struct lov_user_md *lum, int lum_size)
120 int i, j, ent_count, obj_count;
121 struct lov_comp_md_v1 *comp_v1 = NULL;
122 struct lov_comp_md_entry_v1 *ent;
123 struct lov_user_ost_data *lod;
125 if (lum->lmm_magic != __swab32(LOV_MAGIC_V1) &&
126 lum->lmm_magic != __swab32(LOV_MAGIC_V3) &&
127 lum->lmm_magic != __swab32(LOV_MAGIC_COMP_V1))
130 if (lum->lmm_magic == __swab32(LOV_MAGIC_COMP_V1))
131 comp_v1 = (struct lov_comp_md_v1 *)lum;
133 if (comp_v1 != NULL) {
134 __swab32s(&comp_v1->lcm_magic);
135 __swab32s(&comp_v1->lcm_size);
136 __swab32s(&comp_v1->lcm_layout_gen);
137 __swab16s(&comp_v1->lcm_flags);
138 __swab16s(&comp_v1->lcm_entry_count);
139 ent_count = comp_v1->lcm_entry_count;
144 for (i = 0; i < ent_count; i++) {
145 if (comp_v1 != NULL) {
146 ent = &comp_v1->lcm_entries[i];
147 __swab32s(&ent->lcme_id);
148 __swab32s(&ent->lcme_flags);
149 __swab64s(&ent->lcme_extent.e_start);
150 __swab64s(&ent->lcme_extent.e_end);
151 __swab32s(&ent->lcme_offset);
152 __swab32s(&ent->lcme_size);
154 lum = (struct lov_user_md *)((char *)comp_v1 +
156 lum_size = ent->lcme_size;
158 obj_count = llapi_layout_objects_in_lum(lum, lum_size);
160 __swab32s(&lum->lmm_magic);
161 __swab32s(&lum->lmm_pattern);
162 __swab32s(&lum->lmm_stripe_size);
163 __swab16s(&lum->lmm_stripe_count);
164 __swab16s(&lum->lmm_stripe_offset);
166 if (lum->lmm_magic != LOV_MAGIC_V1) {
167 struct lov_user_md_v3 *v3;
168 v3 = (struct lov_user_md_v3 *)lum;
169 lod = v3->lmm_objects;
171 lod = lum->lmm_objects;
174 for (j = 0; j < obj_count; j++)
175 __swab32s(&lod[j].l_ost_idx);
180 * (Re-)allocate llc_objects[] to \a num_stripes stripes.
182 * Copy over existing llc_objects[], if any, to the new llc_objects[].
184 * \param[in] layout existing layout to be modified
185 * \param[in] num_stripes number of stripes in new layout
187 * \retval 0 if the objects are re-allocated successfully
188 * \retval -1 on error with errno set
190 static int __llapi_comp_objects_realloc(struct llapi_layout_comp *comp,
191 unsigned int new_stripes)
193 struct lov_user_ost_data_v1 *new_objects;
196 if (new_stripes > LOV_MAX_STRIPE_COUNT) {
201 if (new_stripes == comp->llc_objects_count)
204 if (new_stripes != 0 && new_stripes <= comp->llc_objects_count)
207 new_objects = realloc(comp->llc_objects,
208 sizeof(*new_objects) * new_stripes);
209 if (new_objects == NULL && new_stripes != 0) {
214 for (i = comp->llc_objects_count; i < new_stripes; i++)
215 new_objects[i].l_ost_idx = LLAPI_LAYOUT_IDX_MAX;
217 comp->llc_objects = new_objects;
218 comp->llc_objects_count = new_stripes;
224 * Allocate storage for a llapi_layout_comp with \a num_stripes stripes.
226 * \param[in] num_stripes number of stripes in new layout
228 * \retval valid pointer if allocation succeeds
229 * \retval NULL if allocation fails
231 static struct llapi_layout_comp *__llapi_comp_alloc(unsigned int num_stripes)
233 struct llapi_layout_comp *comp;
235 if (num_stripes > LOV_MAX_STRIPE_COUNT) {
240 comp = calloc(1, sizeof(*comp));
246 comp->llc_objects = NULL;
247 comp->llc_objects_count = 0;
249 if (__llapi_comp_objects_realloc(comp, num_stripes) < 0) {
255 comp->llc_pattern = LLAPI_LAYOUT_DEFAULT;
256 comp->llc_stripe_size = LLAPI_LAYOUT_DEFAULT;
257 comp->llc_stripe_count = LLAPI_LAYOUT_DEFAULT;
258 comp->llc_stripe_offset = LLAPI_LAYOUT_DEFAULT;
259 comp->llc_pool_name[0] = '\0';
260 comp->llc_extent.e_start = 0;
261 comp->llc_extent.e_end = LUSTRE_EOF;
264 INIT_LIST_HEAD(&comp->llc_list);
270 * Free memory allocated for \a comp
272 * \param[in] comp previously allocated by __llapi_comp_alloc()
274 static void __llapi_comp_free(struct llapi_layout_comp *comp)
276 if (comp->llc_objects != NULL)
277 free(comp->llc_objects);
282 * Free memory allocated for \a layout.
284 * \param[in] layout previously allocated by llapi_layout_alloc()
286 void llapi_layout_free(struct llapi_layout *layout)
288 struct llapi_layout_comp *comp, *n;
293 list_for_each_entry_safe(comp, n, &layout->llot_comp_list, llc_list) {
294 list_del_init(&comp->llc_list);
295 __llapi_comp_free(comp);
301 * Allocate and initialize a llapi_layout structure.
303 * \retval valid llapi_layout pointer on success
304 * \retval NULL if memory allocation fails
306 static struct llapi_layout *__llapi_layout_alloc(void)
308 struct llapi_layout *layout;
310 layout = calloc(1, sizeof(*layout));
311 if (layout == NULL) {
317 layout->llot_magic = LLAPI_LAYOUT_MAGIC;
318 layout->llot_gen = 0;
319 layout->llot_flags = 0;
320 layout->llot_is_composite = false;
321 layout->llot_cur_comp = NULL;
322 INIT_LIST_HEAD(&layout->llot_comp_list);
328 * Allocate and initialize a new plain layout.
330 * \retval valid llapi_layout pointer on success
331 * \retval NULL if memory allocation fails
333 struct llapi_layout *llapi_layout_alloc(void)
335 struct llapi_layout_comp *comp;
336 struct llapi_layout *layout;
338 layout = __llapi_layout_alloc();
342 comp = __llapi_comp_alloc(0);
348 list_add_tail(&comp->llc_list, &layout->llot_comp_list);
349 layout->llot_cur_comp = comp;
355 * Convert the data from a lov_user_md to a newly allocated llapi_layout.
356 * The caller is responsible for freeing the returned pointer.
358 * \param[in] lum LOV user metadata structure to copy data from
359 * \param[in] lum_size size the the lum passed in
361 * \retval valid llapi_layout pointer on success
362 * \retval NULL if memory allocation fails
364 static struct llapi_layout *
365 llapi_layout_from_lum(const struct lov_user_md *lum, int lum_size)
367 struct lov_comp_md_v1 *comp_v1 = NULL;
368 struct lov_comp_md_entry_v1 *ent;
369 struct lov_user_md *v1;
370 struct llapi_layout *layout;
371 struct llapi_layout_comp *comp;
372 int i, ent_count = 0, obj_count;
374 layout = __llapi_layout_alloc();
378 if (lum->lmm_magic == LOV_MAGIC_COMP_V1) {
379 comp_v1 = (struct lov_comp_md_v1 *)lum;
380 ent_count = comp_v1->lcm_entry_count;
381 layout->llot_is_composite = true;
382 layout->llot_gen = comp_v1->lcm_layout_gen;
383 layout->llot_flags = comp_v1->lcm_flags;
384 } else if (lum->lmm_magic == LOV_MAGIC_V1 ||
385 lum->lmm_magic == LOV_MAGIC_V3) {
387 layout->llot_is_composite = false;
390 if (ent_count == 0) {
395 v1 = (struct lov_user_md *)lum;
396 for (i = 0; i < ent_count; i++) {
397 if (comp_v1 != NULL) {
398 ent = &comp_v1->lcm_entries[i];
399 v1 = (struct lov_user_md *)((char *)comp_v1 +
401 lum_size = ent->lcme_size;
406 obj_count = llapi_layout_objects_in_lum(v1, lum_size);
407 comp = __llapi_comp_alloc(obj_count);
412 comp->llc_extent.e_start = ent->lcme_extent.e_start;
413 comp->llc_extent.e_end = ent->lcme_extent.e_end;
414 comp->llc_id = ent->lcme_id;
415 comp->llc_flags = ent->lcme_flags;
417 comp->llc_extent.e_start = 0;
418 comp->llc_extent.e_end = LUSTRE_EOF;
423 if (v1->lmm_pattern == LOV_PATTERN_RAID0)
424 comp->llc_pattern = LLAPI_LAYOUT_RAID0;
426 /* Lustre only supports RAID0 for now. */
427 comp->llc_pattern = v1->lmm_pattern;
429 if (v1->lmm_stripe_size == 0)
430 comp->llc_stripe_size = LLAPI_LAYOUT_DEFAULT;
432 comp->llc_stripe_size = v1->lmm_stripe_size;
434 if (v1->lmm_stripe_count == (typeof(v1->lmm_stripe_count))-1)
435 comp->llc_stripe_count = LLAPI_LAYOUT_WIDE;
436 else if (v1->lmm_stripe_count == 0)
437 comp->llc_stripe_count = LLAPI_LAYOUT_DEFAULT;
439 comp->llc_stripe_count = v1->lmm_stripe_count;
441 if (v1->lmm_stripe_offset ==
442 (typeof(v1->lmm_stripe_offset))-1)
443 comp->llc_stripe_offset = LLAPI_LAYOUT_DEFAULT;
445 comp->llc_stripe_offset = v1->lmm_stripe_offset;
447 if (v1->lmm_magic != LOV_USER_MAGIC_V1) {
448 const struct lov_user_md_v3 *lumv3;
449 lumv3 = (struct lov_user_md_v3 *)v1;
450 snprintf(comp->llc_pool_name,
451 sizeof(comp->llc_pool_name),
452 "%s", lumv3->lmm_pool_name);
453 memcpy(comp->llc_objects, lumv3->lmm_objects,
454 obj_count * sizeof(lumv3->lmm_objects[0]));
456 const struct lov_user_md_v1 *lumv1;
457 lumv1 = (struct lov_user_md_v1 *)v1;
458 memcpy(comp->llc_objects, lumv1->lmm_objects,
459 obj_count * sizeof(lumv1->lmm_objects[0]));
463 comp->llc_stripe_offset =
464 comp->llc_objects[0].l_ost_idx;
466 list_add_tail(&comp->llc_list, &layout->llot_comp_list);
467 layout->llot_cur_comp = comp;
472 llapi_layout_free(layout);
477 * Convert the data from a llapi_layout to a newly allocated lov_user_md.
478 * The caller is responsible for freeing the returned pointer.
480 * \param[in] layout the layout to copy from
482 * \retval valid lov_user_md pointer on success
483 * \retval NULL if memory allocation fails or the layout is invalid
485 static struct lov_user_md *
486 llapi_layout_to_lum(const struct llapi_layout *layout)
488 struct llapi_layout_comp *comp;
489 struct lov_comp_md_v1 *comp_v1 = NULL;
490 struct lov_comp_md_entry_v1 *ent;
491 struct lov_user_md *lum = NULL;
496 if (layout == NULL ||
497 list_empty((struct list_head *)&layout->llot_comp_list)) {
502 /* Allocate header of lov_comp_md_v1 if necessary */
503 if (layout->llot_is_composite) {
506 list_for_each_entry(comp, &layout->llot_comp_list, llc_list)
509 lum_size = sizeof(*comp_v1) + comp_cnt * sizeof(*ent);
510 lum = malloc(lum_size);
515 comp_v1 = (struct lov_comp_md_v1 *)lum;
516 comp_v1->lcm_magic = LOV_USER_MAGIC_COMP_V1;
517 comp_v1->lcm_size = lum_size;
518 comp_v1->lcm_layout_gen = 0;
519 comp_v1->lcm_flags = 0;
520 comp_v1->lcm_entry_count = comp_cnt;
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 blob = (struct lov_user_md *)((char *)lum + lum_size);
564 lum_size += blob_size;
567 blob->lmm_magic = magic;
568 if (pattern == LLAPI_LAYOUT_DEFAULT)
569 blob->lmm_pattern = 0;
570 else if (pattern == LLAPI_LAYOUT_RAID0)
571 blob->lmm_pattern = LOV_PATTERN_RAID0;
573 blob->lmm_pattern = pattern;
575 if (comp->llc_stripe_size == LLAPI_LAYOUT_DEFAULT)
576 blob->lmm_stripe_size = 0;
578 blob->lmm_stripe_size = comp->llc_stripe_size;
580 if (comp->llc_stripe_count == LLAPI_LAYOUT_DEFAULT)
581 blob->lmm_stripe_count = 0;
582 else if (comp->llc_stripe_count == LLAPI_LAYOUT_WIDE)
583 blob->lmm_stripe_count = LOV_ALL_STRIPES;
585 blob->lmm_stripe_count = comp->llc_stripe_count;
587 if (comp->llc_stripe_offset == LLAPI_LAYOUT_DEFAULT)
588 blob->lmm_stripe_offset = -1;
590 blob->lmm_stripe_offset = comp->llc_stripe_offset;
592 if (magic == LOV_USER_MAGIC_V3 ||
593 magic == LOV_USER_MAGIC_SPECIFIC) {
594 struct lov_user_md_v3 *lumv3 =
595 (struct lov_user_md_v3 *)blob;
597 if (comp->llc_pool_name[0] != '\0') {
598 strncpy(lumv3->lmm_pool_name,
600 sizeof(lumv3->lmm_pool_name));
602 memset(lumv3->lmm_pool_name, 0,
603 sizeof(lumv3->lmm_pool_name));
605 lmm_objects = lumv3->lmm_objects;
607 lmm_objects = blob->lmm_objects;
610 for (i = 0; i < obj_count; i++)
611 lmm_objects[i].l_ost_idx =
612 comp->llc_objects[i].l_ost_idx;
614 if (comp_v1 != NULL) {
615 ent = &comp_v1->lcm_entries[ent_idx];
616 ent->lcme_id = comp->llc_id;
617 ent->lcme_flags = comp->llc_flags;
618 ent->lcme_extent.e_start = comp->llc_extent.e_start;
619 ent->lcme_extent.e_end = comp->llc_extent.e_end;
620 ent->lcme_size = blob_size;
621 ent->lcme_offset = offset;
623 comp_v1->lcm_size += blob_size;
637 * Get the parent directory of a path.
639 * \param[in] path path to get parent of
640 * \param[out] buf buffer in which to store parent path
641 * \param[in] size size in bytes of buffer \a buf
643 static void get_parent_dir(const char *path, char *buf, size_t size)
647 strncpy(buf, path, size);
648 p = strrchr(buf, '/');
653 strncpy(buf, ".", 2);
657 * Substitute unspecified attribute values in \a layout with values
658 * from fs global settings. (lov.stripesize, lov.stripecount,
661 * \param[in] layout layout to inherit values from
662 * \param[in] path file path of the filesystem
664 static void inherit_sys_attributes(struct llapi_layout *layout,
667 struct llapi_layout_comp *comp;
668 unsigned int ssize, scount, soffset;
671 rc = sattr_cache_get_defaults(NULL, path, &scount, &ssize, &soffset);
675 list_for_each_entry(comp, &layout->llot_comp_list, llc_list) {
676 if (comp->llc_pattern == LLAPI_LAYOUT_DEFAULT)
677 comp->llc_pattern = LLAPI_LAYOUT_RAID0;
678 if (comp->llc_stripe_size == LLAPI_LAYOUT_DEFAULT)
679 comp->llc_stripe_size = ssize;
680 if (comp->llc_stripe_count == LLAPI_LAYOUT_DEFAULT)
681 comp->llc_stripe_count = scount;
682 if (comp->llc_stripe_offset == LLAPI_LAYOUT_DEFAULT)
683 comp->llc_stripe_offset = soffset;
688 * Get the current component of \a layout.
690 * \param[in] layout layout to get current component
692 * \retval valid llapi_layout_comp pointer on success
693 * \retval NULL on error
695 static struct llapi_layout_comp *
696 __llapi_layout_cur_comp(const struct llapi_layout *layout)
698 struct llapi_layout_comp *comp;
700 if (layout == NULL || layout->llot_magic != LLAPI_LAYOUT_MAGIC) {
704 if (layout->llot_cur_comp == NULL) {
708 /* Verify data consistency */
709 list_for_each_entry(comp, &layout->llot_comp_list, llc_list)
710 if (comp == layout->llot_cur_comp)
717 * Test if any attributes of \a layout are specified.
719 * \param[in] layout the layout to check
721 * \retval true any attributes are specified
722 * \retval false all attributes are unspecified
724 static bool is_any_specified(const struct llapi_layout *layout)
726 struct llapi_layout_comp *comp;
728 comp = __llapi_layout_cur_comp(layout);
732 if (layout->llot_is_composite)
735 return comp->llc_pattern != LLAPI_LAYOUT_DEFAULT ||
736 comp->llc_stripe_size != LLAPI_LAYOUT_DEFAULT ||
737 comp->llc_stripe_count != LLAPI_LAYOUT_DEFAULT ||
738 comp->llc_stripe_offset != LLAPI_LAYOUT_DEFAULT ||
739 strlen(comp->llc_pool_name);
743 * Check if the given \a lum_size is large enough to hold the required
746 * \param[in] lum the struct lov_user_md to check
747 * \param[in] lum_size the number of bytes in \a lum
749 * \retval true the \a lum_size is too small
750 * \retval false the \a lum_size is large enough
752 static bool llapi_layout_lum_truncated(struct lov_user_md *lum, size_t lum_size)
756 if (lum_size < sizeof(lum->lmm_magic))
759 if (lum->lmm_magic == LOV_MAGIC_V1 ||
760 lum->lmm_magic == __swab32(LOV_MAGIC_V1))
761 magic = LOV_MAGIC_V1;
762 else if (lum->lmm_magic == LOV_MAGIC_V3 ||
763 lum->lmm_magic == __swab32(LOV_MAGIC_V3))
764 magic = LOV_MAGIC_V3;
765 else if (lum->lmm_magic == LOV_MAGIC_COMP_V1 ||
766 lum->lmm_magic == __swab32(LOV_MAGIC_COMP_V1))
767 magic = LOV_MAGIC_COMP_V1;
771 if (magic == LOV_MAGIC_V1 || magic == LOV_MAGIC_V3)
772 return lum_size < lov_user_md_size(0, magic);
774 return lum_size < sizeof(struct lov_comp_md_v1);
777 /* Verify if the objects count in lum is consistent with the
778 * stripe count in lum. It applies to regular file only. */
779 static bool llapi_layout_lum_valid(struct lov_user_md *lum, int lum_size)
781 struct lov_comp_md_v1 *comp_v1 = NULL;
782 int i, ent_count, obj_count;
784 if (lum->lmm_magic == LOV_MAGIC_COMP_V1) {
785 comp_v1 = (struct lov_comp_md_v1 *)lum;
786 ent_count = comp_v1->lcm_entry_count;
787 } else if (lum->lmm_magic == LOV_MAGIC_V1 ||
788 lum->lmm_magic == LOV_MAGIC_V3) {
794 for (i = 0; i < ent_count; i++) {
796 lum = (struct lov_user_md *)((char *)comp_v1 +
797 comp_v1->lcm_entries[i].lcme_offset);
798 lum_size = comp_v1->lcm_entries[i].lcme_size;
800 obj_count = llapi_layout_objects_in_lum(lum, lum_size);
803 if (!(comp_v1->lcm_entries[i].lcme_flags &
804 LCME_FL_INIT) && obj_count != 0)
806 } else if (obj_count != lum->lmm_stripe_count) {
814 * Get the striping layout for the file referenced by file descriptor \a fd.
816 * If the filesystem does not support the "lustre." xattr namespace, the
817 * file must be on a non-Lustre filesystem, so set errno to ENOTTY per
818 * convention. If the file has no "lustre.lov" data, the file will
819 * inherit default values, so return a default layout.
821 * If the kernel gives us back less than the expected amount of data,
822 * we fail with errno set to EINTR.
824 * \param[in] fd open file descriptor
825 * \param[in] flags open file descriptor
827 * \retval valid llapi_layout pointer on success
828 * \retval NULL if an error occurs
830 struct llapi_layout *llapi_layout_get_by_fd(int fd, uint32_t flags)
833 struct lov_user_md *lum;
834 struct llapi_layout *layout = NULL;
838 lum_len = XATTR_SIZE_MAX;
839 lum = malloc(lum_len);
843 bytes_read = fgetxattr(fd, XATTR_LUSTRE_LOV, lum, lum_len);
844 if (bytes_read < 0) {
845 if (errno == EOPNOTSUPP)
847 else if (errno == ENODATA)
848 layout = llapi_layout_alloc();
852 /* Return an error if we got back a partial layout. */
853 if (llapi_layout_lum_truncated(lum, bytes_read)) {
858 llapi_layout_swab_lov_user_md(lum, bytes_read);
860 /* Directories may have a positive non-zero lum->lmm_stripe_count
861 * yet have an empty lum->lmm_objects array. For non-directories the
862 * amount of data returned from the kernel must be consistent
863 * with the stripe count. */
864 if (fstat(fd, &st) < 0)
867 if (!S_ISDIR(st.st_mode) && !llapi_layout_lum_valid(lum, bytes_read)) {
872 layout = llapi_layout_from_lum(lum, bytes_read);
879 * Get the expected striping layout for a file at \a path.
881 * Substitute expected inherited attribute values for unspecified
882 * attributes. Unspecified attributes may belong to directories and
883 * never-written-to files, and indicate that default values will be
884 * assigned when files are created or first written to. A default value
885 * is inherited from the parent directory if the attribute is specified
886 * there, otherwise it is inherited from the filesystem root.
887 * Unspecified attributes normally have the value LLAPI_LAYOUT_DEFAULT.
889 * The complete \a path need not refer to an existing file or directory,
890 * but some leading portion of it must reside within a lustre filesystem.
891 * A use case for this interface would be to obtain the literal striping
892 * values that would be assigned to a new file in a given directory.
894 * \param[in] path path for which to get the expected layout
896 * \retval valid llapi_layout pointer on success
897 * \retval NULL if an error occurs
899 static struct llapi_layout *llapi_layout_expected(const char *path)
901 struct llapi_layout *path_layout = NULL;
902 char donor_path[PATH_MAX];
907 fd = open(path, O_RDONLY);
908 if (fd < 0 && errno != ENOENT)
914 path_layout = llapi_layout_get_by_fd(fd, 0);
920 if (path_layout == NULL) {
921 if (errno != ENODATA && errno != ENOENT)
924 path_layout = llapi_layout_alloc();
925 if (path_layout == NULL)
929 if (is_any_specified(path_layout)) {
930 inherit_sys_attributes(path_layout, path);
934 llapi_layout_free(path_layout);
936 rc = stat(path, &st);
937 if (rc < 0 && errno != ENOENT)
940 /* If path is a not a directory or doesn't exist, inherit layout
941 * from parent directory. */
942 if ((rc == 0 && !S_ISDIR(st.st_mode)) ||
943 (rc < 0 && errno == ENOENT)) {
944 get_parent_dir(path, donor_path, sizeof(donor_path));
945 path_layout = llapi_layout_get_by_path(donor_path, 0);
946 if (path_layout != NULL) {
947 if (is_any_specified(path_layout)) {
948 inherit_sys_attributes(path_layout, donor_path);
951 llapi_layout_free(path_layout);
955 /* Inherit layout from the filesystem root. */
956 rc = llapi_search_mounts(path, 0, donor_path, NULL);
959 path_layout = llapi_layout_get_by_path(donor_path, 0);
960 if (path_layout == NULL)
963 inherit_sys_attributes(path_layout, donor_path);
968 * Get the striping layout for the file at \a path.
970 * If \a flags contains LAYOUT_GET_EXPECTED, substitute
971 * expected inherited attribute values for unspecified attributes. See
972 * llapi_layout_expected().
974 * \param[in] path path for which to get the layout
975 * \param[in] flags flags to control how layout is retrieved
977 * \retval valid llapi_layout pointer on success
978 * \retval NULL if an error occurs
980 struct llapi_layout *llapi_layout_get_by_path(const char *path, uint32_t flags)
982 struct llapi_layout *layout = NULL;
986 if (flags & LAYOUT_GET_EXPECTED)
987 return llapi_layout_expected(path);
989 fd = open(path, O_RDONLY);
993 layout = llapi_layout_get_by_fd(fd, flags);
1002 * Get the layout for the file with FID \a fidstr in filesystem \a lustre_dir.
1004 * \param[in] lustre_dir path within Lustre filesystem containing \a fid
1005 * \param[in] fid Lustre identifier of file to get layout for
1007 * \retval valid llapi_layout pointer on success
1008 * \retval NULL if an error occurs
1010 struct llapi_layout *llapi_layout_get_by_fid(const char *lustre_dir,
1011 const lustre_fid *fid,
1016 int saved_msg_level = llapi_msg_get_level();
1017 struct llapi_layout *layout = NULL;
1019 /* Prevent llapi internal routines from writing to console
1020 * while executing this function, then restore previous message
1022 llapi_msg_set_level(LLAPI_MSG_OFF);
1023 fd = llapi_open_by_fid(lustre_dir, fid, O_RDONLY);
1024 llapi_msg_set_level(saved_msg_level);
1029 layout = llapi_layout_get_by_fd(fd, flags);
1038 * Get the stripe count of \a layout.
1040 * \param[in] layout layout to get stripe count from
1041 * \param[out] count integer to store stripe count in
1043 * \retval 0 on success
1044 * \retval -1 if arguments are invalid
1046 int llapi_layout_stripe_count_get(const struct llapi_layout *layout,
1049 struct llapi_layout_comp *comp;
1051 comp = __llapi_layout_cur_comp(layout);
1055 if (count == NULL) {
1060 *count = comp->llc_stripe_count;
1066 * The llapi_layout API functions have these extra validity checks since
1067 * they use intuitively named macros to denote special behavior, whereas
1068 * the old API uses 0 and -1.
1071 static bool llapi_layout_stripe_count_is_valid(int64_t stripe_count)
1073 return stripe_count == LLAPI_LAYOUT_DEFAULT ||
1074 stripe_count == LLAPI_LAYOUT_WIDE ||
1075 (stripe_count != 0 && stripe_count != -1 &&
1076 llapi_stripe_count_is_valid(stripe_count));
1079 static bool llapi_layout_stripe_size_is_valid(uint64_t stripe_size)
1081 return stripe_size == LLAPI_LAYOUT_DEFAULT ||
1082 (stripe_size != 0 &&
1083 llapi_stripe_size_is_aligned(stripe_size) &&
1084 !llapi_stripe_size_is_too_big(stripe_size));
1087 static bool llapi_layout_stripe_index_is_valid(int64_t stripe_index)
1089 return stripe_index == LLAPI_LAYOUT_DEFAULT ||
1090 (stripe_index >= 0 &&
1091 llapi_stripe_index_is_valid(stripe_index));
1095 * Set the stripe count of \a layout.
1097 * \param[in] layout layout to set stripe count in
1098 * \param[in] count value to be set
1100 * \retval 0 on success
1101 * \retval -1 if arguments are invalid
1103 int llapi_layout_stripe_count_set(struct llapi_layout *layout,
1106 struct llapi_layout_comp *comp;
1108 comp = __llapi_layout_cur_comp(layout);
1112 if (!llapi_layout_stripe_count_is_valid(count)) {
1117 comp->llc_stripe_count = count;
1123 * Get the stripe size of \a layout.
1125 * \param[in] layout layout to get stripe size from
1126 * \param[out] size integer to store stripe size in
1128 * \retval 0 on success
1129 * \retval -1 if arguments are invalid
1131 int llapi_layout_stripe_size_get(const struct llapi_layout *layout,
1134 struct llapi_layout_comp *comp;
1136 comp = __llapi_layout_cur_comp(layout);
1145 *size = comp->llc_stripe_size;
1151 * Set the stripe size of \a layout.
1153 * \param[in] layout layout to set stripe size in
1154 * \param[in] size value to be set
1156 * \retval 0 on success
1157 * \retval -1 if arguments are invalid
1159 int llapi_layout_stripe_size_set(struct llapi_layout *layout,
1162 struct llapi_layout_comp *comp;
1164 comp = __llapi_layout_cur_comp(layout);
1168 if (!llapi_layout_stripe_size_is_valid(size)) {
1173 comp->llc_stripe_size = size;
1179 * Get the RAID pattern of \a layout.
1181 * \param[in] layout layout to get pattern from
1182 * \param[out] pattern integer to store pattern in
1184 * \retval 0 on success
1185 * \retval -1 if arguments are invalid
1187 int llapi_layout_pattern_get(const struct llapi_layout *layout,
1190 struct llapi_layout_comp *comp;
1192 comp = __llapi_layout_cur_comp(layout);
1196 if (pattern == NULL) {
1201 *pattern = comp->llc_pattern;
1207 * Set the RAID pattern of \a layout.
1209 * \param[in] layout layout to set pattern in
1210 * \param[in] pattern value to be set
1212 * \retval 0 on success
1213 * \retval -1 if arguments are invalid or RAID pattern
1216 int llapi_layout_pattern_set(struct llapi_layout *layout, uint64_t pattern)
1218 struct llapi_layout_comp *comp;
1220 comp = __llapi_layout_cur_comp(layout);
1224 if (pattern != LLAPI_LAYOUT_DEFAULT &&
1225 pattern != LLAPI_LAYOUT_RAID0) {
1230 comp->llc_pattern = pattern |
1231 (comp->llc_pattern & LLAPI_LAYOUT_SPECIFIC);
1236 static inline int stripe_number_roundup(int stripe_number)
1238 unsigned int round_up = (stripe_number + 8) & ~7;
1239 return round_up > LOV_MAX_STRIPE_COUNT ?
1240 LOV_MAX_STRIPE_COUNT : round_up;
1244 * Set the OST index of stripe number \a stripe_number to \a ost_index.
1246 * If only the starting stripe's OST index is specified, then this can use
1247 * the normal LOV_MAGIC_{V1,V3} layout type. If multiple OST indices are
1248 * given, then allocate an array to hold the list of indices and ensure that
1249 * the LOV_USER_MAGIC_SPECIFIC layout is used when creating the file.
1251 * \param[in] layout layout to set OST index in
1252 * \param[in] stripe_number stripe number to set index for
1253 * \param[in] ost_index the index to set
1255 * \retval 0 on success
1256 * \retval -1 if arguments are invalid or an unsupported stripe number
1257 * was specified, error returned in errno
1259 int llapi_layout_ost_index_set(struct llapi_layout *layout, int stripe_number,
1262 struct llapi_layout_comp *comp;
1264 comp = __llapi_layout_cur_comp(layout);
1268 if (!llapi_layout_stripe_index_is_valid(ost_index)) {
1273 if (stripe_number == 0 && ost_index == LLAPI_LAYOUT_DEFAULT) {
1274 comp->llc_stripe_offset = ost_index;
1275 comp->llc_pattern &= ~LLAPI_LAYOUT_SPECIFIC;
1276 __llapi_comp_objects_realloc(comp, 0);
1277 } else if (stripe_number >= 0 &&
1278 stripe_number < LOV_MAX_STRIPE_COUNT) {
1279 if (ost_index >= LLAPI_LAYOUT_IDX_MAX) {
1284 /* Preallocate a few more stripes to avoid realloc() overhead.*/
1285 if (__llapi_comp_objects_realloc(comp,
1286 stripe_number_roundup(stripe_number)) < 0)
1289 comp->llc_objects[stripe_number].l_ost_idx = ost_index;
1291 if (stripe_number == 0)
1292 comp->llc_stripe_offset = ost_index;
1294 comp->llc_pattern |= LLAPI_LAYOUT_SPECIFIC;
1296 if (comp->llc_stripe_count == LLAPI_LAYOUT_DEFAULT ||
1297 comp->llc_stripe_count <= stripe_number)
1298 comp->llc_stripe_count = stripe_number + 1;
1308 * Get the OST index associated with stripe \a stripe_number.
1310 * Stripes are indexed starting from zero.
1312 * \param[in] layout layout to get index from
1313 * \param[in] stripe_number stripe number to get index for
1314 * \param[out] index integer to store index in
1316 * \retval 0 on success
1317 * \retval -1 if arguments are invalid
1319 int llapi_layout_ost_index_get(const struct llapi_layout *layout,
1320 uint64_t stripe_number, uint64_t *index)
1322 struct llapi_layout_comp *comp;
1324 comp = __llapi_layout_cur_comp(layout);
1328 if (index == NULL) {
1333 if (stripe_number >= comp->llc_stripe_count ||
1334 stripe_number >= comp->llc_objects_count) {
1339 if (comp->llc_stripe_offset == LLAPI_LAYOUT_DEFAULT)
1340 *index = LLAPI_LAYOUT_DEFAULT;
1342 *index = comp->llc_objects[stripe_number].l_ost_idx;
1349 * Get the pool name of layout \a layout.
1351 * \param[in] layout layout to get pool name from
1352 * \param[out] dest buffer to store pool name in
1353 * \param[in] n size in bytes of buffer \a dest
1355 * \retval 0 on success
1356 * \retval -1 if arguments are invalid
1358 int llapi_layout_pool_name_get(const struct llapi_layout *layout, char *dest,
1361 struct llapi_layout_comp *comp;
1363 comp = __llapi_layout_cur_comp(layout);
1372 strncpy(dest, comp->llc_pool_name, n);
1378 * Set the name of the pool of layout \a layout.
1380 * \param[in] layout layout to set pool name in
1381 * \param[in] pool_name pool name to set
1383 * \retval 0 on success
1384 * \retval -1 if arguments are invalid or pool name is too long
1386 int llapi_layout_pool_name_set(struct llapi_layout *layout,
1387 const char *pool_name)
1389 struct llapi_layout_comp *comp;
1392 comp = __llapi_layout_cur_comp(layout);
1396 if (pool_name == NULL) {
1401 /* Strip off any 'fsname.' portion. */
1402 ptr = strchr(pool_name, '.');
1404 pool_name = ptr + 1;
1406 if (strlen(pool_name) > LOV_MAXPOOLNAME) {
1411 strncpy(comp->llc_pool_name, pool_name, sizeof(comp->llc_pool_name));
1417 * Open and possibly create a file with a given \a layout.
1419 * If \a layout is NULL this function acts as a simple wrapper for
1420 * open(). By convention, ENOTTY is returned in errno if \a path
1421 * refers to a non-Lustre file.
1423 * \param[in] path name of the file to open
1424 * \param[in] open_flags open() flags
1425 * \param[in] mode permissions to create new file with
1426 * \param[in] layout layout to create new file with
1428 * \retval non-negative file descriptor on successful open
1429 * \retval -1 if an error occurred
1431 int llapi_layout_file_open(const char *path, int open_flags, mode_t mode,
1432 const struct llapi_layout *layout)
1437 struct lov_user_md *lum;
1441 (layout != NULL && layout->llot_magic != LLAPI_LAYOUT_MAGIC)) {
1446 /* Object creation must be postponed until after layout attributes
1447 * have been applied. */
1448 if (layout != NULL && (open_flags & O_CREAT))
1449 open_flags |= O_LOV_DELAY_CREATE;
1451 fd = open(path, open_flags, mode);
1453 if (layout == NULL || fd < 0)
1456 lum = llapi_layout_to_lum(layout);
1465 if (lum->lmm_magic == LOV_USER_MAGIC_COMP_V1)
1466 lum_size = ((struct lov_comp_md_v1 *)lum)->lcm_size;
1467 else if (lum->lmm_magic == LOV_USER_MAGIC_SPECIFIC)
1468 lum_size = lov_user_md_size(lum->lmm_stripe_count,
1471 lum_size = lov_user_md_size(0, lum->lmm_magic);
1473 rc = fsetxattr(fd, XATTR_LUSTRE_LOV, lum, lum_size, 0);
1482 errno = errno == EOPNOTSUPP ? ENOTTY : errno;
1488 * Create a file with a given \a layout.
1490 * Force O_CREAT and O_EXCL flags on so caller is assured that file was
1491 * created with the given \a layout on successful function return.
1493 * \param[in] path name of the file to open
1494 * \param[in] open_flags open() flags
1495 * \param[in] mode permissions to create new file with
1496 * \param[in] layout layout to create new file with
1498 * \retval non-negative file descriptor on successful open
1499 * \retval -1 if an error occurred
1501 int llapi_layout_file_create(const char *path, int open_flags, int mode,
1502 const struct llapi_layout *layout)
1504 return llapi_layout_file_open(path, open_flags|O_CREAT|O_EXCL, mode,
1509 * Fetch the start and end offset of the current layout component.
1511 * \param[in] layout the layout component
1512 * \param[out] start extent start, inclusive
1513 * \param[out] end extent end, exclusive
1515 * \retval 0 on success
1516 * \retval <0 if error occurs
1518 int llapi_layout_comp_extent_get(const struct llapi_layout *layout,
1519 uint64_t *start, uint64_t *end)
1521 struct llapi_layout_comp *comp;
1523 comp = __llapi_layout_cur_comp(layout);
1527 if (start == NULL || end == NULL) {
1532 *start = comp->llc_extent.e_start;
1533 *end = comp->llc_extent.e_end;
1539 * Set the layout extent of a layout.
1541 * \param[in] layout the layout to be set
1542 * \param[in] start extent start, inclusive
1543 * \param[in] end extent end, exclusive
1545 * \retval 0 on success
1546 * \retval <0 if error occurs
1548 int llapi_layout_comp_extent_set(struct llapi_layout *layout,
1549 uint64_t start, uint64_t end)
1551 struct llapi_layout_comp *prev, *next, *comp;
1553 comp = __llapi_layout_cur_comp(layout);
1563 * We need to make sure the extent to be set is valid: the new
1564 * extent must be adjacent with the prev & next component.
1566 if (comp->llc_list.prev != &layout->llot_comp_list) {
1567 prev = list_entry(comp->llc_list.prev, typeof(*prev),
1569 if (start != prev->llc_extent.e_end) {
1575 if (comp->llc_list.next != &layout->llot_comp_list) {
1576 next = list_entry(comp->llc_list.next, typeof(*next),
1578 if (end != next->llc_extent.e_start) {
1584 comp->llc_extent.e_start = start;
1585 comp->llc_extent.e_end = end;
1586 layout->llot_is_composite = true;
1592 * Gets the attribute flags of the current component.
1594 * \param[in] layout the layout component
1595 * \param[out] flags stored the returned component flags
1597 * \retval 0 on success
1598 * \retval <0 if error occurs
1600 int llapi_layout_comp_flags_get(const struct llapi_layout *layout,
1603 struct llapi_layout_comp *comp;
1605 comp = __llapi_layout_cur_comp(layout);
1609 if (flags == NULL) {
1614 *flags = comp->llc_flags;
1620 * Sets the specified flags of the current component leaving other flags as-is.
1622 * \param[in] layout the layout component
1623 * \param[in] flags component flags to be set
1625 * \retval 0 on success
1626 * \retval <0 if error occurs
1628 int llapi_layout_comp_flags_set(struct llapi_layout *layout, uint32_t flags)
1630 struct llapi_layout_comp *comp;
1632 comp = __llapi_layout_cur_comp(layout);
1636 comp->llc_flags |= flags;
1642 * Clears the flags specified in the flags leaving other flags as-is.
1644 * \param[in] layout the layout component
1645 * \param[in] flags component flags to be cleared
1647 * \retval 0 on success
1648 * \retval <0 if error occurs
1650 int llapi_layout_comp_flags_clear(struct llapi_layout *layout,
1653 struct llapi_layout_comp *comp;
1655 comp = __llapi_layout_cur_comp(layout);
1659 comp->llc_flags &= ~flags;
1665 * Fetches the file-unique component ID of the current layout component.
1667 * \param[in] layout the layout component
1668 * \param[out] id stored the returned component ID
1670 * \retval 0 on success
1671 * \retval <0 if error occurs
1673 int llapi_layout_comp_id_get(const struct llapi_layout *layout, uint32_t *id)
1675 struct llapi_layout_comp *comp;
1677 comp = __llapi_layout_cur_comp(layout);
1691 * Adds a component to \a layout, the new component will be added to
1692 * the tail of components list and it'll inherit attributes of existing
1693 * ones. The \a layout will change it's current component pointer to
1694 * the newly added component, and it'll be turned into a composite
1695 * layout if it was not before the adding.
1697 * \param[in] layout existing composite or plain layout
1699 * \retval 0 on success
1700 * \retval <0 if error occurs
1702 int llapi_layout_comp_add(struct llapi_layout *layout)
1704 struct llapi_layout_comp *last, *comp, *new;
1706 comp = __llapi_layout_cur_comp(layout);
1710 new = __llapi_comp_alloc(0);
1714 last = list_entry(layout->llot_comp_list.prev, typeof(*last),
1717 /* Inherit some attributes from existing component */
1718 new->llc_stripe_size = comp->llc_stripe_size;
1719 new->llc_stripe_count = comp->llc_stripe_count;
1720 if (new->llc_extent.e_end <= last->llc_extent.e_end) {
1721 __llapi_comp_free(new);
1725 new->llc_extent.e_start = last->llc_extent.e_end;
1727 list_add_tail(&new->llc_list, &layout->llot_comp_list);
1728 layout->llot_cur_comp = new;
1729 layout->llot_is_composite = true;
1735 * Deletes current component from the composite layout. The component
1736 * to be deleted must be the tail of components list, and it can't be
1737 * the last component in the layout.
1739 * \param[in] layout composite layout
1741 * \retval 0 on success
1742 * \retval <0 if error occurs
1744 int llapi_layout_comp_del(struct llapi_layout *layout)
1746 struct llapi_layout_comp *comp;
1748 comp = __llapi_layout_cur_comp(layout);
1752 if (!layout->llot_is_composite) {
1757 /* It must be the tail of the list */
1758 if (comp->llc_list.next != &layout->llot_comp_list) {
1762 /* It can't be the last one on the list */
1763 if (comp->llc_list.prev == &layout->llot_comp_list) {
1768 list_del_init(&comp->llc_list);
1769 __llapi_comp_free(comp);
1770 layout->llot_cur_comp =
1771 list_entry(comp->llc_list.prev, typeof(*comp),
1778 * Move the current component pointer to the component with
1779 * specified component ID.
1781 * \param[in] layout composite layout
1782 * \param[in] id component ID
1784 * \retval =0 : moved successfully
1785 * \retval <0 if error occurs
1787 int llapi_layout_comp_move_at(struct llapi_layout *layout, uint32_t id)
1789 struct llapi_layout_comp *comp;
1791 comp = __llapi_layout_cur_comp(layout);
1795 if (!layout->llot_is_composite) {
1805 list_for_each_entry(comp, &layout->llot_comp_list, llc_list) {
1806 if (comp->llc_id == id) {
1807 layout->llot_cur_comp = comp;
1816 * Move the current component pointer to a specified position.
1818 * \param[in] layout composite layout
1819 * \param[in] pos the position to be moved, it can be:
1820 * LLAPI_LAYOUT_COMP_POS_FIRST: move to head
1821 * LLAPI_LAYOUT_COMP_POS_LAST: move to tail
1822 * LLAPI_LAYOUT_COMP_POS_NEXT: move to next
1824 * \retval =0 : moved successfully
1825 * \retval =1 : already at the tail when move to the next
1826 * \retval <0 if error occurs
1828 int llapi_layout_comp_move(struct llapi_layout *layout, uint32_t pos)
1830 struct llapi_layout_comp *comp, *head, *tail;
1832 comp = __llapi_layout_cur_comp(layout);
1836 if (!layout->llot_is_composite) {
1841 head = list_entry(layout->llot_comp_list.next, typeof(*head),
1843 tail = list_entry(layout->llot_comp_list.prev, typeof(*tail),
1846 if (pos == LLAPI_LAYOUT_COMP_POS_NEXT) {
1849 layout->llot_cur_comp = list_entry(comp->llc_list.next,
1850 typeof(*comp), llc_list);
1851 } else if (pos == LLAPI_LAYOUT_COMP_POS_FIRST) {
1852 layout->llot_cur_comp = head;
1853 } else if (pos == LLAPI_LAYOUT_COMP_POS_LAST) {
1854 layout->llot_cur_comp = tail;
1864 * Add layout component(s) to an existing file.
1866 * \param[in] path The path name of the file
1867 * \param[in] layout The layout component(s) to be added
1869 int llapi_layout_file_comp_add(const char *path,
1870 const struct llapi_layout *layout)
1872 int rc, fd, lum_size, tmp_errno = 0;
1873 struct lov_user_md *lum;
1875 if (path == NULL || layout == NULL ||
1876 layout->llot_magic != LLAPI_LAYOUT_MAGIC) {
1881 lum = llapi_layout_to_lum(layout);
1885 if (lum->lmm_magic != LOV_USER_MAGIC_COMP_V1) {
1890 lum_size = ((struct lov_comp_md_v1 *)lum)->lcm_size;
1892 fd = open(path, O_RDWR);
1899 rc = fsetxattr(fd, XATTR_LUSTRE_LOV".add", lum, lum_size, 0);
1914 * Delete component(s) by the specified component id (accepting lcme_id
1915 * wildcards also) from an existing file.
1917 * \param[in] path path name of the file
1918 * \param[in] id unique component ID or an lcme_id
1919 * (LCME_ID_NONE | LCME_FL_* )
1921 int llapi_layout_file_comp_del(const char *path, uint32_t id)
1925 if (path == NULL || id == 0) {
1930 fd = open(path, O_RDWR);
1934 rc = fsetxattr(fd, XATTR_LUSTRE_LOV".del", &id, sizeof(id), 0);
1936 int tmp_errno = errno;
1946 * Change flags or other parameters of the component(s) by component ID of an
1947 * existing file. The component to be modified is specified by the
1948 * comp->lcme_id value, which must be an unique component ID. The new
1949 * attributes are passed in by @comp and @valid is used to specify which
1950 * attributes in the component are going to be changed.
1952 int llapi_layout_file_comp_set(const char *path,
1953 const struct llapi_layout *comp,