summaryrefslogtreecommitdiff
path: root/drivers/scsi/scsi_lib.c
diff options
context:
space:
mode:
authorBart Van Assche <bart.vanassche@wdc.com>2017-08-29 18:50:13 +0300
committerMartin K. Petersen <martin.petersen@oracle.com>2017-08-30 04:51:42 +0300
commitccf1e0045eea8f98d60fc9327bcb14c958d2e4c7 (patch)
treebc32bc41b24ce324d06deec7528c3310db49ddcd /drivers/scsi/scsi_lib.c
parent1e3f720a67c29e145321ed9b4ef7a83e6416d201 (diff)
downloadlinux-ccf1e0045eea8f98d60fc9327bcb14c958d2e4c7.tar.xz
scsi: Rework handling of scsi_device.vpd_pg8[03]
Introduce struct scsi_vpd for the VPD page length, data and the RCU head that will be used to free the VPD data. Use kfree_rcu() instead of kfree() to free VPD data. Move the VPD buffer pointer check inside the RCU read lock in the sysfs code. Only annotate pointers that are shared across threads with __rcu. Use rcu_dereference() when dereferencing an RCU pointer. This patch suppresses about twenty sparse complaints about the vpd_pg8[03] pointers. This patch also fixes a race condition, namely that updating of the VPD pointers and length variables in struct scsi_device was not atomic with reference to the code reading these variables. See also "Does the update code tolerate concurrent accesses?" in Documentation/RCU/checklist.txt. Fixes: commit 09e2b0b14690 ("scsi: rescan VPD attributes") Signed-off-by: Bart Van Assche <bart.vanassche@wdc.com> Acked-by: Hannes Reinecke <hare@suse.de> Reviewed-by: Shane Seymour <shane.seymour@hpe.com> Cc: Christoph Hellwig <hch@lst.de> Cc: Johannes Thumshirn <jthumshirn@suse.de> Cc: Shane Seymour <shane.seymour@hpe.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi/scsi_lib.c')
-rw-r--r--drivers/scsi/scsi_lib.c16
1 files changed, 8 insertions, 8 deletions
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 696d2eae0ba6..938a7e398cd4 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -3272,8 +3272,8 @@ int scsi_vpd_lun_id(struct scsi_device *sdev, char *id, size_t id_len)
{
u8 cur_id_type = 0xff;
u8 cur_id_size = 0;
- unsigned char *d, *cur_id_str;
- unsigned char __rcu *vpd_pg83;
+ const unsigned char *d, *cur_id_str;
+ const struct scsi_vpd *vpd_pg83;
int id_size = -EINVAL;
rcu_read_lock();
@@ -3304,8 +3304,8 @@ int scsi_vpd_lun_id(struct scsi_device *sdev, char *id, size_t id_len)
}
memset(id, 0, id_len);
- d = vpd_pg83 + 4;
- while (d < vpd_pg83 + sdev->vpd_pg83_len) {
+ d = vpd_pg83->data + 4;
+ while (d < vpd_pg83->data + vpd_pg83->len) {
/* Skip designators not referring to the LUN */
if ((d[1] & 0x30) != 0x00)
goto next_desig;
@@ -3421,8 +3421,8 @@ EXPORT_SYMBOL(scsi_vpd_lun_id);
*/
int scsi_vpd_tpg_id(struct scsi_device *sdev, int *rel_id)
{
- unsigned char *d;
- unsigned char __rcu *vpd_pg83;
+ const unsigned char *d;
+ const struct scsi_vpd *vpd_pg83;
int group_id = -EAGAIN, rel_port = -1;
rcu_read_lock();
@@ -3432,8 +3432,8 @@ int scsi_vpd_tpg_id(struct scsi_device *sdev, int *rel_id)
return -ENXIO;
}
- d = sdev->vpd_pg83 + 4;
- while (d < sdev->vpd_pg83 + sdev->vpd_pg83_len) {
+ d = vpd_pg83->data + 4;
+ while (d < vpd_pg83->data + vpd_pg83->len) {
switch (d[1] & 0xf) {
case 0x4:
/* Relative target port */