Пример #1
0
static struct cl_object *lov_find_subobj(const struct lu_env *env,
					 struct lov_object *lov,
					 struct lov_stripe_md *lsm,
					 int stripe_idx)
{
	struct lov_device	*dev = lu2lov_dev(lov2lu(lov)->lo_dev);
	struct lov_oinfo	*oinfo = lsm->lsm_oinfo[stripe_idx];
	struct lov_thread_info  *lti = lov_env_info(env);
	struct lu_fid		*ofid = &lti->lti_fid;
	struct cl_device	*subdev;
	int			ost_idx;
	int			rc;
	struct cl_object	*result;

	if (lov->lo_type != LLT_RAID0)
		GOTO(out, result = NULL);

	ost_idx = oinfo->loi_ost_idx;
	rc = ostid_to_fid(ofid, &oinfo->loi_oi, ost_idx);
	if (rc != 0)
		GOTO(out, result = NULL);

	subdev = lovsub2cl_dev(dev->ld_target[ost_idx]);
	result = lov_sub_find(env, subdev, ofid, NULL);
out:
	if (result == NULL)
		result = ERR_PTR(-EINVAL);
	return result;
}
Пример #2
0
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;

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

	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;
	}

	LASSERT(conf->coc_opc == OBJECT_CONF_SET);

	if (conf->u.coc_md)
		lsm = conf->u.coc_md->lsm;
	if ((!lsm && !lov->lo_lsm) ||
	    ((lsm && lov->lo_lsm) &&
	     (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;
		result = 0;
		goto out;
	}

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

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

out:
	lov_conf_unlock(lov);
	CDEBUG(D_INODE, DFID" lo_layout_invalid=%d\n",
	       PFID(lu_object_fid(lov2lu(lov))), lov->lo_layout_invalid);
	return result;
}
Пример #3
0
static int lov_layout_wait(const struct lu_env *env, struct lov_object *lov)
{
	struct l_wait_info lwi = { 0 };

	while (atomic_read(&lov->lo_active_ios) > 0) {
		CDEBUG(D_INODE, "file:"DFID" wait for active IO, now: %d.\n",
			PFID(lu_object_fid(lov2lu(lov))),
			atomic_read(&lov->lo_active_ios));

		l_wait_event(lov->lo_waitq,
			     atomic_read(&lov->lo_active_ios) == 0, &lwi);
	}
	return 0;
}
Пример #4
0
struct lu_object *lov_object_alloc(const struct lu_env *env,
				   const struct lu_object_header *unused,
				   struct lu_device *dev)
{
	struct lov_object *lov;
	struct lu_object  *obj;

	OBD_SLAB_ALLOC_PTR_GFP(lov, lov_object_kmem, GFP_NOFS);
	if (lov != NULL) {
		obj = lov2lu(lov);
		lu_object_init(obj, NULL, dev);
		lov->lo_cl.co_ops = &lov_ops;
		lov->lo_type = -1; /* invalid, to catch uninitialized type */
		/*
		 * object io operation vector (cl_object::co_iop) is installed
		 * later in lov_object_init(), as different vectors are used
		 * for object with different layouts.
		 */
		obj->lo_ops = &lov_lu_obj_ops;
	} else
		obj = NULL;
	return obj;
}
Пример #5
0
static int lov_layout_change(const struct lu_env *unused,
			     struct lov_object *lov,
			     const struct cl_object_conf *conf)
{
	int result;
	enum lov_layout_type llt = LLT_EMPTY;
	union lov_layout_state *state = &lov->u;
	const struct lov_layout_operations *old_ops;
	const struct lov_layout_operations *new_ops;

	struct cl_object_header *hdr = cl_object_header(&lov->lo_cl);
	void *cookie;
	struct lu_env *env;
	int refcheck;

	LASSERT(0 <= lov->lo_type && lov->lo_type < ARRAY_SIZE(lov_dispatch));

	if (conf->u.coc_md != NULL)
		llt = lov_type(conf->u.coc_md->lsm);
	LASSERT(0 <= llt && llt < ARRAY_SIZE(lov_dispatch));

	cookie = cl_env_reenter();
	env = cl_env_get(&refcheck);
	if (IS_ERR(env)) {
		cl_env_reexit(cookie);
		return PTR_ERR(env);
	}

	CDEBUG(D_INODE, DFID" from %s to %s\n",
	       PFID(lu_object_fid(lov2lu(lov))),
	       llt2str(lov->lo_type), llt2str(llt));

	old_ops = &lov_dispatch[lov->lo_type];
	new_ops = &lov_dispatch[llt];

	result = old_ops->llo_delete(env, lov, &lov->u);
	if (result == 0) {
		old_ops->llo_fini(env, lov, &lov->u);

		LASSERT(atomic_read(&lov->lo_active_ios) == 0);
		LASSERT(hdr->coh_tree.rnode == NULL);
		LASSERT(hdr->coh_pages == 0);

		lov->lo_type = LLT_EMPTY;
		result = new_ops->llo_init(env,
					lu2lov_dev(lov->lo_cl.co_lu.lo_dev),
					lov, conf, state);
		if (result == 0) {
			new_ops->llo_install(env, lov, state);
			lov->lo_type = llt;
		} else {
			new_ops->llo_delete(env, lov, state);
			new_ops->llo_fini(env, lov, state);
			/* this file becomes an EMPTY file. */
		}
	}

	cl_env_put(env, &refcheck);
	cl_env_reexit(cookie);
	return result;
}
Пример #6
0
static int lov_init_sub(const struct lu_env *env, struct lov_object *lov,
			struct cl_object *stripe, struct lov_layout_raid0 *r0,
			int idx)
{
	struct cl_object_header *hdr;
	struct cl_object_header *subhdr;
	struct cl_object_header *parent;
	struct lov_oinfo	*oinfo;
	int result;

	if (OBD_FAIL_CHECK(OBD_FAIL_LOV_INIT)) {
		/* For sanity:test_206.
		 * Do not leave the object in cache to avoid accessing
		 * freed memory. This is because osc_object is referring to
		 * lov_oinfo of lsm_stripe_data which will be freed due to
		 * this failure. */
		cl_object_kill(env, stripe);
		cl_object_put(env, stripe);
		return -EIO;
	}

	hdr    = cl_object_header(lov2cl(lov));
	subhdr = cl_object_header(stripe);

	oinfo = lov->lo_lsm->lsm_oinfo[idx];
	CDEBUG(D_INODE, DFID"@%p[%d] -> "DFID"@%p: ostid: "DOSTID
	       " idx: %d gen: %d\n",
	       PFID(&subhdr->coh_lu.loh_fid), subhdr, idx,
	       PFID(&hdr->coh_lu.loh_fid), hdr, POSTID(&oinfo->loi_oi),
	       oinfo->loi_ost_idx, oinfo->loi_ost_gen);

	/* reuse ->coh_attr_guard to protect coh_parent change */
	spin_lock(&subhdr->coh_attr_guard);
	parent = subhdr->coh_parent;
	if (parent == NULL) {
		subhdr->coh_parent = hdr;
		spin_unlock(&subhdr->coh_attr_guard);
		subhdr->coh_nesting = hdr->coh_nesting + 1;
		lu_object_ref_add(&stripe->co_lu, "lov-parent", lov);
		r0->lo_sub[idx] = cl2lovsub(stripe);
		r0->lo_sub[idx]->lso_super = lov;
		r0->lo_sub[idx]->lso_index = idx;
		result = 0;
	} else {
		struct lu_object  *old_obj;
		struct lov_object *old_lov;
		unsigned int mask = D_INODE;

		spin_unlock(&subhdr->coh_attr_guard);
		old_obj = lu_object_locate(&parent->coh_lu, &lov_device_type);
		LASSERT(old_obj != NULL);
		old_lov = cl2lov(lu2cl(old_obj));
		if (old_lov->lo_layout_invalid) {
			/* the object's layout has already changed but isn't
			 * refreshed */
			lu_object_unhash(env, &stripe->co_lu);
			result = -EAGAIN;
		} else {
			mask = D_ERROR;
			result = -EIO;
		}

		LU_OBJECT_DEBUG(mask, env, &stripe->co_lu,
				"stripe %d is already owned.\n", idx);
		LU_OBJECT_DEBUG(mask, env, old_obj, "owned.\n");
		LU_OBJECT_HEADER(mask, env, lov2lu(lov), "try to own.\n");
		cl_object_put(env, stripe);
	}
	return result;
}
Пример #7
0
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);
}
Пример #8
0
static int lov_layout_change(const struct lu_env *unused,
			     struct lov_object *lov, struct lov_stripe_md *lsm,
			     const struct cl_object_conf *conf)
{
	enum lov_layout_type llt = lov_type(lsm);
	union lov_layout_state *state = &lov->u;
	const struct lov_layout_operations *old_ops;
	const struct lov_layout_operations *new_ops;
	void *cookie;
	struct lu_env *env;
	__u16 refcheck;
	int rc;
	ENTRY;

	LASSERT(0 <= lov->lo_type && lov->lo_type < ARRAY_SIZE(lov_dispatch));

	cookie = cl_env_reenter();
	env = cl_env_get(&refcheck);
	if (IS_ERR(env)) {
		cl_env_reexit(cookie);
		RETURN(PTR_ERR(env));
	}

	LASSERT(0 <= llt && llt < ARRAY_SIZE(lov_dispatch));

	CDEBUG(D_INODE, DFID" from %s to %s\n",
	       PFID(lu_object_fid(lov2lu(lov))),
	       llt2str(lov->lo_type), llt2str(llt));

	old_ops = &lov_dispatch[lov->lo_type];
	new_ops = &lov_dispatch[llt];

	rc = cl_object_prune(env, &lov->lo_cl);
	if (rc != 0)
		GOTO(out, rc);

	rc = old_ops->llo_delete(env, lov, &lov->u);
	if (rc != 0)
		GOTO(out, rc);

	old_ops->llo_fini(env, lov, &lov->u);

	LASSERT(atomic_read(&lov->lo_active_ios) == 0);

	lov->lo_type = LLT_EMPTY;

	/* page bufsize fixup */
	cl_object_header(&lov->lo_cl)->coh_page_bufsize -=
		lov_page_slice_fixup(lov, NULL);

	rc = new_ops->llo_init(env, lov_object_dev(lov), lov, lsm, conf, state);
	if (rc != 0) {
		new_ops->llo_delete(env, lov, state);
		new_ops->llo_fini(env, lov, state);
		/* this file becomes an EMPTY file. */
		GOTO(out, rc);
	}

	new_ops->llo_install(env, lov, state);
	lov->lo_type = llt;

out:
	cl_env_put(env, &refcheck);
	cl_env_reexit(cookie);

	RETURN(rc);
}