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).
Unified · Split
| @@ -14,6 +14,7 @@ · 13 unmodified lines | ||
| 14 | 14 | #include <linux/rbtree.h> |
| 15 | 15 | #include <linux/blkdev.h> |
| 16 | 16 | #include <linux/blk-mq.h> |
| 17 | +#include <linux/sched/mm.h> | |
| 17 | 18 | |
| 18 | 19 | #include "blk.h" |
| 19 | 20 | |
| @@ -117,8 +118,7 @@ static bool blkdev_report_zone(struct block_device *bdev, struct blk_zone *rep) · 97 unmodified lines | ||
| 117 | 118 | } |
| 118 | 119 | |
| 119 | 120 | static int blk_report_zones(struct gendisk *disk, sector_t sector, |
| 120 | − struct blk_zone *zones, unsigned int *nr_zones, | |
| 121 | − gfp_t gfp_mask) | |
| 121 | + struct blk_zone *zones, unsigned int *nr_zones) | |
| 122 | 122 | { |
| 123 | 123 | struct request_queue *q = disk->queue; |
| 124 | 124 | unsigned int z = 0, n, nrz = *nr_zones; |
| @@ -127,8 +127,7 @@ static int blk_report_zones(struct gendisk *disk, sector_t sector, · 2 unmodified lines | ||
| 127 | 127 | |
| 128 | 128 | while (z < nrz && sector < capacity) { |
| 129 | 129 | n = nrz - z; |
| 130 | − ret = disk->fops->report_zones(disk, sector, &zones[z], &n, | |
| 131 | − gfp_mask); | |
| 130 | + ret = disk->fops->report_zones(disk, sector, &zones[z], &n); | |
| 132 | 131 | if (ret) |
| 133 | 132 | return ret; |
| 134 | 133 | if (!n) |
| @@ -149,17 +148,18 @@ static int blk_report_zones(struct gendisk *disk, sector_t sector, · 14 unmodified lines | ||
| 149 | 148 | * @sector: Sector from which to report zones |
| 150 | 149 | * @zones: Array of zone structures where to return the zones information |
| 151 | 150 | * @nr_zones: Number of zone structures in the zone array |
| 152 | − * @gfp_mask: Memory allocation flags (for bio_alloc) | |
| 153 | 151 | * |
| 154 | 152 | * Description: |
| 155 | 153 | * Get zone information starting from the zone containing @sector. |
| 156 | 154 | * The number of zone information reported may be less than the number |
| 157 | 155 | * requested by @nr_zones. The number of zones actually reported is |
| 158 | 156 | * returned in @nr_zones. |
| 157 | + * The caller must use memalloc_noXX_save/restore() calls to control | |
| 158 | + * memory allocations done within this function (zone array and command | |
| 159 | + * buffer allocation by the device driver). | |
| 159 | 160 | */ |
| 160 | 161 | int blkdev_report_zones(struct block_device *bdev, sector_t sector, |
| 161 | − struct blk_zone *zones, unsigned int *nr_zones, | |
| 162 | − gfp_t gfp_mask) | |
| 162 | + struct blk_zone *zones, unsigned int *nr_zones) | |
| 163 | 163 | { |
| 164 | 164 | struct request_queue *q = bdev_get_queue(bdev); |
| 165 | 165 | unsigned int i, nrz; |
| @@ -184,7 +184,7 @@ int blkdev_report_zones(struct block_device *bdev, sector_t sector, · 18 unmodified lines | ||
| 184 | 184 | nrz = min(*nr_zones, |
| 185 | 185 | __blkdev_nr_zones(q, bdev->bd_part->nr_sects - sector)); |
| 186 | 186 | ret = blk_report_zones(bdev->bd_disk, get_start_sect(bdev) + sector, |
| 187 | − zones, &nrz, gfp_mask); | |
| 187 | + zones, &nrz); | |
| 188 | 188 | if (ret) |
| 189 | 189 | return ret; |
| 190 | 190 | |
| @@ -305,9 +305,7 @@ int blkdev_report_zones_ioctl(struct block_device *bdev, fmode_t mode, · 114 unmodified lines | ||
| 305 | 305 | if (!zones) |
| 306 | 306 | return -ENOMEM; |
| 307 | 307 | |
| 308 | − ret = blkdev_report_zones(bdev, rep.sector, | |
| 309 | − zones, &rep.nr_zones, | |
| 310 | − GFP_KERNEL); | |
| 308 | + ret = blkdev_report_zones(bdev, rep.sector, zones, &rep.nr_zones); | |
| 311 | 309 | if (ret) |
| 312 | 310 | goto out; |
| 313 | 311 | |
| @@ -415,6 +413,7 @@ int blk_revalidate_disk_zones(struct gendisk *disk) · 101 unmodified lines | ||
| 415 | 413 | unsigned long *seq_zones_wlock = NULL, *seq_zones_bitmap = NULL; |
| 416 | 414 | unsigned int i, rep_nr_zones = 0, z = 0, nrz; |
| 417 | 415 | struct blk_zone *zones = NULL; |
| 416 | + unsigned int noio_flag; | |
| 418 | 417 | sector_t sector = 0; |
| 419 | 418 | int ret = 0; |
| 420 | 419 | |
| @@ -427,6 +426,12 @@ int blk_revalidate_disk_zones(struct gendisk *disk) · 6 unmodified lines | ||
| 427 | 426 | return 0; |
| 428 | 427 | } |
| 429 | 428 | |
| 429 | + /* | |
| 430 | + * Ensure that all memory allocations in this context are done as | |
| 431 | + * if GFP_NOIO was specified. | |
| 432 | + */ | |
| 433 | + noio_flag = memalloc_noio_save(); | |
| 434 | + | |
| 430 | 435 | if (!blk_queue_is_zoned(q) || !nr_zones) { |
| 431 | 436 | nr_zones = 0; |
| 432 | 437 | goto update; |
| @@ -449,7 +454,7 @@ int blk_revalidate_disk_zones(struct gendisk *disk) · 16 unmodified lines | ||
| 449 | 454 | |
| 450 | 455 | while (z < nr_zones) { |
| 451 | 456 | nrz = min(nr_zones - z, rep_nr_zones); |
| 452 | − ret = blk_report_zones(disk, sector, zones, &nrz, GFP_NOIO); | |
| 457 | + ret = blk_report_zones(disk, sector, zones, &nrz); | |
| 453 | 458 | if (ret) |
| 454 | 459 | goto out; |
| 455 | 460 | if (!nrz) |
| @@ -480,6 +485,8 @@ update: · 24 unmodified lines | ||
| 480 | 485 | blk_mq_unfreeze_queue(q); |
| 481 | 486 | |
| 482 | 487 | out: |
| 488 | + memalloc_noio_restore(noio_flag); | |
| 489 | + | |
| 483 | 490 | free_pages((unsigned long)zones, |
| 484 | 491 | get_order(rep_nr_zones * sizeof(struct blk_zone))); |
| 485 | 492 | kfree(seq_zones_wlock); |
| @@ -89,8 +89,7 @@ struct nullb { · 88 unmodified lines | ||
| 89 | 89 | int null_zone_init(struct nullb_device *dev); |
| 90 | 90 | void null_zone_exit(struct nullb_device *dev); |
| 91 | 91 | int null_zone_report(struct gendisk *disk, sector_t sector, |
| 92 | − struct blk_zone *zones, unsigned int *nr_zones, | |
| 93 | − gfp_t gfp_mask); | |
| 92 | + struct blk_zone *zones, unsigned int *nr_zones); | |
| 94 | 93 | void null_zone_write(struct nullb_cmd *cmd, sector_t sector, |
| 95 | 94 | unsigned int nr_sectors); |
| 96 | 95 | void null_zone_reset(struct nullb_cmd *cmd, sector_t sector); |
| @@ -67,8 +67,7 @@ void null_zone_exit(struct nullb_device *dev) · 66 unmodified lines | ||
| 67 | 67 | } |
| 68 | 68 | |
| 69 | 69 | int null_zone_report(struct gendisk *disk, sector_t sector, |
| 70 | − struct blk_zone *zones, unsigned int *nr_zones, | |
| 71 | − gfp_t gfp_mask) | |
| 70 | + struct blk_zone *zones, unsigned int *nr_zones) | |
| 72 | 71 | { |
| 73 | 72 | struct nullb *nullb = disk->private_data; |
| 74 | 73 | struct nullb_device *dev = nullb->dev; |
| @@ -461,15 +461,14 @@ static int flakey_prepare_ioctl(struct dm_target *ti, struct block_device **bdev · 460 unmodified lines | ||
| 461 | 461 | |
| 462 | 462 | #ifdef CONFIG_BLK_DEV_ZONED |
| 463 | 463 | static int flakey_report_zones(struct dm_target *ti, sector_t sector, |
| 464 | − struct blk_zone *zones, unsigned int *nr_zones, | |
| 465 | − gfp_t gfp_mask) | |
| 464 | + struct blk_zone *zones, unsigned int *nr_zones) | |
| 466 | 465 | { |
| 467 | 466 | struct flakey_c *fc = ti->private; |
| 468 | 467 | int ret; |
| 469 | 468 | |
| 470 | 469 | /* Do report and remap it */ |
| 471 | 470 | ret = blkdev_report_zones(fc->dev->bdev, flakey_map_sector(ti, sector), |
| 472 | − zones, nr_zones, gfp_mask); | |
| 471 | + zones, nr_zones); | |
| 473 | 472 | if (ret != 0) |
| 474 | 473 | return ret; |
| 475 | 474 | |
| @@ -137,15 +137,14 @@ static int linear_prepare_ioctl(struct dm_target *ti, struct block_device **bdev · 136 unmodified lines | ||
| 137 | 137 | |
| 138 | 138 | #ifdef CONFIG_BLK_DEV_ZONED |
| 139 | 139 | static int linear_report_zones(struct dm_target *ti, sector_t sector, |
| 140 | − struct blk_zone *zones, unsigned int *nr_zones, | |
| 141 | − gfp_t gfp_mask) | |
| 140 | + struct blk_zone *zones, unsigned int *nr_zones) | |
| 142 | 141 | { |
| 143 | 142 | struct linear_c *lc = (struct linear_c *) ti->private; |
| 144 | 143 | int ret; |
| 145 | 144 | |
| 146 | 145 | /* Do report and remap it */ |
| 147 | 146 | ret = blkdev_report_zones(lc->dev->bdev, linear_map_sector(ti, sector), |
| 148 | − zones, nr_zones, gfp_mask); | |
| 147 | + zones, nr_zones); | |
| 149 | 148 | if (ret != 0) |
| 150 | 149 | return ret; |
| 151 | 150 | |
| @@ -8,6 +8,7 @@ · 7 unmodified lines | ||
| 8 | 8 | |
| 9 | 9 | #include <linux/module.h> |
| 10 | 10 | #include <linux/crc32.h> |
| 11 | +#include <linux/sched/mm.h> | |
| 11 | 12 | |
| 12 | 13 | #define DM_MSG_PREFIX "zoned metadata" |
| 13 | 14 | |
| @@ -1162,8 +1163,7 @@ static int dmz_init_zones(struct dmz_metadata *zmd) · 1148 unmodified lines | ||
| 1162 | 1163 | while (sector < dev->capacity) { |
| 1163 | 1164 | /* Get zone information */ |
| 1164 | 1165 | nr_blkz = DMZ_REPORT_NR_ZONES; |
| 1165 | − ret = blkdev_report_zones(dev->bdev, sector, blkz, | |
| 1166 | − &nr_blkz, GFP_KERNEL); | |
| 1166 | + ret = blkdev_report_zones(dev->bdev, sector, blkz, &nr_blkz); | |
| 1167 | 1167 | if (ret) { |
| 1168 | 1168 | dmz_dev_err(dev, "Report zones failed %d", ret); |
| 1169 | 1169 | goto out; |
| @@ -1201,12 +1201,20 @@ out: · 31 unmodified lines | ||
| 1201 | 1201 | static int dmz_update_zone(struct dmz_metadata *zmd, struct dm_zone *zone) |
| 1202 | 1202 | { |
| 1203 | 1203 | unsigned int nr_blkz = 1; |
| 1204 | + unsigned int noio_flag; | |
| 1204 | 1205 | struct blk_zone blkz; |
| 1205 | 1206 | int ret; |
| 1206 | 1207 | |
| 1207 | − /* Get zone information from disk */ | |
| 1208 | + /* | |
| 1209 | + * Get zone information from disk. Since blkdev_report_zones() uses | |
| 1210 | + * GFP_KERNEL by default for memory allocations, set the per-task | |
| 1211 | + * PF_MEMALLOC_NOIO flag so that all allocations are done as if | |
| 1212 | + * GFP_NOIO was specified. | |
| 1213 | + */ | |
| 1214 | + noio_flag = memalloc_noio_save(); | |
| 1208 | 1215 | ret = blkdev_report_zones(zmd->dev->bdev, dmz_start_sect(zmd, zone), |
| 1209 | − &blkz, &nr_blkz, GFP_NOIO); | |
| 1216 | + &blkz, &nr_blkz); | |
| 1217 | + memalloc_noio_restore(noio_flag); | |
| 1210 | 1218 | if (!nr_blkz) |
| 1211 | 1219 | ret = -EIO; |
| 1212 | 1220 | if (ret) { |
| @@ -441,8 +441,7 @@ static int dm_blk_getgeo(struct block_device *bdev, struct hd_geometry *geo) · 440 unmodified lines | ||
| 441 | 441 | } |
| 442 | 442 | |
| 443 | 443 | static int dm_blk_report_zones(struct gendisk *disk, sector_t sector, |
| 444 | − struct blk_zone *zones, unsigned int *nr_zones, | |
| 445 | − gfp_t gfp_mask) | |
| 444 | + struct blk_zone *zones, unsigned int *nr_zones) | |
| 446 | 445 | { |
| 447 | 446 | #ifdef CONFIG_BLK_DEV_ZONED |
| 448 | 447 | struct mapped_device *md = disk->private_data; |
| @@ -480,8 +479,7 @@ static int dm_blk_report_zones(struct gendisk *disk, sector_t sector, · 31 unmodified lines | ||
| 480 | 479 | * So there is no need to loop here trying to fill the entire array |
| 481 | 480 | * of zones. |
| 482 | 481 | */ |
| 483 | − ret = tgt->type->report_zones(tgt, sector, zones, | |
| 484 | − nr_zones, gfp_mask); | |
| 482 | + ret = tgt->type->report_zones(tgt, sector, zones, nr_zones); | |
| 485 | 483 | |
| 486 | 484 | out: |
| 487 | 485 | dm_put_live_table(md, srcu_idx); |
| @@ -213,8 +213,7 @@ extern blk_status_t sd_zbc_setup_reset_cmnd(struct scsi_cmnd *cmd); · 212 unmodified lines | ||
| 213 | 213 | extern void sd_zbc_complete(struct scsi_cmnd *cmd, unsigned int good_bytes, |
| 214 | 214 | struct scsi_sense_hdr *sshdr); |
| 215 | 215 | extern int sd_zbc_report_zones(struct gendisk *disk, sector_t sector, |
| 216 | − struct blk_zone *zones, unsigned int *nr_zones, | |
| 217 | − gfp_t gfp_mask); | |
| 216 | + struct blk_zone *zones, unsigned int *nr_zones); | |
| 218 | 217 | |
| 219 | 218 | #else /* CONFIG_BLK_DEV_ZONED */ |
| 220 | 219 | |
| @@ -109,13 +109,11 @@ static int sd_zbc_do_report_zones(struct scsi_disk *sdkp, unsigned char *buf, · 108 unmodified lines | ||
| 109 | 109 | * @sector: Start 512B sector of the report |
| 110 | 110 | * @zones: Array of zone descriptors |
| 111 | 111 | * @nr_zones: Number of descriptors in the array |
| 112 | − * @gfp_mask: Memory allocation mask | |
| 113 | 112 | * |
| 114 | 113 | * Execute a report zones command on the target disk. |
| 115 | 114 | */ |
| 116 | 115 | int sd_zbc_report_zones(struct gendisk *disk, sector_t sector, |
| 117 | − struct blk_zone *zones, unsigned int *nr_zones, | |
| 118 | − gfp_t gfp_mask) | |
| 116 | + struct blk_zone *zones, unsigned int *nr_zones) | |
| 119 | 117 | { |
| 120 | 118 | struct scsi_disk *sdkp = scsi_disk(disk); |
| 121 | 119 | unsigned int i, buflen, nrz = *nr_zones; |
| @@ -134,7 +132,7 @@ int sd_zbc_report_zones(struct gendisk *disk, sector_t sector, · 12 unmodified lines | ||
| 134 | 132 | */ |
| 135 | 133 | buflen = min(queue_max_hw_sectors(disk->queue) << 9, |
| 136 | 134 | roundup((nrz + 1) * 64, 512)); |
| 137 | − buf = kmalloc(buflen, gfp_mask); | |
| 135 | + buf = kmalloc(buflen, GFP_KERNEL); | |
| 138 | 136 | if (!buf) |
| 139 | 137 | return -ENOMEM; |
| 140 | 138 | |
| @@ -2841,9 +2841,7 @@ static int init_blkz_info(struct f2fs_sb_info *sbi, int devi) · 2840 unmodified lines | ||
| 2841 | 2841 | while (zones && sector < nr_sectors) { |
| 2842 | 2842 | |
| 2843 | 2843 | nr_zones = F2FS_REPORT_NR_ZONES; |
| 2844 | − err = blkdev_report_zones(bdev, sector, | |
| 2845 | − zones, &nr_zones, | |
| 2846 | − GFP_KERNEL); | |
| 2844 | + err = blkdev_report_zones(bdev, sector, zones, &nr_zones); | |
| 2847 | 2845 | if (err) |
| 2848 | 2846 | break; |
| 2849 | 2847 | if (!nr_zones) { |
| @@ -347,7 +347,7 @@ struct queue_limits { · 346 unmodified lines | ||
| 347 | 347 | extern unsigned int blkdev_nr_zones(struct block_device *bdev); |
| 348 | 348 | extern int blkdev_report_zones(struct block_device *bdev, |
| 349 | 349 | sector_t sector, struct blk_zone *zones, |
| 350 | − unsigned int *nr_zones, gfp_t gfp_mask); | |
| 350 | + unsigned int *nr_zones); | |
| 351 | 351 | extern int blkdev_reset_zones(struct block_device *bdev, sector_t sectors, |
| 352 | 352 | sector_t nr_sectors, gfp_t gfp_mask); |
| 353 | 353 | extern int blk_revalidate_disk_zones(struct gendisk *disk); |
| @@ -1673,8 +1673,7 @@ struct block_device_operations { · 1319 unmodified lines | ||
| 1673 | 1673 | /* this callback is with swap_lock and sometimes page table lock held */ |
| 1674 | 1674 | void (*swap_slot_free_notify) (struct block_device *, unsigned long); |
| 1675 | 1675 | int (*report_zones)(struct gendisk *, sector_t sector, |
| 1676 | − struct blk_zone *zones, unsigned int *nr_zones, | |
| 1677 | − gfp_t gfp_mask); | |
| 1676 | + struct blk_zone *zones, unsigned int *nr_zones); | |
| 1678 | 1677 | struct module *owner; |
| 1679 | 1678 | const struct pr_ops *pr_ops; |
| 1680 | 1679 | }; |
| @@ -95,8 +95,7 @@ typedef int (*dm_prepare_ioctl_fn) (struct dm_target *ti, struct block_device ** · 94 unmodified lines | ||
| 95 | 95 | |
| 96 | 96 | typedef int (*dm_report_zones_fn) (struct dm_target *ti, sector_t sector, |
| 97 | 97 | struct blk_zone *zones, |
| 98 | − unsigned int *nr_zones, | |
| 99 | − gfp_t gfp_mask); | |
| 98 | + unsigned int *nr_zones); | |
| 100 | 99 | |
| 101 | 100 | /* |
| 102 | 101 | * These iteration functions are typically used to check (and combine) |