From: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Subject: blkfront: Enhance discard support with secure erasing support
References: fate#309305
Patch-mainline: n/a
    
Part of the blkdev_issue_discard(xx) operation is that it can also
issue a secure discard operation that will permanantly remove the
sectors in question. We advertise that we can support that via the
'discard-secure' attribute and on the request, if the 'secure' bit
is set, we will attempt to pass in REQ_DISCARD | REQ_SECURE.
    
CC: Li Dongyang <lidongyang@novell.com>
[v1: Used 'flag' instead of 'secure:1' bit]
[v2: Use 'reserved 'uint8_t' as a flag]
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Acked-by: jbeulich@suse.com

--- sle11sp3.orig/drivers/xen/blkfront/blkfront.c	2014-01-22 14:13:52.000000000 +0100
+++ sle11sp3/drivers/xen/blkfront/blkfront.c	2014-01-22 14:16:56.000000000 +0100
@@ -332,6 +332,7 @@ static void blkfront_setup_discard(struc
 {
 	unsigned int discard_granularity;
 	unsigned int discard_alignment;
+	int discard_secure;
 
 	info->feature_discard = 1;
 	if (!xenbus_gather(XBT_NIL, info->xbdev->otherend,
@@ -341,6 +342,10 @@ static void blkfront_setup_discard(struc
 		info->discard_granularity = discard_granularity;
 		info->discard_alignment = discard_alignment;
 	}
+	if (xenbus_scanf(XBT_NIL, info->xbdev->otherend,
+			 "discard-secure", "%d", &discard_secure) != 1)
+		discard_secure = 0;
+	info->feature_secdiscard = !!discard_secure;
 }
 
 /*
@@ -840,13 +845,15 @@ static int blkif_queue_request(struct re
 #endif
 		ring_req->operation = info->flush_op;
 
-	if (unlikely(req->cmd_flags & REQ_DISCARD)) {
+	if (unlikely(req->cmd_flags & (REQ_DISCARD | REQ_SECURE))) {
 		struct blkif_request_discard *discard = (void *)ring_req;
 
 		/* id, sector_number and handle are set above. */
 		discard->operation = BLKIF_OP_DISCARD;
 		discard->flag = 0;
 		discard->nr_sectors = blk_rq_sectors(req);
+		if ((req->cmd_flags & REQ_SECURE) && info->feature_secdiscard)
+			discard->flag = BLKIF_DISCARD_SECURE;
 	} else {
 		ring_req->nr_segments = blk_rq_map_sg(req->q, req, info->sg);
 		BUG_ON(ring_req->nr_segments > BLKIF_MAX_SEGMENTS_PER_REQUEST);
@@ -1031,7 +1038,9 @@ static irqreturn_t blkif_int(int irq, vo
 					info->gd->disk_name);
 				ret = -EOPNOTSUPP;
 				info->feature_discard = 0;
+				info->feature_secdiscard = 0;
 				queue_flag_clear(QUEUE_FLAG_DISCARD, rq);
+				queue_flag_clear(QUEUE_FLAG_SECDISCARD, rq);
 			}
 			__blk_end_request_all(req, ret);
 			break;
@@ -1088,6 +1097,9 @@ static void blkif_free(struct blkfront_i
 static void blkif_completion(struct blk_shadow *s)
 {
 	int i;
+
+	if (s->req.operation == BLKIF_OP_DISCARD)
+		return;
 	for (i = 0; i < s->req.nr_segments; i++)
 		gnttab_end_foreign_access(s->req.seg[i].gref, 0UL);
 }
--- sle11sp3.orig/drivers/xen/blkfront/block.h	2012-10-19 15:13:49.000000000 +0200
+++ sle11sp3/drivers/xen/blkfront/block.h	2012-10-19 15:14:19.000000000 +0200
@@ -109,7 +109,8 @@ struct blkfront_info
 	unsigned long shadow_free;
 	unsigned int feature_flush;
 	unsigned int flush_op;
-	unsigned int feature_discard;
+	bool feature_discard;
+	bool feature_secdiscard;
 	unsigned int discard_granularity;
 	unsigned int discard_alignment;
 	int is_ready;
--- sle11sp3.orig/drivers/xen/blkfront/vbd.c	2012-10-19 15:13:53.000000000 +0200
+++ sle11sp3/drivers/xen/blkfront/vbd.c	2012-10-19 15:14:20.000000000 +0200
@@ -370,6 +370,8 @@ xlvbd_init_blk_queue(struct gendisk *gd,
 		blk_queue_max_discard_sectors(rq, get_capacity(gd));
 		rq->limits.discard_granularity = info->discard_granularity;
 		rq->limits.discard_alignment = info->discard_alignment;
+		if (info->feature_secdiscard)
+			queue_flag_set_unlocked(QUEUE_FLAG_SECDISCARD, rq);
 	}
 
 	/* Hard sector size and max sectors impersonate the equiv. hardware. */
