lkml.org 
[lkml]   [2000]   [Jul]   [12]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
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/

\
 
 \ /
  Last update: 2005-03-22 13:57    [W:0.033 / U:0.836 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site