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 | |
| 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>
| -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 | }; |
