[Devel] [PATCH RH8] dm-qcow2: Introduce driver to create block devices over QCOW2 files
Kirill Tkhai
ktkhai at virtuozzo.com
Fri Jul 16 19:19:57 MSK 2021
Driver for attaching QCOW2 files as block devices. It cares
about performance-critical actions like actual IO and
snapshot COW and merge, while complex and fast metadata-related
service actions (e.g., snapshot creation and resize)
are delegated to userspace.
Suspend/resume is a barrier between the driver and userspace.
On suspend the driver brings QCOW2 images in consistent state,
while on resume it re-reads metadata from QCOW2 images.
Userspace proceeds metadata-related service actions, while
device is suspended, and it never does this on running device.
This demarcation allows driver code to be pretty small.
Implemented full support for QCOW2 format: compressed clusters,
internal snapshots, backing files and extended L2 table.
Current limitations: the lowest backing file must be QCOW2
(RAW backing files are not supported), cluster and subcluster
sizes for all backing files in chain must be equal (I'm going
to change this in the future).
Also, implemented backward merge (from top to lower image).
The driver is request based, since this allows to use blk-mq
merging of request. Driver splits requests itself, and every
request (i.e., qio) after splitting fits a single cluster.
(In some cases it is worth to create bigger splits, and this
is a subject of further optimizations).
Example of usage is shown in scripts/qcow2-dm.sh. That script allows
to create/remove device from QCOW2 file/backing files chain.
Signed-off-by: Kirill Tkhai <ktkhai at virtuozzo.com>
---
drivers/md/Kconfig | 17
drivers/md/Makefile | 2
drivers/md/dm-qcow2-cmd.c | 337 +++
drivers/md/dm-qcow2-map.c | 4068 ++++++++++++++++++++++++++++++++++++++++++
drivers/md/dm-qcow2-target.c | 935 ++++++++++
drivers/md/dm-qcow2.h | 360 ++++
scripts/qcow2-dm.sh | 103 +
7 files changed, 5822 insertions(+)
create mode 100644 drivers/md/dm-qcow2-cmd.c
create mode 100644 drivers/md/dm-qcow2-map.c
create mode 100644 drivers/md/dm-qcow2-target.c
create mode 100644 drivers/md/dm-qcow2.h
create mode 100755 scripts/qcow2-dm.sh
diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig
index fc58d19da43f..af1018c5e272 100644
--- a/drivers/md/Kconfig
+++ b/drivers/md/Kconfig
@@ -573,4 +573,21 @@ config DM_ZONED
If unsure, say N.
+config DM_QCOW2
+ tristate "QCOW2 target support"
+ depends on BLK_DEV_DM
+ depends on ZLIB_INFLATE
+ help
+ Driver for attaching QCOW2 files as block devices. It cares
+ about performance-critical actions like actual IO and
+ snapshot COW and merge, while complex and fast metadata-related
+ service actions (e.g., snapshot creation and resize)
+ are delegated to userspace.
+
+ Suspend/resume is a barrier between the driver and userspace.
+ On suspend the driver brings QCOW2 images in consistent state,
+ while on resume it re-reads metadata from QCOW2 images. Thus,
+ userspace proceeds metadata-related service actions, while
+ device is suspended.
+
endif # MD
diff --git a/drivers/md/Makefile b/drivers/md/Makefile
index 7a9b6e85285b..0685b83b7883 100644
--- a/drivers/md/Makefile
+++ b/drivers/md/Makefile
@@ -21,6 +21,7 @@ dm-era-y += dm-era-target.o
ploop-y += dm-ploop-target.o dm-ploop-map.o dm-ploop-cmd.o \
dm-ploop-bat.o
push-backup-y += dm-push-backup.o
+dm-qcow2-y += dm-qcow2-target.o dm-qcow2-map.o dm-qcow2-cmd.o
dm-verity-y += dm-verity-target.o
md-mod-y += md.o md-bitmap.o
raid456-y += raid5.o raid5-cache.o raid5-ppl.o
@@ -69,6 +70,7 @@ obj-$(CONFIG_DM_CACHE_SMQ) += dm-cache-smq.o
obj-$(CONFIG_DM_ERA) += dm-era.o
obj-$(CONFIG_DM_PLOOP) += ploop.o
obj-$(CONFIG_DM_PUSH_BACKUP) += push-backup.o
+obj-$(CONFIG_DM_QCOW2) += dm-qcow2.o
obj-$(CONFIG_DM_LOG_WRITES) += dm-log-writes.o
obj-$(CONFIG_DM_INTEGRITY) += dm-integrity.o
obj-$(CONFIG_DM_ZONED) += dm-zoned.o
diff --git a/drivers/md/dm-qcow2-cmd.c b/drivers/md/dm-qcow2-cmd.c
new file mode 100644
index 000000000000..ee4f4a43ad80
--- /dev/null
+++ b/drivers/md/dm-qcow2-cmd.c
@@ -0,0 +1,337 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2021 Virtuozzo International GmbH. All rights reserved.
+ */
+#include <linux/device-mapper.h>
+#include <linux/sched/signal.h>
+#include <linux/file.h>
+#include "dm-qcow2.h"
+
+#define MERGE_QIOS_MAX 64
+
+static int qcow2_get_errors(struct qcow2_target *tgt, char *result,
+ unsigned int maxlen)
+{
+ bool wants_check = qcow2_wants_check(tgt);
+ unsigned int sz = 0;
+ int ret;
+
+ ret = DMEMIT("wants_check=%d\nmd_writeback_error=%d\ntruncate_error=%d\n",
+ wants_check, tgt->md_writeback_error, tgt->truncate_error);
+
+ return ret ? 1 : 0;
+}
+
+int qcow2_inflight_ref_switch(struct qcow2_target *tgt)
+{
+ struct completion *comp = &tgt->inflight_ref_comp;
+ u8 ref_index = tgt->inflight_ref_index;
+
+ tgt->inflight_ref_index = !ref_index;
+
+ percpu_ref_kill(&tgt->inflight_ref[ref_index]);
+ wait_for_completion(comp);
+
+ percpu_ref_reinit(&tgt->inflight_ref[ref_index]);
+ reinit_completion(comp);
+ return 0;
+}
+
+static void service_qio_endio(struct qcow2_target *tgt, struct qio *qio,
+ void *data, blk_status_t status)
+{
+ blk_status_t *status_ptr = data;
+ unsigned long flags;
+
+ if (unlikely(status)) {
+ spin_lock_irqsave(&tgt->err_status_lock, flags);
+ *status_ptr = status;
+ spin_unlock_irqrestore(&tgt->err_status_lock, flags);
+ }
+
+ atomic_dec(&tgt->service_qios);
+ wake_up(&tgt->service_wq);
+}
+
+static int qcow2_service_iter(struct qcow2_target *tgt, struct qcow2 *qcow2,
+ loff_t end, loff_t step, u8 qio_flags)
+{
+ static blk_status_t service_status;
+ struct bio_vec bvec = {0};
+ struct qio *qio;
+ int ret = 0;
+ loff_t pos;
+
+ WRITE_ONCE(service_status, BLK_STS_OK);
+
+ for (pos = 0; pos < end; pos += step) {
+ if (fatal_signal_pending(current)) {
+ ret = -EINTR;
+ break;
+ }
+
+ qio = alloc_qio(tgt->qio_pool, true);
+ if (!qio) {
+ ret = -ENOMEM;
+ break;
+ }
+
+ /* See fake_merge_qio() and fake_l1cow_qio() */
+ init_qio(qio, REQ_OP_WRITE, qcow2);
+ qio->flags |= qio_flags|QIO_FREE_ON_ENDIO_FL;
+ qio->bi_io_vec = &bvec;
+ qio->bi_iter.bi_sector = to_sector(pos);
+ qio->bi_iter.bi_size = 0;
+ qio->bi_iter.bi_idx = 0;
+ qio->bi_iter.bi_bvec_done = 0;
+ qio->endio_cb = service_qio_endio;
+ qio->endio_cb_data = &service_status;
+
+ dispatch_qios(qcow2, qio, NULL);
+ if (atomic_inc_return(&tgt->service_qios) == MERGE_QIOS_MAX) {
+ wait_event(tgt->service_wq,
+ atomic_read(&tgt->service_qios) < MERGE_QIOS_MAX);
+ }
+
+ if (unlikely(READ_ONCE(service_status)))
+ break;
+ }
+
+ wait_event(tgt->service_wq, !atomic_read(&tgt->service_qios));
+ if (!ret) {
+ spin_lock_irq(&tgt->err_status_lock);
+ ret = blk_status_to_errno(service_status);
+ spin_unlock_irq(&tgt->err_status_lock);
+ }
+
+ return ret;
+}
+
+static int qcow2_merge_common(struct qcow2_target *tgt)
+{
+ struct qcow2 *qcow2 = tgt->top, *lower = qcow2->lower;
+ u32 clu_size = qcow2->clu_size;
+ loff_t end = lower->hdr.size;
+
+ return qcow2_service_iter(tgt, qcow2, end, clu_size, QIO_IS_MERGE_FL);
+}
+
+/*
+ * Forward merge is a simple COW simulation in every clu.
+ * After that, all mapped clus from lower delta become
+ * mapped in top delta. Then, userspace may remove lower
+ * delta from the deltas stack (and it also has to update
+ * backing file name in top delta's metadata).
+ */
+static int qcow2_merge_forward(struct qcow2_target *tgt)
+{
+ return -ENOTTY; /* TODO */
+}
+
+static int qcow2_break_l1cow(struct qcow2_target *tgt)
+{
+ struct qcow2 *qcow2 = tgt->top;
+ loff_t end = qcow2->hdr.size;
+ loff_t step = (u64)qcow2->l2_entries * qcow2->clu_size;
+
+ return qcow2_service_iter(tgt, qcow2, end, step, QIO_IS_L1COW_FL);
+}
+
+static void set_backward_merge_in_process(struct qcow2_target *tgt,
+ struct qcow2 *qcow2, bool set)
+{
+ LIST_HEAD(list);
+
+ /*
+ * To avoid race between allocations and COWS
+ * we completely stop queueing qios and wait
+ * for pending qios. Lock is for visability.
+ */
+ spin_lock_irq(&qcow2->deferred_lock);
+ qcow2->pause_submitting_qios = true;
+ spin_unlock_irq(&qcow2->deferred_lock);
+ qcow2_inflight_ref_switch(tgt);
+
+ /* queue is stopped */
+ spin_lock_irq(&qcow2->deferred_lock);
+ WARN_ON_ONCE(qcow2->backward_merge_in_process == set);
+ qcow2->backward_merge_in_process = set;
+ qcow2->pause_submitting_qios = false;
+ list_splice_init(&qcow2->paused_qios, &list);
+ spin_unlock_irq(&qcow2->deferred_lock);
+
+ submit_embedded_qios(tgt, &list);
+}
+
+static int qcow2_merge_backward(struct qcow2_target *tgt)
+{
+ struct qcow2 *qcow2 = tgt->top, *lower = qcow2->lower;
+ int ret, ret2;
+
+ ret = -ENOENT;
+ if (!lower)
+ goto out;
+ ret = -EACCES;
+ if (!(lower->file->f_mode & FMODE_WRITE))
+ goto out;
+ ret = -EOPNOTSUPP;
+ if (qcow2->clu_size != lower->clu_size)
+ goto out;
+ ret = -EBADSLT;
+ if (lower->hdr.size < qcow2->hdr.size)
+ goto out;
+ /*
+ * Break all COW clus at L1 level. Otherwise, later
+ * there would be problems with unusing them:
+ * we'd have to freeze IO going to all data clusters
+ * under every L1 entry related to several snapshots.
+ */
+ ret = qcow2_break_l1cow(tgt);
+ if (ret) {
+ pr_err("dm-qcow2: Can't break L1 COW\n");
+ goto out;
+ }
+
+ ret = qcow2_set_image_file_features(lower, true);
+ if (ret) {
+ pr_err("dm-qcow2: Can't set dirty bit\n");
+ goto out;
+ }
+ set_backward_merge_in_process(tgt, qcow2, true);
+
+ /* Start merge */
+ ret = qcow2_merge_common(tgt);
+ if (ret) {
+ set_backward_merge_in_process(tgt, qcow2, false);
+ ret2 = qcow2_set_image_file_features(lower, false);
+ if (ret2 < 0)
+ pr_err("dm-qcow2: Can't unuse lower (%d)\n", ret2);
+ goto out;
+ }
+ tgt->nr_images--;
+ tgt->top = lower;
+ smp_wmb(); /* Pairs with qcow2_ref_inc() */
+ qcow2_inflight_ref_switch(tgt); /* Pending qios */
+ flush_deferred_activity(tgt, qcow2); /* Delayed md pages */
+ qcow2->lower = NULL;
+
+ ret2 = qcow2_set_image_file_features(qcow2, false);
+ if (ret2 < 0)
+ pr_err("dm-qcow2: Can't unuse merged img (%d)\n", ret2);
+ qcow2_destroy(qcow2);
+out:
+ return ret;
+}
+
+static int qcow2_get_fd(struct qcow2_target *tgt, u32 img_id,
+ char *result, unsigned int maxlen)
+{
+ struct qcow2 *qcow2 = tgt->top;
+ unsigned int sz = 0;
+ struct file *file;
+ int skip, fd;
+
+ lockdep_assert_held(&tgt->ctl_mutex); /* tgt->top */
+
+ skip = tgt->nr_images - 1 - img_id;
+ while (qcow2 && skip > 0) {
+ qcow2 = qcow2->lower;
+ skip--;
+ }
+
+ if (!qcow2 || skip)
+ return -ENOENT;
+
+ fd = get_unused_fd_flags(0);
+ if (fd < 0)
+ return fd;
+
+ if (DMEMIT("%d\n", fd) == 0) {
+ /* Not enough space in @result */
+ put_unused_fd(fd);
+ return 0;
+ }
+
+ file = qcow2->file;
+ fd_install(fd, get_file(file));
+ return 1;
+}
+
+static int qcow2_get_img_name(struct qcow2_target *tgt, u32 img_id,
+ char *result, unsigned int maxlen)
+{
+ struct qcow2 *qcow2 = tgt->top;
+ int skip, ret;
+ char *p;
+
+ lockdep_assert_held(&tgt->ctl_mutex); /* tgt->top */
+
+ skip = tgt->nr_images - 1 - img_id;
+ while (qcow2 && skip > 0) {
+ qcow2 = qcow2->lower;
+ skip--;
+ }
+
+ if (!qcow2 || skip)
+ return -ENOENT;
+
+ p = file_path(qcow2->file, result, maxlen - 1);
+ if (IS_ERR(p)) {
+ if (PTR_ERR(p) == -ENAMETOOLONG)
+ return 0; /* dm should pass bigger buffer */
+ return PTR_ERR(p);
+ }
+
+ ret = strlen(p);
+ memmove(result, p, ret);
+ result[ret] = 0;
+ return 1;
+}
+
+int qcow2_message(struct dm_target *ti, unsigned int argc, char **argv,
+ char *result, unsigned int maxlen)
+{
+ struct qcow2_target *tgt = to_qcow2_target(ti);
+ int ret = -EPERM;
+ u32 val;
+
+ if (!capable(CAP_SYS_ADMIN))
+ goto out;
+
+ ret = -EINVAL;
+ if (argc < 1)
+ goto out;
+
+ ret = mutex_lock_killable(&tgt->ctl_mutex);
+ if (ret)
+ goto out;
+
+ if (!strcmp(argv[0], "get_errors")) {
+ ret = qcow2_get_errors(tgt, result, maxlen);
+ } else if (!strcmp(argv[0], "get_img_fd")) {
+ if (argc != 2 || kstrtou32(argv[1], 10, &val)) {
+ ret = -EINVAL;
+ goto unlock;
+ }
+ ret = qcow2_get_fd(tgt, val, result, maxlen);
+ } else if (!strcmp(argv[0], "get_img_name")) {
+ if (argc != 2 || kstrtou32(argv[1], 10, &val)) {
+ ret = -EINVAL;
+ goto unlock;
+ }
+ ret = qcow2_get_img_name(tgt, val, result, maxlen);
+ } else if (!tgt->service_operations_allowed) {
+ ret = -EBUSY; /* Suspended */
+ /* Service operations goes below: */
+ } else if (!strcmp(argv[0], "merge_forward")) {
+ ret = qcow2_merge_forward(tgt);
+ } else if (!strcmp(argv[0], "merge_backward")) {
+ ret = qcow2_merge_backward(tgt);
+ } else {
+ ret = -ENOTTY;
+ }
+unlock:
+ mutex_unlock(&tgt->ctl_mutex);
+out:
+ return ret;
+}
diff --git a/drivers/md/dm-qcow2-map.c b/drivers/md/dm-qcow2-map.c
new file mode 100644
index 000000000000..133d74bf0b33
--- /dev/null
+++ b/drivers/md/dm-qcow2-map.c
@@ -0,0 +1,4068 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2021 Virtuozzo International GmbH. All rights reserved.
+ */
+#include <linux/spinlock.h>
+#include <linux/uio.h>
+#include <linux/fs.h>
+#include <uapi/linux/falloc.h>
+#include <linux/blk-mq.h>
+#include <linux/zlib.h>
+
+#include "dm.h"
+#include "dm-rq.h"
+#include "dm-qcow2.h"
+
+/* "Exactly one bit" has the same number in L1 and L2 */
+#define LX_REFCOUNT_EXACTLY_ONE (1ULL << 63)
+#define L1_RESERVED_ZERO_MASK 0x7F000000000001FFULL
+#define L2_READS_ALL_ZEROES (1ULL << 0)
+#define L2_COMPRESSED_CLUSTER (1ULL << 62)
+#define L2_RESERVED_ZERO_MASK 0x3F000000000001FEULL
+#define R1_RESERVED_ZERO_MASK 0x1FFULL
+
+#define qcow2_for_each_bvec(iter, bv, start_iter, from_bv) \
+ for (iter = start_iter; \
+ iter.bi_size && ((bv = mp_bvec_iter_bvec(from_bv, iter)), 1); \
+ bvec_iter_advance(from_bv, &iter, bv.bv_len))
+
+struct qcow2_map_item {
+ /*
+ * Index in clu and index in page.
+ * For L1, L2 and R1 is measured in u64 (even if extended L2).
+ * For R2 is measured in R2 size (may refer to the middle of byte).
+ */
+ u32 index;
+ u32 index_in_page;
+ u64 page_id;
+ struct md_page *md;
+};
+
+struct qcow2_map {
+ struct qcow2_map_item l1, l2;
+ struct qcow2_map_item r1, r2;
+#define L1_LEVEL (1 << 0)
+#define L2_LEVEL (1 << 1)
+ u8 level; /* Cached levels */
+ /* L2 entry has "reads all zeroes", and refers to prealloced block */
+ bool prealloced:1;
+ bool compressed:1;
+ bool clu_is_cow:1;
+ bool all_zeroes:1;
+ /*
+ * DATA clu is allocated (the same time "all zeroes
+ * read" or "sublu is not allocated" may be set).
+ */
+ bool data_clu_alloced:1;
+ bool backing_file_cow:1;
+
+ u32 compressed_sectors;
+ u32 subclus_mask;
+ /*
+ * Cluster-aligned COW source: clusters containing
+ * compressed sectors or internal snapshot cluster.
+ * Their usage count will be decremented after COW.
+ */
+ loff_t cow_clu_pos;
+ loff_t cow_clu_end;
+
+ u64 ext_l2;
+ u64 data_clu_pos;
+
+ struct qcow2 *qcow2;
+};
+
+struct qcow2_bvec {
+ unsigned int nr_pages;
+ struct bio_vec bvec[0];
+};
+
+static int handle_r1r2_maps(struct qcow2 *qcow2, loff_t pos, struct qio **qio,
+ struct qcow2_map_item *r1, struct qcow2_map_item *r2, bool compressed);
+static int punch_hole(struct file *file, loff_t pos, loff_t len);
+static void handle_cleanup_mask(struct qio *qio);
+static void process_read_qio(struct qcow2 *qcow2, struct qio *qio,
+ struct qcow2_map *map);
+
+static loff_t bytes_off_in_cluster(struct qcow2 *qcow2, struct qio *qio)
+{
+ return CLU_OFF(qcow2, to_bytes(qio->bi_iter.bi_sector));
+}
+
+static loff_t bio_sector_to_file_pos(struct qcow2 *qcow2, struct qio *qio,
+ struct qcow2_map *map)
+{
+ WARN_ON_ONCE(!map->data_clu_pos);
+
+ return map->data_clu_pos + bytes_off_in_cluster(qcow2, qio);
+}
+
+static loff_t compressed_clu_end_pos(loff_t start, sector_t compressed_sectors)
+{
+ if (start % SECTOR_SIZE == 0)
+ compressed_sectors++;
+
+ return start + to_bytes(compressed_sectors);
+}
+
+static u8 qio_subclu_indexes(struct qcow2 *qcow2, struct qio *qio, u8 *end_bit)
+{
+ u64 off = bytes_off_in_cluster(qcow2, qio);
+
+ WARN_ON_ONCE(!qcow2->ext_l2 || !qio->bi_iter.bi_size);
+ *end_bit = (off + qio->bi_iter.bi_size - 1) / qcow2->subclu_size;
+
+ return off / qcow2->subclu_size;
+}
+
+static u32 qio_subclus_mask(struct qcow2 *qcow2, struct qio *qio)
+{
+ u8 start_bit, end_bit;
+ u32 mask = ~0U;
+
+ WARN_ON_ONCE(!qcow2->ext_l2 || !qio->bi_iter.bi_size);
+
+ start_bit = qio_subclu_indexes(qcow2, qio, &end_bit);
+ mask = (mask >> start_bit) << start_bit;
+ mask = (mask << (31 - end_bit)) >> (31 - end_bit);
+
+ return mask;
+}
+
+static u32 next_bit(u32 mask, u32 from)
+{
+ mask >>= from;
+ if (!mask)
+ return 32;
+ return __ffs(mask) + from;
+}
+
+static u32 next_zero_bit(u32 mask, u32 from)
+{
+ return next_bit(~mask, from);
+}
+
+static u8 find_bits_range_from(u32 mask, u8 from, u8 *nr)
+{
+ u8 left, right;
+
+ if (from == 32)
+ return 32;
+ left = next_bit(mask, from);
+ if (left == 32)
+ return 32;
+ right = next_zero_bit(mask, left);
+ *nr = right - left;
+ return left;
+}
+
+static u32 get_bits_range_from(u32 mask, u8 from)
+{
+ u8 nr;
+
+ from = find_bits_range_from(mask, from, &nr);
+ if (from == 32)
+ return 0;
+ return (~(u32)0 >> (32 - nr)) << from;
+}
+
+static u32 get_bits_range_up_to(u32 mask, u8 to)
+{
+ int i, next = 0;
+
+ if (to == 0)
+ return (1 << 0) & mask;
+ if (!(mask << (31 - to) >> (31 - to)))
+ return 0;
+
+ while (next < to) {
+ i = next;
+ next = next_zero_bit(mask, i + 1);
+ }
+
+ mask = (mask >> i) << i; /* i is last prev zero bit */
+ mask = (mask << (31 - to)) >> (31 - to);
+ return mask;
+}
+
+static u64 get_u64_from_page(struct page *page, int index_in_page)
+{
+ u64 *indexes, val;
+
+ indexes = kmap_atomic(page);
+ val = indexes[index_in_page];
+ kunmap_atomic(indexes);
+
+ return val;
+}
+
+static u64 get_u64_from_be_page(struct page *page, int index_in_page)
+{
+ return be64_to_cpu(get_u64_from_page(page, index_in_page));
+}
+
+static void set_u64_to_page(struct page *page, int index_in_page, u64 val)
+{
+ u64 *indexes;
+
+ indexes = kmap_atomic(page);
+ indexes[index_in_page] = val;
+ kunmap_atomic(indexes);
+}
+
+static void set_u64_to_be_page(struct page *page, int index_in_page, u64 val)
+{
+ return set_u64_to_page(page, index_in_page, cpu_to_be64(val));
+}
+
+struct qcow2 *qcow2_ref_inc(struct qcow2_target *tgt, u8 *ref_index)
+{
+ struct percpu_ref *ref;
+ struct qcow2 *qcow2;
+
+ rcu_read_lock();
+ do {
+ *ref_index = tgt->inflight_ref_index;
+ smp_rmb(); /* Pairs with qcow2_merge_backward() */
+ qcow2 = tgt->top;
+ ref = &tgt->inflight_ref[*ref_index];
+ } while (unlikely(!percpu_ref_tryget(ref)));
+ rcu_read_unlock();
+
+ return qcow2;
+}
+
+void qcow2_ref_dec(struct qcow2_target *tgt, u8 ref_index)
+{
+ struct percpu_ref *ref = &tgt->inflight_ref[ref_index];
+
+ percpu_ref_put(ref);
+}
+
+/* Zero @count bytes of @bi_iter pointed @bi_io_vec since @from byte */
+static void zero_fill_iter_bvec(struct bvec_iter *bi_iter, struct bio_vec *bi_io_vec,
+ u32 from, u32 count)
+{
+ struct bvec_iter iter;
+ struct bio_vec bv;
+ u32 bytes;
+
+ qcow2_for_each_bvec(iter, bv, *bi_iter, bi_io_vec) {
+ void *data;
+
+ if (!count)
+ break;
+ if (from >= bv.bv_len) {
+ from -= bv.bv_len;
+ continue;
+ }
+
+ bytes = bv.bv_len - from;
+ if (bytes > count)
+ bytes = count;
+
+ data = kmap(bv.bv_page);
+ memset(data + bv.bv_offset + from, 0, bytes);
+ flush_dcache_page(bv.bv_page);
+ kunmap(bv.bv_page);
+ from = 0;
+ count -= bytes;
+ }
+}
+
+/* Zero @count bytes of @qio->bi_io_vec since @from byte */
+static void zero_fill_qio(struct qio *qio, u32 from, u32 count)
+{
+ zero_fill_iter_bvec(&qio->bi_iter, qio->bi_io_vec, from, count);
+}
+
+static bool maybe_mapped_in_lower_delta(struct qcow2 *qcow2, struct qio *qio)
+{
+ if (!qcow2->lower)
+ return false;
+ return (to_bytes(qio->bi_iter.bi_sector) < qcow2->lower->hdr.size);
+}
+
+/* Shorten tail behind qcow2 max possible size */
+static void shorten_and_zero_qio_tail(struct qcow2 *qcow2, struct qio *qio)
+{
+ loff_t start = to_bytes(qio->bi_iter.bi_sector);
+ loff_t end = start + qio->bi_iter.bi_size;
+ loff_t size = qcow2->hdr.size;
+
+ if (likely(size >= end))
+ return;
+ if (WARN_ON_ONCE(start >= size))
+ return;
+ zero_fill_qio(qio, size - start, end - size);
+ qio->bi_iter.bi_size -= end - size;
+}
+
+static unsigned int qio_nr_segs(struct qio *qio)
+{
+ unsigned int nr_segs = 0;
+ struct bvec_iter iter;
+ struct bio_vec bv;
+
+ qcow2_for_each_bvec(iter, bv, qio->bi_iter, qio->bi_io_vec)
+ nr_segs++;
+
+ return nr_segs;
+}
+
+struct qio *alloc_qio(mempool_t *pool, bool zero)
+{
+ struct qio *qio;
+
+ qio = mempool_alloc(pool, GFP_NOIO);
+ if (qio) {
+ if (zero)
+ memset(qio, 0, sizeof(*qio));
+ }
+ return qio;
+}
+
+void init_qio(struct qio *qio, unsigned int bi_op, struct qcow2 *qcow2)
+{
+ qio->qcow2 = qcow2;
+ qio->queue_list_id = QLIST_DEFERRED;
+ qio->ext = NULL;
+ qio->data = NULL;
+ qio->bi_op = bi_op;
+ qio->bi_io_vec = NULL;
+ qio->flags = 0;
+ qio->ref_index = REF_INDEX_INVALID;
+ atomic_set(&qio->remaining, 1);
+
+ /*
+ * Initially set into BLK_STS_OK, while aio complete,
+ * md write complete, etc rewrite bi_status on error.
+ */
+ qio->bi_status = BLK_STS_OK;
+}
+
+static int alloc_qio_ext(struct qio *qio)
+{
+ if (WARN_ON_ONCE(qio->ext))
+ return -EIO;
+ qio->ext = kzalloc(sizeof(*(qio->ext)), GFP_NOIO);
+ if (!qio->ext)
+ return -ENOMEM;
+ return 0;
+}
+
+static void finalize_qio_ext(struct qio *qio)
+{
+ if (qio->ext) {
+ handle_cleanup_mask(qio);
+ kfree(qio->ext);
+ qio->ext = NULL;
+ }
+}
+
+static void free_qio(struct qio *qio, mempool_t *pool)
+{
+ mempool_free(qio, pool);
+}
+
+static void do_qio_endio(struct qio *qio)
+{
+ struct qcow2 *qcow2 = qio->qcow2;
+ struct qcow2_target *tgt = qcow2->tgt;
+ qcow2_endio_t endio_cb = qio->endio_cb;
+ void *endio_cb_data = qio->endio_cb_data;
+ unsigned int flags = qio->flags;
+ u8 ref_index = qio->ref_index;
+
+ if (!atomic_dec_and_test(&qio->remaining))
+ return;
+
+ qio->ref_index = REF_INDEX_INVALID;
+ /* Note, that this may free qio or its container memory */
+ endio_cb(tgt, qio, endio_cb_data, qio->bi_status);
+
+ if (ref_index < REF_INDEX_INVALID)
+ qcow2_ref_dec(tgt, ref_index);
+ if (flags & QIO_FREE_ON_ENDIO_FL)
+ free_qio(qio, tgt->qio_pool);
+}
+
+static void qio_endio(struct qio *qio)
+{
+ finalize_qio_ext(qio);
+
+ do_qio_endio(qio);
+}
+
+static void dispatch_qio(struct qcow2 *qcow2, struct qio *qio)
+{
+ WARN_ON_ONCE(qcow2 != qio->qcow2 ||
+ qio->queue_list_id >= QLIST_INVALID);
+ lockdep_assert_held(&qcow2->deferred_lock);
+
+ list_add_tail(&qio->link, &qcow2->qios[qio->queue_list_id]);
+}
+
+void dispatch_qios(struct qcow2 *qcow2, struct qio *qio,
+ struct list_head *qio_list)
+{
+ unsigned long flags;
+
+ if (!qio && (!qio_list || list_empty(qio_list)))
+ return;
+
+ spin_lock_irqsave(&qcow2->deferred_lock, flags);
+ if (qio)
+ dispatch_qio(qcow2, qio);
+ if (qio_list) {
+ while ((qio = qio_list_pop(qio_list)) != NULL)
+ dispatch_qio(qcow2, qio);
+ }
+
+ spin_unlock_irqrestore(&qcow2->deferred_lock, flags);
+
+ queue_work(qcow2->tgt->wq, &qcow2->worker);
+}
+
+static void end_qios(struct list_head *qio_list, blk_status_t status)
+{
+ struct qio *qio;
+
+ while ((qio = qio_list_pop(qio_list)) != NULL) {
+ if (status != BLK_STS_OK)
+ qio->bi_status = status;
+ qio_endio(qio);
+ }
+}
+
+static void qio_chain_endio(struct qcow2_target *tgt, struct qio *qio,
+ void *parent_ptr, blk_status_t bi_status)
+{
+ struct qio *parent = parent_ptr;
+
+ if (unlikely(bi_status))
+ parent->bi_status = bi_status;
+
+ do_qio_endio(parent);
+}
+
+static void qio_chain(struct qio *qio, struct qio *parent)
+{
+ WARN_ON(qio->endio_cb_data || qio->endio_cb);
+
+ qio->endio_cb_data = parent;
+ qio->endio_cb = qio_chain_endio;
+ atomic_inc(&parent->remaining);
+}
+
+/* Clone of bio_advance_iter() */
+static void qio_advance(struct qio *qio, unsigned int bytes)
+{
+ struct bvec_iter *iter = &qio->bi_iter;
+
+ iter->bi_sector += bytes >> 9;
+
+ if (op_is_discard(qio->bi_op))
+ iter->bi_size -= bytes;
+ else
+ bvec_iter_advance(qio->bi_io_vec, iter, bytes);
+}
+
+static struct qio *split_and_chain_qio(struct qcow2 *qcow2,
+ struct qio *qio, u32 len)
+{
+ struct qio *split;
+
+ split = alloc_qio(qcow2->tgt->qio_pool, true);
+ if (!split)
+ return NULL;
+
+ init_qio(split, qio->bi_op, qcow2);
+ split->queue_list_id = qio->queue_list_id;
+ split->flags |= QIO_FREE_ON_ENDIO_FL;
+ split->flags |= (qio->flags & QIO_SPLIT_INHERITED_FLAGS);
+ split->bi_io_vec = qio->bi_io_vec;
+ split->bi_iter = qio->bi_iter;
+ split->bi_iter.bi_size = len;
+ split->endio_cb = NULL;
+ split->endio_cb_data = NULL;
+ qio_chain(split, qio);
+ if (len)
+ qio_advance(qio, len);
+ return split;
+}
+
+static int split_qio_to_list(struct qcow2 *qcow2, struct qio *qio,
+ struct list_head *ret_list)
+{
+ u32 clu_size = qcow2->clu_size;
+ struct qio *split;
+ LIST_HEAD(list);
+
+ while (1) {
+ loff_t start = to_bytes(qio->bi_iter.bi_sector);
+ loff_t end = start + qio->bi_iter.bi_size;
+ unsigned int len;
+
+ WARN_ON_ONCE(start == end);
+
+ if (start / clu_size == (end - 1) / clu_size)
+ break;
+ end = round_up(start + 1, clu_size);
+ len = end - start;
+
+ split = split_and_chain_qio(qcow2, qio, len);
+ if (!split)
+ goto err;
+
+ list_add_tail(&split->link, &list);
+ }
+
+ list_splice_tail(&list, ret_list);
+ list_add_tail(&qio->link, ret_list);
+ return 0;
+err:
+ while ((qio = qio_list_pop(&list)) != NULL) {
+ qio->bi_status = BLK_STS_RESOURCE;
+ qio_endio(qio);
+ }
+ return -ENOMEM;
+}
+
+static void perform_zero_read(struct qio *qio, u32 size)
+{
+ zero_fill_qio(qio, 0, size);
+}
+
+static void inc_inflight_md(struct qcow2 *qcow2, struct qio *qio)
+{
+ struct qcow2_target *tgt = qcow2->tgt;
+ struct percpu_ref *ref;
+ u8 ref_index;
+
+ do {
+ ref_index = tgt->inflight_ref_index;
+ ref = &tgt->inflight_ref[ref_index];
+ } while (unlikely(!percpu_ref_tryget_live(ref)));
+
+ qio->ref_index = ref_index;
+}
+
+static void dec_inflight_md(struct qcow2 *qcow2, struct qio *qio)
+{
+ struct qcow2_target *tgt = qcow2->tgt;
+ u8 ref_index = qio->ref_index;
+
+ if (!(WARN_ON_ONCE(ref_index > 1)))
+ percpu_ref_put(&tgt->inflight_ref[ref_index]);
+}
+
+static void inc_wpc_readers(struct md_page *md)
+{
+ atomic_inc(&md->wpc_readers);
+}
+
+static void dec_wpc_readers(struct qcow2 *qcow2, struct md_page *md)
+{
+ LIST_HEAD(wait_list);
+ unsigned long flags;
+ bool last;
+
+ last = atomic_dec_and_lock_irqsave(&md->wpc_readers,
+ &qcow2->md_pages_lock, flags);
+ if (last) {
+ list_splice_tail_init(&md->wpc_readers_wait_list, &wait_list);
+ spin_unlock_irqrestore(&qcow2->md_pages_lock, flags);
+ dispatch_qios(qcow2, NULL, &wait_list);
+ }
+}
+
+static bool delay_if_has_wpc_readers(struct qcow2 *qcow2, struct md_page *md,
+ struct qio **qio)
+{
+ bool ret = false;
+
+ spin_lock_irq(&qcow2->md_pages_lock);
+ if (atomic_read(&md->wpc_readers)) {
+ list_add_tail(&(*qio)->link, &md->wpc_readers_wait_list);
+ *qio = NULL;
+ ret = true;
+ }
+ spin_unlock_irq(&qcow2->md_pages_lock);
+
+ return ret;
+}
+
+static u32 calc_cow_mask(struct qcow2 *qcow2, u64 ext_l2,
+ struct qio *qio, bool wants_backing,
+ bool wants_data, bool wants_zeroes)
+{
+ loff_t start = to_bytes(qio->bi_iter.bi_sector);
+ loff_t end = start + qio->bi_iter.bi_size;
+ u32 mask, subclus_mask, mapped_mask, cow_mask;
+ u8 start_bit, end_bit;
+
+ subclus_mask = cow_mask = 0;
+ if (!qcow2->ext_l2)
+ goto out;
+
+ if (fake_merge_qio(qio) || !op_is_write(qio->bi_op)) {
+ WARN_ON_ONCE(wants_backing);
+ goto continue_mask;
+ }
+
+ WARN_ON_ONCE(start == end);
+ start_bit = qio_subclu_indexes(qcow2, qio, &end_bit);
+ mapped_mask = (u32)ext_l2|(ext_l2 >> 32);
+ subclus_mask = qio_subclus_mask(qcow2, qio);
+
+ if (SUBCLU_OFF(qcow2, start)) {
+ if ((wants_backing && ((1 << start_bit) & ~mapped_mask)) ||
+ (wants_data && ((1 << start_bit) & (u32)ext_l2)) ||
+ (wants_zeroes && ((1 << start_bit) & (ext_l2 >> 32))))
+ cow_mask |= (1 << start_bit);
+ }
+ if (SUBCLU_OFF(qcow2, end)) {
+ if ((wants_backing && ((1 << end_bit) & ~mapped_mask)) ||
+ (wants_data && ((1 << end_bit) & (u32)ext_l2)) ||
+ (wants_zeroes && ((1 << end_bit) & (ext_l2 >> 32))))
+ cow_mask |= (1 << end_bit);
+ }
+
+continue_mask:
+ if (wants_data) {
+ /* Unchanged COW subclus */
+ mask = (u32)ext_l2 & ~subclus_mask;
+ cow_mask |= mask;
+ }
+ if (wants_zeroes) {
+ mask = (ext_l2 >> 32) & ~subclus_mask;
+ cow_mask |= mask;
+ }
+out:
+ return cow_mask;
+}
+
+#define CB_OR_RET(start, end, d_p, d2_p, d3_p) \
+ do { \
+ int __ret = cb(start, end, d_p, d2_p, d3_p); \
+ if (__ret) \
+ return __ret; \
+ } while (0)
+
+static int for_each_cow_interval_ext_l2(struct qio *qio, loff_t start, loff_t end,
+ int (*cb)(loff_t, loff_t, void *, void *, void *),
+ void *d_p, void *d2_p, void *d3_p)
+{
+ loff_t from, to, i_from[2], i_to[2], pos;
+ struct qcow2 *qcow2 = qio->qcow2;
+ struct qio_ext *ext = qio->ext;
+ u32 subclu_size = qcow2->subclu_size;
+ u32 mask, cow_mask = ext->cow_mask;
+ u8 start_bit, i, j, nr, end_bit;
+
+ i_from[0] = i_from[1] = OFFSET_MAX;
+
+ if (fake_merge_qio(qio) || !op_is_write(qio->bi_op))
+ goto iterate;
+
+ start_bit = qio_subclu_indexes(qcow2, qio, &end_bit);
+ /* Firstly, find two intervals near qio boundaries: */
+ if (SUBCLU_OFF(qcow2, start) && ((1 << start_bit) & cow_mask)) {
+ /* Left boundary */
+ pos = round_down(start, subclu_size);
+ if (start_bit != 0 && (cow_mask & (1 << (start_bit - 1)))) {
+ /* Left mapped neighbours */
+ mask = get_bits_range_up_to(cow_mask, start_bit - 1);
+ cow_mask &= ~mask;
+ pos -= hweight32(mask) * subclu_size;
+ }
+ i_from[0] = pos;
+ i_to[0] = start;
+ }
+ if (SUBCLU_OFF(qcow2, end) && ((1 << end_bit) & cow_mask)) {
+ /* Right boundary */
+ pos = round_up(end, subclu_size);
+ if (end_bit != 31 && (cow_mask & (1 << (end_bit + 1)))) {
+ /* Right mapped neighbours */
+ mask = get_bits_range_from(cow_mask, end_bit + 1);
+ cow_mask &= ~mask;
+ pos += hweight32(mask) * subclu_size;
+ }
+ i_from[1] = end;
+ i_to[1] = pos;
+ }
+ cow_mask &= ~((1 << start_bit) | (1 << end_bit));
+
+iterate:
+ /*
+ * Start ordered iteration over unchanged COW subclus
+ * and two above intervals:
+ */
+ if (cow_mask) {
+ pos = round_down(start, qcow2->clu_size);
+ for (i = 0;
+ (i = find_bits_range_from(cow_mask, i, &nr)) < 32;
+ i += nr) {
+ from = pos + (loff_t)i * subclu_size;
+ to = pos + (loff_t)(i + nr) * subclu_size;
+
+ for (j = 0; j < 2; j++) {
+ if (i_from[j] >= from)
+ continue;
+ CB_OR_RET(i_from[j], i_to[j], d_p, d2_p, d3_p);
+ i_from[j] = OFFSET_MAX;
+ }
+ CB_OR_RET(from, to, d_p, d2_p, d3_p);
+ }
+ }
+ /* Iterate boundary intervals, if we haven't done that yet: */
+ for (j = 0; j < 2; j++) {
+ if (i_from[j] != OFFSET_MAX)
+ CB_OR_RET(i_from[j], i_to[j], d_p, d2_p, d3_p);
+ }
+
+ return 0;
+}
+
+/*
+ * This function calls @cb for each interval of COW clu,
+ * which is not rewritten by @qio. E.g., let bi_iter of WRITE
+ * @qio refers to [off + clu_size / 4, off + clu_size / 3],
+ * where off is multiply of clu_size, while ext_l2 is disabled.
+ * Then, @cb will be called twice from inside the function:
+ * 1)@cb(off, off + clu_size / 4, ...)
+ * 2)@cb(off + clu_size / 3, off + clu_size, ...).
+ * ext_l2 case also cares about allocated subclus.
+ *
+ * We use this to allocate a single bio_vec[] array with pages
+ * to accommodate and to read/write only not-rewritable data
+ * from COW clu to new place.
+ */
+static int for_each_cow_interval(struct qio *qio,
+ int (*cb)(loff_t, loff_t, void *, void *, void *),
+ void *d_p, void *d2_p, void *d3_p)
+{
+ loff_t start = to_bytes(qio->bi_iter.bi_sector);
+ loff_t end = start + qio->bi_iter.bi_size;
+ struct qcow2 *qcow2 = qio->qcow2;
+ u32 clu_size = qcow2->clu_size;
+
+ if (!qcow2->ext_l2) {
+ if (fake_merge_qio(qio) || !op_is_write(qio->bi_op)) {
+ return cb(round_down(start, clu_size),
+ round_up(start + 1, clu_size),
+ d_p, d2_p, d3_p);
+ }
+
+ if (CLU_OFF(qcow2, start) != 0)
+ CB_OR_RET(round_down(start, clu_size), start, d_p, d2_p, d3_p);
+ if (CLU_OFF(qcow2, end) != 0)
+ CB_OR_RET(end, round_up(end, clu_size), d_p, d2_p, d3_p);
+ return 0;
+ }
+
+ return for_each_cow_interval_ext_l2(qio, start, end, cb, d_p, d2_p, d3_p);
+}
+#undef CB_OR_RET
+
+static int count_cow_pages(loff_t start, loff_t end, void *nr_pages_p,
+ void *nr_segs_p, void *unused)
+{
+ u32 *nr_pages = nr_pages_p, *nr_segs = nr_segs_p;
+
+ start = round_down(start, PAGE_SIZE);
+ end = round_up(end, PAGE_SIZE);
+
+ *nr_pages += (end - start) / PAGE_SIZE;
+ *nr_segs += 1;
+ return 0;
+}
+
+static struct qcow2_bvec *alloc_qvec_with_data(u32 nr_vecs, void **data, u32 data_sz)
+{
+ struct qcow2_bvec *qvec = NULL;
+ unsigned int size;
+
+ size = sizeof(struct qcow2_bvec) + nr_vecs * sizeof(struct bio_vec);
+ qvec = kzalloc(size + data_sz, GFP_NOIO);
+ if (qvec)
+ qvec->nr_pages = nr_vecs;
+ if (data)
+ *data = (void *)qvec + size;
+ return qvec;
+}
+
+static void free_qvec_with_pages(struct qcow2_bvec *qvec)
+{
+ if (qvec) {
+ while (qvec->nr_pages-- > 0)
+ put_page(qvec->bvec[qvec->nr_pages].bv_page);
+ kfree(qvec);
+ }
+}
+
+static struct qcow2_bvec *alloc_qvec_with_pages(ushort nr_pages)
+{
+ struct qcow2_bvec *qvec;
+ struct bio_vec *bvec;
+ int i;
+
+ qvec = alloc_qvec_with_data(nr_pages, NULL, 0);
+ if (!qvec)
+ return NULL;
+
+ bvec = qvec->bvec;
+ for (i = 0; i < nr_pages; i++) {
+ bvec[i].bv_page = alloc_page(GFP_NOIO);
+ if (!bvec[i].bv_page)
+ goto err;
+ bvec[i].bv_len = PAGE_SIZE;
+ bvec[i].bv_offset = 0;
+ }
+
+ return qvec;
+err:
+ qvec->nr_pages = i;
+ free_qvec_with_pages(qvec);
+ return NULL;
+}
+
+static void free_wbd(struct wb_desc *wbd)
+{
+ if (wbd) {
+ if (wbd->pe_page)
+ put_page(wbd->pe_page);
+ kfree(wbd->changed_indexes);
+ kfree(wbd);
+ }
+}
+
+static struct wb_desc *alloc_wbd(bool needs_prealloced)
+{
+ struct wb_desc *wbd;
+
+ wbd = kzalloc(sizeof(*wbd), GFP_NOIO);
+ if (!wbd)
+ return NULL;
+ wbd->changed_indexes = kzalloc(LX_INDEXES_BYTES, GFP_NOIO);
+ if (!wbd->changed_indexes)
+ goto err;
+ if (needs_prealloced) {
+ wbd->pe_page = alloc_page(GFP_NOIO|__GFP_ZERO);
+ if (!wbd->pe_page)
+ goto err;
+ }
+
+ INIT_LIST_HEAD(&wbd->submitted_list);
+ INIT_LIST_HEAD(&wbd->completed_list);
+ INIT_LIST_HEAD(&wbd->dependent_list);
+ return wbd;
+err:
+ free_wbd(wbd);
+ return NULL;
+}
+
+void slow_wb_timer_fn(struct timer_list *t)
+{
+ struct qcow2 *qcow2 = from_timer(qcow2, t, slow_wb_timer);
+ unsigned long flags;
+ bool queue;
+
+ spin_lock_irqsave(&qcow2->md_pages_lock, flags);
+ queue = !list_empty(&qcow2->slow_wb_batch_list);
+ list_splice_init(&qcow2->slow_wb_batch_list, &qcow2->wb_batch_list);
+ spin_unlock_irqrestore(&qcow2->md_pages_lock, flags);
+
+ if (queue)
+ queue_work(qcow2->tgt->wq, &qcow2->worker);
+}
+
+static bool md_make_dirty(struct qcow2 *qcow2, struct md_page *md, bool is_refs)
+{
+ struct list_head *head;
+ bool new = false;
+
+ head = !is_refs ? &qcow2->wb_batch_list : &qcow2->slow_wb_batch_list;
+
+ /* md->status must be visible for complete handlers */
+ lockdep_assert_held(&qcow2->md_pages_lock);
+
+ if (!(md->status & MD_DIRTY)) {
+ md->status |= MD_DIRTY;
+ list_add_tail(&md->wb_link, head);
+ new = true;
+
+ if (is_refs && !timer_pending(&qcow2->slow_wb_timer))
+ mod_timer(&qcow2->slow_wb_timer,
+ jiffies + WB_TIMEOUT_JI);
+ /* Sanity: 1)only L1L2 have wbd, 2)only R1R2 allow redirtying */
+ WARN_ON(md->wbd && ((md->status & MD_WRITEBACK) || is_refs));
+ }
+ return new;
+}
+
+static u64 get_r2_entry(struct qcow2 *qcow2, struct md_page *md,
+ u32 r2_index_in_page)
+{
+ u32 index, start, tail, bits = qcow2->refblock_bits;
+ u64 entry;
+
+ /* index of u64 qword containing our refcounter */
+ index = r2_index_in_page * bits / 64;
+ entry = get_u64_from_page(md->page, index);
+
+ if (bits == 64)
+ return be64_to_cpu(entry);
+ if (bits == 32)
+ return be32_to_cpu(((u32 *)&entry)[r2_index_in_page % 2]);
+ if (bits == 16)
+ return be16_to_cpu(((u16 *)&entry)[r2_index_in_page % 4]);
+ /*
+ * We want to swab original BE u64 qword on both BE and LE.
+ * For LE it is already done because of get_u64_from_page().
+ * For BE it is made here.
+ */
+ entry = cpu_to_le64(entry);
+ /* Bit start in u64 qword */
+ start = r2_index_in_page * bits % 64;
+ /* Cut tail bits */
+ tail = 64 - bits - start;
+ entry = (entry << tail) >> tail;
+ /* Cut bits before start */
+ entry >>= start;
+ return entry;
+}
+
+static void set_r2_entry(struct qcow2 *qcow2, struct md_page *md,
+ u32 r2_index_in_page, u64 val)
+{
+ u32 index, start, bits = qcow2->refblock_bits;
+ u64 mask, entry;
+
+ /* index of u64 qword containing our refcounter */
+ index = r2_index_in_page * bits / 64;
+
+ if (bits == 64) {
+ entry = cpu_to_be64(val);
+ goto set;
+ }
+
+ entry = get_u64_from_page(md->page, index);
+
+ if (bits == 32) {
+ ((u32 *)&entry)[r2_index_in_page % 2] = cpu_to_be32(val);
+ goto set;
+ }
+ if (bits == 16) {
+ ((u16 *)&entry)[r2_index_in_page % 4] = cpu_to_be16(val);
+ goto set;
+ }
+
+ /* Bit start in u64 qword */
+ start = r2_index_in_page * bits % 64;
+ /* 0b0000...11 mask */
+ mask = (~(u64)0) >> (64 - bits);
+ /* Move to position and swab on BE */
+ mask = cpu_to_le64(mask << start);
+ val = cpu_to_le64(val << start);
+ /* Clear old bits and set new bits */
+ entry &= ~mask;
+ entry |= val;
+set:
+ /* Store to BE page: swab on LE */
+ set_u64_to_page(md->page, index, entry);
+}
+
+static void calc_page_id_and_index(loff_t pos, u64 *page_id, u32 *index_in_page)
+{
+ *page_id = pos >> PAGE_SHIFT;
+ *index_in_page = (pos & ~PAGE_MASK) / sizeof(u64);
+}
+
+static int calc_cluster_map(struct qcow2 *qcow2, struct qio *qio,
+ struct qcow2_map *map)
+{
+ loff_t start = to_bytes(qio->bi_iter.bi_sector);
+ loff_t end = start + qio->bi_iter.bi_size;
+ u32 clu_size = qcow2->clu_size;
+ loff_t pos;
+
+ if (unlikely(start / clu_size != (end - 1) / clu_size &&
+ (start != end || (!fake_merge_qio(qio) &&
+ !fake_l1cow_qio(qio)))))
+ goto eio;
+ if (unlikely(end > qcow2->hdr.size))
+ goto eio;
+
+ map->l2.index = (start / clu_size) % qcow2->l2_entries;
+ map->l1.index = (start / clu_size) / qcow2->l2_entries;
+
+ if (qcow2->ext_l2) {
+ /*
+ * Unlike proposed in qcow2 documentation,
+ * we measure index in sizeof(u64).
+ */
+ map->l2.index *= 2;
+ }
+
+ if (unlikely(map->l1.index >= qcow2->hdr.l1_size))
+ goto eio;
+
+ pos = qcow2->hdr.l1_table_offset + map->l1.index * sizeof(u64);
+ calc_page_id_and_index(pos, &map->l1.page_id, &map->l1.index_in_page);
+ /* TODO: we can count l2.index_in_page. See calc_refcounters_map() */
+ return 0;
+eio:
+ WARN_ONCE(1, "qio(%lld,%lld, 0x%x), map(%u, %u)\n", start, end,
+ qio->bi_op, map->l1.index, map->l2.index);
+ return -EIO;
+}
+
+static int calc_refcounters_map(struct qcow2 *qcow2, loff_t pos,
+ struct qcow2_map_item *r1,
+ struct qcow2_map_item *r2)
+{
+ u32 refblock_entries = qcow2->refblock_entries;
+ u32 clus = qcow2->hdr.refcount_table_clusters;
+ u32 bits = qcow2->refblock_bits;
+ u32 clu_size = qcow2->clu_size;
+
+ r2->index = (pos / clu_size) % refblock_entries;
+ r1->index = (pos / clu_size) / refblock_entries;
+
+ if (unlikely((u64)r1->index * sizeof(u64) >= (u64)clus * clu_size))
+ goto eio;
+
+ pos = qcow2->hdr.refcount_table_offset + r1->index * sizeof(u64);
+ calc_page_id_and_index(pos, &r1->page_id, &r1->index_in_page);
+ /*
+ * Since cluster is multiply of PAGE_SIZE, we may count index_in_page.
+ * Note, this may be half/quarter of byte (the same as r2->index).
+ */
+ r2->index_in_page = r2->index % (PAGE_SIZE * 8 / bits);
+ return 0;
+eio:
+ WARN_ONCE(1, "ref(%u, %u)\n", r1->index, r2->index);
+ return -EIO;
+}
+
+static int calc_r2_page_id(struct qcow2 *qcow2, struct qcow2_map_item *r1,
+ struct qcow2_map_item *r2)
+{
+ u64 entry = get_u64_from_be_page(r1->md->page, r1->index_in_page);
+ u32 bits = qcow2->refblock_bits;
+ loff_t pos;
+
+ if (WARN_ON_ONCE((entry & R1_RESERVED_ZERO_MASK) ||
+ (CLU_OFF(qcow2, entry) != 0)))
+ return -EIO;
+
+ /* The corresponding refcount block has not yet been allocated */
+ if (!entry)
+ return -ENOENT;
+
+ pos = entry + r2->index * bits / 8;
+ r2->page_id = pos >> PAGE_SHIFT;
+ return 0;
+}
+
+/* Whether L1 or L2 md is under writeback and @index is allocating */
+static bool dirty_or_writeback(struct qcow2 *qcow2, struct md_page *md,
+ u32 index_in_page)
+{
+ bool ret = false;
+
+ lockdep_assert_held(&qcow2->md_pages_lock);
+ if (md->wbd && (md->status & (MD_DIRTY|MD_WRITEBACK)))
+ ret = test_bit(index_in_page, md->wbd->changed_indexes);
+ return ret;
+}
+
+static bool delay_if_dirty(struct qcow2 *qcow2, struct md_page *md,
+ u32 index_in_page, struct qio **qio)
+{
+ bool ret = false;
+
+ lockdep_assert_held(&qcow2->md_pages_lock);
+ if (md->status & MD_DIRTY) {
+ ret = test_bit(index_in_page, md->wbd->changed_indexes);
+ if (ret) {
+ list_add_tail(&(*qio)->link, &md->wait_list);
+ *qio = NULL;
+ }
+ }
+ return ret;
+}
+
+/*
+ * This is helper for parse_metadata().
+ * In case of writeback is in progress, it's prohibited to:
+ * 1)write to indexes, which are under writeback;
+ * 2)add completely new allocations;
+ * 3)reuse preallocations (they force L2 entry update).
+ * I.e., we may write only to clusters, whose indexes are
+ * already written in image file.
+ */
+static bool __delay_if_writeback(struct qcow2 *qcow2, struct md_page *md,
+ u32 index_in_page, struct qio **qio,
+ bool wants_allocation)
+{
+ bool ret = false;
+
+ lockdep_assert_held(&qcow2->md_pages_lock);
+
+ if ((md->status & MD_WRITEBACK) &&
+ (wants_allocation ||
+ test_bit(index_in_page, md->wbd->changed_indexes))) {
+ list_add_tail(&(*qio)->link, &md->wait_list);
+ *qio = NULL;
+ ret = true;
+ }
+ return ret;
+}
+
+static bool delay_if_writeback(struct qcow2 *qcow2, struct md_page *md,
+ u32 index_in_page, struct qio **qio,
+ bool wants_allocation)
+{
+ bool ret;
+
+ spin_lock_irq(&qcow2->md_pages_lock);
+ ret = __delay_if_writeback(qcow2, md, index_in_page,
+ qio, wants_allocation);
+ spin_unlock_irq(&qcow2->md_pages_lock);
+
+ return ret;
+}
+
+static bool delay_if_wpc_readers_locked(struct qcow2 *qcow2, struct md_page *md,
+ struct qio **qio)
+{
+ bool ret = false;
+
+ lockdep_assert_held(&qcow2->md_pages_lock);
+ if (md->wpc_noread_count) {
+ list_add_tail(&(*qio)->link, &md->wait_list);
+ *qio = NULL;
+ ret = true;
+ }
+
+ return ret;
+}
+
+static void md_index_set_locked(struct qcow2 *qcow2, struct md_page *md,
+ u32 index_in_page)
+{
+ lockdep_assert_held(&qcow2->md_pages_lock);
+ WARN_ON_ONCE(test_bit(index_in_page, md->lockd->indexes));
+ set_bit(index_in_page, md->lockd->indexes);
+ md->lockd->nr++;
+}
+
+static bool delay_if_locked(struct qcow2 *qcow2, struct md_page *md,
+ u32 index_in_page, struct qio **qio)
+{
+ bool ret = false;
+
+ lockdep_assert_held(&qcow2->md_pages_lock);
+ if (md->lockd && test_bit(index_in_page, md->lockd->indexes)) {
+ list_add_tail(&(*qio)->link, &md->wait_list);
+ *qio = NULL;
+ ret = true;
+ }
+
+ return ret;
+}
+
+
+/*
+ * Note, that we delay R1 and R2 pages writeback. In case of power down,
+ * they can easily be restored from L1, L2 and other stable metadata.
+ */
+static void mark_cluster_used(struct qcow2 *qcow2, struct md_page *r2_md,
+ u32 r2_index_in_page)
+{
+ WARN_ON_ONCE(READ_ONCE(r2_md->status) & MD_WRITEBACK);
+
+ spin_lock_irq(&qcow2->md_pages_lock);
+ WARN_ON_ONCE(get_r2_entry(qcow2, r2_md, r2_index_in_page));
+ set_r2_entry(qcow2, r2_md, r2_index_in_page, 1);
+ WARN_ON_ONCE(get_r2_entry(qcow2, r2_md, r2_index_in_page) != 1);
+
+ md_make_dirty(qcow2, r2_md, true);
+ spin_unlock_irq(&qcow2->md_pages_lock);
+}
+
+static void mark_cluster_unused(struct qcow2 *qcow2, struct md_page *r2_md,
+ u32 r2_index_in_page, loff_t pos)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&qcow2->md_pages_lock, flags);
+ WARN_ON_ONCE(get_r2_entry(qcow2, r2_md, r2_index_in_page) != 1);
+ set_r2_entry(qcow2, r2_md, r2_index_in_page, 0);
+ WARN_ON_ONCE(get_r2_entry(qcow2, r2_md, r2_index_in_page) != 0);
+
+ md_make_dirty(qcow2, r2_md, true);
+ if (qcow2->free_cluster_search_pos > pos)
+ qcow2->free_cluster_search_pos = pos;
+ spin_unlock_irqrestore(&qcow2->md_pages_lock, flags);
+}
+
+static void dec_cluster_usage(struct qcow2 *qcow2, struct md_page *r2_md,
+ u32 r2_index_in_page, loff_t pos)
+{
+ unsigned long flags;
+ u64 val;
+
+ spin_lock_irqsave(&qcow2->md_pages_lock, flags);
+ val = get_r2_entry(qcow2, r2_md, r2_index_in_page);
+ WARN_ON_ONCE(val < 1);
+ val--;
+ set_r2_entry(qcow2, r2_md, r2_index_in_page, val);
+ WARN_ON_ONCE(get_r2_entry(qcow2, r2_md, r2_index_in_page) != val);
+
+ md_make_dirty(qcow2, r2_md, true);
+ if (!val && qcow2->free_cluster_search_pos > pos)
+ qcow2->free_cluster_search_pos = pos;
+ spin_unlock_irqrestore(&qcow2->md_pages_lock, flags);
+}
+
+
+static void do_md_page_read_complete(int ret, struct qcow2 *qcow2,
+ struct md_page *md)
+{
+ LIST_HEAD(wait_list);
+ unsigned long flags;
+
+ spin_lock_irqsave(&qcow2->md_pages_lock, flags);
+ if (ret < 0)
+ md_page_erase(qcow2, md);
+ else
+ md->status |= MD_UPTODATE;
+
+ list_splice_tail_init(&md->wait_list, &wait_list);
+ spin_unlock_irqrestore(&qcow2->md_pages_lock, flags);
+
+ if (ret < 0) {
+ free_md_page(md);
+ end_qios(&wait_list, errno_to_blk_status(ret));
+ } else {
+ dispatch_qios(qcow2, NULL, &wait_list);
+ }
+}
+
+/* Be careful with dirty_or_writeback()/etc! Check races. */
+static void revert_clusters_alloc(struct qcow2 *qcow2, struct wb_desc *wbd)
+{
+ struct qcow2_map_item r1, r2;
+ struct page *pe_page;
+ u64 pos, old;
+ int i, ret;
+
+ lockdep_assert_held(&qcow2->md_pages_lock);
+ for_each_set_bit(i, wbd->changed_indexes, LX_INDEXES_PER_PAGE) {
+ pos = get_u64_from_be_page(wbd->md->page, i);
+ WARN_ON_ONCE(!(pos & ~LX_REFCOUNT_EXACTLY_ONE) ||
+ !(pos & LX_REFCOUNT_EXACTLY_ONE));
+
+ /* Here we restore prealloced and compressed clu mappings */
+ pe_page = wbd->pe_page;
+ if (pe_page) { /* Only L2 has this. */
+ old = get_u64_from_be_page(pe_page, i);
+ if (old != 0) {
+ set_u64_to_be_page(wbd->md->page, i, old);
+ continue; /* Avoid mark_cluster_unused() */
+ }
+ }
+
+ set_u64_to_be_page(wbd->md->page, i, 0);
+ spin_unlock(&qcow2->md_pages_lock);
+ pos &= ~LX_REFCOUNT_EXACTLY_ONE;
+
+ /*
+ * R1/R2 should be cached, since we was able
+ * to submit cluster allocation.
+ */
+ ret = handle_r1r2_maps(qcow2, pos, NULL, &r1, &r2, false);
+ if (WARN_ON_ONCE(ret <= 0))
+ continue;
+
+ mark_cluster_unused(qcow2, r2.md, r2.index_in_page, pos);
+ spin_lock(&qcow2->md_pages_lock);
+ }
+}
+
+static void clear_writeback_status(struct qcow2 *qcow2, struct md_page *md,
+ int ret, struct list_head *wait_list,
+ struct list_head *end_list)
+{
+ lockdep_assert_held(&qcow2->md_pages_lock);
+
+ md->status &= ~(MD_WRITEBACK|MD_WRITEBACK_ERROR);
+ list_splice_init(&md->wait_list, wait_list);
+ if (ret && !md->wbd) {
+ /*
+ * L1L2 updates can do safe revert,
+ * so here we care about R1R2 only.
+ */
+ md->status |= MD_WRITEBACK_ERROR;
+ }
+ if (md->wbd) {
+ if (likely(ret == 0))
+ list_splice_init(&md->wbd->dependent_list, wait_list);
+ else
+ list_splice_init(&md->wbd->dependent_list, end_list);
+ md->wbd = NULL;
+ }
+}
+
+static void complete_wbd(struct qcow2 *qcow2, struct wb_desc *wbd)
+{
+ if (unlikely(wbd->ret < 0)) {
+ LIST_HEAD(wait_list);
+ LIST_HEAD(end_list);
+ unsigned long flags;
+
+ spin_lock_irqsave(&qcow2->md_pages_lock, flags);
+ revert_clusters_alloc(qcow2, wbd);
+ clear_writeback_status(qcow2, wbd->md, wbd->ret,
+ &wait_list, &end_list);
+ spin_unlock_irqrestore(&qcow2->md_pages_lock, flags);
+
+ dispatch_qios(qcow2, NULL, &wait_list);
+ end_qios(&end_list, errno_to_blk_status(wbd->ret));
+ }
+ free_wbd(wbd);
+}
+
+static void do_md_page_write_complete(int ret, struct qcow2 *qcow2,
+ struct md_page *md)
+{
+ struct wb_desc *wbd = NULL;
+ bool finalize_wbd = false;
+ LIST_HEAD(wait_list);
+ LIST_HEAD(end_list);
+
+ spin_lock_irq(&qcow2->md_pages_lock);
+ WARN_ON_ONCE(!(md->status & MD_WRITEBACK));
+ wbd = md->wbd;
+ if (wbd) {
+ wbd->completed = true;
+ wbd->ret = ret;
+ list_splice_init(&wbd->completed_list, &end_list);
+ /*
+ * In case of this md writeback completed before
+ * parallel data qios, wbd is finalized by last
+ * completed data qio.
+ */
+ finalize_wbd = list_empty(&wbd->submitted_list);
+ /*
+ * We can finish wb only in case of success.
+ * Otherwise this is done in finalize_wbd()
+ * after data qios stopped use wbd clusters
+ * and clusters allocations reverted.
+ */
+ if (likely(ret == 0)) {
+ clear_writeback_status(qcow2, md, ret,
+ &wait_list, &end_list);
+ }
+ /* FIXME: we should reread md after write fail */
+ } else {
+ clear_writeback_status(qcow2, md, ret, &wait_list, &end_list);
+ }
+ spin_unlock_irq(&qcow2->md_pages_lock);
+
+ end_qios(&end_list, errno_to_blk_status(ret));
+ dispatch_qios(qcow2, NULL, &wait_list);
+ if (finalize_wbd)
+ complete_wbd(qcow2, wbd);
+}
+
+static void md_page_read_complete(struct qio *qio)
+{
+ struct qcow2_bvec *qvec = qio->data;
+ struct md_page *md = qio->ext->md;
+ struct qcow2 *qcow2 = qio->qcow2;
+ int ret = qio->ret;
+ mode_t mode;
+
+ BUG_ON(qvec->bvec[0].bv_page != md->page);
+
+ if (unlikely(ret != PAGE_SIZE && ret > 0)) {
+ /* Read near EOF? See qcow2_attach_file() */
+ loff_t pos = (md->id << PAGE_SHIFT) + ret;
+
+ mode = qcow2->file->f_mode;
+ if (pos == qcow2->file_size && !(mode & FMODE_WRITE)) {
+ zero_fill_page_from(md->page, ret);
+ ret = PAGE_SIZE;
+ }
+ }
+ if (unlikely(ret != PAGE_SIZE))
+ ret = -EIO;
+ else
+ ret = 0;
+
+ do_md_page_read_complete(ret, qcow2, md);
+ dec_inflight_md(qcow2, qio);
+ kfree(qvec); /* qio and ext are tail bytes after qvec */
+}
+
+static void md_page_write_complete(struct qio *qio)
+{
+ struct qcow2 *qcow2 = qio->qcow2;
+ unsigned long flags;
+
+ qio->queue_list_id = QLIST_COMPLETED_WB;
+ spin_lock_irqsave(&qcow2->deferred_lock, flags);
+ list_add_tail(&qio->link, &qcow2->qios[QLIST_COMPLETED_WB]);
+ spin_unlock_irqrestore(&qcow2->deferred_lock, flags);
+ queue_work(qcow2->tgt->wq, &qcow2->fsync_worker);
+}
+
+static void submit_rw_md_page(unsigned int rw, struct qcow2 *qcow2,
+ struct md_page *md)
+{
+ loff_t pos = md->id << PAGE_SHIFT;
+ struct qcow2_bvec *qvec = NULL;
+ struct bio_vec *bvec;
+ struct iov_iter iter;
+ int size, err = 0;
+ struct qio *qio;
+
+ if (pos > qcow2->file_size) {
+ pr_err_once("qcow2: rw=%x pos=%lld behind EOF %lld\n",
+ rw, pos, qcow2->file_size);
+ err = -EIO;
+ } else {
+ /*
+ * Note, this is fake qio, and qio_endio()
+ * can't be called on it!
+ */
+ size = sizeof(struct qio) + sizeof(struct qio_ext);
+ qvec = alloc_qvec_with_data(1, (void *)&qio, size);
+ if (!qvec)
+ err = -ENOMEM;
+ }
+ if (err) {
+ if (rw == READ)
+ do_md_page_read_complete(err, qcow2, md);
+ else
+ do_md_page_write_complete(err, qcow2, md);
+ return;
+ }
+
+ init_qio(qio, rw == READ ? REQ_OP_READ : REQ_OP_WRITE, qcow2);
+ qio->ext = (void *)qio + sizeof(*qio);
+ qio->ext->md = md;
+ qio->data = qvec;
+ if (rw == READ)
+ qio->complete = md_page_read_complete;
+ else
+ qio->complete = md_page_write_complete;
+
+ bvec = &qvec->bvec[0];
+ bvec->bv_page = md->page;
+ bvec->bv_len = PAGE_SIZE;
+ bvec->bv_offset = 0;
+
+ iov_iter_bvec(&iter, rw, bvec, 1, PAGE_SIZE);
+
+ inc_inflight_md(qcow2, qio);
+ call_rw_iter(qcow2->file, pos, rw, &iter, qio);
+}
+
+static int submit_read_md_page(struct qcow2 *qcow2, struct qio **qio,
+ u64 page_id)
+{
+ struct md_page *md;
+ int ret;
+
+ ret = alloc_and_insert_md_page(qcow2, page_id, &md);
+ if (ret < 0) {
+ pr_err("Can't alloc: ret=%d, page_id=%llu\n", ret, page_id);
+ return -EIO;
+ }
+
+ spin_lock_irq(&qcow2->md_pages_lock);
+ list_add_tail(&(*qio)->link, &md->wait_list);
+ spin_unlock_irq(&qcow2->md_pages_lock);
+ *qio = NULL;
+
+ submit_rw_md_page(READ, qcow2, md);
+ return 0;
+}
+
+/*
+ * This may be called with @qio == NULL, in case of we are
+ * interesting in searching cached in memory md only.
+ */
+static int handle_md_page(struct qcow2 *qcow2, u64 page_id,
+ struct qio **qio, struct md_page **ret_md)
+{
+ struct md_page *md;
+
+ md = md_page_find_or_postpone(qcow2, page_id, qio);
+ if (!md) {
+ if (qio && *qio)
+ return submit_read_md_page(qcow2, qio, page_id);
+ return 0;
+ }
+
+ *ret_md = md;
+ return 1;
+}
+
+static u32 qio_subclus_covered_start_size(struct qcow2 *qcow2,
+ struct qio *qio,
+ u32 subclus_mask)
+{
+ u8 start_bit, end_bit, bit;
+
+ start_bit = qio_subclu_indexes(qcow2, qio, &end_bit);
+
+ bit = next_zero_bit(subclus_mask, start_bit);
+ if (bit == start_bit)
+ return 0;
+ if (bit > end_bit)
+ return qio->bi_iter.bi_size;
+ return bit * qcow2->subclu_size - bytes_off_in_cluster(qcow2, qio);
+}
+
+static u32 qio_unmapped_size(struct qcow2 *qcow2, struct qio *qio,
+ struct qcow2_map *map)
+{
+ u32 mapped_mask = (map->ext_l2 >> 32) | (u32)map->ext_l2;
+
+ if (!qcow2->ext_l2) {
+ if (!map->data_clu_alloced && !map->all_zeroes)
+ return qio->bi_iter.bi_size;
+ return 0;
+ }
+
+ return qio_subclus_covered_start_size(qcow2, qio, ~mapped_mask);
+}
+
+static u32 qio_mapped_not_zeroes_size(struct qcow2 *qcow2, struct qio *qio,
+ struct qcow2_map *map)
+{
+ if (!qcow2->ext_l2) {
+ if (map->data_clu_alloced && !map->all_zeroes)
+ return qio->bi_iter.bi_size;
+ return 0;
+ }
+
+ return qio_subclus_covered_start_size(qcow2, qio, (u32)map->ext_l2);
+}
+static u32 qio_all_zeroes_size(struct qcow2 *qcow2, struct qio *qio,
+ struct qcow2_map *map)
+{
+ if (!qcow2->ext_l2) {
+ if (map->all_zeroes)
+ return qio->bi_iter.bi_size;
+ return 0;
+ }
+
+ return qio_subclus_covered_start_size(qcow2, qio, map->ext_l2 >> 32);
+}
+
+static bool qio_border_is_inside_unmapped_unit(struct qcow2 *qcow2,
+ struct qio *qio,
+ struct qcow2_map *map)
+{
+ u64 start_off, end_off;
+ u8 start_bit, end_bit;
+ u32 mapped_mask;
+ bool ret;
+
+ if (WARN_ON_ONCE(!(map->level & L2_LEVEL)))
+ return false;
+
+ if (qio->bi_iter.bi_size == qcow2->clu_size)
+ return false;
+
+ if (!qcow2->ext_l2)
+ return !map->data_clu_alloced && !map->all_zeroes;
+
+ start_bit = qio_subclu_indexes(qcow2, qio, &end_bit);
+ start_off = bytes_off_in_cluster(qcow2, qio);
+ end_off = start_off + qio->bi_iter.bi_size;
+ mapped_mask = (u32)map->ext_l2 | (map->ext_l2 >> 32);
+
+ ret = SUBCLU_OFF(qcow2, start_off) != 0 && ((1 << start_bit) & ~mapped_mask);
+ ret |= SUBCLU_OFF(qcow2, end_off) != 0 && ((1 << end_bit) & ~mapped_mask);
+ return ret;
+}
+
+static bool qio_is_fully_alloced(struct qcow2 *qcow2, struct qio *qio,
+ struct qcow2_map *map)
+{
+ u32 subclus_mask, alloced_mask;
+
+ if (!(map->level & L2_LEVEL))
+ return false;
+
+ if (!qcow2->ext_l2)
+ return map->data_clu_alloced && !map->all_zeroes;
+
+ subclus_mask = qio_subclus_mask(qcow2, qio);
+ alloced_mask = (u32)map->ext_l2;
+
+ return !(subclus_mask & ~alloced_mask);
+}
+
+static loff_t parse_l1(struct qcow2 *qcow2, struct qcow2_map *map,
+ struct qio **qio, bool write)
+
+{
+ struct qcow2_map_item *l1 = &map->l1;
+ bool wants_alloc, exactly_one;
+ u64 pos, entry;
+ loff_t ret;
+
+ spin_lock_irq(&qcow2->md_pages_lock);
+ entry = get_u64_from_be_page(l1->md->page, l1->index_in_page);
+ exactly_one = entry & LX_REFCOUNT_EXACTLY_ONE;
+ pos = entry & ~LX_REFCOUNT_EXACTLY_ONE;
+
+ ret = -EIO;
+ if (WARN_ON_ONCE(entry & L1_RESERVED_ZERO_MASK))
+ goto out;
+ if (WARN_ON_ONCE(CLU_OFF(qcow2, pos) != 0))
+ goto out;
+ if (WARN_ON_ONCE(pos && !qcow2->hdr.nb_snapshots && !exactly_one))
+ goto out;
+
+ if (pos && !exactly_one) {
+ map->clu_is_cow = true;
+ map->cow_clu_pos = pos;
+ map->cow_clu_end = pos + qcow2->clu_size;
+ }
+
+ ret = 0;
+ if (delay_if_locked(qcow2, l1->md, l1->index_in_page, qio))
+ goto out;
+ wants_alloc = write && (pos == 0 || map->clu_is_cow);
+ if (__delay_if_writeback(qcow2, l1->md, l1->index_in_page, qio, wants_alloc))
+ goto out;
+ if (delay_if_dirty(qcow2, l1->md, l1->index_in_page, qio))
+ goto out;
+ if (write && map->clu_is_cow)
+ goto out; /* Avoid to return pos */
+
+ ret = pos;
+out:
+ spin_unlock_irq(&qcow2->md_pages_lock);
+ return ret;
+}
+
+static int parse_compressed_l2(struct qcow2 *qcow2, struct qcow2_map *map,
+ struct qio **qio, bool write, u64 entry)
+{
+ u8 offset_bits = 62 - (qcow2->hdr.cluster_bits - 8);
+ struct qcow2_map_item *l2 = &map->l2;
+ u64 pos, end;
+
+ /* Even for write: it reads compressed clu firstly */
+ if (delay_if_wpc_readers_locked(qcow2, l2->md, qio))
+ return 0;
+ if (WARN_ON_ONCE(dirty_or_writeback(qcow2, l2->md, l2->index_in_page)))
+ return -EIO;
+
+ map->compressed = true;
+ pos = entry << (64 - offset_bits) >> (64 - offset_bits);
+ map->compressed_sectors = entry >> offset_bits;
+ end = compressed_clu_end_pos(pos, map->compressed_sectors);
+
+ map->clu_is_cow = true;
+ /* @pos may point to middle of cluster, so this may take 2 clusters */
+ map->cow_clu_pos = round_down(pos, qcow2->clu_size);
+ map->cow_clu_end = round_up(end, qcow2->clu_size);
+ map->ext_l2 = ~(u32)0;
+
+ if (WARN_ON_ONCE((pos >> 56) != 0 || !entry ||
+ /* This would be very strange compression */
+ end - pos > qcow2->clu_size))
+ return -EIO;
+ map->data_clu_alloced = true;
+ return pos;
+}
+
+static loff_t parse_l2(struct qcow2 *qcow2, struct qcow2_map *map,
+ struct qio **qio, bool write)
+
+{
+ bool wants_alloc, exactly_one, all_zeroes;
+ struct qcow2_map_item *l2 = &map->l2;
+ u64 entry, pos, ext_l2;
+ loff_t ret;
+
+ spin_lock_irq(&qcow2->md_pages_lock);
+ entry = get_u64_from_be_page(l2->md->page, l2->index_in_page);
+ exactly_one = entry & LX_REFCOUNT_EXACTLY_ONE;
+ entry &= ~LX_REFCOUNT_EXACTLY_ONE;
+
+ /*
+ * COW -- note that original cluster type here may be even compressed.
+ * READ: cluster data may disappear and become reused after
+ * compressed COW fail.
+ * WRITE: now we don't handle sending of accompanying qios.
+ */
+ ret = 0;
+ if (delay_if_locked(qcow2, l2->md, l2->index_in_page, qio))
+ goto out;
+
+ ret = -EIO;
+ if (entry & L2_COMPRESSED_CLUSTER) {
+ entry &= ~L2_COMPRESSED_CLUSTER;
+ if (WARN_ON_ONCE(exactly_one || !entry))
+ goto out;
+ ret = parse_compressed_l2(qcow2, map, qio, write, entry);
+ goto out;
+ }
+
+ all_zeroes = map->all_zeroes = entry & L2_READS_ALL_ZEROES;
+ entry &= ~L2_READS_ALL_ZEROES;
+ pos = entry;
+
+ if (pos && !exactly_one) {
+ map->clu_is_cow = true;
+ map->cow_clu_pos = pos;
+ map->cow_clu_end = pos + qcow2->clu_size;
+ }
+
+ if (WARN_ON_ONCE(entry & L2_RESERVED_ZERO_MASK))
+ goto out;
+ if (WARN_ON_ONCE(pos && !qcow2->hdr.nb_snapshots && !exactly_one))
+ goto out;
+ if (WARN_ON_ONCE(CLU_OFF(qcow2, entry) != 0))
+ goto out;
+
+ if (!qcow2->ext_l2) {
+ if (all_zeroes && pos)
+ map->prealloced = true;
+
+ if (WARN_ON_ONCE(map->prealloced && !exactly_one))
+ goto out;
+ if (WARN_ON_ONCE(map->clu_is_cow && all_zeroes))
+ goto out;
+
+ ret = 0;
+
+ wants_alloc = (pos == 0 || map->prealloced || map->clu_is_cow);
+ if (write && __delay_if_writeback(qcow2, l2->md, l2->index_in_page,
+ qio, wants_alloc))
+ goto out;
+ /*
+ * When cluster is under allocation, READ should see zeroes.
+ * On writeback, we could delay READ like for WRITE is done,
+ * but fast zeroing may be useful optimizations on big
+ * clusters (say, 1Mb).
+ * In case of md is dirty, WRITE is not delayed. It becomes
+ * linked to md->wbd in perform_rw_mapped(), and it runs
+ * in parallel with md writeback (accompanying qio).
+ */
+ if (!write && dirty_or_writeback(qcow2, l2->md, l2->index_in_page)) {
+ perform_zero_read(*qio, (*qio)->bi_iter.bi_size);
+ goto out;
+ }
+ } else {
+ ext_l2 = get_u64_from_be_page(l2->md->page,
+ l2->index_in_page + 1);
+ map->ext_l2 = ext_l2;
+ map->subclus_mask = 0;
+ if (!fake_merge_qio(*qio) && !fake_l1cow_qio(*qio))
+ map->subclus_mask = qio_subclus_mask(qcow2, *qio);
+
+ if (WARN_ON_ONCE(all_zeroes || (ext_l2 & (ext_l2 >> 32))))
+ goto out;
+
+ /*
+ * Note, that if "l2->index_in_page" is changed,
+ * then "l2->index_in_page + 1" is also changed.
+ * So, here we check only the second of them.
+ */
+ ret = 0;
+ if (!write &&
+ delay_if_dirty(qcow2, l2->md, l2->index_in_page + 1, qio))
+ goto out;
+ if (__delay_if_writeback(qcow2, l2->md, l2->index_in_page + 1,
+ qio, true))
+ goto out;
+ }
+
+ if (pos)
+ map->data_clu_alloced = true;
+
+ /* See comment in submit_read_whole_cow_clu() */
+ if (!write && pos && !all_zeroes && !exactly_one &&
+ delay_if_wpc_readers_locked(qcow2, l2->md, qio))
+ goto out;
+
+ ret = pos;
+out:
+ spin_unlock_irq(&qcow2->md_pages_lock);
+ return ret;
+}
+
+/*
+ * This may be called with @qio == NULL, in case of we sure
+ * that R1/R2 are already cached and up to date.
+ */
+static int __handle_r1r2_maps(struct qcow2 *qcow2, loff_t pos, struct qio **qio,
+ struct qcow2_map_item *r1, struct qcow2_map_item *r2)
+{
+ int ret;
+
+ if (calc_refcounters_map(qcow2, pos, r1, r2) < 0)
+ return -EIO;
+
+ /* Check R1 table */
+ ret = handle_md_page(qcow2, r1->page_id, qio, &r1->md);
+ if (ret <= 0)
+ return ret;
+
+ ret = calc_r2_page_id(qcow2, r1, r2);
+ if (ret < 0)
+ return ret;
+
+ ret = handle_md_page(qcow2, r2->page_id, qio, &r2->md);
+ if (ret <= 0)
+ return ret;
+
+ /*
+ * XXX: we do not care about R1 or R2 may be under writeback,
+ * since the most actual version of them is cached in memory.
+ */
+ return 1;
+}
+
+/*
+ * This aims to be called for resolving R1 and R2 md pages
+ * related to already allocated cluster at @pos.
+ * Return value: 1 if pages are found and cached; 0 in case
+ * of read md page was submitted; negative in case of error.
+ * The difference to raw __handle_r1r2_maps() is in sanity
+ * checks of R2 cluster exists and refblock entry is sane.
+ * Sanity check is disabled on clusters containing compressed
+ * clusters (their refcount is equal to num of compressed users).
+ */
+static int handle_r1r2_maps(struct qcow2 *qcow2, loff_t pos, struct qio **qio,
+ struct qcow2_map_item *r1, struct qcow2_map_item *r2, bool compressed)
+{
+ u64 entry;
+ int ret;
+
+ ret = __handle_r1r2_maps(qcow2, pos, qio, r1, r2);
+ /* Cluster mapped, but refcount table doesn't know? */
+ WARN_ON_ONCE(ret == -ENOENT);
+
+ if (ret == 1 && !qcow2->hdr.nb_snapshots && !compressed) {
+ entry = get_r2_entry(qcow2, r2->md, r2->index_in_page);
+ /* Sanity check */
+ if (unlikely(entry > 1)) {
+ pr_err("refblock=%llu, while no snapshots\n", entry);
+ return -EIO;
+ }
+ }
+
+ return ret;
+}
+
+/*
+ * This caches pages of allocated on disk md levels, which are
+ * required for submission @qio, and checks they are stable.
+ * The result of parsing L1/L2 entries is stored in @map.
+ * Returns: negative in case of error, or 0 if success.
+ * Special case: return 0 with zeroed @qio means @qio was deferred
+ * till some event: reading of md page, end of writeback, etc.
+ */
+static int parse_metadata(struct qcow2 *qcow2, struct qio **qio,
+ struct qcow2_map *map, bool write)
+{
+ struct md_page *md;
+ u64 pos;
+ int ret;
+
+ WARN_ON_ONCE(map->data_clu_pos != 0);
+ if (calc_cluster_map(qcow2, *qio, map) < 0)
+ return -EIO;
+
+ /* Check L1 page */
+ ret = handle_md_page(qcow2, map->l1.page_id, qio, &md);
+ if (ret <= 0)
+ return ret;
+ map->l1.md = md;
+ map->level = L1_LEVEL;
+
+ /* Find L2 cluster (from L1 page) */
+ pos = parse_l1(qcow2, map, qio, write);
+ if (pos <= 0) /* Err, delayed, L2 is not allocated, or zero read */
+ return pos;
+
+ /* pos is start of cluster */
+ pos += map->l2.index * sizeof(u64);
+ calc_page_id_and_index(pos, &map->l2.page_id, &map->l2.index_in_page);
+
+ /* Check L2 page */
+ ret = handle_md_page(qcow2, map->l2.page_id, qio, &md);
+ if (ret <= 0)
+ return ret;
+ map->l2.md = md;
+ map->level |= L2_LEVEL;
+
+ /* Find DATA cluster (from L2 page) */
+ pos = parse_l2(qcow2, map, qio, write);
+ if (pos <= 0) /* Err, delayed, DATA is not allocated, or zero read */
+ return pos;
+
+ map->data_clu_pos = pos;
+ if (!write)
+ return 0;
+
+ /* Now refcounters table/block */
+ if (!qcow2->hdr.nb_snapshots && !map->compressed)
+ return 0;
+ ret = handle_r1r2_maps(qcow2, pos, qio, &map->r1,
+ &map->r2, map->compressed);
+ return ret < 0 ? ret : 0;
+}
+
+/*
+ * This occupies cluster at @r2_pos for R2 cluster,
+ * and connects it to R1 table entry.
+ */
+static int place_r2(struct qcow2 *qcow2, struct qcow2_map_item *r1,
+ struct qcow2_map_item *r2, loff_t r2_pos, struct qio **qio)
+{
+ u64 page_id = r2_pos >> PAGE_SHIFT;
+ int ret;
+
+ if (delay_if_writeback(qcow2, r1->md, r1->index_in_page, qio, true))
+ return 0;
+
+ ret = punch_hole(qcow2->file, r2_pos, qcow2->clu_size);
+ if (ret) {
+ pr_err("qcow2: punch hole: %d\n", ret);
+ return ret;
+ }
+
+ ret = alloc_and_insert_md_page(qcow2, page_id, &r2->md);
+ if (ret < 0) {
+ pr_err("Can't alloc: ret=%d, page_id=%llu\n", ret, page_id);
+ return -EIO;
+ }
+
+ zero_fill_page_from(r2->md->page, 0);
+
+ spin_lock_irq(&qcow2->md_pages_lock);
+ set_u64_to_be_page(r1->md->page, r1->index_in_page, r2_pos);
+ md_make_dirty(qcow2, r1->md, true);
+ r2->md->status |= MD_UPTODATE;
+ spin_unlock_irq(&qcow2->md_pages_lock);
+
+ mark_cluster_used(qcow2, r2->md, r2->index_in_page);
+ return 1;
+}
+
+static s32 find_unused_block_entry(struct qcow2 *qcow2, struct md_page *md,
+ u32 from)
+{
+ u32 indexes_per_page = PAGE_SIZE * 8 / qcow2->refblock_bits;
+ long i, ret = -ENOENT;
+
+ lockdep_assert_held(&qcow2->md_pages_lock);
+ for (i = from; i < indexes_per_page; i++) {
+ if (get_r2_entry(qcow2, md, i) == 0) {
+ ret = i;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static loff_t find_unused_cluster(struct qcow2 *qcow2, struct qio **qio,
+ struct qcow2_map_item *r1,
+ struct qcow2_map_item *r2)
+{
+ u32 clu_size = qcow2->clu_size;
+ s32 index, ret;
+ loff_t pos;
+again:
+ pos = READ_ONCE(qcow2->free_cluster_search_pos);
+ if (pos >= qcow2->reftable_max_file_size)
+ return -ENOENT;
+
+ ret = __handle_r1r2_maps(qcow2, pos, qio, r1, r2);
+ if (ret <= 0) {
+ if (ret != -ENOENT)
+ return ret;
+ /*
+ * Since pos is not covered by R2, the whole cluster
+ * must be unused. Use it to store R2 cluster.
+ * Both indexes must be 0 here, because of we allocate
+ * clusters from small to big.
+ */
+ WARN_ON_ONCE(r2->index_in_page != 0 || r2->index != 0);
+ ret = place_r2(qcow2, r1, r2, pos, qio);
+ if (ret <= 0)
+ return ret;
+ goto again;
+ }
+
+ spin_lock_irq(&qcow2->md_pages_lock);
+ /*
+ * This is rare usually and very rare during intensive write,
+ * since R1 and R2 writeback are delayed. We faster make all
+ * blocks of the page to be used, than writeback starts.
+ */
+ if (__delay_if_writeback(qcow2, r2->md, r2->index_in_page, qio, true)) {
+ pos = 0;
+ goto unlock;
+ }
+
+ if (unlikely(pos != qcow2->free_cluster_search_pos)) {
+ /* Parallel mark_cluster_unused() changed it */
+ spin_unlock_irq(&qcow2->md_pages_lock);
+ goto again;
+ }
+
+ index = find_unused_block_entry(qcow2, r2->md, r2->index_in_page);
+ if (index < 0) {
+ /* No unused entries in this page */
+ pos = round_up(pos + 1, qcow2->r2_page_covered_file_size);
+ qcow2->free_cluster_search_pos = pos;
+ spin_unlock_irq(&qcow2->md_pages_lock);
+ goto again;
+ }
+
+ /* Advance pos and R2 indexes to point to the block entry */
+ pos += (u64)(index - r2->index_in_page) * clu_size;
+ r2->index += index - r2->index_in_page;
+ r2->index_in_page = index;
+
+ /* In case of caller fails, we have this value cached */
+ qcow2->free_cluster_search_pos = pos;
+unlock:
+ spin_unlock_irq(&qcow2->md_pages_lock);
+
+ return pos;
+}
+
+int qcow2_truncate_safe(struct file *file, loff_t new_len)
+{
+ int ret;
+
+ ret = vfs_truncate(&file->f_path, new_len);
+ if (ret)
+ return ret;
+
+ return vfs_fsync(file, 0);
+}
+
+static int truncate_prealloc_safe(struct qcow2 *qcow2, loff_t len, const char *func)
+{
+ loff_t prealloc_len, max_prealloc_len = qcow2->reftable_max_file_size;
+ struct file *file = qcow2->file;
+ loff_t new_len = len;
+ int ret;
+
+ if (new_len <= qcow2->file_size)
+ return 0;
+ if (new_len < qcow2->reftable_max_file_size) {
+ prealloc_len = ALIGN(new_len, PREALLOC_SIZE);
+ new_len = min_t(loff_t, prealloc_len, max_prealloc_len);
+ }
+
+ ret = qcow2_truncate_safe(file, new_len);
+ if (ret) {
+ pr_err("qcow2: %s->truncate: %d\n", func, ret);
+ return ret;
+ }
+
+ qcow2->file_size = new_len;
+ qcow2->file_preallocated_area_start = len;
+ return 0;
+}
+
+static int punch_hole(struct file *file, loff_t pos, loff_t len)
+{
+ return vfs_fallocate(file, FALLOC_FL_PUNCH_HOLE|FALLOC_FL_KEEP_SIZE,
+ pos, len);
+}
+
+static void set_reftable_in_raw_hdr(struct page *page0, loff_t pos, loff_t clus)
+{
+ struct QCowHeader *raw_hdr;
+
+ raw_hdr = kmap(page0);
+ raw_hdr->refcount_table_offset = cpu_to_be64(pos);
+ raw_hdr->refcount_table_clusters = cpu_to_be32(clus);
+ kunmap(page0);
+}
+
+/*
+ * After all file space covered by current reftable (R1) became used,
+ * this relocates reftable (R1) to new place and extends its size.
+ * The situation is rather rare, and since the function is already
+ * complicated, we should not demonstrate excessive creativity
+ * and optimize it in prejudice of readability.
+ *
+ * We act in the way to provide safe rollback throughout whole function.
+ * Firstly, we cache every related md we're going to use on relocation.
+ * New reftable (R1) is placed next to max cluster covered by old R1.
+ * Since new reftable (R1) clusters should be marked as used after
+ * relocation, we also allocate md for new refblocks (R2) (they should
+ * cover both new R1 and new R2 -- themself). Note, that new R1 and R2
+ * clusters are in the part of file, which is not covered by old R1.
+ *
+ * Then, we try to write new hdr on disk. In case of failure, we
+ * restore old hdr in memory and do safe rollback. In case of success,
+ * there should not be more reasons to fail (only this driver's bugs).
+ * Cached old reftable (R1) pages we renumber to point to new reftable (R1)
+ * place. Then we mark old reftable (R1) clusters as unused, while
+ * new reftable (R1) clusters as used.
+ *
+ * In further, updated R1 and R2 pages will be written on disk
+ * on writeback like during any other R1/R2 update. Even in case of
+ * power down, when refcounts become lost, check util on next mount
+ * can easily restore them by L1 and L2, which are stable.
+ */
+static int relocate_refcount_table(struct qcow2 *qcow2, struct qio **qio)
+{
+ loff_t i, old_pos, old_end, pos, end, r2_end, delta;
+ u32 old_clus, clus, clu_size = qcow2->clu_size;
+ u32 r2_clus, bits = qcow2->refblock_bits;
+ unsigned long nr_pages, index;
+ struct qcow2_map_item r1, r2;
+ struct md_page *md0, *md;
+ int ret;
+
+ /* FIXME: check there is no in-flight operations */
+ old_clus = qcow2->hdr.refcount_table_clusters;
+ clus = min_t(u32, old_clus + 1, REFCOUNT_TABLE_MAX_SIZE / clu_size);
+ if (clus <= old_clus) {
+ pr_debug_ratelimited("qcow2: maximal refcount table size\n");
+ return -ENFILE;
+ }
+
+ /* Boundaries of old reftable (R1) */
+ old_pos = qcow2->hdr.refcount_table_offset;
+ old_end = old_pos + (u64)old_clus * clu_size;
+ nr_pages = (old_end - old_pos) / PAGE_SIZE;
+
+ /* Cache old reftable (R1) pages and image header */
+ index = old_pos / PAGE_SIZE;
+ for (i = 0; i <= nr_pages; i++, index++) {
+ if (i == nr_pages)
+ index = 0; /* hdr */
+ ret = handle_md_page(qcow2, index, qio, &md);
+ if (ret <= 0)
+ return ret;
+ /*
+ * Writeback mustn't require cluster allocation,
+ * otherwise it may result in deadlock here.
+ */
+ if (delay_if_writeback(qcow2, md, -1, qio, true))
+ return 0;
+ }
+ md0 = md;
+
+ /* Cache R1/R2 pages covering clusters of old reftable (R1) */
+ for (i = old_pos; i < old_end; i += PAGE_SIZE) {
+ ret = handle_r1r2_maps(qcow2, i, qio, &r1, &r2, false);
+ if (ret <= 0)
+ return ret;
+ if (delay_if_writeback(qcow2, r1.md, -1, qio, true))
+ return 0;
+ }
+
+ /*
+ * We need R2 clusters to mark used both: new reftable (R1) clusters
+ * and these refblock clusters (R2) themself. This number comes from:
+ * r2_clus >= (clus + r2_clus) * bits / (8 * clu_size)
+ */
+ r2_clus = DIV_ROUND_UP((u64)clus * bits, 8 * clu_size - bits);
+
+ /* Choose position next to max cluster covered by old R1/R2 */
+ pos = qcow2->reftable_max_file_size;
+ end = pos + (u64)clus * clu_size;
+ r2_end = end + (u64)r2_clus * clu_size;
+ ret = truncate_prealloc_safe(qcow2, r2_end, __func__);
+ if (ret)
+ return ret;
+
+ /* Alloc R1/R2 pages covering clusters of new R1 and new R2 */
+ for (i = pos + (u64)old_clus * clu_size; i < r2_end; i += PAGE_SIZE) {
+ ret = alloc_and_insert_md_page(qcow2, i >> PAGE_SHIFT, &md);
+ if (ret < 0)
+ goto err_free_r2_pages;
+ spin_lock_irq(&qcow2->md_pages_lock);
+ zero_fill_page_from(md->page, 0);
+ md->status |= MD_UPTODATE;
+ spin_unlock_irq(&qcow2->md_pages_lock);
+ }
+
+ set_reftable_in_raw_hdr(md0->page, pos, clus);
+ /* Write new hdr: last potential failing operation */
+ ret = rw_page_sync(WRITE, qcow2, 0, md0->page);
+ if (ret) {
+ /* Restore old R1 */
+ set_reftable_in_raw_hdr(md0->page, old_pos, old_clus);
+ goto err_free_r2_pages;
+ }
+
+ /* Update cached values */
+ qcow2->hdr.refcount_table_offset = pos;
+ qcow2->hdr.refcount_table_clusters = clus;
+ calc_cached_parameters(qcow2, &qcow2->hdr);
+
+ /* Now renumber R1 cached pages to point new place and mark dirty */
+ index = old_pos / PAGE_SIZE;
+ delta = (pos - old_pos) / PAGE_SIZE;
+ for (i = 0; i < nr_pages; i++, index++) {
+ spin_lock_irq(&qcow2->md_pages_lock);
+ md = md_page_renumber(qcow2, index, index + delta);
+ if (!WARN_ON_ONCE(!md))
+ md_make_dirty(qcow2, md, true);
+ spin_unlock_irq(&qcow2->md_pages_lock);
+ if (!md)
+ goto err_free_r2_pages;
+ }
+
+ /* Connect new R2 to new R1 */
+ for (i = end; i < r2_end; i += clu_size) {
+ if (calc_refcounters_map(qcow2, i, &r1, &r2) < 0) {
+ WARN_ON_ONCE(1);
+ goto err_free_r2_pages;
+ }
+ md = md_page_find_or_postpone(qcow2, r1.page_id, NULL);
+ if (WARN_ON_ONCE(!md))
+ goto err_free_r2_pages;
+ spin_lock_irq(&qcow2->md_pages_lock);
+ set_u64_to_be_page(md->page, r1.index_in_page, i);
+ md_make_dirty(qcow2, md, true);
+ spin_unlock_irq(&qcow2->md_pages_lock);
+ }
+
+ /* Mark used new R1 and R2 clusters */
+ for (i = pos; i < r2_end; i += clu_size) {
+ ret = handle_r1r2_maps(qcow2, i, NULL, &r1, &r2, false);
+ if (WARN_ON_ONCE(ret <= 0))
+ goto err_free_r2_pages;
+ mark_cluster_used(qcow2, r2.md, r2.index_in_page);
+ }
+
+ /* Mark unused old reftable (R1) clusters */
+ for (i = old_pos; i < old_end; i += clu_size) {
+ ret = handle_r1r2_maps(qcow2, i, NULL, &r1, &r2, false);
+ if (WARN_ON_ONCE(ret <= 0))
+ goto err_free_r2_pages;
+ mark_cluster_unused(qcow2, r2.md, r2.index_in_page, i);
+ }
+
+ return 1;
+
+err_free_r2_pages:
+ for (i = end; i < r2_end; i += clu_size) {
+ md = md_page_find_or_postpone(qcow2, i >> PAGE_SHIFT, NULL);
+ if (!md)
+ break;
+ spin_lock_irq(&qcow2->md_pages_lock);
+ md_page_erase(qcow2, md);
+ spin_unlock_irq(&qcow2->md_pages_lock);
+ free_md_page(md);
+ }
+ /* TODO: switch to RO */
+ return -EIO;
+}
+
+/*
+ * This function is aimed to be called only from main work.
+ * In case of wish to use it from more places, it's needed
+ * to make sure nobody can reuse cluster obtained from
+ * find_unused_cluster() before mark_cluster_used() in done.
+ */
+static loff_t allocate_cluster(struct qcow2 *qcow2, struct qio *qio,
+ struct md_page **r2_md, u32 *r2_index_in_page)
+{
+ u32 clu_size = qcow2->clu_size;
+ struct file *file = qcow2->file;
+ loff_t pos, off, end, old_size;
+ struct qcow2_map_item r1, r2;
+ int ret;
+again:
+ pos = find_unused_cluster(qcow2, &qio, &r1, &r2);
+ if (unlikely(pos == -ENOENT)) {
+ ret = relocate_refcount_table(qcow2, &qio);
+ if (ret <= 0)
+ return ret;
+ goto again;
+ }
+ if (pos <= 0)
+ return pos;
+
+ end = pos + clu_size;
+ old_size = qcow2->file_size;
+
+ if (pos < qcow2->file_preallocated_area_start) {
+ /* Clu at @pos may contain dirty data */
+ off = min_t(loff_t, old_size, end);
+ ret = punch_hole(file, pos, off - pos);
+ if (ret) {
+ pr_err("qcow2: punch hole: %d\n", ret);
+ return ret;
+ }
+ }
+
+ if (end > old_size) {
+ ret = truncate_prealloc_safe(qcow2, end, __func__);
+ if (ret)
+ return ret;
+ } else if (pos < qcow2->file_preallocated_area_start) {
+ /*
+ * Flush punch_hole() modifications.
+ * TODO: track recentry unused blocks
+ * and punch holes in background.
+ */
+ ret = vfs_fsync(file, 0);
+ if (ret)
+ return ret;
+ }
+
+ if (end > qcow2->file_preallocated_area_start)
+ qcow2->file_preallocated_area_start = end;
+
+ mark_cluster_used(qcow2, r2.md, r2.index_in_page);
+ if (r2_md)
+ *r2_md = r2.md;
+ if (r2_index_in_page)
+ *r2_index_in_page = r2.index_in_page;
+ return pos;
+}
+
+#define LU_SET_ONE_MASK (1 << 0)
+#define LU_WANTS_PE_PAGE (1 << 1)
+#define LU_WANTS_ALLOC (1 << 2)
+#define LU_IGN_CHANGED_IND (1 << 3)
+static int prepare_l_entry_update(struct qcow2 *qcow2, struct qio *qio,
+ struct md_page *md, u32 index_in_page,
+ u64 *pval, u32 arg_mask)
+{
+ bool wants_pe_page = (arg_mask & LU_WANTS_PE_PAGE);
+ struct wb_desc *new_wbd = NULL;
+ struct page *pe_page = NULL;
+ u64 old_val, val = *pval;
+
+ /* parse_metadata()->delay_if_writeback() delays them */
+ if (WARN_ON_ONCE(READ_ONCE(md->status) & MD_WRITEBACK))
+ return -EIO;
+ /*
+ * L1/L2 pages become set and unset dirty from main
+ * work only, so lock is not required for visibility.
+ */
+ if (!(md->status & MD_DIRTY)) {
+ /* We're the first changing entry in this md page. */
+ new_wbd = alloc_wbd(wants_pe_page);
+ if (!new_wbd)
+ return -ENOMEM;
+ new_wbd->md = md;
+ } else if (wants_pe_page && !md->wbd->pe_page) {
+ pe_page = alloc_page(GFP_NOIO|__GFP_ZERO);
+ if (!pe_page)
+ return -ENOMEM;
+ }
+
+ if (arg_mask & LU_WANTS_ALLOC) {
+ /* Allocate new zeroed data cluster: no failing actions after it */
+ loff_t pos = allocate_cluster(qcow2, qio, NULL, NULL);
+
+ if (pos <= 0) {
+ free_wbd(new_wbd);
+ if (pe_page)
+ put_page(pe_page);
+ return (int)pos;
+ }
+ val = *pval = pos;
+ }
+
+ spin_lock_irq(&qcow2->md_pages_lock);
+ if (md_make_dirty(qcow2, md, false))
+ md->wbd = new_wbd;
+ else
+ WARN_ON_ONCE(new_wbd);
+ if (!(arg_mask & LU_IGN_CHANGED_IND))
+ WARN_ON_ONCE(test_bit(index_in_page, md->wbd->changed_indexes));
+ set_bit(index_in_page, md->wbd->changed_indexes);
+
+ if (wants_pe_page && !md->wbd->pe_page)
+ md->wbd->pe_page = pe_page;
+ else
+ WARN_ON_ONCE(pe_page);
+ if (wants_pe_page) {
+ old_val = get_u64_from_be_page(md->page, index_in_page);
+ set_u64_to_be_page(md->wbd->pe_page, index_in_page, old_val);
+ }
+
+ /* Set new mapping */
+ if (arg_mask & LU_SET_ONE_MASK)
+ val |= LX_REFCOUNT_EXACTLY_ONE;
+ set_u64_to_be_page(md->page, index_in_page, val);
+
+ /* Keep in mind, we link qio to md in perform_rw_mapped() */
+ spin_unlock_irq(&qcow2->md_pages_lock);
+ return 1;
+}
+
+static int prepare_l1l2_allocation(struct qcow2 *qcow2, struct qio *qio,
+ struct qcow2_map *map)
+{
+ u32 arg_mask, subclus_mask;
+ u64 val;
+ int ret;
+
+ if (WARN_ON_ONCE(!(map->level & L1_LEVEL)))
+ return -EIO; /* Sanity check: L1 must be cached */
+
+ if (!(map->level & L2_LEVEL)) {
+ WARN_ON_ONCE(map->prealloced || map->compressed);
+ /* Allocate cluster for L2 entries, and prepare L1 update */
+ ret = prepare_l_entry_update(qcow2, qio, map->l1.md,
+ map->l1.index_in_page, &val,
+ LU_SET_ONE_MASK|LU_WANTS_ALLOC);
+ if (ret <= 0)
+ return ret;
+
+ /*
+ * 1)For now we don't do parallel L1 and L2 updates.
+ * 2)For COW from backing file this is must.
+ */
+ spin_lock_irq(&qcow2->md_pages_lock);
+ list_add_tail(&qio->link, &map->l1.md->wait_list);
+ spin_unlock_irq(&qcow2->md_pages_lock);
+ return 0;
+ }
+
+ if (!map->data_clu_alloced || map->all_zeroes) {
+ WARN_ON_ONCE(!map->prealloced != !map->data_clu_pos ||
+ map->compressed || map->clu_is_cow);
+ /* Allocate cluster for DATA, and prepare L2 update */
+ arg_mask = LU_SET_ONE_MASK;
+ if (map->prealloced || qcow2->ext_l2)
+ arg_mask |= LU_WANTS_PE_PAGE;
+ if (!map->prealloced)
+ arg_mask |= LU_WANTS_ALLOC;
+
+ ret = prepare_l_entry_update(qcow2, qio, map->l2.md,
+ map->l2.index_in_page,
+ &map->data_clu_pos, arg_mask);
+ if (ret <= 0)
+ return ret;
+
+ if (!qcow2->ext_l2)
+ return 1;
+
+ /*
+ * pe_page is allocated => ext_l2 update won't fail =>
+ * revert of prepare_l_entry_update() won't be needed.
+ */
+ WARN_ON_ONCE(!map->l2.md->wbd->pe_page);
+ }
+
+ subclus_mask = qio_subclus_mask(qcow2, qio);
+ val = map->ext_l2 | subclus_mask;
+ val &= ~((u64)subclus_mask << 32);
+ arg_mask = LU_WANTS_PE_PAGE|LU_IGN_CHANGED_IND;
+
+ return prepare_l_entry_update(qcow2, qio, map->l2.md,
+ map->l2.index_in_page + 1,
+ &val, arg_mask);
+}
+
+/*
+ * Set some wb index to block WRITEs to this cluster.
+ * READs also must be blocked, since they may get data
+ * from cluster, after WRITE marked it's unused. Also,
+ * we have to wait all previous READs. We do that around
+ * index wb. See md->wpc_noread_count update details.
+ */
+static int prepare_l_entry_cow(struct qcow2 *qcow2, struct qcow2_map *map,
+ struct qio *qio, struct md_page *md,
+ u32 index_in_page, loff_t cow_clu_pos,
+ loff_t cow_clu_end, u8 cow_level)
+{
+ struct lock_desc *lockd = NULL;
+ struct qio_ext *ext;
+
+ if (alloc_qio_ext(qio))
+ return -ENOMEM;
+
+ ext = qio->ext;
+ ext->cow_clu_pos = cow_clu_pos;
+ ext->cow_clu_end = cow_clu_end;
+ ext->cow_level = cow_level;
+
+ spin_lock_irq(&qcow2->md_pages_lock);
+ if (!md->lockd) {
+ spin_unlock_irq(&qcow2->md_pages_lock);
+ lockd = kzalloc(sizeof(*lockd), GFP_NOIO);
+ if (!lockd)
+ return -ENOMEM;
+ spin_lock_irq(&qcow2->md_pages_lock);
+ md->lockd = lockd;
+ }
+
+ md_index_set_locked(qcow2, md, index_in_page);
+ spin_unlock_irq(&qcow2->md_pages_lock);
+
+ /* Setup ext, so qio_endio() on error will make all cleanup */
+ ext->cleanup_mask = MD_INDEX_SET_UNLOCKED;
+ ext->lx_index_in_page = index_in_page;
+ return 1;
+}
+
+static int prepare_l1l2_cow(struct qcow2 *qcow2, struct qio *qio,
+ struct qcow2_map *map)
+{
+ if (WARN_ON_ONCE(!(map->level & L1_LEVEL)))
+ return -EIO; /* Sanity check: L1 must be cached */
+
+ if (!(map->level & L2_LEVEL)) {
+ return prepare_l_entry_cow(qcow2, map, qio, map->l1.md,
+ map->l1.index_in_page,
+ map->cow_clu_pos,
+ map->cow_clu_end, L1_LEVEL);
+ }
+
+ return prepare_l_entry_cow(qcow2, map, qio, map->l2.md,
+ map->l2.index_in_page,
+ map->cow_clu_pos,
+ map->cow_clu_end, L2_LEVEL);
+}
+
+static struct qio *alloc_clu_read_qio(struct qcow2 *qcow2, u32 nr_pages,
+ struct qcow2_bvec **qvec)
+{
+ struct qcow2_target *tgt = qcow2->tgt;
+ struct qio *qio;
+
+ qio = alloc_qio(tgt->qio_pool, true);
+ if (!qio)
+ return NULL;
+
+ *qvec = alloc_qvec_with_pages(nr_pages);
+ if (!*qvec) {
+ free_qio(qio, tgt->qio_pool);
+ return NULL;
+ }
+
+ init_qio(qio, REQ_OP_READ, qcow2);
+ qio->bi_io_vec = (*qvec)->bvec;
+ qio->bi_iter.bi_size = nr_pages << PAGE_SHIFT;
+ qio->bi_iter.bi_idx = 0;
+ qio->bi_iter.bi_bvec_done = 0;
+ return qio;
+}
+
+static void backward_merge_write_complete(struct qcow2_target *tgt, struct qio *unused,
+ void *qio_ptr, blk_status_t bi_status)
+{
+ struct qio *qio = qio_ptr;
+ struct qcow2 *qcow2 = qio->qcow2;
+
+ if (unlikely(bi_status)) {
+ qio->bi_status = bi_status;
+ qio_endio(qio);
+ return;
+ }
+
+ WARN_ON_ONCE(qio->flags & QIO_IS_DISCARD_FL);
+ qio->flags |= QIO_IS_DISCARD_FL;
+
+ qio->queue_list_id = QLIST_COW_INDEXES;
+ dispatch_qios(qcow2, qio, NULL);
+}
+
+static void backward_merge_read_complete(struct qcow2_target *tgt, struct qio *unused,
+ void *qio_ptr, blk_status_t bi_status)
+{
+ struct qio *qio = qio_ptr;
+ struct qcow2 *qcow2 = qio->qcow2;
+
+ if (unlikely(bi_status)) {
+ qio->bi_status = bi_status;
+ qio_endio(qio);
+ return;
+ }
+
+ qio->queue_list_id = QLIST_BMERGE_WRITE;
+ dispatch_qios(qcow2, qio, NULL);
+}
+
+static void requeue_if_ok(struct qcow2_target *tgt, struct qio *unused,
+ void *qio_ptr, blk_status_t bi_status)
+{
+ struct qio *qio = qio_ptr;
+
+ if (bi_status) {
+ qio->bi_status = bi_status;
+ qio_endio(qio);
+ return;
+ }
+
+ dispatch_qios(qio->qcow2, qio, NULL);
+}
+
+static int prepare_backward_merge(struct qcow2 *qcow2, struct qio **qio,
+ struct qcow2_map *map, bool write)
+{
+ struct qio *aux_qio;
+ int ret;
+
+ if (!map->data_clu_alloced) {
+ WARN_ON_ONCE(map->clu_is_cow); /* Strange COW at L1 */
+ if (fake_merge_qio(*qio)) {
+ /* Nothing is to merge */
+ goto endio;
+ }
+ WARN_ON_ONCE(!maybe_mapped_in_lower_delta(qcow2, *qio));
+ WARN_ON_ONCE((*qio)->queue_list_id != QLIST_DEFERRED);
+ (*qio)->qcow2 = qcow2->lower;
+ dispatch_qios((*qio)->qcow2, *qio, NULL);
+ return 0;
+ }
+
+ if (!op_is_write((*qio)->bi_op)) {
+ /*
+ * READ qio may data may be contained in several deltas.
+ * We can't read lower delta after prepare_l1l2_cow()
+ * prepares us.
+ */
+ aux_qio = alloc_qio(qcow2->tgt->qio_pool, true);
+ if (!aux_qio) {
+ (*qio)->bi_status = BLK_STS_RESOURCE;
+ goto endio;
+ }
+
+ init_qio(aux_qio, REQ_OP_WRITE, qcow2);
+ aux_qio->flags = QIO_IS_MERGE_FL|QIO_FREE_ON_ENDIO_FL;
+ aux_qio->bi_io_vec = (*qio)->bi_io_vec;
+ aux_qio->bi_iter = (*qio)->bi_iter;
+ aux_qio->bi_iter.bi_size = 0;
+ aux_qio->endio_cb = requeue_if_ok;
+ aux_qio->endio_cb_data = *qio;
+ WARN_ON_ONCE(!fake_merge_qio(aux_qio));
+ *qio = aux_qio;
+ }
+
+ /*
+ * Mark as COW, as this completely defers any parallel qios.
+ * @qio is COW status holder.
+ */
+ ret = prepare_l1l2_cow(qcow2, *qio, map);
+ if (ret < 0) {
+ (*qio)->bi_status = errno_to_blk_status(ret);
+ goto endio;
+ }
+
+ if (!map->clu_is_cow) {
+ /* Forced set these to unuse them after discard */
+ (*qio)->ext->cow_clu_pos = map->data_clu_pos;
+ (*qio)->ext->cow_clu_end = map->data_clu_pos + qcow2->clu_size;
+ }
+
+ return 1;
+endio:
+ qio_endio(*qio); /* Breaks COW set in prepare_l1l2_cow() */
+ return 0;
+}
+
+static void data_rw_complete(struct qio *qio)
+{
+ bool finalize_wbd = false, call_endio = true;
+ bool write = op_is_write(qio->bi_op);
+ blk_status_t bi_status = BLK_STS_OK;
+ struct qcow2 *qcow2 = qio->qcow2;
+ struct wb_desc *wbd;
+ unsigned long flags;
+
+ /* FIXME: short read/write */
+ if (qio->ret != qio->bi_iter.bi_size)
+ bi_status = BLK_STS_IOERR;
+
+ wbd = qio->data;
+ if (write && wbd) {
+ spin_lock_irqsave(&qcow2->md_pages_lock, flags);
+ if (!list_empty(&qio->link)) {
+ list_del_init(&qio->link);
+ if (wbd->completed) {
+ if (wbd->ret != 0)
+ bi_status = errno_to_blk_status(wbd->ret);
+ /* Last user of wbd? */
+ finalize_wbd = list_empty(&wbd->submitted_list);
+ } else if (bi_status == BLK_STS_OK) {
+ call_endio = false;
+ list_add_tail(&qio->link, &wbd->completed_list);
+ }
+ }
+ spin_unlock_irqrestore(&qcow2->md_pages_lock, flags);
+ }
+
+ if (call_endio) {
+ if (bi_status != BLK_STS_OK)
+ qio->bi_status = bi_status;
+ qio_endio(qio);
+ }
+ if (finalize_wbd)
+ complete_wbd(qcow2, wbd);
+}
+
+static void submit_rw_mapped(struct qcow2 *qcow2, loff_t clu_pos, struct qio *qio)
+{
+ unsigned int rw, nr_segs;
+ struct bio_vec *bvec;
+ struct iov_iter iter;
+ loff_t pos;
+
+ rw = (op_is_write(qio->bi_op) ? WRITE : READ);
+ nr_segs = qio_nr_segs(qio);
+ bvec = __bvec_iter_bvec(qio->bi_io_vec, qio->bi_iter);
+
+ iov_iter_bvec(&iter, rw, bvec, nr_segs, qio->bi_iter.bi_size);
+ iter.iov_offset = qio->bi_iter.bi_bvec_done;
+
+ pos = clu_pos + bytes_off_in_cluster(qcow2, qio);
+ call_rw_iter(qcow2->file, pos, rw, &iter, qio);
+}
+
+static void perform_rw_mapped(struct qcow2_map *map, struct qio *qio)
+{
+ struct qcow2 *qcow2 = map->qcow2;
+ struct md_page *md = map->l2.md;
+ unsigned long flags;
+ u32 index_in_page;
+ unsigned int rw;
+
+ rw = (op_is_write(qio->bi_op) ? WRITE : READ);
+ qio->complete = data_rw_complete;
+ qio->data = NULL;
+ INIT_LIST_HEAD(&qio->link);
+
+ /*
+ * The idea is to submit L2 update and qio data write in parallel
+ * for better performance. But since qio_endio() can't be called
+ * till both of them are written, we link qio to md to track that.
+ * In case of qio is not related to changed indexes, it shouldn't
+ * wait for md writeback completion.
+ *
+ * L1/L2 pages become set and unset dirty from main work only,
+ * so lock is not needed for MD_DIRTY/changed_indexes visibility.
+ */
+ index_in_page = map->l2.index_in_page + !!(qcow2->ext_l2);
+ if (rw == WRITE && (md->status & MD_DIRTY) &&
+ test_bit(index_in_page, md->wbd->changed_indexes)) {
+ spin_lock_irqsave(&qcow2->md_pages_lock, flags);
+ list_add(&qio->link, &md->wbd->submitted_list);
+ qio->data = md->wbd;
+ spin_unlock_irqrestore(&qcow2->md_pages_lock, flags);
+ }
+
+ submit_rw_mapped(qcow2, map->data_clu_pos, qio);
+}
+
+static void cow_read_complete(struct qio *qio)
+{
+ struct md_page *md = qio->ext->lx_md;
+ struct qcow2 *qcow2 = qio->qcow2;
+ int ret = qio->ret;
+
+ dec_wpc_readers(qcow2, md); /* We ended to use shared clu on disk */
+
+ if (qio->ret != qcow2->clu_size) {
+ qio->bi_status = errno_to_blk_status(ret < 0 ? ret : -EIO);
+ qio_endio(qio);
+ return;
+ }
+
+ qio->queue_list_id = QLIST_COW_DATA;
+ dispatch_qios(qio->qcow2, qio, NULL);
+}
+
+static void submit_read_whole_cow_clu(struct qcow2_map *map, struct qio *qio)
+{
+ struct qcow2 *qcow2 = map->qcow2;
+ struct md_page *md = map->l1.md;
+ u32 clu_size = qcow2->clu_size;
+ loff_t pos = map->cow_clu_pos;
+ struct qcow2_bvec *qvec;
+ struct iov_iter iter;
+ u32 nr_pages;
+
+ WARN_ON_ONCE(map->level & L2_LEVEL);
+
+ nr_pages = clu_size >> PAGE_SHIFT;
+ qvec = alloc_qvec_with_pages(nr_pages);
+ if (!qvec) {
+ qio->bi_status = BLK_STS_RESOURCE;
+ qio_endio(qio); /* Frees ext */
+ return;
+ }
+
+ qio->complete = cow_read_complete;
+ qio->data = qvec;
+ qio->ext->cleanup_mask |= FREE_QIO_DATA_QVEC;
+ qio->ext->lx_md = md;
+ /*
+ * This is not obligatory, since cluster under COW can't disappear
+ * after we decrement its counter (another snap refers to it). We
+ * do that for the uniformity with compressed COW and better testing.
+ */
+ inc_wpc_readers(md);
+
+ iov_iter_bvec(&iter, READ, qvec->bvec, nr_pages, clu_size);
+ call_rw_iter(qcow2->file, pos, READ, &iter, qio);
+}
+
+static int decompress_zlib_clu(struct qcow2 *qcow2, struct qcow2_bvec *qvec,
+ u16 page0_off, int count, void *buf, void *ws)
+{
+ unsigned int off = page0_off;
+ struct z_stream_s strm;
+ void *from;
+ int i, ret;
+
+ memset(&strm, 0, sizeof(strm));
+ strm.workspace = ws;
+ strm.next_out = buf;
+ strm.avail_out = qcow2->clu_size;
+ strm.total_out = 0;
+
+ ret = zlib_inflateInit2(&strm, -MAX_WBITS); /* minus is zlib (!gzip) */
+ if (ret != Z_OK)
+ return -ENOMEM;
+
+ count -= off;
+ for (i = 0; i < qvec->nr_pages && count > 0; i++, off = 0) {
+ from = kmap(qvec->bvec[i].bv_page);
+ strm.next_in = from + off;
+ strm.avail_in = min_t(int, qvec->bvec[i].bv_len - off, count);
+ strm.total_in = 0;
+ count -= strm.avail_in;
+ ret = zlib_inflate(&strm, Z_NO_FLUSH);
+ kunmap(qvec->bvec[i].bv_page);
+ if (ret == Z_STREAM_END) {
+ ret = Z_OK;
+ break;
+ }
+ if (ret != Z_OK)
+ break;
+ }
+
+ zlib_inflateEnd(&strm);
+ if (ret == Z_OK && strm.total_out == qcow2->clu_size)
+ return strm.total_out;
+ return -EIO;
+}
+
+static int extract_one_compressed(struct qcow2 *qcow2, void *buf,
+ struct qcow2_bvec *qvec,
+ u16 page0_off, u32 qvec_len)
+{
+ void *ws = buf + qcow2->clu_size;
+
+ return decompress_zlib_clu(qcow2, qvec, page0_off, qvec_len, buf, ws);
+}
+
+static int copy_buf_to_bvec_iter(const struct bio_vec *bvec,
+ const struct bvec_iter *biter,
+ const void *buf, u32 max)
+{
+ struct bvec_iter iter;
+ struct bio_vec bv;
+ void *to, *addr;
+ int ret = 0;
+
+ /* This is equivalent of bio_for_each_bvec() */
+ qcow2_for_each_bvec(iter, bv, *biter, bvec) {
+ if (WARN_ON_ONCE(bv.bv_len > max)) {
+ ret = -EIO;
+ break;
+ }
+ addr = kmap(bv.bv_page);
+ to = addr + bv.bv_offset;
+ memcpy(to, buf, bv.bv_len);
+ kunmap(bv.bv_page);
+ max -= bv.bv_len;
+ buf += bv.bv_len;
+ }
+
+ return ret;
+}
+
+static int copy_clu_part_to_qio(struct qcow2 *qcow2, const void *buf, struct qio *qio)
+{
+ u32 max, seek, clu_size = qcow2->clu_size;
+
+ seek = bytes_off_in_cluster(qcow2, qio);
+ if (WARN_ON_ONCE(seek >= clu_size))
+ return -EINVAL;
+
+ buf += seek;
+ max = clu_size - seek;
+
+ return copy_buf_to_bvec_iter(qio->bi_io_vec, &qio->bi_iter, buf, max);
+}
+
+static int copy_zcow_slice(loff_t start, loff_t end, void *qio_p,
+ void *buf, void *consumed_p)
+{
+ struct qio *qio = qio_p;
+ struct qcow2 *qcow2 = qio->qcow2;
+ u32 clu_size = qcow2->clu_size;
+ loff_t *consumed = consumed_p;
+ struct qcow2_bvec *qvec = qio->data;
+ struct bio_vec *bvec = qvec->bvec;
+ struct bvec_iter iter;
+ u32 off = CLU_OFF(qcow2, start);
+
+ if (WARN_ON_ONCE(start >= end))
+ return -EINVAL;
+
+ iter.bi_size = end - start;
+ iter.bi_idx = *consumed / PAGE_SIZE;
+ iter.bi_bvec_done = off & ~PAGE_MASK;
+
+ *consumed += round_up(end, PAGE_SIZE) - round_down(start, PAGE_SIZE);
+
+ return copy_buf_to_bvec_iter(bvec, &iter, buf + off, clu_size - off);
+}
+
+static int prepare_zcow_slices(struct qcow2 *qcow2, void *buf, struct qio *qio)
+{
+ loff_t consumed = 0;
+ /* Place required slices in that pages like further COW expects */
+ for_each_cow_interval(qio, copy_zcow_slice, qio, buf, &consumed);
+ return 0;
+}
+
+static void compressed_read_complete(struct qio *qio)
+{
+ struct md_page *md = qio->ext->lx_md;
+ struct qcow2 *qcow2 = qio->qcow2;
+ int ret = qio->ret;
+
+ dec_wpc_readers(qcow2, md); /* We ended to use compressed clu on disk */
+ /*
+ * We don't interpret as error a positive ret, which is less,
+ * then submitted. Decompress will fail, if we read not enough.
+ */
+ if (ret < 0) {
+ qio->bi_status = errno_to_blk_status(ret ? : -EIO);
+ qio_endio(qio);
+ return;
+ }
+
+ qio->queue_list_id = QLIST_ZREAD;
+ dispatch_qios(qcow2, qio, NULL);
+}
+
+static void submit_read_compressed(struct qcow2_map *map, struct qio *qio,
+ bool for_cow)
+{
+ u32 off, nr_pages, nr_alloc, nr_segs;
+ struct md_page *l2_md = map->l2.md;
+ struct qcow2 *qcow2 = map->qcow2;
+ u32 clu_size = qcow2->clu_size;
+ struct qcow2_bvec *qvec;
+ struct iov_iter iter;
+ loff_t pos, end;
+
+ WARN_ON_ONCE(!map->data_clu_pos);
+ pos = round_down(map->data_clu_pos, PAGE_SIZE);
+ end = compressed_clu_end_pos(map->data_clu_pos, map->compressed_sectors);
+ end = round_up(end, PAGE_SIZE);
+ nr_pages = (end - pos) / PAGE_SIZE;
+
+ nr_alloc = nr_pages;
+ if (for_cow) {
+ qio->ext->cow_mask = calc_cow_mask(qcow2, map->ext_l2, qio,
+ true, map->clu_is_cow, false);
+
+ /* COW reuses this qvec to write rest of cluster */
+ nr_alloc = nr_segs = 0;
+ for_each_cow_interval(qio, count_cow_pages,
+ &nr_alloc, &nr_segs, NULL);
+ if (unlikely(nr_alloc < nr_pages))
+ nr_alloc = nr_pages;
+ qio->ext->cow_segs = nr_segs;
+ }
+
+ qvec = alloc_qvec_with_pages(nr_alloc);
+ /* COW may already allocate qio->ext */
+ if (!qvec || (!qio->ext && alloc_qio_ext(qio) < 0)) {
+ free_qvec_with_pages(qvec);
+ qio->bi_status = BLK_STS_RESOURCE;
+ qio_endio(qio); /* Frees ext */
+ return;
+ }
+ qio->ext->zdata_off = off = map->data_clu_pos - pos;
+ WARN_ON_ONCE(off > ~(u16)0);
+
+ qio->complete = compressed_read_complete;
+ qio->data = qvec;
+ qio->ext->cleanup_mask |= FREE_QIO_DATA_QVEC;
+ qio->ext->lx_md = l2_md;
+ if (for_cow && qcow2->ext_l2)
+ qio->ext->new_ext_l2 = 0x00000000FFFFFFFF;
+ inc_wpc_readers(l2_md);
+
+ if (qio->bi_iter.bi_size == clu_size && for_cow) {
+ /*
+ * Optimization: do not read clu from disk
+ * in case of here is complete clu rewrite.
+ * See the way process_cow_data_write()
+ * updates qvec.
+ */
+ qio->ret = clu_size;
+ cow_read_complete(qio); /* Also skip extract part */
+ return;
+ }
+
+ iov_iter_bvec(&iter, READ, qvec->bvec, nr_pages, end - pos);
+ call_rw_iter(qcow2->file, pos, READ, &iter, qio);
+}
+
+static void sliced_cow_read_complete(struct qcow2_target *tgt, struct qio *read_qio,
+ void *qio_ptr, blk_status_t bi_status)
+{
+ struct qio *qio = qio_ptr;
+ struct qcow2 *qcow2 = qio->qcow2;
+
+ if (unlikely(bi_status)) {
+ qio->bi_status = bi_status;
+ qio_endio(qio);
+ } else {
+ qio->queue_list_id = QLIST_COW_DATA;
+ dispatch_qios(qcow2, qio, NULL);
+ }
+}
+
+/*
+ * This creates a chain from qios going to discontinuous
+ * slices of COW cluster. The main qio of chain will call
+ * endio_cb only after all children qios are completed.
+ */
+static int split_sliced_cow_qio(loff_t start, loff_t end,
+ void *qio_p, void *list_p,
+ void *nr_segs_remaining_p)
+{
+ u32 *nr_segs = nr_segs_remaining_p;
+ struct qio *split, *qio = qio_p;
+ struct qcow2 *qcow2 = qio->qcow2;
+ struct list_head *list = list_p;
+ u32 size = end - start;
+
+ if (WARN_ON_ONCE(start >= end))
+ return -EINVAL;
+
+ qio->bi_iter.bi_size = UINT_MAX; /* Silence qio_advance() */
+
+ if (start & ~PAGE_MASK) {
+ /* Skip our alignment. This only advances qio->bi_io_vec */
+ qio_advance(qio, start & ~PAGE_MASK);
+ }
+
+ if (--*nr_segs > 0) {
+ split = split_and_chain_qio(qcow2, qio, size);
+ if (!split)
+ return -ENOMEM;
+ if (end & ~PAGE_MASK) {
+ /* Skip our alignment: next does not want it */
+ qio_advance(qio, PAGE_SIZE - (end & ~PAGE_MASK));
+ }
+ list_add_tail(&split->link, list);
+ qio = split;
+ }
+
+ qio->bi_iter.bi_sector = to_sector(start);
+ qio->bi_iter.bi_size = size;
+ return 0;
+}
+
+static void submit_read_sliced_clu(struct qcow2_map *map, struct qio *qio,
+ qcow2_endio_t endio_cb)
+
+{
+ struct qcow2 *qcow2 = map->qcow2;
+ struct qcow2_bvec *qvec;
+ u32 nr_pages, nr_segs;
+ struct qio *read_qio;
+ LIST_HEAD(list);
+ int ret;
+
+ nr_pages = nr_segs = 0;
+ for_each_cow_interval(qio, count_cow_pages,
+ &nr_pages, &nr_segs, NULL);
+
+ qio->ext->lx_md = map->l2.md;
+ qio->ext->cow_segs = nr_segs;
+
+ if (!nr_segs) { /* Full overwrite */
+ qio->data = NULL; /* qvec */
+ endio_cb(qcow2->tgt, NULL, qio, BLK_STS_OK);
+ goto out;
+ }
+
+ read_qio = alloc_clu_read_qio(qcow2, nr_pages, &qvec);
+ if (!read_qio)
+ goto err_alloc;
+ read_qio->flags |= QIO_FREE_ON_ENDIO_FL;
+ read_qio->endio_cb = endio_cb;
+ read_qio->endio_cb_data = qio;
+
+ qio->data = qvec;
+ qio->ext->cleanup_mask |= FREE_QIO_DATA_QVEC;
+
+ ret = for_each_cow_interval(qio, split_sliced_cow_qio,
+ read_qio, &list, &nr_segs);
+ list_add_tail(&read_qio->link, &list);
+ if (ret)
+ goto err_split;
+
+ while ((read_qio = qio_list_pop(&list)) != NULL)
+ process_read_qio(qcow2, read_qio, map);
+out:
+ return;
+err_split:
+ end_qios(&list, BLK_STS_RESOURCE);
+ goto out;
+err_alloc:
+ qio->bi_status = BLK_STS_RESOURCE;
+ qio_endio(qio);
+ goto out;
+
+}
+
+static void submit_read_sliced_cow_clu(struct qcow2_map *map, struct qio *qio)
+{
+ struct qcow2 *qcow2 = map->qcow2;
+ u64 mask = 0;
+
+ WARN_ON_ONCE(!(map->level & L2_LEVEL));
+
+ if (qcow2->ext_l2) {
+ mask = map->ext_l2 & ~((u64)map->subclus_mask << 32);
+ qio->ext->new_ext_l2 = mask | map->subclus_mask;
+ if (map->data_clu_alloced && !map->clu_is_cow) {
+ qio->ext->only_set_ext_l2 = true;
+ qio->ext->allocated_clu_pos = map->data_clu_pos;
+ }
+ qio->ext->cow_mask = calc_cow_mask(qcow2, map->ext_l2, qio,
+ true, map->clu_is_cow, false);
+ }
+
+ submit_read_sliced_clu(map, qio, sliced_cow_read_complete);
+}
+
+static void submit_top_delta_read(struct qcow2_map *map, struct qio *qio)
+{
+ struct qcow2 *qcow2 = map->qcow2;
+
+ if (qcow2->ext_l2) {
+ qio->ext->cow_mask = calc_cow_mask(qcow2, map->ext_l2, qio,
+ false, true, true);
+ qio->ext->new_ext_l2 = 0; /* For discard */
+ }
+ submit_read_sliced_clu(map, qio, backward_merge_read_complete);
+}
+
+static void issue_discard(struct qcow2_map *map, struct qio *qio)
+{
+ struct qcow2 *qcow2 = map->qcow2;
+ loff_t pos;
+ int ret;
+
+ WARN_ON_ONCE(!(map->level & L2_LEVEL));
+ pos = bio_sector_to_file_pos(qcow2, qio, map);
+ ret = punch_hole(qcow2->file, pos, qio->bi_iter.bi_size);
+
+ if (ret)
+ qio->bi_status = errno_to_blk_status(ret);
+ qio_endio(qio);
+}
+
+static int handle_metadata(struct qcow2 *qcow2, struct qio **qio,
+ struct qcow2_map *map)
+{
+ bool write = op_is_write((*qio)->bi_op);
+ int ret;
+
+ ret = parse_metadata(qcow2, qio, map, write);
+ if (ret < 0 || !*qio) /* Error or postponed */
+ goto check_err;
+
+ ret = 1;
+ if (unlikely(qcow2->backward_merge_in_process)) {
+ /* Keep in mind the below may replace *qio */
+ ret = prepare_backward_merge(qcow2, qio, map, write);
+ } else if (unlikely(fake_l1cow_qio(*qio)) &&
+ (!map->clu_is_cow || (map->level & L2_LEVEL))) {
+ /* Nothing to COW or L1 is mapped exactly once */
+ qio_endio(*qio);
+ ret = 0;
+ } else if (write &&
+ (!qio_is_fully_alloced(qcow2, *qio, map) || map->clu_is_cow)) {
+ if (map->clu_is_cow) {
+ /* COW to compressed or shared with snapshot cluster */
+ ret = prepare_l1l2_cow(qcow2, *qio, map);
+ } else if ((map->level & L2_LEVEL) &&
+ qio_border_is_inside_unmapped_unit(qcow2, *qio, map) &&
+ maybe_mapped_in_lower_delta(qcow2, *qio)) {
+ /*
+ * Backing file is about data COW, and it is
+ * never about metadata COW (unlike internal
+ * snapshots). Here is data COW on L2_LEVEL.
+ */
+ map->backing_file_cow = true;
+ ret = prepare_l1l2_cow(qcow2, *qio, map);
+ } else if (unlikely(op_is_discard((*qio)->bi_op) &&
+ (map->level & L2_LEVEL))) {
+ if (!map->data_clu_alloced) {
+ qio_endio(*qio);
+ ret = 0;
+ }
+ /* Otherwise issue_discard(). TODO: update L2 */
+ } else {
+ /* Wants L1 or L2 entry allocation */
+ ret = prepare_l1l2_allocation(qcow2, *qio, map);
+ }
+ }
+
+check_err:
+ if (ret < 0) {
+ (*qio)->bi_status = errno_to_blk_status(ret);
+ qio_endio(*qio);
+ ret = 0;
+ }
+
+ return ret;
+}
+
+static void process_read_qio(struct qcow2 *qcow2, struct qio *qio,
+ struct qcow2_map *map)
+{
+ bool unmapped, zeroes, try_lower;
+ struct qio *split;
+ u32 size;
+
+ do {
+ unmapped = try_lower = false;
+ split = NULL;
+
+ zeroes = (size = qio_all_zeroes_size(qcow2, qio, map));
+ if (!size)
+ unmapped = (size = qio_unmapped_size(qcow2, qio, map));
+ if (!size)
+ size = qio_mapped_not_zeroes_size(qcow2, qio, map);
+
+ if (unmapped)
+ try_lower = maybe_mapped_in_lower_delta(qcow2, qio);
+
+ if (zeroes || (unmapped && !try_lower)) {
+ /* All zeroes or clu is not allocated */
+ perform_zero_read(qio, size);
+ if (size == qio->bi_iter.bi_size) {
+ qio_endio(qio);
+ break;
+ }
+ qio_advance(qio, size);
+ continue;
+ }
+
+ if (size < qio->bi_iter.bi_size) {
+ split = split_and_chain_qio(qcow2, qio, size);
+ if (!split)
+ goto err;
+ swap(qio, split);
+ }
+
+ if (unmapped && try_lower) {
+ /* Try to read from lower delta */
+ shorten_and_zero_qio_tail(qcow2->lower, qio);
+ qio->qcow2 = qcow2->lower;
+ WARN_ON_ONCE(qio->queue_list_id != QLIST_DEFERRED);
+ dispatch_qios(qio->qcow2, qio, NULL);
+ } else {
+ /* Mapped */
+ perform_rw_mapped(map, qio);
+ }
+
+ qio = split;
+ } while (qio);
+
+ return;
+err:
+ qio->bi_status = BLK_STS_RESOURCE;
+ qio_endio(qio);
+}
+
+static void process_one_qio(struct qcow2 *qcow2, struct qio *qio)
+{
+ struct qcow2_map map = { .qcow2 = qcow2, };
+ bool write;
+
+ if (!handle_metadata(qcow2, &qio, &map))
+ return;
+
+ if (unlikely(qcow2->backward_merge_in_process)) {
+ submit_top_delta_read(&map, qio);
+ return;
+ }
+
+ write = op_is_write(qio->bi_op);
+
+ if (unlikely(map.compressed)) {
+ /* Compressed qio never uses sub-clus */
+ submit_read_compressed(&map, qio, write);
+ return;
+ }
+
+ if (!write) {
+ process_read_qio(qcow2, qio, &map);
+ } else { /* write */
+ if (unlikely(map.clu_is_cow && !(map.level & L2_LEVEL)))
+ submit_read_whole_cow_clu(&map, qio);
+ else if (unlikely(map.clu_is_cow || map.backing_file_cow))
+ submit_read_sliced_cow_clu(&map, qio);
+ else if (unlikely(op_is_discard(qio->bi_op)))
+ issue_discard(&map, qio);
+ else
+ perform_rw_mapped(&map, qio);
+ }
+}
+
+static struct bio_vec *create_bvec_from_rq(struct request *rq)
+{
+ struct bio_vec bv, *bvec, *tmp;
+ struct req_iterator rq_iter;
+ unsigned int nr_bvec = 0;
+
+ rq_for_each_bvec(bv, rq, rq_iter)
+ nr_bvec++;
+
+ bvec = kmalloc_array(nr_bvec, sizeof(struct bio_vec),
+ GFP_NOIO);
+ if (!bvec)
+ goto out;
+
+ tmp = bvec;
+ rq_for_each_bvec(bv, rq, rq_iter) {
+ *tmp = bv;
+ tmp++;
+ }
+out:
+ return bvec;
+}
+
+static void prepare_one_embedded_qio(struct qcow2 *qcow2, struct qio *qio,
+ struct list_head *deferred_qios)
+{
+ struct qcow2_rq *qrq = embedded_qio_to_qrq(qio);
+ struct request *rq = qrq->rq;
+ struct bio_vec *bvec = NULL;
+ LIST_HEAD(list);
+ int ret;
+
+ if (rq->bio != rq->biotail) {
+ if (req_op(rq) == REQ_OP_DISCARD)
+ goto skip_bvec;
+ /*
+ * Transform a set of bvec arrays related to bios
+ * into a single bvec array (which we can iterate).
+ */
+ bvec = create_bvec_from_rq(rq);
+ if (unlikely(!bvec))
+ goto err;
+ qrq->bvec = bvec;
+skip_bvec:
+ qio->bi_iter.bi_sector = blk_rq_pos(rq);
+ qio->bi_iter.bi_size = blk_rq_bytes(rq);
+ qio->bi_iter.bi_idx = 0;
+ qio->bi_iter.bi_bvec_done = 0;
+ } else {
+ /* Single bio already provides bvec array */
+ bvec = rq->bio->bi_io_vec;
+
+ qio->bi_iter = rq->bio->bi_iter;
+ }
+
+ qio->bi_io_vec = bvec;
+ qio->queue_list_id = QLIST_DEFERRED;
+
+ ret = split_qio_to_list(qcow2, qio, deferred_qios);
+ if (unlikely(ret < 0))
+ goto err;
+
+ return;
+err:
+ qio->bi_status = BLK_STS_RESOURCE;
+ qio_endio(qio);
+}
+
+static void process_embedded_qios(struct qcow2 *qcow2, struct list_head *qios,
+ struct list_head *deferred_qios)
+{
+ struct qio *qio;
+
+ while ((qio = qio_list_pop(qios)))
+ prepare_one_embedded_qio(qcow2, qio, deferred_qios);
+}
+
+static void process_deferred_qios(struct qcow2 *qcow2, struct list_head *qios)
+{
+ struct qio *qio;
+
+ while ((qio = qio_list_pop(qios))) {
+ /* Sanity: on this stage we do not expect ext */
+ if (WARN_ON_ONCE(qio->ext != NULL)) {
+ qio->bi_status = BLK_STS_IOERR;
+ qio_endio(qio);
+ continue;
+ }
+
+ process_one_qio(qcow2, qio);
+ }
+}
+
+static void submit_metadata_writeback(struct qcow2 *qcow2)
+{
+ struct md_page *md;
+
+ while (1) {
+ spin_lock_irq(&qcow2->md_pages_lock);
+ md = list_first_entry_or_null(&qcow2->wb_batch_list,
+ struct md_page, wb_link);
+ if (!md) {
+ spin_unlock_irq(&qcow2->md_pages_lock);
+ break;
+ }
+ list_del_init(&md->wb_link);
+ /* L1L2 mustn't be redirtyed, when wb in-flight! */
+ WARN_ON_ONCE(!(md->status & MD_DIRTY) ||
+ (md->wbd && (md->status & MD_WRITEBACK)));
+ md->status |= MD_WRITEBACK;
+ md->status &= ~MD_DIRTY;
+ spin_unlock_irq(&qcow2->md_pages_lock);
+
+ submit_rw_md_page(WRITE, qcow2, md);
+ }
+}
+
+static int complete_metadata_writeback(struct qcow2 *qcow2)
+{
+ struct qcow2_bvec *qvec;
+ struct md_page *md;
+ int fsync_ret, ret;
+ LIST_HEAD(wb_list);
+ struct qio *qio;
+
+ spin_lock_irq(&qcow2->deferred_lock);
+ list_splice_init(&qcow2->qios[QLIST_COMPLETED_WB], &wb_list);
+ spin_unlock_irq(&qcow2->deferred_lock);
+ if (unlikely(list_empty(&wb_list)))
+ return -EAGAIN;
+
+ fsync_ret = vfs_fsync(qcow2->file, 0);
+ /* FIXME: We should reread md page on error */
+ if (unlikely(fsync_ret))
+ pr_err_ratelimited("qcow2: can't sync md: %d\n", fsync_ret);
+
+ while (!list_empty(&wb_list)) {
+ qio = list_first_entry(&wb_list, struct qio, link);
+ list_del(&qio->link);
+ md = qio->ext->md;
+ qvec = qio->data;
+ ret = qio->ret;
+ if (unlikely(ret != PAGE_SIZE))
+ ret = -EIO;
+ else
+ ret = fsync_ret;
+
+ do_md_page_write_complete(ret, qcow2, md);
+ dec_inflight_md(qcow2, qio);
+ kfree(qvec); /* qio and ext are tail bytes after qvec */
+ }
+
+ return fsync_ret;
+}
+
+/* Process completed compressed READs */
+static void process_compressed_read(struct qcow2 *qcow2, struct list_head *read_list,
+ struct list_head *cow_list)
+{
+ struct qcow2_bvec *qvec;
+ struct qio_ext *ext;
+ blk_status_t ret;
+ void *buf = NULL;
+ struct qio *qio;
+ bool for_cow;
+
+ if (list_empty(read_list))
+ return;
+
+ buf = kmalloc(qcow2->clu_size + zlib_inflate_workspacesize(), GFP_NOIO);
+ if (!buf) {
+ end_qios(read_list, BLK_STS_RESOURCE);
+ return;
+ }
+
+ while ((qio = qio_list_pop(read_list)) != NULL) {
+ qvec = qio->data;
+ ext = qio->ext;
+
+ ret = extract_one_compressed(qcow2, buf, qvec,
+ ext->zdata_off, qio->ret);
+ if (ret)
+ goto err;
+
+ for_cow = op_is_write(qio->bi_op);
+ if (!for_cow)
+ ret = copy_clu_part_to_qio(qcow2, buf, qio);
+ else
+ ret = prepare_zcow_slices(qcow2, buf, qio);
+
+ if (!for_cow || ret) {
+err:
+ if (ret)
+ qio->bi_status = errno_to_blk_status(ret);
+ qio_endio(qio);
+ continue;
+ }
+
+ /* Further COW processing */
+ qio->queue_list_id = QLIST_COW_DATA;
+ list_add_tail(&qio->link, cow_list);
+ }
+
+ kfree(buf);
+}
+
+static int prepare_sliced_data_write(struct qcow2 *qcow2, struct qio *qio,
+ struct list_head *list, qcow2_endio_t endio)
+{
+ struct qcow2_target *tgt = qcow2->tgt;
+ struct qcow2_bvec *qvec = qio->data;
+ u32 nr_segs = qio->ext->cow_segs;
+ struct qio *write_qio, *aux_qio;
+ int ret;
+
+ WARN_ON_ONCE(qio->bi_op == REQ_OP_READ && nr_segs == 0);
+
+ write_qio = alloc_qio(tgt->qio_pool, true);
+ if (!write_qio)
+ goto err_qio;
+ init_qio(write_qio, REQ_OP_WRITE, qcow2);
+ write_qio->flags |= QIO_FREE_ON_ENDIO_FL;
+ write_qio->endio_cb = endio;
+ write_qio->endio_cb_data = qio;
+
+ if (qio->bi_op != REQ_OP_READ && !fake_merge_qio(qio)) {
+ /* Create aux qio to chain @qio bytes write there */
+ aux_qio = write_qio;
+ if (nr_segs) {
+ aux_qio = split_and_chain_qio(qcow2, write_qio, 0);
+ if (!aux_qio) {
+ free_qio(write_qio, tgt->qio_pool);
+ goto err_qio;
+ }
+ list_add(&aux_qio->link, list);
+ }
+ aux_qio->bi_op = qio->bi_op;
+ aux_qio->bi_io_vec = qio->bi_io_vec;
+ aux_qio->bi_iter = qio->bi_iter;
+
+ if (!nr_segs) { /* Full overwrite */
+ list_add(&aux_qio->link, list);
+ goto out;
+ }
+ }
+
+ write_qio->bi_io_vec = qvec->bvec;
+ write_qio->bi_iter.bi_idx = 0;
+ write_qio->bi_iter.bi_bvec_done = 0;
+
+ ret = for_each_cow_interval(qio, split_sliced_cow_qio,
+ write_qio, list, &nr_segs);
+ list_add_tail(&write_qio->link, list);
+ if (ret)
+ goto err_split;
+out:
+ return 0;
+err_split:
+ end_qios(list, BLK_STS_RESOURCE);
+ goto out;
+err_qio:
+ qio->bi_status = BLK_STS_RESOURCE;
+ qio_endio(qio);
+ goto out;
+}
+
+static void process_backward_merge_write(struct qcow2 *qcow2, struct list_head *qio_list)
+{
+ qcow2_endio_t endio = backward_merge_write_complete;
+ struct qio *qio;
+ LIST_HEAD(list);
+
+ while (1) {
+ qio = qio_list_pop(qio_list);
+ if (!qio)
+ break;
+
+ if (prepare_sliced_data_write(qcow2->lower, qio,
+ &list, endio) < 0)
+ continue;
+
+ dispatch_qios(qcow2->lower, NULL, &list);
+ }
+}
+
+static void cow_data_write_complete(struct qio *qio)
+{
+ struct qcow2 *qcow2 = qio->qcow2;
+ int ret = qio->ret;
+
+ BUG_ON(!qio->ext);
+
+ if (ret > 0 && ret != qcow2->clu_size)
+ ret = -EIO;
+ if (ret < 0) {
+ qio->bi_status = errno_to_blk_status(ret);
+ qio_endio(qio);
+ } else {
+ qio->queue_list_id = QLIST_COW_INDEXES;
+ dispatch_qios(qcow2, qio, NULL);
+ }
+}
+
+static void submit_cow_data_write(struct qcow2 *qcow2, struct qio *qio, loff_t pos)
+{
+ u32 nr_segs, clu_size = qcow2->clu_size;
+ struct qcow2_bvec *qvec = qio->data;
+ struct iov_iter iter;
+
+ nr_segs = clu_size >> PAGE_SHIFT;
+ WARN_ON_ONCE(qvec->nr_pages < nr_segs);
+
+ iov_iter_bvec(&iter, WRITE, qvec->bvec, nr_segs, clu_size);
+ qio->complete = cow_data_write_complete;
+
+ call_rw_iter(qcow2->file, pos, WRITE, &iter, qio);
+}
+
+static void sliced_cow_data_write_complete(struct qcow2_target *tgt, struct qio *unused,
+ void *qio_ptr, blk_status_t bi_status)
+
+{
+ struct qio *qio = qio_ptr;
+ struct qcow2 *qcow2 = qio->qcow2;
+
+ BUG_ON(!qio->ext);
+
+ if (bi_status) {
+ qio->bi_status = bi_status;
+ qio_endio(qio);
+ } else {
+ qio->queue_list_id = QLIST_COW_INDEXES;
+ dispatch_qios(qcow2, qio, NULL);
+ }
+}
+
+static void submit_sliced_cow_data_write(struct qcow2 *qcow2, struct qio *qio, loff_t clu_pos)
+{
+ qcow2_endio_t endio = sliced_cow_data_write_complete;
+ struct qio *write_qio;
+ LIST_HEAD(list);
+
+ if (prepare_sliced_data_write(qcow2, qio, &list, endio) < 0)
+ return;
+
+ while ((write_qio = qio_list_pop(&list)) != NULL) {
+ write_qio->complete = data_rw_complete;
+ write_qio->data = NULL;
+ submit_rw_mapped(qcow2, clu_pos, write_qio);
+ }
+}
+
+static void process_cow_data_write(struct qcow2 *qcow2, struct list_head *cow_list)
+{
+ struct qio_ext *ext;
+ struct qio *qio;
+ loff_t pos;
+
+ while (1) {
+ qio = qio_list_pop(cow_list);
+ if (!qio)
+ break;
+ ext = qio->ext;
+
+ if (ext->only_set_ext_l2) {
+ WARN_ON_ONCE(ext->cow_level != L2_LEVEL);
+ pos = ext->allocated_clu_pos;
+ goto submit;
+ }
+
+ WARN_ON_ONCE(qio->queue_list_id != QLIST_COW_DATA);
+ pos = allocate_cluster(qcow2, qio, &ext->r2_md,
+ &ext->r2_index_in_page);
+ if (pos < 0) {
+ qio->bi_status = errno_to_blk_status(pos);
+ qio_endio(qio);
+ }
+
+ if (pos <= 0)
+ continue;
+
+ ext->allocated_clu_pos = pos;
+ ext->cleanup_mask |= FREE_ALLOCATED_CLU;
+submit:
+ if (ext->cow_level == L2_LEVEL)
+ submit_sliced_cow_data_write(qcow2, qio, pos);
+ else
+ submit_cow_data_write(qcow2, qio, pos);
+ }
+}
+
+static void process_cow_indexes_write(struct qcow2 *qcow2,
+ struct list_head *qio_list)
+{
+ struct qcow2_bvec *qvec;
+ struct md_page *lx_md;
+ struct qio_ext *ext;
+ struct qio *qio;
+ bool discard;
+ u32 arg_mask;
+ int ret;
+
+ while (1) {
+ qio = qio_list_pop(qio_list);
+ if (!qio)
+ break;
+ ext = qio->ext;
+ qvec = qio->data;
+ lx_md = ext->lx_md;
+
+ /* Return back to the same stage in case of writeback */
+ qio->queue_list_id = QLIST_COW_INDEXES;
+ if (delay_if_writeback(qcow2, lx_md, -1, &qio, true))
+ continue;
+
+ discard = (qio->flags & QIO_IS_DISCARD_FL) ? true : false;
+ WARN_ON_ONCE(discard && ext->allocated_clu_pos);
+
+ arg_mask = (discard ? 0 : LU_SET_ONE_MASK) | LU_WANTS_PE_PAGE;
+ if (ext->only_set_ext_l2) {
+ WARN_ON_ONCE(ext->cow_level != L2_LEVEL);
+ goto set_ext_l2;
+ }
+
+ /* XXX: check prealloced_pos ==> revert */
+ ret = prepare_l_entry_update(qcow2, qio, lx_md,
+ ext->lx_index_in_page,
+ &ext->allocated_clu_pos,
+ arg_mask);
+ if (ret < 0) {
+ qio->bi_status = errno_to_blk_status(ret);
+ qio_endio(qio);
+ continue;
+ }
+set_ext_l2:
+ if (qcow2->ext_l2 && ext->cow_level == L2_LEVEL) {
+ arg_mask &= ~LU_SET_ONE_MASK;
+ ret = prepare_l_entry_update(qcow2, qio, lx_md,
+ ext->lx_index_in_page + 1,
+ &ext->new_ext_l2, arg_mask);
+ WARN_ON_ONCE(ret < 0);
+ }
+
+ /* Next stage */
+ qio->queue_list_id = QLIST_COW_END;
+
+ spin_lock_irq(&qcow2->md_pages_lock);
+ /*
+ * Prohibit to start new reads from WP clusters.
+ * Otherwise, "wpc_readers == 0" never happens.
+ */
+ WARN_ON_ONCE(lx_md->wpc_noread_count++ < 0);
+ ext->cleanup_mask |= DEC_WPC_NOREAD_COUNT;
+
+ /* Wait md page writeback */
+ list_add_tail(&qio->link, &lx_md->wbd->dependent_list);
+ spin_unlock_irq(&qcow2->md_pages_lock);
+ }
+}
+
+/* Finalize successful COW */
+static void process_cow_end(struct qcow2 *qcow2, struct list_head *qio_list)
+{
+ u32 mask, clu_size = qcow2->clu_size;
+ struct qcow2_map_item r1, r2;
+ struct qio_ext *ext;
+ struct qio *qio;
+ loff_t pos;
+ int ret;
+
+ while (1) {
+next: qio = qio_list_pop(qio_list);
+ if (!qio)
+ break;
+ ext = qio->ext;
+ /* L2 index was written, cluster became used */
+ if (ext->cleanup_mask & FREE_ALLOCATED_CLU)
+ ext->cleanup_mask &= ~FREE_ALLOCATED_CLU;
+
+ /* Should be already set... */
+ qio->queue_list_id = QLIST_COW_END;
+ /*
+ * Wait last user before we (possible) mark clusters
+ * unused. In real only compressed COW requires this.
+ */
+ if (delay_if_has_wpc_readers(qcow2, ext->lx_md, &qio))
+ goto next;
+
+ pos = ext->cow_clu_pos;
+ for (; pos < ext->cow_clu_end; pos += clu_size) {
+ ret = __handle_r1r2_maps(qcow2, pos, &qio, &r1, &r2);
+ if (ret == 0) /* We never shrink md pages, impossible */
+ goto next;
+ if (WARN_ON_ONCE(ret < 0))
+ pr_err("qcow2: clu at %lld leaked\n", pos);
+ else
+ dec_cluster_usage(qcow2, r2.md, r2.index_in_page, pos);
+ ext->cow_clu_pos += clu_size;
+ }
+
+ mask = MD_INDEX_SET_UNLOCKED|DEC_WPC_NOREAD_COUNT;
+ if (qio->data)
+ mask |= FREE_QIO_DATA_QVEC;
+ WARN_ON_ONCE(ext->cleanup_mask != mask); /* Sanity check */
+
+ if (ext->cow_level == L1_LEVEL) {
+ finalize_qio_ext(qio);
+ /* COW on L1 completed, it's time for COW on L2 */
+ qio->queue_list_id = QLIST_DEFERRED;
+ dispatch_qios(qcow2, qio, NULL);
+ } else {
+ /*
+ * This qio was already written together with clu.
+ * Nothing to do. See process_cow_data_write().
+ */
+ qio_endio(qio); /* Makes all cleanup */
+ }
+ }
+}
+
+void do_qcow2_work(struct work_struct *ws)
+{
+ struct qcow2 *qcow2 = container_of(ws, struct qcow2, worker);
+ LIST_HEAD(embedded_qios);
+ LIST_HEAD(deferred_qios);
+ LIST_HEAD(zread_qios);
+ LIST_HEAD(bwrite_qios);
+ LIST_HEAD(cow_data_qios);
+ LIST_HEAD(cow_indexes_qios);
+ LIST_HEAD(cow_end_qios);
+ unsigned int pflags = current->flags;
+
+ current->flags |= PF_LESS_THROTTLE|PF_MEMALLOC_NOIO;
+ spin_lock_irq(&qcow2->deferred_lock);
+ list_splice_init(&qcow2->qios[QLIST_EMBEDDED], &embedded_qios);
+ list_splice_init(&qcow2->qios[QLIST_DEFERRED], &deferred_qios);
+ list_splice_init(&qcow2->qios[QLIST_ZREAD], &zread_qios);
+ list_splice_init(&qcow2->qios[QLIST_BMERGE_WRITE], &bwrite_qios);
+ list_splice_init(&qcow2->qios[QLIST_COW_DATA], &cow_data_qios);
+ list_splice_init(&qcow2->qios[QLIST_COW_INDEXES], &cow_indexes_qios);
+ list_splice_init(&qcow2->qios[QLIST_COW_END], &cow_end_qios);
+ spin_unlock_irq(&qcow2->deferred_lock);
+
+ process_embedded_qios(qcow2, &embedded_qios, &deferred_qios);
+ process_deferred_qios(qcow2, &deferred_qios);
+ process_compressed_read(qcow2, &zread_qios, &cow_data_qios);
+ process_backward_merge_write(qcow2, &bwrite_qios);
+ process_cow_data_write(qcow2, &cow_data_qios);
+ process_cow_indexes_write(qcow2, &cow_indexes_qios);
+ process_cow_end(qcow2, &cow_end_qios);
+
+ /* This actually submits batch of md writeback, initiated above */
+ submit_metadata_writeback(qcow2);
+
+ current_restore_flags(pflags, PF_LESS_THROTTLE|PF_MEMALLOC_NOIO);
+}
+
+void do_qcow2_fsync_work(struct work_struct *ws)
+{
+ struct qcow2 *qcow2 = container_of(ws, struct qcow2, fsync_worker);
+ unsigned int pflags = current->flags;
+ LIST_HEAD(flush_qios);
+ int fsync_ret;
+
+ current->flags |= PF_LESS_THROTTLE|PF_MEMALLOC_NOIO;
+ spin_lock_irq(&qcow2->deferred_lock);
+ list_splice_tail_init(&qcow2->qios[QLIST_FLUSH], &flush_qios);
+ spin_unlock_irq(&qcow2->deferred_lock);
+
+ fsync_ret = complete_metadata_writeback(qcow2);
+ /*
+ * Metadata writeback and flush bios are independent
+ * each other, but we want avoid excess fsync() call,
+ * if it's already done.
+ */
+ if (fsync_ret == -EAGAIN)
+ fsync_ret = vfs_fsync(qcow2->file, 0);
+
+ end_qios(&flush_qios, errno_to_blk_status(fsync_ret));
+
+ current_restore_flags(pflags, PF_LESS_THROTTLE|PF_MEMALLOC_NOIO);
+}
+
+static void qrq_endio(struct qcow2_target *tgt, struct qio *unused,
+ void *qrq_ptr, blk_status_t bi_status)
+{
+ struct qcow2_rq *qrq = qrq_ptr;
+ struct request *rq = qrq->rq;
+
+ if (qrq->bvec)
+ kfree(qrq->bvec);
+ dm_complete_request(rq, bi_status);
+}
+
+static void init_qrq(struct qcow2_rq *qrq, struct request *rq)
+{
+ qrq->rq = rq;
+ qrq->bvec = NULL;
+}
+
+void submit_embedded_qio(struct qcow2_target *tgt, struct qio *qio)
+{
+ struct qcow2_rq *qrq = embedded_qio_to_qrq(qio);
+ struct request *rq = qrq->rq;
+ u8 queue_list_id, ref_index;
+ struct work_struct *worker;
+ struct qcow2 *qcow2;
+ unsigned long flags;
+ bool queue = true;
+
+ qcow2 = qcow2_ref_inc(tgt, &ref_index);
+
+ if (blk_rq_bytes(rq)) {
+ queue_list_id = QLIST_EMBEDDED;
+ worker = &qcow2->worker;
+ } else {
+ WARN_ON_ONCE(qio->bi_op != REQ_OP_FLUSH);
+ queue_list_id = QLIST_FLUSH;
+ worker = &qcow2->fsync_worker;
+ }
+
+ spin_lock_irqsave(&qcow2->deferred_lock, flags);
+ if (unlikely(qcow2->pause_submitting_qios)) {
+ qcow2_ref_dec(tgt, ref_index);
+ list_add_tail(&qio->link, &qcow2->paused_qios);
+ queue = false;
+ } else {
+ qio->qcow2 = qcow2;
+ qio->queue_list_id = queue_list_id;
+ qio->ref_index = ref_index;
+ list_add_tail(&qio->link, &qcow2->qios[qio->queue_list_id]);
+ }
+ spin_unlock_irqrestore(&qcow2->deferred_lock, flags);
+
+ if (queue)
+ queue_work(tgt->wq, worker);
+}
+
+void submit_embedded_qios(struct qcow2_target *tgt, struct list_head *list)
+{
+ struct qio *qio;
+
+ while ((qio = qio_list_pop(list)) != NULL)
+ submit_embedded_qio(tgt, qio);
+}
+
+int qcow2_clone_and_map(struct dm_target *ti, struct request *rq,
+ union map_info *info, struct request **clone)
+{
+ struct qcow2_target *tgt = to_qcow2_target(ti);
+ struct qcow2_rq *qrq;
+ struct qio *qio;
+
+ qrq = map_info_to_embedded_qrq(info);
+ init_qrq(qrq, rq);
+
+ qio = map_info_to_embedded_qio(info);
+ init_qio(qio, req_op(rq), NULL);
+ qio->endio_cb = qrq_endio;
+ qio->endio_cb_data = qrq;
+ /*
+ * Note, this qcow2_clone_and_map() may be called from atomic
+ * context, so here we just delegate qio splitting to kwork.
+ */
+ submit_embedded_qio(tgt, qio);
+ return DM_MAPIO_SUBMITTED;
+}
+
+static void handle_cleanup_mask(struct qio *qio)
+{
+ struct qcow2 *qcow2 = qio->qcow2;
+ struct qio_ext *ext = qio->ext;
+ struct lock_desc *lockd = NULL;
+ LIST_HEAD(qio_list);
+ unsigned long flags;
+ bool last;
+
+ if (ext->cleanup_mask & MD_INDEX_SET_UNLOCKED) {
+ struct md_page *md = ext->lx_md;
+
+ spin_lock_irqsave(&qcow2->md_pages_lock, flags);
+ clear_bit(ext->lx_index_in_page, md->lockd->indexes);
+ WARN_ON_ONCE(--md->lockd->nr < 0);
+ if (!md->lockd->nr)
+ swap(md->lockd, lockd);
+ list_splice_init(&md->wait_list, &qio_list);
+ spin_unlock_irqrestore(&qcow2->md_pages_lock, flags);
+ dispatch_qios(qcow2, NULL, &qio_list);
+ kfree(lockd);
+ ext->cleanup_mask &= ~MD_INDEX_SET_UNLOCKED;
+ }
+
+ if (ext->cleanup_mask & DEC_WPC_NOREAD_COUNT) {
+ struct md_page *md = ext->lx_md;
+
+ spin_lock_irqsave(&qcow2->md_pages_lock, flags);
+ last = !(--md->wpc_noread_count);
+ if (last)
+ list_splice_init(&md->wait_list, &qio_list);
+ spin_unlock_irqrestore(&qcow2->md_pages_lock, flags);
+ if (last)
+ dispatch_qios(qcow2, NULL, &qio_list);
+ ext->cleanup_mask &= ~DEC_WPC_NOREAD_COUNT;
+ }
+
+ if (ext->cleanup_mask & FREE_QIO_DATA_QVEC) {
+ struct qcow2_bvec *qvec = qio->data;
+
+ free_qvec_with_pages(qvec);
+ qio->data = NULL;
+ ext->cleanup_mask &= ~FREE_QIO_DATA_QVEC;
+ }
+
+ if (ext->cleanup_mask & FREE_ALLOCATED_CLU) {
+ u32 index_in_page = ext->r2_index_in_page;
+ loff_t pos = ext->allocated_clu_pos;
+ struct md_page *md = ext->r2_md;
+
+ mark_cluster_unused(qcow2, md, index_in_page, pos);
+ ext->cleanup_mask &= ~FREE_ALLOCATED_CLU;
+ }
+}
diff --git a/drivers/md/dm-qcow2-target.c b/drivers/md/dm-qcow2-target.c
new file mode 100644
index 000000000000..895b69f0a767
--- /dev/null
+++ b/drivers/md/dm-qcow2-target.c
@@ -0,0 +1,935 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2021 Virtuozzo International GmbH. All rights reserved.
+ */
+#include <linux/uio.h>
+
+#include "dm.h"
+#include "dm-qcow2.h"
+
+static bool kernel_sets_dirty_bit; /* false */;
+module_param(kernel_sets_dirty_bit, bool, 0444);
+MODULE_PARM_DESC(kernel_sets_dirty_bit,
+ "Dirty bit is set by kernel, not by userspace");
+
+static void qcow2_set_service_operations(struct dm_target *ti, bool allowed)
+{
+ struct qcow2_target *tgt = to_qcow2_target(ti);
+
+ mutex_lock(&tgt->ctl_mutex);
+ tgt->service_operations_allowed = allowed;
+ mutex_unlock(&tgt->ctl_mutex);
+}
+
+static int rw_pages_sync(unsigned int rw, struct qcow2 *qcow2,
+ u64 index, struct page *pages[], int nr)
+{
+ struct bio_vec *bvec, bvec_on_stack;
+ ssize_t size = nr * PAGE_SIZE, ret;
+ struct iov_iter iter;
+ loff_t from, pos;
+ int i;
+
+ if (rw != READ && rw != WRITE)
+ return -EINVAL;
+
+ bvec = &bvec_on_stack;
+ if (nr != 1)
+ bvec = kmalloc(nr * sizeof(*bvec), GFP_NOIO);
+ if (!bvec)
+ return -ENOMEM;
+
+ for (i = 0; i < nr; i++) {
+ bvec[i].bv_page = pages[i];
+ bvec[i].bv_len = PAGE_SIZE;
+ bvec[i].bv_offset = 0;
+ }
+
+ iov_iter_bvec(&iter, rw, bvec, nr, size);
+ pos = from = index << PAGE_SHIFT;
+
+ if (rw == READ)
+ ret = vfs_iter_read(qcow2->file, &iter, &pos, 0);
+ else
+ ret = vfs_iter_write(qcow2->file, &iter, &pos, 0);
+
+ if (ret == size) {
+ ret = 0;
+ } else if (ret > 0 && pos == qcow2->file_size &&
+ from + size - qcow2->file_size < PAGE_SIZE) {
+ /* Read near EOF? */
+ zero_fill_page_from(pages[nr-1], ret % PAGE_SIZE);
+ ret = 0;
+ } else if (ret >= 0) {
+ ret = -ENODATA;
+ }
+
+ if (bvec != &bvec_on_stack)
+ kfree(bvec);
+ return ret;
+}
+
+int rw_page_sync(unsigned int rw, struct qcow2 *qcow2,
+ u64 index, struct page *page)
+{
+ struct page *pages[] = {page};
+
+ return rw_pages_sync(rw, qcow2, index, pages, 1);
+}
+
+static void qcow2_aio_do_completion(struct qio *qio)
+{
+ if (!atomic_dec_and_test(&qio->aio_ref))
+ return;
+ qio->complete(qio);
+}
+
+static void qcow2_aio_complete(struct kiocb *iocb, long ret, long ret2)
+{
+ struct qio *qio = container_of(iocb, struct qio, iocb);
+
+ WARN_ON_ONCE(ret > INT_MAX);
+ qio->ret = (int)ret;
+ qcow2_aio_do_completion(qio);
+}
+
+void call_rw_iter(struct file *file, loff_t pos, unsigned int rw,
+ struct iov_iter *iter, struct qio *qio)
+{
+ struct kiocb *iocb = &qio->iocb;
+ int ret;
+
+ iocb->ki_pos = pos;
+ iocb->ki_filp = file;
+ iocb->ki_complete = qcow2_aio_complete;
+ iocb->ki_flags = IOCB_DIRECT;
+ iocb->ki_ioprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_NONE, 0);
+
+ atomic_set(&qio->aio_ref, 2);
+
+ if (rw == WRITE)
+ ret = call_write_iter(file, iocb, iter);
+ else
+ ret = call_read_iter(file, iocb, iter);
+
+ qcow2_aio_do_completion(qio);
+
+ if (ret != -EIOCBQUEUED)
+ iocb->ki_complete(iocb, ret, 0);
+}
+
+void free_md_page(struct md_page *md)
+{
+ WARN_ON_ONCE(md->wbd || md->lockd);
+ put_page(md->page);
+ kfree(md);
+}
+
+static void free_md_pages_tree(struct rb_root *root)
+{
+ struct rb_node *node;
+ struct md_page *md;
+
+ while ((node = root->rb_node) != NULL) {
+ md = rb_entry(node, struct md_page, node);
+ rb_erase(node, root);
+ free_md_page(md);
+ }
+}
+
+/* This flushes activity remaining after qios endio (delayed md pages wb */
+void flush_deferred_activity(struct qcow2_target *tgt, struct qcow2 *qcow2)
+{
+ struct rb_node *node;
+ struct md_page *md;
+ int i;
+
+ /*
+ * We need second iteration, since revert_clusters_alloc()
+ * may start timer again after failed wb.
+ */
+ for (i = 0; i < 2; i++) {
+ del_timer_sync(&qcow2->slow_wb_timer);
+ slow_wb_timer_fn(&qcow2->slow_wb_timer);
+ /* Start md writeback */
+ flush_workqueue(tgt->wq);
+ /* Wait AIO of md wb */
+ qcow2_inflight_ref_switch(tgt);
+ }
+
+ spin_lock_irq(&qcow2->md_pages_lock);
+ 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) {
+ pr_err("qcow2: Failed to write dirty pages\n");
+ tgt->md_writeback_error = true;
+ break;
+ }
+ }
+ spin_unlock_irq(&qcow2->md_pages_lock);
+}
+
+static void flush_deferred_activity_all(struct qcow2_target *tgt)
+{
+ struct qcow2 *qcow2 = tgt->top;
+
+ while (qcow2) {
+ flush_deferred_activity(tgt, qcow2);
+ qcow2 = qcow2->lower;
+ }
+}
+static void free_md_pages_all(struct qcow2_target *tgt)
+{
+ struct qcow2 *qcow2 = tgt->top;
+
+ while (qcow2) {
+ free_md_pages_tree(&qcow2->md_pages);
+ qcow2 = qcow2->lower;
+ }
+}
+
+void qcow2_destroy(struct qcow2 *qcow2)
+{
+ int i;
+
+ for (i = 0; i < QLIST_COUNT; i++)
+ WARN(!list_empty(&qcow2->qios[i]),
+ "qcow2: list %d is not empty", i);
+
+ WARN_ON(!list_empty(&qcow2->paused_qios) ||
+ !list_empty(&qcow2->wb_batch_list) ||
+ !list_empty(&qcow2->slow_wb_batch_list) ||
+ timer_pending(&qcow2->slow_wb_timer));
+
+ free_md_pages_tree(&qcow2->md_pages);
+ if (qcow2->file)
+ fput(qcow2->file);
+
+ kfree(qcow2);
+}
+
+static void qcow2_tgt_destroy(struct qcow2_target *tgt)
+{
+ struct qcow2 *lower, *qcow2 = tgt->top;
+ unsigned int i;
+
+ if (tgt->wq) {
+ /*
+ * All activity from DM bios are already done,
+ * since DM waits them. Complete our deferred:
+ */
+ flush_deferred_activity_all(tgt);
+ /* Now kill the queue */
+ destroy_workqueue(tgt->wq);
+ mempool_destroy(tgt->qio_pool);
+ }
+
+ for (i = 0; i < 2; i++)
+ percpu_ref_exit(&tgt->inflight_ref[i]);
+
+ while (qcow2) {
+ lower = qcow2->lower;
+ qcow2_destroy(qcow2);
+ qcow2 = lower;
+ }
+
+ kfree(tgt);
+}
+
+static struct md_page *__md_page_find(struct qcow2 *qcow2, unsigned int id)
+{
+ struct rb_node *node = qcow2->md_pages.rb_node;
+ struct md_page *md;
+
+ lockdep_assert_held(&qcow2->md_pages_lock);
+
+ while (node) {
+ md = rb_entry(node, struct md_page, node);
+ if (id < md->id)
+ node = node->rb_left;
+ else if (id > md->id)
+ node = node->rb_right;
+ else
+ return md;
+ }
+
+ return NULL;
+}
+
+static struct md_page *md_page_find(struct qcow2 *qcow2, unsigned int id)
+{
+ struct md_page *md;
+
+ spin_lock_irq(&qcow2->md_pages_lock);
+ md = __md_page_find(qcow2, id);
+ spin_unlock_irq(&qcow2->md_pages_lock);
+ return md;
+}
+
+/*
+ * This returns md if it's found and up to date, or NULL.
+ * @qio is zeroed if it's postponed.
+ */
+struct md_page *md_page_find_or_postpone(struct qcow2 *qcow2, unsigned int id,
+ struct qio **qio)
+{
+ struct md_page *md;
+
+ spin_lock_irq(&qcow2->md_pages_lock);
+ md = __md_page_find(qcow2, id);
+ if (md && !(md->status & MD_UPTODATE)) {
+ if (qio) {
+ list_add_tail(&(*qio)->link, &md->wait_list);
+ *qio = NULL;
+ }
+ md = NULL;
+ }
+ spin_unlock_irq(&qcow2->md_pages_lock);
+
+ return md;
+}
+
+static void md_page_insert(struct qcow2 *qcow2, struct md_page *new_md)
+{
+ struct rb_root *root = &qcow2->md_pages;
+ unsigned int new_id = new_md->id;
+ struct rb_node *parent, **node;
+ struct md_page *md;
+
+ lockdep_assert_held(&qcow2->md_pages_lock);
+ node = &root->rb_node;
+ parent = NULL;
+
+ while (*node) {
+ parent = *node;
+ md = rb_entry(*node, struct md_page, node);
+ if (new_id < md->id)
+ node = &parent->rb_left;
+ else if (new_id > md->id)
+ node = &parent->rb_right;
+ else
+ BUG();
+ }
+
+ rb_link_node(&new_md->node, parent, node);
+ rb_insert_color(&new_md->node, root);
+}
+
+void md_page_erase(struct qcow2 *qcow2, struct md_page *md)
+{
+ lockdep_assert_held(&qcow2->md_pages_lock);
+ rb_erase(&md->node, &qcow2->md_pages);
+}
+
+struct md_page *md_page_renumber(struct qcow2 *qcow2, unsigned int id,
+ unsigned int new_id)
+{
+ struct md_page *md;
+
+ lockdep_assert_held(&qcow2->md_pages_lock);
+ md = __md_page_find(qcow2, id);
+ if (md) {
+ WARN_ON_ONCE(!list_empty(&md->wait_list));
+ md_page_erase(qcow2, md);
+ md->id = new_id;
+ md_page_insert(qcow2, md);
+ }
+ return md;
+}
+
+void zero_fill_page_from(struct page *page, unsigned int from)
+{
+ void *addr = kmap_atomic(page);
+
+ memset(addr + from, 0, PAGE_SIZE - from);
+ kunmap_atomic(addr);
+}
+
+int alloc_and_insert_md_page(struct qcow2 *qcow2, u64 index, struct md_page **md)
+{
+ int ret = -ENOMEM;
+
+ *md = kmalloc(sizeof(**md), GFP_KERNEL);
+ if (!*md)
+ return -ENOMEM;
+ (*md)->page = alloc_page(GFP_KERNEL);
+ if (!(*md)->page)
+ goto err_kfree;
+
+ (*md)->id = index;
+ (*md)->status = 0;
+ (*md)->wbd = NULL;
+ (*md)->lockd = NULL;
+ atomic_set(&(*md)->wpc_readers, 0);
+ (*md)->wpc_noread_count = 0;
+ INIT_LIST_HEAD(&(*md)->wait_list);
+ INIT_LIST_HEAD(&(*md)->wpc_readers_wait_list);
+ INIT_LIST_HEAD(&(*md)->wb_link);
+
+ spin_lock_irq(&qcow2->md_pages_lock);
+ md_page_insert(qcow2, *md);
+ spin_unlock_irq(&qcow2->md_pages_lock);
+ return 0;
+
+err_kfree:
+ kfree(*md);
+ return ret;
+}
+
+static void inflight_ref_exit0(struct percpu_ref *ref)
+{
+ struct qcow2_target *tgt = container_of(ref, struct qcow2_target,
+ inflight_ref[0]);
+ complete(&tgt->inflight_ref_comp);
+}
+
+static void inflight_ref_exit1(struct percpu_ref *ref)
+{
+ struct qcow2_target *tgt = container_of(ref, struct qcow2_target,
+ inflight_ref[1]);
+ complete(&tgt->inflight_ref_comp);
+}
+
+static struct qcow2_target *alloc_qcow2_target(struct dm_target *ti)
+{
+ percpu_ref_func_t *release;
+ struct qcow2_target *tgt;
+ unsigned int i, flags;
+
+ tgt = kzalloc(sizeof(*tgt), GFP_KERNEL);
+ if (!tgt)
+ return NULL;
+ tgt->qio_pool = mempool_create_kmalloc_pool(MIN_QIOS,
+ sizeof(struct qio));
+ if (!tgt->qio_pool) {
+ ti->error = "Can't create mempool";
+ goto out_target;
+ }
+
+ flags = WQ_MEM_RECLAIM|WQ_HIGHPRI|WQ_UNBOUND;
+ tgt->wq = alloc_workqueue("dm-" DM_MSG_PREFIX, flags, 0);
+ if (!tgt->wq) {
+ ti->error = "Can't create workqueue";
+ goto out_pool;
+ }
+
+ for (i = 0; i < 2; i++) {
+ release = i ? inflight_ref_exit1 : inflight_ref_exit0;
+ if (percpu_ref_init(&tgt->inflight_ref[i], release,
+ PERCPU_REF_ALLOW_REINIT, GFP_KERNEL)) {
+ if (i)
+ percpu_ref_exit(&tgt->inflight_ref[0]);
+ ti->error = "could not alloc percpu_ref";
+ goto out_wq;
+ }
+ }
+
+ init_completion(&tgt->inflight_ref_comp);
+ spin_lock_init(&tgt->err_status_lock);
+ mutex_init(&tgt->ctl_mutex);
+ init_waitqueue_head(&tgt->service_wq);
+ ti->private = tgt;
+ tgt->ti = ti;
+ qcow2_set_service_operations(ti, false);
+
+ return tgt;
+out_wq:
+ destroy_workqueue(tgt->wq);
+out_pool:
+ mempool_destroy(tgt->qio_pool);
+out_target:
+ kfree(tgt);
+ return NULL;
+}
+
+static int qcow2_check_convert_hdr(struct QCowHeader *raw_hdr,
+ struct QCowHeader *hdr,
+ u64 min_len, u64 max_len)
+{
+ u32 clu_size;
+ bool ext_l2;
+
+ hdr->magic = cpu_to_be32(raw_hdr->magic);
+ hdr->version = be32_to_cpu(raw_hdr->version);
+ hdr->cluster_bits = be32_to_cpu(raw_hdr->cluster_bits);
+ hdr->size = be64_to_cpu(raw_hdr->size);
+ /*
+ * In this driver we never check userspace passed correct backing
+ * file fd, since it's impossible: here can be name of a symlink.
+ */
+ hdr->backing_file_offset = be64_to_cpu(raw_hdr->backing_file_offset);
+ hdr->backing_file_size = be32_to_cpu(raw_hdr->backing_file_size);
+ hdr->crypt_method = be32_to_cpu(raw_hdr->crypt_method);
+ hdr->l1_size = be32_to_cpu(raw_hdr->l1_size);
+ hdr->l1_table_offset = be64_to_cpu(raw_hdr->l1_table_offset);
+ hdr->refcount_table_offset = be64_to_cpu(raw_hdr->refcount_table_offset);
+ hdr->refcount_table_clusters = be32_to_cpu(raw_hdr->refcount_table_clusters);
+ hdr->nb_snapshots = be32_to_cpu(raw_hdr->nb_snapshots);
+ hdr->snapshots_offset = be64_to_cpu(raw_hdr->snapshots_offset);
+
+ clu_size = 1 << hdr->cluster_bits;
+ if (hdr->size < min_len || hdr->size > max_len ||
+ /* Note, we do not extend L1 table: */
+ (u64)hdr->l1_size * clu_size / sizeof(u64) * clu_size < min_len)
+ return -EBADSLT;
+
+ if (hdr->magic != QCOW_MAGIC || hdr->version < 2 || hdr->version > 3 ||
+ (hdr->l1_table_offset & (clu_size - 1)) ||
+ hdr->cluster_bits < 9 || hdr->cluster_bits > 21 ||
+ (hdr->refcount_table_offset & (clu_size - 1)))
+ return -EINVAL;
+
+ if (hdr->crypt_method != 0)
+ return -EOPNOTSUPP;
+
+ hdr->refcount_order = 4;
+
+ if (hdr->version == 2)
+ return 0;
+
+ hdr->incompatible_features = be64_to_cpu(raw_hdr->incompatible_features);
+ hdr->autoclear_features = be64_to_cpu(raw_hdr->autoclear_features);
+ hdr->refcount_order = be32_to_cpu(raw_hdr->refcount_order);
+ hdr->header_length = be32_to_cpu(raw_hdr->header_length);
+
+ if (kernel_sets_dirty_bit !=
+ !(hdr->incompatible_features & INCOMPATIBLE_FEATURES_DIRTY_BIT))
+ return kernel_sets_dirty_bit ? -EUCLEAN : -ENOLCK;
+ if (hdr->incompatible_features & ~INCOMPATIBLE_FEATURES_EXTL2_BIT)
+ return -EOPNOTSUPP;
+ ext_l2 = hdr->incompatible_features & INCOMPATIBLE_FEATURES_EXTL2_BIT;
+
+ if (hdr->refcount_order > 6 || (ext_l2 && hdr->cluster_bits < 14))
+ return -EINVAL;
+
+ if (hdr->header_length < offsetof(struct QCowHeader, compression_type))
+ return -EINVAL;
+
+ if (hdr->header_length < offsetof(struct QCowHeader, padding))
+ return 0;
+
+ hdr->compression_type = (u8)raw_hdr->compression_type;
+ if (hdr->compression_type != (u8)0)
+ return -EOPNOTSUPP;
+
+ return 0;
+}
+
+void calc_cached_parameters(struct qcow2 *qcow2, struct QCowHeader *hdr)
+{
+ s64 clu_size, reftable_clus = hdr->refcount_table_clusters;
+ loff_t pos, tmp, max;
+
+ qcow2->clu_size = clu_size = 1 << hdr->cluster_bits;
+ qcow2->ext_l2 = hdr->incompatible_features & INCOMPATIBLE_FEATURES_EXTL2_BIT;
+ if (qcow2->ext_l2)
+ qcow2->subclu_size = clu_size / 32;
+ qcow2->l2_entries = clu_size / (sizeof(u64) * (1 + qcow2->ext_l2));
+ qcow2->refblock_bits = 1 << hdr->refcount_order;
+ qcow2->refblock_entries = clu_size * 8 / qcow2->refblock_bits;
+ pos = div64_s64(PAGE_SIZE * 8ULL, qcow2->refblock_bits) * clu_size;
+ qcow2->r2_page_covered_file_size = pos;
+ max = round_down(LLONG_MAX, clu_size);
+ tmp = div64_s64(reftable_clus * qcow2->refblock_entries, sizeof(u64));
+ if (div64_s64(max, (u64)clu_size * clu_size) >= tmp) {
+ tmp = div64_s64(reftable_clus * clu_size, sizeof(u64));
+ pos = tmp * qcow2->refblock_entries * clu_size;
+ } else {
+ pos = max;
+ }
+ qcow2->reftable_max_file_size = pos;
+}
+
+int qcow2_set_image_file_features(struct qcow2 *qcow2, bool dirty)
+{
+ u64 dirty_mask = cpu_to_be64(INCOMPATIBLE_FEATURES_DIRTY_BIT);
+ struct QCowHeader *raw_hdr;
+ struct md_page *md;
+
+ if (qcow2->hdr.version == 2)
+ return 0;
+
+ md = md_page_find(qcow2, 0);
+ if (WARN_ON_ONCE(!md || !(md->status & MD_UPTODATE)))
+ return -EIO;
+
+ raw_hdr = kmap(md->page);
+ qcow2->hdr.autoclear_features = raw_hdr->autoclear_features = 0;
+ if (kernel_sets_dirty_bit) {
+ if (dirty)
+ raw_hdr->incompatible_features |= dirty_mask;
+ else
+ raw_hdr->incompatible_features &= ~dirty_mask;
+ }
+ kunmap(md->page);
+
+ return rw_page_sync(WRITE, qcow2, md->id, md->page);
+}
+
+static struct qcow2 *qcow2_alloc_delta(struct qcow2_target *tgt, struct qcow2 *upper)
+{
+ struct qcow2 *qcow2;
+ int i;
+
+ qcow2 = kzalloc(sizeof(*qcow2), GFP_KERNEL);
+ if (!qcow2)
+ return ERR_PTR(-ENOMEM);
+ qcow2->tgt = tgt;
+
+ for (i = 0; i < QLIST_COUNT; i++)
+ INIT_LIST_HEAD(&qcow2->qios[i]);
+ INIT_LIST_HEAD(&qcow2->paused_qios);
+ INIT_LIST_HEAD(&qcow2->wb_batch_list);
+ INIT_LIST_HEAD(&qcow2->slow_wb_batch_list);
+ spin_lock_init(&qcow2->deferred_lock);
+ spin_lock_init(&qcow2->md_pages_lock);
+ timer_setup(&qcow2->slow_wb_timer, slow_wb_timer_fn, 0);
+ INIT_WORK(&qcow2->worker, do_qcow2_work);
+ INIT_WORK(&qcow2->fsync_worker, do_qcow2_fsync_work);
+
+ if (upper)
+ upper->lower = qcow2;
+ else /* Top delta */
+ tgt->top = qcow2;
+
+ return qcow2;
+}
+
+static int qcow2_attach_file(struct dm_target *ti, struct qcow2_target *tgt,
+ struct qcow2 *qcow2, int fd)
+{
+ struct file *file;
+ fmode_t mode;
+
+ file = qcow2->file = fget(fd);
+ if (!file) /* In case of further errors, cleanup is made by caller */
+ return -ENOENT;
+
+ if (!S_ISREG(file_inode(file)->i_mode))
+ return -EINVAL;
+
+ mode = tgt->top != qcow2 ? FMODE_READ : dm_table_get_mode(ti->table);
+ mode &= (FMODE_READ|FMODE_WRITE);
+ if (mode & ~(file->f_mode & (FMODE_READ|FMODE_WRITE)))
+ return -EACCES;
+
+ return 0;
+}
+
+static int qcow2_parse_header(struct dm_target *ti, struct qcow2 *qcow2,
+ struct qcow2 *upper, bool is_bottom)
+{
+ struct QCowHeader *raw_hdr, *hdr = &qcow2->hdr;
+ loff_t min_len, max_len, new_size;
+ struct file *file = qcow2->file;
+ struct md_page *md;
+ int ret;
+
+ qcow2->file_size = i_size_read(file_inode(file));
+ if ((file->f_mode & FMODE_WRITE) && (qcow2->file_size & ~PAGE_MASK)) {
+ new_size = PAGE_ALIGN(qcow2->file_size);
+ ret = qcow2_truncate_safe(file, new_size);
+ if (ret) {
+ pr_err("qcow2: Can't truncate file\n");
+ return ret;
+ } /* See md_page_read_complete() */
+ qcow2->file_size = new_size;
+ }
+ qcow2->file_preallocated_area_start = qcow2->file_size;
+
+ ret = alloc_and_insert_md_page(qcow2, 0, &md);
+ if (ret)
+ return ret;
+ ret = rw_page_sync(READ, qcow2, md->id, md->page);
+ if (ret)
+ return ret;
+ md->status |= MD_UPTODATE;
+
+ raw_hdr = kmap(md->page);
+ min_len = to_bytes(ti->len);
+ max_len = LLONG_MAX;
+ if (upper) {
+ min_len = PAGE_SIZE;
+ max_len = upper->hdr.size;
+ }
+ ret = qcow2_check_convert_hdr(raw_hdr, hdr, min_len, max_len);
+ kunmap(md->page);
+ if (ret < 0)
+ goto out;
+
+ calc_cached_parameters(qcow2, hdr);
+ ret = -EOPNOTSUPP;
+ if (qcow2->clu_size < PAGE_SIZE ||
+ (qcow2->ext_l2 && qcow2->clu_size < PAGE_SIZE * 32))
+ goto out;
+ ret = -EXDEV;
+ if (upper && (upper->clu_size != qcow2->clu_size ||
+ upper->ext_l2 != qcow2->ext_l2))
+ goto out; /* This is not supported yet */
+ ret = -ENOENT;
+ if (is_bottom && qcow2->hdr.backing_file_offset)
+ goto out;
+ qcow2->free_cluster_search_pos = qcow2->clu_size * 1;
+
+ ret = -EFBIG;
+ if (qcow2->reftable_max_file_size < qcow2->file_size)
+ goto out;
+ ret = 0;
+out:
+ return ret;
+}
+
+static int qcow2_parse_metadata(struct dm_target *ti, struct qcow2_target *tgt)
+{
+ unsigned int i, nr_images = tgt->nr_images;
+ struct qcow2 *qcow2, *upper = NULL;
+ int ret;
+
+ qcow2 = top_qcow2_protected(ti);
+ for (i = 0; i < nr_images; i++) {
+ ret = -ENOENT;
+ if (!qcow2)
+ goto out;
+
+ ret = qcow2_parse_header(ti, qcow2, upper, i == nr_images - 1);
+ if (ret)
+ goto out;
+
+ upper = qcow2;
+ qcow2 = qcow2->lower;
+ }
+
+ ret = 0;
+out:
+ if (ret)
+ pr_err("dm-qcow2: Can't parse metadata\n");
+ return ret;
+}
+
+static int qcow2_ctr(struct dm_target *ti, unsigned int argc, char **argv)
+{
+ struct qcow2 *qcow2, *upper = NULL;
+ struct qcow2_target *tgt;
+ int i, fd, ret;
+
+ if (argc < 1 || ti->begin != 0)
+ return -EINVAL;
+
+ tgt = alloc_qcow2_target(ti);
+ if (!tgt)
+ return -ENOMEM;
+
+ /*
+ * Userspace passes deltas in bottom, ..., top order,
+ * but we attach it vise versa: from top to bottom.
+ */
+ for (i = argc - 1; i >= 0; i--) {
+ ret = -EINVAL;
+ if (kstrtos32(argv[i], 10, &fd) < 0) {
+ ti->error = "Wrong fd";
+ goto err;
+ }
+
+ qcow2 = qcow2_alloc_delta(tgt, upper);
+ if (IS_ERR(qcow2)) {
+ ret = PTR_ERR(qcow2);
+ goto err;
+ }
+
+ ret = qcow2_attach_file(ti, tgt, qcow2, fd);
+ if (ret) {
+ ti->error = "Error attaching file";
+ goto err;
+ }
+
+ upper = qcow2;
+ }
+
+ tgt->nr_images = argc;
+
+ ret = qcow2_parse_metadata(ti, tgt);
+ if (ret)
+ goto err;
+
+ ti->flush_supported = true;
+ ti->num_flush_bios = 1;
+ ti->discards_supported = true;
+ ti->num_discard_bios = 1;
+ ti->per_io_data_size = qcow2_per_io_data_size();
+ return 0;
+err:
+ qcow2_tgt_destroy(tgt);
+ return ret;
+}
+
+static void qcow2_dtr(struct dm_target *ti)
+{
+ struct qcow2_target *tgt = to_qcow2_target(ti);
+
+ qcow2_tgt_destroy(tgt);
+}
+
+static void qcow2_truncate_preallocations(struct dm_target *ti)
+{
+ struct qcow2_target *tgt = to_qcow2_target(ti);
+ struct qcow2 *qcow2 = top_qcow2_protected(ti);
+ loff_t end = qcow2->file_preallocated_area_start;
+ int ret;
+
+ if (!(dm_table_get_mode(ti->table) & FMODE_WRITE))
+ return;
+ if (end == qcow2->file_size)
+ return;
+
+ ret = qcow2_truncate_safe(qcow2->file, end);
+ if (ret) {
+ pr_err("dm-qcow2: Can't truncate preallocations\n");
+ tgt->truncate_error = true;
+ return;
+ }
+
+ qcow2->file_preallocated_area_start = end;
+ qcow2->file_size = end;
+}
+
+static void qcow2_io_hints(struct dm_target *ti, struct queue_limits *limits)
+{
+ struct qcow2 *qcow2 = top_qcow2_protected(ti);
+ unsigned int block_size = 512;
+ struct super_block *sb;
+
+ sb = file_inode(qcow2->file)->i_sb;
+ if (sb->s_bdev)
+ block_size = bdev_logical_block_size(sb->s_bdev);
+ /*
+ * Even if this is less than discard_granularity of bdev,
+ * we can free a block on filesystem.
+ */
+ limits->discard_granularity = sb->s_blocksize;
+ limits->max_discard_sectors = to_sector(qcow2->clu_size);
+
+ limits->logical_block_size = block_size;
+ limits->physical_block_size = block_size;
+
+ blk_limits_io_min(limits, block_size);
+ blk_limits_io_opt(limits, qcow2->clu_size);
+}
+
+static void qcow2_status(struct dm_target *ti, status_type_t type,
+ unsigned int status_flags, char *result,
+ unsigned int maxlen)
+{
+ struct qcow2_target *tgt = to_qcow2_target(ti);
+ unsigned int sz = 0;
+
+ switch (type) {
+ case STATUSTYPE_INFO:
+ result[0] = '\0';
+ break;
+ case STATUSTYPE_TABLE:
+ DMEMIT("%u", tgt->nr_images);
+ break;
+ }
+}
+
+static void qcow2_presuspend(struct dm_target *ti)
+{
+ qcow2_set_service_operations(ti, false);
+}
+static void qcow2_presuspend_undo(struct dm_target *ti)
+{
+ qcow2_set_service_operations(ti, true);
+}
+static void qcow2_postsuspend(struct dm_target *ti)
+{
+ struct qcow2 *qcow2 = top_qcow2_protected(ti);
+ int ret;
+
+ flush_deferred_activity_all(to_qcow2_target(ti));
+ qcow2_truncate_preallocations(ti);
+
+ if (dm_table_get_mode(ti->table) & FMODE_WRITE) {
+ ret = qcow2_set_image_file_features(qcow2, false);
+ if (ret)
+ pr_err("qcow2: Can't set features\n");
+ }
+}
+static int qcow2_preresume(struct dm_target *ti)
+{
+ struct qcow2_target *tgt = to_qcow2_target(ti);
+ int ret = 0;
+
+ if (qcow2_wants_check(tgt)) {
+ pr_err("qcow2: image check and target reload are required\n");
+ return -EIO;
+ }
+
+ free_md_pages_all(tgt);
+ /*
+ * Reading metadata here allows userspace to modify images
+ * of suspended device without reloading target. We also
+ * want to do this in .ctr to break device creation early
+ * if images are not valid.
+ */
+ ret = qcow2_parse_metadata(ti, tgt);
+ if (ret)
+ return ret;
+ /*
+ * Despite .preresume has no undo, our target is singleton,
+ * so we can set features uncoditionally here.
+ */
+ if (dm_table_get_mode(ti->table) & FMODE_WRITE) {
+ ret = qcow2_set_image_file_features(tgt->top, true);
+ if (ret)
+ pr_err("qcow2: Can't set features\n");
+ }
+
+ return ret;
+}
+static void qcow2_resume(struct dm_target *ti)
+{
+ qcow2_set_service_operations(ti, true);
+}
+
+static struct target_type qcow2_target = {
+ .name = "qcow2",
+ .version = {1, 0, 0},
+ .features = DM_TARGET_SINGLETON|DM_TARGET_IMMUTABLE,
+ .module = THIS_MODULE,
+ .ctr = qcow2_ctr,
+ .dtr = qcow2_dtr,
+ .io_hints = qcow2_io_hints,
+ .status = qcow2_status,
+ .presuspend = qcow2_presuspend,
+ .presuspend_undo = qcow2_presuspend_undo,
+ .postsuspend = qcow2_postsuspend,
+ .preresume = qcow2_preresume,
+ .resume = qcow2_resume,
+ .clone_and_map_rq = qcow2_clone_and_map,
+ .message = qcow2_message,
+};
+
+static int __init dm_qcow2_init(void)
+{
+ int ret;
+
+ ret = dm_register_target(&qcow2_target);
+ if (ret)
+ DMERR("qcow2 target registration failed: %d", ret);
+
+ return ret;
+}
+
+static void __exit dm_qcow2_exit(void)
+{
+ dm_unregister_target(&qcow2_target);
+}
+
+module_init(dm_qcow2_init);
+module_exit(dm_qcow2_exit);
+
+MODULE_DESCRIPTION("QCOW2 block device driver");
+MODULE_AUTHOR("Kirill Tkhai <ktkhai at virtuozzo.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/md/dm-qcow2.h b/drivers/md/dm-qcow2.h
new file mode 100644
index 000000000000..9d4a9f8a1453
--- /dev/null
+++ b/drivers/md/dm-qcow2.h
@@ -0,0 +1,360 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __DM_QCOW2_H
+#define __DM_QCOW2_H
+
+#include <linux/percpu-refcount.h>
+#include <linux/device-mapper.h>
+#include <linux/fs.h>
+
+#define DM_MSG_PREFIX "qcow2"
+
+#define QCOW_MAGIC (('Q' << 24) | ('F' << 16) | ('I' << 8) | 0xfb)
+/*
+ * QEMU has this limit, so we should follow it to keep our images
+ * mountable in VMs... Note, that it's possible to create a disk
+ * with parameters in QEMU, whose size can't be covered by refcount table.
+ */
+#define REFCOUNT_TABLE_MAX_SIZE (8 * 1024 * 1024)
+
+#define MIN_QIOS 512
+#define WB_TIMEOUT_JI (60 * HZ)
+#define PREALLOC_SIZE (128ULL * 1024 * 1024)
+
+struct QCowHeader {
+ uint32_t magic;
+ uint32_t version;
+ uint64_t backing_file_offset;
+ uint32_t backing_file_size;
+ uint32_t cluster_bits;
+ uint64_t size; /* in bytes */
+ uint32_t crypt_method;
+ uint32_t l1_size; /* number of entries in the active L1 table (not clusters) */
+ uint64_t l1_table_offset;
+ uint64_t refcount_table_offset;
+ uint32_t refcount_table_clusters;
+ uint32_t nb_snapshots;
+ uint64_t snapshots_offset;
+
+ /* The following fields are only valid for version >= 3 */
+#define INCOMPATIBLE_FEATURES_DIRTY_BIT (1 << 0)
+#define INCOMPATIBLE_FEATURES_EXTL2_BIT (1 << 4)
+ uint64_t incompatible_features;
+ uint64_t compatible_features;
+ uint64_t autoclear_features;
+
+ uint32_t refcount_order;
+ uint32_t header_length;
+
+ /* Additional fields */
+ uint8_t compression_type;
+
+ /* header must be a multiple of 8 */
+ uint8_t padding[7];
+} __packed;
+
+struct wb_desc {
+ struct md_page *md;
+#define LX_INDEXES_PER_PAGE (PAGE_SIZE / sizeof(u64))
+#define LX_INDEXES_BYTES (BITS_TO_LONGS(LX_INDEXES_PER_PAGE) * sizeof(unsigned long))
+ unsigned long *changed_indexes;
+ /*
+ * Contains old stable values of preallocated/cow entries
+ * to restore them in case of md writeback fails.
+ */
+ struct page *pe_page;
+ struct list_head submitted_list;
+ struct list_head completed_list;
+ /*
+ * These bios want to be dispatched in case of writeback
+ * success, or bio_endio() in case of error.
+ * XXX: Possible we need the same for plain struct md_page.
+ */
+ struct list_head dependent_list;
+ bool completed;
+ int ret;
+};
+
+struct lock_desc {
+ int nr; /* Number of set bits */
+ unsigned long indexes[LX_INDEXES_BYTES/sizeof(unsigned long)];
+};
+
+struct md_page {
+ struct rb_node node;
+ u64 id; /* Number of this page starting from hdr */
+#define MD_UPTODATE (1U << 0) /* Page was read from disk */
+#define MD_DIRTY (1U << 1) /* Page contains changes and wants writeback */
+#define MD_WRITEBACK (1U << 2) /* Writeback was submitted */
+#define MD_WRITEBACK_ERROR (1U << 3) /* Last writeback failed with error */
+ unsigned int status;
+ struct page *page;
+ struct list_head wait_list;
+ /* To link in qcow2::{,slow}wb_batch_list and qcow2::QLIST_COMPLETED_WB */
+ struct list_head wb_link;
+ struct wb_desc *wbd; /* For L1 and L2 update */
+ struct lock_desc *lockd; /* Locked clus map */
+ /*
+ * Readers of clusters, WRITE to which results in COW.
+ * These are compressed clusters, snapshot clusters, etc.
+ */
+ atomic_t wpc_readers;
+ int wpc_noread_count; /* Read is prohibited, if positive */
+ struct list_head wpc_readers_wait_list;
+};
+
+struct qcow2_target {
+ struct dm_target *ti;
+ mempool_t *qio_pool;
+ /*
+ * start_processing_qrq() is the only place during IO handling,
+ * where it's allowed to dereference @top. See backward merge.
+ */
+ struct qcow2 *top;
+ struct workqueue_struct *wq;
+
+ struct completion inflight_ref_comp;
+ struct percpu_ref inflight_ref[2];
+ unsigned int inflight_ref_index:1;
+
+ bool service_operations_allowed;
+ bool md_writeback_error;
+ bool truncate_error;
+
+ unsigned int nr_images;
+
+ atomic_t service_qios;
+ struct wait_queue_head service_wq;
+
+ spinlock_t err_status_lock;
+ struct mutex ctl_mutex;
+};
+
+enum {
+ QLIST_EMBEDDED = 0, /*
+ * List for initial setup embedded qios
+ * related to prq (in process context).
+ * This is used only for top qcow2 image.
+ */
+ QLIST_DEFERRED,
+ QLIST_FLUSH,
+ QLIST_COMPLETED_WB,
+ QLIST_ZREAD,
+ QLIST_BMERGE_WRITE,
+ QLIST_COW_DATA,
+ QLIST_COW_INDEXES,
+ QLIST_COW_END,
+
+ QLIST_COUNT,
+ QLIST_INVALID = QLIST_COUNT,
+};
+
+struct qcow2 {
+ struct qcow2_target *tgt;
+ struct file *file;
+ loff_t file_size;
+ loff_t file_preallocated_area_start;
+ /* Maximum file size covered by refcount table */
+ loff_t reftable_max_file_size;
+ /* Position to search next unused cluster */
+ loff_t free_cluster_search_pos;
+
+ struct qcow2 *lower; /* Lower delta (backing file) */
+
+ struct rb_root md_pages; /* Metadata pages */
+ struct QCowHeader hdr;
+ u32 clu_size;
+ u32 subclu_size;
+ u32 l2_entries;
+ u32 refblock_bits;
+ u32 refblock_entries;
+ bool ext_l2;
+
+ bool pause_submitting_qios; /* This is used only on top qcow2 image */
+ bool backward_merge_in_process;
+ /* File size covered by single page of block entries */
+ loff_t r2_page_covered_file_size;
+
+ spinlock_t deferred_lock ____cacheline_aligned;
+ spinlock_t md_pages_lock;
+
+ struct list_head qios[QLIST_COUNT];
+ struct list_head paused_qios; /* For pause_submitting_qios */
+
+ /* For batching md update: */
+ struct list_head wb_batch_list;
+ struct list_head slow_wb_batch_list;
+ struct timer_list slow_wb_timer;
+
+ struct work_struct worker;
+ struct work_struct fsync_worker;
+};
+
+/*
+ * struct qio is embedded in every incoming bio, so we keep it
+ * as small as possible. It is aimed to fit enough bytes only
+ * for the most likely actions. To process COW, compressed
+ * clusters and other rare actions we need more auxiliary bytes,
+ * so we introduce this struct qio_ext in addition to struct qio.
+ */
+struct qio_ext {
+ struct md_page *lx_md, *r2_md, *md;
+ u32 lx_index_in_page, r2_index_in_page;
+ u64 allocated_clu_pos;
+
+ loff_t cow_clu_pos;
+ loff_t cow_clu_end;
+ u64 new_ext_l2;
+ u32 cow_mask;
+ bool only_set_ext_l2:1;
+
+ u8 cow_level;
+
+#define MD_INDEX_SET_UNLOCKED (1ULL << 0)
+#define DEC_WPC_NOREAD_COUNT (1ULL << 1)
+#define FREE_QIO_DATA_QVEC (1ULL << 2)
+#define FREE_ALLOCATED_CLU (1ULL << 3)
+ u8 cleanup_mask;
+ u16 zdata_off; /* Offset in first page: */
+ u16 cow_segs;
+};
+
+struct qcow2_rq {
+ struct request *rq;
+ struct bio_vec *bvec;
+};
+
+struct qio;
+typedef void (*qcow2_endio_t)(struct qcow2_target *, struct qio *,
+ void *, blk_status_t);
+
+struct qio {
+ struct bvec_iter bi_iter;
+ struct bio_vec *bi_io_vec;
+ unsigned int bi_op;
+ blk_status_t bi_status;
+#define QIO_FREE_ON_ENDIO_FL (1 << 0) /* Free this qio memory from qio_endio() */
+#define QIO_IS_MERGE_FL (1 << 3) /* This is service merge qio */
+#define QIO_IS_DISCARD_FL (1 << 4) /* This zeroes index on backward merge */
+#define QIO_IS_L1COW_FL (1 << 5) /* This qio only wants COW at L1 */
+#define QIO_SPLIT_INHERITED_FLAGS (QIO_IS_DISCARD_FL)
+ u8 flags;
+#define REF_INDEX_INVALID 2
+ u8 ref_index:2;
+ /*
+ * Some operations (say, COW) have more than one stage.
+ * In case of a stage may delay bio (say, it may want
+ * to wait reading md page from disk, or when some counter
+ * becomes zero), this queue_list_id shows the place, where
+ * bio processing should resume.
+ */
+ u8 queue_list_id:4;
+
+ atomic_t remaining;
+
+ struct kiocb iocb;
+ atomic_t aio_ref;
+ int ret; /* iocb result */
+ void (*complete)(struct qio *me);
+ void *data;
+ /* Some operations (COW) require special destruction or requeue */
+ struct qio_ext *ext;
+ struct list_head link;
+ struct qcow2 *qcow2;
+ qcow2_endio_t endio_cb;
+ void *endio_cb_data;
+};
+
+#define CLU_OFF(qcow2, pos) (pos & (qcow2->clu_size - 1))
+#define SUBCLU_OFF(qcow2, pos) (pos & (qcow2->subclu_size - 1))
+
+void qcow2_destroy(struct qcow2 *qcow2);
+int qcow2_set_image_file_features(struct qcow2 *qcow2, bool dirty);
+int qcow2_message(struct dm_target *ti, unsigned int argc, char **argv,
+ char *result, unsigned int maxlen);
+int qcow2_clone_and_map(struct dm_target *ti, struct request *rq,
+ union map_info *info, struct request **clone);
+
+void do_qcow2_work(struct work_struct *ws);
+void do_qcow2_fsync_work(struct work_struct *ws);
+int alloc_and_insert_md_page(struct qcow2 *qcow2, u64 index, struct md_page **md);
+struct md_page *md_page_find_or_postpone(struct qcow2 *qcow2, unsigned int id, struct qio **qio);
+struct md_page *md_page_renumber(struct qcow2 *qcow2, unsigned int id, unsigned int new_id);
+void md_page_erase(struct qcow2 *qcow2, struct md_page *md);
+void free_md_page(struct md_page *md);
+void zero_fill_page_from(struct page *page, unsigned int from);
+int rw_page_sync(unsigned int rw, struct qcow2 *qcow2, u64 index, struct page *page);
+void call_rw_iter(struct file *file, loff_t pos, unsigned int rw,
+ struct iov_iter *iter, struct qio *qio);
+void calc_cached_parameters(struct qcow2 *qcow2, struct QCowHeader *hdr);
+void slow_wb_timer_fn(struct timer_list *t);
+struct qio *alloc_qio(mempool_t *pool, bool zero);
+void init_qio(struct qio *qio, unsigned int bi_op, struct qcow2 *qcow2);
+void dispatch_qios(struct qcow2 *qcow2, struct qio *qio,
+ struct list_head *qio_list);
+void submit_embedded_qios(struct qcow2_target *tgt, struct list_head *list);
+struct qcow2 *qcow2_ref_inc(struct qcow2_target *tgt, u8 *ref_index);
+void qcow2_ref_dec(struct qcow2_target *tgt, u8 ref_index);
+int qcow2_inflight_ref_switch(struct qcow2_target *tgt);
+void flush_deferred_activity(struct qcow2_target *tgt, struct qcow2 *qcow2);
+int qcow2_truncate_safe(struct file *file, loff_t new_len);
+
+static inline ssize_t qcow2_per_io_data_size(void)
+{
+ return sizeof(struct qcow2_rq) + sizeof(struct qio);
+}
+static inline struct qcow2_rq *map_info_to_embedded_qrq(union map_info *info)
+{
+ return (void *)info->ptr;
+}
+static inline struct qio *map_info_to_embedded_qio(union map_info *info)
+{
+ return (void *)info->ptr + sizeof(struct qcow2_rq);
+}
+static inline struct qcow2_rq *embedded_qio_to_qrq(struct qio *qio)
+{
+ return (void *)qio - sizeof(struct qcow2_rq);
+}
+
+static inline struct qcow2_target *to_qcow2_target(struct dm_target *ti)
+{
+ return ti->private;
+}
+
+static inline struct qcow2 *top_qcow2_protected(struct dm_target *ti)
+{
+ struct qcow2_target *tgt = to_qcow2_target(ti);
+
+ return tgt->top;
+}
+
+static inline struct qio *qio_list_pop(struct list_head *qio_list)
+{
+ struct qio *qio;
+
+ qio = list_first_entry_or_null(qio_list, struct qio, link);
+ if (qio)
+ list_del_init(&qio->link);
+ return qio;
+}
+
+static inline bool fake_merge_qio(struct qio *qio)
+{
+ return (qio->bi_op == REQ_OP_WRITE &&
+ qio->bi_iter.bi_size == 0 &&
+ (qio->flags & QIO_IS_MERGE_FL));
+}
+
+static inline bool fake_l1cow_qio(struct qio *qio)
+{
+ return (qio->bi_op == REQ_OP_WRITE &&
+ qio->bi_iter.bi_size == 0 &&
+ (qio->flags & QIO_IS_L1COW_FL));
+}
+
+static inline bool qcow2_wants_check(struct qcow2_target *tgt)
+{
+
+ return !!(tgt->md_writeback_error|tgt->truncate_error);
+}
+
+#endif
diff --git a/scripts/qcow2-dm.sh b/scripts/qcow2-dm.sh
new file mode 100755
index 000000000000..e29205e3f973
--- /dev/null
+++ b/scripts/qcow2-dm.sh
@@ -0,0 +1,103 @@
+#!/bin/bash
+#
+# This requires parameter dm_qcow2.kernel_sets_dirty_bit=y
+
+usage () {
+ cat <<EOF
+Usage:
+ $prog_name create <file.qcow2> <dev_name>
+ $prog_name remove <file.qcow2>
+EOF
+}
+
+create () {
+ if [ "$#" -ne 2 ]; then
+ echo >&2 "Wrong number of arguments."; usage; exit 1;
+ fi
+
+ file=$1
+ dev=$2
+ files=()
+ fds=""
+
+ disk_sz=`qemu-img info -f qcow2 $file | grep "virtual size" | sed 's/.*(\(.*\) bytes)/\1/'`
+ if [ -z "$disk_sz" ]; then
+ echo "Can't get disk size."; exit 1;
+ fi
+
+ while :; do
+ if [ ! -f "$file" ]; then
+ echo "$file does not exist."; exit 1;
+ fi
+
+ files+=("$file")
+
+ exec {fd}<>$file || exit 1
+ flock -x $fd || exit 1
+ fds="$fd $fds"
+
+ file=`qemu-img info $file | grep "backing file:" | sed "s/backing file: //"`
+ if [ -z "$file" ]; then
+ break
+ fi
+ done
+
+ echo "Create device [$dev] of size $disk_sz from [${files[*]}]."
+ dmsetup create $dev --table "0 $((disk_sz / 512)) qcow2 ${fds}"
+}
+
+remove () {
+ if [ "$#" -ne 1 ]; then
+ echo >&2 "Wrong number of arguments."; usage; exit 1;
+ fi
+ user_path=$1
+ path=`realpath $user_path`
+
+ while read line; do
+ dev=`echo $line | sed "s/:.*//"`
+ nr_imgs=`echo $line | sed "s/.*\(\w\)$/\1/"`
+ top_img_id=$((nr_imgs - 1))
+
+ top_img_path=`dmsetup message $dev 0 get_img_name $top_img_id`
+ if [ -z "$top_img_path" ]; then
+ echo "Can't get image path."; exit 1;
+ fi
+
+ if [ "$path" != "$top_img_path" ]; then
+ continue
+ fi
+
+ echo "Removing device [$dev]."
+ dmsetup remove $dev
+ ret=$?
+
+ if [ $? -eq 0 ]; then
+ #Sanity check
+ echo "Checking [$top_img_path]."
+ qemu-img check $top_img_path
+ fi
+ exit $ret
+
+ done < <(LANG=C dmsetup table --target=qcow2 | grep -v "No devices found")
+
+ echo "Can't find device with [$user_path] top image."
+ exit 1
+}
+
+prog_name=$(basename $0)
+
+case $1 in
+ "create")
+ shift
+ create "$@"
+ exit 0
+ ;;
+ "remove")
+ shift
+ remove "$@"
+ ;;
+ *)
+ usage
+ exit 1
+ ;;
+esac
More information about the Devel
mailing list