Пример #1
0
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);
}
Пример #2
0
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);
}
Пример #3
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);
}
Пример #4
0
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);
}
Пример #5
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(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;
}
Пример #6
0
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);
}
Пример #7
0
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;
}
Пример #8
0
/* 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;
}
Пример #9
0
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);
}
Пример #10
0
/* 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);
}
Пример #11
0
/* 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;
}
Пример #12
0
/* 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;
}
Пример #13
0
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;
}