summaryrefslogtreecommitdiffstats
path: root/drivers/s390/char/vmur.c
diff options
context:
space:
mode:
authorFrank Munzert <munzert@de.ibm.com>2008-04-17 07:46:06 +0200
committerHeiko Carstens <heiko.carstens@de.ibm.com>2008-04-17 07:46:59 +0200
commita695f16729e00995fe72baf0e8bee4bf9c232ae0 (patch)
tree2fddf1722972564e33eedbedf9010bdd9735a74d /drivers/s390/char/vmur.c
parent92bf435f383a6193d59c687ce87ccca3529c68a1 (diff)
[S390] vmur: Use wait queue instead of mutex to serialize open
If user space opens a unit record device node then vmur is leaving the kernel with lock open_mutex still held to prevent other processes from opening the device simultaneously. This causes lockdep to complain about a lock held when returning to user space. Now the mutex is replaced by a wait queue to serialize device open. Signed-off-by: Frank Munzert <munzert@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Diffstat (limited to 'drivers/s390/char/vmur.c')
-rw-r--r--drivers/s390/char/vmur.c24
1 files changed, 17 insertions, 7 deletions
diff --git a/drivers/s390/char/vmur.c b/drivers/s390/char/vmur.c
index 7689b500a10..83ae9a852f0 100644
--- a/drivers/s390/char/vmur.c
+++ b/drivers/s390/char/vmur.c
@@ -100,7 +100,8 @@ static struct urdev *urdev_alloc(struct ccw_device *cdev)
urd->reclen = cdev->id.driver_info;
ccw_device_get_id(cdev, &urd->dev_id);
mutex_init(&urd->io_mutex);
- mutex_init(&urd->open_mutex);
+ init_waitqueue_head(&urd->wait);
+ spin_lock_init(&urd->open_lock);
atomic_set(&urd->ref_count, 1);
urd->cdev = cdev;
get_device(&cdev->dev);
@@ -678,17 +679,21 @@ static int ur_open(struct inode *inode, struct file *file)
if (!urd)
return -ENXIO;
- if (file->f_flags & O_NONBLOCK) {
- if (!mutex_trylock(&urd->open_mutex)) {
+ spin_lock(&urd->open_lock);
+ while (urd->open_flag) {
+ spin_unlock(&urd->open_lock);
+ if (file->f_flags & O_NONBLOCK) {
rc = -EBUSY;
goto fail_put;
}
- } else {
- if (mutex_lock_interruptible(&urd->open_mutex)) {
+ if (wait_event_interruptible(urd->wait, urd->open_flag == 0)) {
rc = -ERESTARTSYS;
goto fail_put;
}
+ spin_lock(&urd->open_lock);
}
+ urd->open_flag++;
+ spin_unlock(&urd->open_lock);
TRACE("ur_open\n");
@@ -720,7 +725,9 @@ static int ur_open(struct inode *inode, struct file *file)
fail_urfile_free:
urfile_free(urf);
fail_unlock:
- mutex_unlock(&urd->open_mutex);
+ spin_lock(&urd->open_lock);
+ urd->open_flag--;
+ spin_unlock(&urd->open_lock);
fail_put:
urdev_put(urd);
return rc;
@@ -731,7 +738,10 @@ static int ur_release(struct inode *inode, struct file *file)
struct urfile *urf = file->private_data;
TRACE("ur_release\n");
- mutex_unlock(&urf->urd->open_mutex);
+ spin_lock(&urf->urd->open_lock);
+ urf->urd->open_flag--;
+ spin_unlock(&urf->urd->open_lock);
+ wake_up_interruptible(&urf->urd->wait);
urdev_put(urf->urd);
urfile_free(urf);
return 0;