From ee7dfc5ad17d322e2e27ea2629c4a2d8e11a3507 Mon Sep 17 00:00:00 2001 From: Rajeev Mishra Date: Tue, 4 Apr 2023 00:42:28 +0000 Subject: [PATCH] LU-17025 llapi: Verify stripe pool name Verify the pool exists when setting a stripe within a pool. This avoids situations where the user specifies a missing or invalid pool and an invalid stripe is created test changes: Ensure pool exist before use ost-pools.sh: the test_6 test_7c and test_32 created pool before calling setstripe -p sanity-pfl.sh: test_14 created pool before using it sanity-flr.sh: Test test_0b, test_0c, test_0e and test_0f modified to create pool before using it Test-parameters: trivial testlist=ost-pools,sanity-pfl,sanity-flr HPE-bug-id: LUS-11510 Fixes: cd1f8527d414 ("LU-14645 utils: optimise setstripe") Signed-off-by: Rajeev Mishra Change-Id: I146bc6f886cd083b318dc9ea2e5d1943955bd7d6 Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/51963 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Shaun Tancheff Reviewed-by: Petros Koutoupis Reviewed-by: Oleg Drokin --- lustre/include/lustre/lustreapi.h | 4 ++ lustre/tests/ost-pools.sh | 14 ++++--- lustre/tests/sanity-flr.sh | 24 +++++++++++ lustre/tests/sanity-pfl.sh | 8 +++- lustre/utils/lfs.c | 34 ++++++--------- lustre/utils/liblustreapi.c | 25 +++++++++-- lustre/utils/liblustreapi_layout.c | 85 +++++++++++++++++++++++++++++++++++--- 7 files changed, 156 insertions(+), 38 deletions(-) diff --git a/lustre/include/lustre/lustreapi.h b/lustre/include/lustre/lustreapi.h index b19c0bc..067bc5c 100644 --- a/lustre/include/lustre/lustreapi.h +++ b/lustre/include/lustre/lustreapi.h @@ -1274,6 +1274,8 @@ typedef int (*llapi_layout_iter_cb)(struct llapi_layout *layout, void *cbdata); int llapi_layout_comp_iterate(struct llapi_layout *layout, llapi_layout_iter_cb cb, void *cbdata); +int llapi_verify_pool_name(struct llapi_layout *layout, void *arg); + /** * FLR: mirror operation APIs */ @@ -1294,6 +1296,8 @@ int llapi_heat_set(int fd, __u64 flags); int llapi_ioctl(int fd, unsigned int cmd, void *buf); int llapi_layout_sanity(struct llapi_layout *layout, bool incomplete, bool flr); +int llapi_layout_v2_sanity(struct llapi_layout *layout, bool incomplete, + bool flr, char *fsname); void llapi_layout_sanity_perror(int error); int llapi_layout_dom_size(struct llapi_layout *layout, uint64_t *size); diff --git a/lustre/tests/ost-pools.sh b/lustre/tests/ost-pools.sh index f539289..eebdc22 100755 --- a/lustre/tests/ost-pools.sh +++ b/lustre/tests/ost-pools.sh @@ -693,7 +693,7 @@ test_7c() # setstripe with the same pool name plus 1 letter $LFS setstripe -c 1 $DIR/$tdir/testfile1 --pool "${pool}X" && - error "setstripe succedeed" + error "setstripe succeeded" rm -f $DIR/$tdir/testfile1 @@ -1891,16 +1891,20 @@ test_32() { # LU-15707 ( $LFS getstripe -p $DIR/$tdir | grep -q $pool ) || error "fail to set pool on $DIR/$tdir" - $LFS setstripe -p ignore $DIR/$tdir/$tfile || + local ig_pool="ignore_pool" + + pool_add $ig_pool || error "add $ig_pool failed" + + $LFS setstripe -p $ig_pool $DIR/$tdir/$tfile || error "setstripe fail on $DIR/$tdir/$tfile" - ! ( $LFS getstripe -p $DIR/$tdir/$tfile | egrep -q "[^ ]+" ) || + ( $LFS getstripe -p $DIR/$tdir/$tfile | grep -q $ig_pool ) || error "fail to create $DIR/$tdir/$tfile without pool" # Test with start index local got idx for ((idx = 0; idx < OSTCOUNT; idx++)); do - $LFS setstripe -p ignore -i $idx $DIR/$tdir/$tfile.$idx || + $LFS setstripe -p $ig_pool -i $idx $DIR/$tdir/$tfile.$idx || error "setstripe -i fail on $DIR/$tdir/$tfile.$idx" got=$($LFS getstripe -i $DIR/$tdir/$tfile.$idx) @@ -1909,7 +1913,7 @@ test_32() { # LU-15707 done # Test with ost list - $LFS setstripe -p ignore -o 1,0 $DIR/$tdir/$tfile.1_0 || + $LFS setstripe -p $ig_pool -o 1,0 $DIR/$tdir/$tfile.1_0 || error "setstripe --ost fail on $DIR/$tdir/$tfile.1_0" got=$($LFS getstripe -i $DIR/$tdir/$tfile.1_0) diff --git a/lustre/tests/sanity-flr.sh b/lustre/tests/sanity-flr.sh index e33fa55..01f2b00 100644 --- a/lustre/tests/sanity-flr.sh +++ b/lustre/tests/sanity-flr.sh @@ -361,6 +361,9 @@ test_0b() { $LFS setstripe -S 8M -c -1 -p $pool_name $td || error "$LFS setstripe $td failed" + create_pool $FSNAME.flash || error "create OST pool flash failed" + create_pool $FSNAME.archive || error "create OST pool archive failed" + # create a mirrored file with plain layout mirrors $mirror_cmd -N -N -S 4M -c 2 -p flash -i 2 -o 2,3 \ -N -S 16M -N -c -1 -N -p archive -N -p none $tf || @@ -436,6 +439,11 @@ test_0c() { $LFS setstripe -E 32M -S 8M -c -1 -p $pool_name -E eof -S 16M $td || error "$LFS setstripe $td failed" + create_pool $FSNAME.flash || + error "create OST pool flash failed" + create_pool $FSNAME.archive || + error "create OST pool archive failed" + # create a mirrored file with composite layout mirrors $mirror_cmd -N2 -E 8M -c 2 -p flash -i 1 -o 1,3 -E eof -S 4M \ -N -c 4 -p none \ @@ -549,10 +557,18 @@ test_0e() { # create parent directory mkdir $td || error "mkdir $td failed" + create_pool $FSNAME.ssd || + error "create OST pool ssd failed" + # create a mirrored file with plain layout mirrors $LFS mirror create -N -S 32M -c 3 -p ssd -i 1 -o 1,2,3 $tf || error "create mirrored file $tf failed" + create_pool $FSNAME.flash || + error "create OST pool flash failed" + create_pool $FSNAME.archive || + error "create OST pool archive failed" + # extend the mirrored file with plain layout mirrors $mirror_cmd -N -S 4M -c 2 -p flash -i 2 -o 2,3 \ -N -S 16M -N -c -1 -N -p archive -N -p none $tf || @@ -607,10 +623,18 @@ test_0f() { # create parent directory mkdir $td || error "mkdir $td failed" + create_pool $FSNAME.ssd || + error "create OST pool ssd failed" + # create a mirrored file with composite layout mirror $LFS mirror create -N -E 32M -S 16M -p ssd -E eof -S 32M $tf || error "create mirrored file $tf failed" + create_pool $FSNAME.flash || + error "create OST pool flash failed" + create_pool $FSNAME.archive || + error "create OST pool archive failed" + # extend the mirrored file with composite layout mirrors $mirror_cmd -N -p archive \ -N2 -E 8M -c 2 -p flash -i 1 -o 1,3 -E eof -S 4M \ diff --git a/lustre/tests/sanity-pfl.sh b/lustre/tests/sanity-pfl.sh index b1df3fb..0dc8571 100755 --- a/lustre/tests/sanity-pfl.sh +++ b/lustre/tests/sanity-pfl.sh @@ -844,9 +844,13 @@ test_14() { local file=$DIR/$tdir/$tfile test_mkdir -p $DIR/$tdir rm -f $file + local p1="pool1" + local p2="pool2" - $LFS setstripe -E1m -c1 -S1m --pool="pool1" -E2m \ - -E4m -c2 -S2m --pool="pool2" -E-1 $file || + create_pool $FSNAME.$p1 || error "create_pool $FSNAME.$p1 failed" + create_pool $FSNAME.$p2 || error "create_pool $FSNAME.$p2 failed" + $LFS setstripe -E1m -c1 -S1m --pool=$p1 -E2m \ + -E4m -c2 -S2m --pool=$p2 -E-1 $file || error "Create $file failed" # check --pool inheritance diff --git a/lustre/utils/lfs.c b/lustre/utils/lfs.c index c387aa5..c81df64 100644 --- a/lustre/utils/lfs.c +++ b/lustre/utils/lfs.c @@ -1631,33 +1631,22 @@ enum mirror_flags { * Return: 0 on success or a negative error code on failure. */ static int mirror_create_sanity_check(const char *fname, - struct mirror_args *list, - bool check_fname) + struct mirror_args *list) { int rc = 0; bool has_m_file = false; + char fsname[MAX_OBD_NAME + 1] = { 0 }; bool has_m_layout = false; if (!list) return -EINVAL; - if (fname && check_fname) { - struct llapi_layout *layout; - - layout = llapi_layout_get_by_path(fname, 0); - if (!layout) { - fprintf(stderr, - "error: %s: file '%s' couldn't get layout\n", - progname, fname); - return -ENODATA; - } - - rc = llapi_layout_sanity(layout, false, true); - - llapi_layout_free(layout); - + if (fname) { + rc = llapi_search_fsname(fname, fsname); if (rc) { - llapi_layout_sanity_perror(rc); + fprintf(stderr, + "error: %s: file '%s' has no fsname\n", + progname, fname); return rc; } } @@ -1683,8 +1672,8 @@ static int mirror_create_sanity_check(const char *fname, return -EINVAL; } } - - rc = llapi_layout_sanity(list->m_layout, false, true); + rc = llapi_layout_v2_sanity(list->m_layout, false, true, + fsname); if (rc) { llapi_layout_sanity_perror(rc); return rc; @@ -1740,7 +1729,7 @@ static int mirror_create(char *fname, struct mirror_args *mirror_list) int i = 0; int rc = 0; - rc = mirror_create_sanity_check(fname, mirror_list, false); + rc = mirror_create_sanity_check(fname, mirror_list); if (rc) return rc; @@ -4508,7 +4497,8 @@ static int lfs_setstripe_internal(int argc, char **argv, } } - for (fname = argv[optind]; fname != NULL; fname = argv[++optind]) { + for (fname = argv[optind]; (optind < argc) && (fname != NULL); + fname = argv[++optind]) { if (from_copy) { layout = llapi_layout_get_by_path(template ?: fname, 0); if (!layout) { diff --git a/lustre/utils/liblustreapi.c b/lustre/utils/liblustreapi.c index ddad8a0..bc16eb3 100644 --- a/lustre/utils/liblustreapi.c +++ b/lustre/utils/liblustreapi.c @@ -354,7 +354,7 @@ int llapi_parse_size(const char *optarg, unsigned long long *size, * < 0, error code on failre */ static int llapi_stripe_param_verify(const struct llapi_stripe_param *param, - const char **pool_name) + const char **pool_name, char *fsname) { int count; static int page_size; @@ -419,6 +419,16 @@ static int llapi_stripe_param_verify(const struct llapi_stripe_param *param, "Invalid Poolname '%s'", *pool_name); goto out; } + + /* Make sure the pool exists */ + rc = llapi_search_ost(fsname, *pool_name, NULL); + if (rc < 0) { + llapi_error(LLAPI_MSG_ERROR, rc, + "pool '%s fsname %s' does not exist", + *pool_name, fsname); + rc = -EINVAL; + goto out; + } } out: @@ -543,14 +553,23 @@ int llapi_get_agent_uuid(char *path, char *buf, size_t bufsize) int llapi_file_open_param(const char *name, int flags, mode_t mode, const struct llapi_stripe_param *param) { + char fsname[MAX_OBD_NAME + 1] = { 0 }; struct lov_user_md *lum = NULL; const char *pool_name = param->lsp_pool; size_t lum_size; int fd, rc; + /* Make sure we are on a Lustre file system */ + rc = llapi_search_fsname(name, fsname); + if (rc) { + llapi_error(LLAPI_MSG_ERROR, rc, + "'%s' is not on a Lustre filesystem", name); + return rc; + } + /* Check if the stripe pattern is sane. */ - rc = llapi_stripe_param_verify(param, &pool_name); - if (rc != 0) + rc = llapi_stripe_param_verify(param, &pool_name, fsname); + if (rc < 0) return rc; if (param->lsp_is_specific) diff --git a/lustre/utils/liblustreapi_layout.c b/lustre/utils/liblustreapi_layout.c index 374e9e1..3cabaf3 100644 --- a/lustre/utils/liblustreapi_layout.c +++ b/lustre/utils/liblustreapi_layout.c @@ -1580,6 +1580,7 @@ int llapi_layout_file_open(const char *path, int open_flags, mode_t mode, int tmp; struct lov_user_md *lum; size_t lum_size; + char fsname[MAX_OBD_NAME + 1] = { 0 }; if (path == NULL || (layout != NULL && layout->llot_magic != LLAPI_LAYOUT_MAGIC)) { @@ -1588,8 +1589,16 @@ int llapi_layout_file_open(const char *path, int open_flags, mode_t mode, } if (layout) { - rc = llapi_layout_sanity((struct llapi_layout *)layout, false, - !!(layout->llot_mirror_count > 1)); + /* Make sure we are on a Lustre file system */ + rc = llapi_search_fsname(path, fsname); + if (rc) { + errno = ENOTTY; + return -1; + } + rc = llapi_layout_v2_sanity((struct llapi_layout *)layout, + false, + !!(layout->llot_mirror_count > 1), + fsname); if (rc) { llapi_layout_sanity_perror(rc); return -1; @@ -2195,6 +2204,7 @@ int llapi_layout_file_comp_add(const char *path, int rc, fd = -1, lum_size, tmp_errno = 0; struct llapi_layout *existing_layout = NULL; struct lov_user_md *lum = NULL; + char fsname[MAX_OBD_NAME + 1] = { 0 }; if (path == NULL || layout == NULL || layout->llot_magic != LLAPI_LAYOUT_MAGIC) { @@ -2223,7 +2233,14 @@ int llapi_layout_file_comp_add(const char *path, goto out; } - rc = llapi_layout_sanity(existing_layout, false, false); + rc = llapi_search_fsname(path, fsname); + if (rc) { + tmp_errno = -rc; + rc = -1; + goto out; + } + + rc = llapi_layout_v2_sanity(existing_layout, false, false, fsname); if (rc) { tmp_errno = errno; llapi_layout_sanity_perror(rc); @@ -2471,6 +2488,7 @@ int llapi_layout_file_comp_set(const char *path, uint32_t *ids, uint32_t *flags, struct llapi_layout *layout = NULL; struct llapi_layout_comp *comp; struct lov_user_md *lum = NULL; + char fsname[MAX_OBD_NAME + 1] = { 0 }; if (path == NULL) { errno = EINVAL; @@ -2518,7 +2536,14 @@ int llapi_layout_file_comp_set(const char *path, uint32_t *ids, uint32_t *flags, goto out; } - rc = llapi_layout_sanity(existing_layout, false, false); + rc = llapi_search_fsname(path, fsname); + if (rc) { + tmp_errno = -rc; + rc = -1; + goto out; + } + + rc = llapi_layout_v2_sanity(existing_layout, false, false, fsname); if (rc) { tmp_errno = errno; llapi_layout_sanity_perror(rc); @@ -3343,12 +3368,32 @@ struct llapi_layout_sanity_args { bool lsa_flr; bool lsa_ondisk; int lsa_rc; + char *fsname; }; /* The component flags can be set by users at creation/modification time. */ #define LCME_USER_COMP_FLAGS (LCME_FL_PREF_RW | LCME_FL_NOSYNC | \ LCME_FL_EXTENSION) +/* Inline function to verify the pool name */ +static inline int verify_pool_name(char *fsname, struct llapi_layout *layout) +{ + struct llapi_layout_comp *comp; + + if (!fsname || fsname[0] == '\0') + return 0; + + comp = __llapi_layout_cur_comp(layout); + if (!comp) + return 0; + if (comp->llc_pool_name[0] == '\0') + return 0; + /* check if the pool name exist */ + if (llapi_search_ost(fsname, comp->llc_pool_name, NULL) < 0) + return -1; + return 0; +} + /** * When modified, adjust llapi_stripe_param_verify() if needed as well. */ @@ -3365,6 +3410,11 @@ static int llapi_layout_sanity_cb(struct llapi_layout *layout, goto out_err; } + if (verify_pool_name(args->fsname, layout) != 0) { + args->lsa_rc = -1; + goto out_err; + } + if (comp->llc_list.prev != &layout->llot_comp_list) prev = list_last_entry(&comp->llc_list, typeof(*prev), llc_list); @@ -3560,9 +3610,31 @@ void llapi_layout_sanity_perror(int error) * \retval 0, success, positive: various errors, see * llapi_layout_sanity_perror, -1, failure */ + int llapi_layout_sanity(struct llapi_layout *layout, - bool incomplete, - bool flr) + bool incomplete, bool flr) +{ + return llapi_layout_v2_sanity(layout, incomplete, flr, NULL); +} + +/* This function has been introduced to do pool name checking + * on top of llapi_layout_sanity, the file name passed in this + * function is used later to verify if pool exist. The older version + * of the sanity function is passing NULL for the filename + * Input arguments --- + * \param[in] layout component layout list. + * \param[in] fname file the layout to be checked for + * \param[in] incomplete if layout is complete or not - some checks can + * only be done on complete layouts. + * \param[in] flr set when this is called from FLR mirror create + * \param[in] fsname filesystem name is used to check pool name, if + * NULL no pool name check is performed + * + * \retval 0, success, positive: various errors, see + */ + +int llapi_layout_v2_sanity(struct llapi_layout *layout, + bool incomplete, bool flr, char *fsname) { struct llapi_layout_sanity_args args = { 0 }; struct llapi_layout_comp *curr; @@ -3579,6 +3651,7 @@ int llapi_layout_sanity(struct llapi_layout *layout, args.lsa_rc = 0; args.lsa_flr = flr; args.lsa_incomplete = incomplete; + args.fsname = fsname; /* When we modify an existing layout, this tells us if it's FLR */ if (mirror_id_of(curr->llc_id) > 0) -- 1.8.3.1