|
@@ -17,6 +17,8 @@
|
|
|
#include <linux/task_io_accounting_ops.h>
|
|
|
#include <linux/pagevec.h>
|
|
|
#include <linux/pagemap.h>
|
|
|
+#include <linux/syscalls.h>
|
|
|
+#include <linux/file.h>
|
|
|
|
|
|
/*
|
|
|
* Initialise a struct file's readahead state. Assumes that the caller has
|
|
@@ -562,3 +564,41 @@ page_cache_async_readahead(struct address_space *mapping,
|
|
|
ondemand_readahead(mapping, ra, filp, true, offset, req_size);
|
|
|
}
|
|
|
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 || !mapping->a_ops->readpage)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ force_page_cache_readahead(mapping, filp, index, nr);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+SYSCALL_DEFINE(readahead)(int fd, loff_t offset, size_t count)
|
|
|
+{
|
|
|
+ ssize_t ret;
|
|
|
+ struct file *file;
|
|
|
+
|
|
|
+ ret = -EBADF;
|
|
|
+ file = fget(fd);
|
|
|
+ if (file) {
|
|
|
+ if (file->f_mode & FMODE_READ) {
|
|
|
+ struct address_space *mapping = file->f_mapping;
|
|
|
+ pgoff_t start = offset >> PAGE_CACHE_SHIFT;
|
|
|
+ pgoff_t end = (offset + count - 1) >> PAGE_CACHE_SHIFT;
|
|
|
+ unsigned long len = end - start + 1;
|
|
|
+ ret = do_readahead(mapping, file, start, len);
|
|
|
+ }
|
|
|
+ fput(file);
|
|
|
+ }
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+#ifdef CONFIG_HAVE_SYSCALL_WRAPPERS
|
|
|
+asmlinkage long SyS_readahead(long fd, loff_t offset, long count)
|
|
|
+{
|
|
|
+ return SYSC_readahead((int) fd, offset, (size_t) count);
|
|
|
+}
|
|
|
+SYSCALL_ALIAS(sys_readahead, SyS_readahead);
|
|
|
+#endif
|