Exemplo n.º 1
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 obd_export *exp, struct lov_stripe_md *lsm,
		  struct lov_user_md *lump)
{
	/*
	 * XXX huge struct allocated on stack.
	 */
	/* 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 = NULL;
	int rc, lmm_size;
	int lum_size;
	mm_segment_t seg;

	if (!lsm)
		return -ENODATA;

	/*
	 * "Switch to kernel segment" to allow copying from kernel space by
	 * copy_{to,from}_user().
	 */
	seg = get_fs();
	set_fs(KERNEL_DS);

	/* 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))
		GOTO(out_set, rc = -EFAULT);
	else if ((lum.lmm_magic != LOV_USER_MAGIC) &&
		 (lum.lmm_magic != LOV_USER_MAGIC_V3))
		GOTO(out_set, rc = -EINVAL);

	if (lum.lmm_stripe_count &&
	    (lum.lmm_stripe_count < lsm->lsm_stripe_count)) {
		/* Return right size of stripe to user */
		lum.lmm_stripe_count = lsm->lsm_stripe_count;
		rc = copy_to_user(lump, &lum, lum_size);
		GOTO(out_set, rc = -EOVERFLOW);
	}
	rc = lov_packmd(exp, &lmmk, lsm);
	if (rc < 0)
		GOTO(out_set, rc);
	lmm_size = rc;
	rc = 0;

	/* FIXME: Bug 1185 - copy fields properly when structs change */
	/* struct lov_user_md_v3 and struct lov_mds_md_v3 must be the same */
	CLASSERT(sizeof(lum) == sizeof(struct lov_mds_md_v3));
	CLASSERT(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((char *)(&lmmk->lmm_stripe_count) +
				sizeof(lmmk->lmm_stripe_count),
				((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)
		GOTO(out_set, rc = -EOVERFLOW);
	/*
	 * 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;

	obd_free_diskmd(exp, &lmmk);
out_set:
	set_fs(seg);
	return rc;
}
Exemplo n.º 2
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.
 *
 * If @size > 0, User specified limited buffer size, usually the buffer is from
 * ll_lov_setstripe(), and the buffer can only hold basic layout template info.
 */
int lov_getstripe(const struct lu_env *env, struct lov_object *obj,
		  struct lov_stripe_md *lsm, struct lov_user_md __user *lump,
		  size_t size)
{
	/* we use lov_user_md_v3 because it is larger than lov_user_md_v1 */
	struct lov_mds_md *lmmk, *lmm;
	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 &&
	    lsm->lsm_magic != LOV_MAGIC_COMP_V1) {
		CERROR("bad LSM MAGIC: 0x%08X != 0x%08X nor 0x%08X\n",
		       lsm->lsm_magic, LOV_MAGIC_V1, LOV_MAGIC_V3);
		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);
	if (lmmk == NULL)
		GOTO(out, rc = -ENOMEM);

	lmm_size = lov_lsm_pack(lsm, lmmk, lmmk_size);
	if (lmm_size < 0)
		GOTO(out_free, rc = lmm_size);

	if (cpu_to_le32(LOV_MAGIC) != LOV_MAGIC) {
		if (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);
		} else if (lmmk->lmm_magic == cpu_to_le32(LOV_MAGIC_COMP_V1)) {
			lustre_swab_lov_comp_md_v1(
					(struct lov_comp_md_v1 *)lmmk);
		}
	}

	/* 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);
		}

		lmm = comp_md;
		lmm_size = lum_size;
	} else {
		lmm = lmmk;
		lmm_size = lmmk_size;
	}
	/**
	 * User specified limited buffer size, usually the buffer is
	 * from ll_lov_setstripe(), and the buffer can only hold basic
	 * layout template info.
	 */
	if (size == 0 || size > lmm_size)
		size = lmm_size;
	if (copy_to_user(lump, lmm, size))
		GOTO(out_free, rc = -EFAULT);

out_free:
	OBD_FREE_LARGE(lmmk, lmmk_size);
out:
	RETURN(rc);
}
Exemplo n.º 3
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;
}