Ejemplo n.º 1
0
void 
daemon_cleanup(struct daemon* daemon)
{
	int i;
	log_assert(daemon);
	/* before stopping main worker, handle signals ourselves, so we
	   don't die on multiple reload signals for example. */
	signal_handling_record();
	log_thread_set(NULL);
	/* clean up caches because
	 * a) RRset IDs will be recycled after a reload, causing collisions
	 * b) validation config can change, thus rrset, msg, keycache clear */
	slabhash_clear(&daemon->env->rrset_cache->table);
	slabhash_clear(daemon->env->msg_cache);
	local_zones_delete(daemon->local_zones);
	daemon->local_zones = NULL;
	/* key cache is cleared by module desetup during next daemon_fork() */
	daemon_remote_clear(daemon->rc);
	for(i=0; i<daemon->num; i++)
		worker_delete(daemon->workers[i]);
	free(daemon->workers);
	daemon->workers = NULL;
	daemon->num = 0;
#ifdef USE_DNSTAP
	dt_delete(daemon->dtenv);
#endif
	daemon->cfg = NULL;
}
Ejemplo n.º 2
0
static int out_tx_index_insert_undo(struct mdt_thread_info *info,
				    struct thandle *th, struct tx_arg *arg)
{
	struct dt_object *dt_obj = arg->object;
	int rc;

	LASSERT(dt_obj != NULL && !IS_ERR(dt_obj));

	CDEBUG(D_OTHER, "index delete "DFID" name: %s\n",
	       PFID(lu_object_fid(&arg->object->do_lu)),
	       (char *)arg->u.insert.key);

	if (dt_try_as_dir(info->mti_env, dt_obj) == 0) {
		CERROR("%s: "DFID" is not directory: rc = %d\n",
		       mdt_obd_name(info->mti_mdt),
		       PFID(lu_object_fid(&dt_obj->do_lu)), -ENOTDIR);
		return -ENOTDIR;
	}

	dt_write_lock(info->mti_env, dt_obj, MOR_TGT_CHILD);
	rc = dt_delete(info->mti_env, dt_obj, arg->u.insert.key, th, NULL);
	dt_write_unlock(info->mti_env, dt_obj);

	update_insert_reply(arg->reply, NULL, 0, arg->index, rc);

	return rc;
}
Ejemplo n.º 3
0
static int lfsck_namespace_delete(const struct lu_env *env,
				  struct lfsck_component *com,
				  const struct lu_fid *fid)
{
	struct lfsck_instance	*lfsck  = com->lc_lfsck;
	struct lu_fid		*key    = &lfsck_env_info(env)->lti_fid;
	struct thandle		*handle;
	struct dt_object	*obj    = com->lc_obj;
	int			 rc;
	ENTRY;

	handle = dt_trans_create(env, lfsck->li_bottom);
	if (IS_ERR(handle))
		RETURN(PTR_ERR(handle));

	rc = dt_declare_delete(env, obj, (const struct dt_key *)fid, handle);
	if (rc != 0)
		GOTO(out, rc);

	rc = dt_trans_start_local(env, lfsck->li_bottom, handle);
	if (rc != 0)
		GOTO(out, rc);

	fid_cpu_to_be(key, fid);
	rc = dt_delete(env, obj, (const struct dt_key *)key, handle,
		       BYPASS_CAPA);

	GOTO(out, rc);

out:
	dt_trans_stop(env, lfsck->li_bottom, handle);
	return rc;
}
Ejemplo n.º 4
0
/**
 *  delete an orphan \a obj from orphan index.
 *  \param obj file or directory.
 *  \param th  transaction for index deletion and object destruction.
 *
 *  \pre obj->mod_count == 0 && ORPHAN_OBJ is set for obj.
 *
 *  \retval 0  success
 *  \retval  -ve index operation error.
 */
int mdd_orphan_delete(const struct lu_env *env, struct mdd_object *obj,
		      struct thandle *th)
{
	struct mdd_device *mdd = mdo2mdd(&obj->mod_obj);
	struct dt_object *dor = mdd->mdd_orphans;
	struct dt_key *key;
	int rc = 0;

	ENTRY;

	LASSERT(mdd_write_locked(env, obj) != 0);
	LASSERT(obj->mod_flags & ORPHAN_OBJ);
	LASSERT(obj->mod_count == 0);

	LASSERT(dor);

	key = mdd_orphan_key_fill(env, mdo2fid(obj));
	dt_write_lock(env, mdd->mdd_orphans, MOR_TGT_ORPHAN);

	if (OBD_FAIL_CHECK(OBD_FAIL_MDS_ORPHAN_DELETE))
		goto ref_del;

	rc = dt_delete(env, mdd->mdd_orphans, key, th);
	if (rc == -ENOENT) {
		key = mdd_orphan_key_fill_20(env, mdo2fid(obj));
		rc = dt_delete(env, mdd->mdd_orphans, key, th);
	}

ref_del:
	if (!rc) {
		/* lov objects will be destroyed by caller */
		mdo_ref_del(env, obj, th);
		if (S_ISDIR(mdd_object_type(obj))) {
			mdo_ref_del(env, obj, th);
			dt_ref_del(env, mdd->mdd_orphans, th);
		}
		obj->mod_flags &= ~ORPHAN_OBJ;
	} else {
		CERROR("%s: could not delete orphan object "DFID": rc = %d\n",
		       mdd2obd_dev(mdd)->obd_name, PFID(mdo2fid(obj)), rc);
	}

	dt_write_unlock(env, mdd->mdd_orphans);
	RETURN(rc);
}
Ejemplo n.º 5
0
static inline int mdd_orphan_delete_obj(const struct lu_env *env,
                                        struct mdd_device  *mdd ,
                                        struct dt_key *key,
                                        struct thandle *th)
{
	struct dt_object *dor = mdd->mdd_orphans;

	return dt_delete(env, dor, key, th);
}
Ejemplo n.º 6
0
/*
 * Write a global record
 *
 * \param env - is the environment passed by the caller
 * \param obj - is the on-disk global index to be updated
 * \param id  - index to be updated
 * \param rec - record to be written
 */
int lquota_disk_write_glb(const struct lu_env *env, struct dt_object *obj,
			  __u64 id, struct lquota_glb_rec *rec)
{
	struct dt_device	*dev = lu2dt_dev(obj->do_lu.lo_dev);
	struct thandle		*th;
	struct dt_key		*key = (struct dt_key *)&id;
	int			 rc;
	ENTRY;

	th = dt_trans_create(env, dev);
	if (IS_ERR(th))
		RETURN(PTR_ERR(th));

	/* the entry with 0 key can always be found in IAM file. */
	if (id == 0) {
		rc = dt_declare_delete(env, obj, key, th);
		if (rc)
			GOTO(out, rc);
	}

	rc = dt_declare_insert(env, obj, (struct dt_rec *)rec, key, th);
	if (rc)
		GOTO(out, rc);

	rc = dt_trans_start_local(env, dev, th);
	if (rc)
		GOTO(out, rc);

	dt_write_lock(env, obj, 0);

	if (id == 0) {
		struct lquota_glb_rec *tmp;

		OBD_ALLOC_PTR(tmp);
		if (tmp == NULL)
			GOTO(out_lock, rc = -ENOMEM);

		rc = dt_lookup(env, obj, (struct dt_rec *)tmp, key,
			       BYPASS_CAPA);

		OBD_FREE_PTR(tmp);
		if (rc == 0) {
			rc = dt_delete(env, obj, key, th, BYPASS_CAPA);
			if (rc)
				GOTO(out_lock, rc);
		}
		rc = 0;
	}

	rc = dt_insert(env, obj, (struct dt_rec *)rec, key, th, BYPASS_CAPA, 1);
out_lock:
	dt_write_unlock(env, obj);
out:
	dt_trans_stop(env, dev, th);
	RETURN(rc);
}
Ejemplo n.º 7
0
/*
 * To enable DNE functionality we need FID of /ROOT directory
 * (which is / as seen by the clients) to belong to MDT0 and
 * not to FID_SEQ_LOCAL_FILE or some other local sequence,
 * which can be used by any node, so can't be part of FLDB.
 *
 * Pre-production code was using FID_SEQ_LOCAL_FILE for /ROOT
 * making few existing setups incompatibile with DNE. This
 * applies to ZFS-based setups only as ldiskfs-based setups
 * are still using IGIF to identify /ROOT.
 *
 * The intention of this code is to fix on-disk state to use
 * FID_SEQ_ROOT for /ROOT:
 *  - "." and ".." references in /ROOT itself and it`s subdirectories
 *  - LinkEA in all the objects listed in /ROOT
 *
 * Given only ZFS is affected where "." and ".." are not stored, we need to:
 *  - delete "." and ".." from /ROOT and its subdirectories
 *  - rename references in LinkEA in all the objects listed in /ROOT
 *
 * This code is subject for removal in 2.5
 */
static int mdd_convert_remove_dots(const struct lu_env *env,
				   struct mdd_device *mdd,
				   struct mdd_object *o)
{
	struct thandle		*th;
	const struct dt_key	*dot = (const struct dt_key *)".";
	const struct dt_key	*dotdot = (const struct dt_key *)"..";
	int			 rc;

	if (dt_try_as_dir(env, mdd_object_child(o)) == 0)
		RETURN(-ENOTDIR);

	/* remove "."/".." and do not insert them back - not stored in ZFS */
	th = dt_trans_create(env, mdd->mdd_child);
	if (IS_ERR(th))
		RETURN(PTR_ERR(th));

	rc = dt_declare_delete(env, mdd_object_child(o), dot, th);
	if (rc)
		GOTO(out, rc);
	rc = dt_declare_delete(env, mdd_object_child(o), dotdot, th);
	if (rc)
		GOTO(out, rc);
	rc = dt_trans_start_local(env, mdd->mdd_child, th);
	if (rc)
		GOTO(out, rc);
	/* ignore non-existing "."/".." - we stored them on disk for
	 * pre-production systems, but this is not how regular ZFS works */
	rc = dt_delete(env, mdd_object_child(o), dot, th, BYPASS_CAPA);
	if (rc == -ENOENT)
		rc = 0;
	if (rc)
		GOTO(out, rc);
	rc = dt_delete(env, mdd_object_child(o), dotdot, th, BYPASS_CAPA);
	if (rc == -ENOENT)
		rc = 0;
	if (rc)
		GOTO(out, rc);

out:
	dt_trans_stop(env, mdd->mdd_child, th);
	RETURN(rc);
}
Ejemplo n.º 8
0
static int orph_index_insert(const struct lu_env *env,
			     struct mdd_object *obj,
			     __u32 op, struct thandle *th)
{
	struct mdd_device	*mdd	= mdo2mdd(&obj->mod_obj);
	struct dt_object	*dor	= mdd->mdd_orphans;
	const struct lu_fid	*lf_dor	= lu_object_fid(&dor->do_lu);
	struct dt_object	*next	= mdd_object_child(obj);
	struct dt_insert_rec	*rec	= &mdd_env_info(env)->mti_dt_rec;
	int			 rc;
        ENTRY;

        LASSERT(mdd_write_locked(env, obj) != 0);
        LASSERT(!(obj->mod_flags & ORPHAN_OBJ));

        mdd_orphan_write_lock(env, mdd);

        rc = mdd_orphan_insert_obj(env, mdd, obj, op, th);
        if (rc)
                GOTO(out, rc);

        mdo_ref_add(env, obj, th);
        if (!S_ISDIR(mdd_object_type(obj)))
		GOTO(out, rc = 0);

        mdo_ref_add(env, obj, th);
        mdd_orphan_ref_add(env, mdd, th);

        /* try best to fixup directory, dont return errors
         * from here */
        if (!dt_try_as_dir(env, next))
		GOTO(out, rc = 0);

	dt_delete(env, next, (const struct dt_key *)dotdot, th);

	rec->rec_fid = lf_dor;
	rec->rec_type = S_IFDIR;
	dt_insert(env, next, (const struct dt_rec *)rec,
		  (const struct dt_key *)dotdot, th, 1);

out:
        if (rc == 0)
                obj->mod_flags |= ORPHAN_OBJ;

        mdd_orphan_write_unlock(env, mdd);

        RETURN(rc);
}
Ejemplo n.º 9
0
static int out_obj_index_delete(const struct lu_env *env,
				struct dt_object *dt_obj,
				const struct dt_key *key,
				struct thandle *th)
{
	int rc;

	CDEBUG(D_INFO, "%s: index delete "DFID" name: %s\n",
	       dt_obd_name(th->th_dev), PFID(lu_object_fid(&dt_obj->do_lu)),
	       (char *)key);

	if (dt_try_as_dir(env, dt_obj) == 0)
		return -ENOTDIR;

	dt_write_lock(env, dt_obj, MOR_TGT_CHILD);
	rc = dt_delete(env, dt_obj, key, th, NULL);
	dt_write_unlock(env, dt_obj);

	return rc;
}
Ejemplo n.º 10
0
/*! API: run tests. */
int main(int argc, char *argv[])
{
	plan(8);

	// Register service and signal handler
	struct sigaction sa;
	sa.sa_handler = interrupt_handle;
	sigemptyset(&sa.sa_mask);
	sa.sa_flags = 0;
	sigaction(SIGALRM, &sa, NULL); // Interrupt

	/* Initialize */
	srand(time(NULL));
	pthread_mutex_init(&_runnable_mx, NULL);
	pthread_mutex_init(&_destructor_mx, NULL);

	/* Test 1: Create unit */
	dt_unit_t *unit = dt_create(2, &runnable, NULL, NULL);
	ok(unit != NULL, "dthreads: create unit (size %d)", unit->size);
	if (unit == NULL) {
		skip_block(7, "No dthreads unit");
		goto skip_all;
	}

	/* Test 2: Start tasks. */
	_runnable_i = 0;
	ok(dt_start(unit) == 0, "dthreads: start single task");

	/* Test 3: Wait for tasks. */
	ok(dt_join(unit) == 0, "dthreads: join threads");

	/* Test 4: Compare counter. */
	int expected = _runnable_cycles * 2;
	is_int(expected, _runnable_i, "dthreads: result ok");

	/* Test 5: Deinitialize */
	dt_delete(&unit);
	ok(unit == NULL, "dthreads: delete unit");

	/* Test 6: Wrong values. */
	unit = dt_create(-1, NULL, NULL, NULL);
	ok(unit == NULL, "dthreads: create with negative count");

	/* Test 7: NULL operations crashing. */
	int ret = 0;
	ret += dt_activate(0);
	ret += dt_cancel(0);
	ret += dt_compact(0);
	dt_delete(0);
	ret += dt_is_cancelled(0);
	ret += dt_join(0);
	ret += dt_signalize(0, SIGALRM);
	ret += dt_start(0);
	ret += dt_stop(0);
	ret += dt_unit_lock(0);
	ret += dt_unit_unlock(0);
	is_int(-1098, ret, "dthreads: correct values when passed NULL context");

	/* Test 8: Thread destructor. */
	_destructor_data = 0;
	unit = dt_create(2, 0, destruct, 0);
	dt_start(unit);
	dt_stop(unit);
	dt_join(unit);
	is_int(2, _destructor_data, "dthreads: destructor with dt_create_coherent()");
	dt_delete(&unit);

skip_all:

	pthread_mutex_destroy(&_runnable_mx);
	pthread_mutex_destroy(&_destructor_mx);
	return 0;
}
Ejemplo n.º 11
0
static int llog_osd_destroy(const struct lu_env *env,
			    struct llog_handle *loghandle)
{
	struct llog_thread_info *lgi = llog_info(env);
	struct llog_ctxt	*ctxt;
	struct dt_object	*o, *llog_dir = NULL;
	struct dt_device	*d;
	struct thandle		*th;
	char			*name = NULL;
	int			 rc;

	ENTRY;

	ctxt = loghandle->lgh_ctxt;
	LASSERT(ctxt);

	o = loghandle->lgh_obj;
	LASSERT(o);

	d = lu2dt_dev(o->do_lu.lo_dev);
	LASSERT(d);
	LASSERT(d == ctxt->loc_exp->exp_obd->obd_lvfs_ctxt.dt);

	th = dt_trans_create(env, d);
	if (IS_ERR(th))
		RETURN(PTR_ERR(th));

	if (loghandle->lgh_name) {
		llog_dir = llog_osd_dir_get(env, ctxt);
		if (IS_ERR(llog_dir))
			GOTO(out_trans, rc = PTR_ERR(llog_dir));

		dt_declare_ref_del(env, o, th);
		name = loghandle->lgh_name;
		rc = dt_declare_delete(env, llog_dir,
				       (struct dt_key *)name, th);
		if (rc)
			GOTO(out_trans, rc);
	}

	dt_declare_ref_del(env, o, th);

	rc = dt_declare_destroy(env, o, th);
	if (rc)
		GOTO(out_trans, rc);

	rc = dt_trans_start_local(env, d, th);
	if (rc)
		GOTO(out_trans, rc);

	dt_write_lock(env, o, 0);
	if (dt_object_exists(o)) {
		if (name) {
			dt_ref_del(env, o, th);
			dt_read_lock(env, llog_dir, 0);
			rc = dt_delete(env, llog_dir,
				       (struct dt_key *) name,
				       th, BYPASS_CAPA);
			dt_read_unlock(env, llog_dir);
			if (rc) {
				CERROR("%s: can't remove llog %s: rc = %d\n",
				       o->do_lu.lo_dev->ld_obd->obd_name,
				       name, rc);
				GOTO(out_unlock, rc);
			}
		}
		/*
		 * XXX: compatibility bits
		 *      on old filesystems llogs are referenced by the name
		 *      on the new ones they are referenced by OI and by
		 *      the name
		 */
		rc = dt_attr_get(env, o, &lgi->lgi_attr, NULL);
		if (rc)
			GOTO(out_unlock, rc);
		LASSERT(lgi->lgi_attr.la_nlink < 2);
		if (lgi->lgi_attr.la_nlink == 1)
			dt_ref_del(env, o, th);
		rc = dt_destroy(env, o, th);
		if (rc)
			GOTO(out_unlock, rc);
	}
out_unlock:
	dt_write_unlock(env, o);
out_trans:
	dt_trans_stop(env, d, th);
	if (llog_dir != NULL)
		lu_object_put(env, &llog_dir->do_lu);
	RETURN(rc);
}
Ejemplo n.º 12
0
static int lfsck_namespace_update(const struct lu_env *env,
				  struct lfsck_component *com,
				  const struct lu_fid *fid,
				  __u8 flags, bool force)
{
	struct lfsck_instance	*lfsck  = com->lc_lfsck;
	struct lu_fid		*key    = &lfsck_env_info(env)->lti_fid;
	struct thandle		*handle;
	struct dt_object	*obj    = com->lc_obj;
	int			 rc;
	bool			 exist  = false;
	__u8			 tf;
	ENTRY;

	rc = lfsck_namespace_lookup(env, com, fid, &tf);
	if (rc != 0 && rc != -ENOENT)
		RETURN(rc);

	if (rc == 0) {
		if (!force || flags == tf)
			RETURN(0);

		exist = true;
		handle = dt_trans_create(env, lfsck->li_bottom);
		if (IS_ERR(handle))
			RETURN(PTR_ERR(handle));

		rc = dt_declare_delete(env, obj, (const struct dt_key *)fid,
				       handle);
		if (rc != 0)
			GOTO(out, rc);
	} else {
		handle = dt_trans_create(env, lfsck->li_bottom);
		if (IS_ERR(handle))
			RETURN(PTR_ERR(handle));
	}

	rc = dt_declare_insert(env, obj, (const struct dt_rec *)&flags,
			       (const struct dt_key *)fid, handle);
	if (rc != 0)
		GOTO(out, rc);

	rc = dt_trans_start_local(env, lfsck->li_bottom, handle);
	if (rc != 0)
		GOTO(out, rc);

	fid_cpu_to_be(key, fid);
	if (exist) {
		rc = dt_delete(env, obj, (const struct dt_key *)key, handle,
			       BYPASS_CAPA);
		if (rc != 0) {
			CERROR("%s: fail to insert "DFID": rc = %d\n",
			       lfsck_lfsck2name(com->lc_lfsck), PFID(fid), rc);
			GOTO(out, rc);
		}
	}

	rc = dt_insert(env, obj, (const struct dt_rec *)&flags,
		       (const struct dt_key *)key, handle, BYPASS_CAPA, 1);

	GOTO(out, rc);

out:
	dt_trans_stop(env, lfsck->li_bottom, handle);
	return rc;
}
Ejemplo n.º 13
0
/**
 * insert range in fld store.
 *
 *      \param  range  range to be inserted
 *      \param  th     transaction for this operation as it could compound
 *                     transaction.
 *
 *      \retval  0  success
 *      \retval  -ve error
 *
 * The whole fld index insertion is protected by seq->lss_mutex (see
 * seq_server_alloc_super), i.e. only one thread will access fldb each
 * time, so we do not need worry the fld file and cache will being
 * changed between declare and create.
 * Because the fld entry can only be increamental, so we will only check
 * whether it can be merged from the left.
 **/
int fld_index_create(const struct lu_env *env, struct lu_server_fld *fld,
		     const struct lu_seq_range *new_range, struct thandle *th)
{
	struct lu_seq_range	*range;
	struct lu_seq_range	*tmp;
	struct fld_thread_info	*info;
	int			rc = 0;
	int			deleted = 0;
	struct fld_cache_entry	*flde;
	ENTRY;

	info = lu_context_key_get(&env->le_ctx, &fld_thread_key);

	LASSERT_MUTEX_LOCKED(&fld->lsf_lock);

	range = &info->fti_lrange;
	memset(range, 0, sizeof(*range));
	tmp = &info->fti_irange;
	rc = fld_index_lookup(env, fld, new_range->lsr_start, range);
	if (rc != -ENOENT) {
		rc = rc == 0 ? -EEXIST : rc;
		GOTO(out, rc);
	}

	if (new_range->lsr_start == range->lsr_end && range->lsr_end != 0 &&
	    range_compare_loc(new_range, range) == 0) {
		range_cpu_to_be(tmp, range);
		rc = dt_delete(env, fld->lsf_obj,
			       (struct dt_key *)&tmp->lsr_start, th,
				BYPASS_CAPA);
		if (rc != 0)
			GOTO(out, rc);
		memcpy(tmp, new_range, sizeof(*new_range));
		tmp->lsr_start = range->lsr_start;
		deleted = 1;
	} else {
		memcpy(tmp, new_range, sizeof(*new_range));
	}

	range_cpu_to_be(tmp, tmp);
	rc = dt_insert(env, fld->lsf_obj, (struct dt_rec *)tmp,
		       (struct dt_key *)&tmp->lsr_start, th, BYPASS_CAPA, 1);
	if (rc != 0) {
		CERROR("%s: insert range "DRANGE" failed: rc = %d\n",
		       fld->lsf_name, PRANGE(new_range), rc);
		GOTO(out, rc);
	}

	flde = fld_cache_entry_create(new_range);
	if (IS_ERR(flde))
		GOTO(out, rc = PTR_ERR(flde));

	write_lock(&fld->lsf_cache->fci_lock);
	if (deleted)
		fld_cache_delete_nolock(fld->lsf_cache, new_range);
	rc = fld_cache_insert_nolock(fld->lsf_cache, flde);
	write_unlock(&fld->lsf_cache->fci_lock);
	if (rc)
		OBD_FREE_PTR(flde);
out:
	RETURN(rc);
}
Ejemplo n.º 14
0
static int mdd_orphan_destroy(const struct lu_env *env, struct mdd_object *obj,
			      struct dt_key *key)
{
	struct thandle *th = NULL;
	struct mdd_device *mdd = mdo2mdd(&obj->mod_obj);
	bool orphan_exists = true;
	int rc = 0;
	ENTRY;

	th = mdd_trans_create(env, mdd);
	if (IS_ERR(th)) {
		rc = PTR_ERR(th);
		if (rc != -EINPROGRESS)
			CERROR("%s: cannot get orphan thandle: rc = %d\n",
			       mdd2obd_dev(mdd)->obd_name, rc);
		RETURN(rc);
	}

	mdd_write_lock(env, obj, MOR_TGT_CHILD);
	rc = mdd_orphan_declare_delete(env, obj, th);
	if (rc == -ENOENT)
		orphan_exists = false;
	else if (rc)
		GOTO(unlock, rc);

	if (orphan_exists) {
		rc = mdo_declare_destroy(env, obj, th);
		if (rc)
			GOTO(unlock, rc);
	}

	rc = mdd_trans_start(env, mdd, th);
	if (rc)
		GOTO(unlock, rc);

	if (likely(obj->mod_count == 0)) {
		dt_write_lock(env, mdd->mdd_orphans, MOR_TGT_ORPHAN);
		rc = dt_delete(env, mdd->mdd_orphans, key, th);
		if (rc) {
			CERROR("%s: could not delete orphan "DFID": rc = %d\n",
			       mdd2obd_dev(mdd)->obd_name, PFID(mdo2fid(obj)),
			       rc);
		} else if (orphan_exists) {
			mdo_ref_del(env, obj, th);
			if (S_ISDIR(mdd_object_type(obj))) {
				mdo_ref_del(env, obj, th);
				dt_ref_del(env, mdd->mdd_orphans, th);
			}
			rc = mdo_destroy(env, obj, th);
		} else {
			CWARN("%s: orphan %s "DFID" doesn't exist\n",
			      mdd2obd_dev(mdd)->obd_name, (char *)key,
			      PFID(mdo2fid(obj)));
		}
		dt_write_unlock(env, mdd->mdd_orphans);
	}
unlock:
	mdd_write_unlock(env, obj);

	rc = mdd_trans_stop(env, mdd, 0, th);

	RETURN(rc);
}
Ejemplo n.º 15
0
/*! API: run tests. */
static int dt_tests_run(int argc, char *argv[])
{
	// Register service and signal handler
	struct sigaction sa;
	sa.sa_handler = interrupt_handle;
	sigemptyset(&sa.sa_mask);
	sa.sa_flags = 0;
	sigaction(SIGALRM, &sa, NULL); // Interrupt

	/* Initialize */
	srand(time(NULL));
	struct timeval tv;
	pthread_mutex_init(&_runnable_mx, NULL);

	/* Test 1: Create unit */
	dt_unit_t *unit = dt_test_create(2);
	ok(unit != 0, "dthreads: create unit (optimal size %d)", unit->size);
	skip(unit == 0, DT_TEST_COUNT - 1);

	/* Test 2: Assign a single task. */
	ok(dt_test_single(unit), "dthreads: assign single task");

	/* Test 3: Start tasks. */
	_runnable_i = 0;
	ok(dt_test_start(unit), "dthreads: start single task");

	/* Test 4: Wait for tasks. */
	ok(dt_test_join(unit), "dthreads: join threads");

	/* Test 5: Compare counter. */
	int expected = _runnable_cycles * 1;
	cmp_ok(_runnable_i, "==", expected, "dthreads: result ok");

	/* Test 6: Repurpose threads. */
	_runnable_i = 0;
	ok(dt_test_coherent(unit), "dthreads: repurpose to coherent");

	/* Test 7: Restart threads. */
	ok(dt_test_start(unit), "dthreads: start coherent unit");

	/* Test 8: Repurpose single thread. */
	tv.tv_sec = 0;
	tv.tv_usec = 4000 + rand() % 1000; // 4-5ms
	note("waiting for %dus to let thread do some work ...",
	     tv.tv_usec);
	select(0, 0, 0, 0, &tv);
	ok(dt_test_repurpose(unit, 0), "dthreads: repurpose on-the-fly");

	/* Test 9: Cancel blocking thread. */
	tv.tv_sec = 0;
	tv.tv_usec = (250 + rand() % 500) * 1000; // 250-750ms
	note("waiting for %dms to let thread pretend blocking I/O ...",
	     tv.tv_usec / 1000);
	select(0, 0, 0, 0, &tv);
	ok(dt_test_cancel(unit, 0), "dthreads: cancel blocking thread");

	/* Test 10: Wait for tasks. */
	ok(dt_test_join(unit), "dthreads: join threads");

	/* Test 11: Compare counter. */
	int expected_lo = _runnable_cycles * (unit->size - 1);
	cmp_ok(_runnable_i, ">=", expected_lo,
	       "dthreads: result %d is => %d", _runnable_i, expected_lo);

	/* Test 12: Compare counter #2. */
	/*! \note repurpose could trigger next run of the unit if both finished */
	int expected_hi = _runnable_cycles * (unit->size + unit->size - 1);
	cmp_ok(_runnable_i, "<=", expected_hi,
	       "dthreads: result %d is <= %d", _runnable_i, expected_hi);

	/* Test 13: Reanimate dead threads. */
	ok(dt_test_reanimate(unit), "dthreads: reanimate dead threads");

	/* Test 14: Deinitialize */
	dt_delete(&unit);
	ok(unit == 0, "dthreads: delete unit");
	endskip;

	/* Test 15: Wrong values. */
	unit = dt_create(-1);
	ok(unit == 0, "dthreads: create with negative count");
	unit = dt_create_coherent(dt_optimal_size(), 0, 0);

	/* Test 16: NULL runnable. */
	cmp_ok(dt_start(unit), "==", 0, "dthreads: start with NULL runnable");

	/* Test 17: NULL operations crashing. */
	int op_count = 14;
	int expected_min = op_count * -1;
	// All functions must return -1 at least
	int ret = 0;
	lives_ok( {
		ret += dt_activate(0);              // -1
		ret += dt_cancel(0);                // -1
		ret += dt_compact(0);               // -1
		dt_delete(0);                //
		ret += dt_is_cancelled(0);          // 0
		ret += dt_join(0);                  // -1
		ret += dt_repurpose(0, 0, 0);       // -1
		ret += dt_signalize(0, SIGALRM);    // -1
		ret += dt_start(0);                 // -1
		ret += dt_start_id(0);              // -1
		ret += dt_stop(0);                  // -1
		ret += dt_stop_id(0);               // -1
		ret += dt_unit_lock(0);             // -1
		ret += dt_unit_unlock(0);           // -1
	}, "dthreads: not crashed while executing functions on NULL context");
Ejemplo n.º 16
0
/**
 * Implementation of the llog_operations::lop_destroy
 *
 * This function destroys the llog and deletes also entry in the
 * llog directory in case of named llog. Llog should be opened prior that.
 * Destroy method is not part of external transaction and does everything
 * inside.
 *
 * \param[in] env		execution environment
 * \param[in] loghandle	llog handle of the current llog
 *
 * \retval		0 on successful destroy
 * \retval		negative value on error
 */
static int llog_osd_destroy(const struct lu_env *env,
			    struct llog_handle *loghandle)
{
	struct llog_ctxt	*ctxt;
	struct dt_object	*o, *llog_dir = NULL;
	struct dt_device	*d;
	struct thandle		*th;
	char			*name = NULL;
	int			 rc;

	ENTRY;

	ctxt = loghandle->lgh_ctxt;
	LASSERT(ctxt);

	o = loghandle->lgh_obj;
	LASSERT(o);

	d = lu2dt_dev(o->do_lu.lo_dev);
	LASSERT(d);
	LASSERT(d == ctxt->loc_exp->exp_obd->obd_lvfs_ctxt.dt);

	th = dt_trans_create(env, d);
	if (IS_ERR(th))
		RETURN(PTR_ERR(th));

	if (loghandle->lgh_name) {
		llog_dir = llog_osd_dir_get(env, ctxt);
		if (IS_ERR(llog_dir))
			GOTO(out_trans, rc = PTR_ERR(llog_dir));

		name = loghandle->lgh_name;
		rc = dt_declare_delete(env, llog_dir,
				       (struct dt_key *)name, th);
		if (rc)
			GOTO(out_trans, rc);
	}

	dt_declare_ref_del(env, o, th);

	rc = dt_declare_destroy(env, o, th);
	if (rc)
		GOTO(out_trans, rc);

	rc = dt_trans_start_local(env, d, th);
	if (rc)
		GOTO(out_trans, rc);

	dt_write_lock(env, o, 0);
	if (dt_object_exists(o)) {
		if (name) {
			dt_read_lock(env, llog_dir, 0);
			rc = dt_delete(env, llog_dir,
				       (struct dt_key *) name,
				       th, BYPASS_CAPA);
			dt_read_unlock(env, llog_dir);
			if (rc) {
				CERROR("%s: can't remove llog %s: rc = %d\n",
				       o->do_lu.lo_dev->ld_obd->obd_name,
				       name, rc);
				GOTO(out_unlock, rc);
			}
		}
		dt_ref_del(env, o, th);
		rc = dt_destroy(env, o, th);
		if (rc)
			GOTO(out_unlock, rc);
	}
out_unlock:
	dt_write_unlock(env, o);
out_trans:
	dt_trans_stop(env, d, th);
	if (llog_dir != NULL)
		lu_object_put(env, &llog_dir->do_lu);
	RETURN(rc);
}
Ejemplo n.º 17
0
/*
 * Update a record in a quota index file.
 *
 * \param env - is the environment passed by the caller
 * \param th  - is the transaction to use for disk writes
 * \param obj - is the on-disk index to be updated.
 * \param id  - is the key to be updated
 * \param rec - is the input record containing the new quota settings.
 * \param flags - can be LQUOTA_BUMP_VER or LQUOTA_SET_VER.
 * \param ver   - is the new version of the index if LQUOTA_SET_VER is set or is
 *                used to return the new version of the index when
 *                LQUOTA_BUMP_VER is set.
 *
 * \retval    - 0 on success, appropriate error on failure
 */
int lquota_disk_write(const struct lu_env *env, struct thandle *th,
		      struct dt_object *obj, union lquota_id *id,
		      struct dt_rec *rec, __u32 flags, __u64 *ver)
{
	struct lquota_thread_info	*qti = lquota_info(env);
	struct dt_key			*key = (struct dt_key *)&id->qid_uid;
	int				 rc;
	ENTRY;

	LASSERT(dt_object_exists(obj));
	LASSERT(obj->do_index_ops != NULL);

	/* lock index */
	dt_write_lock(env, obj, 0);

	/* check whether there is already an existing record for this ID */
	rc = dt_lookup(env, obj, (struct dt_rec *)&qti->qti_rec, key,
		       BYPASS_CAPA);
	if (rc == 0) {
		/* delete existing record in order to replace it */
		rc = dt_delete(env, obj, key, th, BYPASS_CAPA);
		if (rc)
			GOTO(out, rc);
	} else if (rc == -ENOENT) {
		/* probably first insert */
		rc = 0;
	} else {
		GOTO(out, rc);
	}

	if (rec != NULL) {
		/* insert record with updated quota settings */
		rc = dt_insert(env, obj, rec, key, th, BYPASS_CAPA, 1);
		if (rc) {
			/* try to insert the old one */
			rc = dt_insert(env, obj, (struct dt_rec *)&qti->qti_rec,
				       key, th, BYPASS_CAPA, 1);
			LASSERTF(rc == 0, "failed to insert record in quota "
			         "index "DFID,
				 PFID(lu_object_fid(&obj->do_lu)));
			GOTO(out, rc);
		}
	}

	if (flags != 0) {
		LASSERT(ver);
		if (flags & LQUOTA_BUMP_VER) {
			/* caller wants to bump the version, let's first read
			 * it */
			*ver = dt_version_get(env, obj);
			(*ver)++;
		} else {
			LASSERT(flags & LQUOTA_SET_VER);
		}
		dt_version_set(env, obj, *ver, th);
	}

	EXIT;
out:
	dt_write_unlock(env, obj);
	return rc;
}