diff options
Diffstat (limited to 'drivers/scsi/sd.c')
-rw-r--r-- | drivers/scsi/sd.c | 67 |
1 files changed, 30 insertions, 37 deletions
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index cea625906440..2710a0e5ae6d 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1465,13 +1465,12 @@ static int sd_getgeo(struct block_device *bdev, struct hd_geometry *geo) * Note: most ioctls are forward onto the block subsystem or further * down in the scsi subsystem. **/ -static int sd_ioctl(struct block_device *bdev, fmode_t mode, - unsigned int cmd, unsigned long arg) +static int sd_ioctl_common(struct block_device *bdev, fmode_t mode, + unsigned int cmd, void __user *p) { struct gendisk *disk = bdev->bd_disk; struct scsi_disk *sdkp = scsi_disk(disk); struct scsi_device *sdp = sdkp->device; - void __user *p = (void __user *)arg; int error; SCSI_LOG_IOCTL(1, sd_printk(KERN_INFO, sdkp, "sd_ioctl: disk=%s, " @@ -1507,9 +1506,6 @@ static int sd_ioctl(struct block_device *bdev, fmode_t mode, break; default: error = scsi_cmd_blk_ioctl(bdev, mode, cmd, p); - if (error != -ENOTTY) - break; - error = scsi_ioctl(sdp, cmd, p); break; } out: @@ -1691,39 +1687,31 @@ static void sd_rescan(struct device *dev) revalidate_disk(sdkp->disk); } +static int sd_ioctl(struct block_device *bdev, fmode_t mode, + unsigned int cmd, unsigned long arg) +{ + void __user *p = (void __user *)arg; + int ret; + + ret = sd_ioctl_common(bdev, mode, cmd, p); + if (ret != -ENOTTY) + return ret; + + return scsi_ioctl(scsi_disk(bdev->bd_disk)->device, cmd, p); +} #ifdef CONFIG_COMPAT -/* - * This gets directly called from VFS. When the ioctl - * is not recognized we go back to the other translation paths. - */ static int sd_compat_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg) { - struct gendisk *disk = bdev->bd_disk; - struct scsi_disk *sdkp = scsi_disk(disk); - struct scsi_device *sdev = sdkp->device; void __user *p = compat_ptr(arg); - int error; - - error = scsi_verify_blk_ioctl(bdev, cmd); - if (error < 0) - return error; + int ret; - error = scsi_ioctl_block_when_processing_errors(sdev, cmd, - (mode & FMODE_NDELAY) != 0); - if (error) - return error; + ret = sd_ioctl_common(bdev, mode, cmd, p); + if (ret != -ENOTTY) + return ret; - if (is_sed_ioctl(cmd)) - return sed_ioctl(sdkp->opal_dev, cmd, p); - - /* - * Let the static ioctl translation table take care of it. - */ - if (!sdev->host->hostt->compat_ioctl) - return -ENOIOCTLCMD; - return sdev->host->hostt->compat_ioctl(sdev, cmd, p); + return scsi_compat_ioctl(scsi_disk(bdev->bd_disk)->device, cmd, p); } #endif @@ -2211,8 +2199,10 @@ static int sd_read_protection_type(struct scsi_disk *sdkp, unsigned char *buffer u8 type; int ret = 0; - if (scsi_device_protection(sdp) == 0 || (buffer[12] & 1) == 0) + if (scsi_device_protection(sdp) == 0 || (buffer[12] & 1) == 0) { + sdkp->protection_type = 0; return ret; + } type = ((buffer[12] >> 1) & 7) + 1; /* P_TYPE 0 = Type 1 */ @@ -2956,15 +2946,16 @@ static void sd_read_block_characteristics(struct scsi_disk *sdkp) q->limits.zoned = BLK_ZONED_HM; } else { sdkp->zoned = (buffer[8] >> 4) & 3; - if (sdkp->zoned == 1) + if (sdkp->zoned == 1 && !disk_has_partitions(sdkp->disk)) { /* Host-aware */ q->limits.zoned = BLK_ZONED_HA; - else + } else { /* - * Treat drive-managed devices as - * regular block devices. + * Treat drive-managed devices and host-aware devices + * with partitions as regular block devices. */ q->limits.zoned = BLK_ZONED_NONE; + } } if (blk_queue_is_zoned(q) && sdkp->first_scan) sd_printk(KERN_NOTICE, sdkp, "Host-%s zoned block device\n", @@ -3178,9 +3169,11 @@ static int sd_revalidate_disk(struct gendisk *disk) if (sd_validate_opt_xfer_size(sdkp, dev_max)) { q->limits.io_opt = logical_to_bytes(sdp, sdkp->opt_xfer_blocks); rw_max = logical_to_sectors(sdp, sdkp->opt_xfer_blocks); - } else + } else { + q->limits.io_opt = 0; rw_max = min_not_zero(logical_to_sectors(sdp, dev_max), (sector_t)BLK_DEF_MAX_SECTORS); + } /* Do not exceed controller limit */ rw_max = min(rw_max, queue_max_hw_sectors(q)); |