patch-2.4.0-test5 linux/fs/select.c

Next file: linux/fs/smbfs/ChangeLog
Previous file: linux/fs/qnx4/inode.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.0-test4/linux/fs/select.c linux/fs/select.c
@@ -24,6 +24,21 @@
 #define ROUND_UP(x,y) (((x)+(y)-1)/(y))
 #define DEFAULT_POLLMASK (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM)
 
+struct poll_table_entry {
+	struct file * filp;
+	wait_queue_t wait;
+	wait_queue_head_t * wait_address;
+};
+
+struct poll_table_page {
+	struct poll_table_page * next;
+	struct poll_table_entry * entry;
+	struct poll_table_entry entries[0];
+};
+
+#define POLL_TABLE_FULL(table) \
+	((unsigned long)((table)->entry+1) > PAGE_SIZE + (unsigned long)(table))
+
 /*
  * Ok, Peter made a complicated, but straightforward multiple_wait() function.
  * I have rewritten this, taking some shortcuts: This code may not be easy to
@@ -44,13 +59,12 @@
 		struct poll_table_entry * entry;
 		struct poll_table_page *old;
 
-		entry = p->entry + p->nr;
-		while (p->nr > 0) {
-			p->nr--;
+		entry = p->entry;
+		do {
 			entry--;
 			remove_wait_queue(entry->wait_address,&entry->wait);
 			fput(entry->filp);
-		}
+		} while (entry > p->entries);
 		old = p;
 		p = p->next;
 		free_page((unsigned long) old);
@@ -61,7 +75,7 @@
 {
 	struct poll_table_page *table = p->table;
 
-	if (!table || table->nr >= __MAX_POLL_TABLE_ENTRIES) {
+	if (!table || POLL_TABLE_FULL(table)) {
 		struct poll_table_page *new_table;
 
 		new_table = (struct poll_table_page *) __get_free_page(GFP_KERNEL);
@@ -70,8 +84,7 @@
 			__set_current_state(TASK_RUNNING);
 			return;
 		}
-		new_table->nr = 0;
-		new_table->entry = (struct poll_table_entry *)(new_table + 1);
+		new_table->entry = new_table->entries;
 		new_table->next = table;
 		p->table = new_table;
 		table = new_table;
@@ -79,9 +92,8 @@
 
 	/* Add a new entry */
 	{
-		struct poll_table_entry * entry;
-	 	entry = table->entry + table->nr;
-		table->nr++;
+		struct poll_table_entry * entry = table->entry;
+		table->entry = entry+1;
 	 	get_file(filp);
 	 	entry->filp = filp;
 		entry->wait_address = wait_address;
@@ -221,6 +233,16 @@
 	return retval;
 }
 
+static void *select_bits_alloc(int size)
+{
+	return kmalloc(6 * size, GFP_KERNEL);
+}
+
+static void select_bits_free(void *bits, int size)
+{
+	kfree(bits);
+}
+
 /*
  * We can actually return ERESTARTSYS instead of EINTR, but I'd
  * like to be certain this leads to no problems. So I return
@@ -273,7 +295,7 @@
 	 */
 	ret = -ENOMEM;
 	size = FDS_BYTES(n);
-	bits = kmalloc(6 * size, GFP_KERNEL);
+	bits = select_bits_alloc(size);
 	if (!bits)
 		goto out_nofds;
 	fds.in      = (unsigned long *)  bits;
@@ -318,7 +340,7 @@
 	set_fd_set(n, exp, fds.res_ex);
 
 out:
-	kfree(bits);
+	select_bits_free(bits, size);
 out_nofds:
 	return ret;
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)