X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=fs%2Fselect.c;h=f10a10317d5494e0eb4995d9c016113a093f34ee;hb=a7c243b544c0e9f6775c2607decaa59d54fb9e11;hp=25b1ccac2f2cdcc73cbc42135837bfed752e7f9e;hpb=1da177e4c3f41524e886b7f1b8a0c1fc7321cac2;p=linux-2.6 diff --git a/fs/select.c b/fs/select.c index 25b1ccac2f..f10a10317d 100644 --- a/fs/select.c +++ b/fs/select.c @@ -22,6 +22,7 @@ #include /* for STICKY_TIMEOUTS */ #include #include +#include #include @@ -55,7 +56,8 @@ struct poll_table_page { * as all select/poll functions have to call it to add an entry to the * poll table. */ -void __pollwait(struct file *filp, wait_queue_head_t *wait_address, poll_table *p); +static void __pollwait(struct file *filp, wait_queue_head_t *wait_address, + poll_table *p); void poll_initwait(struct poll_wqueues *pwq) { @@ -87,7 +89,8 @@ void poll_freewait(struct poll_wqueues *pwq) EXPORT_SYMBOL(poll_freewait); -void __pollwait(struct file *filp, wait_queue_head_t *wait_address, poll_table *_p) +static void __pollwait(struct file *filp, wait_queue_head_t *wait_address, + poll_table *_p) { struct poll_wqueues *p = container_of(_p, struct poll_wqueues, pt); struct poll_table_page *table = p->table; @@ -130,11 +133,13 @@ static int max_select_fd(unsigned long n, fd_set_bits *fds) unsigned long *open_fds; unsigned long set; int max; + struct fdtable *fdt; /* handle last in-complete long-word first */ set = ~(~0UL << (n & (__NFDBITS-1))); n /= __NFDBITS; - open_fds = current->files->open_fds->fds_bits+n; + fdt = files_fdtable(current->files); + open_fds = fdt->open_fds->fds_bits+n; max = 0; if (set) { set &= BITS(fds, n); @@ -181,9 +186,9 @@ int do_select(int n, fd_set_bits *fds, long *timeout) int retval, i; long __timeout = *timeout; - spin_lock(¤t->files->file_lock); + rcu_read_lock(); retval = max_select_fd(n, fds); - spin_unlock(¤t->files->file_lock); + rcu_read_unlock(); if (retval < 0) return retval; @@ -297,6 +302,7 @@ sys_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, s char *bits; long timeout; int ret, size, max_fdset; + struct fdtable *fdt; timeout = MAX_SCHEDULE_TIMEOUT; if (tvp) { @@ -324,7 +330,10 @@ sys_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, s goto out_nofds; /* max_fdset can increase, so grab it once to avoid race */ - max_fdset = current->files->max_fdset; + rcu_read_lock(); + fdt = files_fdtable(current->files); + max_fdset = fdt->max_fdset; + rcu_read_unlock(); if (n > max_fdset) n = max_fdset; @@ -462,9 +471,15 @@ asmlinkage long sys_poll(struct pollfd __user * ufds, unsigned int nfds, long ti unsigned int i; struct poll_list *head; struct poll_list *walk; + struct fdtable *fdt; + int max_fdset; /* Do a sanity check on nfds ... */ - if (nfds > current->files->max_fdset && nfds > OPEN_MAX) + rcu_read_lock(); + fdt = files_fdtable(current->files); + max_fdset = fdt->max_fdset; + rcu_read_unlock(); + if (nfds > max_fdset && nfds > OPEN_MAX) return -EINVAL; if (timeout) {