Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

authored by

Frank Munzert and committed by
Heiko Carstens
a695f167 92bf435f

+20 -8
+17 -7
drivers/s390/char/vmur.c
··· 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); ··· 679 678 if (!urd) 680 679 return -ENXIO; 681 680 682 - if (file->f_flags & O_NONBLOCK) { 683 - if (!mutex_trylock(&urd->open_mutex)) { 681 + spin_lock(&urd->open_lock); 682 + while (urd->open_flag) { 683 + spin_unlock(&urd->open_lock); 684 + if (file->f_flags & O_NONBLOCK) { 684 685 rc = -EBUSY; 685 686 goto fail_put; 686 687 } 687 - } else { 688 - if (mutex_lock_interruptible(&urd->open_mutex)) { 688 + if (wait_event_interruptible(urd->wait, urd->open_flag == 0)) { 689 689 rc = -ERESTARTSYS; 690 690 goto fail_put; 691 691 } 692 + spin_lock(&urd->open_lock); 692 693 } 694 + urd->open_flag++; 695 + spin_unlock(&urd->open_lock); 693 696 694 697 TRACE("ur_open\n"); 695 698 ··· 725 720 fail_urfile_free: 726 721 urfile_free(urf); 727 722 fail_unlock: 728 - mutex_unlock(&urd->open_mutex); 723 + spin_lock(&urd->open_lock); 724 + urd->open_flag--; 725 + spin_unlock(&urd->open_lock); 729 726 fail_put: 730 727 urdev_put(urd); 731 728 return rc; ··· 738 731 struct urfile *urf = file->private_data; 739 732 740 733 TRACE("ur_release\n"); 741 - mutex_unlock(&urf->urd->open_mutex); 734 + spin_lock(&urf->urd->open_lock); 735 + urf->urd->open_flag--; 736 + spin_unlock(&urf->urd->open_lock); 737 + wake_up_interruptible(&urf->urd->wait); 742 738 urdev_put(urf->urd); 743 739 urfile_free(urf); 744 740 return 0;
+3 -1
drivers/s390/char/vmur.h
··· 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; ··· 70 71 int class; /* VM device class */ 71 72 int io_request_rc; /* return code from I/O request */ 72 73 atomic_t ref_count; /* reference counter */ 74 + wait_queue_head_t wait; /* wait queue to serialize open */ 75 + int open_flag; /* "urdev is open" flag */ 76 + spinlock_t open_lock; /* serialize critical sections */ 73 77 }; 74 78 75 79 /*