staging: comedi: rearrange comedi_write() code
Rearrange the code in `comedi_write()` to reduce the amount of indentation. The code never reiterates the `while` loop once `count` has become non-zero, so we can check that in the `while` condition to save an indentation level. (Note that `nbytes` has been checked to be non-zero before entering the loop, so we can remove that check.) Move the code that makes the subdevice "become non-busy" outside the `while` loop, using a new flag variable `become_nonbusy` to decide whether it needs to be done. This simplifies the wait queue handling so there is a single place where the task is removed from the wait queue, and we can remove the `on_wait_queue` flag variable. Signed-off-by: Ian Abbott <abbotti@mev.co.uk> Reviewed-by: H Hartley Sweeten <hsweeten@visionengravers.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
b4717ff608
commit
06181de14f
@@ -2307,7 +2307,7 @@ static ssize_t comedi_write(struct file *file, const char __user *buf,
|
|||||||
DECLARE_WAITQUEUE(wait, current);
|
DECLARE_WAITQUEUE(wait, current);
|
||||||
struct comedi_file *cfp = file->private_data;
|
struct comedi_file *cfp = file->private_data;
|
||||||
struct comedi_device *dev = cfp->dev;
|
struct comedi_device *dev = cfp->dev;
|
||||||
bool on_wait_queue = false;
|
bool become_nonbusy = false;
|
||||||
bool attach_locked;
|
bool attach_locked;
|
||||||
unsigned int old_detach_count;
|
unsigned int old_detach_count;
|
||||||
|
|
||||||
@@ -2342,48 +2342,16 @@ static ssize_t comedi_write(struct file *file, const char __user *buf,
|
|||||||
}
|
}
|
||||||
|
|
||||||
add_wait_queue(&async->wait_head, &wait);
|
add_wait_queue(&async->wait_head, &wait);
|
||||||
on_wait_queue = true;
|
while (count == 0 && !retval) {
|
||||||
while (nbytes > 0 && !retval) {
|
|
||||||
unsigned runflags;
|
unsigned runflags;
|
||||||
|
|
||||||
set_current_state(TASK_INTERRUPTIBLE);
|
set_current_state(TASK_INTERRUPTIBLE);
|
||||||
|
|
||||||
runflags = comedi_get_subdevice_runflags(s);
|
runflags = comedi_get_subdevice_runflags(s);
|
||||||
if (!comedi_is_runflags_running(runflags)) {
|
if (!comedi_is_runflags_running(runflags)) {
|
||||||
if (count == 0) {
|
if (comedi_is_runflags_in_error(runflags))
|
||||||
struct comedi_subdevice *new_s;
|
retval = -EPIPE;
|
||||||
|
become_nonbusy = true;
|
||||||
if (comedi_is_runflags_in_error(runflags))
|
|
||||||
retval = -EPIPE;
|
|
||||||
else
|
|
||||||
retval = 0;
|
|
||||||
/*
|
|
||||||
* To avoid deadlock, cannot acquire dev->mutex
|
|
||||||
* while dev->attach_lock is held. Need to
|
|
||||||
* remove task from the async wait queue before
|
|
||||||
* releasing dev->attach_lock, as it might not
|
|
||||||
* be valid afterwards.
|
|
||||||
*/
|
|
||||||
remove_wait_queue(&async->wait_head, &wait);
|
|
||||||
on_wait_queue = false;
|
|
||||||
up_read(&dev->attach_lock);
|
|
||||||
attach_locked = false;
|
|
||||||
mutex_lock(&dev->mutex);
|
|
||||||
/*
|
|
||||||
* Become non-busy unless things have changed
|
|
||||||
* behind our back. Checking dev->detach_count
|
|
||||||
* is unchanged ought to be sufficient (unless
|
|
||||||
* there have been 2**32 detaches in the
|
|
||||||
* meantime!), but check the subdevice pointer
|
|
||||||
* as well just in case.
|
|
||||||
*/
|
|
||||||
new_s = comedi_file_write_subdevice(file);
|
|
||||||
if (dev->attached &&
|
|
||||||
old_detach_count == dev->detach_count &&
|
|
||||||
s == new_s && new_s->async == async)
|
|
||||||
do_become_nonbusy(dev, s);
|
|
||||||
mutex_unlock(&dev->mutex);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2433,12 +2401,33 @@ static ssize_t comedi_write(struct file *file, const char __user *buf,
|
|||||||
nbytes -= n;
|
nbytes -= n;
|
||||||
|
|
||||||
buf += n;
|
buf += n;
|
||||||
break; /* makes device work like a pipe */
|
}
|
||||||
|
remove_wait_queue(&async->wait_head, &wait);
|
||||||
|
set_current_state(TASK_RUNNING);
|
||||||
|
if (become_nonbusy && count == 0) {
|
||||||
|
struct comedi_subdevice *new_s;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* To avoid deadlock, cannot acquire dev->mutex
|
||||||
|
* while dev->attach_lock is held.
|
||||||
|
*/
|
||||||
|
up_read(&dev->attach_lock);
|
||||||
|
attach_locked = false;
|
||||||
|
mutex_lock(&dev->mutex);
|
||||||
|
/*
|
||||||
|
* Check device hasn't become detached behind our back.
|
||||||
|
* Checking dev->detach_count is unchanged ought to be
|
||||||
|
* sufficient (unless there have been 2**32 detaches in the
|
||||||
|
* meantime!), but check the subdevice pointer as well just in
|
||||||
|
* case.
|
||||||
|
*/
|
||||||
|
new_s = comedi_file_write_subdevice(file);
|
||||||
|
if (dev->attached && old_detach_count == dev->detach_count &&
|
||||||
|
s == new_s && new_s->async == async)
|
||||||
|
do_become_nonbusy(dev, s);
|
||||||
|
mutex_unlock(&dev->mutex);
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
if (on_wait_queue)
|
|
||||||
remove_wait_queue(&async->wait_head, &wait);
|
|
||||||
set_current_state(TASK_RUNNING);
|
|
||||||
if (attach_locked)
|
if (attach_locked)
|
||||||
up_read(&dev->attach_lock);
|
up_read(&dev->attach_lock);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user