Whamcloud - gitweb
LU-10100 llite: swab LOV EA user data 91/35291/12
authorJian Yu <yujian@whamcloud.com>
Sat, 20 Jul 2019 09:30:33 +0000 (02:30 -0700)
committerOleg Drokin <green@whamcloud.com>
Sat, 27 Jul 2019 00:21:20 +0000 (00:21 +0000)
Many sub-tests failed with "Invalid argument" failures
on PPC client because of the endianness issue.

This patch fixes the issue by adding a common function
lustre_swab_lov_user_md() to swab the LOV EA user data.

Test-Parameters: clientarch=ppc64 \
envdefinitions=ONLY=27 testlist=sanity

Change-Id: I46bab0788300cd79c4e66e1a4990c3e1f7192391
Signed-off-by: Jian Yu <yujian@whamcloud.com>
Reviewed-on: https://review.whamcloud.com/35291
Tested-by: jenkins <devops@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Patrick Farrell <pfarrell@whamcloud.com>
Reviewed-by: Lai Siyao <lai.siyao@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/include/lustre_swab.h
lustre/llite/dir.c
lustre/llite/file.c
lustre/llite/llite_lib.c
lustre/llite/xattr.c
lustre/ptlrpc/pack_generic.c
lustre/tests/parse_foreign_dir.c
lustre/tests/parse_foreign_file.c

index cece542..ceaf9c9 100644 (file)
@@ -98,6 +98,7 @@ void lustre_swab_lov_user_md_v3(struct lov_user_md_v3 *lum);
 void lustre_swab_lov_comp_md_v1(struct lov_comp_md_v1 *lum);
 void lustre_swab_lov_user_md_objects(struct lov_user_ost_data *lod,
                                     int stripe_count);
+void lustre_swab_lov_user_md(struct lov_user_md *lum);
 void lustre_swab_lov_mds_md(struct lov_mds_md *lmm);
 void lustre_swab_idx_info(struct idx_info *ii);
 void lustre_swab_lip_header(struct lu_idxpage *lip);
index b2227af..57db3ac 100644 (file)
@@ -554,84 +554,67 @@ out_op_data:
 int ll_dir_setstripe(struct inode *inode, struct lov_user_md *lump,
                      int set_default)
 {
-        struct ll_sb_info *sbi = ll_i2sbi(inode);
-        struct md_op_data *op_data;
-        struct ptlrpc_request *req = NULL;
-        int rc = 0;
+       struct ll_sb_info *sbi = ll_i2sbi(inode);
+       struct md_op_data *op_data;
+       struct ptlrpc_request *req = NULL;
+       int rc = 0;
 #if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 13, 53, 0)
-        struct lustre_sb_info *lsi = s2lsi(inode->i_sb);
-        struct obd_device *mgc = lsi->lsi_mgc;
+       struct lustre_sb_info *lsi = s2lsi(inode->i_sb);
+       struct obd_device *mgc = lsi->lsi_mgc;
 #endif
-        int lum_size;
+       int lum_size;
        ENTRY;
 
-        if (lump != NULL) {
-                /*
-                 * This is coming from userspace, so should be in
-                 * local endian.  But the MDS would like it in little
-                 * endian, so we swab it before we send it.
-                 */
-                switch (lump->lmm_magic) {
-                case LOV_USER_MAGIC_V1: {
-                        if (lump->lmm_magic != cpu_to_le32(LOV_USER_MAGIC_V1))
-                                lustre_swab_lov_user_md_v1(lump);
-                        lum_size = sizeof(struct lov_user_md_v1);
-                        break;
-                }
-                case LOV_USER_MAGIC_V3: {
-                        if (lump->lmm_magic != cpu_to_le32(LOV_USER_MAGIC_V3))
-                                lustre_swab_lov_user_md_v3(
-                                        (struct lov_user_md_v3 *)lump);
-                        lum_size = sizeof(struct lov_user_md_v3);
-                        break;
-                }
-               case LOV_USER_MAGIC_COMP_V1: {
-                       if (lump->lmm_magic !=
-                           cpu_to_le32(LOV_USER_MAGIC_COMP_V1))
-                               lustre_swab_lov_comp_md_v1(
-                                       (struct lov_comp_md_v1 *)lump);
-                       lum_size = le32_to_cpu(
-                               ((struct lov_comp_md_v1 *)lump)->lcm_size);
+       if (lump != NULL) {
+               switch (lump->lmm_magic) {
+               case LOV_USER_MAGIC_V1:
+                       lum_size = sizeof(struct lov_user_md_v1);
                        break;
-               }
-               case LMV_USER_MAGIC: {
+               case LOV_USER_MAGIC_V3:
+                       lum_size = sizeof(struct lov_user_md_v3);
+                       break;
+               case LOV_USER_MAGIC_COMP_V1:
+                       lum_size = ((struct lov_comp_md_v1 *)lump)->lcm_size;
+                       break;
+               case LMV_USER_MAGIC:
                        if (lump->lmm_magic != cpu_to_le32(LMV_USER_MAGIC))
                                lustre_swab_lmv_user_md(
                                        (struct lmv_user_md *)lump);
                        lum_size = sizeof(struct lmv_user_md);
                        break;
-               }
                case LOV_USER_MAGIC_SPECIFIC: {
                        struct lov_user_md_v3 *v3 =
-                                       (struct lov_user_md_v3 *)lump;
+                               (struct lov_user_md_v3 *)lump;
                        if (v3->lmm_stripe_count > LOV_MAX_STRIPE_COUNT)
                                RETURN(-EINVAL);
-                       if (lump->lmm_magic !=
-                           cpu_to_le32(LOV_USER_MAGIC_SPECIFIC)) {
-                               lustre_swab_lov_user_md_v3(v3);
-                               lustre_swab_lov_user_md_objects(v3->lmm_objects,
-                                               v3->lmm_stripe_count);
-                       }
                        lum_size = lov_user_md_size(v3->lmm_stripe_count,
                                                    LOV_USER_MAGIC_SPECIFIC);
                        break;
                }
-               default: {
+               default:
                        CDEBUG(D_IOCTL, "bad userland LOV MAGIC:"
                                        " %#08x != %#08x nor %#08x\n",
                                        lump->lmm_magic, LOV_USER_MAGIC_V1,
                                        LOV_USER_MAGIC_V3);
                        RETURN(-EINVAL);
                }
-                }
-        } else {
-                lum_size = sizeof(struct lov_user_md_v1);
-        }
 
-        op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL, 0, 0,
-                                     LUSTRE_OPC_ANY, NULL);
-        if (IS_ERR(op_data))
-                RETURN(PTR_ERR(op_data));
+               /*
+                * This is coming from userspace, so should be in
+                * local endian.  But the MDS would like it in little
+                * endian, so we swab it before we send it.
+                */
+               if ((__swab32(lump->lmm_magic) & le32_to_cpu(LOV_MAGIC_MASK)) ==
+                   le32_to_cpu(LOV_MAGIC_MAGIC))
+                       lustre_swab_lov_user_md(lump);
+       } else {
+               lum_size = sizeof(struct lov_user_md_v1);
+       }
+
+       op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL, 0, 0,
+                                    LUSTRE_OPC_ANY, NULL);
+       if (IS_ERR(op_data))
+               RETURN(PTR_ERR(op_data));
 
        /* swabbing is done in lov_setstripe() on server side */
        rc = md_setattr(sbi->ll_md_exp, op_data, lump, lum_size, &req);
@@ -754,17 +737,11 @@ int ll_dir_getstripe(struct inode *inode, void **plmm, int *plmm_size,
        /* We don't swab objects for directories */
        switch (le32_to_cpu(lmm->lmm_magic)) {
        case LOV_MAGIC_V1:
-               if (LOV_MAGIC != cpu_to_le32(LOV_MAGIC))
-                       lustre_swab_lov_user_md_v1((struct lov_user_md_v1 *)lmm);
-               break;
        case LOV_MAGIC_V3:
-               if (LOV_MAGIC != cpu_to_le32(LOV_MAGIC))
-                       lustre_swab_lov_user_md_v3((struct lov_user_md_v3 *)lmm);
-               break;
        case LOV_MAGIC_COMP_V1:
+       case LOV_USER_MAGIC_SPECIFIC:
                if (LOV_MAGIC != cpu_to_le32(LOV_MAGIC))
-                       lustre_swab_lov_comp_md_v1(
-                                       (struct lov_comp_md_v1 *)lmm);
+                       lustre_swab_lov_user_md((struct lov_user_md *)lmm);
                break;
        case LMV_MAGIC_V1:
                if (LMV_MAGIC != cpu_to_le32(LMV_MAGIC))
@@ -774,16 +751,6 @@ int ll_dir_getstripe(struct inode *inode, void **plmm, int *plmm_size,
                if (LMV_USER_MAGIC != cpu_to_le32(LMV_USER_MAGIC))
                        lustre_swab_lmv_user_md((struct lmv_user_md *)lmm);
                break;
-       case LOV_USER_MAGIC_SPECIFIC: {
-               struct lov_user_md_v3 *v3 = (struct lov_user_md_v3 *)lmm;
-
-               if (LOV_MAGIC != cpu_to_le32(LOV_MAGIC)) {
-                       lustre_swab_lov_user_md_v3(v3);
-                       lustre_swab_lov_user_md_objects(v3->lmm_objects,
-                                                       v3->lmm_stripe_count);
-                       }
-               }
-               break;
        case LMV_MAGIC_FOREIGN: {
                struct lmv_foreign_md *lfm = (struct lmv_foreign_md *)lmm;
 
index e081f33..e36bb37 100644 (file)
@@ -2015,6 +2015,12 @@ int ll_lov_setstripe_ea_info(struct inode *inode, struct dentry *dentry,
        int rc;
        ENTRY;
 
+       if ((__swab32(lum->lmm_magic) & le32_to_cpu(LOV_MAGIC_MASK)) ==
+           le32_to_cpu(LOV_MAGIC_MAGIC)) {
+               /* this code will only exist for big-endian systems */
+               lustre_swab_lov_user_md(lum);
+       }
+
        ll_inode_size_lock(inode);
        rc = ll_intent_file_open(dentry, lum, lum_size, &oit);
        if (rc < 0)
@@ -2078,13 +2084,14 @@ int ll_lov_getstripe_ea_info(struct inode *inode, const char *filename,
            lmm->lmm_magic != cpu_to_le32(LOV_MAGIC_FOREIGN))
                GOTO(out, rc = -EPROTO);
 
-        /*
-         * This is coming from the MDS, so is probably in
-         * little endian.  We convert it to host endian before
-         * passing it to userspace.
-         */
-        if (LOV_MAGIC != cpu_to_le32(LOV_MAGIC)) {
-               int stripe_count;
+       /*
+        * This is coming from the MDS, so is probably in
+        * little endian.  We convert it to host endian before
+        * passing it to userspace.
+        */
+       if ((lmm->lmm_magic & __swab32(LOV_MAGIC_MAGIC)) ==
+           __swab32(LOV_MAGIC_MAGIC)) {
+               int stripe_count = 0;
 
                if (lmm->lmm_magic == cpu_to_le32(LOV_MAGIC_V1) ||
                    lmm->lmm_magic == cpu_to_le32(LOV_MAGIC_V3)) {
@@ -2094,36 +2101,19 @@ int ll_lov_getstripe_ea_info(struct inode *inode, const char *filename,
                                stripe_count = 0;
                }
 
-                /* if function called for directory - we should
-                 * avoid swab not existent lsm objects */
-                if (lmm->lmm_magic == cpu_to_le32(LOV_MAGIC_V1)) {
-                       lustre_swab_lov_user_md_v1(
-                                       (struct lov_user_md_v1 *)lmm);
-                       if (S_ISREG(body->mbo_mode))
-                               lustre_swab_lov_user_md_objects(
-                                   ((struct lov_user_md_v1 *)lmm)->lmm_objects,
-                                   stripe_count);
-               } else if (lmm->lmm_magic == cpu_to_le32(LOV_MAGIC_V3)) {
-                       lustre_swab_lov_user_md_v3(
-                                       (struct lov_user_md_v3 *)lmm);
-                       if (S_ISREG(body->mbo_mode))
-                               lustre_swab_lov_user_md_objects(
-                                   ((struct lov_user_md_v3 *)lmm)->lmm_objects,
-                                   stripe_count);
-               } else if (lmm->lmm_magic ==
-                          cpu_to_le32(LOV_MAGIC_COMP_V1)) {
-                       lustre_swab_lov_comp_md_v1(
-                                       (struct lov_comp_md_v1 *)lmm);
-               } else if (lmm->lmm_magic ==
-                          cpu_to_le32(LOV_MAGIC_FOREIGN)) {
-                       struct lov_foreign_md *lfm;
-
-                       lfm = (struct lov_foreign_md *)lmm;
-                       __swab32s(&lfm->lfm_magic);
-                       __swab32s(&lfm->lfm_length);
-                       __swab32s(&lfm->lfm_type);
-                       __swab32s(&lfm->lfm_flags);
-               }
+               lustre_swab_lov_user_md((struct lov_user_md *)lmm);
+
+               /* if function called for directory - we should
+                * avoid swab not existent lsm objects */
+               if (lmm->lmm_magic == LOV_MAGIC_V1 && S_ISREG(body->mbo_mode))
+                       lustre_swab_lov_user_md_objects(
+                               ((struct lov_user_md_v1 *)lmm)->lmm_objects,
+                               stripe_count);
+               else if (lmm->lmm_magic == LOV_MAGIC_V3 &&
+                        S_ISREG(body->mbo_mode))
+                       lustre_swab_lov_user_md_objects(
+                               ((struct lov_user_md_v3 *)lmm)->lmm_objects,
+                               stripe_count);
        }
 
 out:
@@ -2210,7 +2200,7 @@ static int ll_lov_setstripe(struct inode *inode, struct file *file,
        cl_lov_delay_create_clear(&file->f_flags);
 
 out:
-       OBD_FREE(klum, lum_size);
+       OBD_FREE_LARGE(klum, lum_size);
        RETURN(rc);
 }
 
index 5ba34db..eda3627 100644 (file)
@@ -2880,12 +2880,12 @@ ssize_t ll_copy_user_md(const struct lov_user_md __user *md,
        if (lum_size < 0)
                RETURN(lum_size);
 
-       OBD_ALLOC(*kbuf, lum_size);
+       OBD_ALLOC_LARGE(*kbuf, lum_size);
        if (*kbuf == NULL)
                RETURN(-ENOMEM);
 
        if (copy_from_user(*kbuf, md, lum_size) != 0) {
-               OBD_FREE(*kbuf, lum_size);
+               OBD_FREE_LARGE(*kbuf, lum_size);
                RETURN(-EFAULT);
        }
 
index 7abc814..1bf2819 100644 (file)
@@ -41,6 +41,7 @@
 #include <obd_support.h>
 #include <lustre_dlm.h>
 #include <lustre_eacl.h>
+#include <lustre_swab.h>
 
 #include "llite_internal.h"
 
@@ -329,6 +330,11 @@ static int ll_xattr_set(const struct xattr_handler *handler,
                return 0;
        }
 
+       if (strncmp(name, "lov.", 4) == 0 &&
+           (__swab32(((struct lov_user_md *)value)->lmm_magic) &
+           le32_to_cpu(LOV_MAGIC_MASK)) == le32_to_cpu(LOV_MAGIC_MAGIC))
+               lustre_swab_lov_user_md((struct lov_user_md *)value);
+
        return ll_xattr_set_common(handler, dentry, inode, name, value, size,
                                   flags);
 }
@@ -498,10 +504,24 @@ static ssize_t ll_getxattr_lov(struct inode *inode, void *buf, size_t buf_size)
                 * file is restored. See LU-2809.
                 */
                magic = ((struct lov_mds_md *)buf)->lmm_magic;
-               if (magic == LOV_MAGIC_COMP_V1 || magic == LOV_MAGIC_FOREIGN)
+               if ((magic & __swab32(LOV_MAGIC_MAGIC)) ==
+                   __swab32(LOV_MAGIC_MAGIC))
+                       magic = __swab32(magic);
+
+               switch (magic) {
+               case LOV_MAGIC_V1:
+               case LOV_MAGIC_V3:
+               case LOV_MAGIC_SPECIFIC:
+                       ((struct lov_mds_md *)buf)->lmm_layout_gen = 0;
+                       break;
+               case LOV_MAGIC_COMP_V1:
+               case LOV_MAGIC_FOREIGN:
                        goto out_env;
+               default:
+                       CERROR("Invalid LOV magic %08x\n", magic);
+                       GOTO(out_env, rc = -EINVAL);
+               }
 
-               ((struct lov_mds_md *)buf)->lmm_layout_gen = 0;
 out_env:
                cl_env_put(env, &refcheck);
 
index fa6bc0f..7a05a90 100644 (file)
@@ -2141,6 +2141,8 @@ void lustre_swab_lmv_user_md(struct lmv_user_md *lum)
        if (lum->lum_magic == LMV_MAGIC_FOREIGN) {
                __swab32s(&lum->lum_magic);
                __swab32s(&((struct lmv_foreign_md *)lum)->lfm_length);
+               __swab32s(&((struct lmv_foreign_md *)lum)->lfm_type);
+               __swab32s(&((struct lmv_foreign_md *)lum)->lfm_flags);
                return;
        }
 
@@ -2354,20 +2356,6 @@ void lustre_swab_lov_comp_md_v1(struct lov_comp_md_v1 *lum)
 }
 EXPORT_SYMBOL(lustre_swab_lov_comp_md_v1);
 
-void lustre_swab_lov_mds_md(struct lov_mds_md *lmm)
-{
-       ENTRY;
-       CDEBUG(D_IOCTL, "swabbing lov_mds_md\n");
-       __swab32s(&lmm->lmm_magic);
-       __swab32s(&lmm->lmm_pattern);
-       lustre_swab_lmm_oi(&lmm->lmm_oi);
-       __swab32s(&lmm->lmm_stripe_size);
-       __swab16s(&lmm->lmm_stripe_count);
-       __swab16s(&lmm->lmm_layout_gen);
-       EXIT;
-}
-EXPORT_SYMBOL(lustre_swab_lov_mds_md);
-
 void lustre_swab_lov_user_md_objects(struct lov_user_ost_data *lod,
                                      int stripe_count)
 {
@@ -2382,6 +2370,67 @@ void lustre_swab_lov_user_md_objects(struct lov_user_ost_data *lod,
 }
 EXPORT_SYMBOL(lustre_swab_lov_user_md_objects);
 
+void lustre_swab_lov_user_md(struct lov_user_md *lum)
+{
+       ENTRY;
+
+       CDEBUG(D_IOCTL, "swabbing lov_user_md\n");
+       switch (lum->lmm_magic) {
+       case __swab32(LOV_MAGIC_V1):
+       case LOV_USER_MAGIC_V1:
+               lustre_swab_lov_user_md_v1((struct lov_user_md_v1 *)lum);
+               break;
+       case __swab32(LOV_MAGIC_V3):
+       case LOV_USER_MAGIC_V3:
+               lustre_swab_lov_user_md_v3((struct lov_user_md_v3 *)lum);
+               break;
+       case __swab32(LOV_USER_MAGIC_SPECIFIC):
+       case LOV_USER_MAGIC_SPECIFIC:
+       {
+               struct lov_user_md_v3 *v3 = (struct lov_user_md_v3 *)lum;
+               __u16 stripe_count = v3->lmm_stripe_count;
+
+               if (lum->lmm_magic != LOV_USER_MAGIC_SPECIFIC)
+                       __swab16s(&stripe_count);
+
+               lustre_swab_lov_user_md_v3(v3);
+               lustre_swab_lov_user_md_objects(v3->lmm_objects, stripe_count);
+               break;
+       }
+       case __swab32(LOV_MAGIC_COMP_V1):
+       case LOV_USER_MAGIC_COMP_V1:
+               lustre_swab_lov_comp_md_v1((struct lov_comp_md_v1 *)lum);
+               break;
+       case __swab32(LOV_MAGIC_FOREIGN):
+       case LOV_USER_MAGIC_FOREIGN:
+       {
+               struct lov_foreign_md *lfm = (struct lov_foreign_md *)lum;
+               __swab32s(&lfm->lfm_magic);
+               __swab32s(&lfm->lfm_length);
+               __swab32s(&lfm->lfm_type);
+               __swab32s(&lfm->lfm_flags);
+               break;
+       }
+       default:
+               CDEBUG(D_IOCTL, "Invalid LOV magic %08x\n", lum->lmm_magic);
+       }
+}
+EXPORT_SYMBOL(lustre_swab_lov_user_md);
+
+void lustre_swab_lov_mds_md(struct lov_mds_md *lmm)
+{
+       ENTRY;
+       CDEBUG(D_IOCTL, "swabbing lov_mds_md\n");
+       __swab32s(&lmm->lmm_magic);
+       __swab32s(&lmm->lmm_pattern);
+       lustre_swab_lmm_oi(&lmm->lmm_oi);
+       __swab32s(&lmm->lmm_stripe_size);
+       __swab16s(&lmm->lmm_stripe_count);
+       __swab16s(&lmm->lmm_layout_gen);
+       EXIT;
+}
+EXPORT_SYMBOL(lustre_swab_lov_mds_md);
+
 void lustre_swab_ldlm_res_id (struct ldlm_res_id *id)
 {
         int  i;
index a0499bd..83fb763 100644 (file)
@@ -85,6 +85,13 @@ int main(int argc, char **argv)
                                lfm->lfm_length, len2);
        }
 
+       if (lfm->lfm_magic == bswap_32(LMV_MAGIC_FOREIGN)) {
+               lfm->lfm_magic = bswap_32(lfm->lfm_magic);
+               lfm->lfm_length = bswap_32(lfm->lfm_length);
+               lfm->lfm_type = bswap_32(lfm->lfm_type);
+               lfm->lfm_flags = bswap_32(lfm->lfm_flags);
+       }
+
        fprintf(stdout, "lmv_xattr_size: %zu\n", len2);
        fprintf(stdout, "lmv_foreign_magic: 0x%x\n", lfm->lfm_magic);
        fprintf(stdout, "lmv_foreign_size: %u\n", lfm->lfm_length);
index 5b2cddd..cb18b54 100644 (file)
@@ -85,6 +85,13 @@ int main(int argc, char **argv)
                                lfm->lfm_length, len2);
        }
 
+       if (lfm->lfm_magic == bswap_32(LOV_USER_MAGIC_FOREIGN)) {
+               lfm->lfm_magic = bswap_32(lfm->lfm_magic);
+               lfm->lfm_length = bswap_32(lfm->lfm_length);
+               lfm->lfm_type = bswap_32(lfm->lfm_type);
+               lfm->lfm_flags = bswap_32(lfm->lfm_flags);
+       }
+
        fprintf(stdout, "lov_xattr_size: %zu\n", len2);
        fprintf(stdout, "lov_foreign_magic: 0x%08X\n", lfm->lfm_magic);
        fprintf(stdout, "lov_foreign_size: %u\n", lfm->lfm_length);