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 <[email protected]>

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

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);

--
dm-devel mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/dm-devel

Reply via email to