[PATCH] ncpfs update for poll changes

From: Manfred (manfred@colorfullife.com)
Date: Wed Jul 12 2000 - 07:03:55 EST


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/



This archive was generated by hypermail 2b29 : Sat Jul 15 2000 - 21:00:14 EST