Skip to content

Commit

Permalink
[SCSI] scsi_debug: protect device access with atomic_rw lock
Browse files Browse the repository at this point in the history
This change ensures that concurrent device access including ramdisk
storage, protection info, and provisioning map by read, write, and
unmap commands are protected with atomic_rw spinlock.

Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com>
Reviewed-by: Douglas Gilbert <dgilbert@interlog.com>
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
  • Loading branch information
Akinobu Mita authored and James Bottomley committed Mar 19, 2014
1 parent be4e11b commit 6c78cc0
Showing 1 changed file with 10 additions and 2 deletions.
12 changes: 10 additions & 2 deletions drivers/scsi/scsi_debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -1888,17 +1888,19 @@ static int resp_read(struct scsi_cmnd *SCpnt, unsigned long long lba,
return check_condition_result;
}

read_lock_irqsave(&atomic_rw, iflags);

/* DIX + T10 DIF */
if (scsi_debug_dix && scsi_prot_sg_count(SCpnt)) {
int prot_ret = prot_verify_read(SCpnt, lba, num, ei_lba);

if (prot_ret) {
read_unlock_irqrestore(&atomic_rw, iflags);
mk_sense_buffer(devip, ABORTED_COMMAND, 0x10, prot_ret);
return illegal_condition_result;
}
}

read_lock_irqsave(&atomic_rw, iflags);
ret = do_device_access(SCpnt, devip, lba, num, 0);
read_unlock_irqrestore(&atomic_rw, iflags);
if (ret == -1)
Expand Down Expand Up @@ -2098,17 +2100,19 @@ static int resp_write(struct scsi_cmnd *SCpnt, unsigned long long lba,
if (ret)
return ret;

write_lock_irqsave(&atomic_rw, iflags);

/* DIX + T10 DIF */
if (scsi_debug_dix && scsi_prot_sg_count(SCpnt)) {
int prot_ret = prot_verify_write(SCpnt, lba, num, ei_lba);

if (prot_ret) {
write_unlock_irqrestore(&atomic_rw, iflags);
mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x10, prot_ret);
return illegal_condition_result;
}
}

write_lock_irqsave(&atomic_rw, iflags);
ret = do_device_access(SCpnt, devip, lba, num, 1);
if (scsi_debug_lbp())
map_region(lba, num);
Expand Down Expand Up @@ -2187,6 +2191,7 @@ static int resp_unmap(struct scsi_cmnd * scmd, struct sdebug_dev_info * devip)
struct unmap_block_desc *desc;
unsigned int i, payload_len, descriptors;
int ret;
unsigned long iflags;

ret = check_readiness(scmd, 1, devip);
if (ret)
Expand All @@ -2208,6 +2213,8 @@ static int resp_unmap(struct scsi_cmnd * scmd, struct sdebug_dev_info * devip)

desc = (void *)&buf[8];

write_lock_irqsave(&atomic_rw, iflags);

for (i = 0 ; i < descriptors ; i++) {
unsigned long long lba = get_unaligned_be64(&desc[i].lba);
unsigned int num = get_unaligned_be32(&desc[i].blocks);
Expand All @@ -2222,6 +2229,7 @@ static int resp_unmap(struct scsi_cmnd * scmd, struct sdebug_dev_info * devip)
ret = 0;

out:
write_unlock_irqrestore(&atomic_rw, iflags);
kfree(buf);

return ret;
Expand Down

0 comments on commit 6c78cc0

Please sign in to comment.