Skip to content

Commit

Permalink
[S390] vmur: Use wait queue instead of mutex to serialize open
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Frank Munzert authored and Heiko Carstens committed Apr 17, 2008
1 parent 92bf435 commit a695f16
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 8 deletions.
24 changes: 17 additions & 7 deletions drivers/s390/char/vmur.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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");

Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down
4 changes: 3 additions & 1 deletion drivers/s390/char/vmur.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ struct file_control_block {
struct urdev {
struct ccw_device *cdev; /* Backpointer to ccw device */
struct mutex io_mutex; /* Serialises device IO */
struct mutex open_mutex; /* Serialises access to device */
struct completion *io_done; /* do_ur_io waits; irq completes */
struct device *device;
struct cdev *char_device;
Expand All @@ -71,6 +70,9 @@ struct urdev {
int class; /* VM device class */
int io_request_rc; /* return code from I/O request */
atomic_t ref_count; /* reference counter */
wait_queue_head_t wait; /* wait queue to serialize open */
int open_flag; /* "urdev is open" flag */
spinlock_t open_lock; /* serialize critical sections */
};

/*
Expand Down

0 comments on commit a695f16

Please sign in to comment.