Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a695f167 authored by Frank Munzert's avatar Frank Munzert Committed by Heiko Carstens
Browse files

[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: default avatarFrank Munzert <munzert@de.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: default avatarHeiko Carstens <heiko.carstens@de.ibm.com>
parent 92bf435f
Loading
Loading
Loading
Loading
+17 −7
Original line number Original line Diff line number Diff line
@@ -100,7 +100,8 @@ static struct urdev *urdev_alloc(struct ccw_device *cdev)
	urd->reclen = cdev->id.driver_info;
	urd->reclen = cdev->id.driver_info;
	ccw_device_get_id(cdev, &urd->dev_id);
	ccw_device_get_id(cdev, &urd->dev_id);
	mutex_init(&urd->io_mutex);
	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);
	atomic_set(&urd->ref_count,  1);
	urd->cdev = cdev;
	urd->cdev = cdev;
	get_device(&cdev->dev);
	get_device(&cdev->dev);
@@ -678,17 +679,21 @@ static int ur_open(struct inode *inode, struct file *file)
	if (!urd)
	if (!urd)
		return -ENXIO;
		return -ENXIO;


	spin_lock(&urd->open_lock);
	while (urd->open_flag) {
		spin_unlock(&urd->open_lock);
		if (file->f_flags & O_NONBLOCK) {
		if (file->f_flags & O_NONBLOCK) {
		if (!mutex_trylock(&urd->open_mutex)) {
			rc = -EBUSY;
			rc = -EBUSY;
			goto fail_put;
			goto fail_put;
		}
		}
	} else {
		if (wait_event_interruptible(urd->wait, urd->open_flag == 0)) {
		if (mutex_lock_interruptible(&urd->open_mutex)) {
			rc = -ERESTARTSYS;
			rc = -ERESTARTSYS;
			goto fail_put;
			goto fail_put;
		}
		}
		spin_lock(&urd->open_lock);
	}
	}
	urd->open_flag++;
	spin_unlock(&urd->open_lock);


	TRACE("ur_open\n");
	TRACE("ur_open\n");


@@ -720,7 +725,9 @@ static int ur_open(struct inode *inode, struct file *file)
fail_urfile_free:
fail_urfile_free:
	urfile_free(urf);
	urfile_free(urf);
fail_unlock:
fail_unlock:
	mutex_unlock(&urd->open_mutex);
	spin_lock(&urd->open_lock);
	urd->open_flag--;
	spin_unlock(&urd->open_lock);
fail_put:
fail_put:
	urdev_put(urd);
	urdev_put(urd);
	return rc;
	return rc;
@@ -731,7 +738,10 @@ static int ur_release(struct inode *inode, struct file *file)
	struct urfile *urf = file->private_data;
	struct urfile *urf = file->private_data;


	TRACE("ur_release\n");
	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);
	urdev_put(urf->urd);
	urfile_free(urf);
	urfile_free(urf);
	return 0;
	return 0;
+3 −1
Original line number Original line Diff line number Diff line
@@ -62,7 +62,6 @@ struct file_control_block {
struct urdev {
struct urdev {
	struct ccw_device *cdev;	/* Backpointer to ccw device */
	struct ccw_device *cdev;	/* Backpointer to ccw device */
	struct mutex io_mutex;		/* Serialises device IO */
	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 completion *io_done;	/* do_ur_io waits; irq completes */
	struct device *device;
	struct device *device;
	struct cdev *char_device;
	struct cdev *char_device;
@@ -71,6 +70,9 @@ struct urdev {
	int class;			/* VM device class */
	int class;			/* VM device class */
	int io_request_rc;		/* return code from I/O request */
	int io_request_rc;		/* return code from I/O request */
	atomic_t ref_count;		/* reference counter */
	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 */
};
};


/*
/*