lkml.org 
[lkml]   [2000]   [Feb]   [1]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
SubjectRe: gfp called by non-running (1) task from c012ee46
rtviado@iligan.com wrote:
>
> I'm running squid on 2.2.15pre5 and i got this message from the console
>
> gfp called by non-running (1) task from c012ee46!
> [...]
> c012edd8 T __pollwait
> c012ee70 t max_select_fd
> c012ef10 T do_select
>

Yes, that's a real bug:
__pollwait() allocated new memory if you either select() or poll() with
more than ~1000 file descriptors.

Could you try the attached patch? [only slightly tested]

--
Manfred--- 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;
}
\
 
 \ /
  Last update: 2005-03-22 13:56    [W:1.535 / U:0.540 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site