From: jbeulich@suse.com
Subject: blkif: indirect request segment descriptors definitions
Patch-mainline: Never, SUSE-Xen specific
References: fate#316876

--- a/include/xen/blkif.h
+++ b/include/xen/blkif.h
@@ -25,6 +25,12 @@
 #include <xen/interface/io/blkif.h>
 #include <xen/interface/io/protocols.h>
 
+#define BLKIF_SEGS_PER_INDIRECT_FRAME \
+	(PAGE_SIZE / sizeof(struct blkif_request_segment))
+#define BLKIF_INDIRECT_PAGES(segs) \
+	(((segs) + BLKIF_SEGS_PER_INDIRECT_FRAME - 1) \
+	 / BLKIF_SEGS_PER_INDIRECT_FRAME)
+
 /* Not a real protocol.  Used to generate ring structs which contain
  * the elements common to all protocols only.  This way we get a
  * compiler-checkable way to use common struct elements, so we can
@@ -36,6 +42,7 @@ struct blkif_common_request {
 union __attribute__((transparent_union)) blkif_union {
 	struct blkif_request *generic;
 	struct blkif_request_discard *discard;
+	struct blkif_request_indirect *indirect;
 };
 
 /* i386 protocol version */
@@ -56,9 +63,20 @@ struct blkif_x86_32_discard {
 	blkif_sector_t sector_number;/* start sector idx on disk             */
 	uint64_t       nr_sectors;   /* number of contiguous sectors         */
 };
+struct blkif_x86_32_indirect {
+	uint8_t        operation;    /* BLKIF_OP_INDIRECT                    */
+	uint8_t        indirect_op;  /* BLKIF_OP_{READ/WRITE}                */
+	uint16_t       nr_segments;  /* number of segments                   */
+	uint64_t       id;           /* private guest value, echoed in resp  */
+	blkif_sector_t sector_number;/* start sector idx on disk (r/w only)  */
+	blkif_vdev_t   handle;       /* same as for read/write requests      */
+	grant_ref_t    indirect_grefs[BLKIF_MAX_INDIRECT_PAGES_PER_REQUEST];
+	uint64_t       pad;          /* make it 64 byte aligned */
+};
 union blkif_x86_32_union {
 	struct blkif_x86_32_request generic;
 	struct blkif_x86_32_discard discard;
+	struct blkif_x86_32_indirect indirect;
 };
 #pragma pack(pop)
 
@@ -79,9 +97,19 @@ struct blkif_x86_64_discard {
 	blkif_sector_t sector_number;/* start sector idx on disk             */
 	uint64_t       nr_sectors;   /* number of contiguous sectors         */
 };
+struct blkif_x86_64_indirect {
+	uint8_t        operation;    /* BLKIF_OP_INDIRECT                    */
+	uint8_t        indirect_op;  /* BLKIF_OP_{READ/WRITE}                */
+	uint16_t       nr_segments;  /* number of segments                   */
+	uint64_t       __attribute__((__aligned__(8))) id;
+	blkif_sector_t sector_number;/* start sector idx on disk (r/w only)  */
+	blkif_vdev_t   handle;       /* same as for read/write requests      */
+	grant_ref_t    indirect_grefs[BLKIF_MAX_INDIRECT_PAGES_PER_REQUEST];
+};
 union blkif_x86_64_union {
 	struct blkif_x86_64_request generic;
 	struct blkif_x86_64_discard discard;
+	struct blkif_x86_64_indirect indirect;
 };
 
 #define blkif_native_sring blkif_sring
@@ -131,6 +159,14 @@ static void inline blkif_get_x86_32_req(
 		/* All fields up to sector_number got copied above already. */
 		dst.discard->nr_sectors = src->discard.nr_sectors;
 		break;
+	case BLKIF_OP_INDIRECT:
+		/* All fields up to sector_number got copied above already. */
+		dst.indirect->handle = src->indirect.handle;
+		n = min_t(unsigned int, BLKIF_INDIRECT_PAGES(dst.indirect->nr_segments),
+			  BLKIF_MAX_INDIRECT_PAGES_PER_REQUEST);
+		for (i = 0; i < n; ++i)
+			dst.indirect->indirect_grefs[i] = src->indirect.indirect_grefs[i];
+		break;
 	}
 #endif
 }
@@ -160,6 +196,14 @@ static void inline blkif_get_x86_64_req(
 		/* All fields up to sector_number got copied above already. */
 		dst.discard->nr_sectors = src->discard.nr_sectors;
 		break;
+	case BLKIF_OP_INDIRECT:
+		/* All fields up to sector_number got copied above already. */
+		dst.indirect->handle = src->indirect.handle;
+		n = min_t(unsigned int, BLKIF_INDIRECT_PAGES(dst.indirect->nr_segments),
+			  BLKIF_MAX_INDIRECT_PAGES_PER_REQUEST);
+		for (i = 0; i < n; ++i)
+			dst.indirect->indirect_grefs[i] = src->indirect.indirect_grefs[i];
+		break;
 	}
 #endif
 }
