Messages in this thread Patch in this message | | | Date | Wed, 12 Jul 2000 14:03:55 +0200 (CEST) | From | Manfred <> | Subject | [PATCH] ncpfs update for poll changes |
| |
Linus fixed an oopsable bug in fs/select.c, and that broke ncpfs.
Below is an update for ncpfs, but I couldn't test it.
Please give it a try, Manfred
<<<<<<<<< // $Header$ // Kernel Version: // VERSION = 2 // PATCHLEVEL = 4 // SUBLEVEL = 0 // EXTRAVERSION = -test4 --- 2.4/fs/select.c Wed Jul 12 12:37:13 2000 +++ build-2.4/fs/select.c Wed Jul 12 13:13:09 2000 @@ -31,14 +31,15 @@ * understand what I'm doing here, then you understand how the linux * sleep/wakeup mechanism works. * - * Two very simple procedures, poll_wait() and free_wait() make all the + * Two very simple procedures, poll_wait() and poll_freewait() make all the * work. poll_wait() is an inline-function defined in <linux/poll.h>, * as all select/poll functions have to call it to add an entry to the * poll table. */ -static void free_wait(struct poll_table_page * p) +void poll_freewait(poll_table* pt) { + struct poll_table_page * p = pt->table; while (p) { struct poll_table_entry * entry; struct poll_table_page *old; @@ -66,6 +67,7 @@ new_table = (struct poll_table_page *) __get_free_page(GFP_KERNEL); if (!new_table) { p->error = -ENOMEM; + __set_current_state(TASK_RUNNING); return; } new_table->nr = 0; @@ -160,8 +162,7 @@ return retval; n = retval; - table.error = 0; - table.table = NULL; + poll_initwait(&table); wait = &table; retval = 0; for (;;) { @@ -201,11 +202,15 @@ wait = NULL; if (retval || !__timeout || signal_pending(current)) break; + if(table.error) { + retval = table.error; + break; + } __timeout = schedule_timeout(__timeout); } current->state = TASK_RUNNING; - free_wait(table.table); + poll_freewait(&table); /* * Up-to-date the caller timeout. @@ -354,18 +359,22 @@ struct pollfd *fds[], poll_table *wait, long timeout) { int count = 0; + poll_table* pt = wait; for (;;) { unsigned int i; set_current_state(TASK_INTERRUPTIBLE); for (i=0; i < nchunks; i++) - do_pollfd(POLLFD_PER_PAGE, fds[i], &wait, &count); + do_pollfd(POLLFD_PER_PAGE, fds[i], &pt, &count); if (nleft) - do_pollfd(nleft, fds[nchunks], &wait, &count); - wait = NULL; + do_pollfd(nleft, fds[nchunks], &pt, &count); + pt = NULL; if (count || !timeout || signal_pending(current)) break; + if(wait->error) { + return wait->error; + } timeout = schedule_timeout(timeout); } current->state = TASK_RUNNING; @@ -391,8 +400,7 @@ timeout = MAX_SCHEDULE_TIMEOUT; } - table.error = 0; - table.table = NULL; + poll_initwait(&table); err = -ENOMEM; fds = NULL; @@ -452,6 +460,6 @@ if (nfds != 0) kfree(fds); out: - free_wait(table.table); + poll_freewait(&table); return err; } --- 2.4/include/linux/poll.h Wed Jul 12 12:37:15 2000 +++ build-2.4/include/linux/poll.h Wed Jul 12 12:53:07 2000 @@ -38,22 +38,13 @@ __pollwait(filp, wait_address, p); } -/* - * For the kernel fd_set we use a fixed set-size for allocation purposes. - * This set-size doesn't necessarily bear any relation to the size the user - * uses, but should preferably obviously be larger than any possible user - * size (NR_OPEN bits). - * - * We need 6 bitmaps (in/out/ex for both incoming and outgoing), and we - * allocate one page for all the bitmaps. Thus we have 8*PAGE_SIZE bits, - * to be divided by 6. And we'd better make sure we round to a full - * long-word (in fact, we'll round to 64 bytes). - */ +static inline void poll_initwait(poll_table* pt) +{ + pt->error = 0; + pt->table = NULL; +} +extern void poll_freewait(poll_table* pt); - -#define KFDS_64BLOCK ((PAGE_SIZE/(6*64))*64) -#define KFDS_NR (KFDS_64BLOCK*8 > NR_OPEN ? NR_OPEN : KFDS_64BLOCK*8) -typedef unsigned long kernel_fd_set[KFDS_NR/__NFDBITS]; /* * Scaleable version of the fd_set. --- 2.4/fs/ncpfs/sock.c Tue Jul 11 18:36:47 2000 +++ build-2.4/fs/ncpfs/sock.c Wed Jul 12 13:19:20 2000 @@ -87,7 +87,6 @@ int result; char *start = server->packet; poll_table wait_table; - struct poll_table_entry entry; int init_timeout, max_timeout; int timeout; int retrans; @@ -136,8 +135,7 @@ break; } re_select: - wait_table.nr = 0; - wait_table.entry = &entry; + poll_initwait(&wait_table); /* mb() is not necessary because ->poll() will serialize instructions adding the wait_table waitqueues in the waitqueue-head before going to calculate the mask-retval. */ @@ -154,13 +152,16 @@ timeout = max_timeout; } timed_out = !schedule_timeout(timeout); - remove_wait_queue(entry.wait_address, &entry.wait); - fput(file); + poll_freewait(&wait_table); current->state = TASK_RUNNING; if (signal_pending(current)) { result = -ERESTARTSYS; break; } + if(wait_table.error) { + result = wait_table.error; + break; + } if (timed_out) { if (n < retrans) continue; @@ -179,9 +180,8 @@ major_timeout_seen = 1; continue; } - } else if (wait_table.nr) { - remove_wait_queue(entry.wait_address, &entry.wait); - fput(file); + } else { + poll_freewait(&wait_table); } current->state = TASK_RUNNING; @@ -262,7 +262,6 @@ static int do_tcp_rcv(struct ncp_server *server, void *buffer, size_t len) { poll_table wait_table; - struct poll_table_entry entry; struct file *file; struct socket *sock; int init_timeout; @@ -281,16 +280,14 @@ init_timeout = 0x7FFF0000; while (len) { - wait_table.nr = 0; - wait_table.entry = &entry; + poll_initwait(&wait_table); /* mb() is not necessary because ->poll() will serialize instructions adding the wait_table waitqueues in the waitqueue-head before going to calculate the mask-retval. */ __set_current_state(TASK_INTERRUPTIBLE); if (!(sock->ops->poll(file, sock, &wait_table) & POLLIN)) { init_timeout = schedule_timeout(init_timeout); - remove_wait_queue(entry.wait_address, &entry.wait); - fput(file); + poll_freewait(&wait_table); current->state = TASK_RUNNING; if (signal_pending(current)) { return -ERESTARTSYS; @@ -298,9 +295,11 @@ if (!init_timeout) { return -EIO; } - } else if (wait_table.nr) { - remove_wait_queue(entry.wait_address, &entry.wait); - fput(file); + if(wait_table.error) { + return wait_table.error; + } + } else { + poll_freewait(&wait_table); } current->state = TASK_RUNNING; --- 2.4/arch/sparc64/solaris/timod.c Sat Jun 24 11:07:29 2000 +++ build-2.4/arch/sparc64/solaris/timod.c Wed Jul 12 13:06:53 2000 @@ -619,22 +619,6 @@ return -EINVAL; } -/* copied directly from fs/select.c */ - -static void free_wait(poll_table * p) -{ - struct poll_table_entry * entry = p->entry + p->nr; - - SOLD("entry"); - while (p->nr > 0) { - p->nr--; - entry--; - remove_wait_queue(entry->wait_address,&entry->wait); - } - SOLD("done"); -} - - int timod_getmsg(unsigned int fd, char *ctl_buf, int ctl_maxlen, s32 *ctl_len, char *data_buf, int data_maxlen, s32 *data_len, int *flags_p) { @@ -670,14 +654,8 @@ } if (!(filp->f_flags & O_NONBLOCK)) { poll_table wait_table, *wait; - struct poll_table_entry *entry; - SOLD("getting poll_table"); - entry = (struct poll_table_entry *)__get_free_page(GFP_KERNEL); - if (!entry) - return -ENOMEM; - SOLD("got one"); - wait_table.nr = 0; - wait_table.entry = entry; + + poll_initwait(&wait_table); wait = &wait_table; for(;;) { SOLD("loop"); @@ -705,13 +683,16 @@ SOLD("avoiding lockup"); break ; } + if(wait_table.error) { + poll_freewait(&wait_table); + return wait_table.error; + } SOLD("scheduling"); schedule(); } SOLD("loop done"); current->state = TASK_RUNNING; - free_wait(&wait_table); - free_page((unsigned long)entry); + poll_freewait(&wait_table); if (signal_pending(current)) { SOLD("signal pending"); return -EINTR;
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/
| |