]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - block/blk-lib.c
sbitmap: add sbitmap_get_shallow() operation
[mirror_ubuntu-bionic-kernel.git] / block / blk-lib.c
index f9f24ec69c272594b798ceab8ae9cb0b21010ef9..e8caecd71688e00a4974b5d45b95bc53e4eaeac5 100644 (file)
@@ -37,17 +37,12 @@ int __blkdev_issue_discard(struct block_device *bdev, sector_t sector,
                return -ENXIO;
 
        if (flags & BLKDEV_DISCARD_SECURE) {
-               if (flags & BLKDEV_DISCARD_ZERO)
-                       return -EOPNOTSUPP;
                if (!blk_queue_secure_erase(q))
                        return -EOPNOTSUPP;
                op = REQ_OP_SECURE_ERASE;
        } else {
                if (!blk_queue_discard(q))
                        return -EOPNOTSUPP;
-               if ((flags & BLKDEV_DISCARD_ZERO) &&
-                   !q->limits.discard_zeroes_data)
-                       return -EOPNOTSUPP;
                op = REQ_OP_DISCARD;
        }
 
@@ -126,7 +121,7 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector,
                        &bio);
        if (!ret && bio) {
                ret = submit_bio_wait(bio);
-               if (ret == -EOPNOTSUPP && !(flags & BLKDEV_DISCARD_ZERO))
+               if (ret == -EOPNOTSUPP)
                        ret = 0;
                bio_put(bio);
        }
@@ -226,20 +221,9 @@ int blkdev_issue_write_same(struct block_device *bdev, sector_t sector,
 }
 EXPORT_SYMBOL(blkdev_issue_write_same);
 
-/**
- * __blkdev_issue_write_zeroes - generate number of bios with WRITE ZEROES
- * @bdev:      blockdev to issue
- * @sector:    start sector
- * @nr_sects:  number of sectors to write
- * @gfp_mask:  memory allocation flags (for bio_alloc)
- * @biop:      pointer to anchor bio
- *
- * Description:
- *  Generate and issue number of bios(REQ_OP_WRITE_ZEROES) with zerofiled pages.
- */
 static int __blkdev_issue_write_zeroes(struct block_device *bdev,
                sector_t sector, sector_t nr_sects, gfp_t gfp_mask,
-               struct bio **biop)
+               struct bio **biop, unsigned flags)
 {
        struct bio *bio = *biop;
        unsigned int max_write_zeroes_sectors;
@@ -258,7 +242,9 @@ static int __blkdev_issue_write_zeroes(struct block_device *bdev,
                bio = next_bio(bio, 0, gfp_mask);
                bio->bi_iter.bi_sector = sector;
                bio->bi_bdev = bdev;
-               bio_set_op_attrs(bio, REQ_OP_WRITE_ZEROES, 0);
+               bio->bi_opf = REQ_OP_WRITE_ZEROES;
+               if (flags & BLKDEV_ZERO_NOUNMAP)
+                       bio->bi_opf |= REQ_NOUNMAP;
 
                if (nr_sects > max_write_zeroes_sectors) {
                        bio->bi_iter.bi_size = max_write_zeroes_sectors << 9;
@@ -288,8 +274,17 @@ static int __blkdev_issue_write_zeroes(struct block_device *bdev,
  *  Zero-fill a block range, either using hardware offload or by explicitly
  *  writing zeroes to the device.
  *
+ *  Note that this function may fail with -EOPNOTSUPP if the driver signals
+ *  zeroing offload support, but the device fails to process the command (for
+ *  some devices there is no non-destructive way to verify whether this
+ *  operation is actually supported).  In this case the caller should call
+ *  retry the call to blkdev_issue_zeroout() and the fallback path will be used.
+ *
  *  If a device is using logical block provisioning, the underlying space will
  *  not be released if %flags contains BLKDEV_ZERO_NOUNMAP.
+ *
+ *  If %flags contains BLKDEV_ZERO_NOFALLBACK, the function will return
+ *  -EOPNOTSUPP if no explicit hardware offload for zeroing is provided.
  */
 int __blkdev_issue_zeroout(struct block_device *bdev, sector_t sector,
                sector_t nr_sects, gfp_t gfp_mask, struct bio **biop,
@@ -306,8 +301,8 @@ int __blkdev_issue_zeroout(struct block_device *bdev, sector_t sector,
                return -EINVAL;
 
        ret = __blkdev_issue_write_zeroes(bdev, sector, nr_sects, gfp_mask,
-                       biop);
-       if (ret == 0 || (ret && ret != -EOPNOTSUPP))
+                       biop, flags);
+       if (ret != -EOPNOTSUPP || (flags & BLKDEV_ZERO_NOFALLBACK))
                goto out;
 
        ret = 0;
@@ -355,12 +350,6 @@ int blkdev_issue_zeroout(struct block_device *bdev, sector_t sector,
        struct bio *bio = NULL;
        struct blk_plug plug;
 
-       if (!(flags & BLKDEV_ZERO_NOUNMAP)) {
-               if (!blkdev_issue_discard(bdev, sector, nr_sects, gfp_mask,
-                               BLKDEV_DISCARD_ZERO))
-                       return 0;
-       }
-
        blk_start_plug(&plug);
        ret = __blkdev_issue_zeroout(bdev, sector, nr_sects, gfp_mask,
                        &bio, flags);