lkml.org 
[lkml]   [2000]   [Jan]   [8]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
Subject[PATCH] Polling > 16000 FDs
Here's a patch for the problem with polling more than 16000 file
descriptors. The problem was that kmalloc() wouldn't let us allocate more
room than 131072 bytes at a time. I modified sys_poll() so that it will
allocation at most 131072 bytes and, if need be, loop to handle more file
descriptors using the same alloced space.

I checked it out and it ran for me. See what it does for you :-).

Bill
--- linux-2.3.38.old/fs/select.c Tue Aug 31 13:30:48 1999
+++ linux-2.3.38/fs/select.c Sat Jan 8 05:32:04 2000
@@ -371,11 +371,17 @@
return count;
}

+/*
+ * 131072 is the largest slab of memory that kmalloc lets us allocate.
+ * It's a pain that this is hardcoded...
+ */
+#define NUM_POLLFDS (131072 / sizeof(struct pollfd))
+
asmlinkage long sys_poll(struct pollfd * ufds, unsigned int nfds, long timeout)
{
- int i, fdcount, err, size;
- struct pollfd * fds, *fds1;
- poll_table *wait_table = NULL, *wait = NULL;
+ int fdcount, err, size, iter, offset, res;
+ struct pollfd *fds;
+ poll_table *wait = NULL;

lock_kernel();
/* Do a sanity check on nfds ... */
@@ -384,7 +390,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,30 +399,49 @@

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;
+ }
+
+ iter = (int)(nfds / NUM_POLLFDS) + 1;
+
+ if (iter == 1) {
+ size = nfds * sizeof(struct pollfd);
+ res = nfds;
+ } else {
+ size = NUM_POLLFDS * sizeof(struct pollfd);
+ res = nfds % NUM_POLLFDS;
}

- size = nfds * sizeof(struct pollfd);
fds = (struct pollfd *) kmalloc(size, GFP_KERNEL);
+
if (!fds)
- goto out;
+ goto out_nomem;
+
+ fdcount = 0;
+
+ for (offset = 0; iter > 0; iter--, offset += NUM_POLLFDS) {
+ struct pollfd *fds1, *ufds1;
+ unsigned int fds_num = (iter == 1 ? res : NUM_POLLFDS);
+ int i;
+
+ err = -EFAULT;
+
+ if (copy_from_user(fds, &ufds[offset], fds_num * sizeof(struct pollfd)))
+ goto out_fds;
+
+ fdcount += do_poll(fds_num, fds, wait, timeout);
+
+ /* OK, now copy the revents fields back to user space. */
+ fds1 = fds;
+ ufds1 = &ufds[offset];

- err = -EFAULT;
- if (copy_from_user(fds, ufds, size))
- goto out_fds;
-
- fdcount = do_poll(nfds, fds, wait, timeout);
-
- /* OK, now copy the revents fields back to user space. */
- fds1 = fds;
- for(i=0; i < (int)nfds; i++, ufds++, fds1++) {
- __put_user(fds1->revents, &ufds->revents);
+ for (i = 0; i < (int)fds_num; i++, ufds1++, fds1++)
+ __put_user(fds1->revents, &ufds1->revents);
}

err = fdcount;
@@ -425,9 +450,9 @@

out_fds:
kfree(fds);
+out_nomem:
+ free_wait(wait);
out:
- if (wait)
- free_wait(wait_table);
unlock_kernel();
return err;
}
\
 
 \ /
  Last update: 2005-03-22 13:55    [W:0.166 / U:0.240 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site