diff options
author | Hannes Reinecke <hare@suse.de> | 2015-11-09 13:24:28 +0100 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2015-11-30 11:23:45 -0500 |
commit | 09e2b0b14690fb13ccfc04af49f156df3e25b152 (patch) | |
tree | 4643ba86b1896df0b6a119416f31db4d4da0851b /drivers/scsi/scsi.c | |
parent | fe0798c5e150be8f06959250076d3864477e74c2 (diff) | |
download | linux-09e2b0b14690fb13ccfc04af49f156df3e25b152.tar.bz2 |
scsi: rescan VPD attributes
The VPD page information might change, so we need to be able to update
it. This patch implements a VPD page rescan whenever the 'rescan' sysfs
attribute is triggered.
Signed-off-by: Hannes Reinecke <hare@suse.de>
Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Reviewed-by: Shane Seymour <shane.seymour@hpe.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi/scsi.c')
-rw-r--r-- | drivers/scsi/scsi.c | 20 |
1 files changed, 17 insertions, 3 deletions
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index d07fb653f5dc..b1bf42b93fcc 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -782,7 +782,7 @@ void scsi_attach_vpd(struct scsi_device *sdev) int vpd_len = SCSI_VPD_PG_LEN; int pg80_supported = 0; int pg83_supported = 0; - unsigned char *vpd_buf; + unsigned char __rcu *vpd_buf, *orig_vpd_buf = NULL; if (sdev->skip_vpd_pages) return; @@ -828,8 +828,16 @@ retry_pg80: kfree(vpd_buf); goto retry_pg80; } + mutex_lock(&sdev->inquiry_mutex); + orig_vpd_buf = sdev->vpd_pg80; sdev->vpd_pg80_len = result; - sdev->vpd_pg80 = vpd_buf; + rcu_assign_pointer(sdev->vpd_pg80, vpd_buf); + mutex_unlock(&sdev->inquiry_mutex); + synchronize_rcu(); + if (orig_vpd_buf) { + kfree(orig_vpd_buf); + orig_vpd_buf = NULL; + } vpd_len = SCSI_VPD_PG_LEN; } @@ -849,8 +857,14 @@ retry_pg83: kfree(vpd_buf); goto retry_pg83; } + mutex_lock(&sdev->inquiry_mutex); + orig_vpd_buf = sdev->vpd_pg83; sdev->vpd_pg83_len = result; - sdev->vpd_pg83 = vpd_buf; + rcu_assign_pointer(sdev->vpd_pg83, vpd_buf); + mutex_unlock(&sdev->inquiry_mutex); + synchronize_rcu(); + if (orig_vpd_buf) + kfree(orig_vpd_buf); } } |