aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/s390/char/vmur.c24
-rw-r--r--drivers/s390/char/vmur.h4
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)
720fail_urfile_free: 725fail_urfile_free:
721 urfile_free(urf); 726 urfile_free(urf);
722fail_unlock: 727fail_unlock:
723 mutex_unlock(&urd->open_mutex); 728 spin_lock(&urd->open_lock);
729 urd->open_flag--;
730 spin_unlock(&urd->open_lock);
724fail_put: 731fail_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 {
62struct urdev { 62struct 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/*