parse_metadata() is called not only from the main kwork: qcow2_llseek_hole() calls it in process context, in parallel with the kwork. When both miss the same md page, both drop md_pages_lock in submit_read_md_page() and try to insert a new md page. The one that loses the insert gets -EEXIST from qcow2_alloc_and_insert_md_page() and returns it as is: a guest I/O on the kwork side ends with EIO, or lseek(SEEK_DATA/SEEK_HOLE) fails with -EEXIST.
Teach __handle_md_page() to handle -EEXIST by repeating the lookup: the page inserted in parallel is found then, and the qio is either served from it or postponed until its read completes. https://virtuozzo.atlassian.net/browse/VSTOR-95494 Fixes: 412d5a4f7bf1 ("dm/dm-qcow2: add llseek_hole") Feature: dm-qcow2: block device over QCOW2 files driver Signed-off-by: Andrey Zhadchenko <[email protected]> --- v2: say in the message what fails without the patch: the race of qcow2_llseek_hole() with main kwork; added Fixes: tag drivers/md/dm-qcow2-map.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/md/dm-qcow2-map.c b/drivers/md/dm-qcow2-map.c index 34d9d9810f601..21d1c8975af99 100644 --- a/drivers/md/dm-qcow2-map.c +++ b/drivers/md/dm-qcow2-map.c @@ -1594,20 +1594,23 @@ static int submit_read_md_page(struct qcow2 *qcow2, struct qio **qio, /* * This may be called with @qio == NULL, in case of we are * interesting in searching cached in memory md only. - * This is aimed to be called not only from main kwork - * for L1/L2 pages, so all callers looking for L1/L2 - * must care about submit_read_md_page() may return EEXIST. */ static int __handle_md_page(struct qcow2 *qcow2, u64 page_id, struct qio **qio, struct md_page **ret_md) { struct md_page *md; + int ret; lockdep_assert_held(&qcow2->md_pages_lock); +again: md = qcow2_md_page_find_or_postpone(qcow2, page_id, qio); if (!md) { - if (qio && *qio) - return submit_read_md_page(qcow2, qio, page_id); + if (qio && *qio) { + ret = submit_read_md_page(qcow2, qio, page_id); + if (unlikely(ret == -EEXIST)) + goto again; + return ret; + } return 0; } -- 2.43.5 _______________________________________________ Devel mailing list [email protected] https://lists.openvz.org/mailman/listinfo/devel
