linux/block/blk-lib.c
<<
>>
Prefs
   1/*
   2 * Functions related to generic helpers functions
   3 */
   4#include <linux/kernel.h>
   5#include <linux/module.h>
   6#include <linux/bio.h>
   7#include <linux/blkdev.h>
   8#include <linux/scatterlist.h>
   9
  10#include "blk.h"
  11
  12static struct bio *next_bio(struct bio *bio, unsigned int nr_pages,
  13                gfp_t gfp)
  14{
  15        struct bio *new = bio_alloc(gfp, nr_pages);
  16
  17        if (bio) {
  18                bio_chain(bio, new);
  19                submit_bio(bio);
  20        }
  21
  22        return new;
  23}
  24
  25int __blkdev_issue_discard(struct block_device *bdev, sector_t sector,
  26                sector_t nr_sects, gfp_t gfp_mask, int flags,
  27                struct bio **biop)
  28{
  29        struct request_queue *q = bdev_get_queue(bdev);
  30        struct bio *bio = *biop;
  31        unsigned int granularity;
  32        enum req_op op;
  33        int alignment;
  34        sector_t bs_mask;
  35
  36        if (!q)
  37                return -ENXIO;
  38
  39        if (flags & BLKDEV_DISCARD_SECURE) {
  40                if (flags & BLKDEV_DISCARD_ZERO)
  41                        return -EOPNOTSUPP;
  42                if (!blk_queue_secure_erase(q))
  43                        return -EOPNOTSUPP;
  44                op = REQ_OP_SECURE_ERASE;
  45        } else {
  46                if (!blk_queue_discard(q))
  47                        return -EOPNOTSUPP;
  48                if ((flags & BLKDEV_DISCARD_ZERO) &&
  49                    !q->limits.discard_zeroes_data)
  50                        return -EOPNOTSUPP;
  51                op = REQ_OP_DISCARD;
  52        }
  53
  54        bs_mask = (bdev_logical_block_size(bdev) >> 9) - 1;
  55        if ((sector | nr_sects) & bs_mask)
  56                return -EINVAL;
  57
  58        /* Zero-sector (unknown) and one-sector granularities are the same.  */
  59        granularity = max(q->limits.discard_granularity >> 9, 1U);
  60        alignment = (bdev_discard_alignment(bdev) >> 9) % granularity;
  61
  62        while (nr_sects) {
  63                unsigned int req_sects;
  64                sector_t end_sect, tmp;
  65
  66                /* Make sure bi_size doesn't overflow */
  67                req_sects = min_t(sector_t, nr_sects, UINT_MAX >> 9);
  68
  69                /**
  70                 * If splitting a request, and the next starting sector would be
  71                 * misaligned, stop the discard at the previous aligned sector.
  72                 */
  73                end_sect = sector + req_sects;
  74                tmp = end_sect;
  75                if (req_sects < nr_sects &&
  76                    sector_div(tmp, granularity) != alignment) {
  77                        end_sect = end_sect - alignment;
  78                        sector_div(end_sect, granularity);
  79                        end_sect = end_sect * granularity + alignment;
  80                        req_sects = end_sect - sector;
  81                }
  82
  83                bio = next_bio(bio, 1, gfp_mask);
  84                bio->bi_iter.bi_sector = sector;
  85                bio->bi_bdev = bdev;
  86                bio_set_op_attrs(bio, op, 0);
  87
  88                bio->bi_iter.bi_size = req_sects << 9;
  89                nr_sects -= req_sects;
  90                sector = end_sect;
  91
  92                /*
  93                 * We can loop for a long time in here, if someone does
  94                 * full device discards (like mkfs). Be nice and allow
  95                 * us to schedule out to avoid softlocking if preempt
  96                 * is disabled.
  97                 */
  98                cond_resched();
  99        }
 100
 101        *biop = bio;
 102        return 0;
 103}
 104EXPORT_SYMBOL(__blkdev_issue_discard);
 105
 106/**
 107 * blkdev_issue_discard - queue a discard
 108 * @bdev:       blockdev to issue discard for
 109 * @sector:     start sector
 110 * @nr_sects:   number of sectors to discard
 111 * @gfp_mask:   memory allocation flags (for bio_alloc)
 112 * @flags:      BLKDEV_IFL_* flags to control behaviour
 113 *
 114 * Description:
 115 *    Issue a discard request for the sectors in question.
 116 */
 117int blkdev_issue_discard(struct block_device *bdev, sector_t sector,
 118                sector_t nr_sects, gfp_t gfp_mask, unsigned long flags)
 119{
 120        struct bio *bio = NULL;
 121        struct blk_plug plug;
 122        int ret;
 123
 124        blk_start_plug(&plug);
 125        ret = __blkdev_issue_discard(bdev, sector, nr_sects, gfp_mask, flags,
 126                        &bio);
 127        if (!ret && bio) {
 128                ret = submit_bio_wait(bio);
 129                if (ret == -EOPNOTSUPP && !(flags & BLKDEV_DISCARD_ZERO))
 130                        ret = 0;
 131                bio_put(bio);
 132        }
 133        blk_finish_plug(&plug);
 134
 135        return ret;
 136}
 137EXPORT_SYMBOL(blkdev_issue_discard);
 138
 139/**
 140 * blkdev_issue_write_same - queue a write same operation
 141 * @bdev:       target blockdev
 142 * @sector:     start sector
 143 * @nr_sects:   number of sectors to write
 144 * @gfp_mask:   memory allocation flags (for bio_alloc)
 145 * @page:       page containing data to write
 146 *
 147 * Description:
 148 *    Issue a write same request for the sectors in question.
 149 */
 150int blkdev_issue_write_same(struct block_device *bdev, sector_t sector,
 151                            sector_t nr_sects, gfp_t gfp_mask,
 152                            struct page *page)
 153{
 154        struct request_queue *q = bdev_get_queue(bdev);
 155        unsigned int max_write_same_sectors;
 156        struct bio *bio = NULL;
 157        int ret = 0;
 158        sector_t bs_mask;
 159
 160        if (!q)
 161                return -ENXIO;
 162
 163        bs_mask = (bdev_logical_block_size(bdev) >> 9) - 1;
 164        if ((sector | nr_sects) & bs_mask)
 165                return -EINVAL;
 166
 167        /* Ensure that max_write_same_sectors doesn't overflow bi_size */
 168        max_write_same_sectors = UINT_MAX >> 9;
 169
 170        while (nr_sects) {
 171                bio = next_bio(bio, 1, gfp_mask);
 172                bio->bi_iter.bi_sector = sector;
 173                bio->bi_bdev = bdev;
 174                bio->bi_vcnt = 1;
 175                bio->bi_io_vec->bv_page = page;
 176                bio->bi_io_vec->bv_offset = 0;
 177                bio->bi_io_vec->bv_len = bdev_logical_block_size(bdev);
 178                bio_set_op_attrs(bio, REQ_OP_WRITE_SAME, 0);
 179
 180                if (nr_sects > max_write_same_sectors) {
 181                        bio->bi_iter.bi_size = max_write_same_sectors << 9;
 182                        nr_sects -= max_write_same_sectors;
 183                        sector += max_write_same_sectors;
 184                } else {
 185                        bio->bi_iter.bi_size = nr_sects << 9;
 186                        nr_sects = 0;
 187                }
 188        }
 189
 190        if (bio) {
 191                ret = submit_bio_wait(bio);
 192                bio_put(bio);
 193        }
 194        return ret;
 195}
 196EXPORT_SYMBOL(blkdev_issue_write_same);
 197
 198/**
 199 * blkdev_issue_zeroout - generate number of zero filed write bios
 200 * @bdev:       blockdev to issue
 201 * @sector:     start sector
 202 * @nr_sects:   number of sectors to write
 203 * @gfp_mask:   memory allocation flags (for bio_alloc)
 204 *
 205 * Description:
 206 *  Generate and issue number of bios with zerofiled pages.
 207 */
 208
 209static int __blkdev_issue_zeroout(struct block_device *bdev, sector_t sector,
 210                                  sector_t nr_sects, gfp_t gfp_mask)
 211{
 212        int ret;
 213        struct bio *bio = NULL;
 214        unsigned int sz;
 215        sector_t bs_mask;
 216
 217        bs_mask = (bdev_logical_block_size(bdev) >> 9) - 1;
 218        if ((sector | nr_sects) & bs_mask)
 219                return -EINVAL;
 220
 221        while (nr_sects != 0) {
 222                bio = next_bio(bio, min(nr_sects, (sector_t)BIO_MAX_PAGES),
 223                                gfp_mask);
 224                bio->bi_iter.bi_sector = sector;
 225                bio->bi_bdev   = bdev;
 226                bio_set_op_attrs(bio, REQ_OP_WRITE, 0);
 227
 228                while (nr_sects != 0) {
 229                        sz = min((sector_t) PAGE_SIZE >> 9 , nr_sects);
 230                        ret = bio_add_page(bio, ZERO_PAGE(0), sz << 9, 0);
 231                        nr_sects -= ret >> 9;
 232                        sector += ret >> 9;
 233                        if (ret < (sz << 9))
 234                                break;
 235                }
 236        }
 237
 238        if (bio) {
 239                ret = submit_bio_wait(bio);
 240                bio_put(bio);
 241                return ret;
 242        }
 243        return 0;
 244}
 245
 246/**
 247 * blkdev_issue_zeroout - zero-fill a block range
 248 * @bdev:       blockdev to write
 249 * @sector:     start sector
 250 * @nr_sects:   number of sectors to write
 251 * @gfp_mask:   memory allocation flags (for bio_alloc)
 252 * @discard:    whether to discard the block range
 253 *
 254 * Description:
 255 *  Zero-fill a block range.  If the discard flag is set and the block
 256 *  device guarantees that subsequent READ operations to the block range
 257 *  in question will return zeroes, the blocks will be discarded. Should
 258 *  the discard request fail, if the discard flag is not set, or if
 259 *  discard_zeroes_data is not supported, this function will resort to
 260 *  zeroing the blocks manually, thus provisioning (allocating,
 261 *  anchoring) them. If the block device supports the WRITE SAME command
 262 *  blkdev_issue_zeroout() will use it to optimize the process of
 263 *  clearing the block range. Otherwise the zeroing will be performed
 264 *  using regular WRITE calls.
 265 */
 266
 267int blkdev_issue_zeroout(struct block_device *bdev, sector_t sector,
 268                         sector_t nr_sects, gfp_t gfp_mask, bool discard)
 269{
 270        if (discard) {
 271                if (!blkdev_issue_discard(bdev, sector, nr_sects, gfp_mask,
 272                                BLKDEV_DISCARD_ZERO))
 273                        return 0;
 274        }
 275
 276        if (bdev_write_same(bdev) &&
 277            blkdev_issue_write_same(bdev, sector, nr_sects, gfp_mask,
 278                                    ZERO_PAGE(0)) == 0)
 279                return 0;
 280
 281        return __blkdev_issue_zeroout(bdev, sector, nr_sects, gfp_mask);
 282}
 283EXPORT_SYMBOL(blkdev_issue_zeroout);
 284