Re: [PATCH 1/5] sd: configure ZBC devices

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, Jul 19, 2016 at 8:25 AM, Hannes Reinecke <hare@xxxxxxx> wrote:
> For ZBC devices I/O must not cross zone boundaries, so setup
> the 'chunk_sectors' block queue setting to the zone size.
> This is only valid for REPORT ZONES SAME type 2 or 3;
> for other types the zone sizes might be different
> for individual zones. So issue a warning if the type is
> found to be different.
> Also the capacity might be different from the announced
> capacity, so adjust it as needed.
>
> Signed-off-by: Hannes Reinecke <hare@xxxxxxxx>
> ---
>  drivers/scsi/sd.c         | 120 ++++++++++++++++++++++++++++++++++++++++++++--
>  drivers/scsi/sd.h         |  12 +++++
>  include/scsi/scsi_proto.h |  17 +++++++
>  3 files changed, 144 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
> index 428c03e..249ea81 100644
> --- a/drivers/scsi/sd.c
> +++ b/drivers/scsi/sd.c
> @@ -1972,6 +1972,57 @@ sd_spinup_disk(struct scsi_disk *sdkp)
>         }
>  }
>
> +/**
> + * sd_zbc_report_zones - Issue a REPORT ZONES scsi command
> + * @sdkp: SCSI disk to which the command should be send
> + * @buffer: response buffer
> + * @bufflen: length of @buffer
> + * @start_sector: logical sector for the zone information should be reported
> + * @option: option for report zones command
> + * @partial: flag to set 'partial' bit for report zones command
> + */
> +static int
> +sd_zbc_report_zones(struct scsi_disk *sdkp, unsigned char *buffer,
> +                   int bufflen, sector_t start_sector,
> +                   enum zbc_zone_reporting_options option, bool partial)
> +{
> +       struct scsi_device *sdp = sdkp->device;
> +       const int timeout = sdp->request_queue->rq_timeout
> +               * SD_FLUSH_TIMEOUT_MULTIPLIER;
> +       struct scsi_sense_hdr sshdr;
> +       sector_t start_lba = sectors_to_logical(sdkp->device, start_sector);
> +       unsigned char cmd[16];
> +       int result;
> +
> +       if (!scsi_device_online(sdp)) {
> +               sd_printk(KERN_INFO, sdkp, "device not online\n");
> +               return -ENODEV;
> +       }
> +
> +       sd_printk(KERN_INFO, sdkp, "REPORT ZONES lba %zu len %d\n",
> +                 start_lba, bufflen);
> +
> +       memset(cmd, 0, 16);
> +       cmd[0] = ZBC_IN;
> +       cmd[1] = ZI_REPORT_ZONES;
> +       put_unaligned_be64(start_lba, &cmd[2]);
> +       put_unaligned_be32(bufflen, &cmd[10]);
> +       cmd[14] = (partial ? ZBC_REPORT_ZONE_PARTIAL : 0) | option;
> +       memset(buffer, 0, bufflen);
> +
> +       result = scsi_execute_req(sdp, cmd, DMA_FROM_DEVICE,
> +                                 buffer, bufflen, &sshdr,
> +                                 timeout, SD_MAX_RETRIES, NULL);
> +
> +       if (result) {
> +               sd_printk(KERN_NOTICE, sdkp,
> +                         "REPORT ZONES lba %zu failed with %d/%d\n",
> +                         start_lba, host_byte(result), driver_byte(result));
> +
> +               return -EIO;
> +       }
> +       return 0;
> +}
>
>  /*
>   * Determine whether disk supports Data Integrity Field.
> @@ -2014,6 +2065,59 @@ static int sd_read_protection_type(struct scsi_disk *sdkp, unsigned char *buffer
>         return ret;
>  }
>
> +static void sd_read_zones(struct scsi_disk *sdkp, unsigned char *buffer)
> +{
> +       int retval;
> +       unsigned char *desc;
> +       u32 rep_len;
> +       u8 same;
> +       u64 zone_len, lba;
> +
> +       if (sdkp->zoned != 1)
> +               /* Device managed, no special handling required */
> +               return;
> +
> +       retval = sd_zbc_report_zones(sdkp, buffer, SD_BUF_SIZE,
> +                                    0, ZBC_ZONE_REPORTING_OPTION_ALL, false);
> +       if (retval < 0)
> +               return;
> +
> +       rep_len = get_unaligned_be32(&buffer[0]);
> +       if (rep_len < 64) {
> +               sd_printk(KERN_WARNING, sdkp,
> +                         "REPORT ZONES report invalid length %u\n",
> +                         rep_len);
> +               return;
> +       }
> +
> +       if (sdkp->rc_basis == 0) {
> +               /* The max_lba field is the capacity of a zoned device */
> +               lba = get_unaligned_be64(&buffer[8]);
> +               if (lba + 1 > sdkp->capacity) {
> +                       sd_printk(KERN_WARNING, sdkp,
> +                                 "Max LBA %zu (capacity %zu)\n",
> +                                 (sector_t) lba + 1, sdkp->capacity);
> +                       sdkp->capacity = lba + 1;
> +               }
> +       }
> +
> +       /*
> +        * Adjust 'chunk_sectors' to the zone length if the device
> +        * supports equal zone sizes.
> +        */
> +       same = buffer[4] & 0xf;
> +       if (same == 0 || same > 3) {
> +               sd_printk(KERN_WARNING, sdkp,
> +                         "REPORT ZONES SAME type %d not supported\n", same);
> +               return;
> +       }

It's a bit unfortunate that you abort here. The current Seagate Host
Aware drives
must report a same code of 0 here due to the final 'runt' zone and are therefore
not supported by your RB-Tree in the following patches.

> +       /* Read the zone length from the first zone descriptor */
> +       desc = &buffer[64];
> +       zone_len = logical_to_sectors(sdkp->device,
> +                                     get_unaligned_be64(&desc[8]));
> +       blk_queue_chunk_sectors(sdkp->disk->queue, zone_len);
> +}
> +
>  static void read_capacity_error(struct scsi_disk *sdkp, struct scsi_device *sdp,
>                         struct scsi_sense_hdr *sshdr, int sense_valid,
>                         int the_result)

-- 
Shaun Tancheff
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]
  Powered by Linux