Whamcloud - gitweb
EX-4015 lipe: implement lazy size and blocks
authorJohn L. Hammond <jhammond@whamcloud.com>
Fri, 4 Mar 2022 14:17:48 +0000 (08:17 -0600)
committerJohn L. Hammond <jhammond@whamcloud.com>
Thu, 10 Mar 2022 21:38:06 +0000 (21:38 +0000)
If the current file is an OST object or not a regular file then we use
the size and blocks values from the inode. (But this is wrong for
striped directories.) If the current file is an regular MDT inode then
we check for strict or lazy SOM, followed by HSM released, followed by
unstriped.

Rename loa_attr_bits to loa_valid. Add new fields loa_noattr and
loa_error to distinguish among the cases of xattrs we haven't tried to
read, xattrs which are not set, and xattrs which could not be read (or
parsed).

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: I5b197dd7989a3f618c97c9025a4bd534dfe86152
Reviewed-on: https://review.whamcloud.com/46698
Tested-by: jenkins <devops@whamcloud.com>
lipe/src/lipe_scan3/ls3_main.c
lipe/src/lipe_scan3/ls3_object_attrs.c
lipe/src/lipe_scan3/ls3_object_attrs.h
lipe/src/lipe_scan3/ls3_scan.c
lustre/tests/sanity-lipe-scan3.sh

index 6f365fc..3994c35 100644 (file)
@@ -478,7 +478,7 @@ static struct ls3_object_attrs *ls3_attrs_try(enum ls3_object_attr_bit bits)
 
        bits &= LS3_OBJECT_ATTR_ALL;
 
-       if ((loa->loa_attr_bits & bits) == bits)
+       if ((loa->loa_valid & bits) == bits)
                return loa;
 
        ls3_read_attrs(ls3_current()->lc_instance, ls3_current()->lc_object,
@@ -497,7 +497,7 @@ static struct ls3_object_attrs *ls3_attrs(enum ls3_object_attr_bit bits)
 
        bits &= LS3_OBJECT_ATTR_ALL;
 
-       if ((loa->loa_attr_bits & bits) == bits)
+       if ((loa->loa_valid & bits) == bits)
                return loa;
 
        errno = 0;
@@ -510,7 +510,7 @@ static struct ls3_object_attrs *ls3_attrs(enum ls3_object_attr_bit bits)
                ls3_throw_read_attr_error(bits, rc);
 
        assert(rc == 0);
-       assert((loa->loa_attr_bits & bits) == bits);
+       assert((loa->loa_valid & bits) == bits);
 
        return loa;
 }
@@ -520,7 +520,7 @@ SCM_DEFINE(ls3_scm_current_attrs, "lipe-scan-current-attrs", 0, 0, 0,
 {
        struct ls3_object_attrs *loa = ls3_attrs(0);
 
-       return scm_from_ulong(loa->loa_attr_bits);
+       return scm_from_ulong(loa->loa_valid);
 }
 
 #define LS3_DEF_ATTR_U(name, member)                                   \
@@ -538,7 +538,6 @@ SCM_DEFINE(ls3_scm_current_attrs, "lipe-scan-current-attrs", 0, 0, 0,
        }
 
 LS3_DEF_ATTR_U("atime", atime);
-LS3_DEF_ATTR_U("blocks", blocks); /* 512B blocks */
 LS3_DEF_ATTR_U("ctime", ctime);
 LS3_DEF_ATTR_U("crtime", crtime);
 LS3_DEF_ATTR_U("flags", flags);
@@ -548,9 +547,27 @@ LS3_DEF_ATTR_U("mode", mode);
 LS3_DEF_ATTR_U("mtime", mtime);
 LS3_DEF_ATTR_U("nlink", nlink);
 LS3_DEF_ATTR_U("projid", projid);
-LS3_DEF_ATTR_U("size", size);
 LS3_DEF_ATTR_U("uid", uid);
 
+SCM_DEFINE(ls3_scm_attr_size, "size", 0, 0, 0, (),
+          "return size of current file")
+{
+       struct ls3_object_attrs *loa = ls3_attrs(LS3_OBJECT_ATTR_SIZE);
+       /* TODO Add an optional argument to control strictness,
+        * laziness, truthiness... */
+
+       return scm_from_uintmax(loa->loa_size);
+}
+
+SCM_DEFINE(ls3_scm_attr_blocks, "blocks", 0, 0, 0, (),
+          "return block count of current file")
+{
+       struct ls3_object_attrs *loa = ls3_attrs(LS3_OBJECT_ATTR_SIZE);
+       /* We use _SIZE for blocks too. */
+
+       return scm_from_uintmax(loa->loa_blocks); /* 512B blocks. */
+}
+
 SCM_DEFINE(ls3_scm_file_fid_ref, "file-fid", 0, 0, 0, (), "return FID of current file")
 {
        struct ls3_object_attrs *loa = ls3_attrs(LS3_OBJECT_ATTR_FILE_FID);
@@ -724,12 +741,10 @@ SCM_DEFINE(ls3_scm_lov_mirror_count, "lov-mirror-count", 0, 0, 0,
        int rc;
 
        /* TODO Distinguish between missing xattr and other error. */
-       if (!(loa->loa_attr_bits & LS3_OBJECT_ATTR_LOV))
+       if (loa->loa_layout == NULL)
                return scm_from_int(0);
 
        /* XXX llapi_layout_*() functions return -1 on error and set errno. */
-       assert(loa->loa_layout != NULL);
-
        rc = llapi_layout_mirror_count_get(loa->loa_layout, &count);
        if (rc < 0)
                ls3_throw_read_attr_error(LS3_OBJECT_ATTR_LOV,
@@ -746,12 +761,10 @@ SCM_DEFINE(ls3_scm_lov_stripe_count, "lov-stripe-count", 0, 0, 0,
        int rc;
 
        /* TODO Distinguish between missing xattr and other error. */
-       if (!(loa->loa_attr_bits & LS3_OBJECT_ATTR_LOV))
+       if (loa->loa_layout == NULL)
                return scm_from_int(0);
 
        /* XXX llapi_layout_*() functions return -1 on error and set errno. */
-       assert(loa->loa_layout != NULL);
-
        rc = llapi_layout_get_last_init_comp(loa->loa_layout);
        if (rc < 0)
                goto out;
@@ -775,13 +788,12 @@ SCM_DEFINE(ls3_scm_lov_pools_list, "lov-pools", 0, 0, 0,
        int rc;
 
        /* TODO Distinguish between missing xattr and other error. */
-       if (!(loa->loa_attr_bits & LS3_OBJECT_ATTR_LOV))
+       if (loa->loa_layout == NULL)
                return SCM_EOL;
 
-       /* XXX llapi_layout_*() functions return -1 on error and set errno. */
-       assert(loa->loa_layout != NULL);
        ll = loa->loa_layout;
 
+       /* XXX llapi_layout_*() functions return -1 on error and set errno. */
        rc = llapi_layout_comp_use(ll, LLAPI_LAYOUT_COMP_USE_LAST);
        if (rc < 0)
                goto out;
@@ -817,13 +829,12 @@ SCM_DEFINE(ls3_scm_lov_ost_indexes_list, "lov-ost-indexes", 0, 0, 0,
        int rc;
 
        /* TODO Distinguish between missing xattr and other error. */
-       if (!(loa->loa_attr_bits & LS3_OBJECT_ATTR_LOV))
+       if (loa->loa_layout == NULL)
                return SCM_EOL;
 
-       /* XXX llapi_layout_*() functions return -1 on error and set errno. */
-       assert(loa->loa_layout != NULL);
        ll = loa->loa_layout;
 
+       /* XXX llapi_layout_*() functions return -1 on error and set errno. */
        rc = llapi_layout_comp_use(ll, LLAPI_LAYOUT_COMP_USE_LAST);
        if (rc < 0)
                goto out;
index ff1e39b..b3b4994 100644 (file)
@@ -472,7 +472,7 @@ ls3_object_attrs_to_json(struct ls3_instance *li,
 
                rc = ls3_read_attrs(li, lo, loa, jad->jad_attr_bits, true /* quit_on_error */);
 
-               if (rc < 0 || jad->jad_attr_bits != (jad->jad_attr_bits & loa->loa_attr_bits)) {
+               if (rc < 0 || jad->jad_attr_bits != (jad->jad_attr_bits & loa->loa_valid)) {
                        if (is_required)
                                goto out;
                        else
@@ -532,7 +532,9 @@ static void lipe_object_attrs_xattrs_fini(struct ls3_object_attrs *attrs)
 
 void lipe_object_attrs_reset(struct ls3_object_attrs *loa)
 {
-       loa->loa_attr_bits = 0;
+       loa->loa_valid = 0;
+       loa->loa_nodata = 0;
+       loa->loa_error = 0;
        loa->loa_ino = 0;
        memset(&loa->loa_file_fid, 0, sizeof(loa->loa_file_fid));
        memset(&loa->loa_lma, 0, sizeof(loa->loa_lma));
@@ -655,8 +657,6 @@ int lipe_object_attrs_set_links(struct ls3_object_attrs *attrs,
                return -EOVERFLOW;
        }
 
-       attrs->loa_attr_bits |= LS3_OBJECT_ATTR_LINKS;
-
        return 0;
 }
 
@@ -707,7 +707,7 @@ int lipe_object_attrs_set_paths(struct ls3_object_attrs *loa,
                goto out;
        }
 
-       if (!(loa->loa_attr_bits & LS3_OBJECT_ATTR_FILE_FID)) {
+       if (!(loa->loa_valid & LS3_OBJECT_ATTR_FILE_FID)) {
                rc = -EINVAL;
                goto out;
        }
@@ -742,8 +742,6 @@ int lipe_object_attrs_set_paths(struct ls3_object_attrs *loa,
 
                linkno = gf->gf_linkno;
        }
-
-       loa->loa_attr_bits |= LS3_OBJECT_ATTR_PATHS;
 out:
        free(gf);
 
index 1e1ab5e..7c87014 100644 (file)
@@ -154,15 +154,17 @@ struct lipe_xattr {
 };
 
 struct ls3_object_attrs {
-       enum ls3_object_attr_bit loa_attr_bits;
+       enum ls3_object_attr_bit loa_valid;
+       enum ls3_object_attr_bit loa_nodata;
+       enum ls3_object_attr_bit loa_error;
        int64_t                  loa_ino;
        int64_t                  loa_atime;
        int64_t                  loa_mtime;
        int64_t                  loa_ctime;
        int64_t                  loa_crtime;
-       int64_t                  loa_size;
+       int64_t                  loa_i_size; /* from inode, LS3_OBJECT_ATTR_BASE */
+       int64_t                  loa_i_blocks; /* from inode, number of 512B blocks. */
        int64_t                  loa_mode;
-       int64_t                  loa_blocks; /* number of 512B blocks. */
        int64_t                  loa_flags;
        int64_t                  loa_nlink;
        uid_t                    loa_uid;
@@ -179,6 +181,10 @@ struct ls3_object_attrs {
        struct llapi_layout     *loa_layout; /* LS3_OBJECT_ATTR_LOV */
        struct hsm_user_state    loa_hsm_state;
        struct lustre_som_attrs  loa_som;
+
+       int64_t                  loa_size; /* LS3_OBJECT_ATTR_SIZE */
+       int64_t                  loa_blocks; /* number of 512B blocks */
+
        /* The entry number. If inode is not directory, value is zero */
        int64_t                  loa_entries;
        /*
index 3a593a6..f20ed6d 100644 (file)
@@ -135,9 +135,6 @@ ldiskfs_read_attr_self_fid(struct ls3_instance *li,
        int size;
        int rc;
 
-       if (loa->loa_attr_bits & LS3_OBJECT_ATTR_SELF_FID)
-               return 0;
-
        rc = ldiskfs_trusted_xattr_get(lo, XATTR_NAME_LMA, buf, sizeof(buf), &size);
        if (rc < 0)
                return rc;
@@ -147,8 +144,6 @@ ldiskfs_read_attr_self_fid(struct ls3_instance *li,
        loa->loa_lma.lma_compat = ext2fs_le32_to_cpu(lma->lma_compat);
        loa->loa_lma.lma_incompat = ext2fs_le32_to_cpu(lma->lma_incompat);
 
-       loa->loa_attr_bits |= LS3_OBJECT_ATTR_SELF_FID;
-
        return 0;
 }
 
@@ -162,9 +157,6 @@ ldiskfs_read_attr_filter_fid(struct ls3_instance *li,
        int size;
        int rc;
 
-       if (loa->loa_attr_bits & LS3_OBJECT_ATTR_FILTER_FID)
-               return 0;
-
        rc = ldiskfs_trusted_xattr_get(lo, XATTR_NAME_FID, ff, sizeof(*ff), &size);
        if (rc < 0)
                return rc;
@@ -173,8 +165,6 @@ ldiskfs_read_attr_filter_fid(struct ls3_instance *li,
        ff->ff_parent = pfid;
        loa->loa_filter_fid_size = size;
 
-       loa->loa_attr_bits |= LS3_OBJECT_ATTR_FILTER_FID;
-
        return 0;
 }
 
@@ -185,17 +175,14 @@ ldiskfs_read_attr_file_fid(struct ls3_instance *li,
 {
        int rc;
 
-       if (loa->loa_attr_bits & LS3_OBJECT_ATTR_FILE_FID)
-               return 0;
-
        if (li->li_device_is_mdt) {
-               rc = ldiskfs_read_attr_self_fid(li, lo, loa);
+               rc = ls3_read_attrs(li, lo, loa, LS3_OBJECT_ATTR_SELF_FID, 1);
                if (rc < 0)
                        return rc;
 
                loa->loa_file_fid = *loa_self_fid(loa);
        } else if (li->li_device_is_ost) {
-               rc = ldiskfs_read_attr_filter_fid(li, lo, loa);
+               rc = ls3_read_attrs(li, lo, loa, LS3_OBJECT_ATTR_FILTER_FID, 1);
                if (rc < 0)
                        return rc;
 
@@ -207,8 +194,6 @@ ldiskfs_read_attr_file_fid(struct ls3_instance *li,
                return -EINVAL;
        }
 
-       loa->loa_attr_bits |= LS3_OBJECT_ATTR_FILE_FID;
-
        return 0;
 }
 
@@ -220,9 +205,6 @@ ldiskfs_read_attr_links(struct ls3_instance *li,
        int size;
        int rc;
 
-       if (loa->loa_attr_bits & LS3_OBJECT_ATTR_LINKS)
-               return 0;
-
        assert(lipe_list_empty(&loa->loa_links));
 
        /* We use the link xattr plus caching to speed up paths but we
@@ -230,7 +212,7 @@ ldiskfs_read_attr_links(struct ls3_instance *li,
         * properly after unlink. This is why we test
         * LMAI_ORPHAN. */
 
-       rc = ldiskfs_read_attr_self_fid(li, lo, loa);
+       rc = ls3_read_attrs(li, lo, loa, LS3_OBJECT_ATTR_SELF_FID, 1);
        if (rc < 0)
                return rc;
 
@@ -250,8 +232,6 @@ ldiskfs_read_attr_links(struct ls3_instance *li,
                return rc;
        }
 out_ok:
-       loa->loa_attr_bits |= LS3_OBJECT_ATTR_LINKS;
-
        return 0;
 }
 
@@ -277,13 +257,10 @@ ldiskfs_read_attr_paths(struct ls3_instance *li,
        struct lipe_link_entry *lle;
        int rc;
 
-       if (loa->loa_attr_bits & LS3_OBJECT_ATTR_PATHS)
-               return 0;
-
        assert(lipe_list_empty(&loa->loa_paths));
 
        if (li->li_device_is_ost) {
-               rc = ldiskfs_read_attr_file_fid(li, lo, loa);
+               rc = ls3_read_attrs(li, lo, loa, LS3_OBJECT_ATTR_FILE_FID, 1);
                if (rc < 0)
                        return rc;
 
@@ -293,7 +270,7 @@ ldiskfs_read_attr_paths(struct ls3_instance *li,
        /* Requiring a link xattr before fid2path prevents MDT crashes
         * when we pass fids of OI_scrub or other internal files. */
 
-       rc = ldiskfs_read_attr_links(li, lo, loa);
+       rc = ls3_read_attrs(li, lo, loa, LS3_OBJECT_ATTR_LINKS, 1);
        if (rc < 0)
                return rc;
 
@@ -328,8 +305,6 @@ ldiskfs_read_attr_paths(struct ls3_instance *li,
                return rc;
        }
 out_ok:
-       loa->loa_attr_bits |= LS3_OBJECT_ATTR_PATHS;
-
        return 0;
 }
 
@@ -350,9 +325,6 @@ static int ldiskfs_read_attr_xattrs(struct ls3_instance *li,
        struct ext2_xattr_handle *handle = NULL;
        errcode_t rc;
 
-       if (loa->loa_attr_bits & LS3_OBJECT_ATTR_XATTRS)
-               return 0;
-
        rc = ext2fs_xattrs_open(fs, ino, &handle);
        if (rc) {
                LS3_ERROR_OBJ(lo, "cannot open xattrs: rc = %ld\n", rc);
@@ -371,7 +343,6 @@ static int ldiskfs_read_attr_xattrs(struct ls3_instance *li,
                goto out_close;
        }
 
-       loa->loa_attr_bits |= LS3_OBJECT_ATTR_XATTRS;
 out_close:
        ext2fs_xattrs_close(&handle);
 
@@ -386,9 +357,6 @@ static int ldiskfs_read_attr_lov(struct ls3_instance *li,
        int size;
        int rc;
 
-       if (loa->loa_attr_bits & LS3_OBJECT_ATTR_LOV)
-               return 0;
-
        rc = ldiskfs_trusted_xattr_get(lo, XATTR_NAME_LOV, lum, loa->loa_lum_size, &size);
        if (rc < 0)
                goto out;
@@ -400,8 +368,6 @@ static int ldiskfs_read_attr_lov(struct ls3_instance *li,
                rc = -errno;
                goto out;
        }
-
-       loa->loa_attr_bits |= LS3_OBJECT_ATTR_LOV;
 out:
        return rc;
 }
@@ -413,9 +379,6 @@ static int ldiskfs_read_attr_lmv(struct ls3_instance *li,
        int size;
        int rc;
 
-       if (loa->loa_attr_bits & LS3_OBJECT_ATTR_LMV)
-               return 0;
-
        rc = ldiskfs_trusted_xattr_get(lo, XATTR_NAME_LMV,
                                       loa->loa_lmv_buf, loa->loa_lmv_buf_size, &size);
        if (rc < 0)
@@ -423,8 +386,6 @@ static int ldiskfs_read_attr_lmv(struct ls3_instance *li,
 
        /* TODO Store and check size. */
 
-       loa->loa_attr_bits |= LS3_OBJECT_ATTR_LMV;
-
        return 0;
 }
 
@@ -454,9 +415,6 @@ static int ldiskfs_read_attr_hsm(struct ls3_instance *li,
        int size;
        int rc;
 
-       if (loa->loa_attr_bits & LS3_OBJECT_ATTR_HSM)
-               return 0;
-
        assert(sizeof(*hsm) < XATTR_SIZE_MAX);
 
        rc = ldiskfs_trusted_xattr_get(lo, XATTR_NAME_HSM, buf, sizeof(buf), &size);
@@ -467,8 +425,6 @@ static int ldiskfs_read_attr_hsm(struct ls3_instance *li,
        hus->hus_states = ext2fs_le32_to_cpu(hsm->hsm_flags);
        hus->hus_archive_id = ext2fs_le64_to_cpu(hsm->hsm_arch_id);
 
-       loa->loa_attr_bits |= LS3_OBJECT_ATTR_HSM;
-
        return 0;
 }
 
@@ -480,9 +436,6 @@ static int ldiskfs_read_attr_som(struct ls3_instance *li,
        int size;
        int rc;
 
-       if (loa->loa_attr_bits & LS3_OBJECT_ATTR_SOM)
-               return 0;
-
        rc = ldiskfs_trusted_xattr_get(lo, XATTR_NAME_SOM, som, sizeof(*som), &size);
        if (rc < 0)
                return rc;
@@ -499,13 +452,8 @@ static int ldiskfs_read_attr_som(struct ls3_instance *li,
 
        switch (loa->loa_som.lsa_valid) {
        case SOM_FL_STRICT:
-               loa->loa_size = som->lsa_size;
-               loa->loa_blocks = som->lsa_blocks;
-               loa->loa_attr_bits |= LS3_OBJECT_ATTR_SIZE;
-               /* fallthrough */
        case SOM_FL_STALE:
        case SOM_FL_LAZY:
-               loa->loa_attr_bits |= LS3_OBJECT_ATTR_SOM;
                rc = 0;
                break;
        default:
@@ -520,36 +468,51 @@ static int ldiskfs_read_attr_size(struct ls3_instance *li,
                                  struct lipe_object *lo,
                                  struct ls3_object_attrs *loa)
 {
-       if (loa->loa_attr_bits & LS3_OBJECT_ATTR_SIZE)
-               return 0;
+       /* This function is responsible for reading size and blocks
+        * attrs. If the current file is an OST object or not a
+        * regular file then we use the size and blocks values from
+        * the inode. (But this is wrong for striped directories.) If
+        * the current file is an regular MDT inode then we check for
+        * strict or lazy SOM, followed by HSM released, followed by
+        * unstriped. */
 
-       assert(loa->loa_attr_bits & LS3_OBJECT_ATTR_BASE);
+       assert(loa->loa_valid & LS3_OBJECT_ATTR_BASE);
 
-       if (!S_ISREG(loa->loa_mode)) {
+       if (li->li_device_is_ost || !S_ISREG(loa->loa_mode)) {
                /* FIXME This is wrong for striped directories. */
-               loa->loa_attr_bits |= LS3_OBJECT_ATTR_SIZE;
+use_i_size:
+               loa->loa_size = loa->loa_i_size;
+               loa->loa_blocks = loa->loa_i_blocks;
                return 0;
        }
 
-       ldiskfs_read_attr_som(li, lo, loa);
+       ls3_read_attrs(li, lo, loa, LS3_OBJECT_ATTR_SOM, 1);
 
-       if (loa->loa_attr_bits & LS3_OBJECT_ATTR_SIZE)
+       if (loa->loa_valid & LS3_OBJECT_ATTR_SOM &&
+           loa->loa_som.lsa_valid & (SOM_FL_STRICT | SOM_FL_LAZY)) {
+               loa->loa_size = loa->loa_som.lsa_size;
+               loa->loa_blocks = loa->loa_som.lsa_blocks;
                return 0;
+       }
+
+       ls3_read_attrs(li, lo, loa, LS3_OBJECT_ATTR_HSM, 1);
+
+       if (loa->loa_valid & LS3_OBJECT_ATTR_HSM &&
+           loa->loa_hsm_state.hus_states & HS_RELEASED)
+               goto use_i_size;
+
+       ls3_read_attrs(li, lo, loa, LS3_OBJECT_ATTR_LOV, 1);
+
+       if (loa->loa_nodata & LS3_OBJECT_ATTR_LOV)
+               goto use_i_size; /* Striping is not set. */
 
        /* Try stat? */
 
        return -ENODATA;
 }
 
-static bool ls3_need_read_attr(const struct ls3_object_attrs *loa,
-                               enum ls3_object_attr_bit need_bits,
-                               enum ls3_object_attr_bit bit)
-{
-       return ~loa->loa_attr_bits & need_bits & bit;
-}
-
 static const struct {
-       unsigned int r_bit;
+       unsigned int r_flag;
        int (*r_read)(struct ls3_instance *,
                      struct lipe_object *,
                      struct ls3_object_attrs *);
@@ -570,26 +533,55 @@ static const struct {
 int ls3_read_attrs(struct ls3_instance *li,
                   struct lipe_object *lo,
                   struct ls3_object_attrs *loa,
-                  enum ls3_object_attr_bit need_bits,
+                  enum ls3_object_attr_bit need,
                   bool quit_on_error)
 {
        int rc = 0;
        size_t i;
 
        for (i = 0; i < ARRAY_SIZE(ls3_ldiskfs_attr_readers); i++) {
-               if (ls3_need_read_attr(loa, need_bits, ls3_ldiskfs_attr_readers[i].r_bit)) {
-                       int rc2 = (*ls3_ldiskfs_attr_readers[i].r_read)(li, lo, loa);
-                       if (rc2 != 0) {
-                               if (quit_on_error)
-                                       return rc2;
-
-                               if (rc == 0)
-                                       rc = rc2;
-                       }
+               unsigned int flag = ls3_ldiskfs_attr_readers[i].r_flag;
+               int rc2;
+
+               if (!(need & flag))
+                       continue;
+
+               if (loa->loa_valid & flag)
+                       continue;
+
+               if (loa->loa_nodata & flag) {
+                       rc2 = -ENODATA;
+                       goto skip_read;
+               }
+
+               if (loa->loa_error & flag) {
+                       rc2 = -EIO;
+                       goto skip_read;
+               }
+
+               rc2 = (*ls3_ldiskfs_attr_readers[i].r_read)(li, lo, loa);
+               switch (rc2) {
+               case 0:
+                       loa->loa_valid |= flag;
+                       break;
+               case -ENODATA:
+                       loa->loa_nodata |= flag;
+                       break;
+               default:
+                       loa->loa_error |= flag;
+                       break;
+               }
+skip_read:
+               if (rc2 != 0) {
+                       if (quit_on_error)
+                               return rc2;
+
+                       if (rc == 0)
+                               rc = rc2;
                }
        }
 
-       assert((need_bits & loa->loa_attr_bits) == need_bits || rc < 0);
+       assert((need & loa->loa_valid) == need || rc < 0);
 
        return rc;
 }
@@ -647,16 +639,16 @@ static void ldiskfs_copy_inode_attrs(ext2_filsys fs,
        loa->loa_mtime = inode_time(inode->i_mtime, inode->i_mtime_extra);
        loa->loa_ctime = inode_time(inode->i_ctime, inode->i_ctime_extra);
        loa->loa_crtime = inode_time(inode->i_crtime, inode->i_crtime_extra);
-       loa->loa_size = EXT2_I_SIZE(inode);
+       loa->loa_i_size = EXT2_I_SIZE(inode);
        loa->loa_mode = inode->i_mode; /* __u16 */
        loa->loa_uid = inode_uid(*inode);
        loa->loa_gid = inode_gid(*inode);
        loa->loa_flags = inode->i_flags; /* __u32 */
        loa->loa_nlink = inode->i_links_count; /* __u16 */
-       loa->loa_blocks = blocks_from_inode(fs, inode);
+       loa->loa_i_blocks = blocks_from_inode(fs, inode);
        loa->loa_projid = inode_projid(*inode);
 
-       loa->loa_attr_bits = LS3_OBJECT_ATTR_BASE | LS3_OBJECT_ATTR_PROJID;
+       loa->loa_valid = LS3_OBJECT_ATTR_BASE | LS3_OBJECT_ATTR_PROJID;
 }
 
 static int ldiskfs_scan_groups(ext2_inode_scan scan,
@@ -717,12 +709,18 @@ static int ldiskfs_scan_groups(ext2_inode_scan scan,
                rc2 = ls3_read_attrs(li, lo, loa, li->li_required_attrs,
                                     true /* quit on error. */);
                if (rc2 != 0) {
-                       LS3_DEBUG_OBJ(lo, "missing required attrs %#"PRIxMAX"\n",
-                                     (uintmax_t)(li->li_required_attrs & ~loa->loa_attr_bits));
+                       LS3_DEBUG_OBJ(lo, "missing required attrs %#"PRIxMAX", have "
+                                     "valid %#"PRIxMAX", "
+                                     "nodata %#"PRIxMAX", "
+                                     "error %#"PRIxMAX"\n",
+                                     (uintmax_t)(li->li_required_attrs & ~loa->loa_valid),
+                                     (uintmax_t)(loa->loa_valid),
+                                     (uintmax_t)(loa->loa_nodata),
+                                     (uintmax_t)(loa->loa_error));
                        continue;
                }
 
-               assert((loa->loa_attr_bits & li->li_required_attrs) ==
+               assert((loa->loa_valid & li->li_required_attrs) ==
                       li->li_required_attrs);
 
                /* Requiring fid_is_norm() prevents us from returning
index 33e0d7a..7b6d6ee 100644 (file)
@@ -466,17 +466,63 @@ test_104() {
        local device="$(facet_device $facet)"
        local file=$MOUNT/$tfile
        local size
+       local som_size
+       local som_blocks
+       local som_flags
+       local stat_size
+       local stat_blocks
 
        init_lipe_scan3_env "$file"
 
        expect_attr "$device" size 0
 
+       # For a file without striping, the MDT inode has the szie.
        for size in "${SIZES[@]}"; do
                $TRUNCATE $file "$size"
                expect_attr "$device" size "$size"
        done
 
        expect_attr "$device" blocks 0
+
+       params=$($LCTL get_param 'llite.*.xattr_cache')
+       $LCTL set_param 'llite.*.xattr_cache=0'
+       stack_trap "$LCTL set_param $params"
+
+       dd if=/dev/urandom of="$file" bs=512 count=10
+       sync
+
+       $LFS getsom "$file"
+
+       # For a regular file, lipe_scan3 size and blocks are as good
+       # as the SoM implementation.
+       som_size=$($LFS getsom -s "$file")
+       som_blocks=$($LFS getsom -b "$file")
+       som_flags=$($LFS getsom -f "$file")
+       ((som_flags == 4)) || error "expected som flags 4, got '$som_flags'"
+       expect_attr "$device" size "$som_size"
+       expect_attr "$device" blocks "$som_blocks"
+       rm "$file"
+
+       $LFS mkdir -i0 -c1 "$file"
+       stat_size=$(stat --format=%s "$file")
+       stat_blocks=$(stat --format=%b "$file")
+       expect_attr "$device" size "$stat_size"
+       expect_attr "$device" blocks "$stat_blocks"
+       rmdir "$file"
+
+       ln -s /dev/null "$file"
+       stat_size=$(stat --format=%s "$file")
+       stat_blocks=$(stat --format=%b "$file")
+       expect_attr "$device" size "$stat_size"
+       expect_attr "$device" blocks "$stat_blocks"
+       rm "$file"
+
+       mkfifo "$file"
+       stat_size=$(stat --format=%s "$file")
+       stat_blocks=$(stat --format=%b "$file")
+       expect_attr "$device" size "$stat_size"
+       expect_attr "$device" blocks "$stat_blocks"
+       rm "$file"
 }
 run_test 104 "lipe_scan3 size/blocks do the right thing"