summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAmir Goldstein <amir73il@gmail.com>2018-08-29 01:41:29 -0400
committerMiklos Szeredi <mszeredi@redhat.com>2018-08-30 14:01:32 -0400
commit3d8f7615319b2bca87a4815e13787439e3339a93 (patch)
treef7f5c2be4f572892747e47c9fc1001e86f74ca61
parent45cd0faae3715e305bc46e23b34c5ed4d185ceb8 (diff)
vfs: implement readahead(2) using POSIX_FADV_WILLNEED
The implementation of readahead(2) syscall is identical to that of fadvise64(POSIX_FADV_WILLNEED) with a few exceptions: 1. readahead(2) returns -EINVAL for !mapping->a_ops and fadvise64() ignores the request and returns 0. 2. fadvise64() checks for integer overflow corner case 3. fadvise64() calls the optional filesystem fadvise() file operation Unite the two implementations by calling vfs_fadvise() from readahead(2) syscall. Check the !mapping->a_ops in readahead(2) syscall to preserve documented syscall ABI behaviour. Suggested-by: Miklos Szeredi <mszeredi@redhat.com> Fixes: d1d04ef8572b ("ovl: stack file ops") Signed-off-by: Amir Goldstein <amir73il@gmail.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
-rw-r--r--mm/Makefile3
-rw-r--r--mm/fadvise.c3
-rw-r--r--mm/readahead.c45
3 files changed, 21 insertions, 30 deletions
diff --git a/mm/Makefile b/mm/Makefile
index 8716bdabe1e6..26ef77a3883b 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -32,7 +32,7 @@ ifdef CONFIG_CROSS_MEMORY_ATTACH
32mmu-$(CONFIG_MMU) += process_vm_access.o 32mmu-$(CONFIG_MMU) += process_vm_access.o
33endif 33endif
34 34
35obj-y := filemap.o mempool.o oom_kill.o \ 35obj-y := filemap.o mempool.o oom_kill.o fadvise.o \
36 maccess.o page_alloc.o page-writeback.o \ 36 maccess.o page_alloc.o page-writeback.o \
37 readahead.o swap.o truncate.o vmscan.o shmem.o \ 37 readahead.o swap.o truncate.o vmscan.o shmem.o \
38 util.o mmzone.o vmstat.o backing-dev.o \ 38 util.o mmzone.o vmstat.o backing-dev.o \
@@ -49,7 +49,6 @@ else
49 obj-y += bootmem.o 49 obj-y += bootmem.o
50endif 50endif
51 51
52obj-$(CONFIG_ADVISE_SYSCALLS) += fadvise.o
53ifdef CONFIG_MMU 52ifdef CONFIG_MMU
54 obj-$(CONFIG_ADVISE_SYSCALLS) += madvise.o 53 obj-$(CONFIG_ADVISE_SYSCALLS) += madvise.o
55endif 54endif
diff --git a/mm/fadvise.c b/mm/fadvise.c
index 2f59bac1cb77..467bcd032037 100644
--- a/mm/fadvise.c
+++ b/mm/fadvise.c
@@ -188,6 +188,8 @@ int vfs_fadvise(struct file *file, loff_t offset, loff_t len, int advice)
188} 188}
189EXPORT_SYMBOL(vfs_fadvise); 189EXPORT_SYMBOL(vfs_fadvise);
190 190
191#ifdef CONFIG_ADVISE_SYSCALLS
192
191int ksys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice) 193int ksys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice)
192{ 194{
193 struct fd f = fdget(fd); 195 struct fd f = fdget(fd);
@@ -215,3 +217,4 @@ SYSCALL_DEFINE4(fadvise64, int, fd, loff_t, offset, size_t, len, int, advice)
215} 217}
216 218
217#endif 219#endif
220#endif
diff --git a/mm/readahead.c b/mm/readahead.c
index a59ea70527b9..4e630143a0ba 100644
--- a/mm/readahead.c
+++ b/mm/readahead.c
@@ -20,6 +20,7 @@
20#include <linux/file.h> 20#include <linux/file.h>
21#include <linux/mm_inline.h> 21#include <linux/mm_inline.h>
22#include <linux/blk-cgroup.h> 22#include <linux/blk-cgroup.h>
23#include <linux/fadvise.h>
23 24
24#include "internal.h" 25#include "internal.h"
25 26
@@ -575,24 +576,6 @@ page_cache_async_readahead(struct address_space *mapping,
575} 576}
576EXPORT_SYMBOL_GPL(page_cache_async_readahead); 577EXPORT_SYMBOL_GPL(page_cache_async_readahead);
577 578
578static ssize_t
579do_readahead(struct address_space *mapping, struct file *filp,
580 pgoff_t index, unsigned long nr)
581{
582 if (!mapping || !mapping->a_ops)
583 return -EINVAL;
584
585 /*
586 * Readahead doesn't make sense for DAX inodes, but we don't want it
587 * to report a failure either. Instead, we just return success and
588 * don't do any work.
589 */
590 if (dax_mapping(mapping))
591 return 0;
592
593 return force_page_cache_readahead(mapping, filp, index, nr);
594}
595
596ssize_t ksys_readahead(int fd, loff_t offset, size_t count) 579ssize_t ksys_readahead(int fd, loff_t offset, size_t count)
597{ 580{
598 ssize_t ret; 581 ssize_t ret;
@@ -600,16 +583,22 @@ ssize_t ksys_readahead(int fd, loff_t offset, size_t count)
600 583
601 ret = -EBADF; 584 ret = -EBADF;
602 f = fdget(fd); 585 f = fdget(fd);
603 if (f.file) { 586 if (!f.file || !(f.file->f_mode & FMODE_READ))
604 if (f.file->f_mode & FMODE_READ) { 587 goto out;
605 struct address_space *mapping = f.file->f_mapping; 588
606 pgoff_t start = offset >> PAGE_SHIFT; 589 /*
607 pgoff_t end = (offset + count - 1) >> PAGE_SHIFT; 590 * The readahead() syscall is intended to run only on files
608 unsigned long len = end - start + 1; 591 * that can execute readahead. If readahead is not possible
609 ret = do_readahead(mapping, f.file, start, len); 592 * on this file, then we must return -EINVAL.
610 } 593 */
611 fdput(f); 594 ret = -EINVAL;
612 } 595 if (!f.file->f_mapping || !f.file->f_mapping->a_ops ||
596 !S_ISREG(file_inode(f.file)->i_mode))
597 goto out;
598
599 ret = vfs_fadvise(f.file, offset, count, POSIX_FADV_WILLNEED);
600out:
601 fdput(f);
613 return ret; 602 return ret;
614} 603}
615 604