forked from Minki/linux
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 <hch@lst.de> Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com> Acked-by: Christoph Böhmwalder <christoph.boehmwalder@linbit.com> [drbd] Acked-by: Ryusuke Konishi <konishi.ryusuke@gmail.com> [nifs2] Acked-by: Jaegeuk Kim <jaegeuk@kernel.org> [f2fs] Acked-by: Coly Li <colyli@suse.de> [bcache] Acked-by: David Sterba <dsterba@suse.com> [btrfs] Acked-by: Chao Yu <chao@kernel.org> Reviewed-by: Chaitanya Kulkarni <kch@nvidia.com> Link: https://lore.kernel.org/r/20220415045258.199825-27-hch@lst.de Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
parent
7b47ef52d0
commit
44abff2c0b
@ -824,7 +824,7 @@ void submit_bio_noacct(struct bio *bio)
|
|||||||
goto not_supported;
|
goto not_supported;
|
||||||
break;
|
break;
|
||||||
case REQ_OP_SECURE_ERASE:
|
case REQ_OP_SECURE_ERASE:
|
||||||
if (!blk_queue_secure_erase(q))
|
if (!bdev_max_secure_erase_sectors(bdev))
|
||||||
goto not_supported;
|
goto not_supported;
|
||||||
break;
|
break;
|
||||||
case REQ_OP_ZONE_APPEND:
|
case REQ_OP_ZONE_APPEND:
|
||||||
|
@ -36,26 +36,15 @@ static sector_t bio_discard_limit(struct block_device *bdev, sector_t sector)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int __blkdev_issue_discard(struct block_device *bdev, sector_t sector,
|
int __blkdev_issue_discard(struct block_device *bdev, sector_t sector,
|
||||||
sector_t nr_sects, gfp_t gfp_mask, int flags,
|
sector_t nr_sects, gfp_t gfp_mask, struct bio **biop)
|
||||||
struct bio **biop)
|
|
||||||
{
|
{
|
||||||
struct request_queue *q = bdev_get_queue(bdev);
|
|
||||||
struct bio *bio = *biop;
|
struct bio *bio = *biop;
|
||||||
unsigned int op;
|
|
||||||
sector_t bs_mask;
|
sector_t bs_mask;
|
||||||
|
|
||||||
if (bdev_read_only(bdev))
|
if (bdev_read_only(bdev))
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
|
|
||||||
if (flags & BLKDEV_DISCARD_SECURE) {
|
|
||||||
if (!blk_queue_secure_erase(q))
|
|
||||||
return -EOPNOTSUPP;
|
|
||||||
op = REQ_OP_SECURE_ERASE;
|
|
||||||
} else {
|
|
||||||
if (!bdev_max_discard_sectors(bdev))
|
if (!bdev_max_discard_sectors(bdev))
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
op = REQ_OP_DISCARD;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* In case the discard granularity isn't set by buggy device driver */
|
/* In case the discard granularity isn't set by buggy device driver */
|
||||||
if (WARN_ON_ONCE(!bdev_discard_granularity(bdev))) {
|
if (WARN_ON_ONCE(!bdev_discard_granularity(bdev))) {
|
||||||
@ -77,7 +66,7 @@ int __blkdev_issue_discard(struct block_device *bdev, sector_t sector,
|
|||||||
sector_t req_sects =
|
sector_t req_sects =
|
||||||
min(nr_sects, bio_discard_limit(bdev, sector));
|
min(nr_sects, bio_discard_limit(bdev, sector));
|
||||||
|
|
||||||
bio = blk_next_bio(bio, bdev, 0, op, gfp_mask);
|
bio = blk_next_bio(bio, bdev, 0, REQ_OP_DISCARD, gfp_mask);
|
||||||
bio->bi_iter.bi_sector = sector;
|
bio->bi_iter.bi_sector = sector;
|
||||||
bio->bi_iter.bi_size = req_sects << 9;
|
bio->bi_iter.bi_size = req_sects << 9;
|
||||||
sector += req_sects;
|
sector += req_sects;
|
||||||
@ -103,21 +92,19 @@ EXPORT_SYMBOL(__blkdev_issue_discard);
|
|||||||
* @sector: start sector
|
* @sector: start sector
|
||||||
* @nr_sects: number of sectors to discard
|
* @nr_sects: number of sectors to discard
|
||||||
* @gfp_mask: memory allocation flags (for bio_alloc)
|
* @gfp_mask: memory allocation flags (for bio_alloc)
|
||||||
* @flags: BLKDEV_DISCARD_* flags to control behaviour
|
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Issue a discard request for the sectors in question.
|
* Issue a discard request for the sectors in question.
|
||||||
*/
|
*/
|
||||||
int blkdev_issue_discard(struct block_device *bdev, sector_t sector,
|
int blkdev_issue_discard(struct block_device *bdev, sector_t sector,
|
||||||
sector_t nr_sects, gfp_t gfp_mask, unsigned long flags)
|
sector_t nr_sects, gfp_t gfp_mask)
|
||||||
{
|
{
|
||||||
struct bio *bio = NULL;
|
struct bio *bio = NULL;
|
||||||
struct blk_plug plug;
|
struct blk_plug plug;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
blk_start_plug(&plug);
|
blk_start_plug(&plug);
|
||||||
ret = __blkdev_issue_discard(bdev, sector, nr_sects, gfp_mask, flags,
|
ret = __blkdev_issue_discard(bdev, sector, nr_sects, gfp_mask, &bio);
|
||||||
&bio);
|
|
||||||
if (!ret && bio) {
|
if (!ret && bio) {
|
||||||
ret = submit_bio_wait(bio);
|
ret = submit_bio_wait(bio);
|
||||||
if (ret == -EOPNOTSUPP)
|
if (ret == -EOPNOTSUPP)
|
||||||
@ -314,3 +301,42 @@ retry:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(blkdev_issue_zeroout);
|
EXPORT_SYMBOL(blkdev_issue_zeroout);
|
||||||
|
|
||||||
|
int blkdev_issue_secure_erase(struct block_device *bdev, sector_t sector,
|
||||||
|
sector_t nr_sects, gfp_t gfp)
|
||||||
|
{
|
||||||
|
sector_t bs_mask = (bdev_logical_block_size(bdev) >> 9) - 1;
|
||||||
|
unsigned int max_sectors = bdev_max_secure_erase_sectors(bdev);
|
||||||
|
struct bio *bio = NULL;
|
||||||
|
struct blk_plug plug;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (max_sectors == 0)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
if ((sector | nr_sects) & bs_mask)
|
||||||
|
return -EINVAL;
|
||||||
|
if (bdev_read_only(bdev))
|
||||||
|
return -EPERM;
|
||||||
|
|
||||||
|
blk_start_plug(&plug);
|
||||||
|
for (;;) {
|
||||||
|
unsigned int len = min_t(sector_t, nr_sects, max_sectors);
|
||||||
|
|
||||||
|
bio = blk_next_bio(bio, bdev, 0, REQ_OP_SECURE_ERASE, gfp);
|
||||||
|
bio->bi_iter.bi_sector = sector;
|
||||||
|
bio->bi_iter.bi_size = len;
|
||||||
|
|
||||||
|
sector += len << SECTOR_SHIFT;
|
||||||
|
nr_sects -= len << SECTOR_SHIFT;
|
||||||
|
if (!nr_sects) {
|
||||||
|
ret = submit_bio_wait(bio);
|
||||||
|
bio_put(bio);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cond_resched();
|
||||||
|
}
|
||||||
|
blk_finish_plug(&plug);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(blkdev_issue_secure_erase);
|
||||||
|
@ -115,7 +115,6 @@ static const char *const blk_queue_flag_name[] = {
|
|||||||
QUEUE_FLAG_NAME(IO_STAT),
|
QUEUE_FLAG_NAME(IO_STAT),
|
||||||
QUEUE_FLAG_NAME(NOXMERGES),
|
QUEUE_FLAG_NAME(NOXMERGES),
|
||||||
QUEUE_FLAG_NAME(ADD_RANDOM),
|
QUEUE_FLAG_NAME(ADD_RANDOM),
|
||||||
QUEUE_FLAG_NAME(SECERASE),
|
|
||||||
QUEUE_FLAG_NAME(SAME_FORCE),
|
QUEUE_FLAG_NAME(SAME_FORCE),
|
||||||
QUEUE_FLAG_NAME(DEAD),
|
QUEUE_FLAG_NAME(DEAD),
|
||||||
QUEUE_FLAG_NAME(INIT_DONE),
|
QUEUE_FLAG_NAME(INIT_DONE),
|
||||||
|
@ -46,6 +46,7 @@ void blk_set_default_limits(struct queue_limits *lim)
|
|||||||
lim->max_zone_append_sectors = 0;
|
lim->max_zone_append_sectors = 0;
|
||||||
lim->max_discard_sectors = 0;
|
lim->max_discard_sectors = 0;
|
||||||
lim->max_hw_discard_sectors = 0;
|
lim->max_hw_discard_sectors = 0;
|
||||||
|
lim->max_secure_erase_sectors = 0;
|
||||||
lim->discard_granularity = 0;
|
lim->discard_granularity = 0;
|
||||||
lim->discard_alignment = 0;
|
lim->discard_alignment = 0;
|
||||||
lim->discard_misaligned = 0;
|
lim->discard_misaligned = 0;
|
||||||
@ -176,6 +177,18 @@ void blk_queue_max_discard_sectors(struct request_queue *q,
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(blk_queue_max_discard_sectors);
|
EXPORT_SYMBOL(blk_queue_max_discard_sectors);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* blk_queue_max_secure_erase_sectors - set max sectors for a secure erase
|
||||||
|
* @q: the request queue for the device
|
||||||
|
* @max_sectors: maximum number of sectors to secure_erase
|
||||||
|
**/
|
||||||
|
void blk_queue_max_secure_erase_sectors(struct request_queue *q,
|
||||||
|
unsigned int max_sectors)
|
||||||
|
{
|
||||||
|
q->limits.max_secure_erase_sectors = max_sectors;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(blk_queue_max_secure_erase_sectors);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* blk_queue_max_write_zeroes_sectors - set max sectors for a single
|
* blk_queue_max_write_zeroes_sectors - set max sectors for a single
|
||||||
* write zeroes
|
* write zeroes
|
||||||
@ -661,7 +674,8 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,
|
|||||||
t->discard_alignment = lcm_not_zero(t->discard_alignment, alignment) %
|
t->discard_alignment = lcm_not_zero(t->discard_alignment, alignment) %
|
||||||
t->discard_granularity;
|
t->discard_granularity;
|
||||||
}
|
}
|
||||||
|
t->max_secure_erase_sectors = min_not_zero(t->max_secure_erase_sectors,
|
||||||
|
b->max_secure_erase_sectors);
|
||||||
t->zone_write_granularity = max(t->zone_write_granularity,
|
t->zone_write_granularity = max(t->zone_write_granularity,
|
||||||
b->zone_write_granularity);
|
b->zone_write_granularity);
|
||||||
t->zoned = max(t->zoned, b->zoned);
|
t->zoned = max(t->zoned, b->zoned);
|
||||||
|
@ -677,7 +677,7 @@ static long blkdev_fallocate(struct file *file, int mode, loff_t start,
|
|||||||
break;
|
break;
|
||||||
case FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE | FALLOC_FL_NO_HIDE_STALE:
|
case FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE | FALLOC_FL_NO_HIDE_STALE:
|
||||||
error = blkdev_issue_discard(bdev, start >> SECTOR_SHIFT,
|
error = blkdev_issue_discard(bdev, start >> SECTOR_SHIFT,
|
||||||
len >> SECTOR_SHIFT, GFP_KERNEL, 0);
|
len >> SECTOR_SHIFT, GFP_KERNEL);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
error = -EOPNOTSUPP;
|
error = -EOPNOTSUPP;
|
||||||
|
@ -83,7 +83,7 @@ static int compat_blkpg_ioctl(struct block_device *bdev,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int blk_ioctl_discard(struct block_device *bdev, fmode_t mode,
|
static int blk_ioctl_discard(struct block_device *bdev, fmode_t mode,
|
||||||
unsigned long arg, unsigned long flags)
|
unsigned long arg)
|
||||||
{
|
{
|
||||||
uint64_t range[2];
|
uint64_t range[2];
|
||||||
uint64_t start, len;
|
uint64_t start, len;
|
||||||
@ -114,15 +114,43 @@ static int blk_ioctl_discard(struct block_device *bdev, fmode_t mode,
|
|||||||
err = truncate_bdev_range(bdev, mode, start, start + len - 1);
|
err = truncate_bdev_range(bdev, mode, start, start + len - 1);
|
||||||
if (err)
|
if (err)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
err = blkdev_issue_discard(bdev, start >> 9, len >> 9, GFP_KERNEL);
|
||||||
err = blkdev_issue_discard(bdev, start >> 9, len >> 9,
|
|
||||||
GFP_KERNEL, flags);
|
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
filemap_invalidate_unlock(inode->i_mapping);
|
filemap_invalidate_unlock(inode->i_mapping);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int blk_ioctl_secure_erase(struct block_device *bdev, fmode_t mode,
|
||||||
|
void __user *argp)
|
||||||
|
{
|
||||||
|
uint64_t start, len;
|
||||||
|
uint64_t range[2];
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (!(mode & FMODE_WRITE))
|
||||||
|
return -EBADF;
|
||||||
|
if (!bdev_max_secure_erase_sectors(bdev))
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
if (copy_from_user(range, argp, sizeof(range)))
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
start = range[0];
|
||||||
|
len = range[1];
|
||||||
|
if ((start & 511) || (len & 511))
|
||||||
|
return -EINVAL;
|
||||||
|
if (start + len > bdev_nr_bytes(bdev))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
filemap_invalidate_lock(bdev->bd_inode->i_mapping);
|
||||||
|
err = truncate_bdev_range(bdev, mode, start, start + len - 1);
|
||||||
|
if (!err)
|
||||||
|
err = blkdev_issue_secure_erase(bdev, start >> 9, len >> 9,
|
||||||
|
GFP_KERNEL);
|
||||||
|
filemap_invalidate_unlock(bdev->bd_inode->i_mapping);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int blk_ioctl_zeroout(struct block_device *bdev, fmode_t mode,
|
static int blk_ioctl_zeroout(struct block_device *bdev, fmode_t mode,
|
||||||
unsigned long arg)
|
unsigned long arg)
|
||||||
{
|
{
|
||||||
@ -450,10 +478,9 @@ static int blkdev_common_ioctl(struct block_device *bdev, fmode_t mode,
|
|||||||
case BLKROSET:
|
case BLKROSET:
|
||||||
return blkdev_roset(bdev, mode, cmd, arg);
|
return blkdev_roset(bdev, mode, cmd, arg);
|
||||||
case BLKDISCARD:
|
case BLKDISCARD:
|
||||||
return blk_ioctl_discard(bdev, mode, arg, 0);
|
return blk_ioctl_discard(bdev, mode, arg);
|
||||||
case BLKSECDISCARD:
|
case BLKSECDISCARD:
|
||||||
return blk_ioctl_discard(bdev, mode, arg,
|
return blk_ioctl_secure_erase(bdev, mode, argp);
|
||||||
BLKDEV_DISCARD_SECURE);
|
|
||||||
case BLKZEROOUT:
|
case BLKZEROOUT:
|
||||||
return blk_ioctl_zeroout(bdev, mode, arg);
|
return blk_ioctl_zeroout(bdev, mode, arg);
|
||||||
case BLKGETDISKSEQ:
|
case BLKGETDISKSEQ:
|
||||||
|
@ -1547,7 +1547,8 @@ int drbd_issue_discard_or_zero_out(struct drbd_device *device, sector_t start, u
|
|||||||
start = tmp;
|
start = tmp;
|
||||||
}
|
}
|
||||||
while (nr_sectors >= max_discard_sectors) {
|
while (nr_sectors >= max_discard_sectors) {
|
||||||
err |= blkdev_issue_discard(bdev, start, max_discard_sectors, GFP_NOIO, 0);
|
err |= blkdev_issue_discard(bdev, start, max_discard_sectors,
|
||||||
|
GFP_NOIO);
|
||||||
nr_sectors -= max_discard_sectors;
|
nr_sectors -= max_discard_sectors;
|
||||||
start += max_discard_sectors;
|
start += max_discard_sectors;
|
||||||
}
|
}
|
||||||
@ -1559,7 +1560,7 @@ int drbd_issue_discard_or_zero_out(struct drbd_device *device, sector_t start, u
|
|||||||
nr = nr_sectors;
|
nr = nr_sectors;
|
||||||
nr -= (unsigned int)nr % granularity;
|
nr -= (unsigned int)nr % granularity;
|
||||||
if (nr) {
|
if (nr) {
|
||||||
err |= blkdev_issue_discard(bdev, start, nr, GFP_NOIO, 0);
|
err |= blkdev_issue_discard(bdev, start, nr, GFP_NOIO);
|
||||||
nr_sectors -= nr;
|
nr_sectors -= nr;
|
||||||
start += nr;
|
start += nr;
|
||||||
}
|
}
|
||||||
|
@ -1365,8 +1365,8 @@ static void setup_request_queue(struct rnbd_clt_dev *dev)
|
|||||||
dev->queue->limits.discard_granularity = dev->discard_granularity;
|
dev->queue->limits.discard_granularity = dev->discard_granularity;
|
||||||
dev->queue->limits.discard_alignment = dev->discard_alignment;
|
dev->queue->limits.discard_alignment = dev->discard_alignment;
|
||||||
if (dev->secure_discard)
|
if (dev->secure_discard)
|
||||||
blk_queue_flag_set(QUEUE_FLAG_SECERASE, dev->queue);
|
blk_queue_max_secure_erase_sectors(dev->queue,
|
||||||
|
dev->max_discard_sectors);
|
||||||
blk_queue_flag_set(QUEUE_FLAG_SAME_COMP, dev->queue);
|
blk_queue_flag_set(QUEUE_FLAG_SAME_COMP, dev->queue);
|
||||||
blk_queue_flag_set(QUEUE_FLAG_SAME_FORCE, dev->queue);
|
blk_queue_flag_set(QUEUE_FLAG_SAME_FORCE, dev->queue);
|
||||||
blk_queue_max_segments(dev->queue, dev->max_segments);
|
blk_queue_max_segments(dev->queue, dev->max_segments);
|
||||||
|
@ -44,7 +44,7 @@ static inline int rnbd_dev_get_max_hw_sects(const struct rnbd_dev *dev)
|
|||||||
|
|
||||||
static inline int rnbd_dev_get_secure_discard(const struct rnbd_dev *dev)
|
static inline int rnbd_dev_get_secure_discard(const struct rnbd_dev *dev)
|
||||||
{
|
{
|
||||||
return blk_queue_secure_erase(bdev_get_queue(dev->bdev));
|
return bdev_max_secure_erase_sectors(dev->bdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int rnbd_dev_get_max_discard_sects(const struct rnbd_dev *dev)
|
static inline int rnbd_dev_get_max_discard_sects(const struct rnbd_dev *dev)
|
||||||
|
@ -970,7 +970,6 @@ static int dispatch_discard_io(struct xen_blkif_ring *ring,
|
|||||||
int status = BLKIF_RSP_OKAY;
|
int status = BLKIF_RSP_OKAY;
|
||||||
struct xen_blkif *blkif = ring->blkif;
|
struct xen_blkif *blkif = ring->blkif;
|
||||||
struct block_device *bdev = blkif->vbd.bdev;
|
struct block_device *bdev = blkif->vbd.bdev;
|
||||||
unsigned long secure;
|
|
||||||
struct phys_req preq;
|
struct phys_req preq;
|
||||||
|
|
||||||
xen_blkif_get(blkif);
|
xen_blkif_get(blkif);
|
||||||
@ -987,13 +986,15 @@ static int dispatch_discard_io(struct xen_blkif_ring *ring,
|
|||||||
}
|
}
|
||||||
ring->st_ds_req++;
|
ring->st_ds_req++;
|
||||||
|
|
||||||
secure = (blkif->vbd.discard_secure &&
|
if (blkif->vbd.discard_secure &&
|
||||||
(req->u.discard.flag & BLKIF_DISCARD_SECURE)) ?
|
(req->u.discard.flag & BLKIF_DISCARD_SECURE))
|
||||||
BLKDEV_DISCARD_SECURE : 0;
|
err = blkdev_issue_secure_erase(bdev,
|
||||||
|
req->u.discard.sector_number,
|
||||||
|
req->u.discard.nr_sectors, GFP_KERNEL);
|
||||||
|
else
|
||||||
err = blkdev_issue_discard(bdev, req->u.discard.sector_number,
|
err = blkdev_issue_discard(bdev, req->u.discard.sector_number,
|
||||||
req->u.discard.nr_sectors,
|
req->u.discard.nr_sectors, GFP_KERNEL);
|
||||||
GFP_KERNEL, secure);
|
|
||||||
fail_response:
|
fail_response:
|
||||||
if (err == -EOPNOTSUPP) {
|
if (err == -EOPNOTSUPP) {
|
||||||
pr_debug("discard op failed, not supported\n");
|
pr_debug("discard op failed, not supported\n");
|
||||||
|
@ -484,7 +484,6 @@ static int xen_vbd_create(struct xen_blkif *blkif, blkif_vdev_t handle,
|
|||||||
{
|
{
|
||||||
struct xen_vbd *vbd;
|
struct xen_vbd *vbd;
|
||||||
struct block_device *bdev;
|
struct block_device *bdev;
|
||||||
struct request_queue *q;
|
|
||||||
|
|
||||||
vbd = &blkif->vbd;
|
vbd = &blkif->vbd;
|
||||||
vbd->handle = handle;
|
vbd->handle = handle;
|
||||||
@ -516,11 +515,9 @@ static int xen_vbd_create(struct xen_blkif *blkif, blkif_vdev_t handle,
|
|||||||
if (vbd->bdev->bd_disk->flags & GENHD_FL_REMOVABLE)
|
if (vbd->bdev->bd_disk->flags & GENHD_FL_REMOVABLE)
|
||||||
vbd->type |= VDISK_REMOVABLE;
|
vbd->type |= VDISK_REMOVABLE;
|
||||||
|
|
||||||
q = bdev_get_queue(bdev);
|
|
||||||
if (bdev_write_cache(bdev))
|
if (bdev_write_cache(bdev))
|
||||||
vbd->flush_support = true;
|
vbd->flush_support = true;
|
||||||
|
if (bdev_max_secure_erase_sectors(bdev))
|
||||||
if (q && blk_queue_secure_erase(q))
|
|
||||||
vbd->discard_secure = true;
|
vbd->discard_secure = true;
|
||||||
|
|
||||||
vbd->feature_gnt_persistent = feature_persistent;
|
vbd->feature_gnt_persistent = feature_persistent;
|
||||||
|
@ -949,7 +949,8 @@ static void blkif_set_queue_limits(struct blkfront_info *info)
|
|||||||
info->physical_sector_size;
|
info->physical_sector_size;
|
||||||
rq->limits.discard_alignment = info->discard_alignment;
|
rq->limits.discard_alignment = info->discard_alignment;
|
||||||
if (info->feature_secdiscard)
|
if (info->feature_secdiscard)
|
||||||
blk_queue_flag_set(QUEUE_FLAG_SECERASE, rq);
|
blk_queue_max_secure_erase_sectors(rq,
|
||||||
|
get_capacity(gd));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Hard sector size and max sectors impersonate the equiv. hardware. */
|
/* Hard sector size and max sectors impersonate the equiv. hardware. */
|
||||||
@ -1606,7 +1607,7 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
|
|||||||
info->feature_discard = 0;
|
info->feature_discard = 0;
|
||||||
info->feature_secdiscard = 0;
|
info->feature_secdiscard = 0;
|
||||||
blk_queue_max_discard_sectors(rq, 0);
|
blk_queue_max_discard_sectors(rq, 0);
|
||||||
blk_queue_flag_clear(QUEUE_FLAG_SECERASE, rq);
|
blk_queue_max_secure_erase_sectors(rq, 0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case BLKIF_OP_FLUSH_DISKCACHE:
|
case BLKIF_OP_FLUSH_DISKCACHE:
|
||||||
|
@ -336,7 +336,7 @@ static int bch_allocator_thread(void *arg)
|
|||||||
mutex_unlock(&ca->set->bucket_lock);
|
mutex_unlock(&ca->set->bucket_lock);
|
||||||
blkdev_issue_discard(ca->bdev,
|
blkdev_issue_discard(ca->bdev,
|
||||||
bucket_to_sector(ca->set, bucket),
|
bucket_to_sector(ca->set, bucket),
|
||||||
ca->sb.bucket_size, GFP_KERNEL, 0);
|
ca->sb.bucket_size, GFP_KERNEL);
|
||||||
mutex_lock(&ca->set->bucket_lock);
|
mutex_lock(&ca->set->bucket_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1920,9 +1920,7 @@ static int device_not_secure_erase_capable(struct dm_target *ti,
|
|||||||
struct dm_dev *dev, sector_t start,
|
struct dm_dev *dev, sector_t start,
|
||||||
sector_t len, void *data)
|
sector_t len, void *data)
|
||||||
{
|
{
|
||||||
struct request_queue *q = bdev_get_queue(dev->bdev);
|
return !bdev_max_secure_erase_sectors(dev->bdev);
|
||||||
|
|
||||||
return !blk_queue_secure_erase(q);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool dm_table_supports_secure_erase(struct dm_table *t)
|
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,
|
|||||||
q->limits.discard_misaligned = 0;
|
q->limits.discard_misaligned = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dm_table_supports_secure_erase(t))
|
if (!dm_table_supports_secure_erase(t))
|
||||||
blk_queue_flag_set(QUEUE_FLAG_SECERASE, q);
|
q->limits.max_secure_erase_sectors = 0;
|
||||||
|
|
||||||
if (dm_table_supports_flush(t, (1UL << QUEUE_FLAG_WC))) {
|
if (dm_table_supports_flush(t, (1UL << QUEUE_FLAG_WC))) {
|
||||||
wc = true;
|
wc = true;
|
||||||
|
@ -398,8 +398,8 @@ static int issue_discard(struct discard_op *op, dm_block_t data_b, dm_block_t da
|
|||||||
sector_t s = block_to_sectors(tc->pool, data_b);
|
sector_t s = block_to_sectors(tc->pool, data_b);
|
||||||
sector_t len = block_to_sectors(tc->pool, data_e - data_b);
|
sector_t len = block_to_sectors(tc->pool, data_e - data_b);
|
||||||
|
|
||||||
return __blkdev_issue_discard(tc->pool_dev->bdev, s, len,
|
return __blkdev_issue_discard(tc->pool_dev->bdev, s, len, GFP_NOWAIT,
|
||||||
GFP_NOWAIT, 0, &op->bio);
|
&op->bio);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void end_discard(struct discard_op *op, int r)
|
static void end_discard(struct discard_op *op, int r)
|
||||||
|
@ -8584,7 +8584,7 @@ void md_submit_discard_bio(struct mddev *mddev, struct md_rdev *rdev,
|
|||||||
{
|
{
|
||||||
struct bio *discard_bio = NULL;
|
struct bio *discard_bio = NULL;
|
||||||
|
|
||||||
if (__blkdev_issue_discard(rdev->bdev, start, size, GFP_NOIO, 0,
|
if (__blkdev_issue_discard(rdev->bdev, start, size, GFP_NOIO,
|
||||||
&discard_bio) || !discard_bio)
|
&discard_bio) || !discard_bio)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -1344,14 +1344,14 @@ static void r5l_write_super_and_discard_space(struct r5l_log *log,
|
|||||||
if (log->last_checkpoint < end) {
|
if (log->last_checkpoint < end) {
|
||||||
blkdev_issue_discard(bdev,
|
blkdev_issue_discard(bdev,
|
||||||
log->last_checkpoint + log->rdev->data_offset,
|
log->last_checkpoint + log->rdev->data_offset,
|
||||||
end - log->last_checkpoint, GFP_NOIO, 0);
|
end - log->last_checkpoint, GFP_NOIO);
|
||||||
} else {
|
} else {
|
||||||
blkdev_issue_discard(bdev,
|
blkdev_issue_discard(bdev,
|
||||||
log->last_checkpoint + log->rdev->data_offset,
|
log->last_checkpoint + log->rdev->data_offset,
|
||||||
log->device_size - log->last_checkpoint,
|
log->device_size - log->last_checkpoint,
|
||||||
GFP_NOIO, 0);
|
GFP_NOIO);
|
||||||
blkdev_issue_discard(bdev, log->rdev->data_offset, end,
|
blkdev_issue_discard(bdev, log->rdev->data_offset, end,
|
||||||
GFP_NOIO, 0);
|
GFP_NOIO);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,7 +189,7 @@ static void mmc_queue_setup_discard(struct request_queue *q,
|
|||||||
if (card->pref_erase > max_discard)
|
if (card->pref_erase > max_discard)
|
||||||
q->limits.discard_granularity = SECTOR_SIZE;
|
q->limits.discard_granularity = SECTOR_SIZE;
|
||||||
if (mmc_can_secure_erase_trim(card))
|
if (mmc_can_secure_erase_trim(card))
|
||||||
blk_queue_flag_set(QUEUE_FLAG_SECERASE, q);
|
blk_queue_max_secure_erase_sectors(q, max_discard);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned short mmc_get_max_segments(struct mmc_host *host)
|
static unsigned short mmc_get_max_segments(struct mmc_host *host)
|
||||||
|
@ -360,7 +360,7 @@ static u16 nvmet_bdev_discard_range(struct nvmet_req *req,
|
|||||||
ret = __blkdev_issue_discard(ns->bdev,
|
ret = __blkdev_issue_discard(ns->bdev,
|
||||||
nvmet_lba_to_sect(ns, range->slba),
|
nvmet_lba_to_sect(ns, range->slba),
|
||||||
le32_to_cpu(range->nlb) << (ns->blksize_shift - 9),
|
le32_to_cpu(range->nlb) << (ns->blksize_shift - 9),
|
||||||
GFP_KERNEL, 0, bio);
|
GFP_KERNEL, bio);
|
||||||
if (ret && ret != -EOPNOTSUPP) {
|
if (ret && ret != -EOPNOTSUPP) {
|
||||||
req->error_slba = le64_to_cpu(range->slba);
|
req->error_slba = le64_to_cpu(range->slba);
|
||||||
return errno_to_nvme_status(req, ret);
|
return errno_to_nvme_status(req, ret);
|
||||||
|
@ -558,7 +558,7 @@ fd_execute_unmap(struct se_cmd *cmd, sector_t lba, sector_t nolb)
|
|||||||
ret = blkdev_issue_discard(bdev,
|
ret = blkdev_issue_discard(bdev,
|
||||||
target_to_linux_sector(dev, lba),
|
target_to_linux_sector(dev, lba),
|
||||||
target_to_linux_sector(dev, nolb),
|
target_to_linux_sector(dev, nolb),
|
||||||
GFP_KERNEL, 0);
|
GFP_KERNEL);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
pr_warn("FILEIO: blkdev_issue_discard() failed: %d\n",
|
pr_warn("FILEIO: blkdev_issue_discard() failed: %d\n",
|
||||||
ret);
|
ret);
|
||||||
|
@ -434,7 +434,7 @@ iblock_execute_unmap(struct se_cmd *cmd, sector_t lba, sector_t nolb)
|
|||||||
ret = blkdev_issue_discard(bdev,
|
ret = blkdev_issue_discard(bdev,
|
||||||
target_to_linux_sector(dev, lba),
|
target_to_linux_sector(dev, lba),
|
||||||
target_to_linux_sector(dev, nolb),
|
target_to_linux_sector(dev, nolb),
|
||||||
GFP_KERNEL, 0);
|
GFP_KERNEL);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
pr_err("blkdev_issue_discard() failed: %d\n", ret);
|
pr_err("blkdev_issue_discard() failed: %d\n", ret);
|
||||||
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
||||||
|
@ -1239,7 +1239,7 @@ static int btrfs_issue_discard(struct block_device *bdev, u64 start, u64 len,
|
|||||||
|
|
||||||
if (size) {
|
if (size) {
|
||||||
ret = blkdev_issue_discard(bdev, start >> 9, size >> 9,
|
ret = blkdev_issue_discard(bdev, start >> 9, size >> 9,
|
||||||
GFP_NOFS, 0);
|
GFP_NOFS);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
*discarded_bytes += size;
|
*discarded_bytes += size;
|
||||||
else if (ret != -EOPNOTSUPP)
|
else if (ret != -EOPNOTSUPP)
|
||||||
@ -1256,7 +1256,7 @@ static int btrfs_issue_discard(struct block_device *bdev, u64 start, u64 len,
|
|||||||
|
|
||||||
if (bytes_left) {
|
if (bytes_left) {
|
||||||
ret = blkdev_issue_discard(bdev, start >> 9, bytes_left >> 9,
|
ret = blkdev_issue_discard(bdev, start >> 9, bytes_left >> 9,
|
||||||
GFP_NOFS, 0);
|
GFP_NOFS);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
*discarded_bytes += bytes_left;
|
*discarded_bytes += bytes_left;
|
||||||
}
|
}
|
||||||
|
@ -3629,7 +3629,7 @@ static inline int ext4_issue_discard(struct super_block *sb,
|
|||||||
return __blkdev_issue_discard(sb->s_bdev,
|
return __blkdev_issue_discard(sb->s_bdev,
|
||||||
(sector_t)discard_block << (sb->s_blocksize_bits - 9),
|
(sector_t)discard_block << (sb->s_blocksize_bits - 9),
|
||||||
(sector_t)count << (sb->s_blocksize_bits - 9),
|
(sector_t)count << (sb->s_blocksize_bits - 9),
|
||||||
GFP_NOFS, 0, biop);
|
GFP_NOFS, biop);
|
||||||
} else
|
} else
|
||||||
return sb_issue_discard(sb, discard_block, count, GFP_NOFS, 0);
|
return sb_issue_discard(sb, discard_block, count, GFP_NOFS, 0);
|
||||||
}
|
}
|
||||||
|
@ -3685,18 +3685,18 @@ out:
|
|||||||
static int f2fs_secure_erase(struct block_device *bdev, struct inode *inode,
|
static int f2fs_secure_erase(struct block_device *bdev, struct inode *inode,
|
||||||
pgoff_t off, block_t block, block_t len, u32 flags)
|
pgoff_t off, block_t block, block_t len, u32 flags)
|
||||||
{
|
{
|
||||||
struct request_queue *q = bdev_get_queue(bdev);
|
|
||||||
sector_t sector = SECTOR_FROM_BLOCK(block);
|
sector_t sector = SECTOR_FROM_BLOCK(block);
|
||||||
sector_t nr_sects = SECTOR_FROM_BLOCK(len);
|
sector_t nr_sects = SECTOR_FROM_BLOCK(len);
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (!q)
|
if (flags & F2FS_TRIM_FILE_DISCARD) {
|
||||||
return -ENXIO;
|
if (bdev_max_secure_erase_sectors(bdev))
|
||||||
|
ret = blkdev_issue_secure_erase(bdev, sector, nr_sects,
|
||||||
if (flags & F2FS_TRIM_FILE_DISCARD)
|
GFP_NOFS);
|
||||||
ret = blkdev_issue_discard(bdev, sector, nr_sects, GFP_NOFS,
|
else
|
||||||
blk_queue_secure_erase(q) ?
|
ret = blkdev_issue_discard(bdev, sector, nr_sects,
|
||||||
BLKDEV_DISCARD_SECURE : 0);
|
GFP_NOFS);
|
||||||
|
}
|
||||||
|
|
||||||
if (!ret && (flags & F2FS_TRIM_FILE_ZEROOUT)) {
|
if (!ret && (flags & F2FS_TRIM_FILE_ZEROOUT)) {
|
||||||
if (IS_ENCRYPTED(inode))
|
if (IS_ENCRYPTED(inode))
|
||||||
|
@ -1244,7 +1244,7 @@ static int __submit_discard_cmd(struct f2fs_sb_info *sbi,
|
|||||||
err = __blkdev_issue_discard(bdev,
|
err = __blkdev_issue_discard(bdev,
|
||||||
SECTOR_FROM_BLOCK(start),
|
SECTOR_FROM_BLOCK(start),
|
||||||
SECTOR_FROM_BLOCK(len),
|
SECTOR_FROM_BLOCK(len),
|
||||||
GFP_NOFS, 0, &bio);
|
GFP_NOFS, &bio);
|
||||||
submit:
|
submit:
|
||||||
if (err) {
|
if (err) {
|
||||||
spin_lock_irqsave(&dc->lock, flags);
|
spin_lock_irqsave(&dc->lock, flags);
|
||||||
|
@ -1825,7 +1825,7 @@ static int __jbd2_journal_erase(journal_t *journal, unsigned int flags)
|
|||||||
err = blkdev_issue_discard(journal->j_dev,
|
err = blkdev_issue_discard(journal->j_dev,
|
||||||
byte_start >> SECTOR_SHIFT,
|
byte_start >> SECTOR_SHIFT,
|
||||||
byte_count >> SECTOR_SHIFT,
|
byte_count >> SECTOR_SHIFT,
|
||||||
GFP_NOFS, 0);
|
GFP_NOFS);
|
||||||
} else if (flags & JBD2_JOURNAL_FLUSH_ZEROOUT) {
|
} else if (flags & JBD2_JOURNAL_FLUSH_ZEROOUT) {
|
||||||
err = blkdev_issue_zeroout(journal->j_dev,
|
err = blkdev_issue_zeroout(journal->j_dev,
|
||||||
byte_start >> SECTOR_SHIFT,
|
byte_start >> SECTOR_SHIFT,
|
||||||
|
@ -1100,7 +1100,7 @@ int nilfs_sufile_trim_fs(struct inode *sufile, struct fstrim_range *range)
|
|||||||
ret = blkdev_issue_discard(nilfs->ns_bdev,
|
ret = blkdev_issue_discard(nilfs->ns_bdev,
|
||||||
start * sects_per_block,
|
start * sects_per_block,
|
||||||
nblocks * sects_per_block,
|
nblocks * sects_per_block,
|
||||||
GFP_NOFS, 0);
|
GFP_NOFS);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
put_bh(su_bh);
|
put_bh(su_bh);
|
||||||
goto out_sem;
|
goto out_sem;
|
||||||
@ -1134,7 +1134,7 @@ int nilfs_sufile_trim_fs(struct inode *sufile, struct fstrim_range *range)
|
|||||||
ret = blkdev_issue_discard(nilfs->ns_bdev,
|
ret = blkdev_issue_discard(nilfs->ns_bdev,
|
||||||
start * sects_per_block,
|
start * sects_per_block,
|
||||||
nblocks * sects_per_block,
|
nblocks * sects_per_block,
|
||||||
GFP_NOFS, 0);
|
GFP_NOFS);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
ndiscarded += nblocks;
|
ndiscarded += nblocks;
|
||||||
}
|
}
|
||||||
|
@ -672,7 +672,7 @@ int nilfs_discard_segments(struct the_nilfs *nilfs, __u64 *segnump,
|
|||||||
ret = blkdev_issue_discard(nilfs->ns_bdev,
|
ret = blkdev_issue_discard(nilfs->ns_bdev,
|
||||||
start * sects_per_block,
|
start * sects_per_block,
|
||||||
nblocks * sects_per_block,
|
nblocks * sects_per_block,
|
||||||
GFP_NOFS, 0);
|
GFP_NOFS);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
nblocks = 0;
|
nblocks = 0;
|
||||||
@ -682,7 +682,7 @@ int nilfs_discard_segments(struct the_nilfs *nilfs, __u64 *segnump,
|
|||||||
ret = blkdev_issue_discard(nilfs->ns_bdev,
|
ret = blkdev_issue_discard(nilfs->ns_bdev,
|
||||||
start * sects_per_block,
|
start * sects_per_block,
|
||||||
nblocks * sects_per_block,
|
nblocks * sects_per_block,
|
||||||
GFP_NOFS, 0);
|
GFP_NOFS);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1333,7 +1333,7 @@ int ntfs_discard(struct ntfs_sb_info *sbi, CLST lcn, CLST len)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err = blkdev_issue_discard(sb->s_bdev, start >> 9, (end - start) >> 9,
|
err = blkdev_issue_discard(sb->s_bdev, start >> 9, (end - start) >> 9,
|
||||||
GFP_NOFS, 0);
|
GFP_NOFS);
|
||||||
|
|
||||||
if (err == -EOPNOTSUPP)
|
if (err == -EOPNOTSUPP)
|
||||||
sbi->flags |= NTFS_FLAGS_NODISCARD;
|
sbi->flags |= NTFS_FLAGS_NODISCARD;
|
||||||
|
@ -114,7 +114,7 @@ xfs_trim_extents(
|
|||||||
}
|
}
|
||||||
|
|
||||||
trace_xfs_discard_extent(mp, agno, fbno, flen);
|
trace_xfs_discard_extent(mp, agno, fbno, flen);
|
||||||
error = blkdev_issue_discard(bdev, dbno, dlen, GFP_NOFS, 0);
|
error = blkdev_issue_discard(bdev, dbno, dlen, GFP_NOFS);
|
||||||
if (error)
|
if (error)
|
||||||
goto out_del_cursor;
|
goto out_del_cursor;
|
||||||
*blocks_trimmed += flen;
|
*blocks_trimmed += flen;
|
||||||
|
@ -605,7 +605,7 @@ xlog_discard_busy_extents(
|
|||||||
error = __blkdev_issue_discard(mp->m_ddev_targp->bt_bdev,
|
error = __blkdev_issue_discard(mp->m_ddev_targp->bt_bdev,
|
||||||
XFS_AGB_TO_DADDR(mp, busyp->agno, busyp->bno),
|
XFS_AGB_TO_DADDR(mp, busyp->agno, busyp->bno),
|
||||||
XFS_FSB_TO_BB(mp, busyp->length),
|
XFS_FSB_TO_BB(mp, busyp->length),
|
||||||
GFP_NOFS, 0, &bio);
|
GFP_NOFS, &bio);
|
||||||
if (error && error != -EOPNOTSUPP) {
|
if (error && error != -EOPNOTSUPP) {
|
||||||
xfs_info(mp,
|
xfs_info(mp,
|
||||||
"discard failed for extent [0x%llx,%u], error %d",
|
"discard failed for extent [0x%llx,%u], error %d",
|
||||||
|
@ -248,6 +248,7 @@ struct queue_limits {
|
|||||||
unsigned int io_opt;
|
unsigned int io_opt;
|
||||||
unsigned int max_discard_sectors;
|
unsigned int max_discard_sectors;
|
||||||
unsigned int max_hw_discard_sectors;
|
unsigned int max_hw_discard_sectors;
|
||||||
|
unsigned int max_secure_erase_sectors;
|
||||||
unsigned int max_write_zeroes_sectors;
|
unsigned int max_write_zeroes_sectors;
|
||||||
unsigned int max_zone_append_sectors;
|
unsigned int max_zone_append_sectors;
|
||||||
unsigned int discard_granularity;
|
unsigned int discard_granularity;
|
||||||
@ -542,7 +543,6 @@ struct request_queue {
|
|||||||
#define QUEUE_FLAG_IO_STAT 7 /* do disk/partitions IO accounting */
|
#define QUEUE_FLAG_IO_STAT 7 /* do disk/partitions IO accounting */
|
||||||
#define QUEUE_FLAG_NOXMERGES 9 /* No extended merges */
|
#define QUEUE_FLAG_NOXMERGES 9 /* No extended merges */
|
||||||
#define QUEUE_FLAG_ADD_RANDOM 10 /* Contributes to random pool */
|
#define QUEUE_FLAG_ADD_RANDOM 10 /* Contributes to random pool */
|
||||||
#define QUEUE_FLAG_SECERASE 11 /* supports secure erase */
|
|
||||||
#define QUEUE_FLAG_SAME_FORCE 12 /* force complete on same CPU */
|
#define QUEUE_FLAG_SAME_FORCE 12 /* force complete on same CPU */
|
||||||
#define QUEUE_FLAG_DEAD 13 /* queue tear-down finished */
|
#define QUEUE_FLAG_DEAD 13 /* queue tear-down finished */
|
||||||
#define QUEUE_FLAG_INIT_DONE 14 /* queue is initialized */
|
#define QUEUE_FLAG_INIT_DONE 14 /* queue is initialized */
|
||||||
@ -583,8 +583,6 @@ bool blk_queue_flag_test_and_set(unsigned int flag, struct request_queue *q);
|
|||||||
#define blk_queue_add_random(q) test_bit(QUEUE_FLAG_ADD_RANDOM, &(q)->queue_flags)
|
#define blk_queue_add_random(q) test_bit(QUEUE_FLAG_ADD_RANDOM, &(q)->queue_flags)
|
||||||
#define blk_queue_zone_resetall(q) \
|
#define blk_queue_zone_resetall(q) \
|
||||||
test_bit(QUEUE_FLAG_ZONE_RESETALL, &(q)->queue_flags)
|
test_bit(QUEUE_FLAG_ZONE_RESETALL, &(q)->queue_flags)
|
||||||
#define blk_queue_secure_erase(q) \
|
|
||||||
(test_bit(QUEUE_FLAG_SECERASE, &(q)->queue_flags))
|
|
||||||
#define blk_queue_dax(q) test_bit(QUEUE_FLAG_DAX, &(q)->queue_flags)
|
#define blk_queue_dax(q) test_bit(QUEUE_FLAG_DAX, &(q)->queue_flags)
|
||||||
#define blk_queue_pci_p2pdma(q) \
|
#define blk_queue_pci_p2pdma(q) \
|
||||||
test_bit(QUEUE_FLAG_PCI_P2PDMA, &(q)->queue_flags)
|
test_bit(QUEUE_FLAG_PCI_P2PDMA, &(q)->queue_flags)
|
||||||
@ -947,6 +945,8 @@ extern void blk_queue_chunk_sectors(struct request_queue *, unsigned int);
|
|||||||
extern void blk_queue_max_segments(struct request_queue *, unsigned short);
|
extern void blk_queue_max_segments(struct request_queue *, unsigned short);
|
||||||
extern void blk_queue_max_discard_segments(struct request_queue *,
|
extern void blk_queue_max_discard_segments(struct request_queue *,
|
||||||
unsigned short);
|
unsigned short);
|
||||||
|
void blk_queue_max_secure_erase_sectors(struct request_queue *q,
|
||||||
|
unsigned int max_sectors);
|
||||||
extern void blk_queue_max_segment_size(struct request_queue *, unsigned int);
|
extern void blk_queue_max_segment_size(struct request_queue *, unsigned int);
|
||||||
extern void blk_queue_max_discard_sectors(struct request_queue *q,
|
extern void blk_queue_max_discard_sectors(struct request_queue *q,
|
||||||
unsigned int max_discard_sectors);
|
unsigned int max_discard_sectors);
|
||||||
@ -1087,13 +1087,12 @@ static inline long nr_blockdev_pages(void)
|
|||||||
|
|
||||||
extern void blk_io_schedule(void);
|
extern void blk_io_schedule(void);
|
||||||
|
|
||||||
#define BLKDEV_DISCARD_SECURE (1 << 0) /* issue a secure erase */
|
int blkdev_issue_discard(struct block_device *bdev, sector_t sector,
|
||||||
|
sector_t nr_sects, gfp_t gfp_mask);
|
||||||
extern int blkdev_issue_discard(struct block_device *bdev, sector_t sector,
|
int __blkdev_issue_discard(struct block_device *bdev, sector_t sector,
|
||||||
sector_t nr_sects, gfp_t gfp_mask, unsigned long flags);
|
sector_t nr_sects, gfp_t gfp_mask, struct bio **biop);
|
||||||
extern int __blkdev_issue_discard(struct block_device *bdev, sector_t sector,
|
int blkdev_issue_secure_erase(struct block_device *bdev, sector_t sector,
|
||||||
sector_t nr_sects, gfp_t gfp_mask, int flags,
|
sector_t nr_sects, gfp_t gfp);
|
||||||
struct bio **biop);
|
|
||||||
|
|
||||||
#define BLKDEV_ZERO_NOUNMAP (1 << 0) /* do not free blocks */
|
#define BLKDEV_ZERO_NOUNMAP (1 << 0) /* do not free blocks */
|
||||||
#define BLKDEV_ZERO_NOFALLBACK (1 << 1) /* don't write explicit zeroes */
|
#define BLKDEV_ZERO_NOFALLBACK (1 << 1) /* don't write explicit zeroes */
|
||||||
@ -1112,7 +1111,7 @@ static inline int sb_issue_discard(struct super_block *sb, sector_t block,
|
|||||||
SECTOR_SHIFT),
|
SECTOR_SHIFT),
|
||||||
nr_blocks << (sb->s_blocksize_bits -
|
nr_blocks << (sb->s_blocksize_bits -
|
||||||
SECTOR_SHIFT),
|
SECTOR_SHIFT),
|
||||||
gfp_mask, flags);
|
gfp_mask);
|
||||||
}
|
}
|
||||||
static inline int sb_issue_zeroout(struct super_block *sb, sector_t block,
|
static inline int sb_issue_zeroout(struct super_block *sb, sector_t block,
|
||||||
sector_t nr_blocks, gfp_t gfp_mask)
|
sector_t nr_blocks, gfp_t gfp_mask)
|
||||||
@ -1262,6 +1261,12 @@ static inline unsigned int bdev_discard_granularity(struct block_device *bdev)
|
|||||||
return bdev_get_queue(bdev)->limits.discard_granularity;
|
return bdev_get_queue(bdev)->limits.discard_granularity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline unsigned int
|
||||||
|
bdev_max_secure_erase_sectors(struct block_device *bdev)
|
||||||
|
{
|
||||||
|
return bdev_get_queue(bdev)->limits.max_secure_erase_sectors;
|
||||||
|
}
|
||||||
|
|
||||||
static inline unsigned int bdev_write_zeroes_sectors(struct block_device *bdev)
|
static inline unsigned int bdev_write_zeroes_sectors(struct block_device *bdev)
|
||||||
{
|
{
|
||||||
struct request_queue *q = bdev_get_queue(bdev);
|
struct request_queue *q = bdev_get_queue(bdev);
|
||||||
|
@ -179,7 +179,7 @@ static int discard_swap(struct swap_info_struct *si)
|
|||||||
nr_blocks = ((sector_t)se->nr_pages - 1) << (PAGE_SHIFT - 9);
|
nr_blocks = ((sector_t)se->nr_pages - 1) << (PAGE_SHIFT - 9);
|
||||||
if (nr_blocks) {
|
if (nr_blocks) {
|
||||||
err = blkdev_issue_discard(si->bdev, start_block,
|
err = blkdev_issue_discard(si->bdev, start_block,
|
||||||
nr_blocks, GFP_KERNEL, 0);
|
nr_blocks, GFP_KERNEL);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
cond_resched();
|
cond_resched();
|
||||||
@ -190,7 +190,7 @@ static int discard_swap(struct swap_info_struct *si)
|
|||||||
nr_blocks = (sector_t)se->nr_pages << (PAGE_SHIFT - 9);
|
nr_blocks = (sector_t)se->nr_pages << (PAGE_SHIFT - 9);
|
||||||
|
|
||||||
err = blkdev_issue_discard(si->bdev, start_block,
|
err = blkdev_issue_discard(si->bdev, start_block,
|
||||||
nr_blocks, GFP_KERNEL, 0);
|
nr_blocks, GFP_KERNEL);
|
||||||
if (err)
|
if (err)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -254,7 +254,7 @@ static void discard_swap_cluster(struct swap_info_struct *si,
|
|||||||
start_block <<= PAGE_SHIFT - 9;
|
start_block <<= PAGE_SHIFT - 9;
|
||||||
nr_blocks <<= PAGE_SHIFT - 9;
|
nr_blocks <<= PAGE_SHIFT - 9;
|
||||||
if (blkdev_issue_discard(si->bdev, start_block,
|
if (blkdev_issue_discard(si->bdev, start_block,
|
||||||
nr_blocks, GFP_NOIO, 0))
|
nr_blocks, GFP_NOIO))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
se = next_se(se);
|
se = next_se(se);
|
||||||
|
Loading…
Reference in New Issue
Block a user