block: Kill gfp_t argument of blkdev_report_zones()
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>
This commit is contained in:
parent
b4c5875d36
commit
bd976e5272
@ -14,6 +14,7 @@
|
|||||||
#include <linux/rbtree.h>
|
#include <linux/rbtree.h>
|
||||||
#include <linux/blkdev.h>
|
#include <linux/blkdev.h>
|
||||||
#include <linux/blk-mq.h>
|
#include <linux/blk-mq.h>
|
||||||
|
#include <linux/sched/mm.h>
|
||||||
|
|
||||||
#include "blk.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,
|
static int blk_report_zones(struct gendisk *disk, sector_t sector,
|
||||||
struct blk_zone *zones, unsigned int *nr_zones,
|
struct blk_zone *zones, unsigned int *nr_zones)
|
||||||
gfp_t gfp_mask)
|
|
||||||
{
|
{
|
||||||
struct request_queue *q = disk->queue;
|
struct request_queue *q = disk->queue;
|
||||||
unsigned int z = 0, n, nrz = *nr_zones;
|
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) {
|
while (z < nrz && sector < capacity) {
|
||||||
n = nrz - z;
|
n = nrz - z;
|
||||||
ret = disk->fops->report_zones(disk, sector, &zones[z], &n,
|
ret = disk->fops->report_zones(disk, sector, &zones[z], &n);
|
||||||
gfp_mask);
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
if (!n)
|
if (!n)
|
||||||
@ -149,17 +148,18 @@ static int blk_report_zones(struct gendisk *disk, sector_t sector,
|
|||||||
* @sector: Sector from which to report zones
|
* @sector: Sector from which to report zones
|
||||||
* @zones: Array of zone structures where to return the zones information
|
* @zones: Array of zone structures where to return the zones information
|
||||||
* @nr_zones: Number of zone structures in the zone array
|
* @nr_zones: Number of zone structures in the zone array
|
||||||
* @gfp_mask: Memory allocation flags (for bio_alloc)
|
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Get zone information starting from the zone containing @sector.
|
* Get zone information starting from the zone containing @sector.
|
||||||
* The number of zone information reported may be less than the number
|
* The number of zone information reported may be less than the number
|
||||||
* requested by @nr_zones. The number of zones actually reported is
|
* requested by @nr_zones. The number of zones actually reported is
|
||||||
* returned in @nr_zones.
|
* 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,
|
int blkdev_report_zones(struct block_device *bdev, sector_t sector,
|
||||||
struct blk_zone *zones, unsigned int *nr_zones,
|
struct blk_zone *zones, unsigned int *nr_zones)
|
||||||
gfp_t gfp_mask)
|
|
||||||
{
|
{
|
||||||
struct request_queue *q = bdev_get_queue(bdev);
|
struct request_queue *q = bdev_get_queue(bdev);
|
||||||
unsigned int i, nrz;
|
unsigned int i, nrz;
|
||||||
@ -184,7 +184,7 @@ int blkdev_report_zones(struct block_device *bdev, sector_t sector,
|
|||||||
nrz = min(*nr_zones,
|
nrz = min(*nr_zones,
|
||||||
__blkdev_nr_zones(q, bdev->bd_part->nr_sects - sector));
|
__blkdev_nr_zones(q, bdev->bd_part->nr_sects - sector));
|
||||||
ret = blk_report_zones(bdev->bd_disk, get_start_sect(bdev) + sector,
|
ret = blk_report_zones(bdev->bd_disk, get_start_sect(bdev) + sector,
|
||||||
zones, &nrz, gfp_mask);
|
zones, &nrz);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@ -305,9 +305,7 @@ int blkdev_report_zones_ioctl(struct block_device *bdev, fmode_t mode,
|
|||||||
if (!zones)
|
if (!zones)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
ret = blkdev_report_zones(bdev, rep.sector,
|
ret = blkdev_report_zones(bdev, rep.sector, zones, &rep.nr_zones);
|
||||||
zones, &rep.nr_zones,
|
|
||||||
GFP_KERNEL);
|
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
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 long *seq_zones_wlock = NULL, *seq_zones_bitmap = NULL;
|
||||||
unsigned int i, rep_nr_zones = 0, z = 0, nrz;
|
unsigned int i, rep_nr_zones = 0, z = 0, nrz;
|
||||||
struct blk_zone *zones = NULL;
|
struct blk_zone *zones = NULL;
|
||||||
|
unsigned int noio_flag;
|
||||||
sector_t sector = 0;
|
sector_t sector = 0;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
@ -427,6 +426,12 @@ int blk_revalidate_disk_zones(struct gendisk *disk)
|
|||||||
return 0;
|
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) {
|
if (!blk_queue_is_zoned(q) || !nr_zones) {
|
||||||
nr_zones = 0;
|
nr_zones = 0;
|
||||||
goto update;
|
goto update;
|
||||||
@ -449,7 +454,7 @@ int blk_revalidate_disk_zones(struct gendisk *disk)
|
|||||||
|
|
||||||
while (z < nr_zones) {
|
while (z < nr_zones) {
|
||||||
nrz = min(nr_zones - z, rep_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)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
if (!nrz)
|
if (!nrz)
|
||||||
@ -480,6 +485,8 @@ update:
|
|||||||
blk_mq_unfreeze_queue(q);
|
blk_mq_unfreeze_queue(q);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
memalloc_noio_restore(noio_flag);
|
||||||
|
|
||||||
free_pages((unsigned long)zones,
|
free_pages((unsigned long)zones,
|
||||||
get_order(rep_nr_zones * sizeof(struct blk_zone)));
|
get_order(rep_nr_zones * sizeof(struct blk_zone)));
|
||||||
kfree(seq_zones_wlock);
|
kfree(seq_zones_wlock);
|
||||||
|
@ -89,8 +89,7 @@ struct nullb {
|
|||||||
int null_zone_init(struct nullb_device *dev);
|
int null_zone_init(struct nullb_device *dev);
|
||||||
void null_zone_exit(struct nullb_device *dev);
|
void null_zone_exit(struct nullb_device *dev);
|
||||||
int null_zone_report(struct gendisk *disk, sector_t sector,
|
int null_zone_report(struct gendisk *disk, sector_t sector,
|
||||||
struct blk_zone *zones, unsigned int *nr_zones,
|
struct blk_zone *zones, unsigned int *nr_zones);
|
||||||
gfp_t gfp_mask);
|
|
||||||
void null_zone_write(struct nullb_cmd *cmd, sector_t sector,
|
void null_zone_write(struct nullb_cmd *cmd, sector_t sector,
|
||||||
unsigned int nr_sectors);
|
unsigned int nr_sectors);
|
||||||
void null_zone_reset(struct nullb_cmd *cmd, sector_t sector);
|
void null_zone_reset(struct nullb_cmd *cmd, sector_t sector);
|
||||||
|
@ -67,8 +67,7 @@ void null_zone_exit(struct nullb_device *dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int null_zone_report(struct gendisk *disk, sector_t sector,
|
int null_zone_report(struct gendisk *disk, sector_t sector,
|
||||||
struct blk_zone *zones, unsigned int *nr_zones,
|
struct blk_zone *zones, unsigned int *nr_zones)
|
||||||
gfp_t gfp_mask)
|
|
||||||
{
|
{
|
||||||
struct nullb *nullb = disk->private_data;
|
struct nullb *nullb = disk->private_data;
|
||||||
struct nullb_device *dev = nullb->dev;
|
struct nullb_device *dev = nullb->dev;
|
||||||
|
@ -461,15 +461,14 @@ static int flakey_prepare_ioctl(struct dm_target *ti, struct block_device **bdev
|
|||||||
|
|
||||||
#ifdef CONFIG_BLK_DEV_ZONED
|
#ifdef CONFIG_BLK_DEV_ZONED
|
||||||
static int flakey_report_zones(struct dm_target *ti, sector_t sector,
|
static int flakey_report_zones(struct dm_target *ti, sector_t sector,
|
||||||
struct blk_zone *zones, unsigned int *nr_zones,
|
struct blk_zone *zones, unsigned int *nr_zones)
|
||||||
gfp_t gfp_mask)
|
|
||||||
{
|
{
|
||||||
struct flakey_c *fc = ti->private;
|
struct flakey_c *fc = ti->private;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* Do report and remap it */
|
/* Do report and remap it */
|
||||||
ret = blkdev_report_zones(fc->dev->bdev, flakey_map_sector(ti, sector),
|
ret = blkdev_report_zones(fc->dev->bdev, flakey_map_sector(ti, sector),
|
||||||
zones, nr_zones, gfp_mask);
|
zones, nr_zones);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@ -137,15 +137,14 @@ static int linear_prepare_ioctl(struct dm_target *ti, struct block_device **bdev
|
|||||||
|
|
||||||
#ifdef CONFIG_BLK_DEV_ZONED
|
#ifdef CONFIG_BLK_DEV_ZONED
|
||||||
static int linear_report_zones(struct dm_target *ti, sector_t sector,
|
static int linear_report_zones(struct dm_target *ti, sector_t sector,
|
||||||
struct blk_zone *zones, unsigned int *nr_zones,
|
struct blk_zone *zones, unsigned int *nr_zones)
|
||||||
gfp_t gfp_mask)
|
|
||||||
{
|
{
|
||||||
struct linear_c *lc = (struct linear_c *) ti->private;
|
struct linear_c *lc = (struct linear_c *) ti->private;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* Do report and remap it */
|
/* Do report and remap it */
|
||||||
ret = blkdev_report_zones(lc->dev->bdev, linear_map_sector(ti, sector),
|
ret = blkdev_report_zones(lc->dev->bdev, linear_map_sector(ti, sector),
|
||||||
zones, nr_zones, gfp_mask);
|
zones, nr_zones);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/crc32.h>
|
#include <linux/crc32.h>
|
||||||
|
#include <linux/sched/mm.h>
|
||||||
|
|
||||||
#define DM_MSG_PREFIX "zoned metadata"
|
#define DM_MSG_PREFIX "zoned metadata"
|
||||||
|
|
||||||
@ -1162,8 +1163,7 @@ static int dmz_init_zones(struct dmz_metadata *zmd)
|
|||||||
while (sector < dev->capacity) {
|
while (sector < dev->capacity) {
|
||||||
/* Get zone information */
|
/* Get zone information */
|
||||||
nr_blkz = DMZ_REPORT_NR_ZONES;
|
nr_blkz = DMZ_REPORT_NR_ZONES;
|
||||||
ret = blkdev_report_zones(dev->bdev, sector, blkz,
|
ret = blkdev_report_zones(dev->bdev, sector, blkz, &nr_blkz);
|
||||||
&nr_blkz, GFP_KERNEL);
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dmz_dev_err(dev, "Report zones failed %d", ret);
|
dmz_dev_err(dev, "Report zones failed %d", ret);
|
||||||
goto out;
|
goto out;
|
||||||
@ -1201,12 +1201,20 @@ out:
|
|||||||
static int dmz_update_zone(struct dmz_metadata *zmd, struct dm_zone *zone)
|
static int dmz_update_zone(struct dmz_metadata *zmd, struct dm_zone *zone)
|
||||||
{
|
{
|
||||||
unsigned int nr_blkz = 1;
|
unsigned int nr_blkz = 1;
|
||||||
|
unsigned int noio_flag;
|
||||||
struct blk_zone blkz;
|
struct blk_zone blkz;
|
||||||
int ret;
|
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),
|
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)
|
if (!nr_blkz)
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
@ -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,
|
static int dm_blk_report_zones(struct gendisk *disk, sector_t sector,
|
||||||
struct blk_zone *zones, unsigned int *nr_zones,
|
struct blk_zone *zones, unsigned int *nr_zones)
|
||||||
gfp_t gfp_mask)
|
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_BLK_DEV_ZONED
|
#ifdef CONFIG_BLK_DEV_ZONED
|
||||||
struct mapped_device *md = disk->private_data;
|
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
|
* So there is no need to loop here trying to fill the entire array
|
||||||
* of zones.
|
* of zones.
|
||||||
*/
|
*/
|
||||||
ret = tgt->type->report_zones(tgt, sector, zones,
|
ret = tgt->type->report_zones(tgt, sector, zones, nr_zones);
|
||||||
nr_zones, gfp_mask);
|
|
||||||
|
|
||||||
out:
|
out:
|
||||||
dm_put_live_table(md, srcu_idx);
|
dm_put_live_table(md, srcu_idx);
|
||||||
|
@ -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,
|
extern void sd_zbc_complete(struct scsi_cmnd *cmd, unsigned int good_bytes,
|
||||||
struct scsi_sense_hdr *sshdr);
|
struct scsi_sense_hdr *sshdr);
|
||||||
extern int sd_zbc_report_zones(struct gendisk *disk, sector_t sector,
|
extern int sd_zbc_report_zones(struct gendisk *disk, sector_t sector,
|
||||||
struct blk_zone *zones, unsigned int *nr_zones,
|
struct blk_zone *zones, unsigned int *nr_zones);
|
||||||
gfp_t gfp_mask);
|
|
||||||
|
|
||||||
#else /* CONFIG_BLK_DEV_ZONED */
|
#else /* CONFIG_BLK_DEV_ZONED */
|
||||||
|
|
||||||
|
@ -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
|
* @sector: Start 512B sector of the report
|
||||||
* @zones: Array of zone descriptors
|
* @zones: Array of zone descriptors
|
||||||
* @nr_zones: Number of descriptors in the array
|
* @nr_zones: Number of descriptors in the array
|
||||||
* @gfp_mask: Memory allocation mask
|
|
||||||
*
|
*
|
||||||
* Execute a report zones command on the target disk.
|
* Execute a report zones command on the target disk.
|
||||||
*/
|
*/
|
||||||
int sd_zbc_report_zones(struct gendisk *disk, sector_t sector,
|
int sd_zbc_report_zones(struct gendisk *disk, sector_t sector,
|
||||||
struct blk_zone *zones, unsigned int *nr_zones,
|
struct blk_zone *zones, unsigned int *nr_zones)
|
||||||
gfp_t gfp_mask)
|
|
||||||
{
|
{
|
||||||
struct scsi_disk *sdkp = scsi_disk(disk);
|
struct scsi_disk *sdkp = scsi_disk(disk);
|
||||||
unsigned int i, buflen, nrz = *nr_zones;
|
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,
|
buflen = min(queue_max_hw_sectors(disk->queue) << 9,
|
||||||
roundup((nrz + 1) * 64, 512));
|
roundup((nrz + 1) * 64, 512));
|
||||||
buf = kmalloc(buflen, gfp_mask);
|
buf = kmalloc(buflen, GFP_KERNEL);
|
||||||
if (!buf)
|
if (!buf)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
@ -2841,9 +2841,7 @@ static int init_blkz_info(struct f2fs_sb_info *sbi, int devi)
|
|||||||
while (zones && sector < nr_sectors) {
|
while (zones && sector < nr_sectors) {
|
||||||
|
|
||||||
nr_zones = F2FS_REPORT_NR_ZONES;
|
nr_zones = F2FS_REPORT_NR_ZONES;
|
||||||
err = blkdev_report_zones(bdev, sector,
|
err = blkdev_report_zones(bdev, sector, zones, &nr_zones);
|
||||||
zones, &nr_zones,
|
|
||||||
GFP_KERNEL);
|
|
||||||
if (err)
|
if (err)
|
||||||
break;
|
break;
|
||||||
if (!nr_zones) {
|
if (!nr_zones) {
|
||||||
|
@ -347,7 +347,7 @@ struct queue_limits {
|
|||||||
extern unsigned int blkdev_nr_zones(struct block_device *bdev);
|
extern unsigned int blkdev_nr_zones(struct block_device *bdev);
|
||||||
extern int blkdev_report_zones(struct block_device *bdev,
|
extern int blkdev_report_zones(struct block_device *bdev,
|
||||||
sector_t sector, struct blk_zone *zones,
|
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,
|
extern int blkdev_reset_zones(struct block_device *bdev, sector_t sectors,
|
||||||
sector_t nr_sectors, gfp_t gfp_mask);
|
sector_t nr_sectors, gfp_t gfp_mask);
|
||||||
extern int blk_revalidate_disk_zones(struct gendisk *disk);
|
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 */
|
/* this callback is with swap_lock and sometimes page table lock held */
|
||||||
void (*swap_slot_free_notify) (struct block_device *, unsigned long);
|
void (*swap_slot_free_notify) (struct block_device *, unsigned long);
|
||||||
int (*report_zones)(struct gendisk *, sector_t sector,
|
int (*report_zones)(struct gendisk *, sector_t sector,
|
||||||
struct blk_zone *zones, unsigned int *nr_zones,
|
struct blk_zone *zones, unsigned int *nr_zones);
|
||||||
gfp_t gfp_mask);
|
|
||||||
struct module *owner;
|
struct module *owner;
|
||||||
const struct pr_ops *pr_ops;
|
const struct pr_ops *pr_ops;
|
||||||
};
|
};
|
||||||
|
@ -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,
|
typedef int (*dm_report_zones_fn) (struct dm_target *ti, sector_t sector,
|
||||||
struct blk_zone *zones,
|
struct blk_zone *zones,
|
||||||
unsigned int *nr_zones,
|
unsigned int *nr_zones);
|
||||||
gfp_t gfp_mask);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These iteration functions are typically used to check (and combine)
|
* These iteration functions are typically used to check (and combine)
|
||||||
|
Loading…
Reference in New Issue
Block a user