Messages in this thread Patch in this message | | | Date | Mon, 10 Jan 2000 02:27:16 -0600 | From | Bill Wendling <> | 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] | |