[PATCH 5/5] block: don't allow fatal signals to interrupt (__)blkdev_issue_discard
Christoph Hellwig
hch at lst.de
Tue Mar 12 07:48:26 PDT 2024
File system won't to handle fatal signals themselves and are generally
not prepared for EINTR errors from (__)blkdev_issue_discard. Remove
the logic from the generic helpers and instead open code the discard
bio submission in the ioctl handler that wants it.
Fixes: 8a08c5fd89b4 ("blk-lib: check for kill signal")
Signed-off-by: Christoph Hellwig <hch at lst.de>
---
block/blk-lib.c | 12 +++---------
block/ioctl.c | 24 ++++++++++++++++++++++--
2 files changed, 25 insertions(+), 11 deletions(-)
diff --git a/block/blk-lib.c b/block/blk-lib.c
index 8021bc3831d56a..90b75605299b9c 100644
--- a/block/blk-lib.c
+++ b/block/blk-lib.c
@@ -65,16 +65,10 @@ int __blkdev_issue_discard(struct block_device *bdev, sector_t sector,
{
struct bio *bio;
- while (!fatal_signal_pending(current)) {
- bio = blk_alloc_discard_bio(bdev, §or, &nr_sects, gfp_mask);
- if (!bio)
- return 0;
+ while ((bio = blk_alloc_discard_bio(bdev, §or, &nr_sects,
+ gfp_mask)))
*biop = bio_chain_and_submit(*biop, bio);
- }
-
- if (*biop)
- bio_await_chain(*biop);
- return -EINTR;
+ return 0;
}
EXPORT_SYMBOL(__blkdev_issue_discard);
diff --git a/block/ioctl.c b/block/ioctl.c
index 57c8171fda93c5..32bbdba77d6941 100644
--- a/block/ioctl.c
+++ b/block/ioctl.c
@@ -96,10 +96,12 @@ static int blk_ioctl_discard(struct block_device *bdev, blk_mode_t mode,
unsigned long arg)
{
sector_t bs_mask = (bdev_logical_block_size(bdev) >> SECTOR_SHIFT) - 1;
+ struct inode *inode = bdev->bd_inode;
sector_t sector, nr_sects;
+ struct bio *bio = NULL, *new;
+ struct blk_plug plug;
uint64_t range[2];
uint64_t start, len;
- struct inode *inode = bdev->bd_inode;
int err;
if (!(mode & BLK_OPEN_WRITE))
@@ -129,7 +131,25 @@ static int blk_ioctl_discard(struct block_device *bdev, blk_mode_t mode,
err = truncate_bdev_range(bdev, mode, start, start + len - 1);
if (err)
goto fail;
- err = blkdev_issue_discard(bdev, sector, nr_sects, GFP_KERNEL);
+ blk_start_plug(&plug);
+ while (!fatal_signal_pending(current)) {
+ new = blk_alloc_discard_bio(bdev, §or, &nr_sects,
+ GFP_KERNEL);
+ if (!new)
+ break;
+ bio = bio_chain_and_submit(bio, new);
+ }
+ if (fatal_signal_pending(current)) {
+ if (bio)
+ bio_await_chain(bio);
+ err = -EINTR;
+ } else if (bio) {
+ err = submit_bio_wait(bio);
+ if (err == -EOPNOTSUPP)
+ err = 0;
+ bio_put(bio);
+ }
+ blk_finish_plug(&plug);
fail:
filemap_invalidate_unlock(inode->i_mapping);
return err;
--
2.39.2
More information about the Linux-nvme
mailing list