Whamcloud - gitweb
EX-7290 lipe: lipe_find3 get attr warnings
authorAlexandre Ioffe <aioffe@ddn.com>
Wed, 6 Sep 2023 08:17:59 +0000 (01:17 -0700)
committerAndreas Dilger <adilger@whamcloud.com>
Thu, 14 Sep 2023 07:34:52 +0000 (07:34 +0000)
Report each get attr error when command line
option --warnings=get-attr.
Count all get attr errors per attr type and report them at the end.
Exclude the 'trusted.link' when scanning an OST.

Test-Parameters: trivial testlist=sanity-lipe-scan3,sanity-lipe-find3,sanityn
Signed-off-by: Alexandre Ioffe <aioffe@ddn.com>
Change-Id: I5e9b226bd4046eddcf779ca06af0892589d447ac
Reviewed-on: https://review.whamcloud.com/c/ex/lustre-release/+/52292
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
lipe/man/lipe_find3.1
lipe/src/lipe_find3/lf3_parse.y
lipe/src/lipe_scan3/lipe-scan3-notes.txt
lipe/src/lipe_scan3/ls3_debug.h
lipe/src/lipe_scan3/ls3_main.c
lipe/src/lipe_scan3/ls3_object_attrs.h
lipe/src/lipe_scan3/ls3_scan.c
lipe/src/lipe_scan3/tests/lipe.scm

index 74c9a2a..2909e66 100644 (file)
@@ -31,6 +31,9 @@ list available JSON attribute names and exit
 \fB\-\-thread\-count\fR=\fICOUNT\fR
 use COUNT scaninng threads (default 4)
 .TP
+\fB\-\-warnings\fR=\fIWARN_TYPE\fR
+enable additional warning diagnostic. Available warning type: get-attr - warning is reported when getting file attribute fails
+.TP
 \fB\-h\fR, \fB\-\-help\fR
 display this help text and exit
 .TP
index 0aee9d7..7e4fdc3 100644 (file)
@@ -287,7 +287,9 @@ static char *lf3_user_expr(int begin, int end)
        if (rc == INT_MIN)
                LF3_FATAL_AT(begin + 1, "'%s' is not the name of a known user\n", name);
        else if (rc < 0)
-               LF3_FATAL_AT(begin + 1, "cannot get UID for user '%s': %s\n", name, strerror(-rc));
+               LF3_FATAL_AT(begin + 1,
+                            "cannot get UID for user '%s': %s\n",
+                            name, strerror(-rc));
 
        return xsprintf("(= (uid) %llu)", (__ull)id);
 }
@@ -304,7 +306,9 @@ static char *lf3_group_expr(int begin, int end)
        if (rc == INT_MIN)
                LF3_FATAL_AT(begin + 1, "'%s' is not the name of a known group\n", name);
        else if (rc < 0)
-               LF3_FATAL_AT(begin + 1, "cannot get GID for group '%s': %s\n", name, strerror(-rc));
+               LF3_FATAL_AT(begin + 1,
+                            "cannot get GID for group '%s': %s\n",
+                            name, strerror(-rc));
 
        return xsprintf("(= (gid) %llu)", (__ull)id);
 }
@@ -1312,6 +1316,7 @@ enum {
        LF3_OPT_NOW,
        LF3_OPT_SCAN_COMMAND,
        LF3_OPT_THREAD_COUNT,
+       LF3_OPT_WARN,
        LF3_OPT_HELP = 'h',
        LF3_OPT_VERSION = 'v',
 };
@@ -1329,6 +1334,7 @@ static void help(void)
 /* --now=EPOCH                 use EPOCH instead of current time (for testing) */
 /* --scan-command=COMMAND      use 'cat' to print the code we would send to lipe_scan3 */
 "  --thread-count=COUNT        use COUNT scaninng threads\n"
+"  --warnings=get-attr          enable get attribute warnings\n"
 "  -h, --help                  display this help text and exit\n"
 "  -v, --version               output version information and exit\n",
        program_invocation_short_name);
@@ -1341,6 +1347,7 @@ static const struct option options[] = {
        { "now", required_argument, 0, LF3_OPT_NOW },
        { "scan-command", required_argument, 0, LF3_OPT_SCAN_COMMAND },
        { "thread-count", required_argument, 0, LF3_OPT_THREAD_COUNT },
+       { "warnings", required_argument, 0, LF3_OPT_WARN },
        { "help", no_argument, 0,  LF3_OPT_HELP },
        { "version", no_argument, 0, LF3_OPT_VERSION },
        { NULL },
@@ -1351,6 +1358,7 @@ int main(int argc, char *argv[])
        const char *scan_command = LF3_SCAN_COMMAND;
        const char *thread_count = NULL;
        bool debug_scan = false;
+       const char *opt_warns = NULL;
        int rc;
        int c;
 
@@ -1383,6 +1391,9 @@ int main(int argc, char *argv[])
                case LF3_OPT_THREAD_COUNT:
                        thread_count = optarg;
                        break;
+               case LF3_OPT_WARN:
+                       opt_warns = optarg;
+                       break;
                case LF3_OPT_HELP:
                        help();
                        exit(EXIT_SUCCESS);
@@ -1406,6 +1417,20 @@ int main(int argc, char *argv[])
        if (debug_scan)
                lf3_init_add("(lipe-debug-enable #t)");
 
+       if (opt_warns) {
+               if (strcmp(opt_warns, "get-attr") == 0)
+                       lf3_init_add("(lipe-warnings-get-attr-enable #t)");
+               else {
+                       fprintf(stderr,
+                               "Usage: --warnings=get-attr\n"
+                               "Try '%s --help for more information.\n",
+                               program_invocation_short_name);
+                       exit(EXIT_FAILURE + 1);
+               }
+       }
+
+       LF3_DEBUG_S(opt_warns);
+
        if (lf3_now == -1)
                lf3_now = time(NULL);
 
index b64e767..ef464e4 100644 (file)
@@ -161,6 +161,7 @@ Other procedures
 
   The following can be called from any context:
     (lipe-debug-enable [enable]) enable or disable debugging. Returns previous value.
+    (lipe-warnings-get-attr-enable [enable]) enable or disable warning report when get attr errored. Returns previous value.
     (lipe-gettid) return calling thread ID (Linux tid for gdb -p, not pthread ID)
     (lipe-getopt-client-mount-path) see above
     (lipe-getopt-required-attrs) see above
index 926c687..fbbffde 100644 (file)
@@ -21,6 +21,7 @@ enum {
 };
 
 extern bool ls3_debug;
+extern bool ls3_warn_get_attr;
 extern const char *ls3_progname_;
 extern __thread int ls3_tid;
 
@@ -49,6 +50,14 @@ static inline const char *ls3_progname(void)
 #define LS3_WARNING(fmt, args...)                                              \
        fprintf(stderr, "%s[%d]: WARNING: "fmt, ls3_progname(), ls3_tid, ##args)
 
+/*
+#define LS3_WARN_GET_ATTR(fmt, args...)                                        \
+       do {                                                            \
+               if (ls3_warn_get_attr)                                  \
+                       LS3_WARNING(fmt, ##args)                        \
+       } while (0)
+*/
+
 #define LS3_ERROR_ONCE(fmt, args...)                                   \
        do {                                                            \
                static int ls3_error_once;                              \
index bd58057..a304630 100644 (file)
@@ -55,6 +55,7 @@ SCM ls3_scm_policy_exception_handler;
 
 bool ls3_debug;
 bool save_fsize_stats;
+bool ls3_warn_get_attr;
 const char *ls3_progname_;
 __thread int ls3_tid; /* gettid() thread id for debug messages. */
 
@@ -416,6 +417,17 @@ SCM_DEFINE(ls3_scm_debug_enable, "lipe-debug-enable", 0, 1, 0,
        return scm_from_bool(old_debug);
 }
 
+SCM_DEFINE(ls3_scm_warn_get_attr_enable, "lipe-warnings-get-attr-enable", 0, 1, 0,
+          (SCM enable), "get or set get attr warning")
+{
+       bool old_warn = ls3_warn_get_attr;
+
+       if (!SCM_UNBNDP(enable))
+               ls3_warn_get_attr = scm_is_true(enable);
+
+       return scm_from_bool(old_warn);
+}
+
 SCM_DEFINE(ls3_scm_gettid, "lipe-gettid", 0, 0, 0, (), "print caller's thread ID (not pthread id)")
 {
        return scm_from_ulong(syscall(SYS_gettid));
@@ -534,6 +546,7 @@ static void ls3_throw_read_attr_error(enum ls3_object_attr_bit bits,
 {
        struct ls3_object_attrs *loa = ls3_current()->lc_attrs;
 
+       /* *** See ls3_policy_exception_handler */
        scm_throw(ls3_sym_read_attr_error,
                  scm_list_3(scm_from_ulong(loa->loa_ino),
                             scm_from_ulong(bits),
@@ -550,12 +563,10 @@ static struct ls3_object_attrs *ls3_attrs_try(enum ls3_object_attr_bit bits)
 
        if ((loa->loa_valid & bits) == bits)
                return loa;
-
        ls3_read_attrs(ls3_current()->lc_instance, ls3_current()->lc_object,
                       loa,
                       bits,
                       false /* quit_on_error */);
-
        return loa;
 }
 
@@ -1384,6 +1395,7 @@ static void ls3_module_init(void *unused)
        "lipe-getopt-device-path",
        "lipe-getopt-required-attrs",
        "lipe-getopt-thread-count",
+       "lipe-warnings-get-attr-enable",
        "lipe-scan",
        "lipe-scan-break",
        "lipe-scan-client-mount-fd",
index 8edd54c..282f2f0 100644 (file)
@@ -15,41 +15,107 @@ struct ls3_instance;
 struct lipe_object;
 struct json_object;
 
+#define BIT(pos) (1U << (pos))
+
+enum ls3_object_attr_bit_pos {
+       LS3_OBJECT_ATTR_BIT_BASE,
+       LS3_OBJECT_ATTR_BIT_PROJID,
+       LS3_OBJECT_ATTR_BIT_FILTER_FID,
+       LS3_OBJECT_ATTR_BIT_HSM,
+       LS3_OBJECT_ATTR_BIT_LINKS,
+       LS3_OBJECT_ATTR_BIT_LMV,
+       LS3_OBJECT_ATTR_BIT_LOV,
+       LS3_OBJECT_ATTR_BIT_SELF_FID,
+       LS3_OBJECT_ATTR_BIT_SOM,
+       LS3_OBJECT_ATTR_BIT_XATTRS,
+       LS3_OBJECT_ATTR_BIT_FILE_FID,
+       LS3_OBJECT_ATTR_BIT_SIZE,
+       LS3_OBJECT_ATTR_BIT_PATHS,
+
+       LS3_OBJECT_ATTR_BIT_MAX
+};
+
+#ifndef ARRAY_SIZE
+# define ARRAY_SIZE(a) ((sizeof(a)) / (sizeof((a)[0])))
+#endif
+
+static inline const char *ls3_object_attr_bit_pos2str(enum ls3_object_attr_bit_pos pos)
+{
+       const char *attr_bit_str[LS3_OBJECT_ATTR_BIT_MAX] = {
+               [LS3_OBJECT_ATTR_BIT_BASE]       = "base",
+               [LS3_OBJECT_ATTR_BIT_PROJID]     = "projid",
+               [LS3_OBJECT_ATTR_BIT_FILTER_FID] = "filter_fid",
+               [LS3_OBJECT_ATTR_BIT_HSM]        = "hsm",
+               [LS3_OBJECT_ATTR_BIT_LINKS]      = "links",
+               [LS3_OBJECT_ATTR_BIT_LMV]        = "lmv",
+               [LS3_OBJECT_ATTR_BIT_LOV]        = "lov",
+               [LS3_OBJECT_ATTR_BIT_SELF_FID]   = "self_fid",
+               [LS3_OBJECT_ATTR_BIT_SOM]        = "som",
+               [LS3_OBJECT_ATTR_BIT_XATTRS]     = "xattrs",
+               [LS3_OBJECT_ATTR_BIT_FILE_FID]   = "file_fid",
+               [LS3_OBJECT_ATTR_BIT_SIZE]       = "size",
+               [LS3_OBJECT_ATTR_BIT_PATHS]      = "paths",
+       };
+       if (pos >=  ARRAY_SIZE(attr_bit_str))
+               return "<unknown>";
+       return attr_bit_str[pos];
+}
+
 enum ls3_object_attr_bit {
        /* Includes ino, mode, nlink, uid, gid, atime, ctime, mtime
         * and flags. Does not include size/blocks. */
-       LS3_OBJECT_ATTR_BASE            = 0x0001,
-       LS3_OBJECT_ATTR_PROJID          = 0x0002,
+       LS3_OBJECT_ATTR_BASE            = BIT(LS3_OBJECT_ATTR_BIT_BASE),
+       LS3_OBJECT_ATTR_PROJID          = BIT(LS3_OBJECT_ATTR_BIT_PROJID),
 
        /* OST objects XATTR_NAME_FID which saves the prarent FID
         * (i.e. the FID of the file on MDT). Files on MDT don't have
         * this xattr. */
-       LS3_OBJECT_ATTR_FILTER_FID      = 0x0004, /* XATTR_NAME_FID */
-       LS3_OBJECT_ATTR_HSM             = 0x0008, /* XATTR_NAME_HSM */
-       LS3_OBJECT_ATTR_LINKS           = 0x0010, /* XATTR_NAME_LINK */
-       LS3_OBJECT_ATTR_LMV             = 0x0020, /* XATTR_NAME_LMV */
-       LS3_OBJECT_ATTR_LOV             = 0x0040, /* XATTR_NAME_LOV */
-       LS3_OBJECT_ATTR_SELF_FID        = 0x0080, /* XATTR_NAME_LMA */
-       LS3_OBJECT_ATTR_SOM             = 0x0100, /* XATTR_NAME_SOM */
-
-       LS3_OBJECT_ATTR_XATTRS          = 0x0200,
+       /* XATTR_NAME_FID */
+       LS3_OBJECT_ATTR_FILTER_FID      = BIT(LS3_OBJECT_ATTR_BIT_FILTER_FID),
+       /* XATTR_NAME_HSM */
+       LS3_OBJECT_ATTR_HSM             = BIT(LS3_OBJECT_ATTR_BIT_HSM),
+       /* XATTR_NAME_LINK */
+       LS3_OBJECT_ATTR_LINKS           = BIT(LS3_OBJECT_ATTR_BIT_LINKS),
+       /* XATTR_NAME_LMV */
+       LS3_OBJECT_ATTR_LMV             = BIT(LS3_OBJECT_ATTR_BIT_LMV),
+       /* XATTR_NAME_LOV */
+       LS3_OBJECT_ATTR_LOV             = BIT(LS3_OBJECT_ATTR_BIT_LOV),
+       /* XATTR_NAME_LMA */
+       LS3_OBJECT_ATTR_SELF_FID        = BIT(LS3_OBJECT_ATTR_BIT_SELF_FID),
+       /* XATTR_NAME_SOM */
+       LS3_OBJECT_ATTR_SOM             = BIT(LS3_OBJECT_ATTR_BIT_SOM),
+       LS3_OBJECT_ATTR_XATTRS          = BIT(LS3_OBJECT_ATTR_BIT_XATTRS),
 
        /* self_fid on MDT, FID of parent file on OST */
-       LS3_OBJECT_ATTR_FILE_FID        = 0x0400,
+       LS3_OBJECT_ATTR_FILE_FID        = BIT(LS3_OBJECT_ATTR_BIT_FILE_FID),
 
        /* The file size on MDT is always 0 (without Data on MDT). But
         * Lazy Size on MDT can be used as an estimated size since the
         * inaccuracy doesn't bother the policy engine. So, if DoM,
         * use real size; if LSoM exists, use it as file size. */
-       LS3_OBJECT_ATTR_SIZE            = 0x0800,
+       LS3_OBJECT_ATTR_SIZE            = BIT(LS3_OBJECT_ATTR_BIT_SIZE),
 
        /* Paths from fid2path ioctl for LS3_OBJECT_ATTR_FID on client. */
-       LS3_OBJECT_ATTR_PATHS           = 0x1000,
+       LS3_OBJECT_ATTR_PATHS           = BIT(LS3_OBJECT_ATTR_BIT_PATHS),
 
 /*     LS3_OBJECT_ATTR_EMPTY           TODO Make work for striped directories. */
 /*     LS3_OBJECT_ATTR_ENTRIES         TODO Make work for striped directories. */
 
-       LS3_OBJECT_ATTR_ALL             = 0x1fff,
+       LS3_OBJECT_ATTR_ALL =
+               LS3_OBJECT_ATTR_BASE    |
+               LS3_OBJECT_ATTR_PROJID  |
+               LS3_OBJECT_ATTR_FILTER_FID |
+               LS3_OBJECT_ATTR_HSM     |
+               LS3_OBJECT_ATTR_LINKS   |
+               LS3_OBJECT_ATTR_LMV     |
+               LS3_OBJECT_ATTR_LOV     |
+               LS3_OBJECT_ATTR_SELF_FID |
+               LS3_OBJECT_ATTR_SOM     |
+               LS3_OBJECT_ATTR_XATTRS  |
+               LS3_OBJECT_ATTR_FILE_FID |
+               LS3_OBJECT_ATTR_SIZE    |
+               LS3_OBJECT_ATTR_PATHS,
+
        LS3_OBJECT_ATTR_DEFAULT         = -1U,
 };
 
@@ -84,33 +150,33 @@ enum {
 };
 
 enum ls3_json_attr {
-       LS3_JSON_ATTR_INO = 1U << LS3_JSON_BIT_INO,
-       LS3_JSON_ATTR_MODE = 1U << LS3_JSON_BIT_MODE,
-       LS3_JSON_ATTR_NLINK = 1U << LS3_JSON_BIT_NLINK,
-       LS3_JSON_ATTR_UID = 1U << LS3_JSON_BIT_UID,
-       LS3_JSON_ATTR_GID = 1U << LS3_JSON_BIT_GID,
-       LS3_JSON_ATTR_PROJID = 1U << LS3_JSON_BIT_PROJID,
-       LS3_JSON_ATTR_FLAGS = 1U <<  LS3_JSON_BIT_FLAGS,
-       LS3_JSON_ATTR_ATIME = 1U << LS3_JSON_BIT_ATIME,
-       LS3_JSON_ATTR_MTIME = 1U << LS3_JSON_BIT_MTIME,
-       LS3_JSON_ATTR_CTIME = 1U << LS3_JSON_BIT_CTIME,
-       LS3_JSON_ATTR_CRTIME = 1U << LS3_JSON_BIT_CRTIME,
-       LS3_JSON_ATTR_SIZE = 1U << LS3_JSON_BIT_SIZE,
-       LS3_JSON_ATTR_BLOCKS = 1U << LS3_JSON_BIT_BLOCKS,
-       LS3_JSON_ATTR_FILE_FID = 1U << LS3_JSON_BIT_FILE_FID,
-       LS3_JSON_ATTR_SELF_FID = 1U << LS3_JSON_BIT_SELF_FID,
-       LS3_JSON_ATTR_FILTER_FID = 1U << LS3_JSON_BIT_FILTER_FID,
-       LS3_JSON_ATTR_LMA = 1U << LS3_JSON_BIT_LMA,
-       LS3_JSON_ATTR_HSM = 1U << LS3_JSON_BIT_HSM,
-       LS3_JSON_ATTR_LOV = 1U << LS3_JSON_BIT_LOV,
-       LS3_JSON_ATTR_LMV = 1U << LS3_JSON_BIT_LMV,
-       LS3_JSON_ATTR_POOLS = 1U << LS3_JSON_BIT_POOLS,
-       LS3_JSON_ATTR_LINKS = 1U << LS3_JSON_BIT_LINKS,
-       LS3_JSON_ATTR_PATHS = 1U << LS3_JSON_BIT_PATHS,
-       LS3_JSON_ATTR_SOM = 1U << LS3_JSON_BIT_SOM,
-       LS3_JSON_ATTR_XATTRS = 1U << LS3_JSON_BIT_XATTRS,
-       LS3_JSON_ATTR_DEVICE_NAME = 1U << LS3_JSON_BIT_DEVICE_NAME,
-       LS3_JSON_ATTR_DEVICE_PATH = 1U << LS3_JSON_BIT_DEVICE_PATH,
+       LS3_JSON_ATTR_INO = BIT(LS3_JSON_BIT_INO),
+       LS3_JSON_ATTR_MODE = BIT(LS3_JSON_BIT_MODE),
+       LS3_JSON_ATTR_NLINK = BIT(LS3_JSON_BIT_NLINK),
+       LS3_JSON_ATTR_UID = BIT(LS3_JSON_BIT_UID),
+       LS3_JSON_ATTR_GID = BIT(LS3_JSON_BIT_GID),
+       LS3_JSON_ATTR_PROJID = BIT(LS3_JSON_BIT_PROJID),
+       LS3_JSON_ATTR_FLAGS = BIT(LS3_JSON_BIT_FLAGS),
+       LS3_JSON_ATTR_ATIME = BIT(LS3_JSON_BIT_ATIME),
+       LS3_JSON_ATTR_MTIME = BIT(LS3_JSON_BIT_MTIME),
+       LS3_JSON_ATTR_CTIME = BIT(LS3_JSON_BIT_CTIME),
+       LS3_JSON_ATTR_CRTIME = BIT(LS3_JSON_BIT_CRTIME),
+       LS3_JSON_ATTR_SIZE = BIT(LS3_JSON_BIT_SIZE),
+       LS3_JSON_ATTR_BLOCKS = BIT(LS3_JSON_BIT_BLOCKS),
+       LS3_JSON_ATTR_FILE_FID = BIT(LS3_JSON_BIT_FILE_FID),
+       LS3_JSON_ATTR_SELF_FID = BIT(LS3_JSON_BIT_SELF_FID),
+       LS3_JSON_ATTR_FILTER_FID = BIT(LS3_JSON_BIT_FILTER_FID),
+       LS3_JSON_ATTR_LMA = BIT(LS3_JSON_BIT_LMA),
+       LS3_JSON_ATTR_HSM = BIT(LS3_JSON_BIT_HSM),
+       LS3_JSON_ATTR_LOV = BIT(LS3_JSON_BIT_LOV),
+       LS3_JSON_ATTR_LMV = BIT(LS3_JSON_BIT_LMV),
+       LS3_JSON_ATTR_POOLS = BIT(LS3_JSON_BIT_POOLS),
+       LS3_JSON_ATTR_LINKS = BIT(LS3_JSON_BIT_LINKS),
+       LS3_JSON_ATTR_PATHS = BIT(LS3_JSON_BIT_PATHS),
+       LS3_JSON_ATTR_SOM = BIT(LS3_JSON_BIT_SOM),
+       LS3_JSON_ATTR_XATTRS = BIT(LS3_JSON_BIT_XATTRS),
+       LS3_JSON_ATTR_DEVICE_NAME = BIT(LS3_JSON_BIT_DEVICE_NAME),
+       LS3_JSON_ATTR_DEVICE_PATH = BIT(LS3_JSON_BIT_DEVICE_PATH),
 
        /* Print the fast and mostly correct attributes by default. */
        LS3_JSON_ATTR_DEFAULT =
index 08256ec..fe08362 100644 (file)
@@ -50,7 +50,8 @@ struct ls3_scan_control {
        size_t sc_thread_count;
        intmax_t sc_thread_rc_max;
        intmax_t sc_break_rc;
-       uintmax_t sc_read_attr_error_count;
+       uintmax_t sc_read_attr_error_count[LS3_OBJECT_ATTR_BIT_MAX];
+       uintmax_t sc_read_attr_error_count_total;
        uintmax_t sc_other_error_count;
 };
 
@@ -64,7 +65,7 @@ struct ls3_thread_info {
        unsigned long ti_group_start;
        unsigned long ti_group_current;
        unsigned long ti_group_end;
-       uintmax_t ti_read_attr_error_count;
+       uintmax_t ti_read_attr_error_count[LS3_OBJECT_ATTR_BIT_MAX];
        uintmax_t ti_other_error_count;
        int ti_started;
        int ti_should_stop; /* Use __ATOMIC_RELAXED. */
@@ -237,6 +238,18 @@ ldiskfs_read_attr_links(struct ls3_instance *li,
        size_t value_size = 0;
        int rc;
 
+       if (li->li_device_is_ost) {
+               /* No links xattr on OST */
+               return 0;
+       }
+
+       if (!li->li_device_is_mdt) {
+               LS3_ERROR_ONCE("cannot get links on device '%s' "
+                              "with unrecognized type\n",
+                              li->li_device_path);
+               return -EINVAL;
+       }
+
        assert(lipe_list_empty(&loa->loa_links));
 
        /* We use the link xattr plus caching to speed up paths but we
@@ -771,7 +784,7 @@ out:
                ext2fs_xattrs_close(&lo.u.lo_ldiskfs.lol_xattr_handle);
 
        lipe_object_attrs_fini(&loa);
-}
+} /* ls3_scan_inode */
 
 static int ldiskfs_scan_groups(ext2_inode_scan scan,
                               ext2_filsys fs,
@@ -1002,7 +1015,7 @@ static void ls3_scan_control_stop(struct ls3_scan_control *sc)
 static int ls3_scan_control_join(struct ls3_scan_control *sc)
 {
        int rc = 0;
-       int i;
+       int i, j;
 
        for (i = 0; i < sc->sc_thread_count; i++) {
                struct ls3_thread_info *ti = &sc->sc_thread_infos[i];
@@ -1028,7 +1041,13 @@ static int ls3_scan_control_join(struct ls3_scan_control *sc)
                if (sc->sc_thread_rc_max < imaxabs(thread_rc))
                        sc->sc_thread_rc_max = imaxabs(thread_rc);
 
-               sc->sc_read_attr_error_count += ti->ti_read_attr_error_count;
+               for (j = 0; j < ARRAY_SIZE(ti->ti_read_attr_error_count); j++) {
+                       sc->sc_read_attr_error_count[j] +=
+                               ti->ti_read_attr_error_count[j];
+                       sc->sc_read_attr_error_count_total +=
+                               ti->ti_read_attr_error_count[j];
+               }
+
                sc->sc_other_error_count += ti->ti_other_error_count;
        }
 
@@ -1048,6 +1067,7 @@ static intmax_t ls3_scan_fs(struct ls3_instance *li, ext2_filsys fs, size_t thre
                .sc_group_desc_count = fs->group_desc_count,
        };
        intmax_t rc, rc2;
+       enum ls3_object_attr_bit_pos pos;
 
        LS3_DEBUG_U(sc.sc_group_desc_count);
 
@@ -1078,12 +1098,18 @@ static intmax_t ls3_scan_fs(struct ls3_instance *li, ext2_filsys fs, size_t thre
 
        LS3_DEBUG_D(rc);
        LS3_DEBUG_D(sc.sc_thread_rc_max);
-       LS3_DEBUG_U(sc.sc_read_attr_error_count);
-       LS3_DEBUG_U(sc.sc_other_error_count);
 
-       if (sc.sc_read_attr_error_count > 0)
-               LS3_WARNING("device '%s': read attr error count %"PRIuMAX"\n",
-                           li->li_device_path, sc.sc_read_attr_error_count);
+       if (sc.sc_read_attr_error_count_total > 0) {
+               LS3_WARNING("device '%s': read attr error count %"PRIuMAX" :\n",
+                           li->li_device_path, sc.sc_read_attr_error_count_total);
+
+               for (pos = 0; pos < ARRAY_SIZE(sc.sc_read_attr_error_count); pos++) {
+                       if (sc.sc_read_attr_error_count[pos] != 0)
+                               LS3_WARNING("    '%s'\t: %"PRIuMAX"\n",
+                                           ls3_object_attr_bit_pos2str(pos),
+                                           (uintmax_t)(sc.sc_read_attr_error_count[pos]));
+               }
+       }
 
        if (sc.sc_other_error_count > 0)
                LS3_WARNING("device '%s': other error count %"PRIuMAX"\n",
@@ -1389,7 +1415,42 @@ SCM ls3_policy_exception_handler(SCM key, SCM args)
                return SCM_BOOL_T;
 
        if (scm_is_eq(key, ls3_sym_read_attr_error)) {
-               ti->ti_read_attr_error_count++;
+               size_t len, i;
+               unsigned long bits;
+
+               const SCM vector = scm_make_vector(scm_length(args), SCM_UNDEFINED);
+
+               len = scm_c_vector_length(vector);
+               for (i = 0; i < len && scm_is_pair(args); i++) {
+                       scm_c_vector_set_x(vector, i, scm_car(args));
+                       args = scm_cdr(args);
+               }
+
+               bits = scm_to_ulong(SCM_SIMPLE_VECTOR_REF(vector, 1));
+
+               bits &= LS3_OBJECT_ATTR_ALL;
+
+               while (bits) {
+                       enum ls3_object_attr_bit_pos pos = __builtin_ffsl(bits)-1;
+
+                       ti->ti_read_attr_error_count[pos]++;
+
+                       /* Report each get attribute warning only when enabled */
+                       if (ls3_warn_get_attr) {
+                               int64_t loa_ino =
+                                       scm_to_ulong(SCM_SIMPLE_VECTOR_REF(vector, 0));
+                               int error =
+                                       scm_to_int(SCM_SIMPLE_VECTOR_REF(vector, 2));
+
+                               LS3_WARNING("read attr error: ino: %llu, "
+                                           "attr: '%s', error: %d\n",
+                                           (unsigned long long int)loa_ino,
+                                           ls3_object_attr_bit_pos2str(pos),
+                                           error);
+                       }
+
+                       bits &= ~(1UL << pos);
+               }
        } else if (scm_is_eq(key, ls3_sym_scan_break)) {
                struct ls3_scan_control *sc = ti->ti_scan_control;
                SCM rc;
index 446ea9a..4de0ab9 100644 (file)
@@ -7,6 +7,13 @@
 (assert (eq? #t (lipe-debug-enable #f)))
 (assert (eq? #f (lipe-debug-enable)))
 
+(assert (procedure? lipe-warnings-get-attr-enable))
+(assert (eq? #f (lipe-warnings-get-attr-enable)))
+(assert (eq? #f (lipe-warnings-get-attr-enable #t)))
+(assert (eq? #t (lipe-warnings-get-attr-enable)))
+(assert (eq? #t (lipe-warnings-get-attr-enable #f)))
+(assert (eq? #f (lipe-warnings-get-attr-enable)))
+
 (assert (procedure? lipe-gettid))
 (assert (integer? (lipe-gettid)))
 (assert (positive? (lipe-gettid)))