Commit e1a0202c authored by Chen Linxuan's avatar Chen Linxuan Committed by Jens Axboe
Browse files

blk-cgroup: improve policy registration error handling



This patch improve the returned error code of blkcg_policy_register().

1. Move the validation check for cpd/pd_alloc_fn and cpd/pd_free_fn
   function pairs to the start of blkcg_policy_register(). This ensures
   we immediately return -EINVAL if the function pairs are not correctly
   provided, rather than returning -ENOSPC after locking and unlocking
   mutexes unnecessarily.

   Those locks should not contention any problems, as error of policy
   registration is a super cold path.

2. Return -ENOMEM when cpd_alloc_fn() failed.

Co-authored-by: default avatarWen Tao <wentao@uniontech.com>
Signed-off-by: default avatarWen Tao <wentao@uniontech.com>
Signed-off-by: default avatarChen Linxuan <chenlinxuan@uniontech.com>
Reviewed-by: default avatarMichal Koutný <mkoutny@suse.com>
Acked-by: default avatarTejun Heo <tj@kernel.org>
Reviewed-by: default avatarYu Kuai <yukuai3@huawei.com>
Link: https://lore.kernel.org/r/3E333A73B6B6DFC0+20250317022924.150907-1-chenlinxuan@uniontech.com


Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 86947bdc
Loading
Loading
Loading
Loading
+12 −10
Original line number Diff line number Diff line
@@ -1727,27 +1727,27 @@ int blkcg_policy_register(struct blkcg_policy *pol)
	struct blkcg *blkcg;
	int i, ret;

	/*
	 * Make sure cpd/pd_alloc_fn and cpd/pd_free_fn in pairs, and policy
	 * without pd_alloc_fn/pd_free_fn can't be activated.
	 */
	if ((!pol->cpd_alloc_fn ^ !pol->cpd_free_fn) ||
	    (!pol->pd_alloc_fn ^ !pol->pd_free_fn))
		return -EINVAL;

	mutex_lock(&blkcg_pol_register_mutex);
	mutex_lock(&blkcg_pol_mutex);

	/* find an empty slot */
	ret = -ENOSPC;
	for (i = 0; i < BLKCG_MAX_POLS; i++)
		if (!blkcg_policy[i])
			break;
	if (i >= BLKCG_MAX_POLS) {
		pr_warn("blkcg_policy_register: BLKCG_MAX_POLS too small\n");
		ret = -ENOSPC;
		goto err_unlock;
	}

	/*
	 * Make sure cpd/pd_alloc_fn and cpd/pd_free_fn in pairs, and policy
	 * without pd_alloc_fn/pd_free_fn can't be activated.
	 */
	if ((!pol->cpd_alloc_fn ^ !pol->cpd_free_fn) ||
	    (!pol->pd_alloc_fn ^ !pol->pd_free_fn))
		goto err_unlock;

	/* register @pol */
	pol->plid = i;
	blkcg_policy[pol->plid] = pol;
@@ -1758,8 +1758,10 @@ int blkcg_policy_register(struct blkcg_policy *pol)
			struct blkcg_policy_data *cpd;

			cpd = pol->cpd_alloc_fn(GFP_KERNEL);
			if (!cpd)
			if (!cpd) {
				ret = -ENOMEM;
				goto err_free_cpds;
			}

			blkcg->cpd[pol->plid] = cpd;
			cpd->blkcg = blkcg;