+
+ if (loi - lsm->lsm_oinfo != lsm->lsm_stripe_count) {
+ CERROR("missing objects in lmm struct\n");
+ lov_dump_lmm_v0(D_WARNING, lmm);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int lov_unpackmd_v1(struct lov_obd *lov, struct lov_stripe_md *lsm,
+ struct lov_mds_md_v1 *lmm)
+{
+ struct lov_oinfo *loi;
+ int i;
+
+ lsm->lsm_object_id = le64_to_cpu(lmm->lmm_object_id);
+ lsm->lsm_object_gr = le64_to_cpu(lmm->lmm_object_gr);
+ lsm->lsm_stripe_size = le32_to_cpu(lmm->lmm_stripe_size);
+ lsm->lsm_pattern = le32_to_cpu(lmm->lmm_pattern);
+ lsm->lsm_xfersize = lsm->lsm_stripe_size * lsm->lsm_stripe_count;
+
+ for (i = 0, loi = lsm->lsm_oinfo; i < lsm->lsm_stripe_count; i++) {
+ /* XXX LOV STACKING call down to osc_unpackmd() */
+ loi->loi_id = le64_to_cpu(lmm->lmm_objects[i].l_object_id);
+ loi->loi_gr = le64_to_cpu(lmm->lmm_objects[i].l_object_gr);
+ loi->loi_ost_idx = le32_to_cpu(lmm->lmm_objects[i].l_ost_idx);
+ loi->loi_ost_gen = le32_to_cpu(lmm->lmm_objects[i].l_ost_gen);
+ if (loi->loi_ost_idx > lov->desc.ld_tgt_count) {
+ CERROR("OST index %d more than OST count %d\n",
+ loi->loi_ost_idx, lov->desc.ld_tgt_count);
+ lov_dump_lmm_v1(D_WARNING, lmm);
+ return -EINVAL;
+ }
+ loi++;
+ }
+
+ return 0;
+}
+
+/* Unpack LOV object metadata from disk storage. It is packed in LE byte
+ * order and is opaque to the networking layer.
+ */
+int lov_unpackmd(struct obd_export *exp, struct lov_stripe_md **lsmp,
+ struct lov_mds_md *lmm, int lmm_bytes)
+{
+ struct obd_device *obd = class_exp2obd(exp);
+ struct lov_obd *lov = &obd->u.lov;
+ int rc = 0, stripe_count, lsm_size;
+ ENTRY;
+
+ /* If passed an MDS struct use values from there, otherwise defaults */
+ if (lmm) {
+ rc = lov_verify_lmm(lmm, lmm_bytes, &stripe_count);
+ if (rc)
+ RETURN(rc);
+ } else {
+ stripe_count = lov_get_stripecnt(lov, 0);
+ }
+
+ /* If we aren't passed an lsmp struct, we just want the size */
+ if (!lsmp)
+ /* XXX LOV STACKING call into osc for sizes */
+ RETURN(lov_stripe_md_size(stripe_count));
+
+ /* If we are passed an allocated struct but nothing to unpack, free */
+ if (*lsmp && !lmm) {
+ lov_free_memmd(lsmp);
+ RETURN(0);
+ }
+
+ lsm_size = lov_alloc_memmd(lsmp, stripe_count, LOV_PATTERN_RAID0);
+ if (lsm_size < 0)
+ RETURN(lsm_size);
+
+ /* If we are passed a pointer but nothing to unpack, we only alloc */
+ if (!lmm)
+ RETURN(lsm_size);
+
+ switch (le32_to_cpu(lmm->lmm_magic)) {
+ case LOV_MAGIC_V1:
+ rc = lov_unpackmd_v1(lov, *lsmp, lmm);
+ break;
+ case LOV_MAGIC_V0:
+ rc = lov_unpackmd_v0(lov, *lsmp, (void *)lmm);
+ break;
+ }
+
+ if (rc) {
+ lov_free_memmd(lsmp);
+ RETURN(rc);
+ }