Whamcloud - gitweb
937d5ccb0610cfa20d3c9fc953b7f892643198fc
[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  * Author: Ned Bass <bass6@llnl.gov>
27  */
28
29 #include <stdio.h>
30 #include <fcntl.h>
31 #include <stdlib.h>
32 #include <unistd.h>
33 #include <errno.h>
34 #include <limits.h>
35 #include <sys/xattr.h>
36
37 #include <lustre/lustreapi.h>
38 #include <lustre/lustre_idl.h>
39 #include "lustreapi_internal.h"
40
41 /**
42  * An Opaque data type abstracting the layout of a Lustre file.
43  *
44  * Duplicate the fields we care about from struct lov_user_md_v3.
45  * Deal with v1 versus v3 format issues only when we read or write
46  * files.
47  */
48 struct llapi_layout {
49         uint32_t        llot_magic;
50         uint64_t        llot_pattern;
51         uint64_t        llot_stripe_size;
52         uint64_t        llot_stripe_count;
53         uint64_t        llot_stripe_offset;
54         /** Indicates if llot_objects array has been initialized. */
55         bool            llot_objects_are_valid;
56         /* Add 1 so user always gets back a null terminated string. */
57         char            llot_pool_name[LOV_MAXPOOLNAME + 1];
58         struct          lov_user_ost_data_v1 llot_objects[0];
59 };
60
61 /**
62  * Byte-swap the fields of struct lov_user_md.
63  *
64  * XXX Rather than duplicating swabbing code here, we should eventually
65  * refactor the needed functions in lustre/ptlrpc/pack_generic.c
66  * into a library that can be shared between kernel and user code.
67  */
68 static void
69 llapi_layout_swab_lov_user_md(struct lov_user_md *lum, int object_count)
70 {
71         int i;
72         struct lov_user_md_v3 *lumv3 = (struct lov_user_md_v3 *)lum;
73         struct lov_user_ost_data *lod;
74
75         __swab32s(&lum->lmm_magic);
76         __swab32s(&lum->lmm_pattern);
77         __swab32s(&lum->lmm_stripe_size);
78         __swab16s(&lum->lmm_stripe_count);
79         __swab16s(&lum->lmm_stripe_offset);
80
81         if (lum->lmm_magic != LOV_MAGIC_V1)
82                 lod = lumv3->lmm_objects;
83         else
84                 lod = lum->lmm_objects;
85
86         for (i = 0; i < object_count; i++)
87                 __swab32s(&lod[i].l_ost_idx);
88 }
89
90 /**
91  * Allocate storage for a llapi_layout with \a num_stripes stripes.
92  *
93  * \param[in] num_stripes       number of stripes in new layout
94  *
95  * \retval      valid pointer if allocation succeeds
96  * \retval      NULL if allocation fails
97  */
98 static struct llapi_layout *__llapi_layout_alloc(unsigned int num_stripes)
99 {
100         struct llapi_layout *layout = NULL;
101         size_t size = sizeof(*layout) +
102                 (num_stripes * sizeof(layout->llot_objects[0]));
103
104         if (num_stripes > LOV_MAX_STRIPE_COUNT)
105                 errno = EINVAL;
106         else
107                 layout = calloc(1, size);
108
109         return layout;
110 }
111
112 /**
113  * Copy the data from a lov_user_md to a newly allocated llapi_layout.
114  *
115  * The caller is responsible for freeing the returned pointer.
116  *
117  * \param[in] lum       LOV user metadata structure to copy data from
118  *
119  * \retval              valid llapi_layout pointer on success
120  * \retval              NULL if memory allocation fails
121  */
122 static struct llapi_layout *
123 llapi_layout_from_lum(const struct lov_user_md *lum, size_t object_count)
124 {
125         struct llapi_layout *layout;
126         size_t objects_sz;
127
128         objects_sz = object_count * sizeof(lum->lmm_objects[0]);
129
130         layout = __llapi_layout_alloc(object_count);
131         if (layout == NULL)
132                 return NULL;
133
134         layout->llot_magic = LLAPI_LAYOUT_MAGIC;
135
136         if (lum->lmm_pattern == LOV_PATTERN_RAID0)
137                 layout->llot_pattern = LLAPI_LAYOUT_RAID0;
138         else
139                 /* Lustre only supports RAID0 for now. */
140                 layout->llot_pattern = lum->lmm_pattern;
141
142         if (lum->lmm_stripe_size == 0)
143                 layout->llot_stripe_size = LLAPI_LAYOUT_DEFAULT;
144         else
145                 layout->llot_stripe_size = lum->lmm_stripe_size;
146
147         if (lum->lmm_stripe_count == (typeof(lum->lmm_stripe_count))-1)
148                 layout->llot_stripe_count = LLAPI_LAYOUT_WIDE;
149         else if (lum->lmm_stripe_count == 0)
150                 layout->llot_stripe_count = LLAPI_LAYOUT_DEFAULT;
151         else
152                 layout->llot_stripe_count = lum->lmm_stripe_count;
153
154         /* Don't copy lmm_stripe_offset: it is always zero
155          * when reading attributes. */
156
157         if (lum->lmm_magic != LOV_USER_MAGIC_V1) {
158                 const struct lov_user_md_v3 *lumv3;
159                 lumv3 = (struct lov_user_md_v3 *)lum;
160                 snprintf(layout->llot_pool_name, sizeof(layout->llot_pool_name),
161                          "%s", lumv3->lmm_pool_name);
162                 memcpy(layout->llot_objects, lumv3->lmm_objects, objects_sz);
163         } else {
164                 const struct lov_user_md_v1 *lumv1;
165                 lumv1 = (struct lov_user_md_v1 *)lum;
166                 memcpy(layout->llot_objects, lumv1->lmm_objects, objects_sz);
167         }
168         if (object_count > 0)
169                 layout->llot_objects_are_valid = true;
170
171         return layout;
172 }
173
174 /**
175  * Copy the data from a llapi_layout to a newly allocated lov_user_md.
176  *
177  * The caller is responsible for freeing the returned pointer.
178  *
179  * The current version of this API doesn't support specifying the OST
180  * index of arbitrary stripes, only stripe 0 via lmm_stripe_offset.
181  * There is therefore no need to copy the lmm_objects array.
182  *
183  * \param[in] layout    the layout to copy from
184  *
185  * \retval      valid lov_user_md pointer on success
186  * \retval      NULL if memory allocation fails
187  */
188 static struct lov_user_md *
189 llapi_layout_to_lum(const struct llapi_layout *layout)
190 {
191         struct lov_user_md *lum;
192         size_t lum_size;
193         uint32_t magic = LOV_USER_MAGIC_V1;
194
195         if (strlen(layout->llot_pool_name) != 0)
196                 magic = LOV_USER_MAGIC_V3;
197
198         /* The lum->lmm_objects array won't be
199          * sent to the kernel when we write the lum, so
200          * we don't allocate storage for it.
201          */
202         lum_size = lov_user_md_size(0, magic);
203         lum = malloc(lum_size);
204         if (lum == NULL)
205                 return NULL;
206
207         lum->lmm_magic = magic;
208
209         if (layout->llot_pattern == LLAPI_LAYOUT_DEFAULT)
210                 lum->lmm_pattern = 0;
211         else if (layout->llot_pattern == LLAPI_LAYOUT_RAID0)
212                 lum->lmm_pattern = 1;
213         else
214                 lum->lmm_pattern = layout->llot_pattern;
215
216         if (layout->llot_stripe_size == LLAPI_LAYOUT_DEFAULT)
217                 lum->lmm_stripe_size = 0;
218         else
219                 lum->lmm_stripe_size = layout->llot_stripe_size;
220
221         if (layout->llot_stripe_count == LLAPI_LAYOUT_DEFAULT)
222                 lum->lmm_stripe_count = 0;
223         else if (layout->llot_stripe_count == LLAPI_LAYOUT_WIDE)
224                 lum->lmm_stripe_count = -1;
225         else
226                 lum->lmm_stripe_count = layout->llot_stripe_count;
227
228         if (layout->llot_stripe_offset == LLAPI_LAYOUT_DEFAULT)
229                 lum->lmm_stripe_offset = -1;
230         else
231                 lum->lmm_stripe_offset = layout->llot_stripe_offset;
232
233         if (lum->lmm_magic != LOV_USER_MAGIC_V1) {
234                 struct lov_user_md_v3 *lumv3 = (struct lov_user_md_v3 *)lum;
235
236                 strncpy(lumv3->lmm_pool_name, layout->llot_pool_name,
237                         sizeof(lumv3->lmm_pool_name));
238         }
239
240         return lum;
241 }
242
243 /**
244  * Get the parent directory of a path.
245  *
246  * \param[in] path      path to get parent of
247  * \param[out] buf      buffer in which to store parent path
248  * \param[in] size      size in bytes of buffer \a buf
249  */
250 static void get_parent_dir(const char *path, char *buf, size_t size)
251 {
252         char *p;
253
254         strncpy(buf, path, size);
255         p = strrchr(buf, '/');
256
257         if (p != NULL)
258                 *p = '\0';
259         else if (size >= 2)
260                 strncpy(buf, ".", 2);
261 }
262
263 /**
264  * Substitute unspecified attribute values in \a dest with
265  * values from \a src.
266  *
267  * \param[in] src       layout to inherit values from
268  * \param[in] dest      layout to receive inherited values
269  */
270 static void inherit_layout_attributes(const struct llapi_layout *src,
271                                         struct llapi_layout *dest)
272 {
273         if (dest->llot_pattern == LLAPI_LAYOUT_DEFAULT)
274                 dest->llot_pattern = src->llot_pattern;
275
276         if (dest->llot_stripe_size == LLAPI_LAYOUT_DEFAULT)
277                 dest->llot_stripe_size = src->llot_stripe_size;
278
279         if (dest->llot_stripe_count == LLAPI_LAYOUT_DEFAULT)
280                 dest->llot_stripe_count = src->llot_stripe_count;
281 }
282
283 /**
284  * Test if all attributes of \a layout are specified.
285  *
286  * \param[in] layout    the layout to check
287  *
288  * \retval true         all attributes are specified
289  * \retval false        at least one attribute is unspecified
290  */
291 static bool is_fully_specified(const struct llapi_layout *layout)
292 {
293         return  layout->llot_pattern != LLAPI_LAYOUT_DEFAULT &&
294                 layout->llot_stripe_size != LLAPI_LAYOUT_DEFAULT &&
295                 layout->llot_stripe_count != LLAPI_LAYOUT_DEFAULT;
296 }
297
298 /**
299  * Allocate and initialize a new layout.
300  *
301  * \retval      valid llapi_layout pointer on success
302  * \retval      NULL if memory allocation fails
303  */
304 struct llapi_layout *llapi_layout_alloc(void)
305 {
306         struct llapi_layout *layout;
307
308         layout = __llapi_layout_alloc(0);
309         if (layout == NULL)
310                 return layout;
311
312         /* Set defaults. */
313         layout->llot_magic = LLAPI_LAYOUT_MAGIC;
314         layout->llot_pattern = LLAPI_LAYOUT_DEFAULT;
315         layout->llot_stripe_size = LLAPI_LAYOUT_DEFAULT;
316         layout->llot_stripe_count = LLAPI_LAYOUT_DEFAULT;
317         layout->llot_stripe_offset = LLAPI_LAYOUT_DEFAULT;
318         layout->llot_objects_are_valid = false;
319         layout->llot_pool_name[0] = '\0';
320
321         return layout;
322 }
323
324 /**
325  * Check if the given \a lum_size is large enough to hold the required
326  * fields in \a lum.
327  *
328  * \param[in] lum       the struct lov_user_md to check
329  * \param[in] lum_size  the number of bytes in \a lum
330  *
331  * \retval true         the \a lum_size is too small
332  * \retval false        the \a lum_size is large enough
333  */
334 static bool llapi_layout_lum_truncated(struct lov_user_md *lum, size_t lum_size)
335 {
336         uint32_t magic;
337
338         if (lum_size < lov_user_md_size(0, LOV_MAGIC_V1))
339                 return false;
340
341         if (lum->lmm_magic == __swab32(LOV_MAGIC_V1) ||
342             lum->lmm_magic == __swab32(LOV_MAGIC_V3))
343                 magic = __swab32(lum->lmm_magic);
344         else
345                 magic = lum->lmm_magic;
346
347         return lum_size < lov_user_md_size(0, magic);
348 }
349
350 /**
351  * Compute the number of elements in the lmm_objects array of \a lum
352  * with size \a lum_size.
353  *
354  * \param[in] lum       the struct lov_user_md to check
355  * \param[in] lum_size  the number of bytes in \a lum
356  *
357  * \retval              number of elements in array lum->lmm_objects
358  */
359 static int llapi_layout_objects_in_lum(struct lov_user_md *lum, size_t lum_size)
360 {
361         uint32_t magic;
362         size_t base_size;
363
364         if (lum_size < lov_user_md_size(0, LOV_MAGIC_V1))
365                 return 0;
366
367         if (lum->lmm_magic == __swab32(LOV_MAGIC_V1) ||
368             lum->lmm_magic == __swab32(LOV_MAGIC_V3))
369                 magic = __swab32(lum->lmm_magic);
370         else
371                 magic = lum->lmm_magic;
372
373         base_size = lov_user_md_size(0, magic);
374
375         if (lum_size <= base_size)
376                 return 0;
377         else
378                 return (lum_size - base_size) / sizeof(lum->lmm_objects[0]);
379 }
380
381 /**
382  * Get the striping layout for the file referenced by file descriptor \a fd.
383  *
384  * If the filesystem does not support the "lustre." xattr namespace, the
385  * file must be on a non-Lustre filesystem, so set errno to ENOTTY per
386  * convention.  If the file has no "lustre.lov" data, the file will
387  * inherit default values, so return a default layout.
388  *
389  * If the kernel gives us back less than the expected amount of data,
390  * we fail with errno set to EINTR.
391  *
392  * \param[in] fd        open file descriptor
393  * \param[in] flags     open file descriptor
394  *
395  * \retval      valid llapi_layout pointer on success
396  * \retval      NULL if an error occurs
397  */
398 struct llapi_layout *llapi_layout_get_by_fd(int fd, uint32_t flags)
399 {
400         size_t lum_len;
401         struct lov_user_md *lum;
402         struct llapi_layout *layout = NULL;
403         ssize_t bytes_read;
404         int object_count;
405         int lum_stripe_count;
406         struct stat st;
407         bool need_swab;
408
409         lum_len = XATTR_SIZE_MAX;
410         lum = malloc(lum_len);
411         if (lum == NULL)
412                 return NULL;
413
414         bytes_read = fgetxattr(fd, XATTR_LUSTRE_LOV, lum, lum_len);
415         if (bytes_read < 0) {
416                 if (errno == EOPNOTSUPP)
417                         errno = ENOTTY;
418                 else if (errno == ENODATA)
419                         layout = llapi_layout_alloc();
420                 goto out;
421         }
422
423         /* Return an error if we got back a partial layout. */
424         if (llapi_layout_lum_truncated(lum, bytes_read)) {
425                 errno = EINTR;
426                 goto out;
427         }
428
429         object_count = llapi_layout_objects_in_lum(lum, bytes_read);
430
431         need_swab = lum->lmm_magic == __swab32(LOV_MAGIC_V1) ||
432                     lum->lmm_magic == __swab32(LOV_MAGIC_V3);
433
434         if (need_swab)
435                 lum_stripe_count = __swab16(lum->lmm_stripe_count);
436         else
437                 lum_stripe_count = lum->lmm_stripe_count;
438
439         /* Directories may have a positive non-zero lum->lmm_stripe_count
440          * yet have an empty lum->lmm_objects array. For non-directories the
441          * amount of data returned from the kernel must be consistent
442          * with the stripe count. */
443         if (fstat(fd, &st) < 0)
444                 goto out;
445
446         if (!S_ISDIR(st.st_mode) && object_count != lum_stripe_count) {
447                 errno = EINTR;
448                 goto out;
449         }
450
451         if (need_swab)
452                 llapi_layout_swab_lov_user_md(lum, object_count);
453
454         layout = llapi_layout_from_lum(lum, object_count);
455
456 out:
457         free(lum);
458         return layout;
459 }
460
461 /**
462  * Get the expected striping layout for a file at \a path.
463  *
464  * Substitute expected inherited attribute values for unspecified
465  * attributes.  Unspecified attributes may belong to directories and
466  * never-written-to files, and indicate that default values will be
467  * assigned when files are created or first written to.  A default value
468  * is inherited from the parent directory if the attribute is specified
469  * there, otherwise it is inherited from the filesystem root.
470  * Unspecified attributes normally have the value LLAPI_LAYOUT_DEFAULT.
471  *
472  * The complete \a path need not refer to an existing file or directory,
473  * but some leading portion of it must reside within a lustre filesystem.
474  * A use case for this interface would be to obtain the literal striping
475  * values that would be assigned to a new file in a given directory.
476  *
477  * \param[in] path      path for which to get the expected layout
478  *
479  * \retval      valid llapi_layout pointer on success
480  * \retval      NULL if an error occurs
481  */
482 static struct llapi_layout *llapi_layout_expected(const char *path)
483 {
484         struct llapi_layout     *path_layout = NULL;
485         struct llapi_layout     *donor_layout;
486         char                    donor_path[PATH_MAX];
487         struct stat st;
488         int fd;
489         int rc;
490
491         fd = open(path, O_RDONLY);
492         if (fd < 0 && errno != ENOENT)
493                 return NULL;
494
495         if (fd >= 0) {
496                 int tmp;
497
498                 path_layout = llapi_layout_get_by_fd(fd, 0);
499                 tmp = errno;
500                 close(fd);
501                 errno = tmp;
502         }
503
504         if (path_layout == NULL) {
505                 if (errno != ENODATA && errno != ENOENT)
506                         return NULL;
507
508                 path_layout = llapi_layout_alloc();
509                 if (path_layout == NULL)
510                         return NULL;
511         }
512
513         if (is_fully_specified(path_layout))
514                 return path_layout;
515
516         rc = stat(path, &st);
517         if (rc < 0 && errno != ENOENT) {
518                 llapi_layout_free(path_layout);
519                 return NULL;
520         }
521
522         /* If path is a not a directory or doesn't exist, inherit unspecified
523          * attributes from parent directory. */
524         if ((rc == 0 && !S_ISDIR(st.st_mode)) ||
525             (rc < 0 && errno == ENOENT)) {
526                 get_parent_dir(path, donor_path, sizeof(donor_path));
527                 donor_layout = llapi_layout_get_by_path(donor_path, 0);
528                 if (donor_layout != NULL) {
529                         inherit_layout_attributes(donor_layout, path_layout);
530                         llapi_layout_free(donor_layout);
531                         if (is_fully_specified(path_layout))
532                                 return path_layout;
533                 }
534         }
535
536         /* Inherit remaining unspecified attributes from the filesystem root. */
537         rc = llapi_search_mounts(path, 0, donor_path, NULL);
538         if (rc < 0) {
539                 llapi_layout_free(path_layout);
540                 return NULL;
541         }
542         donor_layout = llapi_layout_get_by_path(donor_path, 0);
543         if (donor_layout == NULL) {
544                 llapi_layout_free(path_layout);
545                 return NULL;
546         }
547
548         inherit_layout_attributes(donor_layout, path_layout);
549         llapi_layout_free(donor_layout);
550
551         return path_layout;
552 }
553
554 /**
555  * Get the striping layout for the file at \a path.
556  *
557  * If \a flags contains LAYOUT_GET_EXPECTED, substitute
558  * expected inherited attribute values for unspecified attributes. See
559  * llapi_layout_expected().
560  *
561  * \param[in] path      path for which to get the layout
562  * \param[in] flags     flags to control how layout is retrieved
563  *
564  * \retval      valid llapi_layout pointer on success
565  * \retval      NULL if an error occurs
566  */
567 struct llapi_layout *llapi_layout_get_by_path(const char *path, uint32_t flags)
568 {
569         struct llapi_layout *layout = NULL;
570         int fd;
571         int tmp;
572
573         if (flags & LAYOUT_GET_EXPECTED)
574                 return llapi_layout_expected(path);
575
576         fd = open(path, O_RDONLY);
577         if (fd < 0)
578                 return layout;
579
580         layout = llapi_layout_get_by_fd(fd, flags);
581         tmp = errno;
582         close(fd);
583         errno = tmp;
584
585         return layout;
586 }
587
588 /**
589  * Get the layout for the file with FID \a fidstr in filesystem \a lustre_dir.
590  *
591  * \param[in] lustre_dir        path within Lustre filesystem containing \a fid
592  * \param[in] fid               Lustre identifier of file to get layout for
593  *
594  * \retval      valid llapi_layout pointer on success
595  * \retval      NULL if an error occurs
596  */
597 struct llapi_layout *llapi_layout_get_by_fid(const char *lustre_dir,
598                                              const lustre_fid *fid,
599                                              uint32_t flags)
600 {
601         int fd;
602         int tmp;
603         int saved_msg_level = llapi_msg_get_level();
604         struct llapi_layout *layout = NULL;
605
606         /* Prevent llapi internal routines from writing to console
607          * while executing this function, then restore previous message
608          * level. */
609         llapi_msg_set_level(LLAPI_MSG_OFF);
610         fd = llapi_open_by_fid(lustre_dir, fid, O_RDONLY);
611         llapi_msg_set_level(saved_msg_level);
612
613         if (fd < 0)
614                 return NULL;
615
616         layout = llapi_layout_get_by_fd(fd, flags);
617         tmp = errno;
618         close(fd);
619         errno = tmp;
620
621         return layout;
622 }
623
624 /** * Free memory allocated for \a layout. */
625 void llapi_layout_free(struct llapi_layout *layout)
626 {
627         free(layout);
628 }
629
630 /**
631  * Get the stripe count of \a layout.
632  *
633  * \param[in] layout    layout to get stripe count from
634  * \param[out] count    integer to store stripe count in
635  *
636  * \retval      0 on success
637  * \retval      -1 if arguments are invalid
638  */
639 int llapi_layout_stripe_count_get(const struct llapi_layout *layout,
640                                   uint64_t *count)
641 {
642         if (layout == NULL || count == NULL ||
643             layout->llot_magic != LLAPI_LAYOUT_MAGIC) {
644                 errno = EINVAL;
645                 return -1;
646         }
647         *count = layout->llot_stripe_count;
648         return 0;
649 }
650
651 /*
652  * The llapi_layout API functions have these extra validity checks since
653  * they use intuitively named macros to denote special behavior, whereas
654  * the old API uses 0 and -1.
655  */
656
657 static bool llapi_layout_stripe_count_is_valid(int64_t stripe_count)
658 {
659         return stripe_count == LLAPI_LAYOUT_DEFAULT ||
660                 stripe_count == LLAPI_LAYOUT_WIDE ||
661                 (stripe_count != 0 && stripe_count != -1 &&
662                  llapi_stripe_count_is_valid(stripe_count));
663 }
664
665 static bool llapi_layout_stripe_size_is_valid(uint64_t stripe_size)
666 {
667         return stripe_size == LLAPI_LAYOUT_DEFAULT ||
668                 (stripe_size != 0 &&
669                  llapi_stripe_size_is_aligned(stripe_size) &&
670                  !llapi_stripe_size_is_too_big(stripe_size));
671 }
672
673 static bool llapi_layout_stripe_index_is_valid(int64_t stripe_index)
674 {
675         return stripe_index == LLAPI_LAYOUT_DEFAULT ||
676                 (stripe_index >= 0 &&
677                 llapi_stripe_index_is_valid(stripe_index));
678 }
679
680 /**
681  * Set the stripe count of \a layout.
682  *
683  * \param[in] layout    layout to set stripe count in
684  * \param[in] count     value to be set
685  *
686  * \retval      0 on success
687  * \retval      -1 if arguments are invalid
688  */
689 int llapi_layout_stripe_count_set(struct llapi_layout *layout,
690                                   uint64_t count)
691 {
692         if (layout == NULL || layout->llot_magic != LLAPI_LAYOUT_MAGIC ||
693             !llapi_layout_stripe_count_is_valid(count)) {
694                 errno = EINVAL;
695                 return -1;
696         }
697
698         layout->llot_stripe_count = count;
699
700         return 0;
701 }
702
703 /**
704  * Get the stripe size of \a layout.
705  *
706  * \param[in] layout    layout to get stripe size from
707  * \param[out] size     integer to store stripe size in
708  *
709  * \retval      0 on success
710  * \retval      -1 if arguments are invalid
711  */
712 int llapi_layout_stripe_size_get(const struct llapi_layout *layout,
713                                  uint64_t *size)
714 {
715         if (layout == NULL || size == NULL ||
716             layout->llot_magic != LLAPI_LAYOUT_MAGIC) {
717                 errno = EINVAL;
718                 return -1;
719         }
720
721         *size = layout->llot_stripe_size;
722
723         return 0;
724 }
725
726 /**
727  * Set the stripe size of \a layout.
728  *
729  * \param[in] layout    layout to set stripe size in
730  * \param[in] size      value to be set
731  *
732  * \retval      0 on success
733  * \retval      -1 if arguments are invalid
734  */
735 int llapi_layout_stripe_size_set(struct llapi_layout *layout,
736                                  uint64_t size)
737 {
738         if (layout == NULL || layout->llot_magic != LLAPI_LAYOUT_MAGIC ||
739             !llapi_layout_stripe_size_is_valid(size)) {
740                 errno = EINVAL;
741                 return -1;
742         }
743
744         layout->llot_stripe_size = size;
745
746         return 0;
747 }
748
749 /**
750  * Get the RAID pattern of \a layout.
751  *
752  * \param[in] layout    layout to get pattern from
753  * \param[out] pattern  integer to store pattern in
754  *
755  * \retval      0 on success
756  * \retval      -1 if arguments are invalid
757  */
758 int llapi_layout_pattern_get(const struct llapi_layout *layout,
759                              uint64_t *pattern)
760 {
761         if (layout == NULL || pattern == NULL ||
762             layout->llot_magic != LLAPI_LAYOUT_MAGIC) {
763                 errno = EINVAL;
764                 return -1;
765         }
766
767         *pattern = layout->llot_pattern;
768
769         return 0;
770 }
771
772 /**
773  * Set the RAID pattern of \a layout.
774  *
775  * \param[in] layout    layout to set pattern in
776  * \param[in] pattern   value to be set
777  *
778  * \retval      0 on success
779  * \retval      -1 if arguments are invalid or RAID pattern
780  *              is unsupported
781  */
782 int llapi_layout_pattern_set(struct llapi_layout *layout, uint64_t pattern)
783 {
784         if (layout == NULL || layout->llot_magic != LLAPI_LAYOUT_MAGIC) {
785                 errno = EINVAL;
786                 return -1;
787         }
788
789         if (pattern != LLAPI_LAYOUT_DEFAULT ||
790             pattern != LLAPI_LAYOUT_RAID0) {
791                 errno = EOPNOTSUPP;
792                 return -1;
793         }
794
795         layout->llot_pattern = pattern;
796
797         return 0;
798 }
799
800 /**
801  * Set the OST index of stripe number \a stripe_number to \a ost_index.
802  *
803  * The index may only be set for stripe number 0 for now.
804  *
805  * \param[in] layout            layout to set OST index in
806  * \param[in] stripe_number     stripe number to set index for
807  * \param[in] ost_index         the index to set
808  *
809  * \retval      0 on success
810  * \retval      -1 if arguments are invalid or an unsupported stripe number
811  *              was specified
812  */
813 int llapi_layout_ost_index_set(struct llapi_layout *layout, int stripe_number,
814                                uint64_t ost_index)
815 {
816         if (layout == NULL || layout->llot_magic != LLAPI_LAYOUT_MAGIC ||
817             !llapi_layout_stripe_index_is_valid(ost_index)) {
818                 errno = EINVAL;
819                 return -1;
820         }
821
822         if (stripe_number != 0) {
823                 errno = EOPNOTSUPP;
824                 return -1;
825         }
826
827         layout->llot_stripe_offset = ost_index;
828
829         return 0;
830 }
831
832 /**
833  * Get the OST index associated with stripe \a stripe_number.
834  *
835  * Stripes are indexed starting from zero.
836  *
837  * \param[in] layout            layout to get index from
838  * \param[in] stripe_number     stripe number to get index for
839  * \param[out] index            integer to store index in
840  *
841  * \retval      0 on success
842  * \retval      -1 if arguments are invalid
843  */
844 int llapi_layout_ost_index_get(const struct llapi_layout *layout,
845                                uint64_t stripe_number, uint64_t *index)
846 {
847         if (layout == NULL || layout->llot_magic != LLAPI_LAYOUT_MAGIC ||
848             stripe_number >= layout->llot_stripe_count ||
849             index == NULL  || layout->llot_objects_are_valid == 0) {
850                 errno = EINVAL;
851                 return -1;
852         }
853
854         if (layout->llot_objects[stripe_number].l_ost_idx == -1)
855                 *index = LLAPI_LAYOUT_DEFAULT;
856         else
857                 *index = layout->llot_objects[stripe_number].l_ost_idx;
858
859         return 0;
860 }
861
862 /**
863  *
864  * Get the pool name of layout \a layout.
865  *
866  * \param[in] layout    layout to get pool name from
867  * \param[out] dest     buffer to store pool name in
868  * \param[in] n         size in bytes of buffer \a dest
869  *
870  * \retval      0 on success
871  * \retval      -1 if arguments are invalid
872  */
873 int llapi_layout_pool_name_get(const struct llapi_layout *layout, char *dest,
874                                size_t n)
875 {
876         if (layout == NULL || layout->llot_magic != LLAPI_LAYOUT_MAGIC ||
877             dest == NULL) {
878                 errno = EINVAL;
879                 return -1;
880         }
881
882         strncpy(dest, layout->llot_pool_name, n);
883
884         return 0;
885 }
886
887 /**
888  * Set the name of the pool of layout \a layout.
889  *
890  * \param[in] layout    layout to set pool name in
891  * \param[in] pool_name pool name to set
892  *
893  * \retval      0 on success
894  * \retval      -1 if arguments are invalid or pool name is too long
895  */
896 int llapi_layout_pool_name_set(struct llapi_layout *layout,
897                                const char *pool_name)
898 {
899         char *ptr;
900
901         if (layout == NULL || layout->llot_magic != LLAPI_LAYOUT_MAGIC ||
902             pool_name == NULL) {
903                 errno = EINVAL;
904                 return -1;
905         }
906
907         /* Strip off any 'fsname.' portion. */
908         ptr = strchr(pool_name, '.');
909         if (ptr != NULL)
910                 pool_name = ptr + 1;
911
912         if (strlen(pool_name) > LOV_MAXPOOLNAME) {
913                 errno = EINVAL;
914                 return -1;
915         }
916
917         strncpy(layout->llot_pool_name, pool_name,
918                 sizeof(layout->llot_pool_name));
919
920         return 0;
921 }
922
923 /**
924  * Open and possibly create a file with a given \a layout.
925  *
926  * If \a layout is NULL this function acts as a simple wrapper for
927  * open().  By convention, ENOTTY is returned in errno if \a path
928  * refers to a non-Lustre file.
929  *
930  * \param[in] path              name of the file to open
931  * \param[in] open_flags        open() flags
932  * \param[in] mode              permissions to create new file with
933  * \param[in] layout            layout to create new file with
934  *
935  * \retval              non-negative file descriptor on successful open
936  * \retval              -1 if an error occurred
937  */
938 int llapi_layout_file_open(const char *path, int open_flags, mode_t mode,
939                            const struct llapi_layout *layout)
940 {
941         int fd;
942         int rc;
943         int tmp;
944         struct lov_user_md *lum;
945         size_t lum_size;
946
947         if (path == NULL ||
948             (layout != NULL && layout->llot_magic != LLAPI_LAYOUT_MAGIC)) {
949                 errno = EINVAL;
950                 return -1;
951         }
952
953         /* Object creation must be postponed until after layout attributes
954          * have been applied. */
955         if (layout != NULL && (open_flags & O_CREAT))
956                 open_flags |= O_LOV_DELAY_CREATE;
957
958         fd = open(path, open_flags, mode);
959
960         if (layout == NULL || fd < 0)
961                 return fd;
962
963         lum = llapi_layout_to_lum(layout);
964
965         if (lum == NULL) {
966                 tmp = errno;
967                 close(fd);
968                 errno = tmp;
969                 return -1;
970         }
971
972         lum_size = lov_user_md_size(0, lum->lmm_magic);
973
974         rc = fsetxattr(fd, XATTR_LUSTRE_LOV, lum, lum_size, 0);
975         if (rc < 0) {
976                 tmp = errno;
977                 close(fd);
978                 errno = tmp;
979                 fd = -1;
980         }
981
982         free(lum);
983         errno = errno == EOPNOTSUPP ? ENOTTY : errno;
984
985         return fd;
986 }
987
988 /**
989  * Create a file with a given \a layout.
990  *
991  * Force O_CREAT and O_EXCL flags on so caller is assured that file was
992  * created with the given \a layout on successful function return.
993  *
994  * \param[in] path              name of the file to open
995  * \param[in] open_flags        open() flags
996  * \param[in] mode              permissions to create new file with
997  * \param[in] layout            layout to create new file with
998  *
999  * \retval              non-negative file descriptor on successful open
1000  * \retval              -1 if an error occurred
1001  */
1002 int llapi_layout_file_create(const char *path, int open_flags, int mode,
1003                              const struct llapi_layout *layout)
1004 {
1005         return llapi_layout_file_open(path, open_flags|O_CREAT|O_EXCL, mode,
1006                                       layout);
1007 }