コード例 #1
0
ファイル: lov_object.c プロジェクト: KnightKu/lustre-stable
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);
}
コード例 #2
0
ファイル: lov_object.c プロジェクト: KnightKu/lustre-stable
static loff_t lov_object_maxbytes(struct cl_object *obj)
{
	struct lov_object *lov = cl2lov(obj);
	struct lov_stripe_md *lsm = lov_lsm_addref(lov);
	loff_t maxbytes;

	if (lsm == NULL)
		return LLONG_MAX;

	maxbytes = lsm->lsm_maxbytes;

	lov_lsm_put(lsm);

	return maxbytes;
}
コード例 #3
0
ファイル: lov_object.c プロジェクト: acton393/linux
static int lov_object_getstripe(const struct lu_env *env, struct cl_object *obj,
				struct lov_user_md __user *lum)
{
	struct lov_object *lov = cl2lov(obj);
	struct lov_stripe_md *lsm;
	int rc = 0;

	lsm = lov_lsm_addref(lov);
	if (!lsm)
		return -ENODATA;

	rc = lov_getstripe(cl2lov(obj), lsm, lum);
	lov_lsm_put(obj, lsm);
	return rc;
}
コード例 #4
0
ファイル: lov_object.c プロジェクト: KnightKu/lustre-stable
static int lov_object_getstripe(const struct lu_env *env, struct cl_object *obj,
				struct lov_user_md __user *lum)
{
	struct lov_object	*lov = cl2lov(obj);
	struct lov_stripe_md	*lsm;
	int			rc = 0;
	ENTRY;

	lsm = lov_lsm_addref(lov);
	if (lsm == NULL)
		RETURN(-ENODATA);

	rc = lov_getstripe(cl2lov(obj), lsm, lum);
	lov_lsm_put(lsm);
	RETURN(rc);
}
コード例 #5
0
ファイル: lov_object.c プロジェクト: KnightKu/lustre-stable
/*****************************************************************************
 *
 * Lov object operations.
 *
 */
int lov_object_init(const struct lu_env *env, struct lu_object *obj,
		    const struct lu_object_conf *conf)
{
	struct lov_object            *lov   = lu2lov(obj);
	struct lov_device            *dev   = lov_object_dev(lov);
	const struct cl_object_conf  *cconf = lu2cl_conf(conf);
	union lov_layout_state	     *set   = &lov->u;
	const struct lov_layout_operations *ops;
	struct lov_stripe_md *lsm = NULL;
	int rc;
	ENTRY;

	init_rwsem(&lov->lo_type_guard);
	atomic_set(&lov->lo_active_ios, 0);
	init_waitqueue_head(&lov->lo_waitq);
	cl_object_page_init(lu2cl(obj), sizeof(struct lov_page));

	lov->lo_type = LLT_EMPTY;
	if (cconf->u.coc_layout.lb_buf != NULL) {
		lsm = lov_unpackmd(dev->ld_lov,
				   cconf->u.coc_layout.lb_buf,
				   cconf->u.coc_layout.lb_len);
		if (IS_ERR(lsm))
			RETURN(PTR_ERR(lsm));
	}

	/* no locking is necessary, as object is being created */
	lov->lo_type = lov_type(lsm);
	ops = &lov_dispatch[lov->lo_type];
	rc = ops->llo_init(env, dev, lov, lsm, cconf, set);
	if (rc != 0)
		GOTO(out_lsm, rc);

	ops->llo_install(env, lov, set);

out_lsm:
	lov_lsm_put(lsm);

	RETURN(rc);
}
コード例 #6
0
ファイル: lov_object.c プロジェクト: KnightKu/lustre-stable
static int lov_conf_set(const struct lu_env *env, struct cl_object *obj,
                        const struct cl_object_conf *conf)
{
	struct lov_stripe_md	*lsm = NULL;
	struct lov_object	*lov = cl2lov(obj);
	int			 result = 0;
	ENTRY;

	if (conf->coc_opc == OBJECT_CONF_SET &&
	    conf->u.coc_layout.lb_buf != NULL) {
		lsm = lov_unpackmd(lov_object_dev(lov)->ld_lov,
				   conf->u.coc_layout.lb_buf,
				   conf->u.coc_layout.lb_len);
		if (IS_ERR(lsm))
			RETURN(PTR_ERR(lsm));
	}

	lov_conf_lock(lov);
	if (conf->coc_opc == OBJECT_CONF_INVALIDATE) {
		lov->lo_layout_invalid = true;
		GOTO(out, result = 0);
	}

	if (conf->coc_opc == OBJECT_CONF_WAIT) {
		if (lov->lo_layout_invalid &&
		    atomic_read(&lov->lo_active_ios) > 0) {
			lov_conf_unlock(lov);
			result = lov_layout_wait(env, lov);
			lov_conf_lock(lov);
		}
		GOTO(out, result);
	}

	LASSERT(conf->coc_opc == OBJECT_CONF_SET);

	if ((lsm == NULL && lov->lo_lsm == NULL) ||
	    ((lsm != NULL && lov->lo_lsm != NULL) &&
	     (lov->lo_lsm->lsm_layout_gen == lsm->lsm_layout_gen) &&
	     (lov->lo_lsm->lsm_pattern == lsm->lsm_pattern))) {
		/* same version of layout */
		lov->lo_layout_invalid = false;
		GOTO(out, result = 0);
	}

	/* will change layout - check if there still exists active IO. */
	if (atomic_read(&lov->lo_active_ios) > 0) {
		lov->lo_layout_invalid = true;
		GOTO(out, result = -EBUSY);
	}

	result = lov_layout_change(env, lov, lsm, conf);
	lov->lo_layout_invalid = result != 0;
	EXIT;

out:
	lov_conf_unlock(lov);
	lov_lsm_put(lsm);
	CDEBUG(D_INODE, DFID" lo_layout_invalid=%d\n",
	       PFID(lu_object_fid(lov2lu(lov))), lov->lo_layout_invalid);
	RETURN(result);
}
コード例 #7
0
ファイル: lov_object.c プロジェクト: KnightKu/lustre-stable
/**
 * Break down the FIEMAP request and send appropriate calls to individual OSTs.
 * This also handles the restarting of FIEMAP calls in case mapping overflows
 * the available number of extents in single call.
 *
 * \param env [in]		lustre environment
 * \param obj [in]		file object
 * \param fmkey [in]		fiemap request header and other info
 * \param fiemap [out]		fiemap buffer holding retrived map extents
 * \param buflen [in/out]	max buffer length of @fiemap, when iterate
 *				each OST, it is used to limit max map needed
 * \retval 0	success
 * \retval < 0	error
 */
static int lov_object_fiemap(const struct lu_env *env, struct cl_object *obj,
			     struct ll_fiemap_info_key *fmkey,
			     struct fiemap *fiemap, size_t *buflen)
{
	struct lov_stripe_md	*lsm;
	struct cl_object	*subobj = NULL;
	struct lov_obd		*lov = lu2lov_dev(obj->co_lu.lo_dev)->ld_lov;
	struct fiemap		*fm_local = NULL;
	struct fiemap_extent	*lcl_fm_ext;
	loff_t			fm_start;
	loff_t			fm_end;
	loff_t			fm_length;
	loff_t			fm_end_offset;
	int			count_local;
	int			ost_index = 0;
	int			start_stripe;
	int			current_extent = 0;
	int			rc = 0;
	int			last_stripe;
	int			cur_stripe = 0;
	int			cur_stripe_wrap = 0;
	int			stripe_count;
	unsigned int		buffer_size = FIEMAP_BUFFER_SIZE;
	/* Whether have we collected enough extents */
	bool			enough = false;
	/* EOF for object */
	bool			ost_eof = false;
	/* done with required mapping for this OST? */
	bool			ost_done = false;
	ENTRY;

	lsm = lov_lsm_addref(cl2lov(obj));
	if (lsm == NULL)
		RETURN(-ENODATA);

	/**
	 * If the stripe_count > 1 and the application does not understand
	 * DEVICE_ORDER flag, it cannot interpret the extents correctly.
	 */
	if (lsm->lsm_stripe_count > 1 && !(fiemap->fm_flags &
					   FIEMAP_FLAG_DEVICE_ORDER))
		GOTO(out_lsm, rc = -ENOTSUPP);

	if (lsm_is_released(lsm)) {
		if (fiemap->fm_start < fmkey->lfik_oa.o_size) {
			/**
			 * released file, return a minimal FIEMAP if
			 * request fits in file-size.
			 */
			fiemap->fm_mapped_extents = 1;
			fiemap->fm_extents[0].fe_logical = fiemap->fm_start;
			if (fiemap->fm_start + fiemap->fm_length <
			    fmkey->lfik_oa.o_size)
				fiemap->fm_extents[0].fe_length =
					fiemap->fm_length;
			else
				fiemap->fm_extents[0].fe_length =
					fmkey->lfik_oa.o_size -
					fiemap->fm_start;
			fiemap->fm_extents[0].fe_flags |=
				FIEMAP_EXTENT_UNKNOWN | FIEMAP_EXTENT_LAST;
		}
		GOTO(out_lsm, rc = 0);
	}

	if (fiemap_count_to_size(fiemap->fm_extent_count) < buffer_size)
		buffer_size = fiemap_count_to_size(fiemap->fm_extent_count);

	OBD_ALLOC_LARGE(fm_local, buffer_size);
	if (fm_local == NULL)
		GOTO(out_lsm, rc = -ENOMEM);
	lcl_fm_ext = &fm_local->fm_extents[0];
	count_local = fiemap_size_to_count(buffer_size);

	fm_start = fiemap->fm_start;
	fm_length = fiemap->fm_length;
	/* Calculate start stripe, last stripe and length of mapping */
	start_stripe = lov_stripe_number(lsm, fm_start);
	fm_end = (fm_length == ~0ULL) ? fmkey->lfik_oa.o_size :
					fm_start + fm_length - 1;
	/* If fm_length != ~0ULL but fm_start_fm_length-1 exceeds file size */
	if (fm_end > fmkey->lfik_oa.o_size)
		fm_end = fmkey->lfik_oa.o_size;

	last_stripe = fiemap_calc_last_stripe(lsm, fm_start, fm_end,
					      start_stripe, &stripe_count);
	fm_end_offset = fiemap_calc_fm_end_offset(fiemap, lsm, fm_start, fm_end,
						  &start_stripe);
	if (fm_end_offset == -EINVAL)
		GOTO(out_fm_local, rc = -EINVAL);

	/**
	 * Requested extent count exceeds the fiemap buffer size, shrink our
	 * ambition.
	 */
	if (fiemap_count_to_size(fiemap->fm_extent_count) > *buflen)
		fiemap->fm_extent_count = fiemap_size_to_count(*buflen);
	if (fiemap->fm_extent_count == 0)
		count_local = 0;

	/* Check each stripe */
	for (cur_stripe = start_stripe; stripe_count > 0;
	     --stripe_count,
	     cur_stripe = (cur_stripe + 1) % lsm->lsm_stripe_count) {
		loff_t req_fm_len; /* Stores length of required mapping */
		loff_t len_mapped_single_call;
		loff_t lun_start;
		loff_t lun_end;
		loff_t obd_object_end;
		unsigned int ext_count;

		cur_stripe_wrap = cur_stripe;

		/* Find out range of mapping on this stripe */
		if ((lov_stripe_intersects(lsm, cur_stripe, fm_start, fm_end,
					   &lun_start, &obd_object_end)) == 0)
			continue;

		if (lov_oinfo_is_dummy(lsm->lsm_oinfo[cur_stripe]))
			GOTO(out_fm_local, rc = -EIO);

		/* If this is a continuation FIEMAP call and we are on
		 * starting stripe then lun_start needs to be set to
		 * fm_end_offset */
		if (fm_end_offset != 0 && cur_stripe == start_stripe)
			lun_start = fm_end_offset;

		if (fm_length != ~0ULL) {
			/* Handle fm_start + fm_length overflow */
			if (fm_start + fm_length < fm_start)
				fm_length = ~0ULL - fm_start;
			lun_end = lov_size_to_stripe(lsm, fm_start + fm_length,
						     cur_stripe);
		} else {
			lun_end = ~0ULL;
		}

		if (lun_start == lun_end)
			continue;

		req_fm_len = obd_object_end - lun_start;
		fm_local->fm_length = 0;
		len_mapped_single_call = 0;

		/* find lobsub object */
		subobj = lov_find_subobj(env, cl2lov(obj), lsm,
					     cur_stripe);
		if (IS_ERR(subobj))
			GOTO(out_fm_local, rc = PTR_ERR(subobj));
		/* If the output buffer is very large and the objects have many
		 * extents we may need to loop on a single OST repeatedly */
		ost_eof = false;
		ost_done = false;
		do {
			if (fiemap->fm_extent_count > 0) {
				/* Don't get too many extents. */
				if (current_extent + count_local >
				    fiemap->fm_extent_count)
					count_local = fiemap->fm_extent_count -
						      current_extent;
			}

			lun_start += len_mapped_single_call;
			fm_local->fm_length = req_fm_len -
					      len_mapped_single_call;
			req_fm_len = fm_local->fm_length;
			fm_local->fm_extent_count = enough ? 1 : count_local;
			fm_local->fm_mapped_extents = 0;
			fm_local->fm_flags = fiemap->fm_flags;

			ost_index = lsm->lsm_oinfo[cur_stripe]->loi_ost_idx;

			if (ost_index < 0 ||
			    ost_index >= lov->desc.ld_tgt_count)
				GOTO(obj_put, rc = -EINVAL);
			/* If OST is inactive, return extent with UNKNOWN
			 * flag. */
			if (!lov->lov_tgts[ost_index]->ltd_active) {
				fm_local->fm_flags |= FIEMAP_EXTENT_LAST;
				fm_local->fm_mapped_extents = 1;

				lcl_fm_ext[0].fe_logical = lun_start;
				lcl_fm_ext[0].fe_length = obd_object_end -
							  lun_start;
				lcl_fm_ext[0].fe_flags |= FIEMAP_EXTENT_UNKNOWN;

				goto inactive_tgt;
			}

			fm_local->fm_start = lun_start;
			fm_local->fm_flags &= ~FIEMAP_FLAG_DEVICE_ORDER;
			memcpy(&fmkey->lfik_fiemap, fm_local,
			       sizeof(*fm_local));
			*buflen = fiemap_count_to_size(
						fm_local->fm_extent_count);

			rc = cl_object_fiemap(env, subobj, fmkey, fm_local,
					      buflen);
			if (rc != 0)
				GOTO(obj_put, rc);
inactive_tgt:
			ext_count = fm_local->fm_mapped_extents;
			if (ext_count == 0) {
				ost_done = true;
				/* If last stripe has hold at the end,
				 * we need to return */
				if (cur_stripe_wrap == last_stripe) {
					fiemap->fm_mapped_extents = 0;
					goto finish;
				}
				break;
			} else if (enough) {
				/*
				 * We've collected enough extents and there are
				 * more extents after it.
				 */
				goto finish;
			}

			/* If we just need num of extents, got to next device */
			if (fiemap->fm_extent_count == 0) {
				current_extent += ext_count;
				break;
			}

			/* prepare to copy retrived map extents */
			len_mapped_single_call =
				lcl_fm_ext[ext_count - 1].fe_logical -
				lun_start + lcl_fm_ext[ext_count - 1].fe_length;

			/* Have we finished mapping on this device? */
			if (req_fm_len <= len_mapped_single_call)
				ost_done = true;

			/* Clear the EXTENT_LAST flag which can be present on
			 * the last extent */
			if (lcl_fm_ext[ext_count - 1].fe_flags &
			    FIEMAP_EXTENT_LAST)
				lcl_fm_ext[ext_count - 1].fe_flags &=
							~FIEMAP_EXTENT_LAST;
			if (lov_stripe_size(lsm,
					lcl_fm_ext[ext_count - 1].fe_logical +
					lcl_fm_ext[ext_count - 1].fe_length,
					cur_stripe) >= fmkey->lfik_oa.o_size)
				ost_eof = true;

			fiemap_prepare_and_copy_exts(fiemap, lcl_fm_ext,
						     ost_index, ext_count,
						     current_extent);
			current_extent += ext_count;

			/* Ran out of available extents? */
			if (current_extent >= fiemap->fm_extent_count)
				enough = true;
		} while (!ost_done && !ost_eof);

		cl_object_put(env, subobj);
		subobj = NULL;

		if (cur_stripe_wrap == last_stripe)
			goto finish;
	} /* for each stripe */
finish:
	/* Indicate that we are returning device offsets unless file just has
	 * single stripe */
	if (lsm->lsm_stripe_count > 1)
		fiemap->fm_flags |= FIEMAP_FLAG_DEVICE_ORDER;

	if (fiemap->fm_extent_count == 0)
		goto skip_last_device_calc;

	/* Check if we have reached the last stripe and whether mapping for that
	 * stripe is done. */
	if ((cur_stripe_wrap == last_stripe) && (ost_done || ost_eof))
		fiemap->fm_extents[current_extent - 1].fe_flags |=
							     FIEMAP_EXTENT_LAST;
skip_last_device_calc:
	fiemap->fm_mapped_extents = current_extent;
obj_put:
	if (subobj != NULL)
		cl_object_put(env, subobj);
out_fm_local:
	OBD_FREE_LARGE(fm_local, buffer_size);

out_lsm:
	lov_lsm_put(lsm);

	return rc;
}