static int lsm_lmm_verify_v3(struct lov_mds_md *lmmv1, int lmm_bytes, __u16 *stripe_count) { struct lov_mds_md_v3 *lmm; lmm = (struct lov_mds_md_v3 *)lmmv1; if (lmm_bytes < sizeof(*lmm)) { CERROR("lov_mds_md_v3 too small: %d, need at least %d\n", lmm_bytes, (int)sizeof(*lmm)); return -EINVAL; } *stripe_count = le16_to_cpu(lmm->lmm_stripe_count); if (lmm_bytes < lov_mds_md_size(*stripe_count, LOV_MAGIC_V3)) { CERROR("LOV EA V3 too small: %d, need %d\n", lmm_bytes, lov_mds_md_size(*stripe_count, LOV_MAGIC_V3)); lov_dump_lmm_common(D_WARNING, lmm); return -EINVAL; } return lsm_lmm_verify_common((struct lov_mds_md_v1 *)lmm, lmm_bytes, *stripe_count); }
static int lov_object_layout_get(const struct lu_env *env, struct cl_object *obj, struct cl_layout *cl) { struct lov_object *lov = cl2lov(obj); struct lov_stripe_md *lsm = lov_lsm_addref(lov); struct lu_buf *buf = &cl->cl_buf; ssize_t rc; ENTRY; if (lsm == NULL) { cl->cl_size = 0; cl->cl_layout_gen = CL_LAYOUT_GEN_EMPTY; RETURN(0); } cl->cl_size = lov_mds_md_size(lsm->lsm_stripe_count, lsm->lsm_magic); cl->cl_layout_gen = lsm->lsm_layout_gen; rc = lov_lsm_pack(lsm, buf->lb_buf, buf->lb_len); lov_lsm_put(lsm); RETURN(rc < 0 ? rc : 0); }
/** * Pack LOV striping metadata for disk storage format (in little * endian byte order). * * This follows the getxattr() conventions. If \a buf_size is zero * then return the size needed. If \a buf_size is too small then * return -ERANGE. Otherwise return the size of the result. */ ssize_t lov_lsm_pack_v1v3(const struct lov_stripe_md *lsm, void *buf, size_t buf_size) { struct lov_mds_md_v1 *lmmv1 = buf; struct lov_mds_md_v3 *lmmv3 = buf; struct lov_ost_data_v1 *lmm_objects; size_t lmm_size; unsigned int i; ENTRY; lmm_size = lov_mds_md_size(lsm->lsm_entries[0]->lsme_stripe_count, lsm->lsm_magic); if (buf_size == 0) RETURN(lmm_size); if (buf_size < lmm_size) RETURN(-ERANGE); /* lmmv1 and lmmv3 point to the same struct and have the * same first fields */ lmmv1->lmm_magic = cpu_to_le32(lsm->lsm_magic); lmm_oi_cpu_to_le(&lmmv1->lmm_oi, &lsm->lsm_oi); lmmv1->lmm_stripe_size = cpu_to_le32( lsm->lsm_entries[0]->lsme_stripe_size); lmmv1->lmm_stripe_count = cpu_to_le16( lsm->lsm_entries[0]->lsme_stripe_count); lmmv1->lmm_pattern = cpu_to_le32(lsm->lsm_entries[0]->lsme_pattern); lmmv1->lmm_layout_gen = cpu_to_le16(lsm->lsm_layout_gen); if (lsm->lsm_magic == LOV_MAGIC_V3) { CLASSERT(sizeof(lsm->lsm_entries[0]->lsme_pool_name) == sizeof(lmmv3->lmm_pool_name)); strlcpy(lmmv3->lmm_pool_name, lsm->lsm_entries[0]->lsme_pool_name, sizeof(lmmv3->lmm_pool_name)); lmm_objects = lmmv3->lmm_objects; } else { lmm_objects = lmmv1->lmm_objects; } if (lsm->lsm_is_released) RETURN(lmm_size); for (i = 0; i < lsm->lsm_entries[0]->lsme_stripe_count; i++) { struct lov_oinfo *loi = lsm->lsm_entries[0]->lsme_oinfo[i]; ostid_cpu_to_le(&loi->loi_oi, &lmm_objects[i].l_ost_oi); lmm_objects[i].l_ost_gen = cpu_to_le32(loi->loi_ost_gen); lmm_objects[i].l_ost_idx = cpu_to_le32(loi->loi_ost_idx); } RETURN(lmm_size); }
static int lsm_lmm_verify_v1(struct lov_mds_md_v1 *lmm, int lmm_bytes, __u16 *stripe_count) { if (lmm_bytes < sizeof(*lmm)) { CERROR("lov_mds_md_v1 too small: %d, need at least %d\n", lmm_bytes, (int)sizeof(*lmm)); return -EINVAL; } *stripe_count = le16_to_cpu(lmm->lmm_stripe_count); if (le32_to_cpu(lmm->lmm_pattern) & LOV_PATTERN_F_RELEASED) *stripe_count = 0; if (lmm_bytes < lov_mds_md_size(*stripe_count, LOV_MAGIC_V1)) { CERROR("LOV EA V1 too small: %d, need %d\n", lmm_bytes, lov_mds_md_size(*stripe_count, LOV_MAGIC_V1)); lov_dump_lmm_common(D_WARNING, lmm); return -EINVAL; } return lsm_lmm_verify_common(lmm, lmm_bytes, *stripe_count); }
/** * Pack LOV striping metadata for disk storage format (in little * endian byte order). * * This follows the getxattr() conventions. If \a buf_size is zero * then return the size needed. If \a buf_size is too small then * return -ERANGE. Otherwise return the size of the result. */ ssize_t lov_lsm_pack(const struct lov_stripe_md *lsm, void *buf, size_t buf_size) { struct lov_ost_data_v1 *lmm_objects; struct lov_mds_md_v1 *lmmv1 = buf; struct lov_mds_md_v3 *lmmv3 = buf; size_t lmm_size; unsigned int i; lmm_size = lov_mds_md_size(lsm->lsm_stripe_count, lsm->lsm_magic); if (!buf_size) return lmm_size; if (buf_size < lmm_size) return -ERANGE; /* * lmmv1 and lmmv3 point to the same struct and have the * same first fields */ lmmv1->lmm_magic = cpu_to_le32(lsm->lsm_magic); lmm_oi_cpu_to_le(&lmmv1->lmm_oi, &lsm->lsm_oi); lmmv1->lmm_stripe_size = cpu_to_le32(lsm->lsm_stripe_size); lmmv1->lmm_stripe_count = cpu_to_le16(lsm->lsm_stripe_count); lmmv1->lmm_pattern = cpu_to_le32(lsm->lsm_pattern); lmmv1->lmm_layout_gen = cpu_to_le16(lsm->lsm_layout_gen); if (lsm->lsm_magic == LOV_MAGIC_V3) { BUILD_BUG_ON(sizeof(lsm->lsm_pool_name) != sizeof(lmmv3->lmm_pool_name)); strlcpy(lmmv3->lmm_pool_name, lsm->lsm_pool_name, sizeof(lmmv3->lmm_pool_name)); lmm_objects = lmmv3->lmm_objects; } else { lmm_objects = lmmv1->lmm_objects; } for (i = 0; i < lsm->lsm_stripe_count; i++) { struct lov_oinfo *loi = lsm->lsm_oinfo[i]; ostid_cpu_to_le(&loi->loi_oi, &lmm_objects[i].l_ost_oi); lmm_objects[i].l_ost_gen = cpu_to_le32(loi->loi_ost_gen); lmm_objects[i].l_ost_idx = cpu_to_le32(loi->loi_ost_idx); } return lmm_size; }
ssize_t lov_lsm_pack(const struct lov_stripe_md *lsm, void *buf, size_t buf_size) { struct lov_comp_md_v1 *lcmv1 = buf; struct lov_comp_md_entry_v1 *lcme; struct lov_ost_data_v1 *lmm_objects; size_t lmm_size; unsigned int entry; unsigned int offset; unsigned int size; unsigned int i; ENTRY; if (lsm->lsm_magic == LOV_MAGIC_V1 || lsm->lsm_magic == LOV_MAGIC_V3) return lov_lsm_pack_v1v3(lsm, buf, buf_size); lmm_size = lov_comp_md_size(lsm); if (buf_size == 0) RETURN(lmm_size); if (buf_size < lmm_size) RETURN(-ERANGE); lcmv1->lcm_magic = cpu_to_le32(lsm->lsm_magic); lcmv1->lcm_size = cpu_to_le32(lmm_size); lcmv1->lcm_layout_gen = cpu_to_le32(lsm->lsm_layout_gen); lcmv1->lcm_flags = cpu_to_le16(lsm->lsm_flags); lcmv1->lcm_mirror_count = cpu_to_le16(lsm->lsm_mirror_count); lcmv1->lcm_entry_count = cpu_to_le16(lsm->lsm_entry_count); offset = sizeof(*lcmv1) + sizeof(*lcme) * lsm->lsm_entry_count; for (entry = 0; entry < lsm->lsm_entry_count; entry++) { struct lov_stripe_md_entry *lsme; struct lov_mds_md *lmm; __u16 stripe_count; lsme = lsm->lsm_entries[entry]; lcme = &lcmv1->lcm_entries[entry]; lcme->lcme_id = cpu_to_le32(lsme->lsme_id); lcme->lcme_flags = cpu_to_le32(lsme->lsme_flags); lcme->lcme_extent.e_start = cpu_to_le64(lsme->lsme_extent.e_start); lcme->lcme_extent.e_end = cpu_to_le64(lsme->lsme_extent.e_end); lcme->lcme_offset = cpu_to_le32(offset); lmm = (struct lov_mds_md *)((char *)lcmv1 + offset); lmm->lmm_magic = cpu_to_le32(lsme->lsme_magic); /* lmm->lmm_oi not set */ lmm->lmm_pattern = cpu_to_le32(lsme->lsme_pattern); lmm->lmm_stripe_size = cpu_to_le32(lsme->lsme_stripe_size); lmm->lmm_stripe_count = cpu_to_le16(lsme->lsme_stripe_count); lmm->lmm_layout_gen = cpu_to_le16(lsme->lsme_layout_gen); if (lsme->lsme_magic == LOV_MAGIC_V3) { struct lov_mds_md_v3 *lmmv3 = (struct lov_mds_md_v3 *)lmm; strlcpy(lmmv3->lmm_pool_name, lsme->lsme_pool_name, sizeof(lmmv3->lmm_pool_name)); lmm_objects = lmmv3->lmm_objects; } else { lmm_objects = ((struct lov_mds_md_v1 *)lmm)->lmm_objects; } if (lsme_inited(lsme) && !(lsme->lsme_pattern & LOV_PATTERN_F_RELEASED)) stripe_count = lsme->lsme_stripe_count; else stripe_count = 0; for (i = 0; i < stripe_count; i++) { struct lov_oinfo *loi = lsme->lsme_oinfo[i]; ostid_cpu_to_le(&loi->loi_oi, &lmm_objects[i].l_ost_oi); lmm_objects[i].l_ost_gen = cpu_to_le32(loi->loi_ost_gen); lmm_objects[i].l_ost_idx = cpu_to_le32(loi->loi_ost_idx); } size = lov_mds_md_size(stripe_count, lsme->lsme_magic); lcme->lcme_size = cpu_to_le32(size); offset += size; } /* for each layout component */ RETURN(lmm_size); }
static int __lov_setstripe(struct obd_export *exp, int max_lmm_size, struct lov_stripe_md **lsmp, struct lov_user_md *lump) { struct obd_device *obd = class_exp2obd(exp); struct lov_obd *lov = &obd->u.lov; char buffer[sizeof(struct lov_user_md_v3)]; struct lov_user_md_v3 *lumv3 = (struct lov_user_md_v3 *)&buffer[0]; struct lov_user_md_v1 *lumv1 = (struct lov_user_md_v1 *)&buffer[0]; int lmm_magic; __u16 stripe_count; int rc; int cplen = 0; rc = lov_lum_swab_if_needed(lumv3, &lmm_magic, lump); if (rc) return rc; /* in the rest of the tests, as *lumv1 and lumv3 have the same * fields, we use lumv1 to avoid code duplication */ if (lumv1->lmm_pattern == 0) { lumv1->lmm_pattern = lov->desc.ld_pattern ? lov->desc.ld_pattern : LOV_PATTERN_RAID0; } if (lov_pattern(lumv1->lmm_pattern) != LOV_PATTERN_RAID0) { CDEBUG(D_IOCTL, "bad userland stripe pattern: %#x\n", lumv1->lmm_pattern); return -EINVAL; } /* 64kB is the largest common page size we see (ia64), and matches the * check in lfs */ if (lumv1->lmm_stripe_size & (LOV_MIN_STRIPE_SIZE - 1)) { CDEBUG(D_IOCTL, "stripe size %u not multiple of %u, fixing\n", lumv1->lmm_stripe_size, LOV_MIN_STRIPE_SIZE); lumv1->lmm_stripe_size = LOV_MIN_STRIPE_SIZE; } if ((lumv1->lmm_stripe_offset >= lov->desc.ld_tgt_count) && (lumv1->lmm_stripe_offset != (typeof(lumv1->lmm_stripe_offset))(-1))) { CDEBUG(D_IOCTL, "stripe offset %u > number of OSTs %u\n", lumv1->lmm_stripe_offset, lov->desc.ld_tgt_count); return -EINVAL; } stripe_count = lov_get_stripecnt(lov, lmm_magic, lumv1->lmm_stripe_count); if (max_lmm_size) { int max_stripes = (max_lmm_size - lov_mds_md_size(0, lmm_magic)) / sizeof(struct lov_ost_data_v1); if (unlikely(max_stripes < stripe_count)) { CDEBUG(D_IOCTL, "stripe count reset from %d to %d\n", stripe_count, max_stripes); stripe_count = max_stripes; } } if (lmm_magic == LOV_USER_MAGIC_V3) { struct pool_desc *pool; /* In the function below, .hs_keycmp resolves to * pool_hashkey_keycmp() */ /* coverity[overrun-buffer-val] */ pool = lov_find_pool(lov, lumv3->lmm_pool_name); if (pool != NULL) { if (lumv3->lmm_stripe_offset != (typeof(lumv3->lmm_stripe_offset))(-1)) { rc = lov_check_index_in_pool( lumv3->lmm_stripe_offset, pool); if (rc < 0) { lov_pool_putref(pool); return -EINVAL; } } if (stripe_count > pool_tgt_count(pool)) stripe_count = pool_tgt_count(pool); lov_pool_putref(pool); } } if (lumv1->lmm_pattern & LOV_PATTERN_F_RELEASED) stripe_count = 0; rc = lov_alloc_memmd(lsmp, stripe_count, lumv1->lmm_pattern, lmm_magic); if (rc >= 0) { (*lsmp)->lsm_oinfo[0]->loi_ost_idx = lumv1->lmm_stripe_offset; (*lsmp)->lsm_stripe_size = lumv1->lmm_stripe_size; if (lmm_magic == LOV_USER_MAGIC_V3) { cplen = strlcpy((*lsmp)->lsm_pool_name, lumv3->lmm_pool_name, sizeof((*lsmp)->lsm_pool_name)); if (cplen >= sizeof((*lsmp)->lsm_pool_name)) rc = -E2BIG; } rc = 0; } return rc; }
/* Pack LOV object metadata for disk storage. It is packed in LE byte * order and is opaque to the networking layer. * * XXX In the future, this will be enhanced to get the EA size from the * underlying OSC device(s) to get their EA sizes so we can stack * LOVs properly. For now lov_mds_md_size() just assumes one obd_id * per stripe. */ int lov_packmd(struct obd_export *exp, struct lov_mds_md **lmmp, struct lov_stripe_md *lsm) { struct obd_device *obd = class_exp2obd(exp); struct lov_obd *lov = &obd->u.lov; struct lov_mds_md_v1 *lmmv1; struct lov_mds_md_v3 *lmmv3; __u16 stripe_count; struct lov_ost_data_v1 *lmm_objects; int lmm_size, lmm_magic; int i; int cplen = 0; if (lsm) { lmm_magic = lsm->lsm_magic; } else { if (lmmp && *lmmp) lmm_magic = le32_to_cpu((*lmmp)->lmm_magic); else /* lsm == NULL and lmmp == NULL */ lmm_magic = LOV_MAGIC; } if ((lmm_magic != LOV_MAGIC_V1) && (lmm_magic != LOV_MAGIC_V3)) { CERROR("bad mem LOV MAGIC: 0x%08X != 0x%08X nor 0x%08X\n", lmm_magic, LOV_MAGIC_V1, LOV_MAGIC_V3); return -EINVAL; } if (lsm) { /* If we are just sizing the EA, limit the stripe count * to the actual number of OSTs in this filesystem. */ if (!lmmp) { stripe_count = lov_get_stripecnt(lov, lmm_magic, lsm->lsm_stripe_count); lsm->lsm_stripe_count = stripe_count; } else if (!lsm_is_released(lsm)) { stripe_count = lsm->lsm_stripe_count; } else { stripe_count = 0; } } else { /* No need to allocate more than maximum supported stripes. * Anyway, this is pretty inaccurate since ld_tgt_count now * represents max index and we should rely on the actual number * of OSTs instead */ stripe_count = lov_mds_md_max_stripe_count( lov->lov_ocd.ocd_max_easize, lmm_magic); if (stripe_count > lov->desc.ld_tgt_count) stripe_count = lov->desc.ld_tgt_count; } /* XXX LOV STACKING call into osc for sizes */ lmm_size = lov_mds_md_size(stripe_count, lmm_magic); if (!lmmp) return lmm_size; if (*lmmp && !lsm) { stripe_count = le16_to_cpu((*lmmp)->lmm_stripe_count); lmm_size = lov_mds_md_size(stripe_count, lmm_magic); OBD_FREE_LARGE(*lmmp, lmm_size); *lmmp = NULL; return 0; } if (!*lmmp) { OBD_ALLOC_LARGE(*lmmp, lmm_size); if (!*lmmp) return -ENOMEM; } CDEBUG(D_INFO, "lov_packmd: LOV_MAGIC 0x%08X, lmm_size = %d \n", lmm_magic, lmm_size); lmmv1 = *lmmp; lmmv3 = (struct lov_mds_md_v3 *)*lmmp; if (lmm_magic == LOV_MAGIC_V3) lmmv3->lmm_magic = cpu_to_le32(LOV_MAGIC_V3); else lmmv1->lmm_magic = cpu_to_le32(LOV_MAGIC_V1); if (!lsm) return lmm_size; /* lmmv1 and lmmv3 point to the same struct and have the * same first fields */ lmm_oi_cpu_to_le(&lmmv1->lmm_oi, &lsm->lsm_oi); lmmv1->lmm_stripe_size = cpu_to_le32(lsm->lsm_stripe_size); lmmv1->lmm_stripe_count = cpu_to_le16(stripe_count); lmmv1->lmm_pattern = cpu_to_le32(lsm->lsm_pattern); lmmv1->lmm_layout_gen = cpu_to_le16(lsm->lsm_layout_gen); if (lsm->lsm_magic == LOV_MAGIC_V3) { cplen = strlcpy(lmmv3->lmm_pool_name, lsm->lsm_pool_name, sizeof(lmmv3->lmm_pool_name)); if (cplen >= sizeof(lmmv3->lmm_pool_name)) return -E2BIG; lmm_objects = lmmv3->lmm_objects; } else { lmm_objects = lmmv1->lmm_objects; } for (i = 0; i < stripe_count; i++) { struct lov_oinfo *loi = lsm->lsm_oinfo[i]; /* XXX LOV STACKING call down to osc_packmd() to do packing */ LASSERTF(ostid_id(&loi->loi_oi) != 0, "lmm_oi "DOSTID " stripe %u/%u idx %u\n", POSTID(&lmmv1->lmm_oi), i, stripe_count, loi->loi_ost_idx); ostid_cpu_to_le(&loi->loi_oi, &lmm_objects[i].l_ost_oi); lmm_objects[i].l_ost_gen = cpu_to_le32(loi->loi_ost_gen); lmm_objects[i].l_ost_idx = cpu_to_le32(loi->loi_ost_idx); } return lmm_size; }
static int __lov_setstripe(struct obd_export *exp, int max_lmm_size, struct lov_stripe_md **lsmp, struct lov_user_md *lump) { struct obd_device *obd = class_exp2obd(exp); struct lov_obd *lov = &obd->u.lov; char buffer[sizeof(struct lov_user_md_v3)]; struct lov_user_md_v3 *lumv3 = (struct lov_user_md_v3 *)&buffer[0]; struct lov_user_md_v1 *lumv1 = (struct lov_user_md_v1 *)&buffer[0]; int lmm_magic; int stripe_count; int rc; ENTRY; if (cfs_copy_from_user(lumv3, lump, sizeof(struct lov_user_md_v1))) RETURN(-EFAULT); lmm_magic = lumv1->lmm_magic; if (lmm_magic == __swab32(LOV_USER_MAGIC_V1)) { lustre_swab_lov_user_md_v1(lumv1); lmm_magic = LOV_USER_MAGIC_V1; } else if (lmm_magic == LOV_USER_MAGIC_V3) { if (cfs_copy_from_user(lumv3, lump, sizeof(*lumv3))) RETURN(-EFAULT); } else if (lmm_magic == __swab32(LOV_USER_MAGIC_V3)) { if (cfs_copy_from_user(lumv3, lump, sizeof(*lumv3))) RETURN(-EFAULT); lustre_swab_lov_user_md_v3(lumv3); lmm_magic = LOV_USER_MAGIC_V3; } else if (lmm_magic != LOV_USER_MAGIC_V1) { CDEBUG(D_IOCTL, "bad userland LOV MAGIC: %#08x != %#08x nor %#08x\n", lmm_magic, LOV_USER_MAGIC_V1, LOV_USER_MAGIC_V3); RETURN(-EINVAL); } /* in the rest of the tests, as *lumv1 and lumv3 have the same * fields, we use lumv1 to avoid code duplication */ if (lumv1->lmm_pattern == 0) { lumv1->lmm_pattern = lov->desc.ld_pattern ? lov->desc.ld_pattern : LOV_PATTERN_RAID0; } if (lumv1->lmm_pattern != LOV_PATTERN_RAID0) { CDEBUG(D_IOCTL, "bad userland stripe pattern: %#x\n", lumv1->lmm_pattern); RETURN(-EINVAL); } /* 64kB is the largest common page size we see (ia64), and matches the * check in lfs */ if (lumv1->lmm_stripe_size & (LOV_MIN_STRIPE_SIZE - 1)) { CDEBUG(D_IOCTL, "stripe size %u not multiple of %u, fixing\n", lumv1->lmm_stripe_size, LOV_MIN_STRIPE_SIZE); lumv1->lmm_stripe_size = LOV_MIN_STRIPE_SIZE; } if ((lumv1->lmm_stripe_offset >= lov->desc.ld_tgt_count) && (lumv1->lmm_stripe_offset != (typeof(lumv1->lmm_stripe_offset))(-1))) { CDEBUG(D_IOCTL, "stripe offset %u > number of OSTs %u\n", lumv1->lmm_stripe_offset, lov->desc.ld_tgt_count); RETURN(-EINVAL); } stripe_count = lov_get_stripecnt(lov, lumv1->lmm_stripe_count); if (max_lmm_size) { int max_stripes = (max_lmm_size - lov_mds_md_size(0, lmm_magic)) / sizeof(struct lov_ost_data_v1); if (unlikely(max_stripes < stripe_count)) { CDEBUG(D_IOCTL, "stripe count reset from %d to %d\n", stripe_count, max_stripes); stripe_count = max_stripes; } } if (lmm_magic == LOV_USER_MAGIC_V3) { struct pool_desc *pool; pool = lov_find_pool(lov, lumv3->lmm_pool_name); if (pool != NULL) { if (lumv3->lmm_stripe_offset != (typeof(lumv3->lmm_stripe_offset))(-1)) { rc = lov_check_index_in_pool( lumv3->lmm_stripe_offset, pool); if (rc < 0) { lov_pool_putref(pool); RETURN(-EINVAL); } } if (stripe_count > pool_tgt_count(pool)) stripe_count = pool_tgt_count(pool); lov_pool_putref(pool); } } rc = lov_alloc_memmd(lsmp, stripe_count, lumv1->lmm_pattern, lmm_magic); if (rc >= 0) { (*lsmp)->lsm_oinfo[0]->loi_ost_idx = lumv1->lmm_stripe_offset; (*lsmp)->lsm_stripe_size = lumv1->lmm_stripe_size; if (lmm_magic == LOV_USER_MAGIC_V3) strncpy((*lsmp)->lsm_pool_name, lumv3->lmm_pool_name, LOV_MAXPOOLNAME); rc = 0; } RETURN(rc); }
/* Pack LOV object metadata for disk storage. It is packed in LE byte * order and is opaque to the networking layer. * * XXX In the future, this will be enhanced to get the EA size from the * underlying OSC device(s) to get their EA sizes so we can stack * LOVs properly. For now lov_mds_md_size() just assumes one obd_id * per stripe. */ int lov_packmd(struct obd_export *exp, struct lov_mds_md **lmmp, struct lov_stripe_md *lsm) { struct obd_device *obd = class_exp2obd(exp); struct lov_obd *lov = &obd->u.lov; struct lov_mds_md_v1 *lmmv1; struct lov_mds_md_v3 *lmmv3; int stripe_count; struct lov_ost_data_v1 *lmm_objects; int lmm_size, lmm_magic; int i; ENTRY; if (lsm) { lmm_magic = lsm->lsm_magic; /* If we are just sizing the EA, limit the stripe count * to the actual number of OSTs in this filesystem. */ if (!lmmp) { stripe_count = lov_get_stripecnt(lov, lsm->lsm_stripe_count); lsm->lsm_stripe_count = stripe_count; } else { stripe_count = lsm->lsm_stripe_count; } } else { /* No needs to allocated more than LOV_MAX_STRIPE_COUNT. * Anyway, this is pretty inaccurate since ld_tgt_count now * represents max index and we should rely on the actual number * of OSTs instead */ stripe_count = min((__u32)LOV_MAX_STRIPE_COUNT, lov->desc.ld_tgt_count); if (lmmp && *lmmp) lmm_magic = le32_to_cpu((*lmmp)->lmm_magic); else /* lsm == NULL and lmmp == NULL */ lmm_magic = LOV_MAGIC; } if ((lmm_magic != LOV_MAGIC_V1) && (lmm_magic != LOV_MAGIC_V3)) { CERROR("bad mem LOV MAGIC: 0x%08X != 0x%08X nor 0x%08X\n", lmm_magic, LOV_MAGIC_V1, LOV_MAGIC_V3); RETURN(-EINVAL); } /* XXX LOV STACKING call into osc for sizes */ lmm_size = lov_mds_md_size(stripe_count, lmm_magic); if (!lmmp) RETURN(lmm_size); if (*lmmp && !lsm) { stripe_count = le32_to_cpu((*lmmp)->lmm_stripe_count); lmm_size = lov_mds_md_size(stripe_count, lmm_magic); OBD_FREE(*lmmp, lmm_size); *lmmp = NULL; RETURN(0); } if (!*lmmp) { OBD_ALLOC(*lmmp, lmm_size); if (!*lmmp) RETURN(-ENOMEM); } CDEBUG(D_INFO, "lov_packmd: LOV_MAGIC 0x%08X, lmm_size = %d \n", lmm_magic, lmm_size); lmmv1 = *lmmp; lmmv3 = (struct lov_mds_md_v3 *)*lmmp; if (lmm_magic == LOV_MAGIC_V3) lmmv3->lmm_magic = cpu_to_le32(LOV_MAGIC_V3); else lmmv1->lmm_magic = cpu_to_le32(LOV_MAGIC_V1); if (!lsm) RETURN(lmm_size); /* lmmv1 and lmmv3 point to the same struct and have the * same first fields */ lmmv1->lmm_object_id = cpu_to_le64(lsm->lsm_object_id); lmmv1->lmm_object_seq = cpu_to_le64(lsm->lsm_object_seq); lmmv1->lmm_stripe_size = cpu_to_le32(lsm->lsm_stripe_size); lmmv1->lmm_stripe_count = cpu_to_le32(stripe_count); lmmv1->lmm_pattern = cpu_to_le32(lsm->lsm_pattern); if (lsm->lsm_magic == LOV_MAGIC_V3) { strncpy(lmmv3->lmm_pool_name, lsm->lsm_pool_name, LOV_MAXPOOLNAME); lmm_objects = lmmv3->lmm_objects; } else { lmm_objects = lmmv1->lmm_objects; } for (i = 0; i < stripe_count; i++) { struct lov_oinfo *loi = lsm->lsm_oinfo[i]; /* XXX LOV STACKING call down to osc_packmd() to do packing */ LASSERTF(loi->loi_id, "lmm_oid "LPU64" stripe %u/%u idx %u\n", lmmv1->lmm_object_id, i, stripe_count, loi->loi_ost_idx); lmm_objects[i].l_object_id = cpu_to_le64(loi->loi_id); lmm_objects[i].l_object_seq = cpu_to_le64(loi->loi_seq); lmm_objects[i].l_ost_gen = cpu_to_le32(loi->loi_ost_gen); lmm_objects[i].l_ost_idx = cpu_to_le32(loi->loi_ost_idx); } RETURN(lmm_size); }
/* Retrieve object striping information. * * @lump is a pointer to an in-core struct with lmm_ost_count indicating * 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) { /* we use lov_user_md_v3 because it is larger than lov_user_md_v1 */ struct lov_user_md_v3 lum; struct lov_mds_md *lmmk; u32 stripe_count; ssize_t lmm_size; size_t lmmk_size; size_t lum_size; int rc; if (!lsm) return -ENODATA; if (lsm->lsm_magic != LOV_MAGIC_V1 && lsm->lsm_magic != LOV_MAGIC_V3) { CERROR("bad LSM MAGIC: 0x%08X != 0x%08X nor 0x%08X\n", lsm->lsm_magic, LOV_MAGIC_V1, LOV_MAGIC_V3); rc = -EIO; goto out; } if (!lsm_is_released(lsm)) stripe_count = lsm->lsm_stripe_count; else stripe_count = 0; /* we only need the header part from user space to get lmm_magic and * lmm_stripe_count, (the header part is common to v1 and v3) */ lum_size = sizeof(struct lov_user_md_v1); if (copy_from_user(&lum, lump, lum_size)) { rc = -EFAULT; goto out; } if (lum.lmm_magic != LOV_USER_MAGIC_V1 && lum.lmm_magic != LOV_USER_MAGIC_V3 && lum.lmm_magic != LOV_USER_MAGIC_SPECIFIC) { rc = -EINVAL; goto out; } if (lum.lmm_stripe_count && (lum.lmm_stripe_count < lsm->lsm_stripe_count)) { /* Return right size of stripe to user */ lum.lmm_stripe_count = stripe_count; rc = copy_to_user(lump, &lum, lum_size); rc = -EOVERFLOW; goto out; } lmmk_size = lov_mds_md_size(stripe_count, lsm->lsm_magic); lmmk = kvzalloc(lmmk_size, GFP_NOFS); if (!lmmk) { rc = -ENOMEM; goto out; } lmm_size = lov_lsm_pack(lsm, lmmk, lmmk_size); if (lmm_size < 0) { rc = lmm_size; goto out_free; } /* FIXME: Bug 1185 - copy fields properly when structs change */ /* struct lov_user_md_v3 and struct lov_mds_md_v3 must be the same */ BUILD_BUG_ON(sizeof(lum) != sizeof(struct lov_mds_md_v3)); BUILD_BUG_ON(sizeof(lum.lmm_objects[0]) != sizeof(lmmk->lmm_objects[0])); if (cpu_to_le32(LOV_MAGIC) != LOV_MAGIC && (lmmk->lmm_magic == cpu_to_le32(LOV_MAGIC_V1) || lmmk->lmm_magic == cpu_to_le32(LOV_MAGIC_V3))) { lustre_swab_lov_mds_md(lmmk); lustre_swab_lov_user_md_objects( (struct lov_user_ost_data *)lmmk->lmm_objects, lmmk->lmm_stripe_count); } if (lum.lmm_magic == LOV_USER_MAGIC) { /* User request for v1, we need skip lmm_pool_name */ if (lmmk->lmm_magic == LOV_MAGIC_V3) { memmove(((struct lov_mds_md_v1 *)lmmk)->lmm_objects, ((struct lov_mds_md_v3 *)lmmk)->lmm_objects, lmmk->lmm_stripe_count * sizeof(struct lov_ost_data_v1)); lmm_size -= LOV_MAXPOOLNAME; } } else { /* if v3 we just have to update the lum_size */ lum_size = sizeof(struct lov_user_md_v3); } /* User wasn't expecting this many OST entries */ if (lum.lmm_stripe_count == 0) { lmm_size = lum_size; } else if (lum.lmm_stripe_count < lmmk->lmm_stripe_count) { rc = -EOVERFLOW; goto out_free; } /* * Have a difference between lov_mds_md & lov_user_md. * So we have to re-order the data before copy to user. */ lum.lmm_stripe_count = lmmk->lmm_stripe_count; lum.lmm_layout_gen = lmmk->lmm_layout_gen; ((struct lov_user_md *)lmmk)->lmm_layout_gen = lum.lmm_layout_gen; ((struct lov_user_md *)lmmk)->lmm_stripe_count = lum.lmm_stripe_count; if (copy_to_user(lump, lmmk, lmm_size)) rc = -EFAULT; else rc = 0; out_free: kvfree(lmmk); out: return rc; }
/* Pack LOV object metadata for disk storage. It is packed in LE byte * order and is opaque to the networking layer. * * XXX In the future, this will be enhanced to get the EA size from the * underlying OSC device(s) to get their EA sizes so we can stack * LOVs properly. For now lov_mds_md_size() just assumes one u64 * per stripe. */ int lov_obd_packmd(struct lov_obd *lov, struct lov_mds_md **lmmp, struct lov_stripe_md *lsm) { struct lov_mds_md_v1 *lmmv1; struct lov_mds_md_v3 *lmmv3; __u16 stripe_count; struct lov_ost_data_v1 *lmm_objects; int lmm_size, lmm_magic; int i; int cplen = 0; if (lsm) { lmm_magic = lsm->lsm_magic; } else { if (lmmp && *lmmp) lmm_magic = le32_to_cpu((*lmmp)->lmm_magic); else /* lsm == NULL and lmmp == NULL */ lmm_magic = LOV_MAGIC; } if ((lmm_magic != LOV_MAGIC_V1) && (lmm_magic != LOV_MAGIC_V3)) { CERROR("bad mem LOV MAGIC: 0x%08X != 0x%08X nor 0x%08X\n", lmm_magic, LOV_MAGIC_V1, LOV_MAGIC_V3); return -EINVAL; } if (lsm) { /* If we are just sizing the EA, limit the stripe count * to the actual number of OSTs in this filesystem. */ if (!lmmp) { stripe_count = lov_get_stripecnt(lov, lmm_magic, lsm->lsm_stripe_count); lsm->lsm_stripe_count = stripe_count; } else if (!lsm_is_released(lsm)) { stripe_count = lsm->lsm_stripe_count; } else { stripe_count = 0; } } else { /* * To calculate maximum easize by active targets at present, * which is exactly the maximum easize to be seen by LOV */ stripe_count = lov->desc.ld_active_tgt_count; } /* XXX LOV STACKING call into osc for sizes */ lmm_size = lov_mds_md_size(stripe_count, lmm_magic); if (!lmmp) return lmm_size; if (*lmmp && !lsm) { stripe_count = le16_to_cpu((*lmmp)->lmm_stripe_count); lmm_size = lov_mds_md_size(stripe_count, lmm_magic); kvfree(*lmmp); *lmmp = NULL; return 0; } if (!*lmmp) { *lmmp = libcfs_kvzalloc(lmm_size, GFP_NOFS); if (!*lmmp) return -ENOMEM; } CDEBUG(D_INFO, "lov_packmd: LOV_MAGIC 0x%08X, lmm_size = %d\n", lmm_magic, lmm_size); lmmv1 = *lmmp; lmmv3 = (struct lov_mds_md_v3 *)*lmmp; if (lmm_magic == LOV_MAGIC_V3) lmmv3->lmm_magic = cpu_to_le32(LOV_MAGIC_V3); else lmmv1->lmm_magic = cpu_to_le32(LOV_MAGIC_V1); if (!lsm) return lmm_size; /* lmmv1 and lmmv3 point to the same struct and have the * same first fields */ lmm_oi_cpu_to_le(&lmmv1->lmm_oi, &lsm->lsm_oi); lmmv1->lmm_stripe_size = cpu_to_le32(lsm->lsm_stripe_size); lmmv1->lmm_stripe_count = cpu_to_le16(stripe_count); lmmv1->lmm_pattern = cpu_to_le32(lsm->lsm_pattern); lmmv1->lmm_layout_gen = cpu_to_le16(lsm->lsm_layout_gen); if (lsm->lsm_magic == LOV_MAGIC_V3) { cplen = strlcpy(lmmv3->lmm_pool_name, lsm->lsm_pool_name, sizeof(lmmv3->lmm_pool_name)); if (cplen >= sizeof(lmmv3->lmm_pool_name)) return -E2BIG; lmm_objects = lmmv3->lmm_objects; } else { lmm_objects = lmmv1->lmm_objects; } for (i = 0; i < stripe_count; i++) { struct lov_oinfo *loi = lsm->lsm_oinfo[i]; /* XXX LOV STACKING call down to osc_packmd() to do packing */ LASSERTF(ostid_id(&loi->loi_oi) != 0, "lmm_oi "DOSTID " stripe %u/%u idx %u\n", POSTID(&lmmv1->lmm_oi), i, stripe_count, loi->loi_ost_idx); ostid_cpu_to_le(&loi->loi_oi, &lmm_objects[i].l_ost_oi); lmm_objects[i].l_ost_gen = cpu_to_le32(loi->loi_ost_gen); lmm_objects[i].l_ost_idx = cpu_to_le32(loi->loi_ost_idx); } return lmm_size; }
int main(int argc, char **argv) { DIR * dir; struct lov_user_md *lum_dir, *lum_file1 = NULL, *lum_file2 = NULL; int rc; int lum_size; if (argc < 3) { llapi_err(LLAPI_MSG_ERROR, "Usage: %s <dirname> <filename1> [filename2]\n", argv[0]); return 1; } dir = opendir(argv[1]); if (dir == NULL) { rc = errno; llapi_err(LLAPI_MSG_ERROR, "error: %s opendir failed\n", argv[1]); return rc; } lum_size = lov_mds_md_size(MAX_LOV_UUID_COUNT, LOV_MAGIC); if ((lum_dir = (struct lov_user_md *)malloc(lum_size)) == NULL) { rc = ENOMEM; llapi_err(LLAPI_MSG_ERROR, "error: can't allocate %d bytes " "for dir EA", lum_size); goto cleanup; } rc = llapi_file_get_stripe(argv[1], lum_dir); if (rc) { if (errno == ENODATA) { free(lum_dir); lum_dir = NULL; } else { rc = errno; llapi_err(LLAPI_MSG_ERROR, "error: can't get EA for %s\n", argv[1]); goto cleanup; } } /* XXX should be llapi_lov_getname() */ rc = llapi_file_get_lov_uuid(argv[1], &lov_uuid); if (rc) { rc = errno; llapi_err(LLAPI_MSG_ERROR, "error: can't get lov name for %s\n", argv[1]); return rc; } if ((lum_file1 = (struct lov_user_md *)malloc(lum_size)) == NULL) { rc = ENOMEM; llapi_err(LLAPI_MSG_ERROR, "error: can't allocate %d bytes for EA\n", lum_size); goto cleanup; } rc = llapi_file_get_stripe(argv[2], lum_file1); if (rc) { rc = errno; llapi_err(LLAPI_MSG_ERROR, "error: unable to get EA for %s\n", argv[2]); goto cleanup; } if (argc == 4) { lum_file2 = (struct lov_user_md *)malloc(lum_size); if (lum_file2 == NULL) { rc = ENOMEM; llapi_err(LLAPI_MSG_ERROR, "error: can't allocate %d " "bytes for file2 EA\n", lum_size); goto cleanup; } rc = llapi_file_get_stripe(argv[3], lum_file2); if (rc) { rc = errno; llapi_err(LLAPI_MSG_ERROR, "error: can't get EA for %s\n", argv[3]); goto cleanup; } } rc = compare(lum_dir, lum_file1, lum_file2); cleanup: closedir(dir); if (lum_dir != NULL) free(lum_dir); if (lum_file1 != NULL) free(lum_file1); if (lum_file2 != NULL) free(lum_file2); return rc; }