[Devel] [PATCH RH9 11/12] <empty message>
Kirill Tkhai
ktkhai at virtuozzo.com
Wed Jan 19 19:20:02 MSK 2022
---
drivers/md/dm-qcow2-cmd.c | 31 +++++++++++++++++++++++++++++++
drivers/md/dm-qcow2-map.c | 6 +++++-
drivers/md/dm-qcow2.h | 11 ++++++++++-
3 files changed, 46 insertions(+), 2 deletions(-)
diff --git a/drivers/md/dm-qcow2-cmd.c b/drivers/md/dm-qcow2-cmd.c
index 966e3287dcfd..e3c2de89d1bf 100644
--- a/drivers/md/dm-qcow2-cmd.c
+++ b/drivers/md/dm-qcow2-cmd.c
@@ -317,12 +317,36 @@ static int qcow2_set_fault_injection(struct qcow2_target *tgt,
return 0;
}
+static int qcow2_seek_hole(struct qcow2_target *tgt, u64 pos)
+{
+ struct qcow2 *qcow2, *img;
+ u8 ref_index;
+ u64 step;
+ int ret;
+
+ qcow2 = img = qcow2_ref_inc(tgt, &ref_index);
+ /* This expects lower deltas have the same clu_size and ext_l2 */
+ step = (u64)qcow2->l2_entries * qcow2->clu_size;
+
+ while (img) { /* Cache metadata of all images */
+ ret = qcow2_service_iter(tgt, img, img->hdr.size, step,
+ REQ_OP_READ, QIO_IS_FAKEREAD_FL);
+ if (ret)
+ goto out;
+ img = img->lower;
+ }
+out:
+ qcow2_ref_dec(tgt, ref_index);
+ return ret;
+}
+
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, val2;
+ u64 val64;
if (!capable(CAP_SYS_ADMIN))
goto out;
@@ -353,6 +377,13 @@ int qcow2_message(struct dm_target *ti, unsigned int argc, char **argv,
}
ret = qcow2_set_fault_injection(tgt, val, val2);
goto out;
+ } else if (!strcmp(argv[0], "seek_hole")) {
+ if (argc != 2 || kstrtou64(argv[1], 10, &val64)) {
+ ret = -EINVAL;
+ goto out;
+ }
+ ret = qcow2_seek_hole(tgt, val64);
+ goto out;
}
ret = mutex_lock_killable(&tgt->ctl_mutex);
diff --git a/drivers/md/dm-qcow2-map.c b/drivers/md/dm-qcow2-map.c
index 67a706a22e32..4531d680fa63 100644
--- a/drivers/md/dm-qcow2-map.c
+++ b/drivers/md/dm-qcow2-map.c
@@ -3268,7 +3268,11 @@ static int handle_metadata(struct qcow2 *qcow2, struct qio **qio,
goto check_err;
ret = 1;
- if (unlikely(qcow2->backward_merge_in_process)) {
+ if (unlikely(fake_read_qio(*qio))) {
+ /* Fake qio to cache md page, nothing to do */
+ qio_endio(*qio);
+ ret = 0;
+ } else 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)) &&
diff --git a/drivers/md/dm-qcow2.h b/drivers/md/dm-qcow2.h
index cff61eec4c93..5c59cc4a7c25 100644
--- a/drivers/md/dm-qcow2.h
+++ b/drivers/md/dm-qcow2.h
@@ -241,6 +241,8 @@ struct qio {
#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_IS_FAKEREAD_FL (1 << 6) /* This qio only wants to cache a single L2 md page
+ * (and L1 md page related to that L2) */
#define QIO_SPLIT_INHERITED_FLAGS (QIO_IS_DISCARD_FL)
u8 flags;
#define REF_INDEX_INVALID 2
@@ -339,9 +341,16 @@ static inline bool fake_l1cow_qio(struct qio *qio)
(qio->flags & QIO_IS_L1COW_FL));
}
+static inline bool fake_read_qio(struct qio *qio)
+{
+ return (qio->bi_op == REQ_OP_READ &&
+ qio->bi_iter.bi_size == 0 &&
+ (qio->flags & QIO_IS_FAKEREAD_FL));
+}
+
static inline bool fake_service_qio(struct qio *qio)
{
- return fake_merge_qio(qio) || fake_l1cow_qio(qio);
+ return fake_merge_qio(qio) || fake_l1cow_qio(qio) || fake_read_qio(qio);
}
static inline bool qcow2_wants_check(struct qcow2_target *tgt)
More information about the Devel
mailing list