Esempio n. 1
0
int lfsck_bookmark_setup(const struct lu_env *env,
			 struct lfsck_instance *lfsck)
{
	struct dt_object *root;
	struct dt_object *obj;
	int		  rc;
	ENTRY;

	root = dt_locate(env, lfsck->li_bottom, &lfsck->li_local_root_fid);
	if (IS_ERR(root))
		RETURN(PTR_ERR(root));

	if (unlikely(!dt_try_as_dir(env, root))) {
		lu_object_put(env, &root->do_lu);

		RETURN(-ENOTDIR);
	}

	obj = local_file_find_or_create(env, lfsck->li_los, root,
					lfsck_bookmark_name,
					S_IFREG | S_IRUGO | S_IWUSR);
	lu_object_put(env, &root->do_lu);
	if (IS_ERR(obj))
		RETURN(PTR_ERR(obj));

	lfsck->li_bookmark_obj = obj;
	rc = lfsck_bookmark_load(env, lfsck);
	if (rc == -ENODATA)
		rc = lfsck_bookmark_init(env, lfsck);

	RETURN(rc);
}
Esempio n. 2
0
/**
 * Find the osd object for given fid.
 *
 * \param fid need to find the osd object having this fid
 *
 * \retval osd_object on success
 * \retval        -ve on error
 */
struct osd_object *osd_object_find(const struct lu_env *env,
				   struct dt_object *dt,
				   const struct lu_fid *fid)
{
	struct lu_device         *ludev = dt->do_lu.lo_dev;
	struct osd_object        *child = NULL;
	struct lu_object         *luch;
	struct lu_object         *lo;

	/*
	 * at this point topdev might not exist yet
	 * (i.e. MGS is preparing profiles). so we can
	 * not rely on topdev and instead lookup with
	 * our device passed as topdev. this can't work
	 * if the object isn't cached yet (as osd doesn't
	 * allocate lu_header). IOW, the object must be
	 * in the cache, otherwise lu_object_alloc() crashes
	 * -bzzz
	 */
	luch = lu_object_find_at(env, ludev, fid, NULL);
	if (IS_ERR(luch))
		return (void *)luch;

	if (lu_object_exists(luch)) {
		lo = lu_object_locate(luch->lo_header, ludev->ld_type);
		if (lo != NULL)
			child = osd_obj(lo);
		else
			LU_OBJECT_DEBUG(D_ERROR, env, luch,
					"%s: object can't be located "DFID"\n",
					osd_dev(ludev)->od_svname, PFID(fid));

		if (child == NULL) {
			lu_object_put(env, luch);
			CERROR("%s: Unable to get osd_object "DFID"\n",
			       osd_dev(ludev)->od_svname, PFID(fid));
			child = ERR_PTR(-ENOENT);
		}
	} else {
		LU_OBJECT_DEBUG(D_ERROR, env, luch,
				"%s: lu_object does not exists "DFID"\n",
				osd_dev(ludev)->od_svname, PFID(fid));
		lu_object_put(env, luch);
		child = ERR_PTR(-ENOENT);
	}

	return child;
}
Esempio n. 3
0
int mdd_local_file_create(const struct lu_env *env, struct mdd_device *mdd,
			  const struct lu_fid *pfid, const char *name, __u32 mode,
			  struct lu_fid *fid)
{
	struct dt_object	*parent, *dto;
	int			 rc;

	ENTRY;

	LASSERT(!fid_is_zero(pfid));
	parent = dt_locate(env, mdd->mdd_bottom, pfid);
	if (unlikely(IS_ERR(parent)))
		RETURN(PTR_ERR(parent));

	/* create local file/dir, if @fid is passed then try to use it */
	if (fid_is_zero(fid))
		dto = local_file_find_or_create(env, mdd->mdd_los, parent,
						name, mode);
	else
		dto = local_file_find_or_create_with_fid(env, mdd->mdd_bottom,
							 fid, parent, name,
							 mode);
	if (IS_ERR(dto))
		GOTO(out_put, rc = PTR_ERR(dto));
	*fid = *lu_object_fid(&dto->do_lu);
	/* since stack is not fully set up the local_storage uses own stack
	 * and we should drop its object from cache */
	lu_object_put_nocache(env, &dto->do_lu);
	EXIT;
out_put:
	lu_object_put(env, &parent->do_lu);
	return 0;
}
Esempio n. 4
0
/**
 * open the PENDING directory for device \a mdd
 *
 * The PENDING directory persistently tracks files and directories that were
 * unlinked from the namespace (nlink == 0) but are still held open by clients.
 * Those inodes shouldn't be deleted if the MDS crashes, because the clients
 * would not be able to recover and reopen those files.  Instead, these inodes
 * are linked into the PENDING directory on disk, and only deleted if all
 * clients close them, or the MDS finishes client recovery without any client
 * reopening them (i.e. former clients didn't join recovery).
 *  \param d   mdd device being started.
 *
 *  \retval 0  success
 *  \retval  -ve index operation error.
 *
 */
int orph_index_init(const struct lu_env *env, struct mdd_device *mdd)
{
	struct lu_fid		 fid;
	struct dt_object	*d;
	int			 rc = 0;

	ENTRY;

	/* create PENDING dir */
	fid_zero(&fid);
	rc = mdd_local_file_create(env, mdd, &mdd->mdd_local_root_fid,
				   orph_index_name, S_IFDIR | S_IRUGO |
				   S_IWUSR | S_IXUGO, &fid);
	if (rc < 0)
		RETURN(rc);

	d = dt_locate(env, mdd->mdd_child, &fid);
	if (IS_ERR(d))
		RETURN(PTR_ERR(d));
	LASSERT(lu_object_exists(&d->do_lu));
	if (!dt_try_as_dir(env, d)) {
		CERROR("%s: \"%s\" is not an index: rc = %d\n",
		       mdd2obd_dev(mdd)->obd_name, orph_index_name, rc);
		lu_object_put(env, &d->do_lu);
		RETURN(-ENOTDIR);
	}
	mdd->mdd_orphans = d;
	RETURN(0);
}
Esempio n. 5
0
/*
 * Called when the MDS is fully configured. We use it to set up local objects
 * associated with the quota master target.
 *
 * \param env - is the environment passed by the caller
 * \param parent - is the lu_device of the parent, that's to say the mdt
 * \param ld  - is the lu_device associated with the master target
 *
 * \retval    - 0 on success, appropriate error on failure
 */
static int qmt_device_prepare(const struct lu_env *env,
			      struct lu_device *parent,
			      struct lu_device *ld)
{
	struct qmt_device	*qmt = lu2qmt_dev(ld);
	struct dt_object	*qmt_root;
	int			 rc;
	ENTRY;

	/* initialize quota master root directory where all index files will be
	 * stored */
	qmt_root = lquota_disk_dir_find_create(env, qmt->qmt_child, NULL,
					       QMT_DIR);
	if (IS_ERR(qmt_root)) {
		rc = PTR_ERR(qmt_root);
		CERROR("%s: failed to create master quota directory (%d)\n",
		       qmt->qmt_svname, rc);
		RETURN(rc);
	}

	/* initialize on-disk indexes associated with each pool */
	rc = qmt_pool_prepare(env, qmt, qmt_root);

	lu_object_put(env, &qmt_root->do_lu);
	RETURN(rc);
}
Esempio n. 6
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;
}
Esempio n. 7
0
static int out_trans_stop(const struct lu_env *env,
			  struct thandle_exec_args *ta, int err)
{
	int i;
	int rc;

	ta->ta_handle->th_result = err;
	rc = dt_trans_stop(env, ta->ta_handle->th_dev, ta->ta_handle);
	for (i = 0; i < ta->ta_argno; i++) {
		if (ta->ta_args[i]->object != NULL) {
			struct dt_object *obj = ta->ta_args[i]->object;

			/* If the object is being created during this
			 * transaction, we need to remove them from the
			 * cache immediately, because a few layers are
			 * missing in OUT handler, i.e. the object might
			 * not be initialized in all layers */
			if (ta->ta_args[i]->exec_fn == out_tx_create_exec)
				set_bit(LU_OBJECT_HEARD_BANSHEE,
					&obj->do_lu.lo_header->loh_flags);
			lu_object_put(env, &ta->ta_args[i]->object->do_lu);
			ta->ta_args[i]->object = NULL;
		}
	}
	ta->ta_handle = NULL;
	ta->ta_argno = 0;

	return rc;
}
Esempio n. 8
0
/**
 * Write the special file which contains the list of llog catalogs IDs
 *
 * This function writes the CATALOG file which contains the array of llog
 * catalogs IDs. It is used mostly to store OSP llogs indexed by OST/MDT
 * number.
 *
 * \param[in]  env	execution environment
 * \param[in]  d	corresponding storage device
 * \param[in]  idx	position to start from, usually OST/MDT index
 * \param[in]  count	how many catalog IDs to write
 * \param[out] idarray	the buffer with the data to write.
 * \param[in]  fid	LLOG_CATALOGS_OID for CATALOG object
 *
 * \retval		0 on successful write of catalog IDs
 * \retval		negative value on error
 */
int llog_osd_put_cat_list(const struct lu_env *env, struct dt_device *d,
			  int idx, int count, struct llog_catid *idarray,
			  const struct lu_fid *fid)
{
	struct llog_thread_info	*lgi = llog_info(env);
	struct dt_object	*o = NULL;
	struct thandle		*th;
	int			 rc, size;

	if (count == 0)
		RETURN(0);

	LASSERT(d);

	size = sizeof(*idarray) * count;
	lgi->lgi_off = idx * sizeof(*idarray);
	lgi->lgi_fid = *fid;

	o = dt_locate(env, d, &lgi->lgi_fid);
	if (IS_ERR(o))
		RETURN(PTR_ERR(o));

	if (!dt_object_exists(o))
		GOTO(out, rc = -ENOENT);

	rc = dt_attr_get(env, o, &lgi->lgi_attr, BYPASS_CAPA);
	if (rc)
		GOTO(out, rc);

	if (!S_ISREG(lgi->lgi_attr.la_mode)) {
		CERROR("%s: CATALOGS is not a regular file!: mode = %o\n",
		       o->do_lu.lo_dev->ld_obd->obd_name,
		       lgi->lgi_attr.la_mode);
		GOTO(out, rc = -ENOENT);
	}

	th = dt_trans_create(env, d);
	if (IS_ERR(th))
		GOTO(out, rc = PTR_ERR(th));

	lgi->lgi_buf.lb_len = size;
	lgi->lgi_buf.lb_buf = idarray;
	rc = dt_declare_record_write(env, o, &lgi->lgi_buf, lgi->lgi_off, th);
	if (rc)
		GOTO(out, rc);

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

	rc = dt_record_write(env, o, &lgi->lgi_buf, &lgi->lgi_off, th);
	if (rc)
		CDEBUG(D_INODE, "can't write CATALOGS at index %d: rc = %d\n",
		       idx, rc);
out_trans:
	dt_trans_stop(env, d, th);
out:
	lu_object_put(env, &o->do_lu);
	RETURN(rc);
}
Esempio n. 9
0
/**
 * Free given iterator.
 *
 * \param  di   - osd iterator
 */
static void osd_it_acct_fini(const struct lu_env *env, struct dt_it *di)
{
	struct osd_it_quota *it = (struct osd_it_quota *)di;
	ENTRY;
	udmu_zap_cursor_fini(it->oiq_zc);
	lu_object_put(env, &it->oiq_obj->oo_dt.do_lu);
	EXIT;
}
Esempio n. 10
0
void orph_index_fini(const struct lu_env *env, struct mdd_device *mdd)
{
        ENTRY;
        if (mdd->mdd_orphans != NULL) {
                lu_object_put(env, &mdd->mdd_orphans->do_lu);
                mdd->mdd_orphans = NULL;
        }
        EXIT;
}
Esempio n. 11
0
void fld_index_fini(const struct lu_env *env, struct lu_server_fld *fld)
{
	ENTRY;
	if (fld->lsf_obj != NULL) {
		if (!IS_ERR(fld->lsf_obj))
			lu_object_put(env, &fld->lsf_obj->do_lu);
		fld->lsf_obj = NULL;
	}
	EXIT;
}
Esempio n. 12
0
/**
 * Implementation of the llog_operations::lop_create
 *
 * This function creates the llog according with llog_handle::lgh_obj
 * and llog_handle::lgh_name.
 *
 * \param[in] env	execution environment
 * \param[in] res	llog handle of the current llog
 * \param[in] th	current transaction handle
 *
 * \retval		0 on successful create
 * \retval		negative value on error
 */
static int llog_osd_create(const struct lu_env *env, struct llog_handle *res,
			   struct thandle *th)
{
	struct llog_thread_info *lgi = llog_info(env);
	struct dt_insert_rec	*rec = &lgi->lgi_dt_rec;
	struct local_oid_storage *los;
	struct dt_object        *o;
	int                      rc = 0;

	ENTRY;

	LASSERT(env);
	o = res->lgh_obj;
	LASSERT(o);

	/* llog can be already created */
	if (dt_object_exists(o))
		RETURN(-EEXIST);

	los = res->private_data;
	LASSERT(los);

	dt_write_lock(env, o, 0);
	if (!dt_object_exists(o))
		rc = llog_osd_create_new_object(env, los, o, th);
	else
		rc = -EEXIST;

	dt_write_unlock(env, o);
	if (rc)
		RETURN(rc);

	if (res->lgh_name) {
		struct dt_object *llog_dir;

		llog_dir = llog_osd_dir_get(env, res->lgh_ctxt);
		if (IS_ERR(llog_dir))
			RETURN(PTR_ERR(llog_dir));

		logid_to_fid(&res->lgh_id, &lgi->lgi_fid);
		rec->rec_fid = &lgi->lgi_fid;
		rec->rec_type = S_IFREG;
		dt_read_lock(env, llog_dir, 0);
		rc = dt_insert(env, llog_dir, (struct dt_rec *)rec,
			       (struct dt_key *)res->lgh_name,
			       th, BYPASS_CAPA, 1);
		dt_read_unlock(env, llog_dir);
		lu_object_put(env, &llog_dir->do_lu);
		if (rc)
			CERROR("%s: can't create named llog %s: rc = %d\n",
			       o->do_lu.lo_dev->ld_obd->obd_name,
			       res->lgh_name, rc);
	}
	RETURN(rc);
}
Esempio n. 13
0
void seq_store_fini(struct lu_server_seq *seq,
                    const struct lu_env *env)
{
        ENTRY;

        if (seq->lss_obj != NULL) {
                if (!IS_ERR(seq->lss_obj))
                        lu_object_put(env, &seq->lss_obj->do_lu);
                seq->lss_obj = NULL;
        }

        EXIT;
}
Esempio n. 14
0
/**
 * Initialize slave index object to collect local quota limit for user or group.
 *
 * \param env - is the environment passed by the caller
 * \param dev - is the dt_device storing the slave index object
 * \param type - is the quota type, either USRQUOTA or GRPQUOTA
 */
static struct dt_object *quota_obj_lookup(const struct lu_env *env,
					  struct dt_device *dev, int type)
{
	struct lquota_thread_info	*qti = lquota_info(env);
	struct dt_object		*obj = NULL;
	ENTRY;

	qti->qti_fid.f_seq = FID_SEQ_QUOTA;
	qti->qti_fid.f_oid = type == USRQUOTA ? LQUOTA_USR_OID : LQUOTA_GRP_OID;
	qti->qti_fid.f_ver = 0;

	/* lookup the quota object */
	obj = dt_locate(env, dev, &qti->qti_fid);
	if (IS_ERR(obj))
		RETURN(obj);

	if (!dt_object_exists(obj)) {
		lu_object_put(env, &obj->do_lu);
		RETURN(ERR_PTR(-ENOENT));
	}

	if (obj->do_index_ops == NULL) {
		int rc;

		/* set up indexing operations */
		rc = obj->do_ops->do_index_try(env, obj,
					       &dt_quota_slv_features);
		if (rc) {
			CERROR("%s: failed to set up indexing operations for %s"
			       " slave index object rc:%d\n",
			       dev->dd_lu_dev.ld_obd->obd_name,
			       QTYPE_NAME(type), rc);
			lu_object_put(env, &obj->do_lu);
			RETURN(ERR_PTR(rc));
		}
	}
	RETURN(obj);
}
Esempio n. 15
0
/**
 * Implementation of the llog_operations::lop_declare_create
 *
 * This function declares the llog create. It declares also name insert
 * into llog directory in case of named llog.
 *
 * \param[in] env	execution environment
 * \param[in] res	llog handle of the current llog
 * \param[in] th	current transaction handle
 *
 * \retval		0 on successful create declaration
 * \retval		negative value on error
 */
static int llog_osd_declare_create(const struct lu_env *env,
				   struct llog_handle *res, struct thandle *th)
{
	struct llog_thread_info		*lgi = llog_info(env);
	struct dt_insert_rec		*rec = &lgi->lgi_dt_rec;
	struct local_oid_storage	*los;
	struct dt_object		*o;
	int				 rc;

	ENTRY;

	LASSERT(res->lgh_obj);
	LASSERT(th);

	/* object can be created by another thread */
	o = res->lgh_obj;
	if (dt_object_exists(o))
		RETURN(0);

	los = res->private_data;
	LASSERT(los);

	rc = llog_osd_declare_new_object(env, los, o, th);
	if (rc)
		RETURN(rc);

	/* do not declare header initialization here as it's declared
	 * in llog_osd_declare_write_rec() which is always called */

	if (res->lgh_name) {
		struct dt_object *llog_dir;

		llog_dir = llog_osd_dir_get(env, res->lgh_ctxt);
		if (IS_ERR(llog_dir))
			RETURN(PTR_ERR(llog_dir));
		logid_to_fid(&res->lgh_id, &lgi->lgi_fid);
		rec->rec_fid = &lgi->lgi_fid;
		rec->rec_type = S_IFREG;
		rc = dt_declare_insert(env, llog_dir,
				       (struct dt_rec *)rec,
				       (struct dt_key *)res->lgh_name, th);
		lu_object_put(env, &llog_dir->do_lu);
		if (rc)
			CERROR("%s: can't declare named llog %s: rc = %d\n",
			       o->do_lu.lo_dev->ld_obd->obd_name,
			       res->lgh_name, rc);
	}
	RETURN(rc);
}
Esempio n. 16
0
/**
 * Look-up accounting object to collect space usage information for user
 * or group.
 *
 * \param env  - is the environment passed by the caller
 * \param dev  - is the dt_device storing the accounting object
 * \param type - is the quota type, either USRQUOTA or GRPQUOTA
 */
struct dt_object *acct_obj_lookup(const struct lu_env *env,
				  struct dt_device *dev, int type)
{
	struct lquota_thread_info	*qti = lquota_info(env);
	struct dt_object		*obj = NULL;
	ENTRY;

	lu_local_obj_fid(&qti->qti_fid,
			 type == USRQUOTA ? ACCT_USER_OID : ACCT_GROUP_OID);

	/* lookup the accounting object */
	obj = dt_locate(env, dev, &qti->qti_fid);
	if (IS_ERR(obj))
		RETURN(obj);

	if (!dt_object_exists(obj)) {
		lu_object_put(env, &obj->do_lu);
		RETURN(ERR_PTR(-ENOENT));
	}

	if (obj->do_index_ops == NULL) {
		int rc;

		/* set up indexing operations */
		rc = obj->do_ops->do_index_try(env, obj, &dt_acct_features);
		if (rc) {
			CERROR("%s: failed to set up indexing operations for %s"
			       " acct object rc:%d\n",
			       dev->dd_lu_dev.ld_obd->obd_name,
			       QTYPE_NAME(type), rc);
			lu_object_put(env, &obj->do_lu);
			RETURN(ERR_PTR(rc));
		}
	}
	RETURN(obj);
}
Esempio n. 17
0
/**
 * Free given iterator.
 *
 * \param  di   - osd iterator
 */
static void osd_it_acct_fini(const struct lu_env *env, struct dt_it *di)
{
	struct osd_thread_info	*info	= osd_oti_get(env);
	struct osd_it_quota	*it	= (struct osd_it_quota *)di;
	ENTRY;

	osd_zap_cursor_fini(it->oiq_zc);
	lu_object_put(env, &it->oiq_obj->oo_dt.do_lu);
	if (it != &info->oti_it_quota)
		OBD_FREE_PTR(it);
	else
		info->oti_it_inline = 0;

	EXIT;
}
Esempio n. 18
0
static int llog_osd_declare_create(const struct lu_env *env,
				   struct llog_handle *res, struct thandle *th)
{
	struct llog_thread_info		*lgi = llog_info(env);
	struct local_oid_storage	*los;
	struct dt_object		*o;
	int				 rc;

	ENTRY;

	LASSERT(res->lgh_obj);
	LASSERT(th);

	/* object can be created by another thread */
	o = res->lgh_obj;
	if (dt_object_exists(o))
		RETURN(0);

	los = res->private_data;
	LASSERT(los);

	rc = llog_osd_declare_new_object(env, los, o, th);
	if (rc)
		RETURN(rc);

	rc = dt_declare_record_write(env, o, LLOG_CHUNK_SIZE, 0, th);
	if (rc)
		RETURN(rc);

	if (res->lgh_name) {
		struct dt_object *llog_dir;

		llog_dir = llog_osd_dir_get(env, res->lgh_ctxt);
		if (IS_ERR(llog_dir))
			RETURN(PTR_ERR(llog_dir));
		dt_declare_ref_add(env, o, th);
		logid_to_fid(&res->lgh_id, &lgi->lgi_fid);
		rc = dt_declare_insert(env, llog_dir,
				       (struct dt_rec *)&lgi->lgi_fid,
				       (struct dt_key *)res->lgh_name, th);
		lu_object_put(env, &llog_dir->do_lu);
		if (rc)
			CERROR("%s: can't declare named llog %s: rc = %d\n",
			       o->do_lu.lo_dev->ld_obd->obd_name,
			       res->lgh_name, rc);
	}
	RETURN(rc);
}
Esempio n. 19
0
static void osd_index_it_fini(const struct lu_env *env, struct dt_it *di)
{
	struct osd_zap_it *it = (struct osd_zap_it *)di;
	struct osd_object *obj;
	ENTRY;

	LASSERT(it);
	LASSERT(it->ozi_obj);

	obj = it->ozi_obj;

	udmu_zap_cursor_fini(it->ozi_zc);
	lu_object_put(env, &obj->oo_dt.do_lu);

	EXIT;
}
Esempio n. 20
0
/*
 * Look-up a slave index file.
 *
 * \param env - is the environment passed by the caller
 * \param dev - is the backend dt_device where to look-up/create the slave index
 * \param parent - is the parent directory where to lookup the slave index
 * \param glb_fid - is the fid of the global index file associated with this
 *                  slave index.
 * \param uuid    - is the uuid of slave which is (re)connecting to the master
 *                  target
 *
 * \retval     - pointer to the dt_object of the slave index on success,
 *               appropriate error on failure
 */
struct dt_object *lquota_disk_slv_find(const struct lu_env *env,
				       struct dt_device *dev,
				       struct dt_object *parent,
				       const struct lu_fid *glb_fid,
				       struct obd_uuid *uuid)
{
	struct lquota_thread_info	*qti = lquota_info(env);
	struct dt_object		*slv_idx;
	int				 rc;
	ENTRY;

	LASSERT(uuid != NULL);

	CDEBUG(D_QUOTA, "lookup slave index file for %s\n",
	       obd_uuid2str(uuid));

	/* generate filename associated with the slave */
	rc = lquota_disk_slv_filename(glb_fid, uuid, qti->qti_buf);
	if (rc)
		RETURN(ERR_PTR(rc));

	/* lookup slave index file */
	rc = dt_lookup_dir(env, parent, qti->qti_buf, &qti->qti_fid);
	if (rc)
                RETURN(ERR_PTR(rc));

	/* name is found, get the object */
	slv_idx = dt_locate(env, dev, &qti->qti_fid);
	if (IS_ERR(slv_idx))
		RETURN(slv_idx);

	if (slv_idx->do_index_ops == NULL) {
		rc = slv_idx->do_ops->do_index_try(env, slv_idx,
						   &dt_quota_slv_features);
		if (rc) {
			CERROR("%s: failed to setup slave index operations for "
			       "%s, rc:%d\n", dev->dd_lu_dev.ld_obd->obd_name,
			       obd_uuid2str(uuid), rc);
			lu_object_put(env, &slv_idx->do_lu);
			slv_idx = ERR_PTR(rc);
		}
	}

	RETURN(slv_idx);
}
Esempio n. 21
0
static int llog_osd_close(const struct lu_env *env, struct llog_handle *handle)
{
	struct local_oid_storage	*los;
	int				 rc = 0;

	LASSERT(handle->lgh_obj);

	lu_object_put(env, &handle->lgh_obj->do_lu);

	los = handle->private_data;
	LASSERT(los);
	dt_los_put(los);

	if (handle->lgh_name)
		OBD_FREE(handle->lgh_name, strlen(handle->lgh_name) + 1);

	return rc;
}
Esempio n. 22
0
static int out_trans_stop(const struct lu_env *env,
			  struct thandle_exec_args *ta, int err)
{
	int i;
	int rc;

	ta->ta_handle->th_result = err;
	LASSERT(ta->ta_handle->th_sync != 0);
	rc = dt_trans_stop(env, ta->ta_dev, ta->ta_handle);
	for (i = 0; i < ta->ta_argno; i++) {
		if (ta->ta_args[i].object != NULL) {
			lu_object_put(env, &ta->ta_args[i].object->do_lu);
			ta->ta_args[i].object = NULL;
		}
	}

	return rc;
}
Esempio n. 23
0
static struct dt_object *out_object_find(struct mdt_thread_info *info,
					 struct lu_fid *fid)
{
	struct lu_object	*obj;
	struct dt_object	*dt_obj;

	obj = lu_object_find(info->mti_env,
			     &info->mti_mdt->mdt_md_dev.md_lu_dev,
			     fid, NULL);
	if (IS_ERR(obj))
		return (struct dt_object *)obj;

	dt_obj = out_get_dt_obj(obj);
	if (IS_ERR(dt_obj)) {
		lu_object_put(info->mti_env, obj);
		return ERR_PTR(-ENOENT);
	}

	return dt_obj;
}
Esempio n. 24
0
int fld_index_init(struct lu_server_fld *fld,
                   const struct lu_env *env,
                   struct dt_device *dt)
{
        struct dt_object *dt_obj;
        struct lu_fid fid;
        int rc;
        ENTRY;

        dt_obj = dt_store_open(env, dt, "", fld_index_name, &fid);
        if (!IS_ERR(dt_obj)) {
                fld->lsf_obj = dt_obj;
                rc = dt_obj->do_ops->do_index_try(env, dt_obj,
                                                  &fld_index_features);
                if (rc == 0) {
                        LASSERT(dt_obj->do_index_ops != NULL);
                        rc = fld_insert_igif_fld(fld, env);

                        if (rc != 0) {
                                CERROR("insert igif in fld! = %d\n", rc);
                                lu_object_put(env, &dt_obj->do_lu);
                                fld->lsf_obj = NULL;
                        }
                } else
                        CERROR("%s: File \"%s\" is not an index!\n",
                               fld->lsf_name, fld_index_name);


        } else {
                CERROR("%s: Can't find \"%s\" obj %d\n",
                       fld->lsf_name, fld_index_name, (int)PTR_ERR(dt_obj));
                rc = PTR_ERR(dt_obj);
        }

        RETURN(rc);
}
Esempio n. 25
0
/*
 * Release a qsd_instance. Companion of qsd_init(). This releases all data
 * structures associated with the quota slave (on-disk objects, lquota entry
 * tables, ...).
 * This function should be called when the OSD is shutting down.
 *
 * \param env - is the environment passed by the caller
 * \param qsd - is the qsd instance to shutdown
 */
void qsd_fini(const struct lu_env *env, struct qsd_instance *qsd)
{
	int	qtype;
	ENTRY;

	if (unlikely(qsd == NULL))
		RETURN_EXIT;

	CDEBUG(D_QUOTA, "%s: initiating QSD shutdown\n", qsd->qsd_svname);
	write_lock(&qsd->qsd_lock);
	qsd->qsd_stopping = true;
	write_unlock(&qsd->qsd_lock);

	/* remove qsd proc entry */
	if (qsd->qsd_proc != NULL) {
		lprocfs_remove(&qsd->qsd_proc);
		qsd->qsd_proc = NULL;
	}

	/* stop the writeback thread */
	qsd_stop_upd_thread(qsd);

	/* shutdown the reintegration threads */
	for (qtype = USRQUOTA; qtype < MAXQUOTAS; qtype++) {
		if (qsd->qsd_type_array[qtype] == NULL)
			continue;
		qsd_stop_reint_thread(qsd->qsd_type_array[qtype]);
	}

	if (qsd->qsd_ns != NULL) {
		qsd->qsd_ns = NULL;
	}

	/* free per-quota type data */
	for (qtype = USRQUOTA; qtype < MAXQUOTAS; qtype++)
		qsd_qtype_fini(env, qsd, qtype);

	/* deregister connection to the quota master */
	qsd->qsd_exp_valid = false;
	lustre_deregister_lwp_item(&qsd->qsd_exp);

	/* release per-filesystem information */
	if (qsd->qsd_fsinfo != NULL) {
		mutex_lock(&qsd->qsd_fsinfo->qfs_mutex);
		/* remove from the list of fsinfo */
		cfs_list_del_init(&qsd->qsd_link);
		mutex_unlock(&qsd->qsd_fsinfo->qfs_mutex);
		qsd_put_fsinfo(qsd->qsd_fsinfo);
		qsd->qsd_fsinfo = NULL;
	}

	/* release quota root directory */
	if (qsd->qsd_root != NULL) {
		lu_object_put(env, &qsd->qsd_root->do_lu);
		qsd->qsd_root = NULL;
	}

	/* release reference on dt_device */
	if (qsd->qsd_dev != NULL) {
		lu_ref_del(&qsd->qsd_dev->dd_lu_dev.ld_reference, "qsd", qsd);
		lu_device_put(&qsd->qsd_dev->dd_lu_dev);
		qsd->qsd_dev = NULL;
	}

	CDEBUG(D_QUOTA, "%s: QSD shutdown completed\n", qsd->qsd_svname);
	OBD_FREE_PTR(qsd);
	EXIT;
}
Esempio n. 26
0
/*
 * Release qsd_qtype_info structure which contains data associated with a
 * given quota type. This releases the accounting objects.
 * It's called on OSD cleanup when the qsd instance is released.
 *
 * \param env - is the environment passed by the caller
 * \param qsd - is the qsd instance managing the qsd_qtype_info structure
 *              to be released
 * \param qtype - is the quota type to be shutdown
 */
static void qsd_qtype_fini(const struct lu_env *env, struct qsd_instance *qsd,
			   int qtype)
{
	struct qsd_qtype_info	*qqi;
	int repeat = 0;
	ENTRY;

	if (qsd->qsd_type_array[qtype] == NULL)
		RETURN_EXIT;
	qqi = qsd->qsd_type_array[qtype];
	qsd->qsd_type_array[qtype] = NULL;

	/* all deferred work lists should be empty */
	LASSERT(cfs_list_empty(&qqi->qqi_deferred_glb));
	LASSERT(cfs_list_empty(&qqi->qqi_deferred_slv));

	/* shutdown lquota site */
	if (qqi->qqi_site != NULL && !IS_ERR(qqi->qqi_site)) {
		lquota_site_free(env, qqi->qqi_site);
		qqi->qqi_site = NULL;
	}

	/* The qqi may still be holding by global locks which are being
	 * canceled asynchronously (LU-4365), see the following steps:
	 *
	 * - On server umount, we try to clear all quota locks first by
	 *   disconnecting LWP (which will invalidate import and cleanup
	 *   all locks on it), however, if quota reint process is holding
	 *   the global lock for reintegration at that time, global lock
	 *   will fail to be cleared on LWP disconnection.
	 *
	 * - Umount process goes on and stops reint process, the global
	 *   lock will be dropped on reint process exit, however, the lock
	 *   cancel in done in asynchronous way, so the
	 *   qsd_glb_blocking_ast() might haven't been called yet when we
	 *   get here.
	 */
	while (atomic_read(&qqi->qqi_ref) > 1) {
		CDEBUG(D_QUOTA, "qqi reference count %u, repeat: %d\n",
		       atomic_read(&qqi->qqi_ref), repeat);
		repeat++;
		schedule_timeout_and_set_state(TASK_INTERRUPTIBLE,
						cfs_time_seconds(1));
	}

	/* by now, all qqi users should have gone away */
	LASSERT(atomic_read(&qqi->qqi_ref) == 1);
	lu_ref_fini(&qqi->qqi_reference);

	/* release accounting object */
	if (qqi->qqi_acct_obj != NULL && !IS_ERR(qqi->qqi_acct_obj)) {
		lu_object_put(env, &qqi->qqi_acct_obj->do_lu);
		qqi->qqi_acct_obj = NULL;
	}

	/* release slv index */
	if (qqi->qqi_slv_obj != NULL && !IS_ERR(qqi->qqi_slv_obj)) {
		lu_object_put(env, &qqi->qqi_slv_obj->do_lu);
		qqi->qqi_slv_obj = NULL;
		qqi->qqi_slv_ver = 0;
	}

	/* release global index */
	if (qqi->qqi_glb_obj != NULL && !IS_ERR(qqi->qqi_glb_obj)) {
		lu_object_put(env, &qqi->qqi_glb_obj->do_lu);
		qqi->qqi_glb_obj = NULL;
		qqi->qqi_glb_ver = 0;
	}

	OBD_FREE_PTR(qqi);
	EXIT;
}
Esempio n. 27
0
/**
 * Implementation of the llog_operations::lop_open
 *
 * This function opens the llog by its logid or by name, it may open also
 * non existent llog and assing then new id to it.
 * The llog_open/llog_close pair works similar to lu_object_find/put,
 * the object may not exist prior open. The result of open is just dt_object
 * in the llog header.
 *
 * \param[in] env		execution environment
 * \param[in] handle		llog handle of the current llog
 * \param[in] logid		logid of llog to open (nameless llog)
 * \param[in] name		name of llog to open (named llog)
 * \param[in] open_param
 *				LLOG_OPEN_NEW - new llog, may not exist
 *				LLOG_OPEN_EXIST - old llog, must exist
 *
 * \retval			0 on successful open, llog_handle::lgh_obj
 *				contains the dt_object of the llog.
 * \retval			negative value on error
 */
static int llog_osd_open(const struct lu_env *env, struct llog_handle *handle,
			 struct llog_logid *logid, char *name,
			 enum llog_open_param open_param)
{
	struct llog_thread_info		*lgi = llog_info(env);
	struct llog_ctxt		*ctxt = handle->lgh_ctxt;
	struct dt_object		*o;
	struct dt_device		*dt;
	struct ls_device		*ls;
	struct local_oid_storage	*los;
	int				 rc = 0;

	ENTRY;

	LASSERT(env);
	LASSERT(ctxt);
	LASSERT(ctxt->loc_exp);
	LASSERT(ctxt->loc_exp->exp_obd);
	dt = ctxt->loc_exp->exp_obd->obd_lvfs_ctxt.dt;
	LASSERT(dt);

	ls = ls_device_get(dt);
	if (IS_ERR(ls))
		RETURN(PTR_ERR(ls));

	mutex_lock(&ls->ls_los_mutex);
	los = dt_los_find(ls, name != NULL ? FID_SEQ_LLOG_NAME : FID_SEQ_LLOG);
	mutex_unlock(&ls->ls_los_mutex);
	LASSERT(los);
	ls_device_put(env, ls);

	LASSERT(handle);

	if (logid != NULL) {
		logid_to_fid(logid, &lgi->lgi_fid);
	} else if (name) {
		struct dt_object *llog_dir;

		llog_dir = llog_osd_dir_get(env, ctxt);
		if (IS_ERR(llog_dir))
			GOTO(out, rc = PTR_ERR(llog_dir));
		dt_read_lock(env, llog_dir, 0);
		rc = dt_lookup_dir(env, llog_dir, name, &lgi->lgi_fid);
		dt_read_unlock(env, llog_dir);
		lu_object_put(env, &llog_dir->do_lu);
		if (rc == -ENOENT && open_param == LLOG_OPEN_NEW) {
			/* generate fid for new llog */
			rc = local_object_fid_generate(env, los,
						       &lgi->lgi_fid);
		}
		if (rc < 0)
			GOTO(out, rc);
		OBD_ALLOC(handle->lgh_name, strlen(name) + 1);
		if (handle->lgh_name)
			strcpy(handle->lgh_name, name);
		else
			GOTO(out, rc = -ENOMEM);
	} else {
		LASSERTF(open_param & LLOG_OPEN_NEW, "%#x\n", open_param);
		/* generate fid for new llog */
		rc = local_object_fid_generate(env, los, &lgi->lgi_fid);
		if (rc < 0)
			GOTO(out, rc);
	}

	o = ls_locate(env, ls, &lgi->lgi_fid, NULL);
	if (IS_ERR(o))
		GOTO(out_name, rc = PTR_ERR(o));

	/* No new llog is expected but doesn't exist */
	if (open_param != LLOG_OPEN_NEW && !dt_object_exists(o))
		GOTO(out_put, rc = -ENOENT);

	fid_to_logid(&lgi->lgi_fid, &handle->lgh_id);
	handle->lgh_obj = o;
	handle->private_data = los;
	LASSERT(handle->lgh_ctxt);

	RETURN(rc);

out_put:
	lu_object_put(env, &o->do_lu);
out_name:
	if (handle->lgh_name != NULL)
		OBD_FREE(handle->lgh_name, strlen(name) + 1);
out:
	dt_los_put(los);
	RETURN(rc);
}
Esempio n. 28
0
/**
 * Read the special file which contains the list of llog catalogs IDs
 *
 * This function reads the CATALOGS file which contains the array of llog
 * catalogs IDs. The main purpose of this file is to store OSP llogs indexed
 * by OST/MDT number.
 *
 * \param[in]  env		execution environment
 * \param[in]  d		corresponding storage device
 * \param[in]  idx		position to start from, usually OST/MDT index
 * \param[in]  count		how many catalog IDs to read
 * \param[out] idarray		the buffer for the data. If it is NULL then
 *				function returns just number of catalog IDs
 *				in the file.
 * \param[in]  fid		LLOG_CATALOGS_OID for CATALOG object
 *
 * \retval			0 on successful read of catalog IDs
 * \retval			negative value on error
 * \retval			positive value which is number of records in
 *				the file if \a idarray is NULL
 */
int llog_osd_get_cat_list(const struct lu_env *env, struct dt_device *d,
			  int idx, int count, struct llog_catid *idarray,
			  const struct lu_fid *fid)
{
	struct llog_thread_info	*lgi = llog_info(env);
	struct dt_object	*o = NULL;
	struct thandle		*th;
	int			 rc, size;

	ENTRY;

	LASSERT(d);

	size = sizeof(*idarray) * count;
	lgi->lgi_off = idx *  sizeof(*idarray);

	lgi->lgi_fid = *fid;
	o = dt_locate(env, d, &lgi->lgi_fid);
	if (IS_ERR(o))
		RETURN(PTR_ERR(o));

	if (!dt_object_exists(o)) {
		th = dt_trans_create(env, d);
		if (IS_ERR(th))
			GOTO(out, rc = PTR_ERR(th));

		lgi->lgi_attr.la_valid = LA_MODE;
		lgi->lgi_attr.la_mode = S_IFREG | S_IRUGO | S_IWUSR;
		lgi->lgi_dof.dof_type = dt_mode_to_dft(S_IFREG);

		rc = dt_declare_create(env, o, &lgi->lgi_attr, NULL,
				       &lgi->lgi_dof, 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))
			rc = dt_create(env, o, &lgi->lgi_attr, NULL,
				       &lgi->lgi_dof, th);
		dt_write_unlock(env, o);
out_trans:
		dt_trans_stop(env, d, th);
		if (rc)
			GOTO(out, rc);
	}

	rc = dt_attr_get(env, o, &lgi->lgi_attr, BYPASS_CAPA);
	if (rc)
		GOTO(out, rc);

	if (!S_ISREG(lgi->lgi_attr.la_mode)) {
		CERROR("%s: CATALOGS is not a regular file!: mode = %o\n",
		       o->do_lu.lo_dev->ld_obd->obd_name,
		       lgi->lgi_attr.la_mode);
		GOTO(out, rc = -ENOENT);
	}

	CDEBUG(D_CONFIG, "cat list: disk size=%d, read=%d\n",
	       (int)lgi->lgi_attr.la_size, size);

	/* return just number of llogs */
	if (idarray == NULL) {
		rc = lgi->lgi_attr.la_size / sizeof(*idarray);
		GOTO(out, rc);
	}

	/* read for new ost index or for empty file */
	memset(idarray, 0, size);
	if (lgi->lgi_attr.la_size <= lgi->lgi_off)
		GOTO(out, rc = 0);
	if (lgi->lgi_attr.la_size < lgi->lgi_off + size)
		size = lgi->lgi_attr.la_size - lgi->lgi_off;

	lgi->lgi_buf.lb_buf = idarray;
	lgi->lgi_buf.lb_len = size;
	rc = dt_record_read(env, o, &lgi->lgi_buf, &lgi->lgi_off);
	if (rc) {
		CERROR("%s: error reading CATALOGS: rc = %d\n",
		       o->do_lu.lo_dev->ld_obd->obd_name,  rc);
		GOTO(out, rc);
	}

	EXIT;
out:
	lu_object_put(env, &o->do_lu);
	RETURN(rc);
}
Esempio n. 29
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);
}
Esempio n. 30
0
/*
 * Helper routine to retrieve slave information.
 * This function converts a quotactl request into quota/accounting object
 * operations. It is independant of the slave stack which is only accessible
 * from the OSD layer.
 *
 * \param env   - is the environment passed by the caller
 * \param dev   - is the dt_device this quotactl is executed on
 * \param oqctl - is the quotactl request
 */
int lquotactl_slv(const struct lu_env *env, struct dt_device *dev,
		  struct obd_quotactl *oqctl)
{
	struct lquota_thread_info	*qti = lquota_info(env);
	__u64				 key;
	struct dt_object		*obj;
	struct obd_dqblk		*dqblk = &oqctl->qc_dqblk;
	int				 rc;
	ENTRY;

	if (oqctl->qc_cmd != Q_GETOQUOTA) {
		/* as in many other places, dev->dd_lu_dev.ld_obd->obd_name
		 * point to an invalid obd_name, to be fixed in LU-1574 */
		CERROR("%s: Unsupported quotactl command: %x\n",
		       dev->dd_lu_dev.ld_obd->obd_name, oqctl->qc_cmd);
		RETURN(-EOPNOTSUPP);
	}

	if (oqctl->qc_type != USRQUOTA && oqctl->qc_type != GRPQUOTA)
		/* no support for directory quota yet */
		RETURN(-EOPNOTSUPP);

	/* qc_id is a 32-bit field while a key has 64 bits */
	key = oqctl->qc_id;

	/* Step 1: collect accounting information */

	obj = acct_obj_lookup(env, dev, oqctl->qc_type);
	if (IS_ERR(obj))
		RETURN(-EOPNOTSUPP);
	if (obj->do_index_ops == NULL)
		GOTO(out, rc = -EINVAL);

	/* lookup record storing space accounting information for this ID */
	rc = dt_lookup(env, obj, (struct dt_rec *)&qti->qti_acct_rec,
		       (struct dt_key *)&key);
	if (rc < 0)
		GOTO(out, rc);

	memset(&oqctl->qc_dqblk, 0, sizeof(struct obd_dqblk));
	dqblk->dqb_curspace	= qti->qti_acct_rec.bspace;
	dqblk->dqb_curinodes	= qti->qti_acct_rec.ispace;
	dqblk->dqb_valid	= QIF_USAGE;

	lu_object_put(env, &obj->do_lu);

	/* Step 2: collect enforcement information */

	obj = quota_obj_lookup(env, dev, oqctl->qc_type);
	if (IS_ERR(obj))
		RETURN(0);
	if (obj->do_index_ops == NULL)
		GOTO(out, rc = 0);

	memset(&qti->qti_slv_rec, 0, sizeof(qti->qti_slv_rec));
	/* lookup record storing enforcement information for this ID */
	rc = dt_lookup(env, obj, (struct dt_rec *)&qti->qti_slv_rec,
		       (struct dt_key *)&key);
	if (rc < 0 && rc != -ENOENT)
		GOTO(out, rc = 0);

	if (lu_device_is_md(dev->dd_lu_dev.ld_site->ls_top_dev)) {
		dqblk->dqb_ihardlimit = qti->qti_slv_rec.qsr_granted;
		dqblk->dqb_bhardlimit = 0;
	} else {
		dqblk->dqb_ihardlimit = 0;
		dqblk->dqb_bhardlimit = qti->qti_slv_rec.qsr_granted;
	}
	dqblk->dqb_valid |= QIF_LIMITS;

	GOTO(out, rc = 0);
out:
	lu_object_put(env, &obj->do_lu);
        return rc;
}