aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/block/dasd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/block/dasd.c')
-rw-r--r--drivers/s390/block/dasd.c51
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)
1742static inline int _dasd_term_running_cqr(struct dasd_device *device) 1742static 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
1752int dasd_sleep_on_immediatly(struct dasd_ccw_req *cqr) 1761int 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
2315static int dasd_open(struct block_device *bdev, fmode_t mode) 2324static 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
2360out: 2369out:
2361 module_put(base->discipline->owner); 2370 module_put(base->discipline->owner);
2362unlock: 2371unlock:
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
2367static int dasd_release(struct gendisk *disk, fmode_t mode) 2377static 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 */
2379static int dasd_getgeo(struct block_device *bdev, struct hd_geometry *geo) 2394static 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