From 545f464b68ee21ccc425113db9b57c63ac2840b1 Mon Sep 17 00:00:00 2001 From: Niu Yawei Date: Thu, 18 May 2017 03:12:54 -0400 Subject: [PATCH] LU-9490 llite: return v1/v3 layout for legacy app Legacy app such as ADIO fetches LOVEA by ioctl LL_IOC_LOV_GETSTRIPE and treats file layout as v1/v3 blindly, we'd return a reasonable v1/v3 in this case. Signed-off-by: Niu Yawei Change-Id: I95694c3e32013c75da097f2f6ae4e8915503596e Reviewed-on: https://review.whamcloud.com/27183 Tested-by: Jenkins Tested-by: Maloo Reviewed-by: Bobi Jam Reviewed-by: Andreas Dilger Reviewed-by: Oleg Drokin --- lustre/lov/lov_cl_internal.h | 4 +-- lustre/lov/lov_object.c | 2 +- lustre/lov/lov_pack.c | 67 +++++++++++++++++++++++++++++++++++++++----- 3 files changed, 63 insertions(+), 10 deletions(-) diff --git a/lustre/lov/lov_cl_internal.h b/lustre/lov/lov_cl_internal.h index 395b5f9..e16a6aa 100644 --- a/lustre/lov/lov_cl_internal.h +++ b/lustre/lov/lov_cl_internal.h @@ -652,8 +652,8 @@ static inline struct lov_stripe_md_entry *lov_lse(struct lov_object *lov, int i) } /* lov_pack.c */ -int lov_getstripe(struct lov_object *obj, struct lov_stripe_md *lsm, - struct lov_user_md __user *lump); +int lov_getstripe(const struct lu_env *env, struct lov_object *obj, + struct lov_stripe_md *lsm, struct lov_user_md __user *lump); /** @} lov */ diff --git a/lustre/lov/lov_object.c b/lustre/lov/lov_object.c index 65e20be..614ca03 100644 --- a/lustre/lov/lov_object.c +++ b/lustre/lov/lov_object.c @@ -1613,7 +1613,7 @@ static int lov_object_getstripe(const struct lu_env *env, struct cl_object *obj, if (lsm == NULL) RETURN(-ENODATA); - rc = lov_getstripe(cl2lov(obj), lsm, lum); + rc = lov_getstripe(env, cl2lov(obj), lsm, lum); lov_lsm_put(lsm); RETURN(rc); } diff --git a/lustre/lov/lov_pack.c b/lustre/lov/lov_pack.c index 67dd99d..baff061 100644 --- a/lustre/lov/lov_pack.c +++ b/lustre/lov/lov_pack.c @@ -342,14 +342,16 @@ struct lov_stripe_md *lov_unpackmd(struct lov_obd *lov, void *buf, * the maximum number of OST indices which will fit in the user buffer. * lmm_magic must be LOV_USER_MAGIC. */ -int lov_getstripe(struct lov_object *obj, struct lov_stripe_md *lsm, - struct lov_user_md __user *lump) +int lov_getstripe(const struct lu_env *env, struct lov_object *obj, + struct lov_stripe_md *lsm, struct lov_user_md __user *lump) { /* we use lov_user_md_v3 because it is larger than lov_user_md_v1 */ - struct lov_mds_md *lmmk; - size_t lmmk_size; - ssize_t lmm_size; - int rc = 0; + struct lov_mds_md *lmmk; + struct lov_user_md_v1 lum; + size_t lmmk_size; + ssize_t lmm_size, lum_size = 0; + static bool printed; + int rc = 0; ENTRY; if (lsm->lsm_magic != LOV_MAGIC_V1 && lsm->lsm_magic != LOV_MAGIC_V3 && @@ -359,6 +361,14 @@ int lov_getstripe(struct lov_object *obj, struct lov_stripe_md *lsm, GOTO(out, rc = -EIO); } + if (!printed) { + LCONSOLE_WARN("%s: using old ioctl(LL_IOC_LOV_GETSTRIPE) on " + DFID", use llapi_layout_get_by_path()\n", + current->comm, + PFID(&obj->lo_cl.co_lu.lo_header->loh_fid)); + printed = true; + } + lmmk_size = lov_comp_md_size(lsm); OBD_ALLOC_LARGE(lmmk, lmmk_size); @@ -382,9 +392,52 @@ int lov_getstripe(struct lov_object *obj, struct lov_stripe_md *lsm, } } - if (copy_to_user(lump, lmmk, lmmk_size)) + /* Legacy appication passes limited buffer, we need to figure out + * the user buffer size by the passed in lmm_stripe_count. */ + if (copy_from_user(&lum, lump, sizeof(struct lov_user_md_v1))) GOTO(out_free, rc = -EFAULT); + if (lum.lmm_magic == LOV_USER_MAGIC_V1 || + lum.lmm_magic == LOV_USER_MAGIC_V3) + lum_size = lov_user_md_size(lum.lmm_stripe_count, + lum.lmm_magic); + + if (lum_size != 0) { + struct lov_mds_md *comp_md = lmmk; + + /* Legacy app (ADIO for instance) treats the layout as V1/V3 + * blindly, we'd return a reasonable V1/V3 for them. */ + if (lmmk->lmm_magic == LOV_MAGIC_COMP_V1) { + struct lov_comp_md_v1 *comp_v1; + struct cl_object *cl_obj; + struct cl_attr attr; + int i; + + attr.cat_size = 0; + cl_obj = cl_object_top(&obj->lo_cl); + cl_object_attr_get(env, cl_obj, &attr); + + /* return the last instantiated component if file size + * is non-zero, otherwise, return the last component.*/ + comp_v1 = (struct lov_comp_md_v1 *)lmmk; + i = attr.cat_size == 0 ? comp_v1->lcm_entry_count : 0; + for (; i < comp_v1->lcm_entry_count; i++) { + if (!(comp_v1->lcm_entries[i].lcme_flags & + LCME_FL_INIT)) + break; + } + if (i > 0) + i--; + comp_md = (struct lov_mds_md *)((char *)comp_v1 + + comp_v1->lcm_entries[i].lcme_offset); + } + if (copy_to_user(lump, comp_md, lum_size)) + GOTO(out_free, rc = -EFAULT); + } else { + if (copy_to_user(lump, lmmk, lmmk_size)) + GOTO(out_free, rc = -EFAULT); + } + out_free: OBD_FREE_LARGE(lmmk, lmmk_size); out: -- 1.8.3.1