--- /dev/null
+From 58d5640ebdb273cc817b0d0cda7bcf2efbbc2ff7 Mon Sep 17 00:00:00 2001
+From: Mark Rutland <mark.rutland@arm.com>
+Date: Wed, 29 Jan 2014 14:05:51 -0800
+Subject: mm/readahead.c: fix do_readahead() for no readpage(s)
+
+From: Mark Rutland <mark.rutland@arm.com>
+
+commit 58d5640ebdb273cc817b0d0cda7bcf2efbbc2ff7 upstream.
+
+Commit 63d0f0a3c7e1 ("mm/readahead.c:do_readhead(): don't check for
+->readpage") unintentionally made do_readahead return 0 for all valid
+files regardless of whether readahead was supported, rather than the
+expected -EINVAL. This gets forwarded on to userspace, and results in
+sys_readahead appearing to succeed in cases that don't make sense (e.g.
+when called on pipes or sockets). This issue is detected by the LTP
+readahead01 testcase.
+
+As the exact return value of force_page_cache_readahead is currently
+never used, we can simplify it to return only 0 or -EINVAL (when
+readpage or readpages is missing). With that in place we can simply
+forward on the return value of force_page_cache_readahead in
+do_readahead.
+
+This patch performs said change, restoring the expected semantics.
+
+Signed-off-by: Mark Rutland <mark.rutland@arm.com>
+Acked-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Josh Boyer <jwboyer@fedoraproject.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ mm/readahead.c | 15 +++++----------
+ 1 file changed, 5 insertions(+), 10 deletions(-)
+
+--- a/mm/readahead.c
++++ b/mm/readahead.c
+@@ -211,8 +211,6 @@ out:
+ int force_page_cache_readahead(struct address_space *mapping, struct file *filp,
+ pgoff_t offset, unsigned long nr_to_read)
+ {
+- int ret = 0;
+-
+ if (unlikely(!mapping->a_ops->readpage && !mapping->a_ops->readpages))
+ return -EINVAL;
+
+@@ -226,15 +224,13 @@ int force_page_cache_readahead(struct ad
+ this_chunk = nr_to_read;
+ err = __do_page_cache_readahead(mapping, filp,
+ offset, this_chunk, 0);
+- if (err < 0) {
+- ret = err;
+- break;
+- }
+- ret += err;
++ if (err < 0)
++ return err;
++
+ offset += this_chunk;
+ nr_to_read -= this_chunk;
+ }
+- return ret;
++ return 0;
+ }
+
+ /*
+@@ -576,8 +572,7 @@ do_readahead(struct address_space *mappi
+ if (!mapping || !mapping->a_ops)
+ return -EINVAL;
+
+- force_page_cache_readahead(mapping, filp, index, nr);
+- return 0;
++ return force_page_cache_readahead(mapping, filp, index, nr);
+ }
+
+ SYSCALL_DEFINE3(readahead, int, fd, loff_t, offset, size_t, count)