Whamcloud - gitweb
EX-4965 lipe: use new e2fsprogs xattr API in lipe_scan3
authorJohn L. Hammond <jhammond@whamcloud.com>
Mon, 21 Mar 2022 15:40:43 +0000 (10:40 -0500)
committerJohn L. Hammond <jhammond@whamcloud.com>
Wed, 23 Mar 2022 13:25:41 +0000 (13:25 +0000)
In lipe_scan3, switch to the ext2fs_xattr_handle API since this
handles xattrs stored in a separate file. Update sanity-lipe-scan3
test_108() to verify.

Test-Parameters: trivial testlist=sanity-lipe-find3
Test-Parameters: trivial testlist=sanity-lipe-scan3
Signed-off-by: John L. Hammond <jhammond@whamcloud.com>
Change-Id: I307d78ba03c6612e5787f71a4682c0af5b23f1c5
Reviewed-on: https://review.whamcloud.com/46875
Tested-by: jenkins <devops@whamcloud.com>
lipe/src/lipe_scan3/ls3_object_attrs.c
lipe/src/lipe_scan3/ls3_object_attrs.h
lipe/src/lipe_scan3/ls3_scan.c
lipe/src/lipe_scan3/ls3_scan.h
lustre/tests/sanity-lipe-scan3.sh

index b3b4994..6d21b8a 100644 (file)
@@ -530,34 +530,9 @@ static void lipe_object_attrs_xattrs_fini(struct ls3_object_attrs *attrs)
        assert(lipe_list_empty(&attrs->loa_xattrs));
 }
 
-void lipe_object_attrs_reset(struct ls3_object_attrs *loa)
-{
-       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));
-       lipe_object_attrs_links_fini(loa);
-       lipe_object_attrs_paths_fini(loa);
-       lipe_object_attrs_xattrs_fini(loa);
-       llapi_layout_free(loa->loa_layout);
-       loa->loa_layout = NULL;
-}
-
 int lipe_object_attrs_init(struct ls3_object_attrs *loa)
 {
        memset(loa, 0, sizeof(*loa));
-       loa->loa_lum_size = lov_user_md_size(LOV_MAX_STRIPE_COUNT,
-                                            LOV_USER_MAGIC_V3);
-       loa->loa_lum = xmalloc(loa->loa_lum_size);
-
-       loa->loa_link_buf_size = XATTR_SIZE_MAX;
-       loa->loa_link_buf = xmalloc(loa->loa_link_buf_size);
-
-       loa->loa_lmv_buf_size = XATTR_SIZE_MAX;
-       loa->loa_lmv_buf = xmalloc(loa->loa_lmv_buf_size);
-
        LIPE_INIT_LIST_HEAD(&loa->loa_links);
        LIPE_INIT_LIST_HEAD(&loa->loa_paths);
        LIPE_INIT_LIST_HEAD(&loa->loa_xattrs);
@@ -570,9 +545,7 @@ void lipe_object_attrs_fini(struct ls3_object_attrs *loa)
        lipe_object_attrs_links_fini(loa);
        lipe_object_attrs_paths_fini(loa);
        lipe_object_attrs_xattrs_fini(loa);
-       free(loa->loa_lum);
-       free(loa->loa_link_buf);
-       free(loa->loa_lmv_buf);
+       free(loa->loa_lmv);
        llapi_layout_free(loa->loa_layout);
 }
 
index 7c87014..8edd54c 100644 (file)
@@ -172,12 +172,8 @@ struct ls3_object_attrs {
        int64_t                  loa_projid;
        struct lu_fid            loa_file_fid;
        struct lustre_mdt_attrs  loa_lma;
-       void                    *loa_link_buf;
-       size_t                   loa_link_buf_size;
-       void                    *loa_lmv_buf;
-       size_t                   loa_lmv_buf_size;
-       struct lov_user_md      *loa_lum;
-       int                      loa_lum_size;
+       void                    *loa_lmv;
+       size_t                   loa_lmv_size;
        struct llapi_layout     *loa_layout; /* LS3_OBJECT_ATTR_LOV */
        struct hsm_user_state    loa_hsm_state;
        struct lustre_som_attrs  loa_som;
@@ -231,7 +227,6 @@ ls3_object_attrs_to_json(struct ls3_instance *li,
 
 int lipe_object_attrs_init(struct ls3_object_attrs *attrs);
 void lipe_object_attrs_fini(struct ls3_object_attrs *attrs);
-void lipe_object_attrs_reset(struct ls3_object_attrs *attrs);
 int lipe_object_attrs_set_links(struct ls3_object_attrs *attrs,
                                const void *link_xattr,
                                size_t link_xattr_size);
index f20ed6d..8b9f13d 100644 (file)
@@ -90,39 +90,50 @@ const char LS3_CSTR_NONE[] = "NONE";
 
 static bool xattr_name_not_found(long errcode)
 {
-       return errcode == EXT2_ET_EA_NAME_NOT_FOUND ||
+       return errcode == EXT2_ET_EA_KEY_NOT_FOUND ||
+              errcode == EXT2_ET_EA_NAME_NOT_FOUND ||
               errcode == EXT2_ET_EA_NAME_NOT_FOUND_1445WC1 ||
               errcode == EXT2_ET_EA_NAME_NOT_FOUND_1456WC1 ||
               errcode == EXT2_ET_EA_NAME_NOT_FOUND_1456WC3 ||
               errcode == EXT2_ET_EA_NAME_NOT_FOUND_1462WC3;
 }
 
-static int ldiskfs_trusted_xattr_get(struct lipe_object *lo,
-                                    const char *name,
-                                    void *buf, size_t buf_size,
-                                    int *value_size)
+static int ls3_xattr_get(struct lipe_object *lo, const char *name, void **value, size_t *value_size)
 {
        ext2_filsys fs = lo->u.lo_ldiskfs.lol_fs;
        struct ext2_inode_large *inode = lo->u.lo_ldiskfs.lol_inode;
+       struct ext2_xattr_handle *handle = NULL;
        errcode_t rc;
 
-       rc = ext2fs_attr_get(fs, (struct ext2_inode *)inode,
-                            EXT2_ATTR_INDEX_TRUSTED,
-                            name + strlen("trusted."),
-                            buf, buf_size, value_size);
+       if (lo->u.lo_ldiskfs.lol_xattr_handle == NULL) {
+               rc = ext2fs_xattrs_open(fs, lo_ino(lo), &handle);
+               if (rc != 0)
+                       goto out;
+
+               rc = ext2fs_xattrs_read_inode(handle, inode);
+               if (rc != 0)
+                       goto out;
+
+               lo->u.lo_ldiskfs.lol_xattr_handle = handle;
+               handle = NULL; /* lo owns it now. */
+       }
+
+       rc = ext2fs_xattr_get(lo->u.lo_ldiskfs.lol_xattr_handle, name, value, value_size);
+out:
        if (xattr_name_not_found(rc)) {
-               return -ENODATA;
-       } else if (rc) {
+               rc = -ENODATA;
+       } else if (rc != 0) {
                /* EXT2_ET_EA_TOO_BIG, what else? */
 
                LS3_ERROR_OBJ(lo, "cannot get '%s' xattr: rc = %ld (%s)\n",
                              name, rc, error_message(rc));
-               return -EINVAL;
+               rc = -EINVAL;
        }
 
-       assert(0 <= *value_size && *value_size <= buf_size);
+       if (handle != NULL)
+               ext2fs_xattrs_close(&handle);
 
-       return 0;
+       return rc;
 }
 
 static int
@@ -130,21 +141,29 @@ ldiskfs_read_attr_self_fid(struct ls3_instance *li,
                           struct lipe_object *lo,
                           struct ls3_object_attrs *loa)
 {
-       const struct lustre_mdt_attrs *lma;
-       char buf[XATTR_SIZE_MAX];
-       int size;
+       const char *name = XATTR_NAME_LMA;
+       struct lustre_mdt_attrs *lma;
+       void *value = NULL;
+       size_t value_size = 0;
        int rc;
 
-       rc = ldiskfs_trusted_xattr_get(lo, XATTR_NAME_LMA, buf, sizeof(buf), &size);
-       if (rc < 0)
-               return rc;
+       rc = ls3_xattr_get(lo, name, &value, &value_size);
+       if (rc != 0)
+               goto out;
+
+       if (value_size < sizeof(*lma)) {
+               rc = -EINVAL;
+               goto out;
+       }
 
-       lma = (const struct lustre_mdt_attrs *)buf;
+       lma = value;
        fid_le_to_cpu(&loa->loa_lma.lma_self_fid, &lma->lma_self_fid);
        loa->loa_lma.lma_compat = ext2fs_le32_to_cpu(lma->lma_compat);
        loa->loa_lma.lma_incompat = ext2fs_le32_to_cpu(lma->lma_incompat);
+out:
+       free(value);
 
-       return 0;
+       return rc;
 }
 
 static int
@@ -152,20 +171,31 @@ ldiskfs_read_attr_filter_fid(struct ls3_instance *li,
                             struct lipe_object *lo,
                             struct ls3_object_attrs *loa)
 {
-       struct filter_fid *ff = &loa->loa_filter_fid;
-       struct lu_fid pfid;
-       int size;
+       const char *name = XATTR_NAME_FID;
+       void *value = NULL;
+       size_t value_size = 0;
        int rc;
+       struct filter_fid *ff = &loa->loa_filter_fid;
 
-       rc = ldiskfs_trusted_xattr_get(lo, XATTR_NAME_FID, ff, sizeof(*ff), &size);
-       if (rc < 0)
-               return rc;
+       rc = ls3_xattr_get(lo, name, &value, &value_size);
+       if (rc != 0)
+               goto out;
 
-       fid_le_to_cpu(&pfid, &ff->ff_parent);
-       ff->ff_parent = pfid;
-       loa->loa_filter_fid_size = size;
+       if (value_size < sizeof(ff->ff_parent)) {
+               rc = -EINVAL;
+               goto out;
+       }
 
-       return 0;
+       memset(ff, 0, sizeof(&ff));
+       memcpy(ff, value, min(sizeof(*ff), value_size));
+       fid_le_to_cpu(&ff->ff_parent, &ff->ff_parent);
+       /* ...? */
+
+       loa->loa_filter_fid_size = value_size;
+out:
+       free(value);
+
+       return rc;
 }
 
 static int
@@ -202,7 +232,9 @@ ldiskfs_read_attr_links(struct ls3_instance *li,
                        struct lipe_object *lo,
                        struct ls3_object_attrs *loa)
 {
-       int size;
+       const char *name = XATTR_NAME_LINK;
+       void *value = NULL;
+       size_t value_size = 0;
        int rc;
 
        assert(lipe_list_empty(&loa->loa_links));
@@ -218,21 +250,23 @@ ldiskfs_read_attr_links(struct ls3_instance *li,
 
        if (loa->loa_lma.lma_incompat & LMAI_ORPHAN) {
                /* Then no links and loa_links is empty so good. */
-               goto out_ok;
+               rc = 0;
+               goto out;
        }
 
-       rc = ldiskfs_trusted_xattr_get(lo, XATTR_NAME_LINK,
-                                      loa->loa_link_buf, loa->loa_link_buf_size, &size);
-       if (rc < 0)
-               return rc;
+       rc = ls3_xattr_get(lo, name, &value, &value_size);
+       if (rc != 0)
+               goto out;
 
-       rc = lipe_object_attrs_set_links(loa, loa->loa_link_buf, size);
-       if (rc) {
-               LS3_ERROR_OBJ(lo, "cannot decode link xattr: rc = %d\n", rc);
-               return rc;
+       rc = lipe_object_attrs_set_links(loa, value, value_size);
+       if (rc != 0) {
+               LS3_DEBUG_OBJ(lo, "cannot decode '%s' xattr, ignoring: rc = %d\n", name, rc);
+               goto out;
        }
-out_ok:
-       return 0;
+out:
+       free(value);
+
+       return rc;
 }
 
 static char *xsprintf(const char *fmt, ...)
@@ -353,22 +387,27 @@ static int ldiskfs_read_attr_lov(struct ls3_instance *li,
                                 struct lipe_object *lo,
                                 struct ls3_object_attrs *loa)
 {
-       struct lov_user_md *lum = loa->loa_lum;
-       int size;
+       const char *name = XATTR_NAME_LOV;
+       void *value = NULL;
+       size_t value_size = 0;
        int rc;
 
-       rc = ldiskfs_trusted_xattr_get(lo, XATTR_NAME_LOV, lum, loa->loa_lum_size, &size);
-       if (rc < 0)
+       rc = ls3_xattr_get(lo, name, &value, &value_size);
+       if (rc != 0)
                goto out;
 
-       loa->loa_layout = llapi_layout_get_by_xattr(lum, size, 0);
+       loa->loa_layout = llapi_layout_get_by_xattr(value, value_size, 0);
        if (loa->loa_layout == NULL) {
                LS3_ERROR_OBJ(lo, "cannot decode '%s' xattr: rc = %d\n",
-                             XATTR_NAME_LOV, rc);
+                             name, rc);
                rc = -errno;
                goto out;
        }
+
+       rc = 0;
 out:
+       free(value);
+
        return rc;
 }
 
@@ -376,17 +415,25 @@ static int ldiskfs_read_attr_lmv(struct ls3_instance *li,
                                 struct lipe_object *lo,
                                 struct ls3_object_attrs *loa)
 {
-       int size;
+       const char *name = XATTR_NAME_LMV;
+       void *value = NULL;
+       size_t value_size = 0;
        int rc;
 
-       rc = ldiskfs_trusted_xattr_get(lo, XATTR_NAME_LMV,
-                                      loa->loa_lmv_buf, loa->loa_lmv_buf_size, &size);
-       if (rc < 0)
-               return rc;
+       rc = ls3_xattr_get(lo, name, &value, &value_size);
+       if (rc != 0)
+               goto out;
+
+       loa->loa_lmv = value;
+       loa->loa_lmv_size = value_size;
+       value = NULL;
+       value_size = 0;
 
        /* TODO Store and check size. */
+out:
+       free(value);
 
-       return 0;
+       return rc;
 }
 
 static bool lo_is_dir_stripe(struct ls3_instance *li,
@@ -400,7 +447,9 @@ static bool lo_is_dir_stripe(struct ls3_instance *li,
        if (rc != 0 && rc != -ENOTSUP)
                return false;
 
-       lmm = (union lmv_mds_md *)loa->loa_lmv_buf;
+       lmm = (union lmv_mds_md *)loa->loa_lmv;
+       if (loa->loa_lmv_size < sizeof(lmm->lmv_magic))
+               return false;
 
        return lmm->lmv_magic == LMV_MAGIC_STRIPE;
 }
@@ -409,46 +458,60 @@ static int ldiskfs_read_attr_hsm(struct ls3_instance *li,
                                 struct lipe_object *lo,
                                 struct ls3_object_attrs *loa)
 {
-       struct hsm_user_state *hus = &loa->loa_hsm_state;
-       char buf[XATTR_SIZE_MAX];
-       struct hsm_attrs *hsm;
-       int size;
+       const char *name = XATTR_NAME_HSM;
+       void *value = NULL;
+       size_t value_size = 0;
        int rc;
+       struct hsm_user_state *hus = &loa->loa_hsm_state;
+       const struct hsm_attrs *hsm;
 
-       assert(sizeof(*hsm) < XATTR_SIZE_MAX);
+       memset(hus, 0, sizeof(*hus));
 
-       rc = ldiskfs_trusted_xattr_get(lo, XATTR_NAME_HSM, buf, sizeof(buf), &size);
-       if (rc < 0)
-               return rc;
+       rc = ls3_xattr_get(lo, name, &value, &value_size);
+       if (rc != 0)
+               goto out;
 
-       hsm = (struct hsm_attrs *)buf;
+       if (value_size < sizeof(*hsm)) {
+               LS3_DEBUG_OBJ(lo, "xattr '%s': got size %zu, expected %zu\n",
+                             name, value_size, sizeof(*hsm));
+               rc = -ENODATA;
+               goto out;
+       }
+
+       hsm = value;
        hus->hus_states = ext2fs_le32_to_cpu(hsm->hsm_flags);
        hus->hus_archive_id = ext2fs_le64_to_cpu(hsm->hsm_arch_id);
+out:
+       free(value);
 
-       return 0;
+       return rc;
 }
 
 static int ldiskfs_read_attr_som(struct ls3_instance *li,
                                 struct lipe_object *lo,
                                 struct ls3_object_attrs *loa)
 {
-       struct lustre_som_attrs *som = &loa->loa_som;
-       int size;
+       const char *name = XATTR_NAME_SOM;
+       void *value = NULL;
+       size_t value_size = 0;
        int rc;
+       const struct lustre_som_attrs *som;
 
-       rc = ldiskfs_trusted_xattr_get(lo, XATTR_NAME_SOM, som, sizeof(*som), &size);
-       if (rc < 0)
-               return rc;
+       rc = ls3_xattr_get(lo, name, &value, &value_size);
+       if (rc != 0)
+               goto out;
 
-       if (size != sizeof(*som)) {
-               LS3_ERROR_OBJ(lo, "unexpected size of '%s' xattr, expected %zu, got %d\n",
-                             XATTR_NAME_SOM, sizeof(*som), size);
-               return -ENODATA;
+       if (value_size < sizeof(*som)) {
+               LS3_ERROR_OBJ(lo, "xattr '%s': got size %zu, expected %zu\n",
+                             name, value_size, sizeof(*som));
+               rc = -ENODATA;
+               goto out;
        }
 
-       som->lsa_valid = ext2fs_le16_to_cpu(som->lsa_valid);
-       som->lsa_size = ext2fs_le64_to_cpu(som->lsa_size);
-       som->lsa_blocks = ext2fs_le64_to_cpu(som->lsa_blocks);
+       som = value;
+       loa->loa_som.lsa_valid = ext2fs_le16_to_cpu(som->lsa_valid);
+       loa->loa_som.lsa_size = ext2fs_le64_to_cpu(som->lsa_size);
+       loa->loa_som.lsa_blocks = ext2fs_le64_to_cpu(som->lsa_blocks);
 
        switch (loa->loa_som.lsa_valid) {
        case SOM_FL_STRICT:
@@ -460,8 +523,10 @@ static int ldiskfs_read_attr_som(struct ls3_instance *li,
                rc = -ENOTSUP;
                break;
        }
+out:
+       free(value);
 
-       return 0;
+       return rc;
 }
 
 static int ldiskfs_read_attr_size(struct ls3_instance *li,
@@ -605,7 +670,7 @@ static bool ldiskfs_scan_get_next_group_batch(struct ls3_scan_control *sc,
  *
  * The similar function in E2fsprogs has a bug LU-13103
  */
-static blkcnt_t blocks_from_inode(ext2_filsys fs, struct ext2_inode_large *inode)
+static blkcnt_t blocks_from_inode(ext2_filsys fs, const struct ext2_inode_large *inode)
 {
        blkcnt_t b;
 
@@ -629,10 +694,10 @@ __s64 inode_time(__u32 xtime, __u32 xtime_extra)
        return time;
 }
 
-static void ldiskfs_copy_inode_attrs(ext2_filsys fs,
-                                    struct ls3_object_attrs *loa,
-                                    ext2_ino_t ino,
-                                    struct ext2_inode_large *inode)
+static void ls3_copy_inode_attrs(struct ls3_object_attrs *loa,
+                                ext2_filsys fs,
+                                ext2_ino_t ino,
+                                const struct ext2_inode_large *inode)
 {
        loa->loa_ino = ino;
        loa->loa_atime = inode_time(inode->i_atime, inode->i_atime_extra);
@@ -651,14 +716,70 @@ static void ldiskfs_copy_inode_attrs(ext2_filsys fs,
        loa->loa_valid = LS3_OBJECT_ATTR_BASE | LS3_OBJECT_ATTR_PROJID;
 }
 
+static void ls3_scan_inode(struct ls3_instance *li,
+                          ext2_filsys fs,
+                          ext2_ino_t ino,
+                          struct ext2_inode_large *inode)
+{
+       struct lipe_object lo = {
+               .u.lo_ldiskfs.lol_fs = fs,
+               .u.lo_ldiskfs.lol_ino = ino,
+               .u.lo_ldiskfs.lol_inode = inode,
+       };
+       struct ls3_object_attrs loa;
+       int rc;
+
+       lipe_object_attrs_init(&loa);
+       ls3_copy_inode_attrs(&loa, fs, ino, inode);
+
+       rc = ls3_read_attrs(li, &lo, &loa, li->li_required_attrs,
+                           true /* quit on error. */);
+       if (rc != 0) {
+               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));
+               goto out;
+       }
+
+       assert((loa.loa_valid & li->li_required_attrs) == li->li_required_attrs);
+
+       /* Requiring fid_is_norm() prevents us from returning ROOT,
+        * .lustre, .lustre/fid, etc. It also prevents crashes when we
+        * try to access objects by or using fid2path. */
+
+       if ((li->li_required_attrs & LS3_OBJECT_ATTR_SELF_FID) &&
+           !fid_is_norm(loa_self_fid(&loa)) && !fid_is_idif(loa_self_fid(&loa)))
+               goto out;
+
+       if (lo_is_dir_stripe(li, &lo, &loa))
+               goto out;
+
+       LS3_CURRENT.lc_object = &lo;
+       LS3_CURRENT.lc_attrs = &loa;
+
+       scm_catch(SCM_BOOL_T, li->li_scm_policy_thunk, ls3_scm_policy_exception_handler);
+
+       LS3_CURRENT.lc_object = NULL;
+       LS3_CURRENT.lc_attrs = NULL;
+out:
+       if (lo.u.lo_ldiskfs.lol_xattr_handle != NULL)
+               ext2fs_xattrs_close(&lo.u.lo_ldiskfs.lol_xattr_handle);
+
+       lipe_object_attrs_fini(&loa);
+}
+
 static int ldiskfs_scan_groups(ext2_inode_scan scan,
                               ext2_filsys fs,
-                              struct ls3_object_attrs *loa,
-                              struct lipe_object *lo,
                               struct ext2_inode_large *inode, int inode_size,
                               struct ls3_thread_info *ti)
 {
        struct ls3_instance *li;
+       ext2_ino_t ino;
        errcode_t rc;
 
        li = ti->ti_instance;
@@ -672,13 +793,9 @@ static int ldiskfs_scan_groups(ext2_inode_scan scan,
                goto out;
        }
 
-       while (!ext2fs_get_next_inode_full(scan, &lo->u.lo_ldiskfs.lol_ino,
+       while (!ext2fs_get_next_inode_full(scan, &ino,
                                           (struct ext2_inode *)inode,
                                           inode_size)) {
-               ext2_ino_t ino;
-               int rc2;
-
-               ino = lo->u.lo_ldiskfs.lol_ino;
                if (ino == 0)
                        break;
 
@@ -703,44 +820,7 @@ static int ldiskfs_scan_groups(ext2_inode_scan scan,
                        continue;
                }
 
-               lipe_object_attrs_reset(loa);
-               ldiskfs_copy_inode_attrs(fs, loa, ino, inode);
-
-               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", 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_valid & li->li_required_attrs) ==
-                      li->li_required_attrs);
-
-               /* Requiring fid_is_norm() prevents us from returning
-                * ROOT, .lustre, .lustre/fid, etc. It also prevents
-                * crashes when we try to access objects by or using
-                * fid2path. */
-               if ((li->li_required_attrs & LS3_OBJECT_ATTR_SELF_FID) &&
-                   !fid_is_norm(loa_self_fid(loa)) && !fid_is_idif(loa_self_fid(loa)))
-                       continue;
-
-               if (lo_is_dir_stripe(li, lo, loa))
-                       continue;
-
-               LS3_CURRENT.lc_object = lo;
-               LS3_CURRENT.lc_attrs = loa;
-
-               scm_catch(SCM_BOOL_T, li->li_scm_policy_thunk, ls3_scm_policy_exception_handler);
-
-               LS3_CURRENT.lc_object = NULL;
-               LS3_CURRENT.lc_attrs = NULL;
+               ls3_scan_inode(li, fs, ino, inode);
        }
 
        rc = 0;
@@ -767,8 +847,6 @@ static void *ls3_scan_thread_start_scm(void *arg)
        ext2_filsys fs = NULL;
        ext2_inode_scan scan = NULL;
        struct ext2_inode_large *inode = NULL;
-       struct lipe_object lo = {
-       };
        struct ls3_object_attrs loa;
        int inode_size;
        intptr_t rc;
@@ -799,8 +877,6 @@ static void *ls3_scan_thread_start_scm(void *arg)
                goto out_free_attrs;
        }
 
-       lo.u.lo_ldiskfs.lol_fs = fs;
-
        rc = ext2fs_read_inode_bitmap(fs);
        if (rc) {
                LS3_ERROR("cannot read inode bitmap from '%s': %s\n", dev,
@@ -820,7 +896,6 @@ static void *ls3_scan_thread_start_scm(void *arg)
                inode_size = sizeof(*inode);
 
        inode = xcalloc(1, inode_size);
-       lo.u.lo_ldiskfs.lol_inode = inode;
 
        while (!__atomic_load_n(&ti->ti_should_stop, __ATOMIC_RELAXED)) {
                bool found_batch;
@@ -837,7 +912,7 @@ static void *ls3_scan_thread_start_scm(void *arg)
 
                ext2fs_set_inode_callback(scan, &ls3_done_group_callback, ti);
 
-               rc = ldiskfs_scan_groups(scan, fs, &loa, &lo, inode, inode_size, ti);
+               rc = ldiskfs_scan_groups(scan, fs, inode, inode_size, ti);
                if (rc != 0)
                        goto out_free;
 
index b32fe3a..ffaf611 100644 (file)
@@ -21,6 +21,7 @@ struct lipe_object_ldiskfs {
        ext2_filsys lol_fs;
        ext2_ino_t lol_ino;
        struct ext2_inode_large *lol_inode;
+       struct ext2_xattr_handle *lol_xattr_handle;
 };
 
 struct lipe_object {
index 7b6d6ee..8ac5764 100644 (file)
@@ -580,6 +580,8 @@ test_108() {
        local device="$(facet_device $facet)"
        local file=$MOUNT/$tfile
        local fd
+       local link_count=200
+       local i
 
        init_lipe_scan3_env "$file"
 
@@ -595,6 +597,13 @@ test_108() {
        ln $file $file-3
        expect_expr "$device" '(length (links))' 3
 
+       for ((i = 4; i < link_count; i++)); do
+               ln $file $file-$i
+       done
+
+       expect_expr "$device" '(caar (links))' "$ROOT_FID"
+       expect_expr "$device" '(cdar (links))' "$tfile"
+
        # FIXME link xattr is not updated when removing last link.
        # exec {fd}>$file
        # rm -- "$file" "$file-2" "$file-3"