Index: xfs/include/linux/mm.h =================================================================== --- xfs.orig/include/linux/mm.h 2012-09-21 17:50:32.243490371 +0200 +++ xfs/include/linux/mm.h 2012-09-21 17:50:43.333490305 +0200 @@ -1467,6 +1467,12 @@ void page_cache_async_readahead(struct a pgoff_t offset, unsigned long size); +void page_cache_nonblock_readahead(struct address_space *mapping, + struct file_ra_state *ra, + struct file *filp, + pgoff_t offset, + unsigned long size); + unsigned long max_sane_readahead(unsigned long nr); unsigned long ra_submit(struct file_ra_state *ra, struct address_space *mapping, Index: xfs/mm/filemap.c =================================================================== --- xfs.orig/mm/filemap.c 2012-09-21 17:50:32.243490371 +0200 +++ xfs/mm/filemap.c 2012-09-21 18:35:53.343474115 +0200 @@ -1107,6 +1107,9 @@ static void do_generic_file_read(struct find_page: page = find_get_page(mapping, index); if (!page) { + if (filp && filp->f_flags & O_NONBLOCK) + goto short_read; + page_cache_sync_readahead(mapping, ra, filp, index, last_index - index); @@ -1218,6 +1221,12 @@ page_not_up_to_date_locked: } readpage: + if (filp && filp->f_flags & O_NONBLOCK) { + unlock_page(page); + page_cache_release(page); + goto short_read; + } + /* * A previous I/O error may have been due to temporary * failures, eg. multipath errors. @@ -1293,6 +1302,10 @@ out: *ppos = ((loff_t)index << PAGE_CACHE_SHIFT) + offset; file_accessed(filp); + return; +short_read: + page_cache_nonblock_readahead(mapping, ra, filp, index, + last_index - index); } int file_read_actor(read_descriptor_t *desc, struct page *page, @@ -1466,7 +1479,8 @@ generic_file_aio_read(struct kiocb *iocb do_generic_file_read(filp, ppos, &desc, file_read_actor); retval += desc.written; if (desc.error) { - retval = retval ?: desc.error; + if (!retval) + retval = desc.error; break; } if (desc.count > 0) Index: xfs/mm/readahead.c =================================================================== --- xfs.orig/mm/readahead.c 2012-09-21 17:50:32.243490371 +0200 +++ xfs/mm/readahead.c 2012-09-21 17:50:43.336823641 +0200 @@ -565,6 +565,22 @@ page_cache_async_readahead(struct addres } EXPORT_SYMBOL_GPL(page_cache_async_readahead); +void +page_cache_nonblock_readahead(struct address_space *mapping, + struct file_ra_state *ra, struct file *filp, + pgoff_t offset, unsigned long req_size) +{ + /* + * Defer asynchronous read-ahead on IO congestion. + */ + if (bdi_read_congested(mapping->backing_dev_info)) + return; + + /* do read-ahead */ + ondemand_readahead(mapping, ra, filp, false, offset, req_size); +} +EXPORT_SYMBOL_GPL(page_cache_nonblock_readahead); + static ssize_t do_readahead(struct address_space *mapping, struct file *filp, pgoff_t index, unsigned long nr)