Commit 8fd138c3 authored by Martin Schwidefsky's avatar Martin Schwidefsky Committed by Martin Schwidefsky

[S390] tape: cleanup reference counting

Rename tape_get_device to tape_find_device and tape_get_device_reference
to tape_get_device. The old names didn't make too much sense.

Follow the get_device()/put_device() semantic and convert tape_put_device
to a void function.
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 1b52fff0
...@@ -292,9 +292,9 @@ extern int tape_generic_pm_suspend(struct ccw_device *); ...@@ -292,9 +292,9 @@ extern int tape_generic_pm_suspend(struct ccw_device *);
extern int tape_generic_probe(struct ccw_device *); extern int tape_generic_probe(struct ccw_device *);
extern void tape_generic_remove(struct ccw_device *); extern void tape_generic_remove(struct ccw_device *);
extern struct tape_device *tape_get_device(int devindex); extern struct tape_device *tape_find_device(int devindex);
extern struct tape_device *tape_get_device_reference(struct tape_device *); extern struct tape_device *tape_get_device(struct tape_device *);
extern struct tape_device *tape_put_device(struct tape_device *); extern void tape_put_device(struct tape_device *);
/* Externals from tape_char.c */ /* Externals from tape_char.c */
extern int tapechar_init(void); extern int tapechar_init(void);
......
...@@ -113,16 +113,16 @@ tape_34xx_work_handler(struct work_struct *work) ...@@ -113,16 +113,16 @@ tape_34xx_work_handler(struct work_struct *work)
{ {
struct tape_34xx_work *p = struct tape_34xx_work *p =
container_of(work, struct tape_34xx_work, work); container_of(work, struct tape_34xx_work, work);
struct tape_device *device = p->device;
switch(p->op) { switch(p->op) {
case TO_MSEN: case TO_MSEN:
tape_34xx_medium_sense(p->device); tape_34xx_medium_sense(device);
break; break;
default: default:
DBF_EVENT(3, "T34XX: internal error: unknown work\n"); DBF_EVENT(3, "T34XX: internal error: unknown work\n");
} }
tape_put_device(device);
p->device = tape_put_device(p->device);
kfree(p); kfree(p);
} }
...@@ -136,7 +136,7 @@ tape_34xx_schedule_work(struct tape_device *device, enum tape_op op) ...@@ -136,7 +136,7 @@ tape_34xx_schedule_work(struct tape_device *device, enum tape_op op)
INIT_WORK(&p->work, tape_34xx_work_handler); INIT_WORK(&p->work, tape_34xx_work_handler);
p->device = tape_get_device_reference(device); p->device = tape_get_device(device);
p->op = op; p->op = op;
schedule_work(&p->work); schedule_work(&p->work);
......
...@@ -608,7 +608,7 @@ tape_3590_schedule_work(struct tape_device *device, enum tape_op op) ...@@ -608,7 +608,7 @@ tape_3590_schedule_work(struct tape_device *device, enum tape_op op)
INIT_WORK(&p->work, tape_3590_work_handler); INIT_WORK(&p->work, tape_3590_work_handler);
p->device = tape_get_device_reference(device); p->device = tape_get_device(device);
p->op = op; p->op = op;
schedule_work(&p->work); schedule_work(&p->work);
......
...@@ -239,7 +239,7 @@ tapeblock_setup_device(struct tape_device * device) ...@@ -239,7 +239,7 @@ tapeblock_setup_device(struct tape_device * device)
disk->major = tapeblock_major; disk->major = tapeblock_major;
disk->first_minor = device->first_minor; disk->first_minor = device->first_minor;
disk->fops = &tapeblock_fops; disk->fops = &tapeblock_fops;
disk->private_data = tape_get_device_reference(device); disk->private_data = tape_get_device(device);
disk->queue = blkdat->request_queue; disk->queue = blkdat->request_queue;
set_capacity(disk, 0); set_capacity(disk, 0);
sprintf(disk->disk_name, "btibm%d", sprintf(disk->disk_name, "btibm%d",
...@@ -247,11 +247,11 @@ tapeblock_setup_device(struct tape_device * device) ...@@ -247,11 +247,11 @@ tapeblock_setup_device(struct tape_device * device)
blkdat->disk = disk; blkdat->disk = disk;
blkdat->medium_changed = 1; blkdat->medium_changed = 1;
blkdat->request_queue->queuedata = tape_get_device_reference(device); blkdat->request_queue->queuedata = tape_get_device(device);
add_disk(disk); add_disk(disk);
tape_get_device_reference(device); tape_get_device(device);
INIT_WORK(&blkdat->requeue_task, tapeblock_requeue); INIT_WORK(&blkdat->requeue_task, tapeblock_requeue);
return 0; return 0;
...@@ -274,13 +274,14 @@ tapeblock_cleanup_device(struct tape_device *device) ...@@ -274,13 +274,14 @@ tapeblock_cleanup_device(struct tape_device *device)
} }
del_gendisk(device->blk_data.disk); del_gendisk(device->blk_data.disk);
device->blk_data.disk->private_data = device->blk_data.disk->private_data = NULL;
tape_put_device(device->blk_data.disk->private_data); tape_put_device(device);
put_disk(device->blk_data.disk); put_disk(device->blk_data.disk);
device->blk_data.disk = NULL; device->blk_data.disk = NULL;
cleanup_queue: cleanup_queue:
device->blk_data.request_queue->queuedata = tape_put_device(device); device->blk_data.request_queue->queuedata = NULL;
tape_put_device(device);
blk_cleanup_queue(device->blk_data.request_queue); blk_cleanup_queue(device->blk_data.request_queue);
device->blk_data.request_queue = NULL; device->blk_data.request_queue = NULL;
...@@ -363,7 +364,7 @@ tapeblock_open(struct block_device *bdev, fmode_t mode) ...@@ -363,7 +364,7 @@ tapeblock_open(struct block_device *bdev, fmode_t mode)
struct tape_device * device; struct tape_device * device;
int rc; int rc;
device = tape_get_device_reference(disk->private_data); device = tape_get_device(disk->private_data);
if (device->required_tapemarks) { if (device->required_tapemarks) {
DBF_EVENT(2, "TBLOCK: missing tapemarks\n"); DBF_EVENT(2, "TBLOCK: missing tapemarks\n");
......
...@@ -286,9 +286,9 @@ tapechar_open (struct inode *inode, struct file *filp) ...@@ -286,9 +286,9 @@ tapechar_open (struct inode *inode, struct file *filp)
lock_kernel(); lock_kernel();
minor = iminor(filp->f_path.dentry->d_inode); minor = iminor(filp->f_path.dentry->d_inode);
device = tape_get_device(minor / TAPE_MINORS_PER_DEV); device = tape_find_device(minor / TAPE_MINORS_PER_DEV);
if (IS_ERR(device)) { if (IS_ERR(device)) {
DBF_EVENT(3, "TCHAR:open: tape_get_device() failed\n"); DBF_EVENT(3, "TCHAR:open: tape_find_device() failed\n");
rc = PTR_ERR(device); rc = PTR_ERR(device);
goto out; goto out;
} }
...@@ -340,7 +340,8 @@ tapechar_release(struct inode *inode, struct file *filp) ...@@ -340,7 +340,8 @@ tapechar_release(struct inode *inode, struct file *filp)
device->char_data.idal_buf = NULL; device->char_data.idal_buf = NULL;
} }
tape_release(device); tape_release(device);
filp->private_data = tape_put_device(device); filp->private_data = NULL;
tape_put_device(device);
return 0; return 0;
} }
......
...@@ -511,11 +511,12 @@ tape_alloc_device(void) ...@@ -511,11 +511,12 @@ tape_alloc_device(void)
* increment the reference count. * increment the reference count.
*/ */
struct tape_device * struct tape_device *
tape_get_device_reference(struct tape_device *device) tape_get_device(struct tape_device *device)
{ {
DBF_EVENT(4, "tape_get_device_reference(%p) = %i\n", device, int count;
atomic_inc_return(&device->ref_count));
count = atomic_inc_return(&device->ref_count);
DBF_EVENT(4, "tape_get_device(%p) = %i\n", device, count);
return device; return device;
} }
...@@ -525,32 +526,25 @@ tape_get_device_reference(struct tape_device *device) ...@@ -525,32 +526,25 @@ tape_get_device_reference(struct tape_device *device)
* The function returns a NULL pointer to be used by the caller * The function returns a NULL pointer to be used by the caller
* for clearing reference pointers. * for clearing reference pointers.
*/ */
struct tape_device * void
tape_put_device(struct tape_device *device) tape_put_device(struct tape_device *device)
{ {
int remain; int count;
remain = atomic_dec_return(&device->ref_count); count = atomic_dec_return(&device->ref_count);
if (remain > 0) { DBF_EVENT(4, "tape_put_device(%p) -> %i\n", device, count);
DBF_EVENT(4, "tape_put_device(%p) -> %i\n", device, remain); BUG_ON(count < 0);
} else { if (count == 0) {
if (remain < 0) { kfree(device->modeset_byte);
DBF_EVENT(4, "put device without reference\n"); kfree(device);
} else {
DBF_EVENT(4, "tape_free_device(%p)\n", device);
kfree(device->modeset_byte);
kfree(device);
}
} }
return NULL;
} }
/* /*
* Find tape device by a device index. * Find tape device by a device index.
*/ */
struct tape_device * struct tape_device *
tape_get_device(int devindex) tape_find_device(int devindex)
{ {
struct tape_device *device, *tmp; struct tape_device *device, *tmp;
...@@ -558,7 +552,7 @@ tape_get_device(int devindex) ...@@ -558,7 +552,7 @@ tape_get_device(int devindex)
read_lock(&tape_device_lock); read_lock(&tape_device_lock);
list_for_each_entry(tmp, &tape_device_list, node) { list_for_each_entry(tmp, &tape_device_list, node) {
if (tmp->first_minor / TAPE_MINORS_PER_DEV == devindex) { if (tmp->first_minor / TAPE_MINORS_PER_DEV == devindex) {
device = tape_get_device_reference(tmp); device = tape_get_device(tmp);
break; break;
} }
} }
...@@ -607,7 +601,8 @@ __tape_discard_requests(struct tape_device *device) ...@@ -607,7 +601,8 @@ __tape_discard_requests(struct tape_device *device)
list_del(&request->list); list_del(&request->list);
/* Decrease ref_count for removed request. */ /* Decrease ref_count for removed request. */
request->device = tape_put_device(device); request->device = NULL;
tape_put_device(device);
request->rc = -EIO; request->rc = -EIO;
if (request->callback != NULL) if (request->callback != NULL)
request->callback(request, request->callback_data); request->callback(request, request->callback_data);
...@@ -665,9 +660,11 @@ tape_generic_remove(struct ccw_device *cdev) ...@@ -665,9 +660,11 @@ tape_generic_remove(struct ccw_device *cdev)
tape_cleanup_device(device); tape_cleanup_device(device);
} }
if (dev_get_drvdata(&cdev->dev)) { device = dev_get_drvdata(&cdev->dev);
if (device) {
sysfs_remove_group(&cdev->dev.kobj, &tape_attr_group); sysfs_remove_group(&cdev->dev.kobj, &tape_attr_group);
dev_set_drvdata(&cdev->dev, tape_put_device(dev_get_drvdata(&cdev->dev))); dev_set_drvdata(&cdev->dev, NULL);
tape_put_device(device);
} }
} }
...@@ -722,9 +719,8 @@ tape_free_request (struct tape_request * request) ...@@ -722,9 +719,8 @@ tape_free_request (struct tape_request * request)
{ {
DBF_LH(6, "Free request %p\n", request); DBF_LH(6, "Free request %p\n", request);
if (request->device != NULL) { if (request->device)
request->device = tape_put_device(request->device); tape_put_device(request->device);
}
kfree(request->cpdata); kfree(request->cpdata);
kfree(request->cpaddr); kfree(request->cpaddr);
kfree(request); kfree(request);
...@@ -839,7 +835,8 @@ static void tape_long_busy_timeout(unsigned long data) ...@@ -839,7 +835,8 @@ static void tape_long_busy_timeout(unsigned long data)
BUG_ON(request->status != TAPE_REQUEST_LONG_BUSY); BUG_ON(request->status != TAPE_REQUEST_LONG_BUSY);
DBF_LH(6, "%08x: Long busy timeout.\n", device->cdev_id); DBF_LH(6, "%08x: Long busy timeout.\n", device->cdev_id);
__tape_start_next_request(device); __tape_start_next_request(device);
device->lb_timeout.data = (unsigned long) tape_put_device(device); device->lb_timeout.data = 0UL;
tape_put_device(device);
spin_unlock_irq(get_ccwdev_lock(device->cdev)); spin_unlock_irq(get_ccwdev_lock(device->cdev));
} }
...@@ -919,7 +916,7 @@ __tape_start_request(struct tape_device *device, struct tape_request *request) ...@@ -919,7 +916,7 @@ __tape_start_request(struct tape_device *device, struct tape_request *request)
} }
/* Increase use count of device for the added request. */ /* Increase use count of device for the added request. */
request->device = tape_get_device_reference(device); request->device = tape_get_device(device);
if (list_empty(&device->req_queue)) { if (list_empty(&device->req_queue)) {
/* No other requests are on the queue. Start this one. */ /* No other requests are on the queue. Start this one. */
...@@ -1118,8 +1115,8 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb) ...@@ -1118,8 +1115,8 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
if (req->status == TAPE_REQUEST_LONG_BUSY) { if (req->status == TAPE_REQUEST_LONG_BUSY) {
DBF_EVENT(3, "(%08x): del timer\n", device->cdev_id); DBF_EVENT(3, "(%08x): del timer\n", device->cdev_id);
if (del_timer(&device->lb_timeout)) { if (del_timer(&device->lb_timeout)) {
device->lb_timeout.data = (unsigned long) device->lb_timeout.data = 0UL;
tape_put_device(device); tape_put_device(device);
__tape_start_next_request(device); __tape_start_next_request(device);
} }
return; return;
...@@ -1174,7 +1171,7 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb) ...@@ -1174,7 +1171,7 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
break; break;
case TAPE_IO_LONG_BUSY: case TAPE_IO_LONG_BUSY:
device->lb_timeout.data = device->lb_timeout.data =
(unsigned long)tape_get_device_reference(device); (unsigned long) tape_get_device(device);
device->lb_timeout.expires = jiffies + device->lb_timeout.expires = jiffies +
LONG_BUSY_TIMEOUT * HZ; LONG_BUSY_TIMEOUT * HZ;
DBF_EVENT(3, "(%08x): add timer\n", device->cdev_id); DBF_EVENT(3, "(%08x): add timer\n", device->cdev_id);
...@@ -1327,7 +1324,7 @@ EXPORT_SYMBOL(tape_generic_online); ...@@ -1327,7 +1324,7 @@ EXPORT_SYMBOL(tape_generic_online);
EXPORT_SYMBOL(tape_generic_offline); EXPORT_SYMBOL(tape_generic_offline);
EXPORT_SYMBOL(tape_generic_pm_suspend); EXPORT_SYMBOL(tape_generic_pm_suspend);
EXPORT_SYMBOL(tape_put_device); EXPORT_SYMBOL(tape_put_device);
EXPORT_SYMBOL(tape_get_device_reference); EXPORT_SYMBOL(tape_get_device);
EXPORT_SYMBOL(tape_state_verbose); EXPORT_SYMBOL(tape_state_verbose);
EXPORT_SYMBOL(tape_op_verbose); EXPORT_SYMBOL(tape_op_verbose);
EXPORT_SYMBOL(tape_state_set); EXPORT_SYMBOL(tape_state_set);
......
...@@ -45,7 +45,7 @@ static int tape_proc_show(struct seq_file *m, void *v) ...@@ -45,7 +45,7 @@ static int tape_proc_show(struct seq_file *m, void *v)
seq_printf(m, "TapeNo\tBusID CuType/Model\t" seq_printf(m, "TapeNo\tBusID CuType/Model\t"
"DevType/Model\tBlkSize\tState\tOp\tMedState\n"); "DevType/Model\tBlkSize\tState\tOp\tMedState\n");
} }
device = tape_get_device(n); device = tape_find_device(n);
if (IS_ERR(device)) if (IS_ERR(device))
return 0; return 0;
spin_lock_irq(get_ccwdev_lock(device->cdev)); spin_lock_irq(get_ccwdev_lock(device->cdev));
......
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