From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from 013.lax.mailroute.net (013.lax.mailroute.net [199.89.1.16]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 514263D3CE2 for ; Thu, 2 Apr 2026 18:40:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=199.89.1.16 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775155238; cv=none; b=iy7YYhczpSzr7MkQ+/WJ/EMa4nw28dszjVC5o+SRJOFwGZ8rDthN3StETdyDgmTnv1/eIdQQsW4BOWg6MhEVg+2K3FL77h0I6JgghpoF7es5spuus7/zBAsAb8e9kLxfz674zgh4gnSkxOpEtDsGksOSa2hj/8iHj2xtSq+rbrc= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775155238; c=relaxed/simple; bh=ml+jSFE8c6KzwPrv0h25kz/Zv9TMEU64st2RRNi2y/0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=eI3IzBlla72XdLlGN7F2e+zgokqomBHOoGerkBofAcgmQbxcM9Ctzg7JleP8mrCnm2ZmhYI+9v7PzPrIVusQQ1y0c+W7XMnxN+yz6KAFkuCEn3ayEQsbYHzwmFxoGnqBSz5jHbLTX9NweWEngrlVNa3hVU9ArZX20kEWa3ywF9k= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=acm.org; spf=pass smtp.mailfrom=acm.org; dkim=pass (2048-bit key) header.d=acm.org header.i=@acm.org header.b=4cnnh17r; arc=none smtp.client-ip=199.89.1.16 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=acm.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=acm.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=acm.org header.i=@acm.org header.b="4cnnh17r" Received: from localhost (localhost [127.0.0.1]) by 013.lax.mailroute.net (Postfix) with ESMTP id 4fmrJf3Mj3zlh2gC; Thu, 2 Apr 2026 18:40:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=acm.org; h= content-transfer-encoding:mime-version:references:in-reply-to :x-mailer:message-id:date:date:subject:subject:from:from :received:received; s=mr01; t=1775155217; x=1777747218; bh=Mu0tQ 0Dta3aTqB4yc7tpLP3wi1JOoHcxG69bhbi5Llk=; b=4cnnh17rx/hJAXaMzaji1 g/2mbKmH5KGVvWvKlboaKpB91nxSelMm2yikG0XcXRmM2y36PE+QGi+bWhOMzjat X2A8WYiN+le8/ayBry4lSGElWEL22C73Fcb5hRNRtfRTNvYRg7eUFmC2lIo5LP03 gb7V+uf1ERByGFbcyqkWTaH4ruA4kKLmqtMnzfmqPE74sMy/Znn8jytWz3+eo2Oq Sy013E2k9Ax1ljeI/ZF3/IDCeBAqQyAqwIjmiR0mhSZWBk7XvOA4lMd3gKypITC5 BwIbI7W8Qt3BRak5MJel180zxRkRhrG1zOt3xPKPdU5N1BPY80fx+ev1nd24wuol g== X-Virus-Scanned: by MailRoute Received: from 013.lax.mailroute.net ([127.0.0.1]) by localhost (013.lax [127.0.0.1]) (mroute_mailscanner, port 10029) with LMTP id OjlD9Vxh5Iqn; Thu, 2 Apr 2026 18:40:17 +0000 (UTC) Received: from bvanassche.mtv.corp.google.com (unknown [104.135.180.219]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: bvanassche@acm.org) by 013.lax.mailroute.net (Postfix) with ESMTPSA id 4fmrJG0Qd4zlh2g6; Thu, 2 Apr 2026 18:40:13 +0000 (UTC) From: Bart Van Assche To: Jens Axboe Cc: linux-block@vger.kernel.org, Christoph Hellwig , Damien Le Moal , Marco Elver , Bart Van Assche , Tejun Heo , Yu Kuai , Josef Bacik , Nathan Chancellor Subject: [PATCH v3 04/12] block/cgroup: Split blkg_conf_exit() Date: Thu, 2 Apr 2026 11:39:36 -0700 Message-ID: <20260402183950.3626956-5-bvanassche@acm.org> X-Mailer: git-send-email 2.53.0.1213.gd9a14994de-goog In-Reply-To: <20260402183950.3626956-1-bvanassche@acm.org> References: <20260402183950.3626956-1-bvanassche@acm.org> Precedence: bulk X-Mailing-List: linux-block@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Split blkg_conf_exit() into blkg_conf_unprep() and blkg_conf_close_bdev() because blkg_conf_exit() is not compatible with the Clang thread-safety annotations. Remove blkg_conf_exit(). Rename blkg_conf_exit_frozen() into blkg_conf_close_bdev_frozen(). Add thread-safety annotations to the new functions. Reviewed-by: Christoph Hellwig Cc: Tejun Heo Signed-off-by: Bart Van Assche --- block/bfq-cgroup.c | 9 ++++-- block/blk-cgroup.c | 58 ++++++++++++++++++------------------- block/blk-cgroup.h | 15 +++++++--- block/blk-iocost.c | 67 +++++++++++++++++++++---------------------- block/blk-iolatency.c | 19 ++++++------ block/blk-throttle.c | 34 +++++++++++++--------- 6 files changed, 108 insertions(+), 94 deletions(-) diff --git a/block/bfq-cgroup.c b/block/bfq-cgroup.c index 38396df9dce7..5d40279d6c9d 100644 --- a/block/bfq-cgroup.c +++ b/block/bfq-cgroup.c @@ -1053,11 +1053,11 @@ static ssize_t bfq_io_set_device_weight(struct ke= rnfs_open_file *of, =20 ret =3D blkg_conf_open_bdev(&ctx); if (ret) - goto out; + return ret; =20 ret =3D blkg_conf_prep(blkcg, &blkcg_policy_bfq, &ctx); if (ret) - goto out; + goto close_bdev; =20 if (sscanf(ctx.body, "%llu", &v) =3D=3D 1) { /* require "default" on dfl */ @@ -1078,8 +1078,11 @@ static ssize_t bfq_io_set_device_weight(struct ker= nfs_open_file *of, bfq_group_set_weight(bfqg, bfqg->entity.weight, v); ret =3D 0; } + out: - blkg_conf_exit(&ctx); + blkg_conf_unprep(&ctx); +close_bdev: + blkg_conf_close_bdev(&ctx); return ret ?: nbytes; } =20 diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c index a8d95d51b866..86513c54c217 100644 --- a/block/blk-cgroup.c +++ b/block/blk-cgroup.c @@ -755,7 +755,7 @@ EXPORT_SYMBOL_GPL(__blkg_prfill_u64); * * Initialize @ctx which can be used to parse blkg config input string @= input. * Once initialized, @ctx can be used with blkg_conf_open_bdev() and - * blkg_conf_prep(), and must be cleaned up with blkg_conf_exit(). + * blkg_conf_prep(). */ void blkg_conf_init(struct blkg_conf_ctx *ctx, char *input) { @@ -817,8 +817,8 @@ EXPORT_SYMBOL_GPL(blkg_conf_open_bdev); * ensures the correct locking order between freeze queue and q->rq_qos_= mutex. * * This function returns negative error on failure. On success it return= s - * memflags which must be saved and later passed to blkg_conf_exit_froze= n - * for restoring the memalloc scope. + * memflags which must be saved and later passed to + * blkg_conf_close_bdev_frozen() for restoring the memalloc scope. */ unsigned long __must_check blkg_conf_open_bdev_frozen(struct blkg_conf_c= tx *ctx) { @@ -858,11 +858,10 @@ unsigned long __must_check blkg_conf_open_bdev_froz= en(struct blkg_conf_ctx *ctx) * * blkg_conf_open_bdev() must be called on @ctx beforehand. On success, = this * function returns with queue lock held and must be followed by - * blkg_conf_exit(). + * blkg_conf_close_bdev(). */ int blkg_conf_prep(struct blkcg *blkcg, const struct blkcg_policy *pol, struct blkg_conf_ctx *ctx) - __acquires(&bdev->bd_queue->queue_lock) { struct gendisk *disk; struct request_queue *q; @@ -968,42 +967,41 @@ int blkg_conf_prep(struct blkcg *blkcg, const struc= t blkcg_policy *pol, EXPORT_SYMBOL_GPL(blkg_conf_prep); =20 /** - * blkg_conf_exit - clean up per-blkg config update + * blkg_conf_unprep - counterpart of blkg_conf_prep() * @ctx: blkg_conf_ctx initialized with blkg_conf_init() - * - * Clean up after per-blkg config update. This function must be called o= n all - * blkg_conf_ctx's initialized with blkg_conf_init(). */ -void blkg_conf_exit(struct blkg_conf_ctx *ctx) - __releases(&ctx->bdev->bd_queue->queue_lock) - __releases(&ctx->bdev->bd_queue->rq_qos_mutex) +void blkg_conf_unprep(struct blkg_conf_ctx *ctx) { - if (ctx->blkg) { - spin_unlock_irq(&bdev_get_queue(ctx->bdev)->queue_lock); - ctx->blkg =3D NULL; - } + WARN_ON_ONCE(!ctx->blkg); + spin_unlock_irq(&ctx->bdev->bd_disk->queue->queue_lock); + ctx->blkg =3D NULL; +} +EXPORT_SYMBOL_GPL(blkg_conf_unprep); =20 - if (ctx->bdev) { - mutex_unlock(&ctx->bdev->bd_queue->rq_qos_mutex); - blkdev_put_no_open(ctx->bdev); - ctx->body =3D NULL; - ctx->bdev =3D NULL; - } +/** + * blkg_conf_close_bdev - counterpart of blkg_conf_open_bdev() + * @ctx: blkg_conf_ctx initialized with blkg_conf_init() + */ +void blkg_conf_close_bdev(struct blkg_conf_ctx *ctx) +{ + mutex_unlock(&ctx->bdev->bd_queue->rq_qos_mutex); + blkdev_put_no_open(ctx->bdev); + ctx->body =3D NULL; + ctx->bdev =3D NULL; } -EXPORT_SYMBOL_GPL(blkg_conf_exit); +EXPORT_SYMBOL_GPL(blkg_conf_close_bdev); =20 /* - * Similar to blkg_conf_exit, but also unfreezes the queue. Should be us= ed + * Similar to blkg_close_bdev, but also unfreezes the queue. Should be u= sed * when blkg_conf_open_bdev_frozen is used to open the bdev. */ -void blkg_conf_exit_frozen(struct blkg_conf_ctx *ctx, unsigned long memf= lags) +void blkg_conf_close_bdev_frozen(struct blkg_conf_ctx *ctx, + unsigned long memflags) { - if (ctx->bdev) { - struct request_queue *q =3D ctx->bdev->bd_queue; + struct request_queue *q =3D ctx->bdev->bd_queue; =20 - blkg_conf_exit(ctx); - blk_mq_unfreeze_queue(q, memflags); - } + blkg_conf_close_bdev(ctx); + blk_mq_unfreeze_queue(q, memflags); } =20 static void blkg_iostat_add(struct blkg_iostat *dst, struct blkg_iostat = *src) diff --git a/block/blk-cgroup.h b/block/blk-cgroup.h index 1cce3294634d..f0a3af520c55 100644 --- a/block/blk-cgroup.h +++ b/block/blk-cgroup.h @@ -218,12 +218,19 @@ struct blkg_conf_ctx { }; =20 void blkg_conf_init(struct blkg_conf_ctx *ctx, char *input); -int blkg_conf_open_bdev(struct blkg_conf_ctx *ctx); +int blkg_conf_open_bdev(struct blkg_conf_ctx *ctx) + __cond_acquires(0, &ctx->bdev->bd_queue->rq_qos_mutex); unsigned long blkg_conf_open_bdev_frozen(struct blkg_conf_ctx *ctx); int blkg_conf_prep(struct blkcg *blkcg, const struct blkcg_policy *pol, - struct blkg_conf_ctx *ctx); -void blkg_conf_exit(struct blkg_conf_ctx *ctx); -void blkg_conf_exit_frozen(struct blkg_conf_ctx *ctx, unsigned long memf= lags); + struct blkg_conf_ctx *ctx) + __cond_acquires(0, &ctx->bdev->bd_disk->queue->queue_lock); +void blkg_conf_unprep(struct blkg_conf_ctx *ctx) + __releases(ctx->bdev->bd_disk->queue->queue_lock); +void blkg_conf_close_bdev(struct blkg_conf_ctx *ctx) + __releases(&ctx->bdev->bd_queue->rq_qos_mutex); +void blkg_conf_close_bdev_frozen(struct blkg_conf_ctx *ctx, + unsigned long memflags) + __releases(&ctx->bdev->bd_queue->rq_qos_mutex); =20 /** * bio_issue_as_root_blkg - see if this bio needs to be issued as root b= lkg diff --git a/block/blk-iocost.c b/block/blk-iocost.c index b34f820dedcc..e611dd63d712 100644 --- a/block/blk-iocost.c +++ b/block/blk-iocost.c @@ -3142,21 +3142,23 @@ static ssize_t ioc_weight_write(struct kernfs_ope= n_file *of, char *buf, =20 ret =3D blkg_conf_open_bdev(&ctx); if (ret) - goto err; + return ret; =20 ret =3D blkg_conf_prep(blkcg, &blkcg_policy_iocost, &ctx); if (ret) - goto err; + goto close_bdev; =20 iocg =3D blkg_to_iocg(ctx.blkg); =20 + ret =3D -EINVAL; + if (!strncmp(ctx.body, "default", 7)) { v =3D 0; } else { if (!sscanf(ctx.body, "%u", &v)) - goto einval; + goto unprep; if (v < CGROUP_WEIGHT_MIN || v > CGROUP_WEIGHT_MAX) - goto einval; + goto unprep; } =20 spin_lock(&iocg->ioc->lock); @@ -3165,14 +3167,15 @@ static ssize_t ioc_weight_write(struct kernfs_ope= n_file *of, char *buf, weight_updated(iocg, &now); spin_unlock(&iocg->ioc->lock); =20 - blkg_conf_exit(&ctx); - return nbytes; + ret =3D 0; =20 -einval: - ret =3D -EINVAL; -err: - blkg_conf_exit(&ctx); - return ret; +unprep: + blkg_conf_unprep(&ctx); + +close_bdev: + blkg_conf_close_bdev(&ctx); + + return ret ? ret : nbytes; } =20 static u64 ioc_qos_prfill(struct seq_file *sf, struct blkg_policy_data *= pd, @@ -3241,10 +3244,8 @@ static ssize_t ioc_qos_write(struct kernfs_open_fi= le *of, char *input, blkg_conf_init(&ctx, input); =20 memflags =3D blkg_conf_open_bdev_frozen(&ctx); - if (IS_ERR_VALUE(memflags)) { - ret =3D memflags; - goto err; - } + if (IS_ERR_VALUE(memflags)) + return memflags; =20 body =3D ctx.body; disk =3D ctx.bdev->bd_disk; @@ -3361,14 +3362,14 @@ static ssize_t ioc_qos_write(struct kernfs_open_f= ile *of, char *input, =20 blk_mq_unquiesce_queue(disk->queue); =20 - blkg_conf_exit_frozen(&ctx, memflags); + blkg_conf_close_bdev_frozen(&ctx, memflags); return nbytes; einval: spin_unlock_irq(&ioc->lock); blk_mq_unquiesce_queue(disk->queue); ret =3D -EINVAL; err: - blkg_conf_exit_frozen(&ctx, memflags); + blkg_conf_close_bdev_frozen(&ctx, memflags); return ret; } =20 @@ -3434,20 +3435,20 @@ static ssize_t ioc_cost_model_write(struct kernfs= _open_file *of, char *input, =20 ret =3D blkg_conf_open_bdev(&ctx); if (ret) - goto err; + return ret; =20 body =3D ctx.body; q =3D bdev_get_queue(ctx.bdev); if (!queue_is_mq(q)) { ret =3D -EOPNOTSUPP; - goto err; + goto close_bdev; } =20 ioc =3D q_to_ioc(q); if (!ioc) { ret =3D blk_iocost_init(ctx.bdev->bd_disk); if (ret) - goto err; + goto close_bdev; ioc =3D q_to_ioc(q); } =20 @@ -3458,6 +3459,8 @@ static ssize_t ioc_cost_model_write(struct kernfs_o= pen_file *of, char *input, memcpy(u, ioc->params.i_lcoefs, sizeof(u)); user =3D ioc->user_cost_model; =20 + ret =3D -EINVAL; + while ((p =3D strsep(&body, " \t\n"))) { substring_t args[MAX_OPT_ARGS]; char buf[32]; @@ -3475,20 +3478,20 @@ static ssize_t ioc_cost_model_write(struct kernfs= _open_file *of, char *input, else if (!strcmp(buf, "user")) user =3D true; else - goto einval; + goto unlock; continue; case COST_MODEL: match_strlcpy(buf, &args[0], sizeof(buf)); if (strcmp(buf, "linear")) - goto einval; + goto unlock; continue; } =20 tok =3D match_token(p, i_lcoef_tokens, args); if (tok =3D=3D NR_I_LCOEFS) - goto einval; + goto unlock; if (match_u64(&args[0], &v)) - goto einval; + goto unlock; u[tok] =3D v; user =3D true; } @@ -3500,24 +3503,18 @@ static ssize_t ioc_cost_model_write(struct kernfs= _open_file *of, char *input, ioc->user_cost_model =3D false; } ioc_refresh_params(ioc, true); - spin_unlock_irq(&ioc->lock); =20 - blk_mq_unquiesce_queue(q); - blk_mq_unfreeze_queue(q, memflags); - - blkg_conf_exit(&ctx); - return nbytes; + ret =3D 0; =20 -einval: +unlock: spin_unlock_irq(&ioc->lock); =20 blk_mq_unquiesce_queue(q); blk_mq_unfreeze_queue(q, memflags); =20 - ret =3D -EINVAL; -err: - blkg_conf_exit(&ctx); - return ret; +close_bdev: + blkg_conf_close_bdev(&ctx); + return ret ? ret : nbytes; } =20 static struct cftype ioc_files[] =3D { diff --git a/block/blk-iolatency.c b/block/blk-iolatency.c index 53e8dd2dfa8a..1aaee6fb0f59 100644 --- a/block/blk-iolatency.c +++ b/block/blk-iolatency.c @@ -840,7 +840,7 @@ static ssize_t iolatency_set_limit(struct kernfs_open= _file *of, char *buf, =20 ret =3D blkg_conf_open_bdev(&ctx); if (ret) - goto out; + return ret; =20 /* * blk_iolatency_init() may fail after rq_qos_add() succeeds which can @@ -850,11 +850,11 @@ static ssize_t iolatency_set_limit(struct kernfs_op= en_file *of, char *buf, if (!iolat_rq_qos(ctx.bdev->bd_queue)) ret =3D blk_iolatency_init(ctx.bdev->bd_disk); if (ret) - goto out; + goto close_bdev; =20 ret =3D blkg_conf_prep(blkcg, &blkcg_policy_iolatency, &ctx); if (ret) - goto out; + goto close_bdev; =20 iolat =3D blkg_to_lat(ctx.blkg); p =3D ctx.body; @@ -865,7 +865,7 @@ static ssize_t iolatency_set_limit(struct kernfs_open= _file *of, char *buf, char val[21]; /* 18446744073709551616 */ =20 if (sscanf(tok, "%15[^=3D]=3D%20s", key, val) !=3D 2) - goto out; + goto unprep; =20 if (!strcmp(key, "target")) { u64 v; @@ -875,9 +875,9 @@ static ssize_t iolatency_set_limit(struct kernfs_open= _file *of, char *buf, else if (sscanf(val, "%llu", &v) =3D=3D 1) lat_val =3D v * NSEC_PER_USEC; else - goto out; + goto unprep; } else { - goto out; + goto unprep; } } =20 @@ -889,8 +889,11 @@ static ssize_t iolatency_set_limit(struct kernfs_ope= n_file *of, char *buf, if (oldval !=3D iolat->min_lat_nsec) iolatency_clear_scaling(blkg); ret =3D 0; -out: - blkg_conf_exit(&ctx); + +unprep: + blkg_conf_unprep(&ctx); +close_bdev: + blkg_conf_close_bdev(&ctx); return ret ?: nbytes; } =20 diff --git a/block/blk-throttle.c b/block/blk-throttle.c index 97188a795848..11b571246f45 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c @@ -1353,21 +1353,21 @@ static ssize_t tg_set_conf(struct kernfs_open_fil= e *of, =20 ret =3D blkg_conf_open_bdev(&ctx); if (ret) - goto out_finish; + return ret; =20 if (!blk_throtl_activated(ctx.bdev->bd_queue)) { ret =3D blk_throtl_init(ctx.bdev->bd_disk); if (ret) - goto out_finish; + goto close_bdev; } =20 ret =3D blkg_conf_prep(blkcg, &blkcg_policy_throtl, &ctx); if (ret) - goto out_finish; + goto close_bdev; =20 ret =3D -EINVAL; if (sscanf(ctx.body, "%llu", &v) !=3D 1) - goto out_finish; + goto unprep; if (!v) v =3D U64_MAX; =20 @@ -1381,8 +1381,12 @@ static ssize_t tg_set_conf(struct kernfs_open_file= *of, =20 tg_conf_updated(tg, false); ret =3D 0; -out_finish: - blkg_conf_exit(&ctx); + +unprep: + blkg_conf_unprep(&ctx); + +close_bdev: + blkg_conf_close_bdev(&ctx); return ret ?: nbytes; } =20 @@ -1537,17 +1541,17 @@ static ssize_t tg_set_limit(struct kernfs_open_fi= le *of, =20 ret =3D blkg_conf_open_bdev(&ctx); if (ret) - goto out_finish; + return ret; =20 if (!blk_throtl_activated(ctx.bdev->bd_queue)) { ret =3D blk_throtl_init(ctx.bdev->bd_disk); if (ret) - goto out_finish; + goto close_bdev; } =20 ret =3D blkg_conf_prep(blkcg, &blkcg_policy_throtl, &ctx); if (ret) - goto out_finish; + goto close_bdev; =20 tg =3D blkg_to_tg(ctx.blkg); tg_update_carryover(tg); @@ -1573,11 +1577,11 @@ static ssize_t tg_set_limit(struct kernfs_open_fi= le *of, p =3D tok; strsep(&p, "=3D"); if (!p || (sscanf(p, "%llu", &val) !=3D 1 && strcmp(p, "max"))) - goto out_finish; + goto unprep; =20 ret =3D -ERANGE; if (!val) - goto out_finish; + goto unprep; =20 ret =3D -EINVAL; if (!strcmp(tok, "rbps")) @@ -1589,7 +1593,7 @@ static ssize_t tg_set_limit(struct kernfs_open_file= *of, else if (!strcmp(tok, "wiops")) v[3] =3D min_t(u64, val, UINT_MAX); else - goto out_finish; + goto unprep; } =20 tg->bps[READ] =3D v[0]; @@ -1599,8 +1603,10 @@ static ssize_t tg_set_limit(struct kernfs_open_fil= e *of, =20 tg_conf_updated(tg, false); ret =3D 0; -out_finish: - blkg_conf_exit(&ctx); +unprep: + blkg_conf_unprep(&ctx); +close_bdev: + blkg_conf_close_bdev(&ctx); return ret ?: nbytes; } =20