diff options
author | Stefan Haberland <stefan.haberland@de.ibm.com> | 2015-12-15 04:45:05 -0500 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2016-02-11 07:05:55 -0500 |
commit | 9d862ababb609439c5d6987f6d3ddd09e703aa0b (patch) | |
tree | 5198aca73de28bec2bafc07ee718de557b31fb7e /drivers/s390 | |
parent | 020bf042e5b397479c1174081b935d0ff15d1a64 (diff) |
s390/dasd: fix refcount for PAV reassignment
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.
Cc: stable@vger.kernel.org
Signed-off-by: Stefan Haberland <stefan.haberland@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390')
-rw-r--r-- | drivers/s390/block/dasd_alias.c | 21 |
1 files changed, 16 insertions, 5 deletions
diff --git a/drivers/s390/block/dasd_alias.c b/drivers/s390/block/dasd_alias.c index 4ff914c0f13c..286782c60da4 100644 --- a/drivers/s390/block/dasd_alias.c +++ b/drivers/s390/block/dasd_alias.c | |||
@@ -264,8 +264,10 @@ void dasd_alias_disconnect_device_from_lcu(struct dasd_device *device) | |||
264 | spin_unlock_irqrestore(&lcu->lock, flags); | 264 | spin_unlock_irqrestore(&lcu->lock, flags); |
265 | cancel_work_sync(&lcu->suc_data.worker); | 265 | cancel_work_sync(&lcu->suc_data.worker); |
266 | spin_lock_irqsave(&lcu->lock, flags); | 266 | spin_lock_irqsave(&lcu->lock, flags); |
267 | if (device == lcu->suc_data.device) | 267 | if (device == lcu->suc_data.device) { |
268 | dasd_put_device(device); | ||
268 | lcu->suc_data.device = NULL; | 269 | lcu->suc_data.device = NULL; |
270 | } | ||
269 | } | 271 | } |
270 | was_pending = 0; | 272 | was_pending = 0; |
271 | if (device == lcu->ruac_data.device) { | 273 | if (device == lcu->ruac_data.device) { |
@@ -273,8 +275,10 @@ void dasd_alias_disconnect_device_from_lcu(struct dasd_device *device) | |||
273 | was_pending = 1; | 275 | was_pending = 1; |
274 | cancel_delayed_work_sync(&lcu->ruac_data.dwork); | 276 | cancel_delayed_work_sync(&lcu->ruac_data.dwork); |
275 | spin_lock_irqsave(&lcu->lock, flags); | 277 | spin_lock_irqsave(&lcu->lock, flags); |
276 | if (device == lcu->ruac_data.device) | 278 | if (device == lcu->ruac_data.device) { |
279 | dasd_put_device(device); | ||
277 | lcu->ruac_data.device = NULL; | 280 | lcu->ruac_data.device = NULL; |
281 | } | ||
278 | } | 282 | } |
279 | private->lcu = NULL; | 283 | private->lcu = NULL; |
280 | spin_unlock_irqrestore(&lcu->lock, flags); | 284 | spin_unlock_irqrestore(&lcu->lock, flags); |
@@ -549,8 +553,10 @@ static void lcu_update_work(struct work_struct *work) | |||
549 | if ((rc && (rc != -EOPNOTSUPP)) || (lcu->flags & NEED_UAC_UPDATE)) { | 553 | if ((rc && (rc != -EOPNOTSUPP)) || (lcu->flags & NEED_UAC_UPDATE)) { |
550 | DBF_DEV_EVENT(DBF_WARNING, device, "could not update" | 554 | DBF_DEV_EVENT(DBF_WARNING, device, "could not update" |
551 | " alias data in lcu (rc = %d), retry later", rc); | 555 | " alias data in lcu (rc = %d), retry later", rc); |
552 | schedule_delayed_work(&lcu->ruac_data.dwork, 30*HZ); | 556 | if (!schedule_delayed_work(&lcu->ruac_data.dwork, 30*HZ)) |
557 | dasd_put_device(device); | ||
553 | } else { | 558 | } else { |
559 | dasd_put_device(device); | ||
554 | lcu->ruac_data.device = NULL; | 560 | lcu->ruac_data.device = NULL; |
555 | lcu->flags &= ~UPDATE_PENDING; | 561 | lcu->flags &= ~UPDATE_PENDING; |
556 | } | 562 | } |
@@ -593,8 +599,10 @@ static int _schedule_lcu_update(struct alias_lcu *lcu, | |||
593 | */ | 599 | */ |
594 | if (!usedev) | 600 | if (!usedev) |
595 | return -EINVAL; | 601 | return -EINVAL; |
602 | dasd_get_device(usedev); | ||
596 | lcu->ruac_data.device = usedev; | 603 | lcu->ruac_data.device = usedev; |
597 | schedule_delayed_work(&lcu->ruac_data.dwork, 0); | 604 | if (!schedule_delayed_work(&lcu->ruac_data.dwork, 0)) |
605 | dasd_put_device(usedev); | ||
598 | return 0; | 606 | return 0; |
599 | } | 607 | } |
600 | 608 | ||
@@ -930,6 +938,7 @@ static void summary_unit_check_handling_work(struct work_struct *work) | |||
930 | /* 3. read new alias configuration */ | 938 | /* 3. read new alias configuration */ |
931 | _schedule_lcu_update(lcu, device); | 939 | _schedule_lcu_update(lcu, device); |
932 | lcu->suc_data.device = NULL; | 940 | lcu->suc_data.device = NULL; |
941 | dasd_put_device(device); | ||
933 | spin_unlock_irqrestore(&lcu->lock, flags); | 942 | spin_unlock_irqrestore(&lcu->lock, flags); |
934 | } | 943 | } |
935 | 944 | ||
@@ -989,6 +998,8 @@ void dasd_alias_handle_summary_unit_check(struct dasd_device *device, | |||
989 | } | 998 | } |
990 | lcu->suc_data.reason = reason; | 999 | lcu->suc_data.reason = reason; |
991 | lcu->suc_data.device = device; | 1000 | lcu->suc_data.device = device; |
1001 | dasd_get_device(device); | ||
992 | spin_unlock(&lcu->lock); | 1002 | spin_unlock(&lcu->lock); |
993 | schedule_work(&lcu->suc_data.worker); | 1003 | if (!schedule_work(&lcu->suc_data.worker)) |
1004 | dasd_put_device(device); | ||
994 | }; | 1005 | }; |