[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