Whamcloud - gitweb
EX-4539 lipe: add -xattr and -xattr-match
authorJohn L. Hammond <jhammond@whamcloud.com>
Mon, 28 Feb 2022 14:05:18 +0000 (08:05 -0600)
committerJohn L. Hammond <jhammond@whamcloud.com>
Thu, 10 Mar 2022 21:37:34 +0000 (21:37 +0000)
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 <jhammond@whamcloud.com>
Change-Id: I32c077f99d495cd79e670efef59e4a2939af753f
Reviewed-on: https://review.whamcloud.com/46681
Tested-by: jenkins <devops@whamcloud.com>
lipe/src/lipe_find3/lf3_lexer.l
lipe/src/lipe_find3/lf3_parse.y
lipe/src/lipe_find3/lf3_parse_format.c
lipe/src/lipe_find3/lipe/find.scm
lipe/src/lipe_scan3/ls3_main.c
lipe/src/lipe_scan3/ls3_scan.c
lustre/tests/sanity-lipe-find3.sh

index 5354b49..1601200 100644 (file)
@@ -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;
index acdc728..2632f6b 100644 (file)
@@ -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)");
index f74016e..ace6d68 100644 (file)
@@ -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);
 
index 6d0901b..c9cbf71 100644 (file)
@@ -29,6 +29,7 @@
            user
            group
            xattr-ref-string
+           xattr-match?
            ))
 
 (define-inlinable (any1 proc lis)
 (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))
index 049925e..5b77536 100644 (file)
@@ -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",
index 4db1048..614d623 100644 (file)
@@ -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));
index f7eb1aa..2009e80 100644 (file)
@@ -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