static struct scsi_disk *__scsi_disk_get(struct gendisk *disk) { struct scsi_disk *sdkp = NULL; if (disk->private_data) { sdkp = scsi_disk(disk); if (scsi_device_get(sdkp->device) == 0) kref_get(&sdkp->kref); else sdkp = NULL; } return sdkp; }
/** * scsi_setup_discard_cmnd - unmap blocks on thinly provisioned device * @sdp: scsi device to operate one * @rq: Request to prepare * * Will issue either UNMAP or WRITE SAME(16) depending on preference * indicated by target device. **/ static int scsi_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq) { struct scsi_disk *sdkp = scsi_disk(rq->rq_disk); struct bio *bio = rq->bio; sector_t sector = bio->bi_sector; unsigned int nr_sectors = bio_sectors(bio); unsigned int len; int ret; char *buf; struct page *page; if (sdkp->device->sector_size == 4096) { sec
static void sd_zbc_report_zones_complete(struct scsi_cmnd *scmd, unsigned int good_bytes) { struct request *rq = scmd->request; struct scsi_disk *sdkp = scsi_disk(rq->rq_disk); struct sg_mapping_iter miter; struct blk_zone_report_hdr hdr; struct blk_zone zone; unsigned int offset, bytes = 0; unsigned long flags; u8 *buf; if (good_bytes < 64) return; memset(&hdr, 0, sizeof(struct blk_zone_report_hdr)); sg_miter_start(&miter, scsi_sglist(scmd), scsi_sg_count(scmd), SG_MITER_TO_SG | SG_MITER_ATOMIC); local_irq_save(flags); while (sg_miter_next(&miter) && bytes < good_bytes) { buf = miter.addr; offset = 0; if (bytes == 0) { /* Set the report header */ hdr.nr_zones = min_t(unsigned int, (good_bytes - 64) / 64, get_unaligned_be32(&buf[0]) / 64); memcpy(buf, &hdr, sizeof(struct blk_zone_report_hdr)); offset += 64; bytes += 64; } /* Parse zone descriptors */ while (offset < miter.length && hdr.nr_zones) { WARN_ON(offset > miter.length); buf = miter.addr + offset; sd_zbc_parse_report(sdkp, buf, &zone); memcpy(buf, &zone, sizeof(struct blk_zone)); offset += 64; bytes += 64; hdr.nr_zones--; } if (!hdr.nr_zones) break; }
/* There are so many devices that report the capacity incorrectly, * this routine was written to counteract some of the resulting * problems. */ static void last_sector_hacks(struct us_data *us, struct scsi_cmnd *srb) { struct gendisk *disk; struct scsi_disk *sdkp; u32 sector; static unsigned char record_not_found[18] = { [0] = 0x70, [2] = MEDIUM_ERROR, [7] = 0x0a, [12] = 0x14 }; if (!us->use_last_sector_hacks) return; if (srb->cmnd[0] != READ_10 && srb->cmnd[0] != WRITE_10) goto done; sector = (srb->cmnd[2] << 24) | (srb->cmnd[3] << 16) | (srb->cmnd[4] << 8) | (srb->cmnd[5]); disk = srb->request->rq_disk; if (!disk) goto done; sdkp = scsi_disk(disk); if (!sdkp) goto done; if (sector + 1 != sdkp->capacity) goto done; if (srb->result == SAM_STAT_GOOD && scsi_get_resid(srb) == 0) { us->use_last_sector_hacks = 0; } else { if (++us->last_sector_retries < 3) return; srb->result = SAM_STAT_CHECK_CONDITION; memcpy(srb->sense_buffer, record_not_found, sizeof(record_not_found)); } done: if (srb->cmnd[0] != TEST_UNIT_READY) us->last_sector_retries = 0; }
int sd_zbc_setup_report_cmnd(struct scsi_cmnd *cmd) { struct request *rq = cmd->request; struct scsi_disk *sdkp = scsi_disk(rq->rq_disk); sector_t lba, sector = blk_rq_pos(rq); unsigned int nr_bytes = blk_rq_bytes(rq); int ret; WARN_ON(nr_bytes == 0); if (!sd_is_zoned(sdkp)) /* Not a zoned device */ return BLKPREP_KILL; ret = scsi_init_io(cmd); if (ret != BLKPREP_OK) return ret; cmd->cmd_len = 16; memset(cmd->cmnd, 0, cmd->cmd_len); cmd->cmnd[0] = ZBC_IN; cmd->cmnd[1] = ZI_REPORT_ZONES; lba = sectors_to_logical(sdkp->device, sector); put_unaligned_be64(lba, &cmd->cmnd[2]); put_unaligned_be32(nr_bytes, &cmd->cmnd[10]); /* Do partial report for speeding things up */ cmd->cmnd[14] = ZBC_REPORT_ZONE_PARTIAL; cmd->sc_data_direction = DMA_FROM_DEVICE; cmd->sdb.length = nr_bytes; cmd->transfersize = sdkp->device->sector_size; cmd->allowed = 0; /* * Report may return less bytes than requested. Make sure * to report completion on the entire initial request. */ rq->__data_len = nr_bytes; return BLKPREP_OK; }
static struct scsi_disk *scsi_disk_get(struct gendisk *disk) { struct scsi_disk *sdkp = NULL; down(&sd_ref_sem); if (disk->private_data == NULL) goto out; sdkp = scsi_disk(disk); kref_get(&sdkp->kref); if (scsi_device_get(sdkp->device)) goto out_put; up(&sd_ref_sem); return sdkp; out_put: kref_put(&sdkp->kref, scsi_disk_release); sdkp = NULL; out: up(&sd_ref_sem); return sdkp; }
/* There are so many devices that report the capacity incorrectly, * this routine was written to counteract some of the resulting * problems. */ static void last_sector_hacks(struct us_data *us, struct scsi_cmnd *srb) { struct gendisk *disk; struct scsi_disk *sdkp; u32 sector; /* To Report "Medium Error: Record Not Found */ static unsigned char record_not_found[18] = { [0] = 0x70, /* current error */ [2] = MEDIUM_ERROR, /* = 0x03 */ [7] = 0x0a, /* additional length */ [12] = 0x14 /* Record Not Found */ }; /* If last-sector problems can't occur, whether because the * capacity was already decremented or because the device is * known to report the correct capacity, then we don't need * to do anything. */ if (!us->use_last_sector_hacks) return; /* Was this command a READ(10) or a WRITE(10)? */ if (srb->cmnd[0] != READ_10 && srb->cmnd[0] != WRITE_10) goto done; /* Did this command access the last sector? */ sector = (srb->cmnd[2] << 24) | (srb->cmnd[3] << 16) | (srb->cmnd[4] << 8) | (srb->cmnd[5]); disk = srb->request->rq_disk; if (!disk) goto done; sdkp = scsi_disk(disk); if (!sdkp) goto done; if (sector + 1 != sdkp->capacity) goto done; if (srb->result == SAM_STAT_GOOD && scsi_get_resid(srb) == 0) { /* The command succeeded. We know this device doesn't * have the last-sector bug, so stop checking it. */ us->use_last_sector_hacks = 0; } else { /* The command failed. Allow up to 3 retries in case this * is some normal sort of failure. After that, assume the * capacity is wrong and we're trying to access the sector * beyond the end. Replace the result code and sense data * with values that will cause the SCSI core to fail the * command immediately, instead of going into an infinite * (or even just a very long) retry loop. */ if (++us->last_sector_retries < 3) return; srb->result = SAM_STAT_CHECK_CONDITION; memcpy(srb->sense_buffer, record_not_found, sizeof(record_not_found)); } done: /* Don't reset the retry counter for TEST UNIT READY commands, * because they get issued after device resets which might be * caused by a failed last-sector access. */ if (srb->cmnd[0] != TEST_UNIT_READY) us->last_sector_retries = 0; }