diff mbox series

sd: sd_zbc: don't pass GFP_NOIO to kvcalloc

Message ID 5a6345e2989fd06c049ac4e4627f6acb492c15b8.1613569821.git.johannes.thumshirn@wdc.com (mailing list archive)
State Accepted
Headers show
Series sd: sd_zbc: don't pass GFP_NOIO to kvcalloc | expand

Commit Message

Johannes Thumshirn Feb. 17, 2021, 1:52 p.m. UTC
Dan reported we're passing in GFP_NOIO to kvmalloc() which will then
fallback to doing kmalloc() instead of an optional vmalloc() if the size
exceeds kmalloc()s limits. This will break with drives that have zone
numbers exceeding PAGE_SIZE/sizeof(u32).

Instead of passing in GFP_NOIO, enter an implicit GFP_NOIO allocation
scope.

Link: https://lore.kernel.org/r/YCuvSfKw4qEQBr/t@mwanda
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
Cc: Damien Le Moal <Damien.LeMoal@wdc.com>
Fixes: 5795eb443060: ("scsi: sd_zbc: emulate ZONE_APPEND commands")
Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
---
 drivers/scsi/sd_zbc.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

Comments

Damien Le Moal Feb. 17, 2021, 10:58 p.m. UTC | #1
On 2021/02/17 22:52, Johannes Thumshirn wrote:
> Dan reported we're passing in GFP_NOIO to kvmalloc() which will then
> fallback to doing kmalloc() instead of an optional vmalloc() if the size
> exceeds kmalloc()s limits. This will break with drives that have zone
> numbers exceeding PAGE_SIZE/sizeof(u32).
> 
> Instead of passing in GFP_NOIO, enter an implicit GFP_NOIO allocation
> scope.
> 
> Link: https://lore.kernel.org/r/YCuvSfKw4qEQBr/t@mwanda
> Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
> Cc: Damien Le Moal <Damien.LeMoal@wdc.com>
> Fixes: 5795eb443060: ("scsi: sd_zbc: emulate ZONE_APPEND commands")
> Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
> ---
>  drivers/scsi/sd_zbc.c | 6 +++++-
>  1 file changed, 5 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/scsi/sd_zbc.c b/drivers/scsi/sd_zbc.c
> index cf07b7f93579..87a7274e4632 100644
> --- a/drivers/scsi/sd_zbc.c
> +++ b/drivers/scsi/sd_zbc.c
> @@ -688,6 +688,7 @@ int sd_zbc_revalidate_zones(struct scsi_disk *sdkp)
>  	unsigned int nr_zones = sdkp->rev_nr_zones;
>  	u32 max_append;
>  	int ret = 0;
> +	unsigned int flags;
>  
>  	/*
>  	 * For all zoned disks, initialize zone append emulation data if not
> @@ -720,16 +721,19 @@ int sd_zbc_revalidate_zones(struct scsi_disk *sdkp)
>  	    disk->queue->nr_zones == nr_zones)
>  		goto unlock;
>  
> +	flags = memalloc_noio_save();
>  	sdkp->zone_blocks = zone_blocks;
>  	sdkp->nr_zones = nr_zones;
> -	sdkp->rev_wp_offset = kvcalloc(nr_zones, sizeof(u32), GFP_NOIO);
> +	sdkp->rev_wp_offset = kvcalloc(nr_zones, sizeof(u32), GFP_KERNEL);
>  	if (!sdkp->rev_wp_offset) {
>  		ret = -ENOMEM;
> +		memalloc_noio_restore(flags);
>  		goto unlock;
>  	}
>  
>  	ret = blk_revalidate_disk_zones(disk, sd_zbc_revalidate_zones_cb);
>  
> +	memalloc_noio_restore(flags);
>  	kvfree(sdkp->rev_wp_offset);
>  	sdkp->rev_wp_offset = NULL;
>  
> 

Looks good to me.

Reviewed-by: Damien Le Moal <damien.lemoal@wdc.com>
Martin K. Petersen Feb. 23, 2021, 3:30 a.m. UTC | #2
Johannes,

> Dan reported we're passing in GFP_NOIO to kvmalloc() which will then
> fallback to doing kmalloc() instead of an optional vmalloc() if the
> size exceeds kmalloc()s limits. This will break with drives that have
> zone numbers exceeding PAGE_SIZE/sizeof(u32).
>
> Instead of passing in GFP_NOIO, enter an implicit GFP_NOIO allocation
> scope.

Applied to 5.12/scsi-staging, thanks!
Martin K. Petersen Feb. 26, 2021, 2:22 a.m. UTC | #3
On Wed, 17 Feb 2021 22:52:45 +0900, Johannes Thumshirn wrote:

> Dan reported we're passing in GFP_NOIO to kvmalloc() which will then
> fallback to doing kmalloc() instead of an optional vmalloc() if the size
> exceeds kmalloc()s limits. This will break with drives that have zone
> numbers exceeding PAGE_SIZE/sizeof(u32).
> 
> Instead of passing in GFP_NOIO, enter an implicit GFP_NOIO allocation
> scope.

Applied to 5.12/scsi-queue, thanks!

[1/1] sd: sd_zbc: don't pass GFP_NOIO to kvcalloc
      https://git.kernel.org/mkp/scsi/c/9acced3f58ad
diff mbox series

Patch

diff --git a/drivers/scsi/sd_zbc.c b/drivers/scsi/sd_zbc.c
index cf07b7f93579..87a7274e4632 100644
--- a/drivers/scsi/sd_zbc.c
+++ b/drivers/scsi/sd_zbc.c
@@ -688,6 +688,7 @@  int sd_zbc_revalidate_zones(struct scsi_disk *sdkp)
 	unsigned int nr_zones = sdkp->rev_nr_zones;
 	u32 max_append;
 	int ret = 0;
+	unsigned int flags;
 
 	/*
 	 * For all zoned disks, initialize zone append emulation data if not
@@ -720,16 +721,19 @@  int sd_zbc_revalidate_zones(struct scsi_disk *sdkp)
 	    disk->queue->nr_zones == nr_zones)
 		goto unlock;
 
+	flags = memalloc_noio_save();
 	sdkp->zone_blocks = zone_blocks;
 	sdkp->nr_zones = nr_zones;
-	sdkp->rev_wp_offset = kvcalloc(nr_zones, sizeof(u32), GFP_NOIO);
+	sdkp->rev_wp_offset = kvcalloc(nr_zones, sizeof(u32), GFP_KERNEL);
 	if (!sdkp->rev_wp_offset) {
 		ret = -ENOMEM;
+		memalloc_noio_restore(flags);
 		goto unlock;
 	}
 
 	ret = blk_revalidate_disk_zones(disk, sd_zbc_revalidate_zones_cb);
 
+	memalloc_noio_restore(flags);
 	kvfree(sdkp->rev_wp_offset);
 	sdkp->rev_wp_offset = NULL;