Whamcloud - gitweb
New release 2.12.7
[fs/lustre-release.git] / lustre / utils / liblustreapi_layout.c
1 /*
2  * LGPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
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
11  *
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.
16  *
17  * LGPL HEADER END
18  */
19 /*
20  * lustre/utils/liblustreapi_layout.c
21  *
22  * lustreapi library for layout calls for interacting with the layout of
23  * Lustre files while hiding details of the internal data structures
24  * from the user.
25  *
26  * Copyright (c) 2016, 2017, Intel Corporation.
27  *
28  * Author: Ned Bass <bass6@llnl.gov>
29  */
30
31 #include <stdio.h>
32 #include <fcntl.h>
33 #include <stdlib.h>
34 #include <unistd.h>
35 #include <errno.h>
36 #include <limits.h>
37 #include <assert.h>
38 #include <sys/xattr.h>
39 #include <sys/param.h>
40
41 #include <libcfs/util/list.h>
42 #include <lustre/lustreapi.h>
43 #include "lustreapi_internal.h"
44
45 /**
46  * Layout component, which contains all attributes of a plain
47  * V1/V3 layout.
48  */
49 struct llapi_layout_comp {
50         uint64_t        llc_pattern;
51         uint64_t        llc_stripe_size;
52         uint64_t        llc_stripe_count;
53         uint64_t        llc_stripe_offset;
54         /* Add 1 so user always gets back a null terminated string. */
55         char            llc_pool_name[LOV_MAXPOOLNAME + 1];
56         /** Number of objects in llc_objects array if was initialized. */
57         uint32_t        llc_objects_count;
58         struct          lov_user_ost_data_v1 *llc_objects;
59         /* fields used only for composite layouts */
60         struct lu_extent        llc_extent;     /* [start, end) of component */
61         uint32_t                llc_id;         /* unique ID of component */
62         uint32_t                llc_flags;      /* LCME_FL_* flags */
63         uint64_t                llc_timestamp;  /* snapshot timestamp */
64         struct list_head        llc_list;       /* linked to the llapi_layout
65                                                    components list */
66 };
67
68 /**
69  * An Opaque data type abstracting the layout of a Lustre file.
70  */
71 struct llapi_layout {
72         uint32_t        llot_magic; /* LLAPI_LAYOUT_MAGIC */
73         uint32_t        llot_gen;
74         uint32_t        llot_flags;
75         bool            llot_is_composite;
76         uint16_t        llot_mirror_count;
77         /* Cursor pointing to one of the components in llot_comp_list */
78         struct llapi_layout_comp *llot_cur_comp;
79         struct list_head          llot_comp_list;
80 };
81
82 /**
83  * Compute the number of elements in the lmm_objects array of \a lum
84  * with size \a lum_size.
85  *
86  * \param[in] lum       the struct lov_user_md to check
87  * \param[in] lum_size  the number of bytes in \a lum
88  *
89  * \retval              number of elements in array lum->lmm_objects
90  */
91 static int llapi_layout_objects_in_lum(struct lov_user_md *lum, size_t lum_size)
92 {
93         uint32_t magic;
94         size_t base_size;
95
96         if (lum_size < lov_user_md_size(0, LOV_MAGIC_V1))
97                 return 0;
98
99         if (lum->lmm_magic == __swab32(LOV_MAGIC_V1) ||
100             lum->lmm_magic == __swab32(LOV_MAGIC_V3))
101                 magic = __swab32(lum->lmm_magic);
102         else
103                 magic = lum->lmm_magic;
104
105         base_size = lov_user_md_size(0, magic);
106
107         if (lum_size <= base_size)
108                 return 0;
109         else
110                 return (lum_size - base_size) / sizeof(lum->lmm_objects[0]);
111 }
112
113 /**
114  * Byte-swap the fields of struct lov_user_md.
115  *
116  * XXX Rather than duplicating swabbing code here, we should eventually
117  * refactor the needed functions in lustre/ptlrpc/pack_generic.c
118  * into a library that can be shared between kernel and user code.
119  */
120 static void
121 llapi_layout_swab_lov_user_md(struct lov_user_md *lum, int lum_size)
122 {
123         int i, j, ent_count, obj_count;
124         struct lov_comp_md_v1 *comp_v1 = NULL;
125         struct lov_comp_md_entry_v1 *ent;
126         struct lov_user_ost_data *lod;
127
128         if (lum->lmm_magic != __swab32(LOV_MAGIC_V1) &&
129             lum->lmm_magic != __swab32(LOV_MAGIC_V3) &&
130             lum->lmm_magic != __swab32(LOV_MAGIC_COMP_V1))
131                 return;
132
133         if (lum->lmm_magic == __swab32(LOV_MAGIC_COMP_V1))
134                 comp_v1 = (struct lov_comp_md_v1 *)lum;
135
136         if (comp_v1 != NULL) {
137                 __swab32s(&comp_v1->lcm_magic);
138                 __swab32s(&comp_v1->lcm_size);
139                 __swab32s(&comp_v1->lcm_layout_gen);
140                 __swab16s(&comp_v1->lcm_flags);
141                 __swab16s(&comp_v1->lcm_entry_count);
142                 ent_count = comp_v1->lcm_entry_count;
143         } else {
144                 ent_count = 1;
145         }
146
147         for (i = 0; i < ent_count; i++) {
148                 if (comp_v1 != NULL) {
149                         ent = &comp_v1->lcm_entries[i];
150                         __swab32s(&ent->lcme_id);
151                         __swab32s(&ent->lcme_flags);
152                         __swab64s(&ent->lcme_timestamp);
153                         __swab64s(&ent->lcme_extent.e_start);
154                         __swab64s(&ent->lcme_extent.e_end);
155                         __swab32s(&ent->lcme_offset);
156                         __swab32s(&ent->lcme_size);
157
158                         lum = (struct lov_user_md *)((char *)comp_v1 +
159                                         ent->lcme_offset);
160                         lum_size = ent->lcme_size;
161                 }
162                 obj_count = llapi_layout_objects_in_lum(lum, lum_size);
163
164                 __swab32s(&lum->lmm_magic);
165                 __swab32s(&lum->lmm_pattern);
166                 __swab32s(&lum->lmm_stripe_size);
167                 __swab16s(&lum->lmm_stripe_count);
168                 __swab16s(&lum->lmm_stripe_offset);
169
170                 if (lum->lmm_magic != LOV_MAGIC_V1) {
171                         struct lov_user_md_v3 *v3;
172                         v3 = (struct lov_user_md_v3 *)lum;
173                         lod = v3->lmm_objects;
174                 } else {
175                         lod = lum->lmm_objects;
176                 }
177
178                 for (j = 0; j < obj_count; j++)
179                         __swab32s(&lod[j].l_ost_idx);
180         }
181 }
182
183 /**
184  * (Re-)allocate llc_objects[] to \a num_stripes stripes.
185  *
186  * Copy over existing llc_objects[], if any, to the new llc_objects[].
187  *
188  * \param[in] layout            existing layout to be modified
189  * \param[in] num_stripes       number of stripes in new layout
190  *
191  * \retval      0 if the objects are re-allocated successfully
192  * \retval      -1 on error with errno set
193  */
194 static int __llapi_comp_objects_realloc(struct llapi_layout_comp *comp,
195                                         unsigned int new_stripes)
196 {
197         struct lov_user_ost_data_v1 *new_objects;
198         unsigned int i;
199
200         if (new_stripes > LOV_MAX_STRIPE_COUNT) {
201                 errno = EINVAL;
202                 return -1;
203         }
204
205         if (new_stripes == comp->llc_objects_count)
206                 return 0;
207
208         if (new_stripes != 0 && new_stripes <= comp->llc_objects_count)
209                 return 0;
210
211         new_objects = realloc(comp->llc_objects,
212                               sizeof(*new_objects) * new_stripes);
213         if (new_objects == NULL && new_stripes != 0) {
214                 errno = ENOMEM;
215                 return -1;
216         }
217
218         for (i = comp->llc_objects_count; i < new_stripes; i++)
219                 new_objects[i].l_ost_idx = LLAPI_LAYOUT_IDX_MAX;
220
221         comp->llc_objects = new_objects;
222         comp->llc_objects_count = new_stripes;
223
224         return 0;
225 }
226
227 /**
228  * Allocate storage for a llapi_layout_comp with \a num_stripes stripes.
229  *
230  * \param[in] num_stripes       number of stripes in new layout
231  *
232  * \retval      valid pointer if allocation succeeds
233  * \retval      NULL if allocation fails
234  */
235 static struct llapi_layout_comp *__llapi_comp_alloc(unsigned int num_stripes)
236 {
237         struct llapi_layout_comp *comp;
238
239         if (num_stripes > LOV_MAX_STRIPE_COUNT) {
240                 errno = EINVAL;
241                 return NULL;
242         }
243
244         comp = calloc(1, sizeof(*comp));
245         if (comp == NULL) {
246                 errno = ENOMEM;
247                 return NULL;
248         }
249
250         comp->llc_objects = NULL;
251         comp->llc_objects_count = 0;
252
253         if (__llapi_comp_objects_realloc(comp, num_stripes) < 0) {
254                 free(comp);
255                 return NULL;
256         }
257
258         /* Set defaults. */
259         comp->llc_pattern = LLAPI_LAYOUT_DEFAULT;
260         comp->llc_stripe_size = LLAPI_LAYOUT_DEFAULT;
261         comp->llc_stripe_count = LLAPI_LAYOUT_DEFAULT;
262         comp->llc_stripe_offset = LLAPI_LAYOUT_DEFAULT;
263         comp->llc_pool_name[0] = '\0';
264         comp->llc_extent.e_start = 0;
265         comp->llc_extent.e_end = LUSTRE_EOF;
266         comp->llc_flags = 0;
267         comp->llc_id = 0;
268         INIT_LIST_HEAD(&comp->llc_list);
269
270         return comp;
271 }
272
273 /**
274  * Free memory allocated for \a comp
275  *
276  * \param[in] comp      previously allocated by __llapi_comp_alloc()
277  */
278 static void __llapi_comp_free(struct llapi_layout_comp *comp)
279 {
280         if (comp->llc_objects != NULL)
281                 free(comp->llc_objects);
282         free(comp);
283 }
284
285 /**
286  * Free memory allocated for \a layout.
287  *
288  * \param[in] layout    previously allocated by llapi_layout_alloc()
289  */
290 void llapi_layout_free(struct llapi_layout *layout)
291 {
292         struct llapi_layout_comp *comp, *n;
293
294         if (layout == NULL)
295                 return;
296
297         list_for_each_entry_safe(comp, n, &layout->llot_comp_list, llc_list) {
298                 list_del_init(&comp->llc_list);
299                 __llapi_comp_free(comp);
300         }
301         free(layout);
302 }
303
304 /**
305  * Allocate and initialize a llapi_layout structure.
306  *
307  * \retval      valid llapi_layout pointer on success
308  * \retval      NULL if memory allocation fails
309  */
310 static struct llapi_layout *__llapi_layout_alloc(void)
311 {
312         struct llapi_layout *layout;
313
314         layout = calloc(1, sizeof(*layout));
315         if (layout == NULL) {
316                 errno = ENOMEM;
317                 return NULL;
318         }
319
320         /* Set defaults. */
321         layout->llot_magic = LLAPI_LAYOUT_MAGIC;
322         layout->llot_gen = 0;
323         layout->llot_flags = 0;
324         layout->llot_is_composite = false;
325         layout->llot_mirror_count = 1;
326         layout->llot_cur_comp = NULL;
327         INIT_LIST_HEAD(&layout->llot_comp_list);
328
329         return layout;
330 }
331
332 /**
333  * Allocate and initialize a new plain layout.
334  *
335  * \retval      valid llapi_layout pointer on success
336  * \retval      NULL if memory allocation fails
337  */
338 struct llapi_layout *llapi_layout_alloc(void)
339 {
340         struct llapi_layout_comp *comp;
341         struct llapi_layout *layout;
342
343         layout = __llapi_layout_alloc();
344         if (layout == NULL)
345                 return NULL;
346
347         comp = __llapi_comp_alloc(0);
348         if (comp == NULL) {
349                 free(layout);
350                 return NULL;
351         }
352
353         list_add_tail(&comp->llc_list, &layout->llot_comp_list);
354         layout->llot_cur_comp = comp;
355
356         return layout;
357 }
358
359 /**
360  * Check if the given \a lum_size is large enough to hold the required
361  * fields in \a lum.
362  *
363  * \param[in] lum       the struct lov_user_md to check
364  * \param[in] lum_size  the number of bytes in \a lum
365  *
366  * \retval true         the \a lum_size is too small
367  * \retval false        the \a lum_size is large enough
368  */
369 static bool llapi_layout_lum_truncated(struct lov_user_md *lum, size_t lum_size)
370 {
371         uint32_t magic;
372
373         if (lum_size < sizeof(lum->lmm_magic))
374                 return true;
375
376         if (lum->lmm_magic == LOV_MAGIC_V1 ||
377             lum->lmm_magic == __swab32(LOV_MAGIC_V1))
378                 magic = LOV_MAGIC_V1;
379         else if (lum->lmm_magic == LOV_MAGIC_V3 ||
380                  lum->lmm_magic == __swab32(LOV_MAGIC_V3))
381                 magic = LOV_MAGIC_V3;
382         else if (lum->lmm_magic == LOV_MAGIC_COMP_V1 ||
383                  lum->lmm_magic == __swab32(LOV_MAGIC_COMP_V1))
384                 magic = LOV_MAGIC_COMP_V1;
385         else
386                 return true;
387
388         if (magic == LOV_MAGIC_V1 || magic == LOV_MAGIC_V3)
389                 return lum_size < lov_user_md_size(0, magic);
390         else
391                 return lum_size < sizeof(struct lov_comp_md_v1);
392 }
393
394 /* Verify if the objects count in lum is consistent with the
395  * stripe count in lum. It applies to regular file only. */
396 static bool llapi_layout_lum_valid(struct lov_user_md *lum, int lum_size)
397 {
398         struct lov_comp_md_v1 *comp_v1 = NULL;
399         int i, ent_count, obj_count;
400
401         if (lum->lmm_magic == LOV_MAGIC_COMP_V1) {
402                 comp_v1 = (struct lov_comp_md_v1 *)lum;
403                 ent_count = comp_v1->lcm_entry_count;
404         } else if (lum->lmm_magic == LOV_MAGIC_V1 ||
405                    lum->lmm_magic == LOV_MAGIC_V3) {
406                 ent_count = 1;
407         } else {
408                 return false;
409         }
410
411         for (i = 0; i < ent_count; i++) {
412                 if (comp_v1) {
413                         lum = (struct lov_user_md *)((char *)comp_v1 +
414                                 comp_v1->lcm_entries[i].lcme_offset);
415                         lum_size = comp_v1->lcm_entries[i].lcme_size;
416                 }
417                 obj_count = llapi_layout_objects_in_lum(lum, lum_size);
418
419                 if (comp_v1) {
420                         if (!(comp_v1->lcm_entries[i].lcme_flags &
421                                  LCME_FL_INIT) && obj_count != 0)
422                                 return false;
423                 } else if (obj_count != lum->lmm_stripe_count) {
424                         return false;
425                 }
426         }
427         return true;
428 }
429
430 /**
431  * Convert the data from a lov_user_md to a newly allocated llapi_layout.
432  * The caller is responsible for freeing the returned pointer.
433  *
434  * \param[in] lov_xattr         LOV user metadata xattr to copy data from
435  * \param[in] lov_xattr_size    size the lov_xattr_size passed in
436  * \param[in] flags             bitwise-or'd flags to control the behavior
437  *
438  * \retval              valid llapi_layout pointer on success
439  * \retval              NULL if memory allocation fails
440  */
441 struct llapi_layout *llapi_layout_get_by_xattr(void *lov_xattr,
442                                                ssize_t lov_xattr_size,
443                                                uint32_t flags)
444 {
445         struct lov_user_md *lum = lov_xattr;
446         struct lov_comp_md_v1 *comp_v1 = NULL;
447         struct lov_comp_md_entry_v1 *ent;
448         struct lov_user_md *v1;
449         struct llapi_layout *layout = NULL;
450         struct llapi_layout_comp *comp;
451         int i, ent_count = 0, obj_count;
452
453         if (lov_xattr == NULL || lov_xattr_size <= 0) {
454                 errno = EINVAL;
455                 return NULL;
456         }
457
458         /* Return an error if we got back a partial layout. */
459         if (llapi_layout_lum_truncated(lov_xattr, lov_xattr_size)) {
460                 errno = ERANGE;
461                 return NULL;
462         }
463
464 #if __BYTE_ORDER == __BIG_ENDIAN
465         if (flags & LLAPI_LXF_COPY) {
466                 lum = malloc(lov_xattr_size);
467                 if (lum == NULL) {
468                         errno = ENOMEM;
469                         return NULL;
470                 }
471                 memcpy(lum, lov_xattr, lov_xattr_size);
472         }
473 #endif
474
475         llapi_layout_swab_lov_user_md(lum, lov_xattr_size);
476
477         if ((flags & LLAPI_LXF_CHECK) &&
478             !llapi_layout_lum_valid(lum, lov_xattr_size)) {
479                 errno = EBADSLT;
480                 goto out;
481         }
482
483         layout = __llapi_layout_alloc();
484         if (layout == NULL) {
485                 errno = ENOMEM;
486                 goto out;
487         }
488
489         if (lum->lmm_magic == LOV_MAGIC_COMP_V1) {
490                 comp_v1 = (struct lov_comp_md_v1 *)lum;
491                 ent_count = comp_v1->lcm_entry_count;
492                 layout->llot_gen = comp_v1->lcm_layout_gen;
493                 layout->llot_is_composite = true;
494                 layout->llot_mirror_count = comp_v1->lcm_mirror_count + 1;
495                 layout->llot_gen = comp_v1->lcm_layout_gen;
496                 layout->llot_flags = comp_v1->lcm_flags;
497         } else if (lum->lmm_magic == LOV_MAGIC_V1 ||
498                    lum->lmm_magic == LOV_MAGIC_V3) {
499                 ent_count = 1;
500                 layout->llot_is_composite = false;
501
502                 if (lov_xattr_size <= 0) {
503                         errno = EINVAL;
504                         goto out_layout;
505                 }
506         } else {
507                 errno = EOPNOTSUPP;
508                 goto out_layout;
509         }
510
511         if (ent_count == 0) {
512                 errno = EINVAL;
513                 goto out_layout;
514         }
515
516         v1 = (struct lov_user_md *)lum;
517         for (i = 0; i < ent_count; i++) {
518                 if (comp_v1 != NULL) {
519                         ent = &comp_v1->lcm_entries[i];
520                         v1 = (struct lov_user_md *)((char *)comp_v1 +
521                                 ent->lcme_offset);
522                         lov_xattr_size = ent->lcme_size;
523                 } else {
524                         ent = NULL;
525                 }
526
527                 obj_count = llapi_layout_objects_in_lum(v1, lov_xattr_size);
528                 comp = __llapi_comp_alloc(obj_count);
529                 if (comp == NULL)
530                         goto out_layout;
531
532                 if (ent != NULL) {
533                         comp->llc_extent.e_start = ent->lcme_extent.e_start;
534                         comp->llc_extent.e_end = ent->lcme_extent.e_end;
535                         comp->llc_id = ent->lcme_id;
536                         comp->llc_flags = ent->lcme_flags;
537                         if (comp->llc_flags & LCME_FL_NOSYNC)
538                                 comp->llc_timestamp = ent->lcme_timestamp;
539                 } else {
540                         comp->llc_extent.e_start = 0;
541                         comp->llc_extent.e_end = LUSTRE_EOF;
542                         comp->llc_id = 0;
543                         comp->llc_flags = 0;
544                 }
545
546                 if (v1->lmm_pattern == LOV_PATTERN_RAID0)
547                         comp->llc_pattern = LLAPI_LAYOUT_RAID0;
548                 else if (v1->lmm_pattern == LOV_PATTERN_MDT)
549                         comp->llc_pattern = LLAPI_LAYOUT_MDT;
550                 else
551                         /* Lustre only supports RAID0 and DoM for now. */
552                         comp->llc_pattern = v1->lmm_pattern;
553
554                 if (v1->lmm_stripe_size == 0)
555                         comp->llc_stripe_size = LLAPI_LAYOUT_DEFAULT;
556                 else
557                         comp->llc_stripe_size = v1->lmm_stripe_size;
558
559                 if (v1->lmm_stripe_count == (typeof(v1->lmm_stripe_count))-1)
560                         comp->llc_stripe_count = LLAPI_LAYOUT_WIDE;
561                 else if (v1->lmm_stripe_count == 0)
562                         comp->llc_stripe_count = LLAPI_LAYOUT_DEFAULT;
563                 else
564                         comp->llc_stripe_count = v1->lmm_stripe_count;
565
566                 if (v1->lmm_stripe_offset ==
567                     (typeof(v1->lmm_stripe_offset))-1)
568                         comp->llc_stripe_offset = LLAPI_LAYOUT_DEFAULT;
569                 else
570                         comp->llc_stripe_offset = v1->lmm_stripe_offset;
571
572                 if (v1->lmm_magic != LOV_USER_MAGIC_V1) {
573                         const struct lov_user_md_v3 *lumv3;
574                         lumv3 = (struct lov_user_md_v3 *)v1;
575                         snprintf(comp->llc_pool_name,
576                                  sizeof(comp->llc_pool_name),
577                                  "%s", lumv3->lmm_pool_name);
578                         memcpy(comp->llc_objects, lumv3->lmm_objects,
579                                obj_count * sizeof(lumv3->lmm_objects[0]));
580                 } else {
581                         const struct lov_user_md_v1 *lumv1;
582                         lumv1 = (struct lov_user_md_v1 *)v1;
583                         memcpy(comp->llc_objects, lumv1->lmm_objects,
584                                obj_count * sizeof(lumv1->lmm_objects[0]));
585                 }
586
587                 if (obj_count != 0)
588                         comp->llc_stripe_offset =
589                                 comp->llc_objects[0].l_ost_idx;
590
591                 list_add_tail(&comp->llc_list, &layout->llot_comp_list);
592                 layout->llot_cur_comp = comp;
593         }
594
595 out:
596         if (lum != lov_xattr)
597                 free(lum);
598         return layout;
599 out_layout:
600         llapi_layout_free(layout);
601         layout = NULL;
602         goto out;
603 }
604
605 /**
606  * Convert the data from a llapi_layout to a newly allocated lov_user_md.
607  * The caller is responsible for freeing the returned pointer.
608  *
609  * \param[in] layout    the layout to copy from
610  *
611  * \retval      valid lov_user_md pointer on success
612  * \retval      NULL if memory allocation fails or the layout is invalid
613  */
614 static struct lov_user_md *
615 llapi_layout_to_lum(const struct llapi_layout *layout)
616 {
617         struct llapi_layout_comp *comp;
618         struct lov_comp_md_v1 *comp_v1 = NULL;
619         struct lov_comp_md_entry_v1 *ent;
620         struct lov_user_md *lum = NULL;
621         size_t lum_size = 0;
622         int ent_idx = 0;
623         uint32_t offset = 0;
624
625         if (layout == NULL ||
626             list_empty((struct list_head *)&layout->llot_comp_list)) {
627                 errno = EINVAL;
628                 return NULL;
629         }
630
631         /* Allocate header of lov_comp_md_v1 if necessary */
632         if (layout->llot_is_composite) {
633                 int comp_cnt = 0;
634
635                 list_for_each_entry(comp, &layout->llot_comp_list, llc_list)
636                         comp_cnt++;
637
638                 lum_size = sizeof(*comp_v1) + comp_cnt * sizeof(*ent);
639                 lum = calloc(lum_size, 1);
640                 if (lum == NULL) {
641                         errno = ENOMEM;
642                         return NULL;
643                 }
644                 comp_v1 = (struct lov_comp_md_v1 *)lum;
645                 comp_v1->lcm_magic = LOV_USER_MAGIC_COMP_V1;
646                 comp_v1->lcm_size = lum_size;
647                 comp_v1->lcm_layout_gen = 0;
648                 comp_v1->lcm_flags = layout->llot_flags;
649                 comp_v1->lcm_entry_count = comp_cnt;
650                 comp_v1->lcm_mirror_count = layout->llot_mirror_count - 1;
651                 offset += lum_size;
652         }
653
654         list_for_each_entry(comp, &layout->llot_comp_list, llc_list) {
655                 struct lov_user_md *blob;
656                 size_t blob_size;
657                 uint32_t magic;
658                 int i, obj_count = 0;
659                 struct lov_user_ost_data *lmm_objects;
660                 uint64_t pattern = comp->llc_pattern;
661
662                 if ((pattern & LLAPI_LAYOUT_SPECIFIC) != 0) {
663                         if (comp->llc_objects_count <
664                             comp->llc_stripe_count) {
665                                 errno = EINVAL;
666                                 goto error;
667                         }
668                         magic = LOV_USER_MAGIC_SPECIFIC;
669                         obj_count = comp->llc_stripe_count;
670                         pattern &= ~LLAPI_LAYOUT_SPECIFIC;
671                 } else if (strlen(comp->llc_pool_name) != 0) {
672                         magic = LOV_USER_MAGIC_V3;
673                 } else {
674                         magic = LOV_USER_MAGIC_V1;
675                 }
676                 /* All stripes must be specified when the pattern contains
677                  * LLAPI_LAYOUT_SPECIFIC */
678                 for (i = 0; i < obj_count; i++) {
679                         if (comp->llc_objects[i].l_ost_idx ==
680                             LLAPI_LAYOUT_IDX_MAX) {
681                                 errno = EINVAL;
682                                 goto error;
683                         }
684                 }
685
686                 blob_size = lov_user_md_size(obj_count, magic);
687                 blob = realloc(lum, lum_size + blob_size);
688                 if (blob == NULL) {
689                         errno = ENOMEM;
690                         goto error;
691                 } else {
692                         lum = blob;
693                         comp_v1 = (struct lov_comp_md_v1 *)lum;
694                         blob = (struct lov_user_md *)((char *)lum + lum_size);
695                         lum_size += blob_size;
696                 }
697
698                 blob->lmm_magic = magic;
699                 if (pattern == LLAPI_LAYOUT_DEFAULT)
700                         blob->lmm_pattern = LOV_PATTERN_RAID0;
701                 else if (pattern == LLAPI_LAYOUT_MDT)
702                         blob->lmm_pattern = LOV_PATTERN_MDT;
703                 else
704                         blob->lmm_pattern = pattern;
705
706                 if (comp->llc_stripe_size == LLAPI_LAYOUT_DEFAULT)
707                         blob->lmm_stripe_size = 0;
708                 else
709                         blob->lmm_stripe_size = comp->llc_stripe_size;
710
711                 if (comp->llc_stripe_count == LLAPI_LAYOUT_DEFAULT)
712                         blob->lmm_stripe_count = 0;
713                 else if (comp->llc_stripe_count == LLAPI_LAYOUT_WIDE)
714                         blob->lmm_stripe_count = LOV_ALL_STRIPES;
715                 else
716                         blob->lmm_stripe_count = comp->llc_stripe_count;
717
718                 if (comp->llc_stripe_offset == LLAPI_LAYOUT_DEFAULT)
719                         blob->lmm_stripe_offset = -1;
720                 else
721                         blob->lmm_stripe_offset = comp->llc_stripe_offset;
722
723                 if (magic == LOV_USER_MAGIC_V3 ||
724                     magic == LOV_USER_MAGIC_SPECIFIC) {
725                         struct lov_user_md_v3 *lumv3 =
726                                 (struct lov_user_md_v3 *)blob;
727
728                         if (comp->llc_pool_name[0] != '\0') {
729                                 strncpy(lumv3->lmm_pool_name,
730                                         comp->llc_pool_name,
731                                         sizeof(lumv3->lmm_pool_name));
732                         } else {
733                                 memset(lumv3->lmm_pool_name, 0,
734                                        sizeof(lumv3->lmm_pool_name));
735                         }
736                         lmm_objects = lumv3->lmm_objects;
737                 } else {
738                         lmm_objects = blob->lmm_objects;
739                 }
740
741                 for (i = 0; i < obj_count; i++)
742                         lmm_objects[i].l_ost_idx =
743                                 comp->llc_objects[i].l_ost_idx;
744
745                 if (layout->llot_is_composite) {
746                         ent = &comp_v1->lcm_entries[ent_idx];
747                         ent->lcme_id = comp->llc_id;
748                         ent->lcme_flags = comp->llc_flags;
749                         if (ent->lcme_flags & LCME_FL_NOSYNC)
750                                 ent->lcme_timestamp = comp->llc_timestamp;
751                         ent->lcme_extent.e_start = comp->llc_extent.e_start;
752                         ent->lcme_extent.e_end = comp->llc_extent.e_end;
753                         ent->lcme_size = blob_size;
754                         ent->lcme_offset = offset;
755                         offset += blob_size;
756                         comp_v1->lcm_size += blob_size;
757                         ent_idx++;
758                 } else {
759                         break;
760                 }
761         }
762
763         return lum;
764 error:
765         free(lum);
766         return NULL;
767 }
768
769 /**
770  * Get the parent directory of a path.
771  *
772  * \param[in] path      path to get parent of
773  * \param[out] buf      buffer in which to store parent path
774  * \param[in] size      size in bytes of buffer \a buf
775  */
776 static void get_parent_dir(const char *path, char *buf, size_t size)
777 {
778         char *p;
779
780         strncpy(buf, path, size - 1);
781         p = strrchr(buf, '/');
782
783         if (p != NULL) {
784                 *p = '\0';
785         } else if (size >= 2) {
786                 strncpy(buf, ".", 2);
787                 buf[size - 1] = '\0';
788         }
789 }
790
791 /**
792  * Substitute unspecified attribute values in \a layout with values
793  * from fs global settings. (lov.stripesize, lov.stripecount,
794  * lov.stripeoffset)
795  *
796  * \param[in] layout    layout to inherit values from
797  * \param[in] path      file path of the filesystem
798  */
799 static void inherit_sys_attributes(struct llapi_layout *layout,
800                                    const char *path)
801 {
802         struct llapi_layout_comp *comp;
803         unsigned int ssize, scount, soffset;
804         int rc;
805
806         rc = sattr_cache_get_defaults(NULL, path, &scount, &ssize, &soffset);
807         if (rc)
808                 return;
809
810         list_for_each_entry(comp, &layout->llot_comp_list, llc_list) {
811                 if (comp->llc_pattern == LLAPI_LAYOUT_DEFAULT)
812                         comp->llc_pattern = LLAPI_LAYOUT_RAID0;
813                 if (comp->llc_stripe_size == LLAPI_LAYOUT_DEFAULT)
814                         comp->llc_stripe_size = ssize;
815                 if (comp->llc_stripe_count == LLAPI_LAYOUT_DEFAULT)
816                         comp->llc_stripe_count = scount;
817                 if (comp->llc_stripe_offset == LLAPI_LAYOUT_DEFAULT)
818                         comp->llc_stripe_offset = soffset;
819         }
820 }
821
822 /**
823  * Get the current component of \a layout.
824  *
825  * \param[in] layout    layout to get current component
826  *
827  * \retval      valid llapi_layout_comp pointer on success
828  * \retval      NULL on error
829  */
830 static struct llapi_layout_comp *
831 __llapi_layout_cur_comp(const struct llapi_layout *layout)
832 {
833         struct llapi_layout_comp *comp;
834
835         if (layout == NULL || layout->llot_magic != LLAPI_LAYOUT_MAGIC) {
836                 errno = EINVAL;
837                 return NULL;
838         }
839         if (layout->llot_cur_comp == NULL) {
840                 errno = EINVAL;
841                 return NULL;
842         }
843         /* Verify data consistency */
844         list_for_each_entry(comp, &layout->llot_comp_list, llc_list)
845                 if (comp == layout->llot_cur_comp)
846                         return comp;
847         errno = EFAULT;
848         return NULL;
849 }
850
851 /**
852  * Test if any attributes of \a layout are specified.
853  *
854  * \param[in] layout    the layout to check
855  *
856  * \retval true         any attributes are specified
857  * \retval false        all attributes are unspecified
858  */
859 static bool is_any_specified(const struct llapi_layout *layout)
860 {
861         struct llapi_layout_comp *comp;
862
863         comp = __llapi_layout_cur_comp(layout);
864         if (comp == NULL)
865                 return false;
866
867         if (layout->llot_is_composite || layout->llot_mirror_count != 1)
868                 return true;
869
870         return comp->llc_pattern != LLAPI_LAYOUT_DEFAULT ||
871                comp->llc_stripe_size != LLAPI_LAYOUT_DEFAULT ||
872                comp->llc_stripe_count != LLAPI_LAYOUT_DEFAULT ||
873                comp->llc_stripe_offset != LLAPI_LAYOUT_DEFAULT ||
874                strlen(comp->llc_pool_name);
875 }
876
877 /**
878  * Get the striping layout for the file referenced by file descriptor \a fd.
879  *
880  * If the filesystem does not support the "lustre." xattr namespace, the
881  * file must be on a non-Lustre filesystem, so set errno to ENOTTY per
882  * convention.  If the file has no "lustre.lov" data, the file will
883  * inherit default values, so return a default layout.
884  *
885  * If the kernel gives us back less than the expected amount of data,
886  * we fail with errno set to EINTR.
887  *
888  * \param[in] fd        open file descriptor
889  * \param[in] flags     open file descriptor
890  *
891  * \retval      valid llapi_layout pointer on success
892  * \retval      NULL if an error occurs
893  */
894 struct llapi_layout *llapi_layout_get_by_fd(int fd, uint32_t flags)
895 {
896         size_t lum_len;
897         struct lov_user_md *lum;
898         struct llapi_layout *layout = NULL;
899         ssize_t bytes_read;
900         struct stat st;
901
902         lum_len = XATTR_SIZE_MAX;
903         lum = malloc(lum_len);
904         if (lum == NULL)
905                 return NULL;
906
907         bytes_read = fgetxattr(fd, XATTR_LUSTRE_LOV, lum, lum_len);
908         if (bytes_read < 0) {
909                 if (errno == EOPNOTSUPP)
910                         errno = ENOTTY;
911                 else if (errno == ENODATA)
912                         layout = llapi_layout_alloc();
913                 goto out;
914         }
915
916         /* Directories may have a positive non-zero lum->lmm_stripe_count
917          * yet have an empty lum->lmm_objects array. For non-directories the
918          * amount of data returned from the kernel must be consistent
919          * with the stripe count. */
920         if (fstat(fd, &st) < 0)
921                 goto out;
922
923         layout = llapi_layout_get_by_xattr(lum, bytes_read,
924                 S_ISDIR(st.st_mode) ? 0 : LLAPI_LXF_CHECK);
925 out:
926         free(lum);
927         return layout;
928 }
929
930 /**
931  * Get the expected striping layout for a file at \a path.
932  *
933  * Substitute expected inherited attribute values for unspecified
934  * attributes.  Unspecified attributes may belong to directories and
935  * never-written-to files, and indicate that default values will be
936  * assigned when files are created or first written to.  A default value
937  * is inherited from the parent directory if the attribute is specified
938  * there, otherwise it is inherited from the filesystem root.
939  * Unspecified attributes normally have the value LLAPI_LAYOUT_DEFAULT.
940  *
941  * The complete \a path need not refer to an existing file or directory,
942  * but some leading portion of it must reside within a lustre filesystem.
943  * A use case for this interface would be to obtain the literal striping
944  * values that would be assigned to a new file in a given directory.
945  *
946  * \param[in] path      path for which to get the expected layout
947  *
948  * \retval      valid llapi_layout pointer on success
949  * \retval      NULL if an error occurs
950  */
951 static struct llapi_layout *llapi_layout_expected(const char *path)
952 {
953         struct llapi_layout     *path_layout = NULL;
954         char                    donor_path[PATH_MAX];
955         struct stat st;
956         int fd;
957         int rc;
958
959         fd = open(path, O_RDONLY);
960         if (fd < 0 && errno != ENOENT)
961                 return NULL;
962
963         if (fd >= 0) {
964                 int tmp;
965
966                 path_layout = llapi_layout_get_by_fd(fd, 0);
967                 tmp = errno;
968                 close(fd);
969                 errno = tmp;
970         }
971
972         if (path_layout == NULL) {
973                 if (errno != ENODATA && errno != ENOENT)
974                         return NULL;
975
976                 path_layout = llapi_layout_alloc();
977                 if (path_layout == NULL)
978                         return NULL;
979         }
980
981         if (is_any_specified(path_layout)) {
982                 inherit_sys_attributes(path_layout, path);
983                 return path_layout;
984         }
985
986         llapi_layout_free(path_layout);
987
988         rc = stat(path, &st);
989         if (rc < 0 && errno != ENOENT)
990                 return NULL;
991
992         /* If path is a not a directory or doesn't exist, inherit layout
993          * from parent directory. */
994         if ((rc == 0 && !S_ISDIR(st.st_mode)) ||
995             (rc < 0 && errno == ENOENT)) {
996                 get_parent_dir(path, donor_path, sizeof(donor_path));
997                 path_layout = llapi_layout_get_by_path(donor_path, 0);
998                 if (path_layout != NULL) {
999                         if (is_any_specified(path_layout)) {
1000                                 inherit_sys_attributes(path_layout, donor_path);
1001                                 return path_layout;
1002                         }
1003                         llapi_layout_free(path_layout);
1004                 }
1005         }
1006
1007         /* Inherit layout from the filesystem root. */
1008         rc = llapi_search_mounts(path, 0, donor_path, NULL);
1009         if (rc < 0)
1010                 return NULL;
1011         path_layout = llapi_layout_get_by_path(donor_path, 0);
1012         if (path_layout == NULL)
1013                 return NULL;
1014
1015         inherit_sys_attributes(path_layout, donor_path);
1016         return path_layout;
1017 }
1018
1019 /**
1020  * Get the striping layout for the file at \a path.
1021  *
1022  * If \a flags contains LAYOUT_GET_EXPECTED, substitute
1023  * expected inherited attribute values for unspecified attributes. See
1024  * llapi_layout_expected().
1025  *
1026  * \param[in] path      path for which to get the layout
1027  * \param[in] flags     flags to control how layout is retrieved
1028  *
1029  * \retval      valid llapi_layout pointer on success
1030  * \retval      NULL if an error occurs
1031  */
1032 struct llapi_layout *llapi_layout_get_by_path(const char *path, uint32_t flags)
1033 {
1034         struct llapi_layout *layout = NULL;
1035         int fd;
1036         int tmp;
1037
1038         if (flags & LAYOUT_GET_EXPECTED)
1039                 return llapi_layout_expected(path);
1040
1041         fd = open(path, O_RDONLY);
1042         if (fd < 0)
1043                 return layout;
1044
1045         layout = llapi_layout_get_by_fd(fd, flags);
1046         tmp = errno;
1047         close(fd);
1048         errno = tmp;
1049
1050         return layout;
1051 }
1052
1053 /**
1054  * Get the layout for the file with FID \a fidstr in filesystem \a lustre_dir.
1055  *
1056  * \param[in] lustre_dir        path within Lustre filesystem containing \a fid
1057  * \param[in] fid               Lustre identifier of file to get layout for
1058  *
1059  * \retval      valid llapi_layout pointer on success
1060  * \retval      NULL if an error occurs
1061  */
1062 struct llapi_layout *llapi_layout_get_by_fid(const char *lustre_dir,
1063                                              const struct lu_fid *fid,
1064                                              uint32_t flags)
1065 {
1066         int fd;
1067         int tmp;
1068         int saved_msg_level = llapi_msg_get_level();
1069         struct llapi_layout *layout = NULL;
1070
1071         /* Prevent llapi internal routines from writing to console
1072          * while executing this function, then restore previous message
1073          * level. */
1074         llapi_msg_set_level(LLAPI_MSG_OFF);
1075         fd = llapi_open_by_fid(lustre_dir, fid, O_RDONLY);
1076         llapi_msg_set_level(saved_msg_level);
1077
1078         if (fd < 0)
1079                 return NULL;
1080
1081         layout = llapi_layout_get_by_fd(fd, flags);
1082         tmp = errno;
1083         close(fd);
1084         errno = tmp;
1085
1086         return layout;
1087 }
1088
1089 /**
1090  * Get the stripe count of \a layout.
1091  *
1092  * \param[in] layout    layout to get stripe count from
1093  * \param[out] count    integer to store stripe count in
1094  *
1095  * \retval      0 on success
1096  * \retval      -1 if arguments are invalid
1097  */
1098 int llapi_layout_stripe_count_get(const struct llapi_layout *layout,
1099                                   uint64_t *count)
1100 {
1101         struct llapi_layout_comp *comp;
1102
1103         comp = __llapi_layout_cur_comp(layout);
1104         if (comp == NULL)
1105                 return -1;
1106
1107         if (count == NULL) {
1108                 errno = EINVAL;
1109                 return -1;
1110         }
1111
1112         *count = comp->llc_stripe_count;
1113
1114         return 0;
1115 }
1116
1117 /*
1118  * The llapi_layout API functions have these extra validity checks since
1119  * they use intuitively named macros to denote special behavior, whereas
1120  * the old API uses 0 and -1.
1121  */
1122
1123 static bool llapi_layout_stripe_count_is_valid(int64_t stripe_count)
1124 {
1125         return stripe_count == LLAPI_LAYOUT_DEFAULT ||
1126                 stripe_count == LLAPI_LAYOUT_WIDE ||
1127                 (stripe_count != 0 && stripe_count != -1 &&
1128                  llapi_stripe_count_is_valid(stripe_count));
1129 }
1130
1131 static bool llapi_layout_stripe_size_is_valid(uint64_t stripe_size)
1132 {
1133         return stripe_size == LLAPI_LAYOUT_DEFAULT ||
1134                 (stripe_size != 0 &&
1135                  llapi_stripe_size_is_aligned(stripe_size) &&
1136                  !llapi_stripe_size_is_too_big(stripe_size));
1137 }
1138
1139 static bool llapi_layout_stripe_index_is_valid(int64_t stripe_index)
1140 {
1141         return stripe_index == LLAPI_LAYOUT_DEFAULT ||
1142                 (stripe_index >= 0 &&
1143                 llapi_stripe_index_is_valid(stripe_index));
1144 }
1145
1146 /**
1147  * Set the stripe count of \a layout.
1148  *
1149  * \param[in] layout    layout to set stripe count in
1150  * \param[in] count     value to be set
1151  *
1152  * \retval      0 on success
1153  * \retval      -1 if arguments are invalid
1154  */
1155 int llapi_layout_stripe_count_set(struct llapi_layout *layout,
1156                                   uint64_t count)
1157 {
1158         struct llapi_layout_comp *comp;
1159
1160         comp = __llapi_layout_cur_comp(layout);
1161         if (comp == NULL)
1162                 return -1;
1163
1164         if (!llapi_layout_stripe_count_is_valid(count)) {
1165                 errno = EINVAL;
1166                 return -1;
1167         }
1168
1169         comp->llc_stripe_count = count;
1170
1171         return 0;
1172 }
1173
1174 /**
1175  * Get the stripe size of \a layout.
1176  *
1177  * \param[in] layout    layout to get stripe size from
1178  * \param[out] size     integer to store stripe size in
1179  *
1180  * \retval      0 on success
1181  * \retval      -1 if arguments are invalid
1182  */
1183 int llapi_layout_stripe_size_get(const struct llapi_layout *layout,
1184                                  uint64_t *size)
1185 {
1186         struct llapi_layout_comp *comp;
1187
1188         comp = __llapi_layout_cur_comp(layout);
1189         if (comp == NULL)
1190                 return -1;
1191
1192         if (size == NULL) {
1193                 errno = EINVAL;
1194                 return -1;
1195         }
1196
1197         *size = comp->llc_stripe_size;
1198
1199         return 0;
1200 }
1201
1202 /**
1203  * Set the stripe size of \a layout.
1204  *
1205  * \param[in] layout    layout to set stripe size in
1206  * \param[in] size      value to be set
1207  *
1208  * \retval      0 on success
1209  * \retval      -1 if arguments are invalid
1210  */
1211 int llapi_layout_stripe_size_set(struct llapi_layout *layout,
1212                                  uint64_t size)
1213 {
1214         struct llapi_layout_comp *comp;
1215
1216         comp = __llapi_layout_cur_comp(layout);
1217         if (comp == NULL)
1218                 return -1;
1219
1220         if (!llapi_layout_stripe_size_is_valid(size)) {
1221                 errno = EINVAL;
1222                 return -1;
1223         }
1224
1225         comp->llc_stripe_size = size;
1226
1227         return 0;
1228 }
1229
1230 /**
1231  * Get the RAID pattern of \a layout.
1232  *
1233  * \param[in] layout    layout to get pattern from
1234  * \param[out] pattern  integer to store pattern in
1235  *
1236  * \retval      0 on success
1237  * \retval      -1 if arguments are invalid
1238  */
1239 int llapi_layout_pattern_get(const struct llapi_layout *layout,
1240                              uint64_t *pattern)
1241 {
1242         struct llapi_layout_comp *comp;
1243
1244         comp = __llapi_layout_cur_comp(layout);
1245         if (comp == NULL)
1246                 return -1;
1247
1248         if (pattern == NULL) {
1249                 errno = EINVAL;
1250                 return -1;
1251         }
1252
1253         *pattern = comp->llc_pattern;
1254
1255         return 0;
1256 }
1257
1258 /**
1259  * Set the pattern of \a layout.
1260  *
1261  * \param[in] layout    layout to set pattern in
1262  * \param[in] pattern   value to be set
1263  *
1264  * \retval      0 on success
1265  * \retval      -1 if arguments are invalid or RAID pattern
1266  *              is unsupported
1267  */
1268 int llapi_layout_pattern_set(struct llapi_layout *layout, uint64_t pattern)
1269 {
1270         struct llapi_layout_comp *comp;
1271
1272         comp = __llapi_layout_cur_comp(layout);
1273         if (comp == NULL)
1274                 return -1;
1275
1276         if (pattern != LLAPI_LAYOUT_DEFAULT &&
1277             pattern != LLAPI_LAYOUT_RAID0 && pattern != LLAPI_LAYOUT_MDT) {
1278                 errno = EOPNOTSUPP;
1279                 return -1;
1280         }
1281
1282         comp->llc_pattern = pattern |
1283                             (comp->llc_pattern & LLAPI_LAYOUT_SPECIFIC);
1284
1285         return 0;
1286 }
1287
1288 static inline int stripe_number_roundup(int stripe_number)
1289 {
1290         unsigned int round_up = (stripe_number + 8) & ~7;
1291         return round_up > LOV_MAX_STRIPE_COUNT ?
1292                 LOV_MAX_STRIPE_COUNT : round_up;
1293 }
1294
1295 /**
1296  * Set the OST index of stripe number \a stripe_number to \a ost_index.
1297  *
1298  * If only the starting stripe's OST index is specified, then this can use
1299  * the normal LOV_MAGIC_{V1,V3} layout type.  If multiple OST indices are
1300  * given, then allocate an array to hold the list of indices and ensure that
1301  * the LOV_USER_MAGIC_SPECIFIC layout is used when creating the file.
1302  *
1303  * \param[in] layout            layout to set OST index in
1304  * \param[in] stripe_number     stripe number to set index for
1305  * \param[in] ost_index         the index to set
1306  *
1307  * \retval      0 on success
1308  * \retval      -1 if arguments are invalid or an unsupported stripe number
1309  *              was specified, error returned in errno
1310  */
1311 int llapi_layout_ost_index_set(struct llapi_layout *layout, int stripe_number,
1312                                uint64_t ost_index)
1313 {
1314         struct llapi_layout_comp *comp;
1315
1316         comp = __llapi_layout_cur_comp(layout);
1317         if (comp == NULL)
1318                 return -1;
1319
1320         if (!llapi_layout_stripe_index_is_valid(ost_index)) {
1321                 errno = EINVAL;
1322                 return -1;
1323         }
1324
1325         if (stripe_number == 0 && ost_index == LLAPI_LAYOUT_DEFAULT) {
1326                 comp->llc_stripe_offset = ost_index;
1327                 comp->llc_pattern &= ~LLAPI_LAYOUT_SPECIFIC;
1328                 __llapi_comp_objects_realloc(comp, 0);
1329         } else if (stripe_number >= 0 &&
1330                    stripe_number < LOV_MAX_STRIPE_COUNT) {
1331                 if (ost_index >= LLAPI_LAYOUT_IDX_MAX) {
1332                         errno = EINVAL;
1333                         return -1;
1334                 }
1335
1336                 /* Preallocate a few more stripes to avoid realloc() overhead.*/
1337                 if (__llapi_comp_objects_realloc(comp,
1338                                 stripe_number_roundup(stripe_number)) < 0)
1339                         return -1;
1340
1341                 comp->llc_objects[stripe_number].l_ost_idx = ost_index;
1342
1343                 if (stripe_number == 0)
1344                         comp->llc_stripe_offset = ost_index;
1345                 else
1346                         comp->llc_pattern |= LLAPI_LAYOUT_SPECIFIC;
1347
1348                 if (comp->llc_stripe_count == LLAPI_LAYOUT_DEFAULT ||
1349                     comp->llc_stripe_count <= stripe_number)
1350                         comp->llc_stripe_count = stripe_number + 1;
1351         } else {
1352                 errno = EINVAL;
1353                 return -1;
1354         }
1355
1356         return 0;
1357 }
1358
1359 /**
1360  * Get the OST index associated with stripe \a stripe_number.
1361  *
1362  * Stripes are indexed starting from zero.
1363  *
1364  * \param[in] layout            layout to get index from
1365  * \param[in] stripe_number     stripe number to get index for
1366  * \param[out] index            integer to store index in
1367  *
1368  * \retval      0 on success
1369  * \retval      -1 if arguments are invalid
1370  */
1371 int llapi_layout_ost_index_get(const struct llapi_layout *layout,
1372                                uint64_t stripe_number, uint64_t *index)
1373 {
1374         struct llapi_layout_comp *comp;
1375
1376         comp = __llapi_layout_cur_comp(layout);
1377         if (comp == NULL)
1378                 return -1;
1379
1380         if (index == NULL) {
1381                 errno = EINVAL;
1382                 return -1;
1383         }
1384
1385         if (stripe_number >= comp->llc_stripe_count ||
1386             stripe_number >= comp->llc_objects_count) {
1387                 errno = EINVAL;
1388                 return -1;
1389         }
1390
1391         if (comp->llc_stripe_offset == LLAPI_LAYOUT_DEFAULT)
1392                 *index = LLAPI_LAYOUT_DEFAULT;
1393         else
1394                 *index = comp->llc_objects[stripe_number].l_ost_idx;
1395
1396         return 0;
1397 }
1398
1399 /**
1400  *
1401  * Get the pool name of layout \a layout.
1402  *
1403  * \param[in] layout    layout to get pool name from
1404  * \param[out] dest     buffer to store pool name in
1405  * \param[in] n         size in bytes of buffer \a dest
1406  *
1407  * \retval      0 on success
1408  * \retval      -1 if arguments are invalid
1409  */
1410 int llapi_layout_pool_name_get(const struct llapi_layout *layout, char *dest,
1411                                size_t n)
1412 {
1413         struct llapi_layout_comp *comp;
1414
1415         comp = __llapi_layout_cur_comp(layout);
1416         if (comp == NULL)
1417                 return -1;
1418
1419         if (dest == NULL) {
1420                 errno = EINVAL;
1421                 return -1;
1422         }
1423
1424         strncpy(dest, comp->llc_pool_name, n);
1425
1426         return 0;
1427 }
1428
1429 /**
1430  * Set the name of the pool of layout \a layout.
1431  *
1432  * \param[in] layout    layout to set pool name in
1433  * \param[in] pool_name pool name to set
1434  *
1435  * \retval      0 on success
1436  * \retval      -1 if arguments are invalid or pool name is too long
1437  */
1438 int llapi_layout_pool_name_set(struct llapi_layout *layout,
1439                                const char *pool_name)
1440 {
1441         struct llapi_layout_comp *comp;
1442         char *ptr;
1443
1444         comp = __llapi_layout_cur_comp(layout);
1445         if (comp == NULL)
1446                 return -1;
1447
1448         if (pool_name == NULL) {
1449                 errno = EINVAL;
1450                 return -1;
1451         }
1452
1453         /* Strip off any 'fsname.' portion. */
1454         ptr = strchr(pool_name, '.');
1455         if (ptr != NULL)
1456                 pool_name = ptr + 1;
1457
1458         if (strlen(pool_name) > LOV_MAXPOOLNAME) {
1459                 errno = EINVAL;
1460                 return -1;
1461         }
1462
1463         strncpy(comp->llc_pool_name, pool_name, sizeof(comp->llc_pool_name));
1464
1465         return 0;
1466 }
1467
1468 /**
1469  * Open and possibly create a file with a given \a layout.
1470  *
1471  * If \a layout is NULL this function acts as a simple wrapper for
1472  * open().  By convention, ENOTTY is returned in errno if \a path
1473  * refers to a non-Lustre file.
1474  *
1475  * \param[in] path              name of the file to open
1476  * \param[in] open_flags        open() flags
1477  * \param[in] mode              permissions to create file, filtered by umask
1478  * \param[in] layout            layout to create new file with
1479  *
1480  * \retval              non-negative file descriptor on successful open
1481  * \retval              -1 if an error occurred
1482  */
1483 int llapi_layout_file_open(const char *path, int open_flags, mode_t mode,
1484                            const struct llapi_layout *layout)
1485 {
1486         int fd;
1487         int rc;
1488         int tmp;
1489         struct lov_user_md *lum;
1490         size_t lum_size;
1491
1492         if (path == NULL ||
1493             (layout != NULL && layout->llot_magic != LLAPI_LAYOUT_MAGIC)) {
1494                 errno = EINVAL;
1495                 return -1;
1496         }
1497
1498         /* Object creation must be postponed until after layout attributes
1499          * have been applied. */
1500         if (layout != NULL && (open_flags & O_CREAT))
1501                 open_flags |= O_LOV_DELAY_CREATE;
1502
1503         fd = open(path, open_flags, mode);
1504
1505         if (layout == NULL || fd < 0)
1506                 return fd;
1507
1508         lum = llapi_layout_to_lum(layout);
1509
1510         if (lum == NULL) {
1511                 tmp = errno;
1512                 close(fd);
1513                 errno = tmp;
1514                 return -1;
1515         }
1516
1517         if (lum->lmm_magic == LOV_USER_MAGIC_COMP_V1)
1518                 lum_size = ((struct lov_comp_md_v1 *)lum)->lcm_size;
1519         else if (lum->lmm_magic == LOV_USER_MAGIC_SPECIFIC)
1520                 lum_size = lov_user_md_size(lum->lmm_stripe_count,
1521                                             lum->lmm_magic);
1522         else
1523                 lum_size = lov_user_md_size(0, lum->lmm_magic);
1524
1525         rc = fsetxattr(fd, XATTR_LUSTRE_LOV, lum, lum_size, 0);
1526         if (rc < 0) {
1527                 tmp = errno;
1528                 close(fd);
1529                 errno = tmp;
1530                 fd = -1;
1531         }
1532
1533         free(lum);
1534         errno = errno == EOPNOTSUPP ? ENOTTY : errno;
1535
1536         return fd;
1537 }
1538
1539 /**
1540  * Create a file with a given \a layout.
1541  *
1542  * Force O_CREAT and O_EXCL flags on so caller is assured that file was
1543  * created with the given \a layout on successful function return.
1544  *
1545  * \param[in] path              name of the file to open
1546  * \param[in] open_flags        open() flags
1547  * \param[in] mode              permissions to create new file with
1548  * \param[in] layout            layout to create new file with
1549  *
1550  * \retval              non-negative file descriptor on successful open
1551  * \retval              -1 if an error occurred
1552  */
1553 int llapi_layout_file_create(const char *path, int open_flags, int mode,
1554                              const struct llapi_layout *layout)
1555 {
1556         return llapi_layout_file_open(path, open_flags|O_CREAT|O_EXCL, mode,
1557                                       layout);
1558 }
1559
1560 int llapi_layout_flags_get(struct llapi_layout *layout, uint32_t *flags)
1561 {
1562         if (layout->llot_magic != LLAPI_LAYOUT_MAGIC) {
1563                 errno = EINVAL;
1564                 return -1;
1565         }
1566
1567         *flags = layout->llot_flags;
1568         return 0;
1569 }
1570
1571 /**
1572  * Set flags to the header of a component layout.
1573  */
1574 int llapi_layout_flags_set(struct llapi_layout *layout, uint32_t flags)
1575 {
1576         if (layout->llot_magic != LLAPI_LAYOUT_MAGIC) {
1577                 errno = EINVAL;
1578                 return -1;
1579         }
1580
1581         layout->llot_flags = flags;
1582         return 0;
1583 }
1584
1585 const char *llapi_layout_flags_string(uint32_t flags)
1586 {
1587         switch (flags & LCM_FL_FLR_MASK) {
1588         case LCM_FL_RDONLY:
1589                 return "ro";
1590         case LCM_FL_WRITE_PENDING:
1591                 return "wp";
1592         case LCM_FL_SYNC_PENDING:
1593                 return "sp";
1594         }
1595
1596         return "0";
1597 }
1598
1599 const __u16 llapi_layout_string_flags(char *string)
1600 {
1601         if (strncmp(string, "ro", strlen(string)) == 0)
1602                 return LCM_FL_RDONLY;
1603         if (strncmp(string, "wp", strlen(string)) == 0)
1604                 return LCM_FL_WRITE_PENDING;
1605         if (strncmp(string, "sp", strlen(string)) == 0)
1606                 return LCM_FL_SYNC_PENDING;
1607
1608         return 0;
1609 }
1610
1611 /**
1612  * llapi_layout_mirror_count_is_valid() - Check the validity of mirror count.
1613  * @count: Mirror count value to be checked.
1614  *
1615  * This function checks the validity of mirror count.
1616  *
1617  * Return: true on success or false on failure.
1618  */
1619 static bool llapi_layout_mirror_count_is_valid(uint16_t count)
1620 {
1621         return count >= 0 && count <= LUSTRE_MIRROR_COUNT_MAX;
1622 }
1623
1624 /**
1625  * llapi_layout_mirror_count_get() - Get mirror count from the header of
1626  *                                   a layout.
1627  * @layout: Layout to get mirror count from.
1628  * @count:  Returned mirror count value.
1629  *
1630  * This function gets mirror count from the header of a layout.
1631  *
1632  * Return: 0 on success or -1 on failure.
1633  */
1634 int llapi_layout_mirror_count_get(struct llapi_layout *layout,
1635                                   uint16_t *count)
1636 {
1637         if (layout->llot_magic != LLAPI_LAYOUT_MAGIC) {
1638                 errno = EINVAL;
1639                 return -1;
1640         }
1641
1642         *count = layout->llot_mirror_count;
1643         return 0;
1644 }
1645
1646 /**
1647  * llapi_layout_mirror_count_set() - Set mirror count to the header of a layout.
1648  * @layout: Layout to set mirror count in.
1649  * @count:  Mirror count value to be set.
1650  *
1651  * This function sets mirror count to the header of a layout.
1652  *
1653  * Return: 0 on success or -1 on failure.
1654  */
1655 int llapi_layout_mirror_count_set(struct llapi_layout *layout,
1656                                   uint16_t count)
1657 {
1658         if (layout->llot_magic != LLAPI_LAYOUT_MAGIC) {
1659                 errno = EINVAL;
1660                 return -1;
1661         }
1662
1663         if (!llapi_layout_mirror_count_is_valid(count)) {
1664                 errno = EINVAL;
1665                 return -1;
1666         }
1667
1668         layout->llot_mirror_count = count;
1669         return 0;
1670 }
1671
1672 /**
1673  * Fetch the start and end offset of the current layout component.
1674  *
1675  * \param[in] layout    the layout component
1676  * \param[out] start    extent start, inclusive
1677  * \param[out] end      extent end, exclusive
1678  *
1679  * \retval      0 on success
1680  * \retval      <0 if error occurs
1681  */
1682 int llapi_layout_comp_extent_get(const struct llapi_layout *layout,
1683                                  uint64_t *start, uint64_t *end)
1684 {
1685         struct llapi_layout_comp *comp;
1686
1687         comp = __llapi_layout_cur_comp(layout);
1688         if (comp == NULL)
1689                 return -1;
1690
1691         if (start == NULL || end == NULL) {
1692                 errno = EINVAL;
1693                 return -1;
1694         }
1695
1696         *start = comp->llc_extent.e_start;
1697         *end = comp->llc_extent.e_end;
1698
1699         return 0;
1700 }
1701
1702 /**
1703  * Set the layout extent of a layout.
1704  *
1705  * \param[in] layout    the layout to be set
1706  * \param[in] start     extent start, inclusive
1707  * \param[in] end       extent end, exclusive
1708  *
1709  * \retval      0 on success
1710  * \retval      <0 if error occurs
1711  */
1712 int llapi_layout_comp_extent_set(struct llapi_layout *layout,
1713                                  uint64_t start, uint64_t end)
1714 {
1715         struct llapi_layout_comp *prev, *next, *comp;
1716
1717         comp = __llapi_layout_cur_comp(layout);
1718         if (comp == NULL)
1719                 return -1;
1720
1721         if (start >= end) {
1722                 errno = EINVAL;
1723                 return -1;
1724         }
1725
1726         /*
1727          * We need to make sure the extent to be set is valid: the new
1728          * extent must be adjacent with the prev & next component.
1729          */
1730         if (comp->llc_list.prev != &layout->llot_comp_list) {
1731                 prev = list_entry(comp->llc_list.prev, typeof(*prev),
1732                                   llc_list);
1733                 if (start != 0 && start != prev->llc_extent.e_end) {
1734                         errno = EINVAL;
1735                         return -1;
1736                 }
1737         }
1738
1739         if (comp->llc_list.next != &layout->llot_comp_list) {
1740                 next = list_entry(comp->llc_list.next, typeof(*next),
1741                                   llc_list);
1742                 if (next->llc_extent.e_start != 0 &&
1743                     end != next->llc_extent.e_start) {
1744                         errno = EINVAL;
1745                         return -1;
1746                 }
1747         }
1748
1749         comp->llc_extent.e_start = start;
1750         comp->llc_extent.e_end = end;
1751         layout->llot_is_composite = true;
1752
1753         return 0;
1754 }
1755
1756 /**
1757  * Gets the attribute flags of the current component.
1758  *
1759  * \param[in] layout    the layout component
1760  * \param[out] flags    stored the returned component flags
1761  *
1762  * \retval      0 on success
1763  * \retval      <0 if error occurs
1764  */
1765 int llapi_layout_comp_flags_get(const struct llapi_layout *layout,
1766                                 uint32_t *flags)
1767 {
1768         struct llapi_layout_comp *comp;
1769
1770         comp = __llapi_layout_cur_comp(layout);
1771         if (comp == NULL)
1772                 return -1;
1773
1774         if (flags == NULL) {
1775                 errno = EINVAL;
1776                 return -1;
1777         }
1778
1779         *flags = comp->llc_flags;
1780
1781         return 0;
1782 }
1783
1784 /**
1785  * Sets the specified flags of the current component leaving other flags as-is.
1786  *
1787  * \param[in] layout    the layout component
1788  * \param[in] flags     component flags to be set
1789  *
1790  * \retval      0 on success
1791  * \retval      <0 if error occurs
1792  */
1793 int llapi_layout_comp_flags_set(struct llapi_layout *layout, uint32_t flags)
1794 {
1795         struct llapi_layout_comp *comp;
1796
1797         comp = __llapi_layout_cur_comp(layout);
1798         if (comp == NULL)
1799                 return -1;
1800
1801         comp->llc_flags |= flags;
1802
1803         return 0;
1804 }
1805
1806 /**
1807  * Clears the flags specified in the flags leaving other flags as-is.
1808  *
1809  * \param[in] layout    the layout component
1810  * \param[in] flags     component flags to be cleared
1811  *
1812  * \retval      0 on success
1813  * \retval      <0 if error occurs
1814  */
1815 int llapi_layout_comp_flags_clear(struct llapi_layout *layout,
1816                                   uint32_t flags)
1817 {
1818         struct llapi_layout_comp *comp;
1819
1820         comp = __llapi_layout_cur_comp(layout);
1821         if (comp == NULL)
1822                 return -1;
1823
1824         comp->llc_flags &= ~flags;
1825
1826         return 0;
1827 }
1828
1829 /**
1830  * Fetches the file-unique component ID of the current layout component.
1831  *
1832  * \param[in] layout    the layout component
1833  * \param[out] id       stored the returned component ID
1834  *
1835  * \retval      0 on success
1836  * \retval      <0 if error occurs
1837  */
1838 int llapi_layout_comp_id_get(const struct llapi_layout *layout, uint32_t *id)
1839 {
1840         struct llapi_layout_comp *comp;
1841
1842         comp = __llapi_layout_cur_comp(layout);
1843         if (comp == NULL)
1844                 return -1;
1845
1846         if (id == NULL) {
1847                 errno = EINVAL;
1848                 return -1;
1849         }
1850         *id = comp->llc_id;
1851
1852         return 0;
1853 }
1854
1855 /**
1856  * Return the mirror id of the current layout component.
1857  *
1858  * \param[in] layout    the layout component
1859  * \param[out] id       stored the returned mirror ID
1860  *
1861  * \retval      0 on success
1862  * \retval      <0 if error occurs
1863  */
1864 int llapi_layout_mirror_id_get(const struct llapi_layout *layout, uint32_t *id)
1865 {
1866         struct llapi_layout_comp *comp;
1867
1868         comp = __llapi_layout_cur_comp(layout);
1869         if (comp == NULL)
1870                 return -1;
1871
1872         if (id == NULL) {
1873                 errno = EINVAL;
1874                 return -1;
1875         }
1876
1877         *id = mirror_id_of(comp->llc_id);
1878
1879         return 0;
1880 }
1881
1882 /**
1883  * Adds a component to \a layout, the new component will be added to
1884  * the tail of components list and it'll inherit attributes of existing
1885  * ones. The \a layout will change it's current component pointer to
1886  * the newly added component, and it'll be turned into a composite
1887  * layout if it was not before the adding.
1888  *
1889  * \param[in] layout    existing composite or plain layout
1890  *
1891  * \retval      0 on success
1892  * \retval      <0 if error occurs
1893  */
1894 int llapi_layout_comp_add(struct llapi_layout *layout)
1895 {
1896         struct llapi_layout_comp *last, *comp, *new;
1897
1898         comp = __llapi_layout_cur_comp(layout);
1899         if (comp == NULL)
1900                 return -1;
1901
1902         new = __llapi_comp_alloc(0);
1903         if (new == NULL)
1904                 return -1;
1905
1906         last = list_entry(layout->llot_comp_list.prev, typeof(*last),
1907                           llc_list);
1908
1909         if (new->llc_extent.e_end <= last->llc_extent.e_end) {
1910                 __llapi_comp_free(new);
1911                 errno = EINVAL;
1912                 return -1;
1913         }
1914         new->llc_extent.e_start = last->llc_extent.e_end;
1915
1916         list_add_tail(&new->llc_list, &layout->llot_comp_list);
1917         layout->llot_cur_comp = new;
1918         layout->llot_is_composite = true;
1919
1920         return 0;
1921 }
1922 /**
1923  * Adds a first component of a mirror to \a layout.
1924  * The \a layout will change it's current component pointer to
1925  * the newly added component, and it'll be turned into a composite
1926  * layout if it was not before the adding.
1927  *
1928  * \param[in] layout            existing composite or plain layout
1929  *
1930  * \retval      0 on success
1931  * \retval      <0 if error occurs
1932  */
1933 int llapi_layout_add_first_comp(struct llapi_layout *layout)
1934 {
1935         struct llapi_layout_comp *comp, *new;
1936
1937         comp = __llapi_layout_cur_comp(layout);
1938         if (comp == NULL)
1939                 return -1;
1940
1941         new = __llapi_comp_alloc(0);
1942         if (new == NULL)
1943                 return -1;
1944
1945         new->llc_extent.e_start = 0;
1946
1947         list_add_tail(&new->llc_list, &layout->llot_comp_list);
1948         layout->llot_cur_comp = new;
1949         layout->llot_is_composite = true;
1950
1951         return 0;
1952 }
1953
1954 /**
1955  * Deletes current component from the composite layout. The component
1956  * to be deleted must be the tail of components list, and it can't be
1957  * the only component in the layout.
1958  *
1959  * \param[in] layout    composite layout
1960  *
1961  * \retval      0 on success
1962  * \retval      <0 if error occurs
1963  */
1964 int llapi_layout_comp_del(struct llapi_layout *layout)
1965 {
1966         struct llapi_layout_comp *comp;
1967
1968         comp = __llapi_layout_cur_comp(layout);
1969         if (comp == NULL)
1970                 return -1;
1971
1972         if (!layout->llot_is_composite) {
1973                 errno = EINVAL;
1974                 return -1;
1975         }
1976
1977         /* It must be the tail of the list (for PFL, can be relaxed
1978          * once we get mirrored components) */
1979         if (comp->llc_list.next != &layout->llot_comp_list) {
1980                 errno = EINVAL;
1981                 return -1;
1982         }
1983         /* It can't be the only one on the list */
1984         if (comp->llc_list.prev == &layout->llot_comp_list) {
1985                 errno = EINVAL;
1986                 return -1;
1987         }
1988
1989         layout->llot_cur_comp =
1990                 list_entry(comp->llc_list.prev, typeof(*comp), llc_list);
1991         list_del_init(&comp->llc_list);
1992         __llapi_comp_free(comp);
1993
1994         return 0;
1995 }
1996
1997 /**
1998  * Move the current component pointer to the component with
1999  * specified component ID.
2000  *
2001  * \param[in] layout    composite layout
2002  * \param[in] id        component ID
2003  *
2004  * \retval      =0 : moved successfully
2005  * \retval      <0 if error occurs
2006  */
2007 int llapi_layout_comp_use_id(struct llapi_layout *layout, uint32_t comp_id)
2008 {
2009         struct llapi_layout_comp *comp;
2010
2011         comp = __llapi_layout_cur_comp(layout);
2012         if (comp == NULL)
2013                 return -1; /* use previously set errno */
2014
2015         if (!layout->llot_is_composite) {
2016                 errno = EINVAL;
2017                 return -1;
2018         }
2019
2020         if (comp_id == LCME_ID_INVAL) {
2021                 errno = EINVAL;
2022                 return -1;
2023         }
2024
2025         list_for_each_entry(comp, &layout->llot_comp_list, llc_list) {
2026                 if (comp->llc_id == comp_id) {
2027                         layout->llot_cur_comp = comp;
2028                         return 0;
2029                 }
2030         }
2031         errno = ENOENT;
2032         return -1;
2033 }
2034
2035 /**
2036  * Move the current component pointer to a specified position.
2037  *
2038  * \param[in] layout    composite layout
2039  * \param[in] pos       the position to be moved, it can be:
2040  *                      LLAPI_LAYOUT_COMP_USE_FIRST: use first component
2041  *                      LLAPI_LAYOUT_COMP_USE_LAST: use last component
2042  *                      LLAPI_LAYOUT_COMP_USE_NEXT: use component after current
2043  *                      LLAPI_LAYOUT_COMP_USE_PREV: use component before current
2044  *
2045  * \retval      =0 : moved successfully
2046  * \retval      =1 : at last component with NEXT, at first component with PREV
2047  * \retval      <0 if error occurs
2048  */
2049 int llapi_layout_comp_use(struct llapi_layout *layout,
2050                           enum llapi_layout_comp_use pos)
2051 {
2052         struct llapi_layout_comp *comp, *head, *tail;
2053
2054         comp = __llapi_layout_cur_comp(layout);
2055         if (comp == NULL)
2056                 return -1;
2057
2058         if (!layout->llot_is_composite) {
2059                 if (pos == LLAPI_LAYOUT_COMP_USE_FIRST ||
2060                     pos == LLAPI_LAYOUT_COMP_USE_LAST)
2061                         return 0;
2062                 errno = ENOENT;
2063                 return 1;
2064         }
2065
2066         head = list_entry(layout->llot_comp_list.next, typeof(*head), llc_list);
2067         tail = list_entry(layout->llot_comp_list.prev, typeof(*tail), llc_list);
2068         switch (pos) {
2069         case LLAPI_LAYOUT_COMP_USE_FIRST:
2070                 layout->llot_cur_comp = head;
2071                 break;
2072         case LLAPI_LAYOUT_COMP_USE_NEXT:
2073                 if (comp == tail) {
2074                         errno = ENOENT;
2075                         return 1;
2076                 }
2077                 layout->llot_cur_comp = list_entry(comp->llc_list.next,
2078                                                    typeof(*comp), llc_list);
2079                 break;
2080         case LLAPI_LAYOUT_COMP_USE_LAST:
2081                 layout->llot_cur_comp = tail;
2082                 break;
2083         case LLAPI_LAYOUT_COMP_USE_PREV:
2084                 if (comp == head) {
2085                         errno = ENOENT;
2086                         return 1;
2087                 }
2088                 layout->llot_cur_comp = list_entry(comp->llc_list.prev,
2089                                                    typeof(*comp), llc_list);
2090                 break;
2091         default:
2092                 errno = EINVAL;
2093                 return -1;
2094         }
2095
2096         return 0;
2097 }
2098
2099 /**
2100  * Add layout component(s) to an existing file.
2101  *
2102  * \param[in] path      The path name of the file
2103  * \param[in] layout    The layout component(s) to be added
2104  */
2105 int llapi_layout_file_comp_add(const char *path,
2106                                const struct llapi_layout *layout)
2107 {
2108         int rc, fd, lum_size, tmp_errno = 0;
2109         struct lov_user_md *lum;
2110
2111         if (path == NULL || layout == NULL ||
2112             layout->llot_magic != LLAPI_LAYOUT_MAGIC) {
2113                 errno = EINVAL;
2114                 return -1;
2115         }
2116
2117         lum = llapi_layout_to_lum(layout);
2118         if (lum == NULL)
2119                 return -1;
2120
2121         if (lum->lmm_magic != LOV_USER_MAGIC_COMP_V1) {
2122                 free(lum);
2123                 errno = EINVAL;
2124                 return -1;
2125         }
2126         lum_size = ((struct lov_comp_md_v1 *)lum)->lcm_size;
2127
2128         fd = open(path, O_RDWR);
2129         if (fd < 0) {
2130                 tmp_errno = errno;
2131                 rc = -1;
2132                 goto out;
2133         }
2134
2135         rc = fsetxattr(fd, XATTR_LUSTRE_LOV".add", lum, lum_size, 0);
2136         if (rc < 0) {
2137                 tmp_errno = errno;
2138                 close(fd);
2139                 rc = -1;
2140                 goto out;
2141         }
2142         close(fd);
2143 out:
2144         free(lum);
2145         errno = tmp_errno;
2146         return rc;
2147 }
2148
2149 /**
2150  * Delete component(s) by the specified component id or component flags
2151  * from an existing file.
2152  *
2153  * \param[in] path      path name of the file
2154  * \param[in] id        unique component ID
2155  * \param[in] flags     flags: LCME_FL_* or;
2156  *                      negative flags: (LCME_FL_NEG|LCME_FL_*)
2157  */
2158 int llapi_layout_file_comp_del(const char *path, uint32_t id, uint32_t flags)
2159 {
2160         int rc, fd, lum_size;
2161         struct llapi_layout *layout;
2162         struct llapi_layout_comp *comp;
2163         struct lov_user_md *lum;
2164
2165         if (path == NULL || id > LCME_ID_MAX || (flags & ~LCME_KNOWN_FLAGS)) {
2166                 errno = EINVAL;
2167                 return -1;
2168         }
2169
2170         /* Can only specify ID or flags, not both. */
2171         if (id != 0 && flags != 0) {
2172                 errno = EINVAL;
2173                 return -1;
2174         }
2175
2176         layout = llapi_layout_alloc();
2177         if (layout == NULL)
2178                 return -1;
2179
2180         llapi_layout_comp_extent_set(layout, 0, LUSTRE_EOF);
2181         comp = __llapi_layout_cur_comp(layout);
2182         if (comp == NULL) {
2183                 llapi_layout_free(layout);
2184                 return -1;
2185         }
2186
2187         comp->llc_id = id;
2188         comp->llc_flags = flags;
2189
2190         lum = llapi_layout_to_lum(layout);
2191         if (lum == NULL) {
2192                 llapi_layout_free(layout);
2193                 return -1;
2194         }
2195         lum_size = ((struct lov_comp_md_v1 *)lum)->lcm_size;
2196
2197         fd = open(path, O_RDWR);
2198         if (fd < 0) {
2199                 rc = -1;
2200                 goto out;
2201         }
2202
2203         rc = fsetxattr(fd, XATTR_LUSTRE_LOV".del", lum, lum_size, 0);
2204         if (rc < 0) {
2205                 int tmp_errno = errno;
2206                 close(fd);
2207                 errno = tmp_errno;
2208                 rc = -1;
2209                 goto out;
2210         }
2211         close(fd);
2212 out:
2213         free(lum);
2214         llapi_layout_free(layout);
2215         return rc;
2216 }
2217
2218 /**
2219  * Change flags or other parameters of the component(s) by component ID of an
2220  * existing file. The component to be modified is specified by the
2221  * comp->lcme_id value, which must be an unique component ID. The new
2222  * attributes are passed in by @comp and @valid is used to specify which
2223  * attributes in the component are going to be changed.
2224  *
2225  * \param[in] path      path name of the file
2226  * \param[in] ids       An array of component IDs
2227  * \param[in] flags     flags: LCME_FL_* or;
2228  *                      negative flags: (LCME_FL_NEG|LCME_FL_*)
2229  * \param[in] count     Number of elements in ids and flags array
2230  */
2231 int llapi_layout_file_comp_set(const char *path, uint32_t *ids, uint32_t *flags,
2232                                size_t count)
2233 {
2234         int rc = -1, fd = -1, i;
2235         size_t lum_size;
2236         struct llapi_layout *layout;
2237         struct llapi_layout_comp *comp;
2238         struct lov_user_md *lum = NULL;
2239
2240         if (path == NULL) {
2241                 errno = EINVAL;
2242                 return -1;
2243         }
2244
2245         if (!count)
2246                 return 0;
2247
2248         for (i = 0; i < count; i++) {
2249                 if (!ids[i] || !flags[i]) {
2250                         errno = EINVAL;
2251                         return -1;
2252                 }
2253
2254                 if (ids[i] > LCME_ID_MAX || (flags[i] & ~LCME_KNOWN_FLAGS)) {
2255                         errno = EINVAL;
2256                         return -1;
2257                 }
2258
2259                 /* do not allow to set or clear INIT flag */
2260                 if (flags[i] & LCME_FL_INIT) {
2261                         errno = EINVAL;
2262                         return -1;
2263                 }
2264         }
2265
2266         layout = __llapi_layout_alloc();
2267         if (layout == NULL)
2268                 return -1;
2269
2270         layout->llot_is_composite = true;
2271         for (i = 0; i < count; i++) {
2272                 comp = __llapi_comp_alloc(0);
2273                 if (comp == NULL)
2274                         goto out;
2275
2276                 comp->llc_id = ids[i];
2277                 comp->llc_flags = flags[i];
2278
2279                 list_add_tail(&comp->llc_list, &layout->llot_comp_list);
2280                 layout->llot_cur_comp = comp;
2281         }
2282
2283         lum = llapi_layout_to_lum(layout);
2284         if (lum == NULL)
2285                 goto out;
2286
2287         lum_size = ((struct lov_comp_md_v1 *)lum)->lcm_size;
2288
2289         fd = open(path, O_RDWR);
2290         if (fd < 0)
2291                 goto out;
2292
2293         /* flush cached pages from clients */
2294         rc = llapi_file_flush(fd);
2295         if (rc) {
2296                 errno = -rc;
2297                 rc = -1;
2298                 goto out_close;
2299         }
2300
2301         rc = fsetxattr(fd, XATTR_LUSTRE_LOV".set.flags", lum, lum_size, 0);
2302         if (rc < 0)
2303                 goto out_close;
2304
2305         rc = 0;
2306
2307 out_close:
2308         if (fd >= 0) {
2309                 int tmp_errno = errno;
2310                 close(fd);
2311                 errno = tmp_errno;
2312         }
2313 out:
2314         if (lum)
2315                 free(lum);
2316         llapi_layout_free(layout);
2317         return rc;
2318 }
2319
2320 /**
2321  * Check if the file layout is composite.
2322  *
2323  * \param[in] layout    the file layout to check
2324  *
2325  * \retval true         composite
2326  * \retval false        not composite
2327  */
2328 bool llapi_layout_is_composite(struct llapi_layout *layout)
2329 {
2330         return layout->llot_is_composite;
2331 }
2332
2333 /**
2334  * Iterate every components in the @layout and call callback function @cb.
2335  *
2336  * \param[in] layout    component layout list.
2337  * \param[in] cb        callback for each component
2338  * \param[in] cbdata    callback data
2339  *
2340  * \retval < 0                          error happens during the iteration
2341  * \retval LLAPI_LAYOUT_ITER_CONT       finished the iteration w/o error
2342  * \retval LLAPI_LAYOUT_ITER_STOP       got something, stop the iteration
2343  */
2344 int llapi_layout_comp_iterate(struct llapi_layout *layout,
2345                               llapi_layout_iter_cb cb, void *cbdata)
2346 {
2347         int rc;
2348
2349         rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_FIRST);
2350         if (rc < 0)
2351                 return rc;
2352
2353         /**
2354          * make sure on success llapi_layout_comp_use() API returns 0 with
2355          * USE_FIRST.
2356          */
2357         assert(rc == 0);
2358
2359         while (1) {
2360                 rc = cb(layout, cbdata);
2361                 if (rc != LLAPI_LAYOUT_ITER_CONT)
2362                         break;
2363
2364                 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_NEXT);
2365                 if (rc < 0)
2366                         return rc;
2367                 else if (rc == 1)       /* reached the last comp */
2368                         return LLAPI_LAYOUT_ITER_CONT;
2369         }
2370
2371         return rc;
2372 }
2373
2374 /**
2375  * llapi_layout_merge() - Merge a composite layout into another one.
2376  * @dst_layout: Destination composite layout.
2377  * @src_layout: Source composite layout.
2378  *
2379  * This function copies all of the components from @src_layout and
2380  * appends them to @dst_layout.
2381  *
2382  * Return: 0 on success or -1 on failure.
2383  */
2384 int llapi_layout_merge(struct llapi_layout **dst_layout,
2385                        const struct llapi_layout *src_layout)
2386 {
2387         struct llapi_layout *new_layout = *dst_layout;
2388         struct llapi_layout_comp *new = NULL;
2389         struct llapi_layout_comp *comp = NULL;
2390         int i = 0;
2391
2392         if (src_layout == NULL ||
2393             list_empty((struct list_head *)&src_layout->llot_comp_list))
2394                 return 0;
2395
2396         if (new_layout == NULL) {
2397                 new_layout = __llapi_layout_alloc();
2398                 if (new_layout == NULL) {
2399                         errno = ENOMEM;
2400                         return -1;
2401                 }
2402         }
2403
2404         list_for_each_entry(comp, &src_layout->llot_comp_list, llc_list) {
2405                 new = __llapi_comp_alloc(0);
2406                 if (new == NULL) {
2407                         errno = ENOMEM;
2408                         goto error;
2409                 }
2410
2411                 new->llc_pattern = comp->llc_pattern;
2412                 new->llc_stripe_size = comp->llc_stripe_size;
2413                 new->llc_stripe_count = comp->llc_stripe_count;
2414                 new->llc_stripe_offset = comp->llc_stripe_offset;
2415
2416                 if (comp->llc_pool_name[0] != '\0')
2417                         strncpy(new->llc_pool_name, comp->llc_pool_name,
2418                                 sizeof(new->llc_pool_name));
2419
2420                 for (i = 0; i < comp->llc_objects_count; i++) {
2421                         if (__llapi_comp_objects_realloc(new,
2422                             stripe_number_roundup(i)) < 0) {
2423                                 errno = EINVAL;
2424                                 __llapi_comp_free(new);
2425                                 goto error;
2426                         }
2427                         new->llc_objects[i].l_ost_idx = \
2428                                 comp->llc_objects[i].l_ost_idx;
2429                 }
2430
2431                 new->llc_objects_count = comp->llc_objects_count;
2432                 new->llc_extent.e_start = comp->llc_extent.e_start;
2433                 new->llc_extent.e_end = comp->llc_extent.e_end;
2434                 new->llc_id = comp->llc_id;
2435                 new->llc_flags = comp->llc_flags;
2436
2437                 list_add_tail(&new->llc_list, &new_layout->llot_comp_list);
2438                 new_layout->llot_cur_comp = new;
2439         }
2440         new_layout->llot_is_composite = true;
2441
2442         *dst_layout = new_layout;
2443         return 0;
2444 error:
2445         llapi_layout_free(new_layout);
2446         return -1;
2447 }
2448
2449 /**
2450  * Find all stale components.
2451  *
2452  * \param[in] layout            component layout list.
2453  * \param[out] comp             array of stale component info.
2454  * \param[in] comp_size         array size of @comp.
2455  * \param[in] mirror_ids        array of mirror id that only components
2456  *                              belonging to these mirror will be collected.
2457  * \param[in] ids_nr            number of mirror ids array.
2458  *
2459  * \retval              number of component info collected on sucess or
2460  *                      an error code on failure.
2461  */
2462 int llapi_mirror_find_stale(struct llapi_layout *layout,
2463                 struct llapi_resync_comp *comp, size_t comp_size,
2464                 __u16 *mirror_ids, int ids_nr)
2465 {
2466         int idx = 0;
2467         int rc;
2468
2469         rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_FIRST);
2470         if (rc < 0)
2471                 goto error;
2472
2473         while (rc == 0) {
2474                 uint32_t id;
2475                 uint32_t mirror_id;
2476                 uint32_t flags;
2477                 uint64_t start, end;
2478
2479                 rc = llapi_layout_comp_flags_get(layout, &flags);
2480                 if (rc < 0)
2481                         goto error;
2482
2483                 if (!(flags & LCME_FL_STALE))
2484                         goto next;
2485
2486                 rc = llapi_layout_mirror_id_get(layout, &mirror_id);
2487                 if (rc < 0)
2488                         goto error;
2489
2490                 /* the caller only wants stale components from specific
2491                  * mirrors */
2492                 if (ids_nr > 0) {
2493                         int j;
2494
2495                         for (j = 0; j < ids_nr; j++) {
2496                                 if (mirror_ids[j] == mirror_id)
2497                                         break;
2498                         }
2499
2500                         /* not in the specified mirror */
2501                         if (j == ids_nr)
2502                                 goto next;
2503                 } else if (flags & LCME_FL_NOSYNC) {
2504                         /* if not specified mirrors, do not resync "nosync"
2505                          * mirrors */
2506                         goto next;
2507                 }
2508
2509                 rc = llapi_layout_comp_id_get(layout, &id);
2510                 if (rc < 0)
2511                         goto error;
2512
2513                 rc = llapi_layout_comp_extent_get(layout, &start, &end);
2514                 if (rc < 0)
2515                         goto error;
2516
2517                 /* pack this component into @comp array */
2518                 comp[idx].lrc_id = id;
2519                 comp[idx].lrc_mirror_id = mirror_id;
2520                 comp[idx].lrc_start = start;
2521                 comp[idx].lrc_end = end;
2522                 idx++;
2523
2524                 if (idx >= comp_size) {
2525                         rc = -EINVAL;
2526                         goto error;
2527                 }
2528
2529         next:
2530                 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_NEXT);
2531                 if (rc < 0) {
2532                         rc = -EINVAL;
2533                         goto error;
2534                 }
2535         }
2536 error:
2537         return rc < 0 ? rc : idx;
2538 }
2539
2540 /* locate @layout to a valid component covering file [file_start, file_end) */
2541 uint32_t llapi_mirror_find(struct llapi_layout *layout,
2542                            uint64_t file_start, uint64_t file_end,
2543                            uint64_t *endp)
2544 {
2545         uint32_t mirror_id = 0;
2546         int rc;
2547
2548         rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_FIRST);
2549         if (rc < 0)
2550                 return rc;
2551
2552         *endp = 0;
2553         while (rc == 0) {
2554                 uint64_t start, end;
2555                 uint32_t flags, id, rid;
2556
2557                 rc = llapi_layout_comp_flags_get(layout, &flags);
2558                 if (rc < 0)
2559                         return rc;
2560
2561                 if (flags & LCME_FL_STALE)
2562                         goto next;
2563
2564                 rc = llapi_layout_mirror_id_get(layout, &rid);
2565                 if (rc < 0)
2566                         return rc;
2567
2568                 rc = llapi_layout_comp_id_get(layout, &id);
2569                 if (rc < 0)
2570                         return rc;
2571
2572                 rc = llapi_layout_comp_extent_get(layout, &start, &end);
2573                 if (rc < 0)
2574                         return rc;
2575
2576                 if (file_start >= start && file_start < end) {
2577                         if (!mirror_id)
2578                                 mirror_id = rid;
2579                         else if (mirror_id != rid || *endp != start)
2580                                 break;
2581
2582                         file_start = *endp = end;
2583                         if (end >= file_end)
2584                                 break;
2585                 }
2586
2587         next:
2588                 rc = llapi_layout_comp_use(layout, LLAPI_LAYOUT_COMP_USE_NEXT);
2589                 if (rc < 0)
2590                         return rc;
2591         }
2592
2593         return mirror_id;
2594 }
2595
2596 int llapi_mirror_resync_many(int fd, struct llapi_layout *layout,
2597                              struct llapi_resync_comp *comp_array,
2598                              int comp_size,  uint64_t start, uint64_t end)
2599 {
2600         uint64_t count;
2601         size_t page_size = sysconf(_SC_PAGESIZE);
2602         const size_t buflen = 4 << 20; /* 4M */
2603         void *buf;
2604         uint64_t pos = start;
2605         int i;
2606         int rc;
2607         int rc2 = 0;
2608
2609         rc = posix_memalign(&buf, page_size, buflen);
2610         if (rc)
2611                 return -rc;
2612
2613         if (end == OBD_OBJECT_EOF)
2614                 count = OBD_OBJECT_EOF;
2615         else
2616                 count = end - start;
2617
2618         while (count > 0) {
2619                 uint32_t src;
2620                 uint64_t mirror_end = 0;
2621                 uint64_t bytes_left;
2622                 ssize_t bytes_read;
2623                 size_t to_read;
2624                 size_t to_write;
2625
2626                 src = llapi_mirror_find(layout, pos, end, &mirror_end);
2627                 if (src == 0)
2628                         return -ENOENT;
2629
2630                 if (mirror_end == OBD_OBJECT_EOF) {
2631                         bytes_left = count;
2632                 } else {
2633                         bytes_left = MIN(count, mirror_end - pos);
2634                         bytes_left = ((bytes_left - 1) | (page_size - 1)) + 1;
2635                 }
2636                 to_read = MIN(buflen, bytes_left);
2637
2638                 bytes_read = llapi_mirror_read(fd, src, buf, to_read, pos);
2639                 if (bytes_read == 0) {
2640                         /* end of file */
2641                         break;
2642                 }
2643                 if (bytes_read < 0) {
2644                         rc = bytes_read;
2645                         break;
2646                 }
2647
2648                 /* round up to page align to make direct IO happy. */
2649                 to_write = ((bytes_read - 1) | (page_size - 1)) + 1;
2650
2651                 for (i = 0; i < comp_size; i++) {
2652                         ssize_t written;
2653                         off_t pos2 = pos;
2654                         size_t to_write2 = to_write;
2655
2656                         /* skip non-overlapped component */
2657                         if (pos >= comp_array[i].lrc_end ||
2658                             pos + to_write <= comp_array[i].lrc_start)
2659                                 continue;
2660
2661                         if (pos < comp_array[i].lrc_start)
2662                                 pos2 = comp_array[i].lrc_start;
2663
2664                         to_write2 -= pos2 - pos;
2665
2666                         if ((pos + to_write) > comp_array[i].lrc_end)
2667                                 to_write2 -= pos + to_write -
2668                                              comp_array[i].lrc_end;
2669
2670                         written = llapi_mirror_write(fd,
2671                                         comp_array[i].lrc_mirror_id,
2672                                         buf + pos2 - pos,
2673                                         to_write2, pos2);
2674                         if (written < 0) {
2675                                 /**
2676                                  * this component is not written successfully,
2677                                  * mark it using its lrc_synced, it is supposed
2678                                  * to be false before getting here.
2679                                  *
2680                                  * And before this function returns, all
2681                                  * elements of comp_array will reverse their
2682                                  * lrc_synced flag to reflect their true
2683                                  * meanings.
2684                                  */
2685                                 comp_array[i].lrc_synced = true;
2686                                 llapi_error(LLAPI_MSG_ERROR, written,
2687                                             "component %u not synced\n",
2688                                             comp_array[i].lrc_id);
2689                                 if (rc2 == 0)
2690                                         rc2 = (int)written;
2691                                 continue;
2692                         }
2693                         assert(written == to_write2);
2694                 }
2695
2696                 pos += bytes_read;
2697                 count -= bytes_read;
2698         }
2699
2700         free(buf);
2701
2702         if (rc < 0) {
2703                 /* fatal error happens */
2704                 for (i = 0; i < comp_size; i++)
2705                         comp_array[i].lrc_synced = false;
2706                 return rc;
2707         }
2708
2709         /**
2710          * no fatal error happens, each lrc_synced tells whether the component
2711          * has been resync successfully (note: we'd reverse the value to
2712          * reflect its true meaning.
2713          */
2714         for (i = 0; i < comp_size; i++) {
2715                 comp_array[i].lrc_synced = !comp_array[i].lrc_synced;
2716                 if (comp_array[i].lrc_synced && pos & (page_size - 1)) {
2717                         rc = llapi_mirror_truncate(fd,
2718                                         comp_array[i].lrc_mirror_id, pos);
2719                         if (rc < 0)
2720                                 comp_array[i].lrc_synced = false;
2721                 }
2722         }
2723
2724         /**
2725          * returns the first error code for partially successful resync if
2726          * possible.
2727          */
2728         return rc2;
2729 }
2730
2731 int lov_comp_md_size(struct lov_comp_md_v1 *lcm)
2732 {
2733         if (lcm->lcm_magic == LOV_MAGIC_V1 || lcm->lcm_magic == LOV_MAGIC_V3) {
2734                 struct lov_user_md *lum = (void *)lcm;
2735
2736                 return lov_user_md_size(lum->lmm_stripe_count, lum->lmm_magic);
2737         }
2738
2739         if (lcm->lcm_magic != LOV_MAGIC_COMP_V1)
2740                 return -EOPNOTSUPP;
2741
2742         return lcm->lcm_size;
2743 }
2744
2745 int llapi_get_lum_file_fd(int dir_fd, const char *fname, __u64 *valid,
2746                           lstatx_t *statx, struct lov_user_md *lum,
2747                           size_t lumsize)
2748 {
2749         struct lov_user_mds_data *lmd;
2750         char buf[65536 + offsetof(typeof(*lmd), lmd_lmm)];
2751         int parent_fd = -1;
2752         int rc;
2753
2754         if (lum && lumsize < sizeof(*lum))
2755                 return -EINVAL;
2756
2757         /* If a file name is provided, it is relative to the parent directory */
2758         if (fname) {
2759                 parent_fd = dir_fd;
2760                 dir_fd = -1;
2761         }
2762
2763         lmd = (struct lov_user_mds_data *)buf;
2764         rc = get_lmd_info_fd(fname, parent_fd, dir_fd, buf, sizeof(buf),
2765                              GET_LMD_INFO);
2766         if (rc)
2767                 return rc;
2768
2769         *valid = lmd->lmd_flags;
2770         if (statx)
2771                 memcpy(statx, &lmd->lmd_stx, sizeof(*statx));
2772
2773         if (lum) {
2774                 if (lmd->lmd_lmmsize > lumsize)
2775                         return -EOVERFLOW;
2776                 memcpy(lum, &lmd->lmd_lmm, lmd->lmd_lmmsize);
2777         }
2778
2779         return 0;
2780 }
2781
2782 int llapi_get_lum_dir_fd(int dir_fd, __u64 *valid, lstatx_t *statx,
2783                          struct lov_user_md *lum, size_t lumsize)
2784 {
2785         return llapi_get_lum_file_fd(dir_fd, NULL, valid, statx, lum, lumsize);
2786 }
2787
2788 int llapi_get_lum_file(const char *path, __u64 *valid, lstatx_t *statx,
2789                        struct lov_user_md *lum, size_t lumsize)
2790 {
2791         char parent[PATH_MAX];
2792         const char *fname;
2793         char *tmp;
2794         int offset;
2795         int dir_fd;
2796         int rc;
2797
2798         tmp = strrchr(path, '/');
2799         if (!tmp) {
2800                 strncpy(parent, ".", sizeof(parent) - 1);
2801                 offset = -1;
2802         } else {
2803                 strncpy(parent, path, tmp - path);
2804                 offset = tmp - path - 1;
2805                 parent[tmp - path] = 0;
2806         }
2807
2808         fname = path;
2809         if (offset >= 0)
2810                 fname += offset + 2;
2811
2812         dir_fd = open(parent, O_RDONLY);
2813         if (dir_fd < 0) {
2814                 rc = -errno;
2815                 llapi_error(LLAPI_MSG_ERROR, rc, "cannot open '%s'", path);
2816                 return rc;
2817         }
2818
2819         rc = llapi_get_lum_file_fd(dir_fd, fname, valid, statx, lum, lumsize);
2820         close(dir_fd);
2821         return rc;
2822 }
2823
2824 int llapi_get_lum_dir(const char *path, __u64 *valid, lstatx_t *statx,
2825                       struct lov_user_md *lum, size_t lumsize)
2826 {
2827         int dir_fd;
2828         int rc;
2829
2830         dir_fd = open(path, O_RDONLY);
2831         if (dir_fd < 0) {
2832                 rc = -errno;
2833                 llapi_error(LLAPI_MSG_ERROR, rc, "cannot open '%s'", path);
2834                 return rc;
2835         }
2836
2837         rc = llapi_get_lum_dir_fd(dir_fd, valid, statx, lum, lumsize);
2838         close(dir_fd);
2839         return rc;
2840 }