Whamcloud - gitweb
LU-9490 llite: return v1/v3 layout for legacy app
[fs/lustre-release.git] / lustre / lov / lov_pack.c
index 67dd99d..baff061 100644 (file)
@@ -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: