Пример #1
0
static int __out_tx_xattr_set(const struct lu_env *env,
			      struct dt_object *dt_obj,
			      const struct lu_buf *buf,
			      const char *name, int flags,
			      struct thandle_exec_args *ta,
			      struct update_reply *reply, int index,
			      char *file, int line)
{
	struct tx_arg		*arg;

	LASSERT(ta->ta_handle != NULL);
	ta->ta_err = dt_declare_xattr_set(env, dt_obj, buf, name,
					  flags, ta->ta_handle);
	if (ta->ta_err != 0)
		return ta->ta_err;

	arg = tx_add_exec(ta, out_tx_xattr_set_exec, NULL, file, line);
	LASSERT(arg);
	lu_object_get(&dt_obj->do_lu);
	arg->object = dt_obj;
	arg->u.xattr_set.name = name;
	arg->u.xattr_set.flags = flags;
	arg->u.xattr_set.buf = *buf;
	arg->reply = reply;
	arg->index = index;
	arg->u.xattr_set.csum = 0;
	return 0;
}
Пример #2
0
/**
 * This is helper function to get llog directory object. It is used by named
 * llog operations to find/insert/delete llog entry from llog directory.
 *
 * \param[in] env	execution environment
 * \param[in] ctxt	llog context
 *
 * \retval		dt_object of llog directory
 * \retval		ERR_PTR of negative value on error
 */
struct dt_object *llog_osd_dir_get(const struct lu_env *env,
				   struct llog_ctxt *ctxt)
{
	struct dt_device	*dt;
	struct dt_thread_info	*dti = dt_info(env);
	struct dt_object	*dir;
	int			 rc;

	dt = ctxt->loc_exp->exp_obd->obd_lvfs_ctxt.dt;
	if (ctxt->loc_dir == NULL) {
		rc = dt_root_get(env, dt, &dti->dti_fid);
		if (rc)
			return ERR_PTR(rc);
		dir = dt_locate(env, dt, &dti->dti_fid);

		if (!IS_ERR(dir) && !dt_try_as_dir(env, dir)) {
			lu_object_put(env, &dir->do_lu);
			return ERR_PTR(-ENOTDIR);
		}
	} else {
		lu_object_get(&ctxt->loc_dir->do_lu);
		dir = ctxt->loc_dir;
	}

	return dir;
}
Пример #3
0
static int __out_tx_write(const struct lu_env *env,
			  struct dt_object *dt_obj,
			  const struct lu_buf *buf,
			  loff_t pos, struct thandle_exec_args *ta,
			  struct object_update_reply *reply,
			  int index, char *file, int line)
{
	struct tx_arg	*arg;

	LASSERT(ta->ta_handle != NULL);
	ta->ta_err = dt_declare_record_write(env, dt_obj, buf, pos,
					     ta->ta_handle);
	if (ta->ta_err != 0)
		return ta->ta_err;

	arg = tx_add_exec(ta, out_tx_write_exec, NULL, file, line);
	LASSERT(arg);
	lu_object_get(&dt_obj->do_lu);
	arg->object = dt_obj;
	arg->u.write.buf = *buf;
	arg->u.write.pos = pos;
	arg->reply = reply;
	arg->index = index;
	return 0;
}
Пример #4
0
static int __out_tx_create(const struct lu_env *env, struct dt_object *obj,
			   struct lu_attr *attr, struct lu_fid *parent_fid,
			   struct dt_object_format *dof,
			   struct thandle_exec_args *ta,
			   struct update_reply *reply,
			   int index, char *file, int line)
{
	struct tx_arg *arg;

	LASSERT(ta->ta_handle != NULL);
	ta->ta_err = dt_declare_create(env, obj, attr, NULL, dof,
				       ta->ta_handle);
	if (ta->ta_err != 0)
		return ta->ta_err;

	arg = tx_add_exec(ta, out_tx_create_exec, out_tx_create_undo, file,
			  line);
	LASSERT(arg);

	/* release the object in out_trans_stop */
	lu_object_get(&obj->do_lu);
	arg->object = obj;
	arg->u.create.attr = *attr;
	if (parent_fid)
		arg->u.create.fid = *parent_fid;
	memset(&arg->u.create.hint, 0, sizeof(arg->u.create.hint));
	arg->u.create.dof  = *dof;
	arg->reply = reply;
	arg->index = index;

	return 0;
}
Пример #5
0
static int __out_tx_index_delete(const struct lu_env *env,
				 struct dt_object *dt_obj, char *name,
				 struct thandle_exec_args *ta,
				 struct update_reply *reply,
				 int index, char *file, int line)
{
	struct tx_arg *arg;

	if (dt_try_as_dir(env, dt_obj) == 0) {
		ta->ta_err = -ENOTDIR;
		return ta->ta_err;
	}

	LASSERT(ta->ta_handle != NULL);
	ta->ta_err = dt_declare_delete(env, dt_obj,
				       (struct dt_key *)name,
				       ta->ta_handle);
	if (ta->ta_err != 0)
		return ta->ta_err;

	arg = tx_add_exec(ta, out_tx_index_delete_exec,
			  out_tx_index_delete_undo, file,
			  line);
	LASSERT(arg);
	lu_object_get(&dt_obj->do_lu);
	arg->object = dt_obj;
	arg->reply = reply;
	arg->index = index;
	arg->u.insert.key = (struct dt_key *)name;
	return 0;
}
Пример #6
0
/**
 * Initialize osd Iterator for given osd index object.
 *
 * \param  dt    - osd index object
 * \param  attr  - not used
 * \param  capa  - BYPASS_CAPA
 */
static struct dt_it *osd_it_acct_init(const struct lu_env *env,
				      struct dt_object *dt,
				      __u32 attr,
				      struct lustre_capa *capa)
{
	struct osd_thread_info	*info = osd_oti_get(env);
	struct osd_it_quota	*it;
	struct lu_object	*lo   = &dt->do_lu;
	struct osd_device	*osd  = osd_dev(lo->lo_dev);
	int			 rc;
	ENTRY;

	LASSERT(lu_object_exists(lo));

	if (info == NULL)
		RETURN(ERR_PTR(-ENOMEM));

	it = &info->oti_it_quota;
	memset(it, 0, sizeof(*it));
	it->oiq_oid = osd_quota_fid2dmu(lu_object_fid(lo));

	/* initialize zap cursor */
	rc = -udmu_zap_cursor_init(&it->oiq_zc, &osd->od_objset, it->oiq_oid,0);
	if (rc)
		RETURN(ERR_PTR(rc));

	/* take object reference */
	lu_object_get(lo);
	it->oiq_obj   = osd_dt_obj(dt);
	it->oiq_reset = 1;

	RETURN((struct dt_it *)it);
}
Пример #7
0
static int __out_tx_attr_set(struct mdt_thread_info *info,
			     struct dt_object *dt_obj,
			     const struct lu_attr *attr,
			     struct thandle_exec_args *th,
			     struct update_reply *reply, int index,
			     char *file, int line)
{
	struct tx_arg		*arg;

	LASSERT(th->ta_handle != NULL);
	th->ta_err = dt_declare_attr_set(info->mti_env, dt_obj, attr,
					 th->ta_handle);
	if (th->ta_err != 0)
		return th->ta_err;

	arg = tx_add_exec(th, out_tx_attr_set_exec, out_tx_attr_set_undo,
			  file, line);
	LASSERT(arg);
	lu_object_get(&dt_obj->do_lu);
	arg->object = dt_obj;
	arg->u.attr_set.attr = *attr;
	arg->reply = reply;
	arg->index = index;
	return 0;
}
Пример #8
0
static struct dt_it *osd_index_it_init(const struct lu_env *env,
				       struct dt_object *dt,
				       __u32 unused,
				       struct lustre_capa *capa)
{
	struct osd_thread_info  *info = osd_oti_get(env);
	struct osd_zap_it       *it;
	struct osd_object       *obj = osd_dt_obj(dt);
	struct osd_device       *osd = osd_obj2dev(obj);
	struct lu_object        *lo  = &dt->do_lu;
	ENTRY;

	/* XXX: check capa ? */

	LASSERT(lu_object_exists(lo));
	LASSERT(obj->oo_db);
	LASSERT(udmu_object_is_zap(obj->oo_db));
	LASSERT(info);

	it = &info->oti_it_zap;

	if (udmu_zap_cursor_init(&it->ozi_zc, &osd->od_objset,
				 obj->oo_db->db_object, 0))
		RETURN(ERR_PTR(-ENOMEM));

	it->ozi_obj   = obj;
	it->ozi_capa  = capa;
	it->ozi_reset = 1;
	lu_object_get(lo);

	RETURN((struct dt_it *)it);
}
Пример #9
0
/**
 * Add new item for parent FID verification.
 *
 * Prepare new verification item and pass it to the dedicated
 * verification thread for further processing.
 *
 * \param[in] env	execution environment
 * \param[in] fo	OFD object
 * \param[in] oa	OBDO structure with PFID
 */
static void ofd_add_inconsistency_item(const struct lu_env *env,
				       struct ofd_object *fo, struct obdo *oa)
{
	struct ofd_device *ofd = ofd_obj2dev(fo);
	struct ofd_inconsistency_item *oii;
	struct filter_fid *ff;
	bool wakeup = false;

	OBD_ALLOC_PTR(oii);
	if (oii == NULL)
		return;

	INIT_LIST_HEAD(&oii->oii_list);
	lu_object_get(&fo->ofo_obj.do_lu);
	oii->oii_obj = fo;
	ff = &oii->oii_ff;
	ff->ff_parent.f_seq = oa->o_parent_seq;
	ff->ff_parent.f_oid = oa->o_parent_oid;
	ff->ff_parent.f_stripe_idx = oa->o_stripe_idx;
	ff->ff_layout = oa->o_layout;

	spin_lock(&ofd->ofd_inconsistency_lock);
	if (fo->ofo_pfid_checking || fo->ofo_pfid_verified) {
		spin_unlock(&ofd->ofd_inconsistency_lock);
		OBD_FREE_PTR(oii);

		return;
	}

	fo->ofo_pfid_checking = 1;
	if (list_empty(&ofd->ofd_inconsistency_list))
		wakeup = true;
	list_add_tail(&oii->oii_list, &ofd->ofd_inconsistency_list);
	spin_unlock(&ofd->ofd_inconsistency_lock);
	if (wakeup)
		wake_up_all(&ofd->ofd_inconsistency_thread.t_ctl_waitq);

	/* XXX: When the found inconsistency exceeds some threshold,
	 *	we can trigger the LFSCK to scan part of the system
	 *	or the whole system, which depends on how to define
	 *	the threshold, a simple way maybe like that: define
	 *	the absolute value of how many inconsisteny allowed
	 *	to be repaired via self detect/repair mechanism, if
	 *	exceeded, then trigger the LFSCK to scan the layout
	 *	inconsistency within the whole system. */
}
Пример #10
0
static int __out_tx_destroy(const struct lu_env *env, struct dt_object *dt_obj,
			     struct thandle_exec_args *ta,
			     struct update_reply *reply,
			     int index, char *file, int line)
{
	struct tx_arg *arg;

	LASSERT(ta->ta_handle != NULL);
	ta->ta_err = dt_declare_destroy(env, dt_obj, ta->ta_handle);
	if (ta->ta_err)
		return ta->ta_err;

	arg = tx_add_exec(ta, out_tx_destroy_exec, out_tx_destroy_undo,
			  file, line);
	LASSERT(arg);
	lu_object_get(&dt_obj->do_lu);
	arg->object = dt_obj;
	arg->reply = reply;
	arg->index = index;
	return 0;
}
Пример #11
0
static int __out_tx_index_insert(struct mdt_thread_info *info,
				 struct dt_object *dt_obj,
				 char *name, struct lu_fid *fid,
				 struct thandle_exec_args *th,
				 struct update_reply *reply,
				 int index, char *file, int line)
{
	struct tx_arg *arg;

	LASSERT(th->ta_handle != NULL);

	if (lu_object_exists(&dt_obj->do_lu)) {
		if (dt_try_as_dir(info->mti_env, dt_obj) == 0) {
			th->ta_err = -ENOTDIR;
			return th->ta_err;
		}
		th->ta_err = dt_declare_insert(info->mti_env, dt_obj,
					       (struct dt_rec *)fid,
					       (struct dt_key *)name,
					       th->ta_handle);
	}

	if (th->ta_err != 0)
		return th->ta_err;

	arg = tx_add_exec(th, out_tx_index_insert_exec,
			  out_tx_index_insert_undo, file,
			  line);
	LASSERT(arg);
	lu_object_get(&dt_obj->do_lu);
	arg->object = dt_obj;
	arg->reply = reply;
	arg->index = index;
	arg->u.insert.rec = (struct dt_rec *)fid;
	arg->u.insert.key = (struct dt_key *)name;

	return 0;
}
Пример #12
0
/*
 * Set up quota directory (either "quota_master" or "quota_slave") for a QMT or
 * QSD instance. This function is also used to create per-pool directory on
 * the quota master.
 * The directory is created with a local sequence if it does not exist already.
 * This function is called at ->ldo_prepare time when the full device stack is
 * configured.
 *
 * \param env  - is the environment passed by the caller
 * \param dev  - is the dt_device where to create the quota directory
 * \param parent  - is the parent directory. If not specified, the directory
 *                  will be created under the root directory
 * \param name - is the name of quota directory to be created
 *
 * \retval     - pointer to quota root dt_object on success, appropriate error
 *               on failure
 */
struct dt_object *lquota_disk_dir_find_create(const struct lu_env *env,
					      struct dt_device *dev,
					      struct dt_object *parent,
					      const char *name)
{
	struct lquota_thread_info	*qti = lquota_info(env);
	struct dt_object		*qt_dir = NULL;
	struct local_oid_storage	*los = NULL;
	int				 rc;
	ENTRY;

	/* Set up local storage to create the quota directory.
	 * We use the sequence reserved for local named objects */
	lu_local_name_obj_fid(&qti->qti_fid, 1);
	rc = local_oid_storage_init(env, dev, &qti->qti_fid, &los);
	if (rc)
		RETURN(ERR_PTR(rc));

	if (parent == NULL) {
		/* Fetch dt object associated with root directory */
		rc = dt_root_get(env, dev, &qti->qti_fid);
		if (rc)
			GOTO(out, rc);

		parent = dt_locate_at(env, dev, &qti->qti_fid,
				      dev->dd_lu_dev.ld_site->ls_top_dev, NULL);
		if (IS_ERR(parent))
			GOTO(out, rc = PTR_ERR(parent));
	} else {
		lu_object_get(&parent->do_lu);
	}

	/* create quota directory to be used for all quota index files */
	qt_dir = local_file_find_or_create(env, los, parent, name, S_IFDIR |
					   S_IRUGO | S_IWUSR | S_IXUGO);
	if (IS_ERR(qt_dir))
		GOTO(out, rc = PTR_ERR(qt_dir));

	/* local_oid_storage_fini() will finalize the local storage device,
	 * we have to open the object in another device stack */
	qti->qti_fid = qt_dir->do_lu.lo_header->loh_fid;
	lu_object_put_nocache(env, &qt_dir->do_lu);
	qt_dir = dt_locate(env, dev, &qti->qti_fid);
	if (IS_ERR(qt_dir))
		GOTO(out, rc = PTR_ERR(qt_dir));

	if (!dt_try_as_dir(env, qt_dir))
		GOTO(out, rc = -ENOTDIR);
	EXIT;
out:
	if (parent != NULL && !IS_ERR(parent))
		lu_object_put(env, &parent->do_lu);
	if (los != NULL)
		local_oid_storage_fini(env, los);
	if (rc) {
		if (qt_dir != NULL && !IS_ERR(qt_dir))
			lu_object_put(env, &qt_dir->do_lu);
		qt_dir = ERR_PTR(rc);
	}
	return qt_dir;
}
Пример #13
0
static int llog_test_8(const struct lu_env *env, struct obd_device *obd)
{
	struct llog_handle	*llh = NULL;
	char			 name[10];
	int			 rc, rc2, i;
	int			 orig_counter;
	struct llog_mini_rec	 lmr;
	struct llog_ctxt	*ctxt;
	struct dt_object	*obj = NULL;

	ENTRY;

	ctxt = llog_get_context(obd, LLOG_TEST_ORIG_CTXT);
	LASSERT(ctxt);

	lmr.lmr_hdr.lrh_len = lmr.lmr_tail.lrt_len = LLOG_MIN_REC_SIZE;
	lmr.lmr_hdr.lrh_type = 0xf00f00;

	CWARN("8a: fill the first plain llog\n");
	rc = llog_open(env, ctxt, &llh, &cat_logid, NULL, LLOG_OPEN_EXISTS);
	if (rc) {
		CERROR("8a: llog_create with logid failed: %d\n", rc);
		GOTO(out_put, rc);
	}

	rc = llog_init_handle(env, llh, LLOG_F_IS_CAT, &uuid);
	if (rc) {
		CERROR("8a: can't init llog handle: %d\n", rc);
		GOTO(out, rc);
	}

	plain_counter = 0;
	rc = llog_cat_process(env, llh, test_8_cb, "foobar", 0, 0);
	if (rc != 0) {
		CERROR("5a: process with test_8_cb failed: %d\n", rc);
		GOTO(out, rc);
	}
	orig_counter = plain_counter;

	for (i = 0; i < 100; i++) {
		rc = llog_cat_add(env, llh, &lmr.lmr_hdr, NULL);
		if (rc) {
			CERROR("5a: add record failed\n");
			GOTO(out, rc);
		}
	}

	/* grab the current plain llog, we'll corrupt it later */
	obj = llh->u.chd.chd_current_log->lgh_obj;
	LASSERT(obj);
	lu_object_get(&obj->do_lu);
	CWARN("8a: pin llog "DFID"\n", PFID(lu_object_fid(&obj->do_lu)));

	rc2 = llog_cat_close(env, llh);
	if (rc2) {
		CERROR("8a: close log %s failed: %d\n", name, rc2);
		if (rc == 0)
			rc = rc2;
		GOTO(out_put, rc);
	}

	CWARN("8b: fill the second plain llog\n");
	rc = llog_open(env, ctxt, &llh, &cat_logid, NULL, LLOG_OPEN_EXISTS);
	if (rc) {
		CERROR("8b: llog_create with logid failed: %d\n", rc);
		GOTO(out_put, rc);
	}

	rc = llog_init_handle(env, llh, LLOG_F_IS_CAT, &uuid);
	if (rc) {
		CERROR("8b: can't init llog handle: %d\n", rc);
		GOTO(out, rc);
	}

	for (i = 0; i < 100; i++) {
		rc = llog_cat_add(env, llh, &lmr.lmr_hdr, NULL);
		if (rc) {
			CERROR("8b: add record failed\n");
			GOTO(out, rc);
		}
	}
	CWARN("8b: second llog "DFID"\n",
		PFID(lu_object_fid(&llh->u.chd.chd_current_log->lgh_obj->do_lu)));

	rc2 = llog_cat_close(env, llh);
	if (rc2) {
		CERROR("8b: close log %s failed: %d\n", name, rc2);
		if (rc == 0)
			rc = rc2;
		GOTO(out_put, rc);
	}

	CWARN("8c: drop two records from the first plain llog\n");
	llog_truncate(env, obj);

	CWARN("8d: count survived records\n");
	rc = llog_open(env, ctxt, &llh, &cat_logid, NULL, LLOG_OPEN_EXISTS);
	if (rc) {
		CERROR("8d: llog_create with logid failed: %d\n", rc);
		GOTO(out_put, rc);
	}

	rc = llog_init_handle(env, llh, LLOG_F_IS_CAT, &uuid);
	if (rc) {
		CERROR("8d: can't init llog handle: %d\n", rc);
		GOTO(out, rc);
	}

	plain_counter = 0;
	rc = llog_cat_process(env, llh, test_8_cb, "foobar", 0, 0);
	if (rc != 0) {
		CERROR("8d: process with test_8_cb failed: %d\n", rc);
		GOTO(out, rc);
	}

	if (orig_counter + 200 - 2 != plain_counter) {
		CERROR("found %d records (expected %d)\n", plain_counter,
		       orig_counter + 200 - 2);
		rc = -EIO;
	}

out:
	CWARN("8d: close re-opened catalog\n");
	rc2 = llog_cat_close(env, llh);
	if (rc2) {
		CERROR("8d: close log %s failed: %d\n", name, rc2);
		if (rc == 0)
			rc = rc2;
	}
out_put:
	llog_ctxt_put(ctxt);

	if (obj != NULL)
		lu_object_put(env, &obj->do_lu);

	RETURN(rc);
}