1
2
3
4
5
6
7
8
9
10#include <linux/kernel.h>
11#include <linux/file.h>
12#include <linux/fs.h>
13#include <linux/mm.h>
14#include <linux/pagemap.h>
15#include <linux/backing-dev.h>
16#include <linux/pagevec.h>
17#include <linux/fadvise.h>
18
19#include <asm/unistd.h>
20
21
22
23
24
25asmlinkage long sys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice)
26{
27 struct file *file = fget(fd);
28 struct address_space *mapping;
29 struct backing_dev_info *bdi;
30 loff_t endbyte;
31 pgoff_t start_index;
32 pgoff_t end_index;
33 unsigned long nrpages;
34 int ret = 0;
35
36 if (!file)
37 return -EBADF;
38
39 mapping = file->f_mapping;
40 if (!mapping || len < 0) {
41 ret = -EINVAL;
42 goto out;
43 }
44
45
46 endbyte = offset + len;
47 if (!len || endbyte < len)
48 endbyte = -1;
49
50 bdi = mapping->backing_dev_info;
51
52 switch (advice) {
53 case POSIX_FADV_NORMAL:
54 file->f_ra.ra_pages = bdi->ra_pages;
55 break;
56 case POSIX_FADV_RANDOM:
57 file->f_ra.ra_pages = 0;
58 break;
59 case POSIX_FADV_SEQUENTIAL:
60 file->f_ra.ra_pages = bdi->ra_pages * 2;
61 break;
62 case POSIX_FADV_WILLNEED:
63 case POSIX_FADV_NOREUSE:
64 if (!mapping->a_ops->readpage) {
65 ret = -EINVAL;
66 break;
67 }
68
69
70 start_index = offset >> PAGE_CACHE_SHIFT;
71 end_index = (endbyte-1) >> PAGE_CACHE_SHIFT;
72
73
74 nrpages = end_index - start_index + 1;
75 if (!nrpages)
76 nrpages = ~0UL;
77
78 ret = force_page_cache_readahead(mapping, file,
79 start_index,
80 max_sane_readahead(nrpages));
81 if (ret > 0)
82 ret = 0;
83 break;
84 case POSIX_FADV_DONTNEED:
85 if (!bdi_write_congested(mapping->backing_dev_info))
86 filemap_flush(mapping);
87
88
89 start_index = (offset + (PAGE_CACHE_SIZE-1)) >> PAGE_CACHE_SHIFT;
90 end_index = (endbyte >> PAGE_CACHE_SHIFT);
91
92 if (end_index > start_index)
93 invalidate_mapping_pages(mapping, start_index, end_index-1);
94 break;
95 default:
96 ret = -EINVAL;
97 }
98out:
99 fput(file);
100 return ret;
101}
102
103#ifdef __ARCH_WANT_SYS_FADVISE64
104
105asmlinkage long sys_fadvise64(int fd, loff_t offset, size_t len, int advice)
106{
107 return sys_fadvise64_64(fd, offset, len, advice);
108}
109
110#endif
111