diff options
author | Frank Munzert <munzert@de.ibm.com> | 2008-04-17 01:46:06 -0400 |
---|---|---|
committer | Heiko Carstens <heiko.carstens@de.ibm.com> | 2008-04-17 01:46:59 -0400 |
commit | a695f16729e00995fe72baf0e8bee4bf9c232ae0 (patch) | |
tree | 2fddf1722972564e33eedbedf9010bdd9735a74d /drivers | |
parent | 92bf435f383a6193d59c687ce87ccca3529c68a1 (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')
-rw-r--r-- | drivers/s390/char/vmur.c | 24 | ||||
-rw-r--r-- | drivers/s390/char/vmur.h | 4 |
2 files changed, 20 insertions, 8 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) | |||
100 | urd->reclen = cdev->id.driver_info; | 100 | urd->reclen = cdev->id.driver_info; |
101 | ccw_device_get_id(cdev, &urd->dev_id); | 101 | ccw_device_get_id(cdev, &urd->dev_id); |
102 | mutex_init(&urd->io_mutex); | 102 | mutex_init(&urd->io_mutex); |
103 | mutex_init(&urd->open_mutex); | 103 | init_waitqueue_head(&urd->wait); |
104 | spin_lock_init(&urd->open_lock); | ||
104 | atomic_set(&urd->ref_count, 1); | 105 | atomic_set(&urd->ref_count, 1); |
105 | urd->cdev = cdev; | 106 | urd->cdev = cdev; |
106 | get_device(&cdev->dev); | 107 | get_device(&cdev->dev); |
@@ -678,17 +679,21 @@ static int ur_open(struct inode *inode, struct file *file) | |||
678 | if (!urd) | 679 | if (!urd) |
679 | return -ENXIO; | 680 | return -ENXIO; |
680 | 681 | ||
681 | if (file->f_flags & O_NONBLOCK) { | 682 | spin_lock(&urd->open_lock); |
682 | if (!mutex_trylock(&urd->open_mutex)) { | 683 | while (urd->open_flag) { |
684 | spin_unlock(&urd->open_lock); | ||
685 | if (file->f_flags & O_NONBLOCK) { | ||
683 | rc = -EBUSY; | 686 | rc = -EBUSY; |
684 | goto fail_put; | 687 | goto fail_put; |
685 | } | 688 | } |
686 | } else { | 689 | if (wait_event_interruptible(urd->wait, urd->open_flag == 0)) { |
687 | if (mutex_lock_interruptible(&urd->open_mutex)) { | ||
688 | rc = -ERESTARTSYS; | 690 | rc = -ERESTARTSYS; |
689 | goto fail_put; | 691 | goto fail_put; |
690 | } | 692 | } |
693 | spin_lock(&urd->open_lock); | ||
691 | } | 694 | } |
695 | urd->open_flag++; | ||
696 | spin_unlock(&urd->open_lock); | ||
692 | 697 | ||
693 | TRACE("ur_open\n"); | 698 | TRACE("ur_open\n"); |
694 | 699 | ||
@@ -720,7 +725,9 @@ static int ur_open(struct inode *inode, struct file *file) | |||
720 | fail_urfile_free: | 725 | fail_urfile_free: |
721 | urfile_free(urf); | 726 | urfile_free(urf); |
722 | fail_unlock: | 727 | fail_unlock: |
723 | mutex_unlock(&urd->open_mutex); | 728 | spin_lock(&urd->open_lock); |
729 | urd->open_flag--; | ||
730 | spin_unlock(&urd->open_lock); | ||
724 | fail_put: | 731 | fail_put: |
725 | urdev_put(urd); | 732 | urdev_put(urd); |
726 | return rc; | 733 | return rc; |
@@ -731,7 +738,10 @@ static int ur_release(struct inode *inode, struct file *file) | |||
731 | struct urfile *urf = file->private_data; | 738 | struct urfile *urf = file->private_data; |
732 | 739 | ||
733 | TRACE("ur_release\n"); | 740 | TRACE("ur_release\n"); |
734 | mutex_unlock(&urf->urd->open_mutex); | 741 | spin_lock(&urf->urd->open_lock); |
742 | urf->urd->open_flag--; | ||
743 | spin_unlock(&urf->urd->open_lock); | ||
744 | wake_up_interruptible(&urf->urd->wait); | ||
735 | urdev_put(urf->urd); | 745 | urdev_put(urf->urd); |
736 | urfile_free(urf); | 746 | urfile_free(urf); |
737 | return 0; | 747 | return 0; |
diff --git a/drivers/s390/char/vmur.h b/drivers/s390/char/vmur.h index fa959644735a..fa320ad4593d 100644 --- a/drivers/s390/char/vmur.h +++ b/drivers/s390/char/vmur.h | |||
@@ -62,7 +62,6 @@ struct file_control_block { | |||
62 | struct urdev { | 62 | struct urdev { |
63 | struct ccw_device *cdev; /* Backpointer to ccw device */ | 63 | struct ccw_device *cdev; /* Backpointer to ccw device */ |
64 | struct mutex io_mutex; /* Serialises device IO */ | 64 | struct mutex io_mutex; /* Serialises device IO */ |
65 | struct mutex open_mutex; /* Serialises access to device */ | ||
66 | struct completion *io_done; /* do_ur_io waits; irq completes */ | 65 | struct completion *io_done; /* do_ur_io waits; irq completes */ |
67 | struct device *device; | 66 | struct device *device; |
68 | struct cdev *char_device; | 67 | struct cdev *char_device; |
@@ -71,6 +70,9 @@ struct urdev { | |||
71 | int class; /* VM device class */ | 70 | int class; /* VM device class */ |
72 | int io_request_rc; /* return code from I/O request */ | 71 | int io_request_rc; /* return code from I/O request */ |
73 | atomic_t ref_count; /* reference counter */ | 72 | atomic_t ref_count; /* reference counter */ |
73 | wait_queue_head_t wait; /* wait queue to serialize open */ | ||
74 | int open_flag; /* "urdev is open" flag */ | ||
75 | spinlock_t open_lock; /* serialize critical sections */ | ||
74 | }; | 76 | }; |
75 | 77 | ||
76 | /* | 78 | /* |