Whamcloud - gitweb
EX-4965 lipe: use new e2fsprogs xattr API
authorJohn L. Hammond <jhammond@whamcloud.com>
Thu, 10 Mar 2022 23:20:27 +0000 (17:20 -0600)
committerJohn L. Hammond <jhammond@whamcloud.com>
Thu, 17 Mar 2022 13:50:23 +0000 (08:50 -0500)
Switch to the ext2fs_xattr_handle API since this handles xattrs stored
in a separate file. Add sanity-lipe test_100() to verify.

Test-Parameters: testlist=sanity-lipe
Signed-off-by: John L. Hammond <jhammond@whamcloud.com>
Change-Id: Ibc39d01ecfb04307755f44751fc69ffbd79b5d69
Reviewed-on: https://review.whamcloud.com/46784
Tested-by: jenkins <devops@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
12 files changed:
lipe/src/lamigo.c
lipe/src/lipe_ldiskfs.c
lipe/src/lipe_object_attrs.c
lipe/src/lipe_object_attrs.h
lipe/src/lipe_zfs.c
lipe/src/lustre_ea.c
lipe/src/lustre_ea.h
lipe/src/lustre_ea_ldiskfs.c
lipe/src/policy.c
lipe/src/policy.h
lipe/src/posix_ea.c
lustre/tests/sanity-lipe.sh

index 9099530..5260ec6 100644 (file)
@@ -1143,10 +1143,11 @@ static int lamigo_get_attrs(const struct lu_fid *fid,
        }
 
        if (need_attr & LIPE_OBJECT_ATTR_LINKEA) {
-               rc = fgetxattr(fd, XATTR_NAME_LINK, attrs->loa_leh_buf,
-                               sizeof(attrs->loa_leh_buf));
+               char buf[XATTR_SIZE_MAX];
+
+               rc = fgetxattr(fd, XATTR_NAME_LINK, buf, sizeof(buf));
                if (rc >= 0)
-                       rc = lipe_object_attrs_set_links(attrs, attrs->loa_leh_buf, rc);
+                       rc = lipe_object_attrs_set_links(attrs, buf, rc);
        }
 
        if (need_attr & LIPE_OBJECT_ATTR_HSMEA) {
@@ -2492,7 +2493,7 @@ static int lamigo_lipe_callback(struct lipe_instance *instance,
                goto out;
        }
 
-       resync = lamigo_striping_is_in_sync((void *)attrs->loa_lum, fast_pools,
+       resync = lamigo_striping_is_in_sync(attrs->loa_lum, fast_pools,
                                            slow_pools, &mo);
        if (resync == AMIGO_RESYNC_NONE) {
                lamigo_hist_add(&attrs->loa_fid, resync);
index 33d2b5e..848bb8d 100644 (file)
@@ -165,7 +165,7 @@ static int ldiskfs_scan_groups(ext2_inode_scan scan,
                        /* skip snapshot inodes */
                        continue;
                }
-                       
+
                if (!LINUX_S_ISDIR(inode->i_mode) &&
                    (inode->i_flags & EXT2_NODUMP_FL)) {
                        /* skip files which are not to be backuped */
@@ -185,6 +185,11 @@ static int ldiskfs_scan_groups(ext2_inode_scan scan,
                        LDEBUG("failed to apply policy on inode [%d]\n", ino);
                        rc = 0;
                }
+
+               if (object->u.lo_ldiskfs.lol_xattr_handle != NULL)
+                       ext2fs_xattrs_close(&object->u.lo_ldiskfs.lol_xattr_handle);
+
+               object->u.lo_ldiskfs.lol_xattr_handle = NULL;
        }
 
        return rc;
@@ -196,7 +201,10 @@ void *ldiskfs_scan_thread(void *arg)
        struct lipe_instance         *instance = info->ti_instance;
        const char                   *dev = instance->li_device;
        struct scan_result           *result = &info->ti_result;
-       struct lipe_object           object;
+       struct lipe_object           object = {
+               .lo_backfs_ops = &ldiskfs_operations,
+               .lo_backfs_type = instance->li_detected_fstype,
+       };
        ext2_filsys                  fs;
        ext2_inode_scan              scan;
        struct ext2_inode_large      *inode;
@@ -212,9 +220,6 @@ void *ldiskfs_scan_thread(void *arg)
                goto out;
        }
 
-       object.lo_backfs_ops = &ldiskfs_operations;
-       object.lo_backfs_type = instance->li_detected_fstype;
-
        gettimeofday(&result->sr_time_start, NULL);
        sysattrs.lps_sys_time = result->sr_time_start.tv_sec * 1000 +
                result->sr_time_start.tv_usec / 1000;
@@ -228,8 +233,6 @@ void *ldiskfs_scan_thread(void *arg)
                goto out_free_attrs;
        }
 
-       object.u.lo_ldiskfs.lol_fs = fs;
-
        rc = ext2fs_read_inode_bitmap(fs);
        if (rc) {
                LERROR("failed to ext2fs_read_inode_bitmap on [%s]: %s\n", dev,
@@ -244,7 +247,6 @@ void *ldiskfs_scan_thread(void *arg)
                goto out_close;
        }
 
-
        inode_size = EXT2_INODE_SIZE(fs->super);
        if (inode_size < sizeof(*inode))
                inode_size = sizeof(*inode);
@@ -255,6 +257,7 @@ void *ldiskfs_scan_thread(void *arg)
                goto out_scan;
        }
 
+       object.u.lo_ldiskfs.lol_fs = fs;
        object.u.lo_ldiskfs.lol_inode = inode;
 
        while (1) {
index 669de48..4295c1e 100644 (file)
@@ -307,32 +307,9 @@ static void lipe_object_attrs_xattrs_fini(struct lipe_object_attrs *attrs)
        LASSERT(lipe_list_empty(&attrs->loa_xattrs));
 }
 
-void lipe_object_attrs_reset(struct lipe_object_attrs *attrs)
-{
-       struct lov_user_md *lum = attrs->loa_lum;
-       int lum_size = attrs->loa_lum_size;
-
-       lipe_object_attrs_links_fini(attrs);
-       lipe_object_attrs_paths_fini(attrs);
-       lipe_object_attrs_xattrs_fini(attrs);
-       memset(lum, 0, lum_size);
-       memset(attrs, 0, sizeof(*attrs));
-       attrs->loa_lum = lum;
-       attrs->loa_lum_size = lum_size;
-       LIPE_INIT_LIST_HEAD(&attrs->loa_links);
-       LIPE_INIT_LIST_HEAD(&attrs->loa_paths);
-       LIPE_INIT_LIST_HEAD(&attrs->loa_xattrs);
-}
-
 int lipe_object_attrs_init(struct lipe_object_attrs *attrs)
 {
        memset(attrs, 0, sizeof(*attrs));
-       attrs->loa_lum_size = lov_user_md_size(LOV_MAX_STRIPE_COUNT,
-                                              LOV_USER_MAGIC_V3);
-       LIPE_ALLOC(attrs->loa_lum, attrs->loa_lum_size);
-       if (attrs->loa_lum == NULL)
-               return -ENOMEM;
-
        LIPE_INIT_LIST_HEAD(&attrs->loa_links);
        LIPE_INIT_LIST_HEAD(&attrs->loa_paths);
        LIPE_INIT_LIST_HEAD(&attrs->loa_xattrs);
@@ -345,16 +322,26 @@ void lipe_object_attrs_fini(struct lipe_object_attrs *attrs)
        lipe_object_attrs_links_fini(attrs);
        lipe_object_attrs_paths_fini(attrs);
        lipe_object_attrs_xattrs_fini(attrs);
-       LIPE_FREE(attrs->loa_lum, attrs->loa_lum_size);
+       free(attrs->loa_lum);
+       free(attrs->loa_lmv);
+}
+
+void lipe_object_attrs_reset(struct lipe_object_attrs *attrs)
+{
+       lipe_object_attrs_fini(attrs);
+       lipe_object_attrs_init(attrs);
 }
 
 int lipe_object_attrs_add_link(struct lipe_object_attrs *attrs,
                               const struct lu_fid *parent_fid,
-                              const char *name)
+                              const char *name, int namelen)
 {
        struct lipe_link_entry *lle = NULL;
        int rc;
 
+       if (namelen <= 0)
+               return -EOVERFLOW; /* ? */
+
        LIPE_ALLOC_PTR(lle);
        if (lle == NULL) {
                rc = -ENOMEM;
@@ -363,7 +350,7 @@ int lipe_object_attrs_add_link(struct lipe_object_attrs *attrs,
 
        lle->lle_parent_fid = *parent_fid;
 
-       lle->lle_name = strdup(name);
+       lle->lle_name = strndup(name, namelen);
        if (lle->lle_name == NULL) {
                rc = -ENOMEM;
                goto out;
@@ -418,6 +405,7 @@ int lipe_object_attrs_set_links(struct lipe_object_attrs *attrs,
        for (i = 0; i < reccount; i++) {
                unsigned int reclen = (lee->lee_reclen[0] << 8) | lee->lee_reclen[1];
                struct lu_fid parent_fid;
+               int namelen;
 
                pos += reclen;
                if (pos > len) {
@@ -428,10 +416,12 @@ int lipe_object_attrs_set_links(struct lipe_object_attrs *attrs,
 
                fid_be_to_cpu(&parent_fid, (const struct lu_fid *)&lee->lee_parent_fid);
 
-               LDEBUG("    %d: parent_fid "DFID", name '%s'\n",
-                      i, PFID(&parent_fid), lee->lee_name);
+               namelen = reclen - offsetof(struct link_ea_entry, lee_name[0]);
+
+               LDEBUG("    %d: parent_fid "DFID", name '%.*s'\n",
+                      i, PFID(&parent_fid), namelen, lee->lee_name);
 
-               rc = lipe_object_attrs_add_link(attrs, &parent_fid, lee->lee_name);
+               rc = lipe_object_attrs_add_link(attrs, &parent_fid, lee->lee_name, namelen);
                if (rc < 0)
                        return rc;
 
index ea5a353..38ccbd9 100644 (file)
@@ -130,12 +130,10 @@ struct lipe_object_attrs {
        struct lu_fid            loa_fid;
        char                     loa_fid_str[FID_NOBRACE_LEN + 1];
        __u64                    loa_attr_bits;
-       /* Buffer for struct link_ea_header */
-       char                     loa_leh_buf[MAX_LINKEA_SIZE];
-       /* Buffer for lmv */
-       char                     loa_lmv_buf[XATTR_SIZE_MAX];
-       struct lov_user_md      *loa_lum;
-       int                      loa_lum_size;
+       void                    *loa_lmv;
+       size_t                   loa_lmv_size;
+       void                    *loa_lum;
+       size_t                   loa_lum_size;
        struct hsm_user_state    loa_hsm_state;
        enum lustre_dom_status   loa_dom_status;
        struct lustre_som_attrs  loa_som;
@@ -193,7 +191,7 @@ void lipe_object_attrs_fini(struct lipe_object_attrs *attrs);
 void lipe_object_attrs_reset(struct lipe_object_attrs *attrs);
 int lipe_object_attrs_add_link(struct lipe_object_attrs *attrs,
                               const struct lu_fid *parent_fid,
-                              const char *name);
+                              const char *name, int namelen);
 int lipe_object_attrs_set_links(struct lipe_object_attrs *attrs,
                                const void *link_xattr,
                                size_t link_xattr_size);
index 441575c..5f72c47 100644 (file)
@@ -85,21 +85,19 @@ close_objset(objset_t *os, void *tag)
 
 static int zfs_get_xattr(struct lipe_object *lobject,
                         struct lipe_object_attrs *attrs,
-                        const char *xattr_name, uchar_t *value, uint_t cnt)
+                        const char *xattr_name, void *value, size_t value_size)
 {
        int rc;
 
-       rc = lipe_object_attrs_add_xattr(attrs, xattr_name, (const char *)value,
-                                        cnt);
+       rc = lipe_object_attrs_add_xattr(attrs, xattr_name, value, value_size);
        if (rc) {
                OBJ_ERROR(lobject, "failed to add xattr [%s]\n", xattr_name);
                return rc;
        }
 
        if (strcmp(xattr_name, XATTR_NAME_LMA) == 0) {
-               struct lustre_mdt_attrs *lma;
+               struct lustre_mdt_attrs *lma = value;
 
-               lma = (struct lustre_mdt_attrs *)value;
                fid_le_to_cpu(&attrs->loa_fid, &lma->lma_self_fid);
                snprintf(attrs->loa_fid_str,
                         sizeof(attrs->loa_fid_str), DFID_NOBRACE,
@@ -109,30 +107,25 @@ static int zfs_get_xattr(struct lipe_object *lobject,
                struct filter_fid *ff = &attrs->loa_filter_fid;
                struct lu_fid pfid;
 
-               memcpy(ff, value, cnt);
+               memcpy(ff, value, value_size);
                fid_le_to_cpu(&pfid, &ff->ff_parent);
                ff->ff_parent = pfid;
                attrs->loa_attr_bits |= LIPE_OBJECT_ATTR_FILTER_FID;
-               attrs->loa_filter_fid_size = cnt;
+               attrs->loa_filter_fid_size = value_size;
        } else if (strcmp(xattr_name, XATTR_NAME_LINK) == 0) {
-               memcpy(attrs->loa_leh_buf, value, cnt);
-
-               rc = lipe_object_attrs_set_links(attrs, value, cnt);
+               rc = lipe_object_attrs_set_links(attrs, value, value_size);
                if (rc) {
                        OBJ_ERROR(lobject, "failed to decode linkea\n");
                        return rc;
                }
        } else if (strcmp(xattr_name, XATTR_NAME_LMV) == 0) {
-               if (cnt > sizeof(attrs->loa_lmv_buf)) {
-                       OBJ_ERROR(lobject, "invalid lmv ea\n");
-                       return -EINVAL;
-               }
-               memcpy(attrs->loa_lmv_buf, value, cnt);
+               rc = xmemdup(&attrs->loa_lmv, &attrs->loa_lmv_size, value, value_size);
+               if (rc < 0)
+                       return rc;
        } else if (strcmp(xattr_name, XATTR_NAME_HSM) == 0) {
+               struct hsm_attrs *hsm = value;
                struct hsm_user_state *hus = &attrs->loa_hsm_state;
-               struct hsm_attrs *hsm;
 
-               hsm = (struct hsm_attrs *)value;
                rc = lipe_hsm2user(hsm, hus);
                if (rc) {
                        OBJ_ERROR(lobject,
@@ -142,22 +135,27 @@ static int zfs_get_xattr(struct lipe_object *lobject,
                }
                attrs->loa_attr_bits |= LIPE_OBJECT_ATTR_HSMEA;
        } else if (strcmp(xattr_name, XATTR_NAME_LOV) == 0) {
-               rc = decode_lum((struct lov_user_md *)value, cnt);
+               rc = decode_lum(value, value_size);
                if (rc) {
                        OBJ_ERROR(lobject, "failed to decode LOV EA, rc = %d\n",
                                  rc);
                        return rc;
                }
-               memcpy(attrs->loa_lum, value, cnt);
+
+               rc = xmemdup(&attrs->loa_lum, &attrs->loa_lum_size, value, value_size);
+               if (rc < 0)
+                       return rc;
+
                attrs->loa_attr_bits |= LIPE_OBJECT_ATTR_LOVEA;
        } else if (strcmp(xattr_name, XATTR_NAME_SOM) == 0) {
-               if (cnt != sizeof(attrs->loa_som)) {
+               if (value_size != sizeof(attrs->loa_som)) {
                        OBJ_ERROR(lobject,
                                  "unexpected size of LSoM xattr, expected [%u] got [%u]\n",
-                                 sizeof(attrs->loa_som), cnt);
+                                 sizeof(attrs->loa_som), value_size);
                }
-               lipe_som_swab((struct lustre_som_attrs *)value);
-               memcpy(&attrs->loa_som, value, cnt);
+
+               lipe_som_swab(value);
+               attrs->loa_som = *(struct lustre_som_attrs *)value;
        }
        return 0;
 }
index 31b06d2..e6141dc 100644 (file)
@@ -7,13 +7,35 @@
  *
  * Author: Li Xi <lixi@ddn.com>
  */
+#include <assert.h>
 #include <errno.h>
 #include <fnmatch.h>
+#include <malloc.h>
+#include <string.h>
 #include <lustre/lustreapi.h>
 #include <linux/lustre/lustre_ostid.h>
 #include "lustre_ea.h"
 #include "debug.h"
 
+int xmemdup(void **pdst, size_t *pdst_size, const void *src, size_t src_size)
+{
+       void *dst;
+
+       assert(*pdst == NULL);
+       assert(*pdst_size == 0);
+
+       dst = malloc(src_size);
+       if (dst == NULL && src_size != 0)
+               return -ENOMEM;
+
+       memcpy(dst, src, src_size);
+
+       *pdst = dst;
+       *pdst_size = src_size;
+
+       return 0;
+}
+
 /* Copied from Lustre/utils/liblustreapi.c */
 static inline struct lov_user_md *
 lov_comp_entry(struct lov_comp_md_v1 *comp_v1, int ent_idx)
index 488ea59..a97fa78 100644 (file)
@@ -9,11 +9,12 @@
  */
 #ifndef _LIPE_LUSTRE_EA_H_
 #define _LIPE_LUSTRE_EA_H_
-
+#include <stddef.h>
 #include <linux/lustre/lustre_ostid.h>
 #include "general_policy.h"
 #include "lipe_object_attrs.h"
 
+int xmemdup(void **pdst, size_t *pdst_size, const void *src, size_t src_size);
 int match_lum_ost(struct lov_user_md *lum, int64_t ost_index);
 int regular_expression_match_lum_pool(struct lov_user_md *lum, regex_t *reg);
 int shell_pattern_match_lum_pool(struct lov_user_md *lum, char *pattern);
index 7baa380..0684672 100644 (file)
 #include "debug.h"
 #include "policy.h"
 
-int get_link_ea_ldiskfs(struct lipe_object *object,
-                       struct lipe_object_attrs *attrs)
-{
-       int                      size;
-       int                      rc;
-       ext2_filsys              fs = object->u.lo_ldiskfs.lol_fs;
-       ext2_ino_t               ino = object->u.lo_ldiskfs.lol_ino;
-       struct ext2_inode_large *inode = object->u.lo_ldiskfs.lol_inode;
-
-       rc = ext2fs_attr_get(fs, (struct ext2_inode *)inode,
-                            EXT2_ATTR_INDEX_TRUSTED,
-                            XATTR_NAME_LINK + strlen("trusted."),
-                            attrs->loa_leh_buf, sizeof(attrs->loa_leh_buf),
-                            &size);
-       if (rc) {
-               LDEBUG("inode [%d] has no [%s] xattr, ignoring rc = %d\n",
-                      ino, XATTR_NAME_LINK, rc);
-               return -ENODATA;
-       }
-
-       rc = lipe_object_attrs_set_links(attrs, attrs->loa_leh_buf, size);
-       if (rc) {
-               LERROR("failed to decode linkea for inode [%d]\n", ino);
-               return rc;
-       }
-
-       attrs->loa_attr_bits |= LIPE_OBJECT_ATTR_LINKEA;
-       return 0;
-}
+#define min(x, y) ({                           \
+       typeof(x) _min1 = (x);                  \
+       typeof(y) _min2 = (y);                  \
+       (void) (&_min1 == &_min2);              \
+       _min1 < _min2 ? _min1 : _min2;          \
+})
 
 /* Due to a bug in e2fsprogs-1.45.6.wc3, and potential ongoing changes in
  * upstream releases, the definition of EXT2_ET_EA_NAME_NOT_FOUND may be
@@ -55,202 +32,281 @@ int get_link_ea_ldiskfs(struct lipe_object *object,
 #define EXT2_ET_EA_NAME_NOT_FOUND_1456WC3        (2133571514L)
 #define EXT2_ET_EA_NAME_NOT_FOUND_1462WC3        (2133571515L)
 
+static ext2_ino_t lo_ino(const struct lipe_object *lo)
+{
+       return lo->u.lo_ldiskfs.lol_ino;
+}
+
 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;
 }
 
-int get_lmv_ea_ldiskfs(struct lipe_object *object,
-                      struct lipe_object_attrs *attrs)
+static int ldiskfs_xattr_get(struct lipe_object *lo,
+                            const char *name,
+                            void **value, size_t *value_size)
 {
-       int                      size;
-       long                     rc;
-       ext2_filsys              fs = object->u.lo_ldiskfs.lol_fs;
-       ext2_ino_t               ino = object->u.lo_ldiskfs.lol_ino;
-       struct ext2_inode_large *inode = object->u.lo_ldiskfs.lol_inode;
-
-       memset(attrs->loa_lmv_buf, 0, sizeof(attrs->loa_lmv_buf));
-       rc = ext2fs_attr_get(fs, (struct ext2_inode *)inode,
-                            EXT2_ATTR_INDEX_TRUSTED,
-                            XATTR_NAME_LMV + strlen("trusted."),
-                            attrs->loa_lmv_buf, sizeof(attrs->loa_lmv_buf),
-                            &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;
+
+       assert(*value == NULL);
+       assert(*value_size == 0);
+
+       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)) {
-               LDEBUG("inode [%d] has no [%s] xattr ignoring rc = %u\n",
-                      ino, XATTR_NAME_LMV, rc);
-               return 1;
-       } else if (rc) {
-               LERROR("failed to get [%s] xattr for inode [%d], rc = %d\n",
-                      XATTR_NAME_LMV, ino, rc);
-               return -ENODATA;
+               rc = -ENODATA;
+       } else if (rc != 0) {
+               /* EXT2_ET_EA_TOO_BIG, what else? */
+
+               LERROR("ino = %u: cannot get '%s' xattr: rc = %ld (%s)\n",
+                      lo_ino(lo), name, rc, error_message(rc));
+               rc = -EINVAL;
        }
 
-       return 0;
+       if (handle != NULL)
+               ext2fs_xattrs_close(&handle);
+
+       return rc;
 }
 
-int get_lma_ea_ldiskfs(struct lipe_object *object,
-                      struct lipe_object_attrs *attrs)
+static int get_link_ea_ldiskfs(struct lipe_object *lo, struct lipe_object_attrs *loa)
 {
-       char                     buf[MAX_LINKEA_SIZE];
+       const char *name = XATTR_NAME_LINK;
+       void *value = NULL;
+       size_t value_size = 0;
+       int rc;
+
+       rc = ldiskfs_xattr_get(lo, name, &value, &value_size);
+       if (rc != 0) {
+               LDEBUG("ino = %u: no '%s' xattr, ignoring: rc = %d\n",
+                      lo_ino(lo), name, rc);
+               goto out;
+       }
+
+       rc = lipe_object_attrs_set_links(loa, value, value_size);
+       if (rc != 0) {
+               LDEBUG("ino = %u: cannot decode '%s' xattr, ignoring: rc = %d\n",
+                      lo_ino(lo), name, rc);
+               goto out;
+       }
+
+       loa->loa_attr_bits |= LIPE_OBJECT_ATTR_LINKEA;
+out:
+       free(value);
+
+       return rc;
+}
+
+static int get_lmv_ea_ldiskfs(struct lipe_object *lo, struct lipe_object_attrs *loa)
+{
+       const char *name = XATTR_NAME_LMV;
+       void *value = NULL;
+       size_t value_size = 0;
+       int rc;
+
+       rc = ldiskfs_xattr_get(lo, name, &value, &value_size);
+       if (rc != 0) {
+               LDEBUG("ino = %u: no '%s' xattr, ignoring: rc = %d\n",
+                      lo_ino(lo), name, rc);
+               goto out;
+       }
+
+       loa->loa_lmv = value;
+       loa->loa_lmv_size = value_size;
+       value = NULL;
+       value_size = 0;
+
+       /* There is no LIPE_OBJECT_ATTR_LMVEA. */
+out:
+       free(value);
+
+       return rc;
+}
+
+static int get_lma_ea_ldiskfs(struct lipe_object *lo, struct lipe_object_attrs *loa)
+{
+       const char *name = XATTR_NAME_LMA;
        struct lustre_mdt_attrs *lma;
-       int                      size;
-       int                      rc;
-       ext2_filsys              fs = object->u.lo_ldiskfs.lol_fs;
-       ext2_ino_t               ino = object->u.lo_ldiskfs.lol_ino;
-       struct ext2_inode_large *inode = object->u.lo_ldiskfs.lol_inode;
-
-       rc = ext2fs_attr_get(fs, (struct ext2_inode *)inode,
-                            EXT2_ATTR_INDEX_TRUSTED,
-                            XATTR_NAME_LMA + strlen("trusted."),
-                            buf, MAX_LINKEA_SIZE, &size);
-       if (rc) {
-               LDEBUG("inode [%d] has no [%s] xattr, ignoring rc = %d\n",
-                      ino, XATTR_NAME_LMA, rc);
-               return -ENODATA;
+       void *value = NULL;
+       size_t value_size = 0;
+       int rc;
+
+       rc = ldiskfs_xattr_get(lo, name, &value, &value_size);
+       if (rc != 0) {
+               LDEBUG("ino = %u: no '%s' xattr, ignoring: rc = %d\n",
+                      lo_ino(lo), name, rc);
+               goto out;
        }
 
-       lma = (struct lustre_mdt_attrs *)buf;
-       fid_le_to_cpu(&attrs->loa_fid, &lma->lma_self_fid);
-       snprintf(attrs->loa_fid_str, sizeof(attrs->loa_fid_str), DFID_NOBRACE,
-                PFID(&attrs->loa_fid));
-       attrs->loa_attr_bits |= LIPE_OBJECT_ATTR_LMAEA;
-       return 0;
+       /* FIXME Check value_size. */
+
+       lma = value;
+       fid_le_to_cpu(&loa->loa_fid, &lma->lma_self_fid);
+       snprintf(loa->loa_fid_str, sizeof(loa->loa_fid_str), DFID_NOBRACE,
+                PFID(&loa->loa_fid));
+
+       loa->loa_attr_bits |= LIPE_OBJECT_ATTR_LMAEA;
+out:
+       free(value);
+
+       return rc;
 }
 
-int get_hsm_ea_ldiskfs(struct lipe_object *object,
-                      struct lipe_object_attrs *attrs)
+static int get_hsm_ea_ldiskfs(struct lipe_object *lo, struct lipe_object_attrs *loa)
 {
-       char                     buf[MAX_LINKEA_SIZE];
-       struct hsm_attrs        *hsm;
-       long                     rc;
-       int                      size;
-       struct hsm_user_state   *hus = &attrs->loa_hsm_state;
-       ext2_filsys              fs = object->u.lo_ldiskfs.lol_fs;
-       ext2_ino_t               ino = object->u.lo_ldiskfs.lol_ino;
-       struct ext2_inode_large *inode = object->u.lo_ldiskfs.lol_inode;
-
-       LASSERT(sizeof(*hsm) < MAX_LINKEA_SIZE);
-
-       rc = ext2fs_attr_get(fs, (struct ext2_inode *)inode,
-                            EXT2_ATTR_INDEX_TRUSTED,
-                            XATTR_NAME_HSM + strlen("trusted."),
-                            buf, MAX_LINKEA_SIZE, &size);
-       if (xattr_name_not_found(rc)) {
-               LDEBUGW(&attrs->loa_fid, "inode [%d] has no [%s] xattr\n",
-                       ino, XATTR_NAME_HSM);
-               hus->hus_states = 0;
-               hus->hus_archive_id  = 0;
-       } else if (rc) {
-               LERROR("failed to get [%s] xattr for inode [%d], rc = %d\n",
-                      XATTR_NAME_HSM, ino, rc);
-               return -ENODATA;
-       } else {
-               hsm = (struct hsm_attrs *)buf;
-               rc = lipe_hsm2user(hsm, hus);
-               if (rc) {
-                       LERROR("failed to extract [%s] xattr for inode [%d], rc = %d\n",
-                              XATTR_NAME_HSM, ino, rc);
-                       return rc;
-               }
+       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;
+       struct hsm_attrs *hsm;
+
+       memset(hus, 0, sizeof(*hus));
+
+       rc = ldiskfs_xattr_get(lo, name, &value, &value_size);
+       if (rc != 0) {
+               LDEBUG("ino = %u: no '%s' xattr, ignoring: rc = %d\n",
+                      lo_ino(lo), name, rc);
+               goto out;
        }
-       attrs->loa_attr_bits |= LIPE_OBJECT_ATTR_HSMEA;
-       return 0;
+
+       if (value_size < sizeof(*hsm)) {
+               LERROR("ino = %u: xattr '%s': got size %zu, expected %zu\n",
+                      lo_ino(lo), name, value_size, sizeof(*hsm));
+               rc = -ENODATA;
+               goto out;
+       }
+
+       hsm = value;
+       rc = lipe_hsm2user(hsm, hus);
+       if (rc != 0) {
+               LERROR("ino = %u: cannot parse '%s' xattr: rc = %d\n", lo_ino(lo), name, rc);
+               goto out;
+       }
+
+       loa->loa_attr_bits |= LIPE_OBJECT_ATTR_HSMEA;
+out:
+       free(value);
+
+       return rc;
 }
 
-int get_fid_ea_ldiskfs(struct lipe_object *object,
-                      struct lipe_object_attrs *attrs)
+static int get_fid_ea_ldiskfs(struct lipe_object *lo, struct lipe_object_attrs *loa)
 {
-       ext2_filsys              fs = object->u.lo_ldiskfs.lol_fs;
-       ext2_ino_t               ino = object->u.lo_ldiskfs.lol_ino;
-       struct ext2_inode_large *inode = object->u.lo_ldiskfs.lol_inode;
-       struct filter_fid       *ff = &attrs->loa_filter_fid;
-       struct lu_fid            pfid;
-       int                      size;
-       int                      rc;
-
-       rc = ext2fs_attr_get(fs, (struct ext2_inode *)inode,
-                            EXT2_ATTR_INDEX_TRUSTED,
-                            XATTR_NAME_FID + strlen("trusted."),
-                            (char *)ff, sizeof(*ff), &size);
-       if (rc) {
-               LDEBUG("inode [%d] has no [%s] xattr, ignoring rc = %d\n",
-                      ino, XATTR_NAME_FID, rc);
-               return -ENODATA;
+       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_xattr_get(lo, name, &value, &value_size);
+       if (rc != 0) {
+               LDEBUG("ino = %u: no '%s' xattr, ignoring: rc = %d\n",
+                      lo_ino(lo), name, rc);
+               goto out;
        }
 
-       fid_le_to_cpu(&pfid, &ff->ff_parent);
-       ff->ff_parent = pfid;
-       attrs->loa_attr_bits |= LIPE_OBJECT_ATTR_FILTER_FID;
-       attrs->loa_filter_fid_size = size;
-       return 0;
+       if (value_size < sizeof(ff->ff_parent)) {
+               rc = -EINVAL;
+               goto out;
+       }
+
+       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;
+       loa->loa_attr_bits |= LIPE_OBJECT_ATTR_FILTER_FID;
+out:
+       free(value);
+
+       return rc;
 }
 
-int get_lum_ea_ldiskfs(struct lipe_object *object,
-                      struct lipe_object_attrs *attrs)
+static int get_lum_ea_ldiskfs(struct lipe_object *lo, struct lipe_object_attrs *loa)
 {
-       int                      rc;
-       int                      size;
-       struct lov_user_md      *lov = attrs->loa_lum;
-       ext2_filsys              fs = object->u.lo_ldiskfs.lol_fs;
-       ext2_ino_t               ino = object->u.lo_ldiskfs.lol_ino;
-       struct ext2_inode_large *inode = object->u.lo_ldiskfs.lol_inode;
-
-       rc = ext2fs_attr_get(fs, (struct ext2_inode *)inode,
-                            EXT2_ATTR_INDEX_TRUSTED,
-                            XATTR_NAME_LOV + strlen("trusted."),
-                            (char *)lov, attrs->loa_lum_size, &size);
-       if (rc) {
-               LDEBUGW(&attrs->loa_fid, "inode [%d] has no [%s] xattr, rc = %d\n",
-                       ino, XATTR_NAME_LOV, rc);
-               return -ENODATA;
+       const char *name = XATTR_NAME_LOV;
+       void *value = NULL;
+       size_t value_size = 0;
+       int rc;
+
+       rc = ldiskfs_xattr_get(lo, name, &value, &value_size);
+       if (rc != 0) {
+               LDEBUG("ino = %u: no '%s' xattr, ignoring: rc = %d\n",
+                      lo_ino(lo), name, rc);
+               goto out;
        }
 
-       rc = decode_lum(lov, size);
-       if (rc) {
-               LERROR("failed to decode lovea for inode [%d], rc = %d\n",
-                      ino, rc);
-               return rc;
+       rc = decode_lum(value, value_size);
+       if (rc != 0) {
+               LERROR("ino = %u: cannot decode '%s' xattr: rc = %d\n",
+                      lo_ino(lo), name, rc);
+               goto out;
        }
-       attrs->loa_attr_bits |= LIPE_OBJECT_ATTR_LOVEA;
-       return 0;
+
+       loa->loa_lum = value;
+       loa->loa_lum_size = value_size;
+       value = NULL;
+       value_size = 0;
+
+       loa->loa_attr_bits |= LIPE_OBJECT_ATTR_LOVEA;
+out:
+       free(value);
+
+       return rc;
 }
 
-/*
- * llapi_layout_get_by_xattr() and LSoM are both included in Lustre-2.12,
- * so no need to duplicate the macros.
- */
-int get_som_ea_ldiskfs(struct lipe_object *object,
-                      struct lipe_object_attrs *attrs)
+static int get_som_ea_ldiskfs(struct lipe_object *lo, struct lipe_object_attrs *loa)
 {
-       int                      rc;
-       int                      size;
-       struct lustre_som_attrs *som = &attrs->loa_som;
-       ext2_filsys              fs = object->u.lo_ldiskfs.lol_fs;
-       ext2_ino_t               ino = object->u.lo_ldiskfs.lol_ino;
-       struct ext2_inode_large *inode = object->u.lo_ldiskfs.lol_inode;
-
-       rc = ext2fs_attr_get(fs, (struct ext2_inode *)inode,
-                            EXT2_ATTR_INDEX_TRUSTED,
-                            XATTR_NAME_SOM + strlen("trusted."),
-                            (char *)som, sizeof(*som), &size);
-       if (rc) {
-               LDEBUGW(&attrs->loa_fid, "inode [%d] has no [%s] xattr, rc = %d\n",
-                       ino, XATTR_NAME_SOM, rc);
-               return -ENODATA;
+       const char *name = XATTR_NAME_SOM;
+       void *value = NULL;
+       size_t value_size = 0;
+       int rc;
+       struct lustre_som_attrs *som = &loa->loa_som;
+
+       rc = ldiskfs_xattr_get(lo, name, &value, &value_size);
+       if (rc != 0) {
+               LDEBUG("ino = %u: no '%s' xattr, ignoring: rc = %d\n",
+                      lo_ino(lo), name, rc);
+               goto out;
        }
 
-       if (size != sizeof(*som)) {
-               LERROR("unexpected size of [%s] xattr for inode [%d], expected [%d], got [%d]\n",
-                      XATTR_NAME_SOM, ino, sizeof(*som), size);
-               return -ENODATA;
+       if (value_size < sizeof(*som)) {
+               LERROR("ino = %u: xattr '%s': got size %zu, expected %zu\n",
+                      lo_ino(lo), name, value_size, sizeof(*som));
+               rc = -ENODATA;
+               goto out;
        }
 
+       *som = *(struct lustre_som_attrs *)value;
        lipe_som_swab(som);
 
+       /* LIPE_OBJECT_ATTR_SOM is set in get_som_ea() according to flags. */
+out:
+       free(value);
+
        return rc;
 }
 
index da7d023..ca7d56c 100644 (file)
@@ -823,10 +823,10 @@ static bool object_is_dir_substripe(struct lipe_object *object,
        if (rc && rc != -ENOTSUP)
                return false;
 
-       lmm = (union lmv_mds_md *)attrs->loa_lmv_buf;
-       if (lmm->lmv_magic == LMV_MAGIC_STRIPE)
-               return true;
-       return false;
+       lmm = attrs->loa_lmv;
+       assert(lmm != NULL);
+
+       return lmm->lmv_magic == LMV_MAGIC_STRIPE;
 }
 
 static int get_lma_ea(struct lipe_object *object,
index 37064f4..1097583 100644 (file)
@@ -286,6 +286,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_zfs {
index 35ecbc8..70d35b7 100644 (file)
@@ -29,9 +29,9 @@ static int get_link_ea_posix(struct lipe_object *object,
        int                      rc;
        ssize_t                  size;
        const char              *path = object->u.lo_posix.lop_path;
+       char buf[XATTR_SIZE_MAX];
 
-       size = lgetxattr(path, XATTR_NAME_LINK, attrs->loa_leh_buf,
-                        sizeof(attrs->loa_leh_buf));
+       size = lgetxattr(path, XATTR_NAME_LINK, buf, sizeof(buf));
        if (size < 0) {
                if (errno == ENOATTR)
                        LDEBUG("path [%s] has no [%s] xattr, ignoring\n",
@@ -42,7 +42,7 @@ static int get_link_ea_posix(struct lipe_object *object,
                return -errno;
        }
 
-       rc = lipe_object_attrs_set_links(attrs, attrs->loa_leh_buf, size);
+       rc = lipe_object_attrs_set_links(attrs, buf, size);
        if (rc) {
                LERROR("failed to decode linkea for path [%s]\n", path);
                return -1;
@@ -54,13 +54,11 @@ static int get_link_ea_posix(struct lipe_object *object,
 static int get_lmv_ea_posix(struct lipe_object *object,
                            struct lipe_object_attrs *attrs)
 {
-       ssize_t                  rc;
-       const char              *path = object->u.lo_posix.lop_path;
-
-       memset(attrs->loa_lmv_buf, 0, sizeof(attrs->loa_lmv_buf));
+       const char *path = object->u.lo_posix.lop_path;
+       char buf[XATTR_SIZE_MAX];
+       ssize_t rc;
 
-       rc = lgetxattr(path, XATTR_NAME_LMV, attrs->loa_lmv_buf,
-                      sizeof(attrs->loa_lmv_buf));
+       rc = lgetxattr(path, XATTR_NAME_LMV, buf, sizeof(buf));
        if (rc < 0) {
                if (errno == ENOATTR) {
                        LDEBUG("path [%s] has no [%s] xattr, ignoring\n",
@@ -73,19 +71,18 @@ static int get_lmv_ea_posix(struct lipe_object *object,
                }
        }
 
-       return 0;
+       return xmemdup(&attrs->loa_lmv, &attrs->loa_lmv_size, buf, rc);
 }
 
 static int get_lma_ea_posix(struct lipe_object *object,
                            struct lipe_object_attrs *attrs)
 {
-       char                     buf[MAX_LINKEA_SIZE];
-       struct lustre_mdt_attrs *lma;
-       ssize_t                  size;
-       const char              *path = object->u.lo_posix.lop_path;
+       const char *path = object->u.lo_posix.lop_path;
+       struct lustre_mdt_attrs *lma;
+       char buf[XATTR_SIZE_MAX];
+       ssize_t size;
 
-       size = lgetxattr(path, XATTR_NAME_LMA, buf,
-                        MAX_LINKEA_SIZE);
+       size = lgetxattr(path, XATTR_NAME_LMA, buf, sizeof(buf));
        if (size < 0) {
                if (errno == ENOATTR)
                        LDEBUG("path [%d] has no [%s] xattr, ignoring\n",
@@ -145,13 +142,12 @@ static int get_hsm_ea_posix(struct lipe_object *object,
 static int get_lum_ea_posix(struct lipe_object *object,
                            struct lipe_object_attrs *attrs)
 {
-       int                      rc;
-       int                      size;
-       struct lov_user_md      *lov = attrs->loa_lum;
-       const char              *path = object->u.lo_posix.lop_path;
+       const char *path = object->u.lo_posix.lop_path;
+       char buf[XATTR_SIZE_MAX];
+       int size;
+       int rc;
 
-       size = lgetxattr(path, XATTR_NAME_LOV,
-                        (char *)lov, attrs->loa_lum_size);
+       size = lgetxattr(path, XATTR_NAME_LOV, buf, sizeof(buf));
        if (size < 0) {
                if (errno == ENOATTR)
                        LDEBUG("path [%d] has no [%s] xattr, ignoring\n",
@@ -162,11 +158,16 @@ static int get_lum_ea_posix(struct lipe_object *object,
                return -errno;
        }
 
-       rc = decode_lum(lov, size);
+       rc = decode_lum((struct lov_user_md_v1 *)buf, size);
        if (rc) {
                LERROR("failed to decode lovea for path [%s]\n", path);
                return rc;
        }
+
+       rc = xmemdup(&attrs->loa_lum, &attrs->loa_lum_size, buf, size);
+       if (rc < 0)
+               return rc;
+
        attrs->loa_attr_bits |= LIPE_OBJECT_ATTR_LOVEA;
        return 0;
 }
index 9bbf2a9..571a288 100644 (file)
@@ -1465,6 +1465,26 @@ test_23() {
 }
 run_test 23 "lipe_find -size and -blocks work"
 
+test_100() {
+       local file=$DIR/$tdir/$tfile
+       local facet=${LIPE_MDS_FACET:-$(lipe_get_random_mds)}
+       local index=$(($(facet_number $facet) - 1))
+       local link_count=200
+       local i
+
+       $LFS mkdir -i $index $DIR/$tdir || error "$LFS mkdir '$td' failed"
+       touch $file
+
+       for ((i = 1; i < link_count; i++)); do
+               ln $file $file.$i
+       done
+
+       lipe_find_expect_file $facet $file true
+       lipe_find_expect_file $facet $file true -name $tfile
+       lipe_find_expect_file $facet $file true -name $tfile.1
+}
+run_test 100 "lipe_find works with big link xattrs"
+
 do_lipe_scan2_facet() {
        local facet="$1"
        local device="$(facet_device $facet)"