OSDN Git Service

Merge tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 15 Mar 2018 00:02:49 +0000 (17:02 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 15 Mar 2018 00:02:49 +0000 (17:02 -0700)
Pull SCSI fixes from James Bottomley:
 "This is four patches, consisting of one regression from the merge
  window (qla2xxx), one long-standing memory leak (sd_zbc), one event
  queue mislabelling which we want to eliminate to discourage the
  pattern (mpt3sas), and one behaviour change because re-reading the
  partition table shouldn't clear the ro flag"

* tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi:
  scsi: sd: Keep disk read-only when re-reading partition
  scsi: qla2xxx: Fix crashes in qla2x00_probe_one on probe failure
  scsi: sd_zbc: Fix potential memory leak
  scsi: mpt3sas: Do not mark fw_event workqueue as WQ_MEM_RECLAIM

1  2 
drivers/scsi/sd.c
drivers/scsi/sd_zbc.c

Simple merge
                if (sdkp->first_scan)
                        sd_printk(KERN_NOTICE, sdkp,
                                  "Zone size too large\n");
-               return -ENODEV;
+               ret = -ENODEV;
+       } else {
+               sdkp->zone_blocks = zone_blocks;
+               sdkp->zone_shift = ilog2(zone_blocks);
        }
  
-       sdkp->zone_blocks = zone_blocks;
-       sdkp->zone_shift = ilog2(zone_blocks);
+ out_free:
+       kfree(buf);
  
-       return 0;
+       return ret;
  }
  
 +/**
 + * sd_zbc_alloc_zone_bitmap - Allocate a zone bitmap (one bit per zone).
 + * @sdkp: The disk of the bitmap
 + */
 +static inline unsigned long *sd_zbc_alloc_zone_bitmap(struct scsi_disk *sdkp)
 +{
 +      struct request_queue *q = sdkp->disk->queue;
 +
 +      return kzalloc_node(BITS_TO_LONGS(sdkp->nr_zones)
 +                          * sizeof(unsigned long),
 +                          GFP_KERNEL, q->node);
 +}
 +
 +/**
 + * sd_zbc_get_seq_zones - Parse report zones reply to identify sequential zones
 + * @sdkp: disk used
 + * @buf: report reply buffer
 + * @seq_zone_bitamp: bitmap of sequential zones to set
 + *
 + * Parse reported zone descriptors in @buf to identify sequential zones and
 + * set the reported zone bit in @seq_zones_bitmap accordingly.
 + * Since read-only and offline zones cannot be written, do not
 + * mark them as sequential in the bitmap.
 + * Return the LBA after the last zone reported.
 + */
 +static sector_t sd_zbc_get_seq_zones(struct scsi_disk *sdkp, unsigned char *buf,
 +                                   unsigned int buflen,
 +                                   unsigned long *seq_zones_bitmap)
 +{
 +      sector_t lba, next_lba = sdkp->capacity;
 +      unsigned int buf_len, list_length;
 +      unsigned char *rec;
 +      u8 type, cond;
 +
 +      list_length = get_unaligned_be32(&buf[0]) + 64;
 +      buf_len = min(list_length, buflen);
 +      rec = buf + 64;
 +
 +      while (rec < buf + buf_len) {
 +              type = rec[0] & 0x0f;
 +              cond = (rec[1] >> 4) & 0xf;
 +              lba = get_unaligned_be64(&rec[16]);
 +              if (type != ZBC_ZONE_TYPE_CONV &&
 +                  cond != ZBC_ZONE_COND_READONLY &&
 +                  cond != ZBC_ZONE_COND_OFFLINE)
 +                      set_bit(lba >> sdkp->zone_shift, seq_zones_bitmap);
 +              next_lba = lba + get_unaligned_be64(&rec[8]);
 +              rec += 64;
 +      }
 +
 +      return next_lba;
 +}
 +
 +/**
 + * sd_zbc_setup_seq_zones_bitmap - Initialize the disk seq zone bitmap.
 + * @sdkp: target disk
 + *
 + * Allocate a zone bitmap and initialize it by identifying sequential zones.
 + */
 +static int sd_zbc_setup_seq_zones_bitmap(struct scsi_disk *sdkp)
 +{
 +      struct request_queue *q = sdkp->disk->queue;
 +      unsigned long *seq_zones_bitmap;
 +      sector_t lba = 0;
 +      unsigned char *buf;
 +      int ret = -ENOMEM;
 +
 +      seq_zones_bitmap = sd_zbc_alloc_zone_bitmap(sdkp);
 +      if (!seq_zones_bitmap)
 +              return -ENOMEM;
 +
 +      buf = kmalloc(SD_ZBC_BUF_SIZE, GFP_KERNEL);
 +      if (!buf)
 +              goto out;
 +
 +      while (lba < sdkp->capacity) {
 +              ret = sd_zbc_report_zones(sdkp, buf, SD_ZBC_BUF_SIZE, lba);
 +              if (ret)
 +                      goto out;
 +              lba = sd_zbc_get_seq_zones(sdkp, buf, SD_ZBC_BUF_SIZE,
 +                                         seq_zones_bitmap);
 +      }
 +
 +      if (lba != sdkp->capacity) {
 +              /* Something went wrong */
 +              ret = -EIO;
 +      }
 +
 +out:
 +      kfree(buf);
 +      if (ret) {
 +              kfree(seq_zones_bitmap);
 +              return ret;
 +      }
 +
 +      q->seq_zones_bitmap = seq_zones_bitmap;
 +
 +      return 0;
 +}
 +
 +static void sd_zbc_cleanup(struct scsi_disk *sdkp)
 +{
 +      struct request_queue *q = sdkp->disk->queue;
 +
 +      kfree(q->seq_zones_bitmap);
 +      q->seq_zones_bitmap = NULL;
 +
 +      kfree(q->seq_zones_wlock);
 +      q->seq_zones_wlock = NULL;
 +
 +      q->nr_zones = 0;
 +}
 +
  static int sd_zbc_setup(struct scsi_disk *sdkp)
  {
 +      struct request_queue *q = sdkp->disk->queue;
 +      int ret;
  
        /* READ16/WRITE16 is mandatory for ZBC disks */
        sdkp->device->use_16_for_rw = 1;