Commit 052db2fe authored by Stefan Haberland's avatar Stefan Haberland Committed by Jiri Slaby

s390/dasd: fix refcount for PAV reassignment

commit 9d862aba upstream.

Add refcount to the DASD device when a summary unit check worker is
scheduled. This prevents that the device is set offline with worker
in place.
Signed-off-by: default avatarStefan Haberland <stefan.haberland@de.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: default avatarJiri Slaby <jslaby@suse.cz>
parent 4c3ada65
...@@ -264,8 +264,10 @@ void dasd_alias_disconnect_device_from_lcu(struct dasd_device *device) ...@@ -264,8 +264,10 @@ void dasd_alias_disconnect_device_from_lcu(struct dasd_device *device)
spin_unlock_irqrestore(&lcu->lock, flags); spin_unlock_irqrestore(&lcu->lock, flags);
cancel_work_sync(&lcu->suc_data.worker); cancel_work_sync(&lcu->suc_data.worker);
spin_lock_irqsave(&lcu->lock, flags); spin_lock_irqsave(&lcu->lock, flags);
if (device == lcu->suc_data.device) if (device == lcu->suc_data.device) {
dasd_put_device(device);
lcu->suc_data.device = NULL; lcu->suc_data.device = NULL;
}
} }
was_pending = 0; was_pending = 0;
if (device == lcu->ruac_data.device) { if (device == lcu->ruac_data.device) {
...@@ -273,8 +275,10 @@ void dasd_alias_disconnect_device_from_lcu(struct dasd_device *device) ...@@ -273,8 +275,10 @@ void dasd_alias_disconnect_device_from_lcu(struct dasd_device *device)
was_pending = 1; was_pending = 1;
cancel_delayed_work_sync(&lcu->ruac_data.dwork); cancel_delayed_work_sync(&lcu->ruac_data.dwork);
spin_lock_irqsave(&lcu->lock, flags); spin_lock_irqsave(&lcu->lock, flags);
if (device == lcu->ruac_data.device) if (device == lcu->ruac_data.device) {
dasd_put_device(device);
lcu->ruac_data.device = NULL; lcu->ruac_data.device = NULL;
}
} }
private->lcu = NULL; private->lcu = NULL;
spin_unlock_irqrestore(&lcu->lock, flags); spin_unlock_irqrestore(&lcu->lock, flags);
...@@ -549,8 +553,10 @@ static void lcu_update_work(struct work_struct *work) ...@@ -549,8 +553,10 @@ static void lcu_update_work(struct work_struct *work)
if ((rc && (rc != -EOPNOTSUPP)) || (lcu->flags & NEED_UAC_UPDATE)) { if ((rc && (rc != -EOPNOTSUPP)) || (lcu->flags & NEED_UAC_UPDATE)) {
DBF_DEV_EVENT(DBF_WARNING, device, "could not update" DBF_DEV_EVENT(DBF_WARNING, device, "could not update"
" alias data in lcu (rc = %d), retry later", rc); " alias data in lcu (rc = %d), retry later", rc);
schedule_delayed_work(&lcu->ruac_data.dwork, 30*HZ); if (!schedule_delayed_work(&lcu->ruac_data.dwork, 30*HZ))
dasd_put_device(device);
} else { } else {
dasd_put_device(device);
lcu->ruac_data.device = NULL; lcu->ruac_data.device = NULL;
lcu->flags &= ~UPDATE_PENDING; lcu->flags &= ~UPDATE_PENDING;
} }
...@@ -593,8 +599,10 @@ static int _schedule_lcu_update(struct alias_lcu *lcu, ...@@ -593,8 +599,10 @@ static int _schedule_lcu_update(struct alias_lcu *lcu,
*/ */
if (!usedev) if (!usedev)
return -EINVAL; return -EINVAL;
dasd_get_device(usedev);
lcu->ruac_data.device = usedev; lcu->ruac_data.device = usedev;
schedule_delayed_work(&lcu->ruac_data.dwork, 0); if (!schedule_delayed_work(&lcu->ruac_data.dwork, 0))
dasd_put_device(usedev);
return 0; return 0;
} }
...@@ -926,6 +934,7 @@ static void summary_unit_check_handling_work(struct work_struct *work) ...@@ -926,6 +934,7 @@ static void summary_unit_check_handling_work(struct work_struct *work)
/* 3. read new alias configuration */ /* 3. read new alias configuration */
_schedule_lcu_update(lcu, device); _schedule_lcu_update(lcu, device);
lcu->suc_data.device = NULL; lcu->suc_data.device = NULL;
dasd_put_device(device);
spin_unlock_irqrestore(&lcu->lock, flags); spin_unlock_irqrestore(&lcu->lock, flags);
} }
...@@ -985,6 +994,8 @@ void dasd_alias_handle_summary_unit_check(struct dasd_device *device, ...@@ -985,6 +994,8 @@ void dasd_alias_handle_summary_unit_check(struct dasd_device *device,
} }
lcu->suc_data.reason = reason; lcu->suc_data.reason = reason;
lcu->suc_data.device = device; lcu->suc_data.device = device;
dasd_get_device(device);
spin_unlock(&lcu->lock); spin_unlock(&lcu->lock);
schedule_work(&lcu->suc_data.worker); if (!schedule_work(&lcu->suc_data.worker))
dasd_put_device(device);
}; };
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment