Skip to content

Commit fb4cece

Browse files
Mahesh Rajashekharamartinkpetersen
authored andcommitted
scsi: smartpqi: Fix logical volume rescan race condition
Correct rescan flag race condition. Multiple conditions are being evaluated before notifying OS to do a rescan. Driver will skip rescanning the device if any one of the following conditions are met: - Devices that have not yet been added to the OS or devices that have been removed. - Devices which are already marked for removal or in the phase of removal. Under very rare conditions, after logical volume size expansion, the OS still sees the size of the logical volume which was before expansion. The rescan flag in the driver is used to signal the need for a logical volume rescan. A race condition can occur in the driver, and it leads to one thread overwriting the flag inadvertently. As a result, driver is not notifying the OS SML to rescan the logical volume. Move device->rescan update into new function pqi_mark_volumes_for_rescan() and protect with a spin lock. Move check for device->rescan into new function pqi_volume_rescan_needed() and protect function call with a spin_lock. Reviewed-by: Scott Teel <[email protected]> Reviewed-by: Scott Benesh <[email protected]> Reviewed-by: Mike McGowen <[email protected]> Reviewed-by: Kevin Barnett <[email protected]> Co-developed-by: Murthy Bhat <[email protected]> Signed-off-by: Murthy Bhat <[email protected]> Signed-off-by: Mahesh Rajashekhara <[email protected]> Signed-off-by: Don Brace <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Martin K. Petersen <[email protected]>
1 parent c6d5aa4 commit fb4cece

File tree

2 files changed

+36
-8
lines changed

2 files changed

+36
-8
lines changed

drivers/scsi/smartpqi/smartpqi.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1347,7 +1347,6 @@ struct pqi_ctrl_info {
13471347
bool controller_online;
13481348
bool block_requests;
13491349
bool scan_blocked;
1350-
u8 logical_volume_rescan_needed : 1;
13511350
u8 inbound_spanning_supported : 1;
13521351
u8 outbound_spanning_supported : 1;
13531352
u8 pqi_mode_enabled : 1;

drivers/scsi/smartpqi/smartpqi_init.c

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2093,8 +2093,6 @@ static void pqi_scsi_update_device(struct pqi_ctrl_info *ctrl_info,
20932093
if (existing_device->devtype == TYPE_DISK) {
20942094
existing_device->raid_level = new_device->raid_level;
20952095
existing_device->volume_status = new_device->volume_status;
2096-
if (ctrl_info->logical_volume_rescan_needed)
2097-
existing_device->rescan = true;
20982096
memset(existing_device->next_bypass_group, 0, sizeof(existing_device->next_bypass_group));
20992097
if (!pqi_raid_maps_equal(existing_device->raid_map, new_device->raid_map)) {
21002098
kfree(existing_device->raid_map);
@@ -2164,6 +2162,20 @@ static inline void pqi_init_device_tmf_work(struct pqi_scsi_dev *device)
21642162
INIT_WORK(&tmf_work->work_struct, pqi_tmf_worker);
21652163
}
21662164

2165+
static inline bool pqi_volume_rescan_needed(struct pqi_scsi_dev *device)
2166+
{
2167+
if (pqi_device_in_remove(device))
2168+
return false;
2169+
2170+
if (device->sdev == NULL)
2171+
return false;
2172+
2173+
if (!scsi_device_online(device->sdev))
2174+
return false;
2175+
2176+
return device->rescan;
2177+
}
2178+
21672179
static void pqi_update_device_list(struct pqi_ctrl_info *ctrl_info,
21682180
struct pqi_scsi_dev *new_device_list[], unsigned int num_new_devices)
21692181
{
@@ -2284,9 +2296,13 @@ static void pqi_update_device_list(struct pqi_ctrl_info *ctrl_info,
22842296
if (device->sdev && device->queue_depth != device->advertised_queue_depth) {
22852297
device->advertised_queue_depth = device->queue_depth;
22862298
scsi_change_queue_depth(device->sdev, device->advertised_queue_depth);
2287-
if (device->rescan) {
2288-
scsi_rescan_device(device->sdev);
2299+
spin_lock_irqsave(&ctrl_info->scsi_device_list_lock, flags);
2300+
if (pqi_volume_rescan_needed(device)) {
22892301
device->rescan = false;
2302+
spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock, flags);
2303+
scsi_rescan_device(device->sdev);
2304+
} else {
2305+
spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock, flags);
22902306
}
22912307
}
22922308
}
@@ -2308,8 +2324,6 @@ static void pqi_update_device_list(struct pqi_ctrl_info *ctrl_info,
23082324
}
23092325
}
23102326

2311-
ctrl_info->logical_volume_rescan_needed = false;
2312-
23132327
}
23142328

23152329
static inline bool pqi_is_supported_device(struct pqi_scsi_dev *device)
@@ -3702,6 +3716,21 @@ static bool pqi_ofa_process_event(struct pqi_ctrl_info *ctrl_info,
37023716
return ack_event;
37033717
}
37043718

3719+
static void pqi_mark_volumes_for_rescan(struct pqi_ctrl_info *ctrl_info)
3720+
{
3721+
unsigned long flags;
3722+
struct pqi_scsi_dev *device;
3723+
3724+
spin_lock_irqsave(&ctrl_info->scsi_device_list_lock, flags);
3725+
3726+
list_for_each_entry(device, &ctrl_info->scsi_device_list, scsi_device_list_entry) {
3727+
if (pqi_is_logical_device(device) && device->devtype == TYPE_DISK)
3728+
device->rescan = true;
3729+
}
3730+
3731+
spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock, flags);
3732+
}
3733+
37053734
static void pqi_disable_raid_bypass(struct pqi_ctrl_info *ctrl_info)
37063735
{
37073736
unsigned long flags;
@@ -3742,7 +3771,7 @@ static void pqi_event_worker(struct work_struct *work)
37423771
ack_event = true;
37433772
rescan_needed = true;
37443773
if (event->event_type == PQI_EVENT_TYPE_LOGICAL_DEVICE)
3745-
ctrl_info->logical_volume_rescan_needed = true;
3774+
pqi_mark_volumes_for_rescan(ctrl_info);
37463775
else if (event->event_type == PQI_EVENT_TYPE_AIO_STATE_CHANGE)
37473776
pqi_disable_raid_bypass(ctrl_info);
37483777
}

0 commit comments

Comments
 (0)