Skip to content

Commit

Permalink
vfs: implement readahead(2) using POSIX_FADV_WILLNEED
Browse files Browse the repository at this point in the history
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 <[email protected]>
Fixes: d1d04ef ("ovl: stack file ops")
Signed-off-by: Amir Goldstein <[email protected]>
Signed-off-by: Miklos Szeredi <[email protected]>
  • Loading branch information
amir73il authored and Miklos Szeredi committed Aug 30, 2018
1 parent 45cd0fa commit 3d8f761
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 30 deletions.
3 changes: 1 addition & 2 deletions mm/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ ifdef CONFIG_CROSS_MEMORY_ATTACH
mmu-$(CONFIG_MMU) += process_vm_access.o
endif

obj-y := filemap.o mempool.o oom_kill.o \
obj-y := filemap.o mempool.o oom_kill.o fadvise.o \
maccess.o page_alloc.o page-writeback.o \
readahead.o swap.o truncate.o vmscan.o shmem.o \
util.o mmzone.o vmstat.o backing-dev.o \
Expand All @@ -49,7 +49,6 @@ else
obj-y += bootmem.o
endif

obj-$(CONFIG_ADVISE_SYSCALLS) += fadvise.o
ifdef CONFIG_MMU
obj-$(CONFIG_ADVISE_SYSCALLS) += madvise.o
endif
Expand Down
3 changes: 3 additions & 0 deletions mm/fadvise.c
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,8 @@ int vfs_fadvise(struct file *file, loff_t offset, loff_t len, int advice)
}
EXPORT_SYMBOL(vfs_fadvise);

#ifdef CONFIG_ADVISE_SYSCALLS

int ksys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice)
{
struct fd f = fdget(fd);
Expand Down Expand Up @@ -215,3 +217,4 @@ SYSCALL_DEFINE4(fadvise64, int, fd, loff_t, offset, size_t, len, int, advice)
}

#endif
#endif
45 changes: 17 additions & 28 deletions mm/readahead.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <linux/file.h>
#include <linux/mm_inline.h>
#include <linux/blk-cgroup.h>
#include <linux/fadvise.h>

#include "internal.h"

Expand Down Expand Up @@ -575,41 +576,29 @@ page_cache_async_readahead(struct address_space *mapping,
}
EXPORT_SYMBOL_GPL(page_cache_async_readahead);

static ssize_t
do_readahead(struct address_space *mapping, struct file *filp,
pgoff_t index, unsigned long nr)
{
if (!mapping || !mapping->a_ops)
return -EINVAL;

/*
* Readahead doesn't make sense for DAX inodes, but we don't want it
* to report a failure either. Instead, we just return success and
* don't do any work.
*/
if (dax_mapping(mapping))
return 0;

return force_page_cache_readahead(mapping, filp, index, nr);
}

ssize_t ksys_readahead(int fd, loff_t offset, size_t count)
{
ssize_t ret;
struct fd f;

ret = -EBADF;
f = fdget(fd);
if (f.file) {
if (f.file->f_mode & FMODE_READ) {
struct address_space *mapping = f.file->f_mapping;
pgoff_t start = offset >> PAGE_SHIFT;
pgoff_t end = (offset + count - 1) >> PAGE_SHIFT;
unsigned long len = end - start + 1;
ret = do_readahead(mapping, f.file, start, len);
}
fdput(f);
}
if (!f.file || !(f.file->f_mode & FMODE_READ))
goto out;

/*
* The readahead() syscall is intended to run only on files
* that can execute readahead. If readahead is not possible
* on this file, then we must return -EINVAL.
*/
ret = -EINVAL;
if (!f.file->f_mapping || !f.file->f_mapping->a_ops ||
!S_ISREG(file_inode(f.file)->i_mode))
goto out;

ret = vfs_fadvise(f.file, offset, count, POSIX_FADV_WILLNEED);
out:
fdput(f);
return ret;
}

Expand Down

0 comments on commit 3d8f761

Please sign in to comment.