From 542e21fcfa5b8a6b82d1a1a51930de7439977727 Mon Sep 17 00:00:00 2001 From: Andreas Dilger Date: Wed, 20 Jul 2016 19:32:01 -0400 Subject: [PATCH] LU-6135 lustreapi: allow specific-OST with llapi_layout Add support to llapi_layout_ost_index_set() for specifying specific OST indices for a newly created files. Using ost_index=LLAPI_LAYOUT_DEFAULT to stripe 0 will reset the specified stripes back to the default. Signed-off-by: Andreas Dilger Signed-off-by: Niu Yawei Change-Id: Ic3aea69527119ddf1cb4f91bac531b6eaa3ebbe5 Reviewed-on: http://review.whamcloud.com/12663 Tested-by: Jenkins Reviewed-by: Frank Zago Reviewed-by: James Simmons Tested-by: Maloo Reviewed-by: Oleg Drokin --- lustre/doc/llapi_layout_ost_index_get.3 | 23 +++- lustre/include/lustre/lustreapi.h | 10 ++ lustre/tests/llapi_layout_test.c | 149 +++++++++++++++++++-- lustre/tests/sanity.sh | 7 +- lustre/utils/liblustreapi_layout.c | 224 ++++++++++++++++++++++++++------ 5 files changed, 355 insertions(+), 58 deletions(-) diff --git a/lustre/doc/llapi_layout_ost_index_get.3 b/lustre/doc/llapi_layout_ost_index_get.3 index d8742d8..1870aa7 100644 --- a/lustre/doc/llapi_layout_ost_index_get.3 +++ b/lustre/doc/llapi_layout_ost_index_get.3 @@ -17,21 +17,25 @@ OST index of a stripe of a Lustre file .B llapi_layout_ost_index_get() stores into .I ost_index -the index number of the Lustre OST associated with stripe number +the index number of the Lustre OST associated with .I stripe_number -in layout +in .IR layout . .PP .B llapi_layout_ost_index_set() -sets the OST index of stripe number +sets the OST index of .I stripe_number -in layout +in .I layout to .IR ost_index . This allows an application to control which OSTs will be used to -allocate storage for a file. Setting the OST index is currently only -supported for stripe 0. +allocate storage for a file. Setting the starting OST index for a file +.RI ( stripe_number =0) +is supported with all versions of Lustre, and other stripes in the file +will be assigned sequentially by the filesystem. Setting the OST indices +other than stripe 0 is only supported with Lustre 2.7 and later, and will +return an error at file creation time for 2.6 and earlier. .PP It is an error to call .B llapi_layout_ost_index_get() @@ -47,7 +51,12 @@ An .I ost_index value of .B LLAPI_LAYOUT_DEFAULT -means that an index will be automatically assigned by the filesystem. +is only valid for +.IR stripe_number =0 +and means that an OST index will be automatically assigned by the +filesystem and will reset previously-set +.I stripe_number +assignments. .SH RETURN VALUES .LP .B llapi_layout_ost_index_get() diff --git a/lustre/include/lustre/lustreapi.h b/lustre/include/lustre/lustreapi.h index e67d859..d94dd03 100644 --- a/lustre/include/lustre/lustreapi.h +++ b/lustre/include/lustre/lustreapi.h @@ -489,6 +489,16 @@ void llapi_layout_free(struct llapi_layout *layout); #define LLAPI_LAYOUT_RAID0 0 /** +* The layout includes a specific set of OSTs on which to allocate. +*/ +#define LLAPI_LAYOUT_SPECIFIC 0x2000000000000000ULL + +/** + * A valid ost index should be less than maximum valid OST index (UINT_MAX). + */ +#define LLAPI_LAYOUT_IDX_MAX 0x00000000FFFFFFFFULL + +/** * Flags to modify how layouts are retrieved. */ /******************** Stripe Count ********************/ diff --git a/lustre/tests/llapi_layout_test.c b/lustre/tests/llapi_layout_test.c index 60d3ab8..9d4dac6 100644 --- a/lustre/tests/llapi_layout_test.c +++ b/lustre/tests/llapi_layout_test.c @@ -70,8 +70,8 @@ static int num_osts = -1; void usage(char *prog) { - printf("Usage: %s [-d lustre_dir] [-p pool_name] [-o num_osts]\n", - prog); + printf("Usage: %s [-d lustre_dir] [-p pool_name] [-o num_osts] " + "[-s $n,$m,..]\n", prog); exit(0); } @@ -556,12 +556,6 @@ void test13(void) layout = llapi_layout_alloc(); ASSERTF(layout != NULL, "errno = %d", errno); - /* Only setting OST index for stripe 0 is supported for now. */ - errno = 0; - rc = llapi_layout_ost_index_set(layout, 1, 1); - ASSERTF(rc == -1 && errno == EOPNOTSUPP, "rc = %d, errno = %d", - rc, errno); - /* invalid OST index */ errno = 0; rc = llapi_layout_ost_index_set(layout, 0, LLAPI_LAYOUT_INVALID); @@ -1202,6 +1196,119 @@ void test28(void) llapi_layout_free(layout); } +#define T29FILE "f29" +#define T29_DESC "set ost index to non-zero stripe number" +void test29(void) +{ + int rc, fd, i; + uint64_t ost0, ost1, nost; + struct llapi_layout *layout; + char path[PATH_MAX]; + + if (num_osts < 2) + return; + + layout = llapi_layout_alloc(); + ASSERTF(layout != NULL, "errno %d", errno); + + snprintf(path, sizeof(path), "%s/%s", lustre_dir, T29FILE); + + rc = unlink(path); + ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno); + + /* set ost index to LLAPI_LAYOUT_IDX_MAX should fail */ + rc = llapi_layout_ost_index_set(layout, 1, LLAPI_LAYOUT_IDX_MAX); + ASSERTF(rc == -1 && errno == EINVAL, "rc = %d, errno = %d\n", + rc, errno); + + /* specify ost index partially */ + rc = llapi_layout_ost_index_set(layout, 1, 0); + ASSERTF(rc == 0, "errno = %d", errno); + + /* create a partially specified layout will fail */ + fd = llapi_layout_file_create(path, 0, 0660, layout); + ASSERTF(fd == -1 && errno == EINVAL, "path = %s, fd = %d, errno = %d", + path, fd, errno); + + rc = unlink(path); + ASSERTF(rc >= 0 || errno == ENOENT, "errno = %d", errno); + + /* specify all stripes */ + rc = llapi_layout_ost_index_set(layout, 0, 1); + ASSERTF(rc == 0, "errno = %d", errno); + + /* create */ + fd = llapi_layout_file_create(path, 0, 0660, layout); + ASSERTF(fd >= 0, "path = %s, fd = %d, errno = %d", path, fd, errno); + + rc = close(fd); + ASSERTF(rc == 0, "errno = %d", errno); + llapi_layout_free(layout); + + /* get layout from file */ + layout = llapi_layout_get_by_path(path, 0); + ASSERTF(layout != NULL, "errno = %d", errno); + + rc = llapi_layout_ost_index_get(layout, 0, &ost0); + ASSERTF(rc == 0, "errno = %d", errno); + rc = llapi_layout_ost_index_get(layout, 1, &ost1); + ASSERTF(rc == 0, "errno = %d", errno); + ASSERTF(ost0 == 1, "%"PRIu64" != %d", ost0, 1); + ASSERTF(ost1 == 0, "%"PRIu64" != %d", ost1, 0); + llapi_layout_free(layout); + + /* specify more ost indexes to test realloc */ + nost = 0; + layout = llapi_layout_alloc(); + ASSERTF(layout != NULL, "errno %d", errno); + for (i = 0; i < LOV_MAX_STRIPE_COUNT; i++) { + rc = llapi_layout_ost_index_set(layout, i, nost); + ASSERTF(rc == 0, "errno = %d", errno); + rc = llapi_layout_ost_index_get(layout, i, &ost0); + ASSERTF(rc == 0, "errno = %d", errno); + nost++; + if (nost == num_osts) + nost = 0; + } + + nost = 0; + for (i = 0; i < LOV_MAX_STRIPE_COUNT; i++) { + rc = llapi_layout_ost_index_get(layout, i, &ost0); + ASSERTF(rc == 0, "errno = %d", errno); + ASSERTF(ost0 == nost, "ost=%"PRIu64" nost=%"PRIu64"", + ost0, nost); + nost++; + if (nost == num_osts) + nost = 0; + } + llapi_layout_free(layout); + + nost = 0; + layout = llapi_layout_alloc(); + ASSERTF(layout != NULL, "errno %d", errno); + for (i = LOV_MAX_STRIPE_COUNT-1; i >= 0; i--) { + rc = llapi_layout_ost_index_set(layout, i, nost); + ASSERTF(rc == 0, "errno = %d", errno); + rc = llapi_layout_ost_index_get(layout, i, &ost0); + ASSERTF(rc == 0, "errno = %d", errno); + nost++; + if (nost == num_osts) + nost = 0; + } + + nost = 0; + for (i = LOV_MAX_STRIPE_COUNT-1; i <= 0; i--) { + rc = llapi_layout_ost_index_get(layout, i, &ost0); + ASSERTF(rc == 0, "errno = %d", errno); + ASSERTF(ost0 == nost, "ost=%"PRIu64", nost=%"PRIu64"", + ost0, nost); + nost++; + if (nost == num_osts) + nost = 0; + } + llapi_layout_free(layout); +} + #define TEST_DESC_LEN 50 struct test_tbl_entry { void (*tte_fn)(void); @@ -1239,6 +1346,7 @@ static struct test_tbl_entry test_tbl[] = { { &test26, T26_DESC, false }, { &test27, T27_DESC, false }, { &test28, T28_DESC, false }, + { &test29, T29_DESC, false }, }; #define NUM_TESTS (sizeof(test_tbl) / sizeof(struct test_tbl_entry)) @@ -1296,11 +1404,31 @@ int test(void (*test_fn)(), const char *test_desc, bool test_skip, int test_num) return rc; } +/* 'str_tests' are the tests to be skipped, such as "1,3,4,.." */ +static void set_tests_skipped(char *str_tests) +{ + char *ptr = str_tests; + int tstno; + + if (ptr == NULL || strlen(ptr) == 0) + return; + + while (*ptr != '\0') { + tstno = strtoul(ptr, &ptr, 0); + if (tstno >= 0 && tstno < NUM_TESTS) + test_tbl[tstno].tte_skip = true; + if (*ptr == ',') + ptr++; + else + break; + } +} + static void process_args(int argc, char *argv[]) { int c; - while ((c = getopt(argc, argv, "d:p:o:")) != -1) { + while ((c = getopt(argc, argv, "d:p:o:s:")) != -1) { switch (c) { case 'd': lustre_dir = optarg; @@ -1311,6 +1439,9 @@ static void process_args(int argc, char *argv[]) case 'o': num_osts = atoi(optarg); break; + case 's': + set_tests_skipped(optarg); + break; case '?': fprintf(stderr, "Unknown option '%c'\n", optopt); usage(argv[0]); diff --git a/lustre/tests/sanity.sh b/lustre/tests/sanity.sh index 4b3c74c..820f25a 100644 --- a/lustre/tests/sanity.sh +++ b/lustre/tests/sanity.sh @@ -2032,8 +2032,13 @@ test_27D() { test_mkdir -p $DIR/$tdir pool_add $POOL || error "pool_add failed" pool_add_targets $POOL $ost_range || error "pool_add_targets failed" - llapi_layout_test -d$DIR/$tdir -p$POOL -o$OSTCOUNT || + + local skip27D + [ $(lustre_version_code $SINGLEMDS) -lt $(version_code 2.7.64) ] && + skip27D = "-s 29" + llapi_layout_test -d$DIR/$tdir -p$POOL -o$OSTCOUNT $skip27D || error "llapi_layout_test failed" + cleanup_pools || error "cleanup_pools failed" } run_test 27D "validate llapi_layout API" diff --git a/lustre/utils/liblustreapi_layout.c b/lustre/utils/liblustreapi_layout.c index 4cd584e..9756717 100644 --- a/lustre/utils/liblustreapi_layout.c +++ b/lustre/utils/liblustreapi_layout.c @@ -51,11 +51,11 @@ struct llapi_layout { uint64_t llot_stripe_size; uint64_t llot_stripe_count; uint64_t llot_stripe_offset; - /** Indicates if llot_objects array has been initialized. */ - bool llot_objects_are_valid; /* Add 1 so user always gets back a null terminated string. */ char llot_pool_name[LOV_MAXPOOLNAME + 1]; - struct lov_user_ost_data_v1 llot_objects[0]; + /** Number of objects in llot_objects array if was initialized. */ + uint32_t llot_objects_count; + struct lov_user_ost_data_v1 *llot_objects; }; /** @@ -88,6 +88,53 @@ llapi_layout_swab_lov_user_md(struct lov_user_md *lum, int object_count) } /** + * (Re-)allocate llot_objects[] to \a num_stripes stripes. + * + * Copy over existing llot_objects[], if any, to the new llot_objects[]. + * + * \param[in] layout existing layout to be modified + * \param[in] num_stripes number of stripes in new layout + * + * \retval 0 if the objects are re-allocated successfully + * \retval -1 on error with errno set + */ +static int __llapi_layout_objects_realloc(struct llapi_layout *layout, + unsigned int new_stripes) +{ + struct lov_user_ost_data_v1 *new_objects; + unsigned int i; + + if (new_stripes > LOV_MAX_STRIPE_COUNT) { + errno = EINVAL; + return -1; + } + + if (new_stripes == 0 && layout->llot_objects_count == 0) + return 0; + + if (new_stripes != 0 && new_stripes <= layout->llot_objects_count) + return 0; + + new_objects = realloc(layout->llot_objects, + sizeof(*new_objects) * new_stripes); + if (new_objects == NULL && new_stripes != 0) { + errno = ENOMEM; + return -1; + } + + for (i = layout->llot_objects_count; i < new_stripes; i++) + new_objects[i].l_ost_idx = LLAPI_LAYOUT_IDX_MAX; + + if (new_stripes == 0) + layout->llot_objects = NULL; + else + layout->llot_objects = new_objects; + layout->llot_objects_count = new_stripes; + + return 0; +} + +/** * Allocate storage for a llapi_layout with \a num_stripes stripes. * * \param[in] num_stripes number of stripes in new layout @@ -97,14 +144,26 @@ llapi_layout_swab_lov_user_md(struct lov_user_md *lum, int object_count) */ static struct llapi_layout *__llapi_layout_alloc(unsigned int num_stripes) { - struct llapi_layout *layout = NULL; - size_t size = sizeof(*layout) + - (num_stripes * sizeof(layout->llot_objects[0])); + struct llapi_layout *layout; - if (num_stripes > LOV_MAX_STRIPE_COUNT) + if (num_stripes > LOV_MAX_STRIPE_COUNT) { errno = EINVAL; - else - layout = calloc(1, size); + return NULL; + } + + layout = calloc(1, sizeof(*layout)); + if (layout == NULL) { + errno = ENOMEM; + return NULL; + } + + layout->llot_objects = NULL; + layout->llot_objects_count = 0; + + if (__llapi_layout_objects_realloc(layout, num_stripes) < 0) { + free(layout); + layout = NULL; + } return layout; } @@ -151,8 +210,10 @@ llapi_layout_from_lum(const struct lov_user_md *lum, size_t object_count) else layout->llot_stripe_count = lum->lmm_stripe_count; - /* Don't copy lmm_stripe_offset: it is always zero - * when reading attributes. */ + if (lum->lmm_stripe_offset == (typeof(lum->lmm_stripe_offset))-1) + layout->llot_stripe_offset = LLAPI_LAYOUT_DEFAULT; + else + layout->llot_stripe_offset = lum->lmm_stripe_offset; if (lum->lmm_magic != LOV_USER_MAGIC_V1) { const struct lov_user_md_v3 *lumv3; @@ -165,8 +226,9 @@ llapi_layout_from_lum(const struct lov_user_md *lum, size_t object_count) lumv1 = (struct lov_user_md_v1 *)lum; memcpy(layout->llot_objects, lumv1->lmm_objects, objects_sz); } - if (object_count > 0) - layout->llot_objects_are_valid = true; + + if (object_count != 0) + layout->llot_stripe_offset = layout->llot_objects[0].l_ost_idx; return layout; } @@ -183,7 +245,7 @@ llapi_layout_from_lum(const struct lov_user_md *lum, size_t object_count) * \param[in] layout the layout to copy from * * \retval valid lov_user_md pointer on success - * \retval NULL if memory allocation fails + * \retval NULL if memory allocation fails or the layout is invalid */ static struct lov_user_md * llapi_layout_to_lum(const struct llapi_layout *layout) @@ -191,27 +253,47 @@ llapi_layout_to_lum(const struct llapi_layout *layout) struct lov_user_md *lum; size_t lum_size; uint32_t magic = LOV_USER_MAGIC_V1; + uint64_t pattern = layout->llot_pattern; + struct lov_user_ost_data *lmm_objects; + int obj_count = 0, i; - if (strlen(layout->llot_pool_name) != 0) + if ((pattern & LLAPI_LAYOUT_SPECIFIC) != 0) { + if (layout->llot_objects_count < layout->llot_stripe_count) { + errno = EINVAL; + return NULL; + } + magic = LOV_USER_MAGIC_SPECIFIC; + obj_count = layout->llot_stripe_count; + pattern &= ~LLAPI_LAYOUT_SPECIFIC; + } else if (strlen(layout->llot_pool_name) != 0) { magic = LOV_USER_MAGIC_V3; + } - /* The lum->lmm_objects array won't be - * sent to the kernel when we write the lum, so - * we don't allocate storage for it. + /* + * All stripes must be specified when the pattern contains + * LLAPI_LAYOUT_SPECIFIC */ - lum_size = lov_user_md_size(0, magic); + for (i = 0; i < obj_count; i++) { + if (layout->llot_objects[i].l_ost_idx == + LLAPI_LAYOUT_IDX_MAX) { + errno = EINVAL; + return NULL; + } + } + + lum_size = lov_user_md_size(obj_count, magic); lum = malloc(lum_size); if (lum == NULL) return NULL; lum->lmm_magic = magic; - if (layout->llot_pattern == LLAPI_LAYOUT_DEFAULT) + if (pattern == LLAPI_LAYOUT_DEFAULT) lum->lmm_pattern = 0; - else if (layout->llot_pattern == LLAPI_LAYOUT_RAID0) - lum->lmm_pattern = 1; + else if (pattern == LLAPI_LAYOUT_RAID0) + lum->lmm_pattern = LOV_PATTERN_RAID0; else - lum->lmm_pattern = layout->llot_pattern; + lum->lmm_pattern = pattern; if (layout->llot_stripe_size == LLAPI_LAYOUT_DEFAULT) lum->lmm_stripe_size = 0; @@ -221,7 +303,7 @@ llapi_layout_to_lum(const struct llapi_layout *layout) if (layout->llot_stripe_count == LLAPI_LAYOUT_DEFAULT) lum->lmm_stripe_count = 0; else if (layout->llot_stripe_count == LLAPI_LAYOUT_WIDE) - lum->lmm_stripe_count = -1; + lum->lmm_stripe_count = LOV_ALL_STRIPES; else lum->lmm_stripe_count = layout->llot_stripe_count; @@ -230,13 +312,23 @@ llapi_layout_to_lum(const struct llapi_layout *layout) else lum->lmm_stripe_offset = layout->llot_stripe_offset; - if (lum->lmm_magic != LOV_USER_MAGIC_V1) { + if (magic == LOV_USER_MAGIC_V3 || magic == LOV_USER_MAGIC_SPECIFIC) { struct lov_user_md_v3 *lumv3 = (struct lov_user_md_v3 *)lum; - strncpy(lumv3->lmm_pool_name, layout->llot_pool_name, - sizeof(lumv3->lmm_pool_name)); + if (strlen(layout->llot_pool_name)) { + strncpy(lumv3->lmm_pool_name, layout->llot_pool_name, + sizeof(lumv3->lmm_pool_name)); + } else { + memset(lumv3->lmm_pool_name, 0, LOV_MAXPOOLNAME); + } + lmm_objects = lumv3->lmm_objects; + } else { + lmm_objects = lum->lmm_objects; } + for (i = 0; i < obj_count; i++) + lmm_objects[i].l_ost_idx = layout->llot_objects[i].l_ost_idx; + return lum; } @@ -278,6 +370,9 @@ static void inherit_layout_attributes(const struct llapi_layout *src, if (dest->llot_stripe_count == LLAPI_LAYOUT_DEFAULT) dest->llot_stripe_count = src->llot_stripe_count; + + if (dest->llot_stripe_offset == LLAPI_LAYOUT_DEFAULT) + dest->llot_stripe_offset = src->llot_stripe_offset; } /** @@ -315,7 +410,6 @@ struct llapi_layout *llapi_layout_alloc(void) layout->llot_stripe_size = LLAPI_LAYOUT_DEFAULT; layout->llot_stripe_count = LLAPI_LAYOUT_DEFAULT; layout->llot_stripe_offset = LLAPI_LAYOUT_DEFAULT; - layout->llot_objects_are_valid = false; layout->llot_pool_name[0] = '\0'; return layout; @@ -621,9 +715,15 @@ struct llapi_layout *llapi_layout_get_by_fid(const char *lustre_dir, return layout; } -/** * Free memory allocated for \a layout. */ +/** + * Free memory allocated for \a layout. + * + * \param[in] layout previously allocated by llapi_layout_alloc() + */ void llapi_layout_free(struct llapi_layout *layout) { + if (layout->llot_objects != NULL) + free(layout->llot_objects); free(layout); } @@ -792,15 +892,26 @@ int llapi_layout_pattern_set(struct llapi_layout *layout, uint64_t pattern) return -1; } - layout->llot_pattern = pattern; + layout->llot_pattern = pattern | + (layout->llot_pattern & LLAPI_LAYOUT_SPECIFIC); return 0; } +static inline int stripe_number_roundup(int stripe_number) +{ + unsigned int round_up = (stripe_number + 8) & ~7; + return round_up > LOV_MAX_STRIPE_COUNT ? + LOV_MAX_STRIPE_COUNT : round_up; +} + /** * Set the OST index of stripe number \a stripe_number to \a ost_index. * - * The index may only be set for stripe number 0 for now. + * If only the starting stripe's OST index is specified, then this can use + * the normal LOV_MAGIC_{V1,V3} layout type. If multiple OST indices are + * given, then allocate an array to hold the list of indices and ensure that + * the LOV_USER_MAGIC_SPECIFIC layout is used when creating the file. * * \param[in] layout layout to set OST index in * \param[in] stripe_number stripe number to set index for @@ -808,23 +919,50 @@ int llapi_layout_pattern_set(struct llapi_layout *layout, uint64_t pattern) * * \retval 0 on success * \retval -1 if arguments are invalid or an unsupported stripe number - * was specified + * was specified, error returned in errno */ int llapi_layout_ost_index_set(struct llapi_layout *layout, int stripe_number, uint64_t ost_index) { - if (layout == NULL || layout->llot_magic != LLAPI_LAYOUT_MAGIC || - !llapi_layout_stripe_index_is_valid(ost_index)) { + if (layout == NULL || layout->llot_magic != LLAPI_LAYOUT_MAGIC) { errno = EINVAL; return -1; } - - if (stripe_number != 0) { - errno = EOPNOTSUPP; + if (!llapi_layout_stripe_index_is_valid(ost_index)) { + errno = EINVAL; return -1; } - layout->llot_stripe_offset = ost_index; + if (stripe_number == 0 && ost_index == LLAPI_LAYOUT_DEFAULT) { + layout->llot_stripe_offset = ost_index; + layout->llot_pattern &= ~LLAPI_LAYOUT_SPECIFIC; + __llapi_layout_objects_realloc(layout, 0); + } else if (stripe_number >= 0 && + stripe_number < LOV_MAX_STRIPE_COUNT) { + if (ost_index >= LLAPI_LAYOUT_IDX_MAX) { + errno = EINVAL; + return -1; + } + + /* Preallocate a few more stripes to avoid realloc() overhead.*/ + if (__llapi_layout_objects_realloc(layout, + stripe_number_roundup(stripe_number)) < 0) + return -1; + + layout->llot_objects[stripe_number].l_ost_idx = ost_index; + + if (stripe_number == 0) + layout->llot_stripe_offset = ost_index; + else + layout->llot_pattern |= LLAPI_LAYOUT_SPECIFIC; + + if (layout->llot_stripe_count == LLAPI_LAYOUT_DEFAULT || + layout->llot_stripe_count <= stripe_number) + layout->llot_stripe_count = stripe_number + 1; + } else { + errno = EINVAL; + return -1; + } return 0; } @@ -846,12 +984,12 @@ int llapi_layout_ost_index_get(const struct llapi_layout *layout, { if (layout == NULL || layout->llot_magic != LLAPI_LAYOUT_MAGIC || stripe_number >= layout->llot_stripe_count || - index == NULL || layout->llot_objects_are_valid == 0) { + stripe_number >= layout->llot_objects_count || index == NULL) { errno = EINVAL; return -1; } - if (layout->llot_objects[stripe_number].l_ost_idx == -1) + if (layout->llot_stripe_offset == LLAPI_LAYOUT_DEFAULT) *index = LLAPI_LAYOUT_DEFAULT; else *index = layout->llot_objects[stripe_number].l_ost_idx; @@ -969,7 +1107,11 @@ int llapi_layout_file_open(const char *path, int open_flags, mode_t mode, return -1; } - lum_size = lov_user_md_size(0, lum->lmm_magic); + if (lum->lmm_magic == LOV_USER_MAGIC_SPECIFIC) + lum_size = lov_user_md_size(lum->lmm_stripe_count, + lum->lmm_magic); + else + lum_size = lov_user_md_size(0, lum->lmm_magic); rc = fsetxattr(fd, XATTR_LUSTRE_LOV, lum, lum_size, 0); if (rc < 0) { -- 1.8.3.1