[PATCH] fix __pollwait()

From: Manfred Spraul (manfreds@colorfullife.com)
Date: Tue Feb 01 2000 - 16:48:19 EST


Hi Alan,

The patch below changes __pollwait(): the old code called gfp() with
!TASK_RUNNING.

I've tested the patch with 2.2.14 i386 UP, could you add it to the next
2.2 kernel?

--
	Manfred
P.S.: I've already "ported" the change to 2.3, and I'll send that patch
to Linus tomorrow.

--- 2.2/fs/select.c Thu Aug 26 17:41:21 1999 +++ build-2.2/fs/select.c Tue Feb 1 16:26:58 2000 @@ -39,6 +39,39 @@ * Linus noticed. -- jrs */ +static poll_table* alloc_wait(int nfds) +{ + poll_table* out; + poll_table* walk; + + out = (poll_table *) __get_free_page(GFP_KERNEL); + if(out==NULL) + return NULL; + out->nr = 0; + out->entry = (struct poll_table_entry *)(out + 1); + out->next = NULL; + nfds -=__MAX_POLL_TABLE_ENTRIES; + walk = out; + while(nfds > 0) { + poll_table *tmp = (poll_table *) __get_free_page(GFP_KERNEL); + if (!tmp) { + while(out != NULL) { + tmp = out->next; + free_page((unsigned long)out); + out = tmp; + } + return NULL; + } + tmp->nr = 0; + tmp->entry = (struct poll_table_entry *)(tmp + 1); + tmp->next = NULL; + walk->next = tmp; + walk = tmp; + nfds -=__MAX_POLL_TABLE_ENTRIES; + } + return out; +} + static void free_wait(poll_table * p) { struct poll_table_entry * entry; @@ -63,7 +96,6 @@ for (;;) { if (p->nr < __MAX_POLL_TABLE_ENTRIES) { struct poll_table_entry * entry; -ok_table: entry = p->entry + p->nr; entry->filp = filp; filp->f_count++; @@ -74,17 +106,6 @@ p->nr++; return; } - if (p->next == NULL) { - poll_table *tmp = (poll_table *) __get_free_page(GFP_KERNEL); - if (!tmp) - return; - tmp->nr = 0; - tmp->entry = (struct poll_table_entry *)(tmp + 1); - tmp->next = NULL; - p->next = tmp; - p = tmp; - goto ok_table; - } p = p->next; } } @@ -154,23 +175,21 @@ long __timeout = *timeout; wait = wait_table = NULL; - if (__timeout) { - wait_table = (poll_table *) __get_free_page(GFP_KERNEL); - if (!wait_table) - return -ENOMEM; - - wait_table->nr = 0; - wait_table->entry = (struct poll_table_entry *)(wait_table + 1); - wait_table->next = NULL; - wait = wait_table; - } - lock_kernel(); retval = max_select_fd(n, fds); if (retval < 0) goto out; n = retval; + if (__timeout) { + retval = -ENOMEM; + wait_table = alloc_wait(n); + if (!wait_table) + goto out; + + wait = wait_table; + } + retval = 0; for (;;) { current->state = TASK_INTERRUPTIBLE; @@ -406,12 +425,10 @@ err = -ENOMEM; if (timeout) { - wait_table = (poll_table *) __get_free_page(GFP_KERNEL); + wait_table = alloc_wait(nfds); if (!wait_table) goto out; - wait_table->nr = 0; - wait_table->entry = (struct poll_table_entry *)(wait_table + 1); - wait_table->next = NULL; + wait = wait_table; }

- 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 : Mon Feb 07 2000 - 21:00:07 EST