lkml.org 
[lkml]   [2000]   [Jan]   [10]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
Subject[PATCH] Polling > 16000 FDs, Take 2
Here is a solution to the problem of polling > 16000 file descriptors at
a time. It uses the `vmalloc()' solution which was discussed earlier. I
couldn't get the `linked list' solution to work. I've included the patch
which works (patch-16000.poll) to be added and the one which doesn't
(patch-16000.poll.bad.gz) in case people would like to futz with it and
make it work more efficiently than the vmalloc solution.

In brief, the "bad" patch seems to cause excessive pollings on files for
some programs. Specifically, when booting my computer, it seems to do
this for the AMD and Linuxconf stuff (Yes, I have RedHat). It also does
it when I run `mutt'.

Share and enjoy!
Bill
--- linux-2.3.39-pre2.old/fs/select.c Tue Aug 31 13:30:48 1999
+++ linux-2.3.39-pre2/fs/select.c Mon Jan 10 02:19:21 2000
@@ -14,6 +14,7 @@
#include <linux/smp_lock.h>
#include <linux/poll.h>
#include <linux/file.h>
+#include <linux/vmalloc.h>

#include <asm/uaccess.h>

@@ -375,7 +376,7 @@
{
int i, fdcount, err, size;
struct pollfd * fds, *fds1;
- poll_table *wait_table = NULL, *wait = NULL;
+ poll_table *wait = NULL;

lock_kernel();
/* Do a sanity check on nfds ... */
@@ -384,7 +385,7 @@
goto out;

if (timeout) {
- /* Carefula about overflow in the intermediate values */
+ /* Careful about overflow in the intermediate values */
if ((unsigned long) timeout < MAX_SCHEDULE_TIMEOUT / HZ)
timeout = (unsigned long)(timeout*HZ+999)/1000+1;
else /* Negative or overflow */
@@ -393,19 +394,25 @@

err = -ENOMEM;
if (timeout) {
- wait_table = (poll_table *) __get_free_page(GFP_KERNEL);
- if (!wait_table)
+ wait = (poll_table *)__get_free_page(GFP_KERNEL);
+ if (!wait)
goto out;
- wait_table->nr = 0;
- wait_table->entry = (struct poll_table_entry *)(wait_table + 1);
- wait_table->next = NULL;
- wait = wait_table;
+ wait->nr = 0;
+ wait->entry = (struct poll_table_entry *)(wait + 1);
+ wait->next = NULL;
}

size = nfds * sizeof(struct pollfd);
- fds = (struct pollfd *) kmalloc(size, GFP_KERNEL);
+
+ if (size < PAGE_SIZE)
+ fds = (struct pollfd *)kmalloc(size, GFP_KERNEL);
+ else if (size == PAGE_SIZE)
+ fds = (struct pollfd *)__get_free_page(GFP_KERNEL);
+ else
+ fds = (struct pollfd *)vmalloc(size);
+
if (!fds)
- goto out;
+ goto out_nomem;

err = -EFAULT;
if (copy_from_user(fds, ufds, size))
@@ -415,19 +422,23 @@

/* OK, now copy the revents fields back to user space. */
fds1 = fds;
- for(i=0; i < (int)nfds; i++, ufds++, fds1++) {
+ for (i = 0; i < (int)nfds; i++, ufds++, fds1++)
__put_user(fds1->revents, &ufds->revents);
- }

err = fdcount;
if (!fdcount && signal_pending(current))
err = -EINTR;

out_fds:
- kfree(fds);
+ if (size < PAGE_SIZE)
+ kfree(fds);
+ else if (size == PAGE_SIZE)
+ free_page((unsigned long)fds);
+ else
+ vfree(fds);
+out_nomem:
+ free_wait(wait);
out:
- if (wait)
- free_wait(wait_table);
unlock_kernel();
return err;
}[unhandled content-type:application/x-gunzip]
\
 
 \ /
  Last update: 2005-03-22 13:55    [W:0.054 / U:0.804 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site