Commit a695f16729e00995fe72baf0e8bee4bf9c232ae0
Committed by
Heiko Carstens
1 parent
92bf435f38
Exists in
master
and in
7 other branches
[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>
Showing 2 changed files with 20 additions and 8 deletions Side-by-side Diff
drivers/s390/char/vmur.c
... | ... | @@ -100,7 +100,8 @@ |
100 | 100 | urd->reclen = cdev->id.driver_info; |
101 | 101 | ccw_device_get_id(cdev, &urd->dev_id); |
102 | 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 | 105 | atomic_set(&urd->ref_count, 1); |
105 | 106 | urd->cdev = cdev; |
106 | 107 | get_device(&cdev->dev); |
107 | 108 | |
108 | 109 | |
109 | 110 | |
... | ... | @@ -678,17 +679,21 @@ |
678 | 679 | if (!urd) |
679 | 680 | return -ENXIO; |
680 | 681 | |
681 | - if (file->f_flags & O_NONBLOCK) { | |
682 | - if (!mutex_trylock(&urd->open_mutex)) { | |
682 | + spin_lock(&urd->open_lock); | |
683 | + while (urd->open_flag) { | |
684 | + spin_unlock(&urd->open_lock); | |
685 | + if (file->f_flags & O_NONBLOCK) { | |
683 | 686 | rc = -EBUSY; |
684 | 687 | goto fail_put; |
685 | 688 | } |
686 | - } else { | |
687 | - if (mutex_lock_interruptible(&urd->open_mutex)) { | |
689 | + if (wait_event_interruptible(urd->wait, urd->open_flag == 0)) { | |
688 | 690 | rc = -ERESTARTSYS; |
689 | 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 | 698 | TRACE("ur_open\n"); |
694 | 699 | |
... | ... | @@ -720,7 +725,9 @@ |
720 | 725 | fail_urfile_free: |
721 | 726 | urfile_free(urf); |
722 | 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 | 731 | fail_put: |
725 | 732 | urdev_put(urd); |
726 | 733 | return rc; |
... | ... | @@ -731,7 +738,10 @@ |
731 | 738 | struct urfile *urf = file->private_data; |
732 | 739 | |
733 | 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 | 745 | urdev_put(urf->urd); |
736 | 746 | urfile_free(urf); |
737 | 747 | return 0; |
drivers/s390/char/vmur.h
... | ... | @@ -62,7 +62,6 @@ |
62 | 62 | struct urdev { |
63 | 63 | struct ccw_device *cdev; /* Backpointer to ccw device */ |
64 | 64 | struct mutex io_mutex; /* Serialises device IO */ |
65 | - struct mutex open_mutex; /* Serialises access to device */ | |
66 | 65 | struct completion *io_done; /* do_ur_io waits; irq completes */ |
67 | 66 | struct device *device; |
68 | 67 | struct cdev *char_device; |
... | ... | @@ -71,6 +70,9 @@ |
71 | 70 | int class; /* VM device class */ |
72 | 71 | int io_request_rc; /* return code from I/O request */ |
73 | 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 | /* |