diff options
author | Founder Fang <founder.fang@gmail.com> | 2012-11-21 02:20:31 -0500 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2012-11-26 08:18:15 -0500 |
commit | 7611e8d26d8dd0e5e132b46e905cb579daf9da1e (patch) | |
tree | 5cf31a59a211195fd15d9f6089b79fd64a1bebcf /drivers/hid/hidraw.c | |
parent | 1a1e8c6fada5f6dc48aa5dad453c9d9ebfdc8218 (diff) |
HID: hidraw: fix nonblock read return EAGAIN after device removed
When nonblock read the condition check (file->f_flags & O_NONBLOCK) always be
true, signal_pending and device exist checking never get a chance to run, so
the user mode code always get EAGAIN even if device removed. move nonblock mode
checking to the last can fix this problem.
Signed-off-by: Founder Fang <founder.fang@gmail.com>
Reviewed-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid/hidraw.c')
-rw-r--r-- | drivers/hid/hidraw.c | 8 |
1 files changed, 4 insertions, 4 deletions
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c index 7c47fc3f7b2b..1d8c0219117e 100644 --- a/drivers/hid/hidraw.c +++ b/drivers/hid/hidraw.c | |||
@@ -57,10 +57,6 @@ static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count, | |||
57 | set_current_state(TASK_INTERRUPTIBLE); | 57 | set_current_state(TASK_INTERRUPTIBLE); |
58 | 58 | ||
59 | while (list->head == list->tail) { | 59 | while (list->head == list->tail) { |
60 | if (file->f_flags & O_NONBLOCK) { | ||
61 | ret = -EAGAIN; | ||
62 | break; | ||
63 | } | ||
64 | if (signal_pending(current)) { | 60 | if (signal_pending(current)) { |
65 | ret = -ERESTARTSYS; | 61 | ret = -ERESTARTSYS; |
66 | break; | 62 | break; |
@@ -69,6 +65,10 @@ static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count, | |||
69 | ret = -EIO; | 65 | ret = -EIO; |
70 | break; | 66 | break; |
71 | } | 67 | } |
68 | if (file->f_flags & O_NONBLOCK) { | ||
69 | ret = -EAGAIN; | ||
70 | break; | ||
71 | } | ||
72 | 72 | ||
73 | /* allow O_NONBLOCK to work well from other threads */ | 73 | /* allow O_NONBLOCK to work well from other threads */ |
74 | mutex_unlock(&list->read_mutex); | 74 | mutex_unlock(&list->read_mutex); |