From f1dcd2db8b8ecb9a2b63f5dbc1d247ef372f2ba6 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" Date: Mon, 28 Feb 2022 08:05:18 -0600 Subject: [PATCH] EX-4539 lipe: add -xattr and -xattr-match Add '-xattr NAME' and '-xattr-match NAME VALUE' tests to lipe_find3. Add sanity-lipe-find3 test_111() to verify. Test-Parameters: trivial testlist=sanity-lipe-find3 serverextra_install_params="--packages lipe-scan" Test-Parameters: trivial testlist=sanity-lipe-scan3 serverextra_install_params="--packages lipe-scan" facet=mds1 Signed-off-by: John L. Hammond Change-Id: I32c077f99d495cd79e670efef59e4a2939af753f Reviewed-on: https://review.whamcloud.com/46681 Tested-by: jenkins --- lipe/src/lipe_find3/lf3_lexer.l | 10 ++++- lipe/src/lipe_find3/lf3_parse.y | 25 ++++++++++++ lipe/src/lipe_find3/lf3_parse_format.c | 2 +- lipe/src/lipe_find3/lipe/find.scm | 12 +++++- lipe/src/lipe_scan3/ls3_main.c | 69 ++++++++++++++++++++++++++-------- lipe/src/lipe_scan3/ls3_scan.c | 16 ++++---- lustre/tests/sanity-lipe-find3.sh | 31 +++++++++++++++ 7 files changed, 138 insertions(+), 27 deletions(-) diff --git a/lipe/src/lipe_find3/lf3_lexer.l b/lipe/src/lipe_find3/lf3_lexer.l index 5354b49..1601200 100644 --- a/lipe/src/lipe_find3/lf3_lexer.l +++ b/lipe/src/lipe_find3/lf3_lexer.l @@ -59,7 +59,7 @@ static int expr_arg_type; return TOKEN_TEST; } --(amin|atime|blocks|cmin|crtime|ctime|gid|group|iname|inum|links|mirror-count|mmin|mtime|name|path|perm|pool|projid|size|stripe-count|type|uid|user)\0 { +-(amin|atime|blocks|cmin|crtime|ctime|gid|group|iname|inum|links|mirror-count|mmin|mtime|name|path|perm|pool|projid|size|stripe-count|type|uid|user|xattr)\0 { LF3_DEBUG("unary '%s'\n", yytext); expr_arg_begin = lf3_arg_index; expr_arg_end = lf3_arg_index + 2; @@ -67,6 +67,14 @@ static int expr_arg_type; BEGIN ARG; } +-(xattr-match)\0 { + LF3_DEBUG("binary '%s'\n", yytext); + expr_arg_begin = lf3_arg_index; + expr_arg_end = lf3_arg_index + 3; + expr_arg_type = TOKEN_TEST; + BEGIN ARG; +} + -(fprint|fprint0|print-json|printf)\0 { LF3_DEBUG("unary '%s'\n", yytext); expr_arg_begin = lf3_arg_index; diff --git a/lipe/src/lipe_find3/lf3_parse.y b/lipe/src/lipe_find3/lf3_parse.y index acdc728..2632f6b 100644 --- a/lipe/src/lipe_find3/lf3_parse.y +++ b/lipe/src/lipe_find3/lf3_parse.y @@ -724,6 +724,29 @@ static char *lf3_pool_expr(int begin, int end) return xsprintf("(member %Q (lov-pools))", lf3_arg[begin + 1]); } +static char *lf3_xattr_expr(int begin, int end) +{ + assert(begin + 2 == end); + + return xsprintf("(xattr? %Q)", lf3_arg[begin + 1]); +} + +static char *lf3_xattr_match_expr(int begin, int end) +{ + const char *name = lf3_arg[begin + 1]; + const char *value = lf3_arg[begin + 2]; + + assert(begin + 3 == end); + + /* Strength reduction. Note we use equal? instead of string=? + * since xattr-ref-string will return #f when xattr is not + * present. */ + if (strpbrk(name, "?*[") == NULL && strpbrk(value, "?*[") == NULL) + return xsprintf("(equal? (xattr-ref-string %Q) %Q)", name, value); + + return xsprintf("(xattr-match? %Q %Q)", name, value); +} + static char *lf3_exec_plus_expr(int begin, int end) { char *expr = NULL; @@ -1128,6 +1151,8 @@ static char *lf3_simple_expr(int begin, int end) X2("false", xstrdup("#f")); X2("wholename", lf3_path_expr(begin, end)); X2("iwholename", lf3_ipath_expr(begin, end)); + X2("xattr", lf3_xattr_expr(begin, end)); + X2("xattr-match", lf3_xattr_match_expr(begin, end)); X2("print-json", lf3_print_json_expr(begin, end)); X2("quit", "(lipe-scan-break 0)"); diff --git a/lipe/src/lipe_find3/lf3_parse_format.c b/lipe/src/lipe_find3/lf3_parse_format.c index f74016e..ace6d68 100644 --- a/lipe/src/lipe_find3/lf3_parse_format.c +++ b/lipe/src/lipe_find3/lf3_parse_format.c @@ -301,7 +301,7 @@ width: strcmp(ext, "mirror-count") == 0) LF3_EMIT_N('d', "(%s)", ext); else if (strstartswith(ext, "xattr:")) - LF3_EMIT_S('a', "(xattr-ref-string %Q)", ext + strlen("xattr:")); + LF3_EMIT_S('a', "(or (xattr-ref-string %Q) %Q)", ext + strlen("xattr:"), ""); else LF3_FATAL_AT_OFFSET(index, n, "unrecognized format directive '%s'\n", ext); diff --git a/lipe/src/lipe_find3/lipe/find.scm b/lipe/src/lipe_find3/lipe/find.scm index 6d0901b..c9cbf71 100644 --- a/lipe/src/lipe_find3/lipe/find.scm +++ b/lipe/src/lipe_find3/lipe/find.scm @@ -29,6 +29,7 @@ user group xattr-ref-string + xattr-match? )) (define-inlinable (any1 proc lis) @@ -202,5 +203,14 @@ (define (group) (%lipe-gid->group (gid))) +(define (bytevector->latin1 bv) + (bytevector->string bv "latin1")) + +(define (xattr-match? name value) + (any1 (lambda (par) + (and (fnmatch? name (car par)) + (fnmatch? value (bytevector->latin1 (cdr par))))) + (xattrs))) + (define (xattr-ref-string name) - (utf8->string (or (xattr-ref name) #vu8()))) + (and=> (xattr-ref name) bytevector->latin1)) diff --git a/lipe/src/lipe_scan3/ls3_main.c b/lipe/src/lipe_scan3/ls3_main.c index 049925e..5b77536 100644 --- a/lipe/src/lipe_scan3/ls3_main.c +++ b/lipe/src/lipe_scan3/ls3_main.c @@ -257,7 +257,7 @@ static SCM ls3_scm_fid_printer(SCM x, SCM port) snprintf(buf, sizeof(buf), DFID, PFID(fid)); if (scm_is_eq(port, SCM_BOOL_F)) - return scm_from_locale_string(buf); + return scm_from_latin1_string(buf); if (scm_is_eq(port, SCM_BOOL_T)) port = scm_current_output_port(); @@ -314,17 +314,23 @@ SCM_DEFINE(ls3_scm_fnmatch_p, "fnmatch?", 2, 1, 0, char *c_pattern = NULL; char *c_string = NULL; int c_flags; + int rc; SCM_VALIDATE_STRING(1, pattern); - c_pattern = scm_to_locale_string(pattern); + c_pattern = scm_to_latin1_string(pattern); SCM_VALIDATE_STRING(2, string); - c_string = scm_to_locale_string(string); + c_string = scm_to_latin1_string(string); if (SCM_UNBNDP(flags)) c_flags = 0; else SCM_VALIDATE_INT_COPY(3, flags, c_flags); - return fnmatch(c_pattern, c_string, c_flags) == 0 ? SCM_BOOL_T : SCM_BOOL_F; + rc = fnmatch(c_pattern, c_string, c_flags); + + free(c_pattern); + free(c_string); + + return rc == 0 ? SCM_BOOL_T : SCM_BOOL_F; } #undef FUNC_NAME @@ -371,7 +377,7 @@ SCM_DEFINE(ls3_scm_string_to_json_attrs, "lipe-string->json-attrs", 1, 0, 0, SCM_DEFINE(ls3_scm_getopt_device_path, LS3_GETOPT_DEVICE_PATH, 0, 0, 0, (), "return device path from options or #f") { if (ls3_device_path != NULL) - return scm_from_locale_string(ls3_device_path); + return scm_from_latin1_string(ls3_device_path); return SCM_BOOL_F; } @@ -389,7 +395,7 @@ SCM_DEFINE(ls3_scm_getopt_client_mount_path, LS3_GETOPT_CLIENT_MOUNT_PATH, 0, 0, else if (ls3_client_mount_path == LS3_CSTR_NONE) return SCM_BOOL_F; else - return scm_from_locale_string(ls3_client_mount_path); + return scm_from_latin1_string(ls3_client_mount_path); } SCM_DEFINE(ls3_scm_getopt_required_attrs, LS3_GETOPT_REQUIRED_ATTRS, 0, 0, 0, (), "return required object attrs from options") @@ -568,7 +574,7 @@ SCM_DEFINE(ls3_scm_links_list, "links", 0, 0, 0, lipe_list_for_each_entry_reverse(lle, &loa->loa_links, lle_linkage) lis = scm_cons(scm_cons(ls3_scm_from_fid(&lle->lle_parent_fid), - scm_from_locale_string(lle->lle_name)), + scm_from_latin1_string(lle->lle_name)), lis); return lis; @@ -611,7 +617,7 @@ SCM_DEFINE(ls3_scm_absolute_paths, "absolute-paths", 0, 0, 0, (), lipe_list_for_each_entry_reverse(lpe, &loa->loa_paths, lpe_linkage) { path = path_append_2(li->li_client_mount_path, lpe->lpe_path); - lis = scm_cons(scm_from_locale_string(path), lis); + lis = scm_cons(scm_from_latin1_string(path), lis); free(path); } @@ -626,11 +632,36 @@ SCM_DEFINE(ls3_scm_relative_paths, "relative-paths", 0, 0, 0, (), SCM lis = SCM_EOL; lipe_list_for_each_entry_reverse(lpe, &loa->loa_paths, lpe_linkage) - lis = scm_cons(scm_from_locale_string(lpe->lpe_path), lis); + lis = scm_cons(scm_from_latin1_string(lpe->lpe_path), lis); return lis; } +SCM_DEFINE(ls3_scm_xattr_p, "xattr?", 1, 0, 0, + (SCM s_name), "return #f if current file has xattr name") +#define FUNC_NAME s_ls3_scm_xattr_p +{ + struct ls3_object_attrs *loa = ls3_attrs(LS3_OBJECT_ATTR_XATTRS); + const struct lipe_xattr *lx; + char *c_name = NULL; + SCM rc = SCM_BOOL_F; + + SCM_VALIDATE_STRING(1, s_name); + c_name = scm_to_latin1_string(s_name); + + lipe_list_for_each_entry(lx, &loa->loa_xattrs, lx_linkage) { + if (strcmp(c_name, lx->lx_name) == 0) { + rc = SCM_BOOL_T; + goto out; + } + } +out: + free(c_name); + + return rc; +} +#undef FUNC_NAME + static SCM ls3_scm_c_xattr_value(const void *value, unsigned int value_len) { SCM bv; @@ -651,7 +682,7 @@ SCM_DEFINE(ls3_scm_xattrs_list, "xattrs", 0, 0, 0, SCM lis = SCM_EOL; lipe_list_for_each_entry_reverse(lx, &loa->loa_xattrs, lx_linkage) - lis = scm_cons(scm_cons(scm_from_locale_string(lx->lx_name), + lis = scm_cons(scm_cons(scm_from_latin1_string(lx->lx_name), ls3_scm_c_xattr_value(lx->lx_value, lx->lx_value_len)), lis); @@ -668,7 +699,7 @@ SCM_DEFINE(ls3_scm_xattr_ref, "xattr-ref", 1, 0, 0, SCM bv_or_false = SCM_BOOL_F; SCM_VALIDATE_STRING(1, s_name); - c_name = scm_to_locale_string(s_name); + c_name = scm_to_latin1_string(s_name); lipe_list_for_each_entry(lx, &loa->loa_xattrs, lx_linkage) { if (strcmp(c_name, lx->lx_name) != 0) @@ -762,7 +793,7 @@ SCM_DEFINE(ls3_scm_lov_pools_list, "lov-pools", 0, 0, 0, goto out; if (buf[0] != '\0') - lis = scm_cons(scm_from_locale_string(buf), lis); + lis = scm_cons(scm_from_latin1_string(buf), lis); rc = llapi_layout_comp_use(ll, LLAPI_LAYOUT_COMP_USE_PREV); if (rc < 0) @@ -948,14 +979,16 @@ SCM_DEFINE(ls3_scm_scan, LS3_SCAN, 5, 0, 0, "scan a device") #define FUNC_NAME s_ls3_scm_scan { - const char *c_device_path; - const char *c_client_mount_path; + char *c_device_path = NULL; + const char *c_client_mount_path = NULL; + char *c_client_mount_path_1 = NULL; + unsigned int c_required_attrs; int c_thread_count; int rc; SCM_VALIDATE_STRING(1, s_device_path); - c_device_path = scm_to_locale_string(s_device_path); + c_device_path = scm_to_latin1_string(s_device_path); if (scm_is_eq(s_client_mount_path, SCM_BOOL_F)) { c_client_mount_path = LS3_CSTR_NONE; @@ -963,7 +996,7 @@ SCM_DEFINE(ls3_scm_scan, LS3_SCAN, 5, 0, 0, c_client_mount_path = LS3_CSTR_AUTO; } else { SCM_VALIDATE_STRING(2, s_client_mount_path); - c_client_mount_path = scm_to_locale_string(s_client_mount_path); + c_client_mount_path = c_client_mount_path_1 = scm_to_latin1_string(s_client_mount_path); } SCM_VALIDATE_THUNK(3, s_policy_thunk); @@ -982,6 +1015,9 @@ SCM_DEFINE(ls3_scm_scan, LS3_SCAN, 5, 0, 0, c_thread_count); LS3_DEBUG_D(rc); + free(c_device_path); + free(c_client_mount_path_1); + return scm_from_int(rc); } #undef FUNC_NAME @@ -1211,6 +1247,7 @@ static void ls3_module_init(void *unused) "links", "absolute-paths", "relative-paths", + "xattr?", "xattrs", "xattr-ref", "lov-mirror-count", diff --git a/lipe/src/lipe_scan3/ls3_scan.c b/lipe/src/lipe_scan3/ls3_scan.c index 4db1048..614d623 100644 --- a/lipe/src/lipe_scan3/ls3_scan.c +++ b/lipe/src/lipe_scan3/ls3_scan.c @@ -1124,7 +1124,7 @@ static int ls3_scan_client_mount_init(struct ls3_instance *li, const char *path, } li->li_client_mount_path = path_canon; - li->li_scm_client_mount_path = scm_from_locale_string(li->li_client_mount_path); + li->li_scm_client_mount_path = scm_from_latin1_string(li->li_client_mount_path); li->li_client_mount_fd = fd; li->li_scm_client_mount_fd = scm_from_int(fd); path_canon = NULL; @@ -1187,10 +1187,10 @@ int ls3_scan(const char *device_path, struct ls3_instance li = { .li_device_path = xstrdup(device_path), .li_client_mount_fd = -1, - .li_scm_device_path = scm_from_locale_string(device_path), - .li_scm_device_name = scm_from_locale_string(""), - .li_scm_fsname = scm_from_locale_string(""), - .li_scm_client_mount_path = scm_from_locale_string(""), + .li_scm_device_path = scm_from_latin1_string(device_path), + .li_scm_device_name = scm_from_latin1_string(""), + .li_scm_fsname = scm_from_latin1_string(""), + .li_scm_client_mount_path = scm_from_latin1_string(""), .li_scm_client_mount_fd = scm_from_int(-1), .li_scm_policy_thunk = policy_thunk, .li_scm_thread_count = scm_from_int(0), @@ -1224,7 +1224,7 @@ int ls3_scan(const char *device_path, li.li_device_name = xstrdup((const char *)fs->super->s_volume_name); LS3_DEBUG_S(li.li_device_name); - li.li_scm_device_name = scm_from_locale_string(li.li_device_name); + li.li_scm_device_name = scm_from_latin1_string(li.li_device_name); rc = ls3_read_ldd(device_path, fs, &ldd); if (rc != 0) @@ -1235,7 +1235,7 @@ int ls3_scan(const char *device_path, LS3_DEBUG_S(ldd.ldd_fsname); LS3_DEBUG_S(ldd.ldd_svname); - li.li_scm_fsname = scm_from_locale_string(ldd.ldd_fsname); + li.li_scm_fsname = scm_from_latin1_string(ldd.ldd_fsname); switch (ldd.ldd_flags & (LDD_F_SV_TYPE_MDT | LDD_F_SV_TYPE_OST)) { case LDD_F_SV_TYPE_MDT: @@ -1305,7 +1305,7 @@ SCM ls3_policy_exception_handler(SCM key, SCM args) } else if (scm_is_eq(key, ls3_sym_scan_continue)) { /* OK */ } else { - SCM fmt = scm_from_locale_string("ERROR: caught ~a ~s\n"); + SCM fmt = scm_from_latin1_string("ERROR: caught ~a ~s\n"); scm_simple_format(scm_current_error_port(), fmt, scm_list_2(key, args)); diff --git a/lustre/tests/sanity-lipe-find3.sh b/lustre/tests/sanity-lipe-find3.sh index f7eb1aa..2009e80 100644 --- a/lustre/tests/sanity-lipe-find3.sh +++ b/lustre/tests/sanity-lipe-find3.sh @@ -705,6 +705,37 @@ test_110() { } run_test 110 "lipe_find3 -pool does the right thing" +test_111() { + local file=$MOUNT/$tfile + local name="user.$TESTNAME" + local fid + + init_lipe_find3_env "$file" + fid=$($LFS path2fid "$file") + + setfattr -n "$name" "$file" + expect1 "$fid" lipe_find3_facet mds1 -xattr "$name" -print-file-fid + expect1 "$fid" lipe_find3_facet mds1 -xattr-match "$name" '' -print-file-fid + expect_empty lipe_find3_facet mds1 -xattr-match "$name" XXX -print-file-fid + + expect1 "$fid" lipe_find3_facet mds1 -xattr trusted.lma -print-file-fid + expect1 "$fid" lipe_find3_facet mds1 -xattr trusted.lov -print-file-fid + + setfattr -n "$name" -v XXX "$file" + expect1 "$fid" lipe_find3_facet mds1 -xattr "$name" -print-file-fid + expect1 "$fid" lipe_find3_facet mds1 -xattr-match "$name" XXX -print-file-fid + expect1 "$fid" lipe_find3_facet mds1 -xattr-match '*' XXX -print-file-fid + expect1 "$fid" lipe_find3_facet mds1 -xattr-match "$name" '*' -print-file-fid + expect1 "$fid" lipe_find3_facet mds1 -xattr-match "$name" 'X*' -print-file-fid + expect_empty lipe_find3_facet mds1 -xattr-match "$name" '' -print-file-fid + + expect_empty lipe_find3_facet mds1 -xattr "${name}-1" -print-file-fid + expect_empty lipe_find3_facet mds1 -xattr-match "${name}-1" '*' -print-file-fid + + expect_error lipe_find3_facet mds1 -xattr +} +run_test 111 "lipe_find3 -xattr does the right thing" + test_130() { local file=$MOUNT/$tfile local xtime -- 1.8.3.1