From: no-reply@sashiko.virtuozzo.com
To: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>,
Konstantin Khorenko <khorenko@virtuozzo.com>
Cc: devel@openvz.org
Subject: Re: [Devel] [PATCH hci-8.1] block/blk-cbt: account a write request also when dm starts it
Date: Fri, 16 Oct 2026 14:41:42 +0000 [thread overview]
Message-ID: <010701a145296351-ade7da64-7c3b-4c0f-a16c-fce44a18603f-000000@eu-central-1.amazonses.com> (raw)
In-Reply-To: <20261016-ptikhomirov-vstor-149268-cbt-account-at-rq-start-v1-1-1f20b151431d@virtuozzo.com>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] block: cbt_page_alloc() GFP_ATOMIC failure sets CBT_ERROR on dm dispatch path
--
commit 07126a82d2afc4a47285774d1cb334f3398a6e89
Author: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
block/blk-cbt: account a write request also when dm starts it
This patch adds blk_cbt_rq_start(), called from dm_start_request(), so a
write is accounted in CBT a second time when request based dm starts it.
A missing bitmap page is allocated with GFP_ATOMIC in this path, and
CBT_ERROR is set if that allocation fails.
Link: https://virtuozzo.atlassian.net/browse/VSTOR-149268
> diff --git a/block/blk-cbt.c b/block/blk-cbt.c
> --- a/block/blk-cbt.c
> +++ b/block/blk-cbt.c
[ ... ]
> @@ -129,11 +137,15 @@ static int cbt_page_alloc(struct cbt_info **cbt_pp, unsigned long idx,
> }
> }
> spin_unlock_irq(&cbt->lock);
> - if (in_rcu)
> - rcu_read_unlock();
> - page = alloc_page(GFP_NOIO|__GFP_ZERO);
> - if (in_rcu)
> - rcu_read_lock();
> + if (alloc == CBT_ALLOC_ATOMIC) {
> + page = alloc_page(GFP_ATOMIC | __GFP_ZERO | __GFP_NOWARN);
[Severity: Medium]
Can this GFP_ATOMIC allocation fail often enough to matter?
Under memory pressure alloc_page(GFP_ATOMIC) has no direct reclaim and
can fail. When it does, a few lines further down in cbt_page_alloc():
if (unlikely(!page)) {
set_bit(CBT_ERROR, &cbt->flags);
spin_unlock_irq(&cbt->lock);
return -ENOMEM;
}
CBT_ERROR is a sticky flag, and __GFP_NOWARN makes the failure silent.
The call chain is:
dm_mq_queue_rq()
dm_start_request()
blk_cbt_rq_start()
blk_cbt_add(..., CBT_ALLOC_ATOMIC)
__blk_cbt_set()
cbt_page_alloc()
Neither blk_cbt_rq_start() nor blk_cbt_add() checks the return value.
After the failure, blk_cbt_add() returns early for this CBT on every
later write:
if (unlikely(test_bit(CBT_ERROR, &cbt->flags)))
return;
cbt_ioc_get() and cbt_ioc_set() then return -EIO.
So a transient atomic allocation failure permanently invalidates the CBT,
and with it the incremental backup chain, until the CBT is re-created.
The old submission time path used GFP_NOIO with the RCU lock dropped,
which does not fail in practice.
Is there a reason not to retry from a sleepable context, or to avoid
setting CBT_ERROR in the atomic case?
[ ... ]
> @@ -248,7 +261,7 @@ static void blk_cbt_add(struct cbt_info *cbt, blkcnt_t start, blkcnt_t len,
> put_cpu_ptr(cbt->cache);
>
> if (likely(old.len))
> - __blk_cbt_set(cbt, old.start, old.len, 1, 1, NULL, NULL);
> + __blk_cbt_set(cbt, old.start, old.len, alloc, 1, NULL, NULL);
[Severity: Medium]
Is the commit message claim correct that a page can be missing here only
for requests submitted before BLKCBTSTART?
The commit message says:
"This only happens for requests submitted before BLKCBTSTART: any later
write has its page allocated already by its submission time accounting."
On the normal (cached) path, blk_cbt_add() only records the extent in the
per-CPU cache. It calls __blk_cbt_set(), and so allocates pages, only
for the evicted old extent.
That means a write submitted after BLKCBTSTART can still have no bitmap
page when dm_start_request() runs.
In blk_cbt_rq_start(), re-adding a range that is not contiguous with the
cached extent evicts the previous cached extent, which is often an
unrelated earlier write. That extent is flushed with CBT_ALLOC_ATOMIC.
So GFP_ATOMIC page allocation looks possible on ordinary write-heavy
workloads, not only in the narrow pre-BLKCBTSTART window.
Also, re-adding the same range from blk_cbt_rq_start() never coalesces,
since ex->start + ex->len != start for it. Each started request
therefore causes an extra __blk_cbt_set() call and bitmap page lock.
Could the commit message and the allocation strategy be revisited in
light of this?
[ ... ]
> +void blk_cbt_rq_start(struct request *rq)
> +{
[ ... ]
> + blk_cbt_add(cbt, bio->bi_iter.bi_sector << 9,
> + bio->bi_iter.bi_size, CBT_ALLOC_ATOMIC);
[Severity: Medium]
This is the same issue as above, seen from the caller. Errors from
blk_cbt_add() are dropped here, so a CBT_ERROR set by a failed
GFP_ATOMIC allocation in blk_cbt_rq_start() is not reported to the dm
dispatch path. Is that intended?
[ ... ]
--
Sashiko AI review · https://sashiko.vzint.dev/#/patchset/20261016-ptikhomirov-vstor-149268-cbt-account-at-rq-start-v1-1-1f20b151431d@virtuozzo.com?part=1
_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel
prev parent reply other threads:[~2026-10-16 14:43 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-16 14:34 Pavel Tikhomirov
2026-10-16 14:41 ` no-reply [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=010701a145296351-ade7da64-7c3b-4c0f-a16c-fce44a18603f-000000@eu-central-1.amazonses.com \
--to=no-reply@sashiko.virtuozzo.com \
--cc=devel@openvz.org \
--cc=khorenko@virtuozzo.com \
--cc=ptikhomirov@virtuozzo.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox