diff -urN test.orig/drivers/block/loop.c test/drivers/block/loop.c
--- test.orig/drivers/block/loop.c	Thu Feb  7 08:13:01 2002
+++ test/drivers/block/loop.c	Thu Feb  7 08:36:53 2002
@@ -278,7 +278,7 @@
 	spin_lock_irq(&lo->lo_lock);
 	file = lo->lo_backing_file;
 	spin_unlock_irq(&lo->lo_lock);
-	do_generic_file_read(file, &pos, &desc, lo_read_actor);
+	do_generic_file_read(file, &pos, &desc, lo_read_actor, 0);
 	return desc.error;
 }
 
diff -urN test.orig/include/linux/errno.h test/include/linux/errno.h
--- test.orig/include/linux/errno.h	Thu Feb  7 08:12:12 2002
+++ test/include/linux/errno.h	Thu Feb  7 08:36:53 2002
@@ -21,6 +21,9 @@
 #define EBADTYPE	527	/* Type not supported by server */
 #define EJUKEBOX	528	/* Request initiated, but will not complete before timeout */
 
+/* Defined for TUX async IO */
+#define EWOULDBLOCKIO	530	/* Would block due to block-IO */
+
 #endif
 
 #endif
diff -urN test.orig/include/linux/fs.h test/include/linux/fs.h
--- test.orig/include/linux/fs.h	Thu Feb  7 08:12:16 2002
+++ test/include/linux/fs.h	Thu Feb  7 08:38:28 2002
@@ -794,6 +794,10 @@
  * read, write, poll, fsync, readv, writev can be called
  *   without the big kernel lock held in all filesystems.
  */
+
+#define F_ATOMIC	0x0001
+#define F_OFFSETOK	0x0002
+
 struct file_operations {
 	struct module *owner;
 	loff_t (*llseek) (struct file *, loff_t, int);
@@ -1487,12 +1491,13 @@
 extern int file_read_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size);
 extern ssize_t generic_file_read(struct file *, char *, size_t, loff_t *);
 extern ssize_t generic_file_write(struct file *, const char *, size_t, loff_t *);
-extern void do_generic_file_read(struct file *, loff_t *, read_descriptor_t *, read_actor_t);
-extern loff_t no_llseek(struct file *file, loff_t offset, int origin);
-extern loff_t generic_file_llseek(struct file *file, loff_t offset, int origin);
+extern void do_generic_file_read(struct file *, loff_t *, read_descriptor_t *, read_actor_t, int);
+
 extern loff_t remote_llseek(struct file *file, loff_t offset, int origin);
 extern ssize_t generic_read_dir(struct file *, char *, size_t, loff_t *);
 extern int generic_file_open(struct inode * inode, struct file * filp);
+extern loff_t no_llseek(struct file *file, loff_t offset, int origin);
+extern loff_t generic_file_llseek(struct file *file, loff_t offset, int origin);
 
 extern struct file_operations generic_ro_fops;
 
diff -urN test.orig/mm/filemap.c test/mm/filemap.c
--- test.orig/mm/filemap.c	Thu Feb  7 08:12:31 2002
+++ test/mm/filemap.c	Thu Feb  7 08:36:53 2002
@@ -1139,7 +1139,7 @@
 
 static void generic_file_readahead(int reada_ok,
 	struct file * filp, struct inode * inode,
-	struct page * page)
+	struct page * page, int flags)
 {
 	unsigned long end_index;
 	unsigned long index = page->index;
@@ -1269,7 +1269,7 @@
  * This is really ugly. But the goto's actually try to clarify some
  * of the logic when it comes to error handling etc.
  */
-void do_generic_file_read(struct file * filp, loff_t *ppos, read_descriptor_t * desc, read_actor_t actor)
+void do_generic_file_read(struct file * filp, loff_t *ppos, read_descriptor_t * desc, read_actor_t actor, int flags)
 {
 	struct address_space *mapping = filp->f_dentry->d_inode->i_mapping;
 	struct inode *inode = mapping->host;
@@ -1328,13 +1328,17 @@
 
 		end_index = inode->i_size >> PAGE_CACHE_SHIFT;
 			
-		if (index > end_index)
+		if (index > end_index) {
+			desc->error = 0;
 			break;
+		}
 		nr = PAGE_CACHE_SIZE;
 		if (index == end_index) {
 			nr = inode->i_size & ~PAGE_CACHE_MASK;
-			if (nr <= offset)
+			if (nr <= offset) {
+				desc->error = 0;
 				break;
+			}
 		}
 
 		nr = nr - offset;
@@ -1354,7 +1358,7 @@
 
 		if (!Page_Uptodate(page))
 			goto page_not_up_to_date;
-		generic_file_readahead(reada_ok, filp, inode, page);
+		generic_file_readahead(reada_ok, filp, inode, page, flags);
 page_ok:
 		/* If users can be writing to this page using arbitrary
 		 * virtual addresses, take care about potential aliasing
@@ -1394,13 +1398,24 @@
  * Ok, the page was not immediately readable, so let's try to read ahead while we're at it..
  */
 page_not_up_to_date:
-		generic_file_readahead(reada_ok, filp, inode, page);
+		generic_file_readahead(reada_ok, filp, inode, page, flags);
 
 		if (Page_Uptodate(page))
 			goto page_ok;
 
 		/* Get exclusive access to the page ... */
-		lock_page(page);
+		if (flags & F_ATOMIC) {
+			if (TryLockPage(page)) {
+				if (Page_Uptodate(page))
+					goto page_ok;
+				printk("page_not_up_to_date: -EAGAIN\n");
+				desc->error = -EWOULDBLOCKIO;
+				page_cache_release(page);
+				break;
+			}
+			printk("page_not_up_to_date: atomic trylock succeeded\n");
+		} else
+			lock_page(page);
 
 		/* Did it get unhashed before we got the lock? */
 		if (!page->mapping) {
@@ -1424,11 +1439,12 @@
 				goto page_ok;
 
 			/* Again, try some read-ahead while waiting for the page to finish.. */
-			generic_file_readahead(reada_ok, filp, inode, page);
-			wait_on_page(page);
+			generic_file_readahead(reada_ok, filp, inode, page, flags);
+			if (!(flags & F_ATOMIC))
+				wait_on_page(page);
 			if (Page_Uptodate(page))
 				goto page_ok;
-			error = -EIO;
+			error = (flags & F_ATOMIC) ? -EWOULDBLOCKIO : -EIO;
 		}
 
 		/* UHHUH! A synchronous read error occurred. Report it */
@@ -1437,6 +1453,11 @@
 		break;
 
 no_cached_page:
+		if (flags & F_ATOMIC) {
+			spin_unlock(&pagecache_lock);
+			desc->error = -EWOULDBLOCKIO;
+			break;
+		}
 		/*
 		 * Ok, it wasn't cached, so we need to create a new
 		 * page..
@@ -1608,7 +1629,7 @@
 			desc.count = count;
 			desc.buf = buf;
 			desc.error = 0;
-			do_generic_file_read(filp, ppos, &desc, file_read_actor);
+			do_generic_file_read(filp, ppos, &desc, file_read_actor, 0);
 
 			retval = desc.written;
 			if (!retval)
@@ -1733,7 +1754,7 @@
 		desc.count = count;
 		desc.buf = (char *) out_file;
 		desc.error = 0;
-		do_generic_file_read(in_file, ppos, &desc, file_send_actor);
+		do_generic_file_read(in_file, ppos, &desc, file_send_actor, 0);
 
 		retval = desc.written;
 		if (!retval)
diff -urN test.orig/net/khttpd/datasending.c test/net/khttpd/datasending.c
--- test.orig/net/khttpd/datasending.c	Thu Feb  7 08:13:10 2002
+++ test/net/khttpd/datasending.c	Thu Feb  7 08:36:53 2002
@@ -127,7 +127,7 @@
 				desc.count = ReadSize;
 				desc.buf = (char *) CurrentRequest->sock;
 				desc.error = 0;
-				do_generic_file_read(CurrentRequest->filp, ppos, &desc, sock_send_actor);
+				do_generic_file_read(CurrentRequest->filp, ppos, &desc, sock_send_actor, 0);
 				if (desc.written>0)
 				{	
 					CurrentRequest->BytesSent += desc.written;