コード例 #1
0
/* Simple wrapper on top of qsd API which implement quota transfer for osd
 * setattr needs. As a reminder, only the root user can change ownership of
 * a file, that's why EDQUOT & EINPROGRESS errors are discarded */
static inline int qsd_transfer(const struct lu_env *env,
			       struct qsd_instance *qsd,
			       struct lquota_trans *trans, int qtype,
			       __u64 orig_id, __u64 new_id, __u64 bspace,
			       struct lquota_id_info *qi)
{
	int	rc;

	if (unlikely(qsd == NULL))
		return 0;

	LASSERT(qtype >= 0 && qtype < MAXQUOTAS);
	qi->lqi_type = qtype;

	/* inode accounting */
	qi->lqi_is_blk = false;

	/* one more inode for the new owner ... */
	qi->lqi_id.qid_uid = new_id;
	qi->lqi_space      = 1;
	rc = qsd_op_begin(env, qsd, trans, qi, NULL);
	if (rc == -EDQUOT || rc == -EINPROGRESS)
		rc = 0;
	if (rc)
		return rc;

	/* and one less inode for the current id */
	qi->lqi_id.qid_uid = orig_id;;
	qi->lqi_space      = -1;
	/* can't get EDQUOT when reducing usage */
	rc = qsd_op_begin(env, qsd, trans, qi, NULL);
	if (rc == -EINPROGRESS)
		rc = 0;
	if (rc)
		return rc;

	/* block accounting */
	qi->lqi_is_blk = true;

	/* more blocks for the new owner ... */
	qi->lqi_id.qid_uid = new_id;
	qi->lqi_space      = bspace;
	rc = qsd_op_begin(env, qsd, trans, qi, NULL);
	if (rc == -EDQUOT || rc == -EINPROGRESS)
		rc = 0;
	if (rc)
		return rc;

	/* and finally less blocks for the current owner */
	qi->lqi_id.qid_uid = orig_id;
	qi->lqi_space      = -bspace;
	rc = qsd_op_begin(env, qsd, trans, qi, NULL);
	/* can't get EDQUOT when reducing usage */
	if (rc == -EINPROGRESS)
		rc = 0;
	return rc;
}
コード例 #2
0
ファイル: osd_quota.c プロジェクト: Lezval/lustre
/*
 * Wrapper for qsd_op_begin().
 *
 * \param env    - the environment passed by the caller
 * \param osd    - is the osd_device
 * \param uid    - user id of the inode
 * \param gid    - group id of the inode
 * \param space  - how many blocks/inodes will be consumed/released
 * \param oh     - osd transaction handle
 * \param is_blk - block quota or inode quota?
 * \param flags  - if the operation is write, return no user quota, no
 *                  group quota, or sync commit flags to the caller
 * \param force  - set to 1 when changes are performed by root user and thus
 *                  can't failed with EDQUOT
 *
 * \retval 0      - success
 * \retval -ve    - failure
 */
int osd_declare_quota(const struct lu_env *env, struct osd_device *osd,
		      qid_t uid, qid_t gid, long long space,
		      struct osd_thandle *oh, bool is_blk, int *flags,
		      bool force)
{
	struct osd_thread_info	*info = osd_oti_get(env);
	struct lquota_id_info	*qi = &info->oti_qi;
	struct qsd_instance     *qsd = osd->od_quota_slave;
	int			 rcu, rcg; /* user & group rc */
	ENTRY;

	if (unlikely(qsd == NULL))
		/* quota slave instance hasn't been allocated yet */
		RETURN(0);

	/* let's start with user quota */
	qi->lqi_id.qid_uid = uid;
	qi->lqi_type       = USRQUOTA;
	qi->lqi_space      = space;
	qi->lqi_is_blk     = is_blk;
	rcu = qsd_op_begin(env, qsd, &oh->ot_quota_trans, qi, flags);

	if (force && (rcu == -EDQUOT || rcu == -EINPROGRESS))
		/* ignore EDQUOT & EINPROGRESS when changes are done by root */
		rcu = 0;

	/* For non-fatal error, we want to continue to get the noquota flags
	 * for group id. This is only for commit write, which has @flags passed
	 * in. See osd_declare_write_commit().
	 * When force is set to true, we also want to proceed with the gid */
	if (rcu && (rcu != -EDQUOT || flags == NULL))
		RETURN(rcu);

	/* and now group quota */
	qi->lqi_id.qid_gid = gid;
	qi->lqi_type       = GRPQUOTA;
	rcg = qsd_op_begin(env, qsd, &oh->ot_quota_trans, qi, flags);

	if (force && (rcg == -EDQUOT || rcg == -EINPROGRESS))
		/* as before, ignore EDQUOT & EINPROGRESS for root */
		rcg = 0;

	RETURN(rcu ? rcu : rcg);
}