diff options
Diffstat (limited to 'drivers/s390/block/dasd.c')
-rw-r--r-- | drivers/s390/block/dasd.c | 51 |
1 files changed, 32 insertions, 19 deletions
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 4d2df2f76ea0..86b6f1cc1b10 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c | |||
@@ -1742,11 +1742,20 @@ int dasd_sleep_on_interruptible(struct dasd_ccw_req *cqr) | |||
1742 | static inline int _dasd_term_running_cqr(struct dasd_device *device) | 1742 | static inline int _dasd_term_running_cqr(struct dasd_device *device) |
1743 | { | 1743 | { |
1744 | struct dasd_ccw_req *cqr; | 1744 | struct dasd_ccw_req *cqr; |
1745 | int rc; | ||
1745 | 1746 | ||
1746 | if (list_empty(&device->ccw_queue)) | 1747 | if (list_empty(&device->ccw_queue)) |
1747 | return 0; | 1748 | return 0; |
1748 | cqr = list_entry(device->ccw_queue.next, struct dasd_ccw_req, devlist); | 1749 | cqr = list_entry(device->ccw_queue.next, struct dasd_ccw_req, devlist); |
1749 | return device->discipline->term_IO(cqr); | 1750 | rc = device->discipline->term_IO(cqr); |
1751 | if (!rc) | ||
1752 | /* | ||
1753 | * CQR terminated because a more important request is pending. | ||
1754 | * Undo decreasing of retry counter because this is | ||
1755 | * not an error case. | ||
1756 | */ | ||
1757 | cqr->retries++; | ||
1758 | return rc; | ||
1750 | } | 1759 | } |
1751 | 1760 | ||
1752 | int dasd_sleep_on_immediatly(struct dasd_ccw_req *cqr) | 1761 | int dasd_sleep_on_immediatly(struct dasd_ccw_req *cqr) |
@@ -2314,15 +2323,14 @@ static void dasd_flush_request_queue(struct dasd_block *block) | |||
2314 | 2323 | ||
2315 | static int dasd_open(struct block_device *bdev, fmode_t mode) | 2324 | static int dasd_open(struct block_device *bdev, fmode_t mode) |
2316 | { | 2325 | { |
2317 | struct dasd_block *block = bdev->bd_disk->private_data; | ||
2318 | struct dasd_device *base; | 2326 | struct dasd_device *base; |
2319 | int rc; | 2327 | int rc; |
2320 | 2328 | ||
2321 | if (!block) | 2329 | base = dasd_device_from_gendisk(bdev->bd_disk); |
2330 | if (!base) | ||
2322 | return -ENODEV; | 2331 | return -ENODEV; |
2323 | 2332 | ||
2324 | base = block->base; | 2333 | atomic_inc(&base->block->open_count); |
2325 | atomic_inc(&block->open_count); | ||
2326 | if (test_bit(DASD_FLAG_OFFLINE, &base->flags)) { | 2334 | if (test_bit(DASD_FLAG_OFFLINE, &base->flags)) { |
2327 | rc = -ENODEV; | 2335 | rc = -ENODEV; |
2328 | goto unlock; | 2336 | goto unlock; |
@@ -2355,21 +2363,28 @@ static int dasd_open(struct block_device *bdev, fmode_t mode) | |||
2355 | goto out; | 2363 | goto out; |
2356 | } | 2364 | } |
2357 | 2365 | ||
2366 | dasd_put_device(base); | ||
2358 | return 0; | 2367 | return 0; |
2359 | 2368 | ||
2360 | out: | 2369 | out: |
2361 | module_put(base->discipline->owner); | 2370 | module_put(base->discipline->owner); |
2362 | unlock: | 2371 | unlock: |
2363 | atomic_dec(&block->open_count); | 2372 | atomic_dec(&base->block->open_count); |
2373 | dasd_put_device(base); | ||
2364 | return rc; | 2374 | return rc; |
2365 | } | 2375 | } |
2366 | 2376 | ||
2367 | static int dasd_release(struct gendisk *disk, fmode_t mode) | 2377 | static int dasd_release(struct gendisk *disk, fmode_t mode) |
2368 | { | 2378 | { |
2369 | struct dasd_block *block = disk->private_data; | 2379 | struct dasd_device *base; |
2370 | 2380 | ||
2371 | atomic_dec(&block->open_count); | 2381 | base = dasd_device_from_gendisk(disk); |
2372 | module_put(block->base->discipline->owner); | 2382 | if (!base) |
2383 | return -ENODEV; | ||
2384 | |||
2385 | atomic_dec(&base->block->open_count); | ||
2386 | module_put(base->discipline->owner); | ||
2387 | dasd_put_device(base); | ||
2373 | return 0; | 2388 | return 0; |
2374 | } | 2389 | } |
2375 | 2390 | ||
@@ -2378,20 +2393,20 @@ static int dasd_release(struct gendisk *disk, fmode_t mode) | |||
2378 | */ | 2393 | */ |
2379 | static int dasd_getgeo(struct block_device *bdev, struct hd_geometry *geo) | 2394 | static int dasd_getgeo(struct block_device *bdev, struct hd_geometry *geo) |
2380 | { | 2395 | { |
2381 | struct dasd_block *block; | ||
2382 | struct dasd_device *base; | 2396 | struct dasd_device *base; |
2383 | 2397 | ||
2384 | block = bdev->bd_disk->private_data; | 2398 | base = dasd_device_from_gendisk(bdev->bd_disk); |
2385 | if (!block) | 2399 | if (!base) |
2386 | return -ENODEV; | 2400 | return -ENODEV; |
2387 | base = block->base; | ||
2388 | 2401 | ||
2389 | if (!base->discipline || | 2402 | if (!base->discipline || |
2390 | !base->discipline->fill_geometry) | 2403 | !base->discipline->fill_geometry) { |
2404 | dasd_put_device(base); | ||
2391 | return -EINVAL; | 2405 | return -EINVAL; |
2392 | 2406 | } | |
2393 | base->discipline->fill_geometry(block, geo); | 2407 | base->discipline->fill_geometry(base->block, geo); |
2394 | geo->start = get_start_sect(bdev) >> block->s2b_shift; | 2408 | geo->start = get_start_sect(bdev) >> base->block->s2b_shift; |
2409 | dasd_put_device(base); | ||
2395 | return 0; | 2410 | return 0; |
2396 | } | 2411 | } |
2397 | 2412 | ||
@@ -2528,7 +2543,6 @@ void dasd_generic_remove(struct ccw_device *cdev) | |||
2528 | dasd_set_target_state(device, DASD_STATE_NEW); | 2543 | dasd_set_target_state(device, DASD_STATE_NEW); |
2529 | /* dasd_delete_device destroys the device reference. */ | 2544 | /* dasd_delete_device destroys the device reference. */ |
2530 | block = device->block; | 2545 | block = device->block; |
2531 | device->block = NULL; | ||
2532 | dasd_delete_device(device); | 2546 | dasd_delete_device(device); |
2533 | /* | 2547 | /* |
2534 | * life cycle of block is bound to device, so delete it after | 2548 | * life cycle of block is bound to device, so delete it after |
@@ -2650,7 +2664,6 @@ int dasd_generic_set_offline(struct ccw_device *cdev) | |||
2650 | dasd_set_target_state(device, DASD_STATE_NEW); | 2664 | dasd_set_target_state(device, DASD_STATE_NEW); |
2651 | /* dasd_delete_device destroys the device reference. */ | 2665 | /* dasd_delete_device destroys the device reference. */ |
2652 | block = device->block; | 2666 | block = device->block; |
2653 | device->block = NULL; | ||
2654 | dasd_delete_device(device); | 2667 | dasd_delete_device(device); |
2655 | /* | 2668 | /* |
2656 | * life cycle of block is bound to device, so delete it after | 2669 | * life cycle of block is bound to device, so delete it after |