From 05334b90a5d3ddd6c8eabc3683fd487f47df6e35 Mon Sep 17 00:00:00 2001 From: Andreas Dilger Date: Mon, 21 Nov 2022 22:40:03 -0700 Subject: [PATCH] LU-16331 utils: fix 'lfs find -O ' with gaps Fix the UUID parsing in llapi_get_target_uuids() so that the OST UUIDs are put into the right slots when there is a gap in numbering. Otherwise, "lfs find -O " will not be able to find the given UUID if it is the first OST after the gap. Add test case for 'lfs find' and 'lfs getstripe' with large/sparse OST indices in conf-sanity test_81. Test-Parameters: trivial testlist=conf-sanity env=ONLY="81-82" Signed-off-by: Andreas Dilger Change-Id: Ia0581f85f016c202514148114924509118a0f792 Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/49207 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Jian Yu Reviewed-by: Feng Lei Reviewed-by: Oleg Drokin --- lustre/tests/conf-sanity.sh | 93 ++++++++++++++++++++++++++------------------- lustre/utils/liblustreapi.c | 52 ++++++++++++++++--------- 2 files changed, 89 insertions(+), 56 deletions(-) diff --git a/lustre/tests/conf-sanity.sh b/lustre/tests/conf-sanity.sh index ba1e892..5a6bc4c 100644 --- a/lustre/tests/conf-sanity.sh +++ b/lustre/tests/conf-sanity.sh @@ -6442,7 +6442,7 @@ save_ostindex() { local i local index - for i in $(seq $OSTCOUNT); do + for ((i = 1; i <= $OSTCOUNT; i++ )); do index=OSTINDEX$i eval saved_ostindex$i=${!index} eval OSTINDEX$i="" @@ -6451,11 +6451,12 @@ save_ostindex() { # Restore the original values of $OSTCOUNT and $OSTINDEX$i. restore_ostindex() { - trap 0 - local i local index - for i in $(seq $OSTCOUNT); do + + echo "restoring OSTCOUNT=$saved_ostcount and OSTINDEXn" + + for ((i = 1; i <= $OSTCOUNT; i++ )); do index=saved_ostindex$i eval OSTINDEX$i=${!index} done @@ -6471,9 +6472,9 @@ restore_ostindex() { # expected. This test uses OST_INDEX_LIST to format OSTs with a randomly # assigned index and ensures we can mount such a formatted file system test_81() { # LU-4665 - [[ "$MDS1_VERSION" -ge $(version_code 2.6.54) ]] || + (( MDS1_VERSION >= $(version_code 2.6.54) )) || skip "Need MDS version at least 2.6.54" - [[ $OSTCOUNT -ge 3 ]] || skip_env "needs >= 3 OSTs" + (( OSTCOUNT >= 3 )) || skip_env "needs >= 3 OSTs" stopall @@ -6493,36 +6494,66 @@ test_81() { # LU-4665 OSTINDEX1=$saved_ostindex1 save_ostindex 3 + stack_trap restore_ostindex # Format OSTs with random sparse indices. - trap "restore_ostindex" EXIT - echo -e "\nFormat $OSTCOUNT OSTs with sparse indices" - OST_INDEX_LIST=[0,$((RANDOM * 2 % 65533 + 1)),65534] formatall + local rand_ost=$(((RANDOM * 2 % 65533) + 1)) + echo "Format $OSTCOUNT OSTs with OST_INDEX_LIST=[0,$rand_ost,65534]" + OST_INDEX_LIST=[0,$rand_ost,65534] formatall || + error "formatall failed with $?" # Setup and check Lustre filesystem. start_mgsmds || error "start_mgsmds failed" - for i in $(seq $OSTCOUNT); do + for ((i = 1; i <= $OSTCOUNT; i++ )); do start ost$i $(ostdevname $i) $OST_MOUNT_OPTS || error "start ost$i failed" done mount_client $MOUNT || error "mount client $MOUNT failed" check_mount || error "check client $MOUNT failed" + $LFS df # Check max_easize. local max_easize=$($LCTL get_param -n llite.*.max_easize) - # 65452 is XATTR_SIZE_MAX less ldiskfs ea overhead - if large_xattr_enabled; then - [[ $max_easize -ge 65452 ]] || - error "max_easize is $max_easize, should be at least 65452 bytes" - else - # LU-11868 - # 4012 is 4096 less ldiskfs ea overhead - [[ $max_easize -ge 4012 ]] || - error "max_easize is $max_easize, should be at least 4012 bytes" - fi + local xattr_size_max=$((4096 - 84)) # 4096 less ldiskfs ea overhead + + # XATTR_SIZE_MAX less ldiskfs ea overhead + large_xattr_enabled && xattr_size_max=$((65536 - 84)) + (( max_easize >= xattr_size_max )) || + error "max_easize $max_easize < $xattr_size_max bytes" + + test_mkdir $DIR/$tdir + $LFS setstripe -i $rand_ost $DIR/$tdir/$tfile || + error "error creating $tfile on ost$rand_ost" + $LFS getstripe $DIR/$tdir/$tfile + + local cmd + local idx + local found + local uuid + + cmd="getstripe -i $DIR/$tdir/$tfile" + echo lfs $cmd + found=$($LFS $cmd) + (( $found == $rand_ost )) || error "index $found is not $rand_ost" + + cmd="find $DIR/$tdir -i $rand_ost" + echo lfs $cmd + $LFS $cmd + found=$($LFS $cmd) + [[ "$found" == "$DIR/$tdir/$tfile" ]] || + error "'lfs find' returned '$found', not '$tfile' by index" - restore_ostindex + $LFS osts + uuid=$(ostuuid_from_index $rand_ost) + + cmd="find $DIR/$tdir -O $uuid" + echo lfs $cmd + $LFS $cmd + found=$($LFS $cmd) + + [[ "$found" == "$DIR/$tdir/$tfile" ]] || + error "'lfs find' returned '$found', not '$tfile' by UUID" } run_test 81 "sparse OST indexing" @@ -6583,7 +6614,7 @@ test_82a() { # LU-4665 mkdir $DIR/$tdir || error "mkdir $DIR/$tdir failed" stack_trap "do_nodes $(comma_list $(mdts_nodes)) \ - $LCTL get_param osp.*.prealloc_*_id" EXIT + $LCTL get_param osp.*.prealloc_*_id || true" EXIT # 1. If the file does not exist, new file will be created # with specified OSTs. @@ -6642,20 +6673,9 @@ test_82a() { # LU-4665 else echo "need MDS+client version at least 2.11.53" fi - - restore_ostindex } run_test 82a "specify OSTs for file (succeed) or directory (succeed)" -cleanup_82b() { - trap 0 - - # Remove OSTs from a pool and destroy the pool. - destroy_pool $ost_pool || true - - restore_ostindex -} - # Test 82b is run to ensure that if the user supplies a pool with a specific # stripe layout that it behaves proprerly. It should fail in the case that # the supplied OST index list points to OSTs not contained in the user @@ -6680,7 +6700,7 @@ test_82b() { # LU-4665 done ost_indices=$(comma_list $ost_indices) - trap "restore_ostindex" EXIT + stack_trap "restore_ostindex" EXIT echo -e "\nFormat $OSTCOUNT OSTs with sparse indices $ost_indices" OST_INDEX_LIST=[$ost_indices] formatall @@ -6702,9 +6722,6 @@ test_82b() { # LU-4665 local ost_pool=$FSNAME.$TESTNAME create_pool $ost_pool || error "create OST pool $ost_pool failed" - trap - EXIT - trap "cleanup_82b" EXIT - local ost_idx_in_list=${ost_indices##*,} local ost_idx_in_pool=$(exclude_items_from_list $ost_indices \ $ost_idx_in_list) @@ -6747,8 +6764,6 @@ test_82b() { # LU-4665 check_obdidx $file $ost_idx_in_list dd if=/dev/urandom of=$file count=1 bs=1M > /dev/null 2>&1 || error "write $file failed" - - cleanup_82b } run_test 82b "specify OSTs for file with --pool and --ost-list options" diff --git a/lustre/utils/liblustreapi.c b/lustre/utils/liblustreapi.c index 58597de..7a3666b 100644 --- a/lustre/utils/liblustreapi.c +++ b/lustre/utils/liblustreapi.c @@ -2217,11 +2217,11 @@ enum tgt_type { * there are more OSTs than allocated to uuidp, then an error is returned with * the ost_count set to number of available obd uuids. */ -static int llapi_get_target_uuids(int fd, struct obd_uuid *uuidp, +static int llapi_get_target_uuids(int fd, struct obd_uuid *uuidp, int *indices, int *ost_count, enum tgt_type type) { char buf[PATH_MAX], format[32]; - int rc = 0, index = 0; + int i, rc = 0; struct obd_uuid name; glob_t param; FILE *fp; @@ -2250,20 +2250,25 @@ static int llapi_get_target_uuids(int fd, struct obd_uuid *uuidp, snprintf(format, sizeof(format), "%%d: %%%zus", sizeof(uuidp[0].uuid) - 1); - while (fgets(buf, sizeof(buf), fp) != NULL) { - if (uuidp && (index < *ost_count)) { - if (sscanf(buf, format, &index, uuidp[index].uuid) < 2) - break; + for (i = 0; fgets(buf, sizeof(buf), fp); i++) { + int index; + + if (sscanf(buf, format, &index, name.uuid) < 2) + break; + + if (i < *ost_count) { + if (uuidp != NULL) + uuidp[i] = name; + if (indices != NULL) + indices[i] = index; } - index++; } - fclose(fp); - if (uuidp && (index > *ost_count)) + if (uuidp && (i > *ost_count)) rc = -EOVERFLOW; - *ost_count = index; + *ost_count = i; free_param: cfs_free_param_data(¶m); return rc; @@ -2271,7 +2276,7 @@ free_param: int llapi_lov_get_uuids(int fd, struct obd_uuid *uuidp, int *ost_count) { - return llapi_get_target_uuids(fd, uuidp, ost_count, LOV_TYPE); + return llapi_get_target_uuids(fd, uuidp, NULL, ost_count, LOV_TYPE); } int llapi_get_obd_count(char *mnt, int *count, int is_mdt) @@ -2418,9 +2423,10 @@ static int setup_indexes(int d, char *path, struct obd_uuid *obduuids, int num_obds, int **obdindexes, int *obdindex, enum tgt_type type) { - int ret, obdcount, obd_valid = 0, obdnum; + int ret, obdcount, maxidx, obd_valid = 0, obdnum; long i; struct obd_uuid *uuids = NULL; + int *indices = NULL; char buf[16]; int *indexes; @@ -2435,17 +2441,26 @@ static int setup_indexes(int d, char *path, struct obd_uuid *obduuids, uuids = malloc(obdcount * sizeof(struct obd_uuid)); if (uuids == NULL) return -ENOMEM; + indices = malloc(obdcount * sizeof(int)); + if (indices == NULL) { + free(uuids); + return -ENOMEM; + } + maxidx = obdcount; retry_get_uuids: - ret = llapi_get_target_uuids(d, uuids, &obdcount, type); + ret = llapi_get_target_uuids(d, uuids, indices, &obdcount, type); if (ret) { if (ret == -EOVERFLOW) { struct obd_uuid *uuids_temp; + int *indices_temp; uuids_temp = realloc(uuids, obdcount * sizeof(struct obd_uuid)); - if (uuids_temp != NULL) { + indices_temp = realloc(indices, obdcount * sizeof(int)); + if (uuids_temp != NULL && indices_temp != NULL) { uuids = uuids_temp; + indices = indices_temp; goto retry_get_uuids; } ret = -ENOMEM; @@ -2466,20 +2481,21 @@ retry_get_uuids: /* The user may have specified a simple index */ i = strtol(obduuids[obdnum].uuid, &end, 0); - if (end && *end == '\0' && i < obdcount) { + if (end && *end == '\0' && i < maxidx) { indexes[obdnum] = i; obd_valid++; } else { for (i = 0; i < obdcount; i++) { if (llapi_uuid_match(uuids[i].uuid, obduuids[obdnum].uuid)) { - indexes[obdnum] = i; + indexes[obdnum] = indices[i]; obd_valid++; break; } } } - if (i >= obdcount) { + + if (i >= maxidx) { indexes[obdnum] = OBD_NOT_FOUND; llapi_err_noerrno(LLAPI_MSG_ERROR, "invalid obduuid '%s'", @@ -2497,6 +2513,8 @@ retry_get_uuids: out_free: if (uuids) free(uuids); + if (indices) + free(indices); return ret; } -- 1.8.3.1