diff -urNp x-ref/include/linux/fs.h x/include/linux/fs.h --- x-ref/include/linux/fs.h 2003-01-31 01:32:19.000000000 +0100 +++ x/include/linux/fs.h 2003-01-31 01:32:21.000000000 +0100 @@ -1478,7 +1478,9 @@ extern int file_read_actor(read_descript 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 ssize_t generic_file_write_nolock(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 void __do_generic_file_read(struct file *, loff_t *, read_descriptor_t *, read_actor_t, int); +#define do_generic_file_read(filp, ppos, desc, actor) __do_generic_file_read(filp, ppos, desc, actor, 0) +#define do_generic_file_read_atomic(filp, ppos, desc, actor) __do_generic_file_read(filp, ppos, desc, actor, 1) 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 ssize_t generic_read_dir(struct file *, char *, size_t, loff_t *); diff -urNp x-ref/kernel/ksyms.c x/kernel/ksyms.c --- x-ref/kernel/ksyms.c 2003-01-31 01:32:14.000000000 +0100 +++ x/kernel/ksyms.c 2003-01-31 01:33:04.000000000 +0100 @@ -224,7 +224,7 @@ EXPORT_SYMBOL(generic_commit_write); EXPORT_SYMBOL(block_truncate_page); EXPORT_SYMBOL(generic_block_bmap); EXPORT_SYMBOL(generic_file_read); -EXPORT_SYMBOL(do_generic_file_read); +EXPORT_SYMBOL(__do_generic_file_read); EXPORT_SYMBOL(generic_file_write); EXPORT_SYMBOL(generic_file_write_nolock); EXPORT_SYMBOL(generic_file_mmap); diff -urNp x-ref/mm/filemap.c x/mm/filemap.c --- x-ref/mm/filemap.c 2003-01-31 01:32:15.000000000 +0100 +++ x/mm/filemap.c 2003-01-31 01:32:21.000000000 +0100 @@ -1294,7 +1294,7 @@ void mark_page_accessed(struct page *pag * 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 nonblock) { struct address_space *mapping = filp->f_dentry->d_inode->i_mapping; struct inode *inode = mapping->host; @@ -1377,9 +1377,16 @@ found_page: page_cache_get(page); spin_unlock(&pagecache_lock); - if (!Page_Uptodate(page)) + if (!Page_Uptodate(page)) { + if (nonblock) { + page_cache_release(page); + desc->error = -EWOULDBLOCKIO; + break; + } goto page_not_up_to_date; - generic_file_readahead(reada_ok, filp, inode, page); + } + if (!nonblock) + generic_file_readahead(reada_ok, filp, inode, page); page_ok: /* If users can be writing to this page using arbitrary * virtual addresses, take care about potential aliasing @@ -1465,6 +1472,11 @@ readpage: break; no_cached_page: + if (nonblock) { + spin_unlock(&pagecache_lock); + desc->error = -EWOULDBLOCKIO; + break; + } /* * Ok, it wasn't cached, so we need to create a new * page..