diff mbox

block: make discard killable

Message ID alpine.LRH.2.02.1807031334400.22443@file01.intranet.prod.int.rdu2.redhat.com (mailing list archive)
State New, archived
Headers show

Commit Message

Mikulas Patocka July 3, 2018, 5:35 p.m. UTC
Discarding can take very long time for some device mapper targets, this
patch makes it possible to kill a process that issues the BLKDISCARD
ioctl.

Note that some filesystems call blkdev_issue_discard or
__blkdev_issue_discard directly, they may not be prepared to handle the
failure, so this patch introduces a flag BLKDEV_DISCARD_KILLABLE that is
only set when the discard is initiated by an ioctl.

Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>

---
 block/blk-lib.c        |   13 +++++++++++--
 block/ioctl.c          |    4 ++--
 include/linux/blkdev.h |    1 +
 3 files changed, 14 insertions(+), 4 deletions(-)

Comments

Jens Axboe July 6, 2018, 1:51 p.m. UTC | #1
On 7/3/18 11:35 AM, Mikulas Patocka wrote:
> Discarding can take very long time for some device mapper targets, this
> patch makes it possible to kill a process that issues the BLKDISCARD
> ioctl.
> 
> Note that some filesystems call blkdev_issue_discard or
> __blkdev_issue_discard directly, they may not be prepared to handle the
> failure, so this patch introduces a flag BLKDEV_DISCARD_KILLABLE that is
> only set when the discard is initiated by an ioctl.

This might be cleaner as a regular request flag, since killable can
apply to other types of IO as well - like readahead.
Christoph Hellwig July 8, 2018, 7:18 p.m. UTC | #2
On Fri, Jul 06, 2018 at 07:51:30AM -0600, Jens Axboe wrote:
> On 7/3/18 11:35 AM, Mikulas Patocka wrote:
> > Discarding can take very long time for some device mapper targets, this
> > patch makes it possible to kill a process that issues the BLKDISCARD
> > ioctl.
> > 
> > Note that some filesystems call blkdev_issue_discard or
> > __blkdev_issue_discard directly, they may not be prepared to handle the
> > failure, so this patch introduces a flag BLKDEV_DISCARD_KILLABLE that is
> > only set when the discard is initiated by an ioctl.
> 
> This might be cleaner as a regular request flag, since killable can
> apply to other types of IO as well - like readahead.

He doesn't actually make the request killable, but just the
synchronous submission loop.  I have an actually killable version
of blk_execute_rq on m short-term todo plate as we want it for the
nvme passthrough ioctls.  That might be useful for discard as well.
Mikulas Patocka July 10, 2018, 1:10 a.m. UTC | #3
On Fri, 6 Jul 2018, Jens Axboe wrote:

> On 7/3/18 11:35 AM, Mikulas Patocka wrote:
> > Discarding can take very long time for some device mapper targets, this
> > patch makes it possible to kill a process that issues the BLKDISCARD
> > ioctl.
> > 
> > Note that some filesystems call blkdev_issue_discard or
> > __blkdev_issue_discard directly, they may not be prepared to handle the
> > failure, so this patch introduces a flag BLKDEV_DISCARD_KILLABLE that is
> > only set when the discard is initiated by an ioctl.
> 
> This might be cleaner as a regular request flag, since killable can
> apply to other types of IO as well - like readahead.
> 
> -- 
> Jens Axboe

blkdev_issue_discard and __blkdev_issue_discard doesn't take flags for the 
request - it has a "flags" argument which could only contain one flag - 
BLKDEV_DISCARD_SECURE.

Do you want to copy the "flags" argument from blkdev_issue_discard to the 
bio and check the bio flag in generic_make_request?

Mikulas
diff mbox

Patch

Index: linux-2.6/block/blk-lib.c
===================================================================
--- linux-2.6.orig/block/blk-lib.c	2018-06-29 20:10:55.540000000 +0200
+++ linux-2.6/block/blk-lib.c	2018-06-29 23:12:24.520000000 +0200
@@ -7,6 +7,7 @@ 
 #include <linux/bio.h>
 #include <linux/blkdev.h>
 #include <linux/scatterlist.h>
+#include <linux/sched/signal.h>
 
 #include "blk.h"
 
@@ -33,6 +34,7 @@  int __blkdev_issue_discard(struct block_
 	unsigned int op;
 	int alignment;
 	sector_t bs_mask;
+	int r;
 
 	if (!q)
 		return -ENXIO;
@@ -68,8 +70,10 @@  int __blkdev_issue_discard(struct block_
 		 */
 		req_sects = min_t(sector_t, nr_sects,
 					q->limits.max_discard_sectors);
-		if (!req_sects)
+		if (!req_sects) {
+			r = -EOPNOTSUPP;
 			goto fail;
+		}
 		if (req_sects > UINT_MAX >> 9)
 			req_sects = UINT_MAX >> 9;
 
@@ -96,6 +100,11 @@  int __blkdev_issue_discard(struct block_
 		nr_sects -= req_sects;
 		sector = end_sect;
 
+		if (flags & BLKDEV_DISCARD_KILLABLE && fatal_signal_pending(current)) {
+			r = -EINTR;
+			goto fail;
+		}
+
 		/*
 		 * We can loop for a long time in here, if someone does
 		 * full device discards (like mkfs). Be nice and allow
@@ -114,7 +123,7 @@  fail:
 		bio_put(bio);
 	}
 	*biop = NULL;
-	return -EOPNOTSUPP;
+	return r;
 }
 EXPORT_SYMBOL(__blkdev_issue_discard);
 
Index: linux-2.6/block/ioctl.c
===================================================================
--- linux-2.6.orig/block/ioctl.c	2018-05-31 18:04:38.068000000 +0200
+++ linux-2.6/block/ioctl.c	2018-06-29 23:06:07.180000000 +0200
@@ -522,10 +522,10 @@  int blkdev_ioctl(struct block_device *bd
 	case BLKROSET:
 		return blkdev_roset(bdev, mode, cmd, arg);
 	case BLKDISCARD:
-		return blk_ioctl_discard(bdev, mode, arg, 0);
+		return blk_ioctl_discard(bdev, mode, arg, BLKDEV_DISCARD_KILLABLE);
 	case BLKSECDISCARD:
 		return blk_ioctl_discard(bdev, mode, arg,
-				BLKDEV_DISCARD_SECURE);
+				BLKDEV_DISCARD_SECURE | BLKDEV_DISCARD_KILLABLE);
 	case BLKZEROOUT:
 		return blk_ioctl_zeroout(bdev, mode, arg);
 	case BLKREPORTZONE:
Index: linux-2.6/include/linux/blkdev.h
===================================================================
--- linux-2.6.orig/include/linux/blkdev.h	2018-06-18 01:09:22.040000000 +0200
+++ linux-2.6/include/linux/blkdev.h	2018-06-29 23:09:50.010000000 +0200
@@ -1390,6 +1390,7 @@  extern int blkdev_issue_write_same(struc
 		sector_t nr_sects, gfp_t gfp_mask, struct page *page);
 
 #define BLKDEV_DISCARD_SECURE	(1 << 0)	/* issue a secure erase */
+#define BLKDEV_DISCARD_KILLABLE	(1 << 1)	/* allow killing the process */
 
 extern int blkdev_issue_discard(struct block_device *bdev, sector_t sector,
 		sector_t nr_sects, gfp_t gfp_mask, unsigned long flags);