Skip to content

Commit 44abff2

Browse files
Christoph Hellwigaxboe
authored andcommitted
block: decouple REQ_OP_SECURE_ERASE from REQ_OP_DISCARD
Secure erase is a very different operation from discard in that it is a data integrity operation vs hint. Fully split the limits and helper infrastructure to make the separation more clear. Signed-off-by: Christoph Hellwig <[email protected]> Reviewed-by: Martin K. Petersen <[email protected]> Acked-by: Christoph Böhmwalder <[email protected]> [drbd] Acked-by: Ryusuke Konishi <[email protected]> [nifs2] Acked-by: Jaegeuk Kim <[email protected]> [f2fs] Acked-by: Coly Li <[email protected]> [bcache] Acked-by: David Sterba <[email protected]> [btrfs] Acked-by: Chao Yu <[email protected]> Reviewed-by: Chaitanya Kulkarni <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jens Axboe <[email protected]>
1 parent 7b47ef5 commit 44abff2

33 files changed

+168
-99
lines changed

block/blk-core.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -824,7 +824,7 @@ void submit_bio_noacct(struct bio *bio)
824824
goto not_supported;
825825
break;
826826
case REQ_OP_SECURE_ERASE:
827-
if (!blk_queue_secure_erase(q))
827+
if (!bdev_max_secure_erase_sectors(bdev))
828828
goto not_supported;
829829
break;
830830
case REQ_OP_ZONE_APPEND:

block/blk-lib.c

Lines changed: 45 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -36,26 +36,15 @@ static sector_t bio_discard_limit(struct block_device *bdev, sector_t sector)
3636
}
3737

3838
int __blkdev_issue_discard(struct block_device *bdev, sector_t sector,
39-
sector_t nr_sects, gfp_t gfp_mask, int flags,
40-
struct bio **biop)
39+
sector_t nr_sects, gfp_t gfp_mask, struct bio **biop)
4140
{
42-
struct request_queue *q = bdev_get_queue(bdev);
4341
struct bio *bio = *biop;
44-
unsigned int op;
4542
sector_t bs_mask;
4643

4744
if (bdev_read_only(bdev))
4845
return -EPERM;
49-
50-
if (flags & BLKDEV_DISCARD_SECURE) {
51-
if (!blk_queue_secure_erase(q))
52-
return -EOPNOTSUPP;
53-
op = REQ_OP_SECURE_ERASE;
54-
} else {
55-
if (!bdev_max_discard_sectors(bdev))
56-
return -EOPNOTSUPP;
57-
op = REQ_OP_DISCARD;
58-
}
46+
if (!bdev_max_discard_sectors(bdev))
47+
return -EOPNOTSUPP;
5948

6049
/* In case the discard granularity isn't set by buggy device driver */
6150
if (WARN_ON_ONCE(!bdev_discard_granularity(bdev))) {
@@ -77,7 +66,7 @@ int __blkdev_issue_discard(struct block_device *bdev, sector_t sector,
7766
sector_t req_sects =
7867
min(nr_sects, bio_discard_limit(bdev, sector));
7968

80-
bio = blk_next_bio(bio, bdev, 0, op, gfp_mask);
69+
bio = blk_next_bio(bio, bdev, 0, REQ_OP_DISCARD, gfp_mask);
8170
bio->bi_iter.bi_sector = sector;
8271
bio->bi_iter.bi_size = req_sects << 9;
8372
sector += req_sects;
@@ -103,21 +92,19 @@ EXPORT_SYMBOL(__blkdev_issue_discard);
10392
* @sector: start sector
10493
* @nr_sects: number of sectors to discard
10594
* @gfp_mask: memory allocation flags (for bio_alloc)
106-
* @flags: BLKDEV_DISCARD_* flags to control behaviour
10795
*
10896
* Description:
10997
* Issue a discard request for the sectors in question.
11098
*/
11199
int blkdev_issue_discard(struct block_device *bdev, sector_t sector,
112-
sector_t nr_sects, gfp_t gfp_mask, unsigned long flags)
100+
sector_t nr_sects, gfp_t gfp_mask)
113101
{
114102
struct bio *bio = NULL;
115103
struct blk_plug plug;
116104
int ret;
117105

118106
blk_start_plug(&plug);
119-
ret = __blkdev_issue_discard(bdev, sector, nr_sects, gfp_mask, flags,
120-
&bio);
107+
ret = __blkdev_issue_discard(bdev, sector, nr_sects, gfp_mask, &bio);
121108
if (!ret && bio) {
122109
ret = submit_bio_wait(bio);
123110
if (ret == -EOPNOTSUPP)
@@ -314,3 +301,42 @@ int blkdev_issue_zeroout(struct block_device *bdev, sector_t sector,
314301
return ret;
315302
}
316303
EXPORT_SYMBOL(blkdev_issue_zeroout);
304+
305+
int blkdev_issue_secure_erase(struct block_device *bdev, sector_t sector,
306+
sector_t nr_sects, gfp_t gfp)
307+
{
308+
sector_t bs_mask = (bdev_logical_block_size(bdev) >> 9) - 1;
309+
unsigned int max_sectors = bdev_max_secure_erase_sectors(bdev);
310+
struct bio *bio = NULL;
311+
struct blk_plug plug;
312+
int ret = 0;
313+
314+
if (max_sectors == 0)
315+
return -EOPNOTSUPP;
316+
if ((sector | nr_sects) & bs_mask)
317+
return -EINVAL;
318+
if (bdev_read_only(bdev))
319+
return -EPERM;
320+
321+
blk_start_plug(&plug);
322+
for (;;) {
323+
unsigned int len = min_t(sector_t, nr_sects, max_sectors);
324+
325+
bio = blk_next_bio(bio, bdev, 0, REQ_OP_SECURE_ERASE, gfp);
326+
bio->bi_iter.bi_sector = sector;
327+
bio->bi_iter.bi_size = len;
328+
329+
sector += len << SECTOR_SHIFT;
330+
nr_sects -= len << SECTOR_SHIFT;
331+
if (!nr_sects) {
332+
ret = submit_bio_wait(bio);
333+
bio_put(bio);
334+
break;
335+
}
336+
cond_resched();
337+
}
338+
blk_finish_plug(&plug);
339+
340+
return ret;
341+
}
342+
EXPORT_SYMBOL(blkdev_issue_secure_erase);

block/blk-mq-debugfs.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,6 @@ static const char *const blk_queue_flag_name[] = {
115115
QUEUE_FLAG_NAME(IO_STAT),
116116
QUEUE_FLAG_NAME(NOXMERGES),
117117
QUEUE_FLAG_NAME(ADD_RANDOM),
118-
QUEUE_FLAG_NAME(SECERASE),
119118
QUEUE_FLAG_NAME(SAME_FORCE),
120119
QUEUE_FLAG_NAME(DEAD),
121120
QUEUE_FLAG_NAME(INIT_DONE),

block/blk-settings.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ void blk_set_default_limits(struct queue_limits *lim)
4646
lim->max_zone_append_sectors = 0;
4747
lim->max_discard_sectors = 0;
4848
lim->max_hw_discard_sectors = 0;
49+
lim->max_secure_erase_sectors = 0;
4950
lim->discard_granularity = 0;
5051
lim->discard_alignment = 0;
5152
lim->discard_misaligned = 0;
@@ -176,6 +177,18 @@ void blk_queue_max_discard_sectors(struct request_queue *q,
176177
}
177178
EXPORT_SYMBOL(blk_queue_max_discard_sectors);
178179

180+
/**
181+
* blk_queue_max_secure_erase_sectors - set max sectors for a secure erase
182+
* @q: the request queue for the device
183+
* @max_sectors: maximum number of sectors to secure_erase
184+
**/
185+
void blk_queue_max_secure_erase_sectors(struct request_queue *q,
186+
unsigned int max_sectors)
187+
{
188+
q->limits.max_secure_erase_sectors = max_sectors;
189+
}
190+
EXPORT_SYMBOL(blk_queue_max_secure_erase_sectors);
191+
179192
/**
180193
* blk_queue_max_write_zeroes_sectors - set max sectors for a single
181194
* write zeroes
@@ -661,7 +674,8 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,
661674
t->discard_alignment = lcm_not_zero(t->discard_alignment, alignment) %
662675
t->discard_granularity;
663676
}
664-
677+
t->max_secure_erase_sectors = min_not_zero(t->max_secure_erase_sectors,
678+
b->max_secure_erase_sectors);
665679
t->zone_write_granularity = max(t->zone_write_granularity,
666680
b->zone_write_granularity);
667681
t->zoned = max(t->zoned, b->zoned);

block/fops.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -677,7 +677,7 @@ static long blkdev_fallocate(struct file *file, int mode, loff_t start,
677677
break;
678678
case FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE | FALLOC_FL_NO_HIDE_STALE:
679679
error = blkdev_issue_discard(bdev, start >> SECTOR_SHIFT,
680-
len >> SECTOR_SHIFT, GFP_KERNEL, 0);
680+
len >> SECTOR_SHIFT, GFP_KERNEL);
681681
break;
682682
default:
683683
error = -EOPNOTSUPP;

block/ioctl.c

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ static int compat_blkpg_ioctl(struct block_device *bdev,
8383
#endif
8484

8585
static int blk_ioctl_discard(struct block_device *bdev, fmode_t mode,
86-
unsigned long arg, unsigned long flags)
86+
unsigned long arg)
8787
{
8888
uint64_t range[2];
8989
uint64_t start, len;
@@ -114,15 +114,43 @@ static int blk_ioctl_discard(struct block_device *bdev, fmode_t mode,
114114
err = truncate_bdev_range(bdev, mode, start, start + len - 1);
115115
if (err)
116116
goto fail;
117-
118-
err = blkdev_issue_discard(bdev, start >> 9, len >> 9,
119-
GFP_KERNEL, flags);
120-
117+
err = blkdev_issue_discard(bdev, start >> 9, len >> 9, GFP_KERNEL);
121118
fail:
122119
filemap_invalidate_unlock(inode->i_mapping);
123120
return err;
124121
}
125122

123+
static int blk_ioctl_secure_erase(struct block_device *bdev, fmode_t mode,
124+
void __user *argp)
125+
{
126+
uint64_t start, len;
127+
uint64_t range[2];
128+
int err;
129+
130+
if (!(mode & FMODE_WRITE))
131+
return -EBADF;
132+
if (!bdev_max_secure_erase_sectors(bdev))
133+
return -EOPNOTSUPP;
134+
if (copy_from_user(range, argp, sizeof(range)))
135+
return -EFAULT;
136+
137+
start = range[0];
138+
len = range[1];
139+
if ((start & 511) || (len & 511))
140+
return -EINVAL;
141+
if (start + len > bdev_nr_bytes(bdev))
142+
return -EINVAL;
143+
144+
filemap_invalidate_lock(bdev->bd_inode->i_mapping);
145+
err = truncate_bdev_range(bdev, mode, start, start + len - 1);
146+
if (!err)
147+
err = blkdev_issue_secure_erase(bdev, start >> 9, len >> 9,
148+
GFP_KERNEL);
149+
filemap_invalidate_unlock(bdev->bd_inode->i_mapping);
150+
return err;
151+
}
152+
153+
126154
static int blk_ioctl_zeroout(struct block_device *bdev, fmode_t mode,
127155
unsigned long arg)
128156
{
@@ -450,10 +478,9 @@ static int blkdev_common_ioctl(struct block_device *bdev, fmode_t mode,
450478
case BLKROSET:
451479
return blkdev_roset(bdev, mode, cmd, arg);
452480
case BLKDISCARD:
453-
return blk_ioctl_discard(bdev, mode, arg, 0);
481+
return blk_ioctl_discard(bdev, mode, arg);
454482
case BLKSECDISCARD:
455-
return blk_ioctl_discard(bdev, mode, arg,
456-
BLKDEV_DISCARD_SECURE);
483+
return blk_ioctl_secure_erase(bdev, mode, argp);
457484
case BLKZEROOUT:
458485
return blk_ioctl_zeroout(bdev, mode, arg);
459486
case BLKGETDISKSEQ:

drivers/block/drbd/drbd_receiver.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1547,7 +1547,8 @@ int drbd_issue_discard_or_zero_out(struct drbd_device *device, sector_t start, u
15471547
start = tmp;
15481548
}
15491549
while (nr_sectors >= max_discard_sectors) {
1550-
err |= blkdev_issue_discard(bdev, start, max_discard_sectors, GFP_NOIO, 0);
1550+
err |= blkdev_issue_discard(bdev, start, max_discard_sectors,
1551+
GFP_NOIO);
15511552
nr_sectors -= max_discard_sectors;
15521553
start += max_discard_sectors;
15531554
}
@@ -1559,7 +1560,7 @@ int drbd_issue_discard_or_zero_out(struct drbd_device *device, sector_t start, u
15591560
nr = nr_sectors;
15601561
nr -= (unsigned int)nr % granularity;
15611562
if (nr) {
1562-
err |= blkdev_issue_discard(bdev, start, nr, GFP_NOIO, 0);
1563+
err |= blkdev_issue_discard(bdev, start, nr, GFP_NOIO);
15631564
nr_sectors -= nr;
15641565
start += nr;
15651566
}

drivers/block/rnbd/rnbd-clt.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1365,8 +1365,8 @@ static void setup_request_queue(struct rnbd_clt_dev *dev)
13651365
dev->queue->limits.discard_granularity = dev->discard_granularity;
13661366
dev->queue->limits.discard_alignment = dev->discard_alignment;
13671367
if (dev->secure_discard)
1368-
blk_queue_flag_set(QUEUE_FLAG_SECERASE, dev->queue);
1369-
1368+
blk_queue_max_secure_erase_sectors(dev->queue,
1369+
dev->max_discard_sectors);
13701370
blk_queue_flag_set(QUEUE_FLAG_SAME_COMP, dev->queue);
13711371
blk_queue_flag_set(QUEUE_FLAG_SAME_FORCE, dev->queue);
13721372
blk_queue_max_segments(dev->queue, dev->max_segments);

drivers/block/rnbd/rnbd-srv-dev.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ static inline int rnbd_dev_get_max_hw_sects(const struct rnbd_dev *dev)
4444

4545
static inline int rnbd_dev_get_secure_discard(const struct rnbd_dev *dev)
4646
{
47-
return blk_queue_secure_erase(bdev_get_queue(dev->bdev));
47+
return bdev_max_secure_erase_sectors(dev->bdev);
4848
}
4949

5050
static inline int rnbd_dev_get_max_discard_sects(const struct rnbd_dev *dev)

drivers/block/xen-blkback/blkback.c

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -970,7 +970,6 @@ static int dispatch_discard_io(struct xen_blkif_ring *ring,
970970
int status = BLKIF_RSP_OKAY;
971971
struct xen_blkif *blkif = ring->blkif;
972972
struct block_device *bdev = blkif->vbd.bdev;
973-
unsigned long secure;
974973
struct phys_req preq;
975974

976975
xen_blkif_get(blkif);
@@ -987,13 +986,15 @@ static int dispatch_discard_io(struct xen_blkif_ring *ring,
987986
}
988987
ring->st_ds_req++;
989988

990-
secure = (blkif->vbd.discard_secure &&
991-
(req->u.discard.flag & BLKIF_DISCARD_SECURE)) ?
992-
BLKDEV_DISCARD_SECURE : 0;
989+
if (blkif->vbd.discard_secure &&
990+
(req->u.discard.flag & BLKIF_DISCARD_SECURE))
991+
err = blkdev_issue_secure_erase(bdev,
992+
req->u.discard.sector_number,
993+
req->u.discard.nr_sectors, GFP_KERNEL);
994+
else
995+
err = blkdev_issue_discard(bdev, req->u.discard.sector_number,
996+
req->u.discard.nr_sectors, GFP_KERNEL);
993997

994-
err = blkdev_issue_discard(bdev, req->u.discard.sector_number,
995-
req->u.discard.nr_sectors,
996-
GFP_KERNEL, secure);
997998
fail_response:
998999
if (err == -EOPNOTSUPP) {
9991000
pr_debug("discard op failed, not supported\n");

drivers/block/xen-blkback/xenbus.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -484,7 +484,6 @@ static int xen_vbd_create(struct xen_blkif *blkif, blkif_vdev_t handle,
484484
{
485485
struct xen_vbd *vbd;
486486
struct block_device *bdev;
487-
struct request_queue *q;
488487

489488
vbd = &blkif->vbd;
490489
vbd->handle = handle;
@@ -516,11 +515,9 @@ static int xen_vbd_create(struct xen_blkif *blkif, blkif_vdev_t handle,
516515
if (vbd->bdev->bd_disk->flags & GENHD_FL_REMOVABLE)
517516
vbd->type |= VDISK_REMOVABLE;
518517

519-
q = bdev_get_queue(bdev);
520518
if (bdev_write_cache(bdev))
521519
vbd->flush_support = true;
522-
523-
if (q && blk_queue_secure_erase(q))
520+
if (bdev_max_secure_erase_sectors(bdev))
524521
vbd->discard_secure = true;
525522

526523
vbd->feature_gnt_persistent = feature_persistent;

drivers/block/xen-blkfront.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -949,7 +949,8 @@ static void blkif_set_queue_limits(struct blkfront_info *info)
949949
info->physical_sector_size;
950950
rq->limits.discard_alignment = info->discard_alignment;
951951
if (info->feature_secdiscard)
952-
blk_queue_flag_set(QUEUE_FLAG_SECERASE, rq);
952+
blk_queue_max_secure_erase_sectors(rq,
953+
get_capacity(gd));
953954
}
954955

955956
/* Hard sector size and max sectors impersonate the equiv. hardware. */
@@ -1606,7 +1607,7 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
16061607
info->feature_discard = 0;
16071608
info->feature_secdiscard = 0;
16081609
blk_queue_max_discard_sectors(rq, 0);
1609-
blk_queue_flag_clear(QUEUE_FLAG_SECERASE, rq);
1610+
blk_queue_max_secure_erase_sectors(rq, 0);
16101611
}
16111612
break;
16121613
case BLKIF_OP_FLUSH_DISKCACHE:

drivers/md/bcache/alloc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ static int bch_allocator_thread(void *arg)
336336
mutex_unlock(&ca->set->bucket_lock);
337337
blkdev_issue_discard(ca->bdev,
338338
bucket_to_sector(ca->set, bucket),
339-
ca->sb.bucket_size, GFP_KERNEL, 0);
339+
ca->sb.bucket_size, GFP_KERNEL);
340340
mutex_lock(&ca->set->bucket_lock);
341341
}
342342

drivers/md/dm-table.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1920,9 +1920,7 @@ static int device_not_secure_erase_capable(struct dm_target *ti,
19201920
struct dm_dev *dev, sector_t start,
19211921
sector_t len, void *data)
19221922
{
1923-
struct request_queue *q = bdev_get_queue(dev->bdev);
1924-
1925-
return !blk_queue_secure_erase(q);
1923+
return !bdev_max_secure_erase_sectors(dev->bdev);
19261924
}
19271925

19281926
static bool dm_table_supports_secure_erase(struct dm_table *t)
@@ -1975,8 +1973,8 @@ int dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
19751973
q->limits.discard_misaligned = 0;
19761974
}
19771975

1978-
if (dm_table_supports_secure_erase(t))
1979-
blk_queue_flag_set(QUEUE_FLAG_SECERASE, q);
1976+
if (!dm_table_supports_secure_erase(t))
1977+
q->limits.max_secure_erase_sectors = 0;
19801978

19811979
if (dm_table_supports_flush(t, (1UL << QUEUE_FLAG_WC))) {
19821980
wc = true;

drivers/md/dm-thin.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -398,8 +398,8 @@ static int issue_discard(struct discard_op *op, dm_block_t data_b, dm_block_t da
398398
sector_t s = block_to_sectors(tc->pool, data_b);
399399
sector_t len = block_to_sectors(tc->pool, data_e - data_b);
400400

401-
return __blkdev_issue_discard(tc->pool_dev->bdev, s, len,
402-
GFP_NOWAIT, 0, &op->bio);
401+
return __blkdev_issue_discard(tc->pool_dev->bdev, s, len, GFP_NOWAIT,
402+
&op->bio);
403403
}
404404

405405
static void end_discard(struct discard_op *op, int r)

drivers/md/md.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8584,7 +8584,7 @@ void md_submit_discard_bio(struct mddev *mddev, struct md_rdev *rdev,
85848584
{
85858585
struct bio *discard_bio = NULL;
85868586

8587-
if (__blkdev_issue_discard(rdev->bdev, start, size, GFP_NOIO, 0,
8587+
if (__blkdev_issue_discard(rdev->bdev, start, size, GFP_NOIO,
85888588
&discard_bio) || !discard_bio)
85898589
return;
85908590

0 commit comments

Comments
 (0)