Esempio n. 1
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 = (type == USRQUOTA) ? LQUOTA_USR_OID
							: LQUOTA_GRP_OID;

		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);
			lu_object_put(env, &slv_idx->do_lu);
			slv_idx = ERR_PTR(rc);
		}
	}

	RETURN(slv_idx);
}
Esempio n. 2
0
/*
 * Handle quota request from slave.
 *
 * \param env  - is the environment passed by the caller
 * \param ld   - is the lu device associated with the qmt
 * \param req  - is the quota acquire request
 */
static int qmt_dqacq(const struct lu_env *env, struct lu_device *ld,
		     struct ptlrpc_request *req)
{
	struct qmt_device	*qmt = lu2qmt_dev(ld);
	struct quota_body	*qbody, *repbody;
	struct obd_uuid		*uuid;
	struct ldlm_lock	*lock;
	struct lquota_entry	*lqe;
	int			 pool_id, pool_type, qtype;
	int			 rc;
	ENTRY;

	qbody = req_capsule_client_get(&req->rq_pill, &RMF_QUOTA_BODY);
	if (qbody == NULL)
		RETURN(err_serious(-EPROTO));

	repbody = req_capsule_server_get(&req->rq_pill, &RMF_QUOTA_BODY);
	if (repbody == NULL)
		RETURN(err_serious(-EFAULT));

	/* verify if global lock is stale */
	if (!lustre_handle_is_used(&qbody->qb_glb_lockh))
		RETURN(-ENOLCK);

	lock = ldlm_handle2lock(&qbody->qb_glb_lockh);
	if (lock == NULL)
		RETURN(-ENOLCK);
	LDLM_LOCK_PUT(lock);

	uuid = &req->rq_export->exp_client_uuid;

	if (req_is_rel(qbody->qb_flags) + req_is_acq(qbody->qb_flags) +
	    req_is_preacq(qbody->qb_flags) > 1) {
		CERROR("%s: malformed quota request with conflicting flags set "
		       "(%x) from slave %s\n", qmt->qmt_svname,
		       qbody->qb_flags, obd_uuid2str(uuid));
		RETURN(-EPROTO);
	}

	if (req_is_acq(qbody->qb_flags) || req_is_preacq(qbody->qb_flags)) {
		/* acquire and pre-acquire should use a valid ID lock */

		if (!lustre_handle_is_used(&qbody->qb_lockh))
			RETURN(-ENOLCK);

		lock = ldlm_handle2lock(&qbody->qb_lockh);
		if (lock == NULL)
			/* no lock associated with this handle */
			RETURN(-ENOLCK);

		LDLM_DEBUG(lock, "%sacquire request",
			   req_is_preacq(qbody->qb_flags) ? "pre" : "");

		if (!obd_uuid_equals(&lock->l_export->exp_client_uuid, uuid)) {
			/* sorry, no way to cheat ... */
			LDLM_LOCK_PUT(lock);
			RETURN(-ENOLCK);
		}

		if ((lock->l_flags & LDLM_FL_AST_SENT) != 0) {
			struct ptlrpc_service_part	*svc;
			unsigned int			 timeout;

			svc = req->rq_rqbd->rqbd_svcpt;
			timeout = at_est2timeout(at_get(&svc->scp_at_estimate));
			timeout = max(timeout, ldlm_timeout);

			/* lock is being cancelled, prolong timeout */
			ldlm_refresh_waiting_lock(lock, timeout);
		}
		LDLM_LOCK_PUT(lock);
	}

	/* extract pool & quota information from global index FID packed in the
	 * request */
	rc = lquota_extract_fid(&qbody->qb_fid, &pool_id, &pool_type, &qtype);
	if (rc)
		RETURN(-EINVAL);

	/* Find the quota entry associated with the quota id */
	lqe = qmt_pool_lqe_lookup(env, qmt, pool_id, pool_type, qtype,
				  &qbody->qb_id);
	if (IS_ERR(lqe))
		RETURN(PTR_ERR(lqe));

	/* process quota request */
	rc = qmt_dqacq0(env, lqe, qmt, uuid, qbody->qb_flags, qbody->qb_count,
			qbody->qb_usage, repbody);

	if (lustre_handle_is_used(&qbody->qb_lockh))
		/* return current qunit value only to slaves owning an per-ID
		 * quota lock. For enqueue, the qunit value will be returned in
		 * the LVB */
		 repbody->qb_qunit = lqe->lqe_qunit;
	lqe_putref(lqe);
	RETURN(rc);
}