Exemplo n.º 1
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, qtype2acct_oid(type));

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

	if (!dt_object_exists(obj)) {
		dt_object_put(env, obj);
		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);
			dt_object_put(env, obj);
			RETURN(ERR_PTR(rc));
		}
	}
	RETURN(obj);
}
Exemplo n.º 2
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 mdd_orphan_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,
				   mdd_orphan_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: orphan dir '%s' is not an index: rc = %d\n",
		       mdd2obd_dev(mdd)->obd_name, mdd_orphan_index_name, rc);
		dt_object_put(env, d);
		RETURN(-ENOTDIR);
	}
	mdd->mdd_orphans = d;
	RETURN(0);
}
Exemplo n.º 3
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);

	dt_object_put(env, qmt_root);
	RETURN(rc);
}
Exemplo n.º 4
0
/*
 * Look-up/create a global index file.
 *
 * \param env - is the environment passed by the caller
 * \parap dev - is the dt_device where to lookup/create the global index file
 * \param parent - is the parent directory where to create the global index if
 *                 not found
 * \param fid - is the fid of the global index to be looked up/created
 * \parap local - indicates whether the index should be created with a local
 *                generated fid or with \fid
 *
 * \retval     - pointer to the dt_object of the global index on success,
 *               appropriate error on failure
 */
struct dt_object *lquota_disk_glb_find_create(const struct lu_env *env,
					      struct dt_device *dev,
					      struct dt_object *parent,
					      struct lu_fid *fid, bool local)
{
	struct lquota_thread_info	*qti = lquota_info(env);
	struct dt_object		*glb_idx;
	const struct dt_index_features	*idx_feat;
	ENTRY;

	CDEBUG(D_QUOTA, "look-up/create %sglobal idx file ("DFID")\n",
	       local ? "local " : "", PFID(fid));

	idx_feat = &dt_quota_glb_features;

	/* the filename is composed of the most signicant bits of the FID,
	 * that's to say the oid which encodes the pool id, pool type and quota
	 * type */
	sprintf(qti->qti_buf, "0x%x", fid->f_oid);

	if (local) {
		/* We use the sequence reserved for local named objects */
		lu_local_name_obj_fid(&qti->qti_fid, 1);
		glb_idx = lquota_disk_find_create(env, dev, parent,
						  &qti->qti_fid, idx_feat,
						  qti->qti_buf);
	} else {
		/* look-up/create global index on disk */
		glb_idx = local_index_find_or_create_with_fid(env, dev, fid,
							      parent,
							      qti->qti_buf,
							      LQUOTA_MODE,
							      idx_feat);
	}

	if (IS_ERR(glb_idx)) {
		CERROR("%s: failed to look-up/create idx file "DFID" rc:%ld "
		       "local:%d\n", dev->dd_lu_dev.ld_obd->obd_name,
		       PFID(fid), PTR_ERR(glb_idx), local);
		RETURN(glb_idx);
	}

	/* install index operation vector */
	if (glb_idx->do_index_ops == NULL) {
		int rc;

		rc = glb_idx->do_ops->do_index_try(env, glb_idx, idx_feat);
		if (rc) {
			CERROR("%s: failed to setup index operations for "DFID
			       " rc:%d\n", dev->dd_lu_dev.ld_obd->obd_name,
			       PFID(lu_object_fid(&glb_idx->do_lu)), rc);
			dt_object_put(env, glb_idx);
			glb_idx = ERR_PTR(rc);
		}
	}

	RETURN(glb_idx);
}
Exemplo n.º 5
0
void mdd_orphan_index_fini(const struct lu_env *env, struct mdd_device *mdd)
{
	ENTRY;
	if (mdd->mdd_orphans != NULL) {
		dt_object_put(env, mdd->mdd_orphans);
		mdd->mdd_orphans = NULL;
	}
	EXIT;
}
Exemplo n.º 6
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 = qtype2slv_oid(type);
	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)) {
		dt_object_put(env, obj);
		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);
			dt_object_put(env, obj);
			RETURN(ERR_PTR(rc));
		}
	}
	RETURN(obj);
}
Exemplo n.º 7
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);
			dt_object_put(env, slv_idx);
			slv_idx = ERR_PTR(rc);
		}
	}

	RETURN(slv_idx);
}
Exemplo n.º 8
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 < 0 || oqctl->qc_type >= LL_MAXQUOTAS)
		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;

	dt_object_put(env, obj);

	/* 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:
	dt_object_put(env, obj);
	return rc;
}
Exemplo n.º 9
0
/*
 * Look-up a slave index file. If the slave index isn't found:
 * - if local is set to false, we allocate a FID from FID_SEQ_QUOTA sequence and
 *   create the index.
 * - otherwise, we create the index file with a local reserved FID (see
 *   lquota_local_oid)
 *
 * \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 create the slave index if
 *                 it does not exist already
 * \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
 * \param local   - indicate whether to use local reserved FID (LQUOTA_USR_OID
 *                  & LQUOTA_GRP_OID) for the slave index creation or to
 *                  allocate a new fid from sequence FID_SEQ_QUOTA
 *
 * \retval     - pointer to the dt_object of the slave index on success,
 *               appropriate error on failure
 */
struct dt_object *lquota_disk_slv_find_create(const struct lu_env *env,
					      struct dt_device *dev,
					      struct dt_object *parent,
					      struct lu_fid *glb_fid,
					      struct obd_uuid *uuid,
					      bool local)
{
	struct lquota_thread_info	*qti = lquota_info(env);
	struct dt_object		*slv_idx;
	int				 rc;
	ENTRY;

	LASSERT(uuid != NULL);

	CDEBUG(D_QUOTA, "lookup/create 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));

	/* Slave indexes uses the FID_SEQ_QUOTA sequence since they can be read
	 * through the network */
	qti->qti_fid.f_seq = FID_SEQ_QUOTA;
	qti->qti_fid.f_ver = 0;
	if (local) {
		int type;

		rc = lquota_extract_fid(glb_fid, NULL, NULL, &type);
		if (rc)
			RETURN(ERR_PTR(rc));

		/* use predefined fid in the reserved oid list */
		qti->qti_fid.f_oid = qtype2slv_oid(type);

		slv_idx = local_index_find_or_create_with_fid(env, dev,
							      &qti->qti_fid,
							      parent,
							      qti->qti_buf,
							      LQUOTA_MODE,
							&dt_quota_slv_features);
	} else {
		/* allocate fid dynamically if index does not exist already */
		qti->qti_fid.f_oid = LQUOTA_GENERATED_OID;

		/* lookup/create slave index file */
		slv_idx = lquota_disk_find_create(env, dev, parent,
						  &qti->qti_fid,
						  &dt_quota_slv_features,
						  qti->qti_buf);
	}

	if (IS_ERR(slv_idx))
		RETURN(slv_idx);

	/* install index operation vector */
	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 index operations for "DFID
			       " rc:%d\n", dev->dd_lu_dev.ld_obd->obd_name,
			       PFID(lu_object_fid(&slv_idx->do_lu)), rc);
			dt_object_put(env, slv_idx);
			slv_idx = ERR_PTR(rc);
		}
	}

	RETURN(slv_idx);
}
Exemplo n.º 10
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;
	dt_object_put_nocache(env, qt_dir);
	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))
		dt_object_put(env, parent);
	if (los != NULL)
		local_oid_storage_fini(env, los);
	if (rc) {
		if (qt_dir != NULL && !IS_ERR(qt_dir))
			dt_object_put(env, qt_dir);
		qt_dir = ERR_PTR(rc);
	}
	return qt_dir;
}