block: Kill gfp_t argument of blkdev_report_zones()
authorDamien Le Moal <damien.lemoal@wdc.com>
Mon, 1 Jul 2019 05:09:16 +0000 (14:09 +0900)
committerJens Axboe <axboe@kernel.dk>
Fri, 12 Jul 2019 02:04:37 +0000 (20:04 -0600)
Only GFP_KERNEL and GFP_NOIO are used with blkdev_report_zones(). In
preparation of using vmalloc() for large report buffer and zone array
allocations used by this function, remove its "gfp_t gfp_mask" argument
and rely on the caller context to use memalloc_noio_save/restore() where
necessary (block layer zone revalidation and dm-zoned I/O error path).

Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
12 files changed:
block/blk-zoned.c
drivers/block/null_blk.h
drivers/block/null_blk_zoned.c
drivers/md/dm-flakey.c
drivers/md/dm-linear.c
drivers/md/dm-zoned-metadata.c
drivers/md/dm.c
drivers/scsi/sd.h
drivers/scsi/sd_zbc.c
fs/f2fs/super.c
include/linux/blkdev.h
include/linux/device-mapper.h

index 3249738242b4c2be4cf2b396f4666654d6776f94..58ced170b424f654f3c834872b118c402da9c716 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/rbtree.h>
 #include <linux/blkdev.h>
 #include <linux/blk-mq.h>
+#include <linux/sched/mm.h>
 
 #include "blk.h"
 
@@ -117,8 +118,7 @@ static bool blkdev_report_zone(struct block_device *bdev, struct blk_zone *rep)
 }
 
 static int blk_report_zones(struct gendisk *disk, sector_t sector,
-                           struct blk_zone *zones, unsigned int *nr_zones,
-                           gfp_t gfp_mask)
+                           struct blk_zone *zones, unsigned int *nr_zones)
 {
        struct request_queue *q = disk->queue;
        unsigned int z = 0, n, nrz = *nr_zones;
@@ -127,8 +127,7 @@ static int blk_report_zones(struct gendisk *disk, sector_t sector,
 
        while (z < nrz && sector < capacity) {
                n = nrz - z;
-               ret = disk->fops->report_zones(disk, sector, &zones[z], &n,
-                                              gfp_mask);
+               ret = disk->fops->report_zones(disk, sector, &zones[z], &n);
                if (ret)
                        return ret;
                if (!n)
@@ -149,17 +148,18 @@ static int blk_report_zones(struct gendisk *disk, sector_t sector,
  * @sector:    Sector from which to report zones
  * @zones:     Array of zone structures where to return the zones information
  * @nr_zones:  Number of zone structures in the zone array
- * @gfp_mask:  Memory allocation flags (for bio_alloc)
  *
  * Description:
  *    Get zone information starting from the zone containing @sector.
  *    The number of zone information reported may be less than the number
  *    requested by @nr_zones. The number of zones actually reported is
  *    returned in @nr_zones.
+ *    The caller must use memalloc_noXX_save/restore() calls to control
+ *    memory allocations done within this function (zone array and command
+ *    buffer allocation by the device driver).
  */
 int blkdev_report_zones(struct block_device *bdev, sector_t sector,
-                       struct blk_zone *zones, unsigned int *nr_zones,
-                       gfp_t gfp_mask)
+                       struct blk_zone *zones, unsigned int *nr_zones)
 {
        struct request_queue *q = bdev_get_queue(bdev);
        unsigned int i, nrz;
@@ -184,7 +184,7 @@ int blkdev_report_zones(struct block_device *bdev, sector_t sector,
        nrz = min(*nr_zones,
                  __blkdev_nr_zones(q, bdev->bd_part->nr_sects - sector));
        ret = blk_report_zones(bdev->bd_disk, get_start_sect(bdev) + sector,
-                              zones, &nrz, gfp_mask);
+                              zones, &nrz);
        if (ret)
                return ret;
 
@@ -305,9 +305,7 @@ int blkdev_report_zones_ioctl(struct block_device *bdev, fmode_t mode,
        if (!zones)
                return -ENOMEM;
 
-       ret = blkdev_report_zones(bdev, rep.sector,
-                                 zones, &rep.nr_zones,
-                                 GFP_KERNEL);
+       ret = blkdev_report_zones(bdev, rep.sector, zones, &rep.nr_zones);
        if (ret)
                goto out;
 
@@ -415,6 +413,7 @@ int blk_revalidate_disk_zones(struct gendisk *disk)
        unsigned long *seq_zones_wlock = NULL, *seq_zones_bitmap = NULL;
        unsigned int i, rep_nr_zones = 0, z = 0, nrz;
        struct blk_zone *zones = NULL;
+       unsigned int noio_flag;
        sector_t sector = 0;
        int ret = 0;
 
@@ -427,6 +426,12 @@ int blk_revalidate_disk_zones(struct gendisk *disk)
                return 0;
        }
 
+       /*
+        * Ensure that all memory allocations in this context are done as
+        * if GFP_NOIO was specified.
+        */
+       noio_flag = memalloc_noio_save();
+
        if (!blk_queue_is_zoned(q) || !nr_zones) {
                nr_zones = 0;
                goto update;
@@ -449,7 +454,7 @@ int blk_revalidate_disk_zones(struct gendisk *disk)
 
        while (z < nr_zones) {
                nrz = min(nr_zones - z, rep_nr_zones);
-               ret = blk_report_zones(disk, sector, zones, &nrz, GFP_NOIO);
+               ret = blk_report_zones(disk, sector, zones, &nrz);
                if (ret)
                        goto out;
                if (!nrz)
@@ -480,6 +485,8 @@ update:
        blk_mq_unfreeze_queue(q);
 
 out:
+       memalloc_noio_restore(noio_flag);
+
        free_pages((unsigned long)zones,
                   get_order(rep_nr_zones * sizeof(struct blk_zone)));
        kfree(seq_zones_wlock);
index 34b22d6523baf9bf4f1dc2af06b2cf3342389976..4b9bbe3bb5a1f450aa2be74f71c37c422954271a 100644 (file)
@@ -89,8 +89,7 @@ struct nullb {
 int null_zone_init(struct nullb_device *dev);
 void null_zone_exit(struct nullb_device *dev);
 int null_zone_report(struct gendisk *disk, sector_t sector,
-                    struct blk_zone *zones, unsigned int *nr_zones,
-                    gfp_t gfp_mask);
+                    struct blk_zone *zones, unsigned int *nr_zones);
 void null_zone_write(struct nullb_cmd *cmd, sector_t sector,
                        unsigned int nr_sectors);
 void null_zone_reset(struct nullb_cmd *cmd, sector_t sector);
index fca0c97ff1aa09925cbf50ae8e199c5d91963386..cb28d93f2bd145a1b7a867dd33cf571d708f76ae 100644 (file)
@@ -67,8 +67,7 @@ void null_zone_exit(struct nullb_device *dev)
 }
 
 int null_zone_report(struct gendisk *disk, sector_t sector,
-                    struct blk_zone *zones, unsigned int *nr_zones,
-                    gfp_t gfp_mask)
+                    struct blk_zone *zones, unsigned int *nr_zones)
 {
        struct nullb *nullb = disk->private_data;
        struct nullb_device *dev = nullb->dev;
index a9bc518156f20876680461715a3bdcb027f289e0..2900fbde89b3508d01e1900972952469fef6fa2b 100644 (file)
@@ -461,15 +461,14 @@ static int flakey_prepare_ioctl(struct dm_target *ti, struct block_device **bdev
 
 #ifdef CONFIG_BLK_DEV_ZONED
 static int flakey_report_zones(struct dm_target *ti, sector_t sector,
-                              struct blk_zone *zones, unsigned int *nr_zones,
-                              gfp_t gfp_mask)
+                              struct blk_zone *zones, unsigned int *nr_zones)
 {
        struct flakey_c *fc = ti->private;
        int ret;
 
        /* Do report and remap it */
        ret = blkdev_report_zones(fc->dev->bdev, flakey_map_sector(ti, sector),
-                                 zones, nr_zones, gfp_mask);
+                                 zones, nr_zones);
        if (ret != 0)
                return ret;
 
index ad980a38fb1e84be717a3032586153c08b9b251a..ecefe67037365a89f2cf08bcd15b7a5cfbdf26a7 100644 (file)
@@ -137,15 +137,14 @@ static int linear_prepare_ioctl(struct dm_target *ti, struct block_device **bdev
 
 #ifdef CONFIG_BLK_DEV_ZONED
 static int linear_report_zones(struct dm_target *ti, sector_t sector,
-                              struct blk_zone *zones, unsigned int *nr_zones,
-                              gfp_t gfp_mask)
+                              struct blk_zone *zones, unsigned int *nr_zones)
 {
        struct linear_c *lc = (struct linear_c *) ti->private;
        int ret;
 
        /* Do report and remap it */
        ret = blkdev_report_zones(lc->dev->bdev, linear_map_sector(ti, sector),
-                                 zones, nr_zones, gfp_mask);
+                                 zones, nr_zones);
        if (ret != 0)
                return ret;
 
index d8334cd45d7cb5eb90745b09463cf4daaa231021..9faf3e49c7affac9590b636b337f993f9261adc1 100644 (file)
@@ -8,6 +8,7 @@
 
 #include <linux/module.h>
 #include <linux/crc32.h>
+#include <linux/sched/mm.h>
 
 #define        DM_MSG_PREFIX           "zoned metadata"
 
@@ -1162,8 +1163,7 @@ static int dmz_init_zones(struct dmz_metadata *zmd)
        while (sector < dev->capacity) {
                /* Get zone information */
                nr_blkz = DMZ_REPORT_NR_ZONES;
-               ret = blkdev_report_zones(dev->bdev, sector, blkz,
-                                         &nr_blkz, GFP_KERNEL);
+               ret = blkdev_report_zones(dev->bdev, sector, blkz, &nr_blkz);
                if (ret) {
                        dmz_dev_err(dev, "Report zones failed %d", ret);
                        goto out;
@@ -1201,12 +1201,20 @@ out:
 static int dmz_update_zone(struct dmz_metadata *zmd, struct dm_zone *zone)
 {
        unsigned int nr_blkz = 1;
+       unsigned int noio_flag;
        struct blk_zone blkz;
        int ret;
 
-       /* Get zone information from disk */
+       /*
+        * Get zone information from disk. Since blkdev_report_zones() uses
+        * GFP_KERNEL by default for memory allocations, set the per-task
+        * PF_MEMALLOC_NOIO flag so that all allocations are done as if
+        * GFP_NOIO was specified.
+        */
+       noio_flag = memalloc_noio_save();
        ret = blkdev_report_zones(zmd->dev->bdev, dmz_start_sect(zmd, zone),
-                                 &blkz, &nr_blkz, GFP_NOIO);
+                                 &blkz, &nr_blkz);
+       memalloc_noio_restore(noio_flag);
        if (!nr_blkz)
                ret = -EIO;
        if (ret) {
index 5475081dcbd6736d37b7fb319b4ef3f72084a0c3..61f1152b74e95f199bfdb0d701c514a74307d64a 100644 (file)
@@ -441,8 +441,7 @@ static int dm_blk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
 }
 
 static int dm_blk_report_zones(struct gendisk *disk, sector_t sector,
-                              struct blk_zone *zones, unsigned int *nr_zones,
-                              gfp_t gfp_mask)
+                              struct blk_zone *zones, unsigned int *nr_zones)
 {
 #ifdef CONFIG_BLK_DEV_ZONED
        struct mapped_device *md = disk->private_data;
@@ -480,8 +479,7 @@ static int dm_blk_report_zones(struct gendisk *disk, sector_t sector,
         * So there is no need to loop here trying to fill the entire array
         * of zones.
         */
-       ret = tgt->type->report_zones(tgt, sector, zones,
-                                     nr_zones, gfp_mask);
+       ret = tgt->type->report_zones(tgt, sector, zones, nr_zones);
 
 out:
        dm_put_live_table(md, srcu_idx);
index 5796ace762254d9816c55f760a526f6533fb30c9..38c50946fc4287452a818188caaf48785ee14823 100644 (file)
@@ -213,8 +213,7 @@ extern blk_status_t sd_zbc_setup_reset_cmnd(struct scsi_cmnd *cmd);
 extern void sd_zbc_complete(struct scsi_cmnd *cmd, unsigned int good_bytes,
                            struct scsi_sense_hdr *sshdr);
 extern int sd_zbc_report_zones(struct gendisk *disk, sector_t sector,
-                              struct blk_zone *zones, unsigned int *nr_zones,
-                              gfp_t gfp_mask);
+                              struct blk_zone *zones, unsigned int *nr_zones);
 
 #else /* CONFIG_BLK_DEV_ZONED */
 
index 7334024b64f161f0a512548eb86c45a201cf523e..ec3764c8f3f161e89814693ed477060ba039e241 100644 (file)
@@ -109,13 +109,11 @@ static int sd_zbc_do_report_zones(struct scsi_disk *sdkp, unsigned char *buf,
  * @sector: Start 512B sector of the report
  * @zones: Array of zone descriptors
  * @nr_zones: Number of descriptors in the array
- * @gfp_mask: Memory allocation mask
  *
  * Execute a report zones command on the target disk.
  */
 int sd_zbc_report_zones(struct gendisk *disk, sector_t sector,
-                       struct blk_zone *zones, unsigned int *nr_zones,
-                       gfp_t gfp_mask)
+                       struct blk_zone *zones, unsigned int *nr_zones)
 {
        struct scsi_disk *sdkp = scsi_disk(disk);
        unsigned int i, buflen, nrz = *nr_zones;
@@ -134,7 +132,7 @@ int sd_zbc_report_zones(struct gendisk *disk, sector_t sector,
         */
        buflen = min(queue_max_hw_sectors(disk->queue) << 9,
                     roundup((nrz + 1) * 64, 512));
-       buf = kmalloc(buflen, gfp_mask);
+       buf = kmalloc(buflen, GFP_KERNEL);
        if (!buf)
                return -ENOMEM;
 
index 6b959bbb336a30543bd24a87e92d7cb28da1f274..4e91ba6c8a2e7b11760cb6a6fbbbacf3f9d426f2 100644 (file)
@@ -2841,9 +2841,7 @@ static int init_blkz_info(struct f2fs_sb_info *sbi, int devi)
        while (zones && sector < nr_sectors) {
 
                nr_zones = F2FS_REPORT_NR_ZONES;
-               err = blkdev_report_zones(bdev, sector,
-                                         zones, &nr_zones,
-                                         GFP_KERNEL);
+               err = blkdev_report_zones(bdev, sector, zones, &nr_zones);
                if (err)
                        break;
                if (!nr_zones) {
index 259bd7ad8312ed8b26bf2447fc7e7270d2fdcd0c..05036e3e3458fb175af4af7e2050dac3a01e0a1d 100644 (file)
@@ -347,7 +347,7 @@ struct queue_limits {
 extern unsigned int blkdev_nr_zones(struct block_device *bdev);
 extern int blkdev_report_zones(struct block_device *bdev,
                               sector_t sector, struct blk_zone *zones,
-                              unsigned int *nr_zones, gfp_t gfp_mask);
+                              unsigned int *nr_zones);
 extern int blkdev_reset_zones(struct block_device *bdev, sector_t sectors,
                              sector_t nr_sectors, gfp_t gfp_mask);
 extern int blk_revalidate_disk_zones(struct gendisk *disk);
@@ -1673,8 +1673,7 @@ struct block_device_operations {
        /* this callback is with swap_lock and sometimes page table lock held */
        void (*swap_slot_free_notify) (struct block_device *, unsigned long);
        int (*report_zones)(struct gendisk *, sector_t sector,
-                           struct blk_zone *zones, unsigned int *nr_zones,
-                           gfp_t gfp_mask);
+                           struct blk_zone *zones, unsigned int *nr_zones);
        struct module *owner;
        const struct pr_ops *pr_ops;
 };
index e1f51d607cc541924cc54c43aaa7b80c06a6322e..3b470cb03b668ff376f4e00c0f063415748cb832 100644 (file)
@@ -95,8 +95,7 @@ typedef int (*dm_prepare_ioctl_fn) (struct dm_target *ti, struct block_device **
 
 typedef int (*dm_report_zones_fn) (struct dm_target *ti, sector_t sector,
                                   struct blk_zone *zones,
-                                  unsigned int *nr_zones,
-                                  gfp_t gfp_mask);
+                                  unsigned int *nr_zones);
 
 /*
  * These iteration functions are typically used to check (and combine)