From 9d17996766e0fa93b1029d2422d45d087edde389 Mon Sep 17 00:00:00 2001 From: Jian Yu Date: Sat, 20 Jul 2019 02:30:33 -0700 Subject: [PATCH] LU-10100 llite: swab LOV EA user data 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 Reviewed-on: https://review.whamcloud.com/35291 Tested-by: jenkins Reviewed-by: Andreas Dilger Tested-by: Maloo Reviewed-by: Patrick Farrell Reviewed-by: Lai Siyao Reviewed-by: Oleg Drokin --- lustre/include/lustre_swab.h | 1 + lustre/llite/dir.c | 109 +++++++++++++------------------------- lustre/llite/file.c | 66 ++++++++++------------- lustre/llite/llite_lib.c | 4 +- lustre/llite/xattr.c | 24 ++++++++- lustre/ptlrpc/pack_generic.c | 77 ++++++++++++++++++++++----- lustre/tests/parse_foreign_dir.c | 7 +++ lustre/tests/parse_foreign_file.c | 7 +++ 8 files changed, 168 insertions(+), 127 deletions(-) diff --git a/lustre/include/lustre_swab.h b/lustre/include/lustre_swab.h index cece542..ceaf9c9 100644 --- a/lustre/include/lustre_swab.h +++ b/lustre/include/lustre_swab.h @@ -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); diff --git a/lustre/llite/dir.c b/lustre/llite/dir.c index b2227af..57db3ac 100644 --- a/lustre/llite/dir.c +++ b/lustre/llite/dir.c @@ -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; diff --git a/lustre/llite/file.c b/lustre/llite/file.c index e081f33..e36bb37 100644 --- a/lustre/llite/file.c +++ b/lustre/llite/file.c @@ -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); } diff --git a/lustre/llite/llite_lib.c b/lustre/llite/llite_lib.c index 5ba34db..eda3627 100644 --- a/lustre/llite/llite_lib.c +++ b/lustre/llite/llite_lib.c @@ -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); } diff --git a/lustre/llite/xattr.c b/lustre/llite/xattr.c index 7abc814b..1bf2819 100644 --- a/lustre/llite/xattr.c +++ b/lustre/llite/xattr.c @@ -41,6 +41,7 @@ #include #include #include +#include #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); diff --git a/lustre/ptlrpc/pack_generic.c b/lustre/ptlrpc/pack_generic.c index fa6bc0f..7a05a90 100644 --- a/lustre/ptlrpc/pack_generic.c +++ b/lustre/ptlrpc/pack_generic.c @@ -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; diff --git a/lustre/tests/parse_foreign_dir.c b/lustre/tests/parse_foreign_dir.c index a0499bd..83fb763 100644 --- a/lustre/tests/parse_foreign_dir.c +++ b/lustre/tests/parse_foreign_dir.c @@ -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); diff --git a/lustre/tests/parse_foreign_file.c b/lustre/tests/parse_foreign_file.c index 5b2cddd..cb18b54 100644 --- a/lustre/tests/parse_foreign_file.c +++ b/lustre/tests/parse_foreign_file.c @@ -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); -- 1.8.3.1