diff options
author | Frank Munzert <munzert@de.ibm.com> | 2008-04-17 09:46:06 +0400 |
---|---|---|
committer | Heiko Carstens <heiko.carstens@de.ibm.com> | 2008-04-17 09:46:59 +0400 |
commit | a695f16729e00995fe72baf0e8bee4bf9c232ae0 (patch) | |
tree | 2fddf1722972564e33eedbedf9010bdd9735a74d /drivers/s390/char/vmur.c | |
parent | 92bf435f383a6193d59c687ce87ccca3529c68a1 (diff) | |
download | linux-a695f16729e00995fe72baf0e8bee4bf9c232ae0.tar.xz |
[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.c | 24 |
1 files changed, 17 insertions, 7 deletions
diff --git a/drivers/s390/char/vmur.c b/drivers/s390/char/vmur.c index 7689b500a104..83ae9a852f00 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; |