Example #1
0
int orph_declare_index_delete(const struct lu_env *env,
                              struct mdd_object *obj,

                              struct thandle *th)
{
        struct mdd_device *mdd = mdo2mdd(&obj->mod_obj);
	struct dt_key	  *key;
        int                rc;

	key = orph_key_fill(env, mdo2fid(obj), ORPH_OP_UNLINK);

	rc = dt_declare_delete(env, mdd->mdd_orphans, key, th);
        if (rc)
                return rc;

        rc = mdo_declare_ref_del(env, obj, th);
        if (rc)
                return rc;

        if (S_ISDIR(mdd_object_type(obj))) {
                rc = mdo_declare_ref_del(env, obj, th);
                if (rc)
                        return rc;

                rc = dt_declare_ref_del(env, mdd->mdd_orphans, th);
        }

        return rc;
}
Example #2
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;
}
Example #3
0
/*
 * Reserve enough credits to 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 where quota settings are stored.
 * \param id  - is the key to be updated
 *
 * \retval    - 0 on success, appropriate error on failure
 */
int lquota_disk_declare_write(const struct lu_env *env, struct thandle *th,
			      struct dt_object *obj, union lquota_id *id)
{
	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);

	/* speculative delete declaration in case there is already an existing
	 * record in the index */
	rc = dt_declare_delete(env, obj, key, th);
	if (rc)
		RETURN(rc);

	/* declare insertion of updated record */
	rc = dt_declare_insert(env, obj, (struct dt_rec *)&qti->qti_rec, key,
			       th);
	if (rc)
		RETURN(rc);

	/* we might have to update the version of the global index too */
	rc = dt_declare_version_set(env, obj, th);

	RETURN(rc);
}
Example #4
0
int mdd_orphan_declare_delete(const struct lu_env *env, struct mdd_object *obj,
			      struct thandle *th)
{
	struct mdd_device *mdd = mdo2mdd(&obj->mod_obj);
	struct dt_key *key;
	int rc;

	key = mdd_orphan_key_fill(env, mdo2fid(obj));

	rc = dt_declare_delete(env, mdd->mdd_orphans, key, th);
	if (rc)
		return rc;

	if (!mdd_object_exists(obj))
		return -ENOENT;

        rc = mdo_declare_ref_del(env, obj, th);
        if (rc)
                return rc;

        if (S_ISDIR(mdd_object_type(obj))) {
                rc = mdo_declare_ref_del(env, obj, th);
                if (rc)
                        return rc;

                rc = dt_declare_ref_del(env, mdd->mdd_orphans, th);
        }

        return rc;
}
Example #5
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;
}
Example #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);
}
Example #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);
}
Example #8
0
int fld_declare_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	*tmp;
	struct lu_seq_range	*range;
	struct fld_thread_info	*info;
	int			rc = 0;

	ENTRY;

	info = lu_context_key_get(&env->le_ctx, &fld_thread_key);
	range = &info->fti_lrange;
	tmp = &info->fti_irange;
	memset(range, 0, sizeof(*range));

	rc = fld_index_lookup(env, fld, new_range->lsr_start, range);
	if (rc == 0) {
		/* In case of duplicate entry, the location must be same */
		LASSERT((range_compare_loc(new_range, range) == 0));
		GOTO(out, rc = -EEXIST);
	}

	if (rc != -ENOENT) {
		CERROR("%s: lookup range "DRANGE" error: rc = %d\n",
			fld->lsf_name, PRANGE(range), rc);
		GOTO(out, rc);
	}

	/* Check for merge case, since the fld entry can only be increamental,
	 * so we will only check whether it can be merged from the left. */
	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_declare_delete(env, fld->lsf_obj,
				       (struct dt_key *)&tmp->lsr_start, th);
		if (rc) {
			CERROR("%s: declare record "DRANGE" failed: rc = %d\n",
			       fld->lsf_name, PRANGE(range), rc);
			GOTO(out, rc);
		}
		memcpy(tmp, new_range, sizeof(*new_range));
		tmp->lsr_start = range->lsr_start;
	} else {
		memcpy(tmp, new_range, sizeof(*new_range));
	}

	range_cpu_to_be(tmp, tmp);
	rc = dt_declare_insert(env, fld->lsf_obj, (struct dt_rec *)tmp,
			       (struct dt_key *)&tmp->lsr_start, th);
out:
	RETURN(rc);
}
Example #9
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);
}
Example #10
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);
}
Example #11
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;
}