Commit 64baa00b authored by Russell King's avatar Russell King

[PCMCIA] Get rid of racy interruptible_sleep_on()

ds.c uses interruptible_sleep_on() without any protection.  Use
wait_event_interruptible() instead.

In addition, fix a bug where threads waiting for cardmgr events to
complete were left waiting if cardmgr exited.
parent 3b32a7e7
...@@ -253,13 +253,10 @@ static int handle_request(struct pcmcia_bus_socket *s, event_t event) ...@@ -253,13 +253,10 @@ static int handle_request(struct pcmcia_bus_socket *s, event_t event)
if (s->state & SOCKET_BUSY) if (s->state & SOCKET_BUSY)
s->req_pending = 1; s->req_pending = 1;
handle_event(s, event); handle_event(s, event);
if (s->req_pending > 0) { if (wait_event_interruptible(s->request, s->req_pending <= 0))
interruptible_sleep_on(&s->request); return CS_IN_USE;
if (signal_pending(current)) if (s->state & SOCKET_BUSY)
return CS_IN_USE; return s->req_result;
else
return s->req_result;
}
return CS_SUCCESS; return CS_SUCCESS;
} }
...@@ -566,8 +563,11 @@ static int ds_release(struct inode *inode, struct file *file) ...@@ -566,8 +563,11 @@ static int ds_release(struct inode *inode, struct file *file)
s = user->socket; s = user->socket;
/* Unlink user data structure */ /* Unlink user data structure */
if ((file->f_flags & O_ACCMODE) != O_RDONLY) if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
s->state &= ~SOCKET_BUSY; s->state &= ~SOCKET_BUSY;
s->req_pending = 0;
wake_up_interruptible(&s->request);
}
file->private_data = NULL; file->private_data = NULL;
for (link = &s->user; *link; link = &(*link)->next) for (link = &s->user; *link; link = &(*link)->next)
if (*link == user) break; if (*link == user) break;
...@@ -589,6 +589,7 @@ static ssize_t ds_read(struct file *file, char *buf, ...@@ -589,6 +589,7 @@ static ssize_t ds_read(struct file *file, char *buf,
socket_t i = iminor(file->f_dentry->d_inode); socket_t i = iminor(file->f_dentry->d_inode);
struct pcmcia_bus_socket *s; struct pcmcia_bus_socket *s;
user_info_t *user; user_info_t *user;
int ret;
DEBUG(2, "ds_read(socket %d)\n", i); DEBUG(2, "ds_read(socket %d)\n", i);
...@@ -603,13 +604,11 @@ static ssize_t ds_read(struct file *file, char *buf, ...@@ -603,13 +604,11 @@ static ssize_t ds_read(struct file *file, char *buf,
if (s->state & SOCKET_DEAD) if (s->state & SOCKET_DEAD)
return -EIO; return -EIO;
if (queue_empty(user)) { ret = wait_event_interruptible(s->queue, !queue_empty(user));
interruptible_sleep_on(&s->queue); if (ret == 0)
if (signal_pending(current)) ret = put_user(get_queued_event(user), (int *)buf) ? -EFAULT : 4;
return -EINTR;
}
return put_user(get_queued_event(user), (int *)buf) ? -EFAULT : 4; return ret;
} /* ds_read */ } /* ds_read */
/*====================================================================*/ /*====================================================================*/
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment