[Devel] [PATCH hci-8.1 v10 09/10] dm-qcow2: retry R1/R2 writeback that failed with ENOSPC
Alexander Ivanov
alexander.ivanov at virtuozzo.com
Mon Nov 9 14:58:55 MSK 2026
A failed R1/R2 writeback sets MD_WRITEBACK_ERROR and drops MD_DIRTY.
Nothing writes the page again unless its refcounts change. On suspend
the md writeback flush finds the error and sets md_writeback_error, so
resume is refused until the image is checked and the target reloaded,
even if the failure was a transient ENOSPC of the underlying fs and
the space has been freed since.
Redirty the page on -ENOSPC, so the slow writeback timer retries it,
as data writes delayed on ENOSPC are retried. The suspend flush fires
the timer, which gives the page one more try. A page that still fails
then is not redirtied, as wants_suspend is set, so nothing is left
pending on a suspended device and md_writeback_error is set as before.
complete_metadata_writeback() turned every failed write into -EIO.
Pass the errno of the write through and keep -EIO for a short write.
A data request depending on a failed L1/L2 write then ends with
BLK_STS_NOSPC and is delayed and resubmitted like any other write
failing with ENOSPC, as already happens when fsync fails with it.
https://virtuozzo.atlassian.net/browse/VSTOR-148171
Feature: dm-qcow2: block device over QCOW2 files driver
Signed-off-by: Alexander Ivanov <alexander.ivanov at virtuozzo.com>
---
drivers/md/dm-qcow2-map.c | 6 ++++--
drivers/md/dm-qcow2-target.c | 1 -
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/md/dm-qcow2-map.c b/drivers/md/dm-qcow2-map.c
index 4197f7704e18..27ae22495f37 100644
--- a/drivers/md/dm-qcow2-map.c
+++ b/drivers/md/dm-qcow2-map.c
@@ -1357,6 +1357,8 @@ static void clear_writeback_status(struct qcow2 *qcow2, struct md_page *md,
* so here we care about R1R2 only.
*/
md->status |= MD_WRITEBACK_ERROR;
+ if (ret == -ENOSPC && !READ_ONCE(qcow2->tgt->wants_suspend))
+ qcow2_md_make_dirty(qcow2, md, true);
}
if (md->wbd) {
if (likely(ret == 0))
@@ -3864,9 +3866,9 @@ static int complete_metadata_writeback(struct qcow2 *qcow2)
md = qio->ext->md;
qvec = qio->data;
ret = qio->ret;
- if (unlikely(ret != PAGE_SIZE))
+ if (unlikely(ret >= 0 && ret != PAGE_SIZE))
ret = -EIO;
- else
+ else if (ret == PAGE_SIZE)
ret = fsync_ret;
do_md_page_write_complete(ret, qcow2, md);
diff --git a/drivers/md/dm-qcow2-target.c b/drivers/md/dm-qcow2-target.c
index 6824d95193ae..1b7a75239291 100644
--- a/drivers/md/dm-qcow2-target.c
+++ b/drivers/md/dm-qcow2-target.c
@@ -190,7 +190,6 @@ void qcow2_flush_deferred_activity(struct qcow2_target *tgt, struct qcow2 *qcow2
for (node = rb_first(&qcow2->md_pages);
node; node = rb_next(node)) {
md = rb_entry(node, struct md_page, node);
- /* FIXME: call md_make_dirty() and try once again? */
if (md->status & MD_WRITEBACK_ERROR) {
QC_ERR(tgt->ti, "Failed to write dirty pages");
tgt->md_writeback_error = true;
--
2.53.0
More information about the Devel
mailing list