From: Li Dongyang <lidongyang@novell.com>
Subject: blkif: support discard
References: fate#309305
Patch-mainline: n/a

Now we use BLKIF_OP_DISCARD and add blkif_request_discard to blkif_request union,
the patch is taken from Owen Smith and Konrad, Thanks

Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Signed-off-by: Owen Smith <owen.smith@citrix.com>
Signed-off-by: Li Dongyang <lidongyang@novell.com>

--- sle11sp3.orig/include/xen/blkif.h	2012-10-17 11:03:50.000000000 +0200
+++ sle11sp3/include/xen/blkif.h	2014-02-06 14:38:26.000000000 +0100
@@ -36,6 +36,11 @@ struct blkif_common_response {
 	char dummy;
 };
 
+union __attribute__((transparent_union)) blkif_union {
+	struct blkif_request *generic;
+	struct blkif_request_discard *discard;
+};
+
 /* i386 protocol version */
 #pragma pack(push, 4)
 struct blkif_x86_32_request {
@@ -46,13 +51,23 @@ struct blkif_x86_32_request {
 	blkif_sector_t sector_number;/* start sector idx on disk (r/w only)  */
 	struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
 };
+struct blkif_x86_32_discard {
+	uint8_t        operation;    /* BLKIF_OP_DISCARD                     */
+	uint8_t        reserved;     /*                                      */
+	blkif_vdev_t   handle;       /* same as for read/write requests      */
+	uint64_t       id;           /* private guest value, echoed in resp  */
+	blkif_sector_t sector_number;/* start sector idx on disk             */
+	uint64_t       nr_sectors;   /* number of contiguous sectors         */
+};
+union blkif_x86_32_union {
+	struct blkif_x86_32_request generic;
+	struct blkif_x86_32_discard discard;
+};
 struct blkif_x86_32_response {
 	uint64_t        id;              /* copied from request */
 	uint8_t         operation;       /* copied from request */
 	int16_t         status;          /* BLKIF_RSP_???       */
 };
-typedef struct blkif_x86_32_request blkif_x86_32_request_t;
-typedef struct blkif_x86_32_response blkif_x86_32_response_t;
 #pragma pack(pop)
 
 /* x86_64 protocol version */
@@ -64,18 +79,28 @@ struct blkif_x86_64_request {
 	blkif_sector_t sector_number;/* start sector idx on disk (r/w only)  */
 	struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
 };
+struct blkif_x86_64_discard {
+	uint8_t        operation;    /* BLKIF_OP_DISCARD                     */
+	uint8_t        reserved;     /*                                      */
+	blkif_vdev_t   handle;       /* sane as for read/write requests      */
+	uint64_t       __attribute__((__aligned__(8))) id;
+	blkif_sector_t sector_number;/* start sector idx on disk             */
+	uint64_t       nr_sectors;   /* number of contiguous sectors         */
+};
+union blkif_x86_64_union {
+	struct blkif_x86_64_request generic;
+	struct blkif_x86_64_discard discard;
+};
 struct blkif_x86_64_response {
 	uint64_t       __attribute__((__aligned__(8))) id;
 	uint8_t         operation;       /* copied from request */
 	int16_t         status;          /* BLKIF_RSP_???       */
 };
-typedef struct blkif_x86_64_request blkif_x86_64_request_t;
-typedef struct blkif_x86_64_response blkif_x86_64_response_t;
 
 #define blkif_native_sring blkif_sring
 DEFINE_RING_TYPES(blkif_common, struct blkif_common_request, struct blkif_common_response);
-DEFINE_RING_TYPES(blkif_x86_32, struct blkif_x86_32_request, struct blkif_x86_32_response);
-DEFINE_RING_TYPES(blkif_x86_64, struct blkif_x86_64_request, struct blkif_x86_64_response);
+DEFINE_RING_TYPES(blkif_x86_32, union blkif_x86_32_union, struct blkif_x86_32_response);
+DEFINE_RING_TYPES(blkif_x86_64, union blkif_x86_64_union, struct blkif_x86_64_response);
 
 union blkif_back_rings {
 	blkif_back_ring_t        native;
@@ -91,34 +116,62 @@ enum blkif_protocol {
 	BLKIF_PROTOCOL_X86_64 = 3,
 };
 
-static void inline blkif_get_x86_32_req(blkif_request_t *dst, blkif_x86_32_request_t *src)
+static void inline blkif_get_x86_32_req(union blkif_union dst,
+					const union blkif_x86_32_union *src)
 {
-	int i, n = BLKIF_MAX_SEGMENTS_PER_REQUEST;
-	dst->operation = src->operation;
-	dst->nr_segments = src->nr_segments;
-	dst->handle = src->handle;
-	dst->id = src->id;
-	dst->sector_number = src->sector_number;
+#ifdef __i386__
+	memcpy(dst.generic, src, sizeof(*dst.generic));
+#else
+	unsigned int i, n;
+
+	dst.generic->operation = src->generic.operation;
+	dst.generic->nr_segments = src->generic.nr_segments;
+	dst.generic->handle = src->generic.handle;
+	dst.generic->id = src->generic.id;
+	dst.generic->sector_number = src->generic.sector_number;
 	barrier();
-	if (n > dst->nr_segments)
-		n = dst->nr_segments;
-	for (i = 0; i < n; i++)
-		dst->seg[i] = src->seg[i];
+	switch (__builtin_expect(dst.generic->operation, BLKIF_OP_READ)) {
+	default:
+		n = min_t(unsigned int, dst.generic->nr_segments,
+			  BLKIF_MAX_SEGMENTS_PER_REQUEST);
+		for (i = 0; i < n; i++)
+			dst.generic->seg[i] = src->generic.seg[i];
+		break;
+	case BLKIF_OP_DISCARD:
+		/* All fields up to sector_number got copied above already. */
+		dst.discard->nr_sectors = src->discard.nr_sectors;
+		break;
+	}
+#endif
 }
 
-static void inline blkif_get_x86_64_req(blkif_request_t *dst, blkif_x86_64_request_t *src)
+static void inline blkif_get_x86_64_req(union blkif_union dst,
+					const union blkif_x86_64_union *src)
 {
-	int i, n = BLKIF_MAX_SEGMENTS_PER_REQUEST;
-	dst->operation = src->operation;
-	dst->nr_segments = src->nr_segments;
-	dst->handle = src->handle;
-	dst->id = src->id;
-	dst->sector_number = src->sector_number;
+#ifdef __x86_64__
+	memcpy(dst.generic, src, sizeof(*dst.generic));
+#else
+	unsigned int i, n;
+
+	dst.generic->operation = src->generic.operation;
+	dst.generic->nr_segments = src->generic.nr_segments;
+	dst.generic->handle = src->generic.handle;
+	dst.generic->id = src->generic.id;
+	dst.generic->sector_number = src->generic.sector_number;
 	barrier();
-	if (n > dst->nr_segments)
-		n = dst->nr_segments;
-	for (i = 0; i < n; i++)
-		dst->seg[i] = src->seg[i];
+	switch (__builtin_expect(dst.generic->operation, BLKIF_OP_READ)) {
+	default:
+		n = min_t(unsigned int, dst.generic->nr_segments,
+			  BLKIF_MAX_SEGMENTS_PER_REQUEST);
+		for (i = 0; i < n; i++)
+			dst.generic->seg[i] = src->generic.seg[i];
+		break;
+	case BLKIF_OP_DISCARD:
+		/* All fields up to sector_number got copied above already. */
+		dst.discard->nr_sectors = src->discard.nr_sectors;
+		break;
+	}
+#endif
 }
 
 #endif /* __XEN_BLKIF_H__ */
