Whamcloud - gitweb
eff35e267c2acb097bb02a8d648f7a2851d7e2d7
[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         struct stat st;
406
407         lum_len = XATTR_SIZE_MAX;
408         lum = malloc(lum_len);
409         if (lum == NULL)
410                 return NULL;
411
412         bytes_read = fgetxattr(fd, XATTR_LUSTRE_LOV, lum, lum_len);
413         if (bytes_read < 0) {
414                 if (errno == EOPNOTSUPP)
415                         errno = ENOTTY;
416                 else if (errno == ENODATA)
417                         layout = llapi_layout_alloc();
418                 goto out;
419         }
420
421         /* Return an error if we got back a partial layout. */
422         if (llapi_layout_lum_truncated(lum, bytes_read)) {
423                 errno = EINTR;
424                 goto out;
425         }
426
427         object_count = llapi_layout_objects_in_lum(lum, bytes_read);
428
429         /* Directories may have a positive non-zero lum->lmm_stripe_count
430          * yet have an empty lum->lmm_objects array. For non-directories the
431          * amount of data returned from the kernel must be consistent
432          * with the stripe count. */
433         if (fstat(fd, &st) < 0)
434                 goto out;
435
436         if (!S_ISDIR(st.st_mode) && object_count != lum->lmm_stripe_count) {
437                 errno = EINTR;
438                 goto out;
439         }
440
441         if (lum->lmm_magic == __swab32(LOV_MAGIC_V1) ||
442             lum->lmm_magic == __swab32(LOV_MAGIC_V3))
443                 llapi_layout_swab_lov_user_md(lum, object_count);
444
445         layout = llapi_layout_from_lum(lum, object_count);
446
447 out:
448         free(lum);
449         return layout;
450 }
451
452 /**
453  * Get the expected striping layout for a file at \a path.
454  *
455  * Substitute expected inherited attribute values for unspecified
456  * attributes.  Unspecified attributes may belong to directories and
457  * never-written-to files, and indicate that default values will be
458  * assigned when files are created or first written to.  A default value
459  * is inherited from the parent directory if the attribute is specified
460  * there, otherwise it is inherited from the filesystem root.
461  * Unspecified attributes normally have the value LLAPI_LAYOUT_DEFAULT.
462  *
463  * The complete \a path need not refer to an existing file or directory,
464  * but some leading portion of it must reside within a lustre filesystem.
465  * A use case for this interface would be to obtain the literal striping
466  * values that would be assigned to a new file in a given directory.
467  *
468  * \param[in] path      path for which to get the expected layout
469  *
470  * \retval      valid llapi_layout pointer on success
471  * \retval      NULL if an error occurs
472  */
473 static struct llapi_layout *llapi_layout_expected(const char *path)
474 {
475         struct llapi_layout     *path_layout = NULL;
476         struct llapi_layout     *donor_layout;
477         char                    donor_path[PATH_MAX];
478         struct stat st;
479         int fd;
480         int rc;
481
482         fd = open(path, O_RDONLY);
483         if (fd < 0 && errno != ENOENT)
484                 return NULL;
485
486         if (fd >= 0) {
487                 int tmp;
488
489                 path_layout = llapi_layout_get_by_fd(fd, 0);
490                 tmp = errno;
491                 close(fd);
492                 errno = tmp;
493         }
494
495         if (path_layout == NULL) {
496                 if (errno != ENODATA && errno != ENOENT)
497                         return NULL;
498
499                 path_layout = llapi_layout_alloc();
500                 if (path_layout == NULL)
501                         return NULL;
502         }
503
504         if (is_fully_specified(path_layout))
505                 return path_layout;
506
507         rc = stat(path, &st);
508         if (rc < 0 && errno != ENOENT) {
509                 llapi_layout_free(path_layout);
510                 return NULL;
511         }
512
513         /* If path is a not a directory or doesn't exist, inherit unspecified
514          * attributes from parent directory. */
515         if ((rc == 0 && !S_ISDIR(st.st_mode)) ||
516             (rc < 0 && errno == ENOENT)) {
517                 get_parent_dir(path, donor_path, sizeof(donor_path));
518                 donor_layout = llapi_layout_get_by_path(donor_path, 0);
519                 if (donor_layout != NULL) {
520                         inherit_layout_attributes(donor_layout, path_layout);
521                         llapi_layout_free(donor_layout);
522                         if (is_fully_specified(path_layout))
523                                 return path_layout;
524                 }
525         }
526
527         /* Inherit remaining unspecified attributes from the filesystem root. */
528         rc = llapi_search_mounts(path, 0, donor_path, NULL);
529         if (rc < 0) {
530                 llapi_layout_free(path_layout);
531                 return NULL;
532         }
533         donor_layout = llapi_layout_get_by_path(donor_path, 0);
534         if (donor_layout == NULL) {
535                 llapi_layout_free(path_layout);
536                 return NULL;
537         }
538
539         inherit_layout_attributes(donor_layout, path_layout);
540         llapi_layout_free(donor_layout);
541
542         return path_layout;
543 }
544
545 /**
546  * Get the striping layout for the file at \a path.
547  *
548  * If \a flags contains LAYOUT_GET_EXPECTED, substitute
549  * expected inherited attribute values for unspecified attributes. See
550  * llapi_layout_expected().
551  *
552  * \param[in] path      path for which to get the layout
553  * \param[in] flags     flags to control how layout is retrieved
554  *
555  * \retval      valid llapi_layout pointer on success
556  * \retval      NULL if an error occurs
557  */
558 struct llapi_layout *llapi_layout_get_by_path(const char *path, uint32_t flags)
559 {
560         struct llapi_layout *layout = NULL;
561         int fd;
562         int tmp;
563
564         if (flags & LAYOUT_GET_EXPECTED)
565                 return llapi_layout_expected(path);
566
567         fd = open(path, O_RDONLY);
568         if (fd < 0)
569                 return layout;
570
571         layout = llapi_layout_get_by_fd(fd, flags);
572         tmp = errno;
573         close(fd);
574         errno = tmp;
575
576         return layout;
577 }
578
579 /**
580  * Get the layout for the file with FID \a fidstr in filesystem \a lustre_dir.
581  *
582  * \param[in] lustre_dir        path within Lustre filesystem containing \a fid
583  * \param[in] fid               Lustre identifier of file to get layout for
584  *
585  * \retval      valid llapi_layout pointer on success
586  * \retval      NULL if an error occurs
587  */
588 struct llapi_layout *llapi_layout_get_by_fid(const char *lustre_dir,
589                                              const lustre_fid *fid,
590                                              uint32_t flags)
591 {
592         int fd;
593         int tmp;
594         int saved_msg_level = llapi_msg_get_level();
595         struct llapi_layout *layout = NULL;
596
597         /* Prevent llapi internal routines from writing to console
598          * while executing this function, then restore previous message
599          * level. */
600         llapi_msg_set_level(LLAPI_MSG_OFF);
601         fd = llapi_open_by_fid(lustre_dir, fid, O_RDONLY);
602         llapi_msg_set_level(saved_msg_level);
603
604         if (fd < 0)
605                 return NULL;
606
607         layout = llapi_layout_get_by_fd(fd, flags);
608         tmp = errno;
609         close(fd);
610         errno = tmp;
611
612         return layout;
613 }
614
615 /** * Free memory allocated for \a layout. */
616 void llapi_layout_free(struct llapi_layout *layout)
617 {
618         free(layout);
619 }
620
621 /**
622  * Get the stripe count of \a layout.
623  *
624  * \param[in] layout    layout to get stripe count from
625  * \param[out] count    integer to store stripe count in
626  *
627  * \retval      0 on success
628  * \retval      -1 if arguments are invalid
629  */
630 int llapi_layout_stripe_count_get(const struct llapi_layout *layout,
631                                   uint64_t *count)
632 {
633         if (layout == NULL || count == NULL ||
634             layout->llot_magic != LLAPI_LAYOUT_MAGIC) {
635                 errno = EINVAL;
636                 return -1;
637         }
638         *count = layout->llot_stripe_count;
639         return 0;
640 }
641
642 /*
643  * The llapi_layout API functions have these extra validity checks since
644  * they use intuitively named macros to denote special behavior, whereas
645  * the old API uses 0 and -1.
646  */
647
648 static bool llapi_layout_stripe_count_is_valid(int64_t stripe_count)
649 {
650         return stripe_count == LLAPI_LAYOUT_DEFAULT ||
651                 stripe_count == LLAPI_LAYOUT_WIDE ||
652                 (stripe_count != 0 && stripe_count != -1 &&
653                  llapi_stripe_count_is_valid(stripe_count));
654 }
655
656 static bool llapi_layout_stripe_size_is_valid(uint64_t stripe_size)
657 {
658         return stripe_size == LLAPI_LAYOUT_DEFAULT ||
659                 (stripe_size != 0 &&
660                  llapi_stripe_size_is_aligned(stripe_size) &&
661                  !llapi_stripe_size_is_too_big(stripe_size));
662 }
663
664 static bool llapi_layout_stripe_index_is_valid(int64_t stripe_index)
665 {
666         return stripe_index == LLAPI_LAYOUT_DEFAULT ||
667                 (stripe_index >= 0 &&
668                 llapi_stripe_index_is_valid(stripe_index));
669 }
670
671 /**
672  * Set the stripe count of \a layout.
673  *
674  * \param[in] layout    layout to set stripe count in
675  * \param[in] count     value to be set
676  *
677  * \retval      0 on success
678  * \retval      -1 if arguments are invalid
679  */
680 int llapi_layout_stripe_count_set(struct llapi_layout *layout,
681                                   uint64_t count)
682 {
683         if (layout == NULL || layout->llot_magic != LLAPI_LAYOUT_MAGIC ||
684             !llapi_layout_stripe_count_is_valid(count)) {
685                 errno = EINVAL;
686                 return -1;
687         }
688
689         layout->llot_stripe_count = count;
690
691         return 0;
692 }
693
694 /**
695  * Get the stripe size of \a layout.
696  *
697  * \param[in] layout    layout to get stripe size from
698  * \param[out] size     integer to store stripe size in
699  *
700  * \retval      0 on success
701  * \retval      -1 if arguments are invalid
702  */
703 int llapi_layout_stripe_size_get(const struct llapi_layout *layout,
704                                  uint64_t *size)
705 {
706         if (layout == NULL || size == NULL ||
707             layout->llot_magic != LLAPI_LAYOUT_MAGIC) {
708                 errno = EINVAL;
709                 return -1;
710         }
711
712         *size = layout->llot_stripe_size;
713
714         return 0;
715 }
716
717 /**
718  * Set the stripe size of \a layout.
719  *
720  * \param[in] layout    layout to set stripe size in
721  * \param[in] size      value to be set
722  *
723  * \retval      0 on success
724  * \retval      -1 if arguments are invalid
725  */
726 int llapi_layout_stripe_size_set(struct llapi_layout *layout,
727                                  uint64_t size)
728 {
729         if (layout == NULL || layout->llot_magic != LLAPI_LAYOUT_MAGIC ||
730             !llapi_layout_stripe_size_is_valid(size)) {
731                 errno = EINVAL;
732                 return -1;
733         }
734
735         layout->llot_stripe_size = size;
736
737         return 0;
738 }
739
740 /**
741  * Get the RAID pattern of \a layout.
742  *
743  * \param[in] layout    layout to get pattern from
744  * \param[out] pattern  integer to store pattern in
745  *
746  * \retval      0 on success
747  * \retval      -1 if arguments are invalid
748  */
749 int llapi_layout_pattern_get(const struct llapi_layout *layout,
750                              uint64_t *pattern)
751 {
752         if (layout == NULL || pattern == NULL ||
753             layout->llot_magic != LLAPI_LAYOUT_MAGIC) {
754                 errno = EINVAL;
755                 return -1;
756         }
757
758         *pattern = layout->llot_pattern;
759
760         return 0;
761 }
762
763 /**
764  * Set the RAID pattern of \a layout.
765  *
766  * \param[in] layout    layout to set pattern in
767  * \param[in] pattern   value to be set
768  *
769  * \retval      0 on success
770  * \retval      -1 if arguments are invalid or RAID pattern
771  *              is unsupported
772  */
773 int llapi_layout_pattern_set(struct llapi_layout *layout, uint64_t pattern)
774 {
775         if (layout == NULL || layout->llot_magic != LLAPI_LAYOUT_MAGIC) {
776                 errno = EINVAL;
777                 return -1;
778         }
779
780         if (pattern != LLAPI_LAYOUT_DEFAULT ||
781             pattern != LLAPI_LAYOUT_RAID0) {
782                 errno = EOPNOTSUPP;
783                 return -1;
784         }
785
786         layout->llot_pattern = pattern;
787
788         return 0;
789 }
790
791 /**
792  * Set the OST index of stripe number \a stripe_number to \a ost_index.
793  *
794  * The index may only be set for stripe number 0 for now.
795  *
796  * \param[in] layout            layout to set OST index in
797  * \param[in] stripe_number     stripe number to set index for
798  * \param[in] ost_index         the index to set
799  *
800  * \retval      0 on success
801  * \retval      -1 if arguments are invalid or an unsupported stripe number
802  *              was specified
803  */
804 int llapi_layout_ost_index_set(struct llapi_layout *layout, int stripe_number,
805                                uint64_t ost_index)
806 {
807         if (layout == NULL || layout->llot_magic != LLAPI_LAYOUT_MAGIC ||
808             !llapi_layout_stripe_index_is_valid(ost_index)) {
809                 errno = EINVAL;
810                 return -1;
811         }
812
813         if (stripe_number != 0) {
814                 errno = EOPNOTSUPP;
815                 return -1;
816         }
817
818         layout->llot_stripe_offset = ost_index;
819
820         return 0;
821 }
822
823 /**
824  * Get the OST index associated with stripe \a stripe_number.
825  *
826  * Stripes are indexed starting from zero.
827  *
828  * \param[in] layout            layout to get index from
829  * \param[in] stripe_number     stripe number to get index for
830  * \param[out] index            integer to store index in
831  *
832  * \retval      0 on success
833  * \retval      -1 if arguments are invalid
834  */
835 int llapi_layout_ost_index_get(const struct llapi_layout *layout,
836                                uint64_t stripe_number, uint64_t *index)
837 {
838         if (layout == NULL || layout->llot_magic != LLAPI_LAYOUT_MAGIC ||
839             stripe_number >= layout->llot_stripe_count ||
840             index == NULL  || layout->llot_objects_are_valid == 0) {
841                 errno = EINVAL;
842                 return -1;
843         }
844
845         if (layout->llot_objects[stripe_number].l_ost_idx == -1)
846                 *index = LLAPI_LAYOUT_DEFAULT;
847         else
848                 *index = layout->llot_objects[stripe_number].l_ost_idx;
849
850         return 0;
851 }
852
853 /**
854  *
855  * Get the pool name of layout \a layout.
856  *
857  * \param[in] layout    layout to get pool name from
858  * \param[out] dest     buffer to store pool name in
859  * \param[in] n         size in bytes of buffer \a dest
860  *
861  * \retval      0 on success
862  * \retval      -1 if arguments are invalid
863  */
864 int llapi_layout_pool_name_get(const struct llapi_layout *layout, char *dest,
865                                size_t n)
866 {
867         if (layout == NULL || layout->llot_magic != LLAPI_LAYOUT_MAGIC ||
868             dest == NULL) {
869                 errno = EINVAL;
870                 return -1;
871         }
872
873         strncpy(dest, layout->llot_pool_name, n);
874
875         return 0;
876 }
877
878 /**
879  * Set the name of the pool of layout \a layout.
880  *
881  * \param[in] layout    layout to set pool name in
882  * \param[in] pool_name pool name to set
883  *
884  * \retval      0 on success
885  * \retval      -1 if arguments are invalid or pool name is too long
886  */
887 int llapi_layout_pool_name_set(struct llapi_layout *layout,
888                                const char *pool_name)
889 {
890         char *ptr;
891
892         if (layout == NULL || layout->llot_magic != LLAPI_LAYOUT_MAGIC ||
893             pool_name == NULL) {
894                 errno = EINVAL;
895                 return -1;
896         }
897
898         /* Strip off any 'fsname.' portion. */
899         ptr = strchr(pool_name, '.');
900         if (ptr != NULL)
901                 pool_name = ptr + 1;
902
903         if (strlen(pool_name) > LOV_MAXPOOLNAME) {
904                 errno = EINVAL;
905                 return -1;
906         }
907
908         strncpy(layout->llot_pool_name, pool_name,
909                 sizeof(layout->llot_pool_name));
910
911         return 0;
912 }
913
914 /**
915  * Open and possibly create a file with a given \a layout.
916  *
917  * If \a layout is NULL this function acts as a simple wrapper for
918  * open().  By convention, ENOTTY is returned in errno if \a path
919  * refers to a non-Lustre file.
920  *
921  * \param[in] path              name of the file to open
922  * \param[in] open_flags        open() flags
923  * \param[in] mode              permissions to create new file with
924  * \param[in] layout            layout to create new file with
925  *
926  * \retval              non-negative file descriptor on successful open
927  * \retval              -1 if an error occurred
928  */
929 int llapi_layout_file_open(const char *path, int open_flags, mode_t mode,
930                            const struct llapi_layout *layout)
931 {
932         int fd;
933         int rc;
934         int tmp;
935         struct lov_user_md *lum;
936         size_t lum_size;
937
938         if (path == NULL ||
939             (layout != NULL && layout->llot_magic != LLAPI_LAYOUT_MAGIC)) {
940                 errno = EINVAL;
941                 return -1;
942         }
943
944         /* Object creation must be postponed until after layout attributes
945          * have been applied. */
946         if (layout != NULL && (open_flags & O_CREAT))
947                 open_flags |= O_LOV_DELAY_CREATE;
948
949         fd = open(path, open_flags, mode);
950
951         if (layout == NULL || fd < 0)
952                 return fd;
953
954         lum = llapi_layout_to_lum(layout);
955
956         if (lum == NULL) {
957                 tmp = errno;
958                 close(fd);
959                 errno = tmp;
960                 return -1;
961         }
962
963         lum_size = lov_user_md_size(0, lum->lmm_magic);
964
965         rc = fsetxattr(fd, XATTR_LUSTRE_LOV, lum, lum_size, 0);
966         if (rc < 0) {
967                 tmp = errno;
968                 close(fd);
969                 errno = tmp;
970                 fd = -1;
971         }
972
973         free(lum);
974         errno = errno == EOPNOTSUPP ? ENOTTY : errno;
975
976         return fd;
977 }
978
979 /**
980  * Create a file with a given \a layout.
981  *
982  * Force O_CREAT and O_EXCL flags on so caller is assured that file was
983  * created with the given \a layout on successful function return.
984  *
985  * \param[in] path              name of the file to open
986  * \param[in] open_flags        open() flags
987  * \param[in] mode              permissions to create new file with
988  * \param[in] layout            layout to create new file with
989  *
990  * \retval              non-negative file descriptor on successful open
991  * \retval              -1 if an error occurred
992  */
993 int llapi_layout_file_create(const char *path, int open_flags, int mode,
994                              const struct llapi_layout *layout)
995 {
996         return llapi_layout_file_open(path, open_flags|O_CREAT|O_EXCL, mode,
997                                       layout);
998 }