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:
Ian Abbott 2015-11-18 17:55:04 +00:00 committed by Greg Kroah-Hartman
parent b4717ff608
commit 06181de14f

View File

@ -2307,7 +2307,7 @@ static ssize_t comedi_write(struct file *file, const char __user *buf,
DECLARE_WAITQUEUE(wait, current);
struct comedi_file *cfp = file->private_data;
struct comedi_device *dev = cfp->dev;
bool on_wait_queue = false;
bool become_nonbusy = false;
bool attach_locked;
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);
on_wait_queue = true;
while (nbytes > 0 && !retval) {
while (count == 0 && !retval) {
unsigned runflags;
set_current_state(TASK_INTERRUPTIBLE);
runflags = comedi_get_subdevice_runflags(s);
if (!comedi_is_runflags_running(runflags)) {
if (count == 0) {
struct comedi_subdevice *new_s;
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);
}
if (comedi_is_runflags_in_error(runflags))
retval = -EPIPE;
become_nonbusy = true;
break;
}
@ -2433,12 +2401,33 @@ static ssize_t comedi_write(struct file *file, const char __user *buf,
nbytes -= 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:
if (on_wait_queue)
remove_wait_queue(&async->wait_head, &wait);
set_current_state(TASK_RUNNING);
if (attach_locked)
up_read(&dev->attach_lock);