Root/
1 | /* |
2 | * mm/fadvise.c |
3 | * |
4 | * Copyright (C) 2002, Linus Torvalds |
5 | * |
6 | * 11Jan2003 Andrew Morton |
7 | * Initial version. |
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 | #include <linux/writeback.h> |
19 | #include <linux/syscalls.h> |
20 | #include <linux/swap.h> |
21 | |
22 | #include <asm/unistd.h> |
23 | |
24 | /* |
25 | * POSIX_FADV_WILLNEED could set PG_Referenced, and POSIX_FADV_NOREUSE could |
26 | * deactivate the pages and clear PG_Referenced. |
27 | */ |
28 | SYSCALL_DEFINE(fadvise64_64)(int fd, loff_t offset, loff_t len, int advice) |
29 | { |
30 | struct fd f = fdget(fd); |
31 | struct address_space *mapping; |
32 | struct backing_dev_info *bdi; |
33 | loff_t endbyte; /* inclusive */ |
34 | pgoff_t start_index; |
35 | pgoff_t end_index; |
36 | unsigned long nrpages; |
37 | int ret = 0; |
38 | |
39 | if (!f.file) |
40 | return -EBADF; |
41 | |
42 | if (S_ISFIFO(file_inode(f.file)->i_mode)) { |
43 | ret = -ESPIPE; |
44 | goto out; |
45 | } |
46 | |
47 | mapping = f.file->f_mapping; |
48 | if (!mapping || len < 0) { |
49 | ret = -EINVAL; |
50 | goto out; |
51 | } |
52 | |
53 | if (mapping->a_ops->get_xip_mem) { |
54 | switch (advice) { |
55 | case POSIX_FADV_NORMAL: |
56 | case POSIX_FADV_RANDOM: |
57 | case POSIX_FADV_SEQUENTIAL: |
58 | case POSIX_FADV_WILLNEED: |
59 | case POSIX_FADV_NOREUSE: |
60 | case POSIX_FADV_DONTNEED: |
61 | /* no bad return value, but ignore advice */ |
62 | break; |
63 | default: |
64 | ret = -EINVAL; |
65 | } |
66 | goto out; |
67 | } |
68 | |
69 | /* Careful about overflows. Len == 0 means "as much as possible" */ |
70 | endbyte = offset + len; |
71 | if (!len || endbyte < len) |
72 | endbyte = -1; |
73 | else |
74 | endbyte--; /* inclusive */ |
75 | |
76 | bdi = mapping->backing_dev_info; |
77 | |
78 | switch (advice) { |
79 | case POSIX_FADV_NORMAL: |
80 | f.file->f_ra.ra_pages = bdi->ra_pages; |
81 | spin_lock(&f.file->f_lock); |
82 | f.file->f_mode &= ~FMODE_RANDOM; |
83 | spin_unlock(&f.file->f_lock); |
84 | break; |
85 | case POSIX_FADV_RANDOM: |
86 | spin_lock(&f.file->f_lock); |
87 | f.file->f_mode |= FMODE_RANDOM; |
88 | spin_unlock(&f.file->f_lock); |
89 | break; |
90 | case POSIX_FADV_SEQUENTIAL: |
91 | f.file->f_ra.ra_pages = bdi->ra_pages * 2; |
92 | spin_lock(&f.file->f_lock); |
93 | f.file->f_mode &= ~FMODE_RANDOM; |
94 | spin_unlock(&f.file->f_lock); |
95 | break; |
96 | case POSIX_FADV_WILLNEED: |
97 | /* First and last PARTIAL page! */ |
98 | start_index = offset >> PAGE_CACHE_SHIFT; |
99 | end_index = endbyte >> PAGE_CACHE_SHIFT; |
100 | |
101 | /* Careful about overflow on the "+1" */ |
102 | nrpages = end_index - start_index + 1; |
103 | if (!nrpages) |
104 | nrpages = ~0UL; |
105 | |
106 | /* |
107 | * Ignore return value because fadvise() shall return |
108 | * success even if filesystem can't retrieve a hint, |
109 | */ |
110 | force_page_cache_readahead(mapping, f.file, start_index, |
111 | nrpages); |
112 | break; |
113 | case POSIX_FADV_NOREUSE: |
114 | break; |
115 | case POSIX_FADV_DONTNEED: |
116 | if (!bdi_write_congested(mapping->backing_dev_info)) |
117 | __filemap_fdatawrite_range(mapping, offset, endbyte, |
118 | WB_SYNC_NONE); |
119 | |
120 | /* First and last FULL page! */ |
121 | start_index = (offset+(PAGE_CACHE_SIZE-1)) >> PAGE_CACHE_SHIFT; |
122 | end_index = (endbyte >> PAGE_CACHE_SHIFT); |
123 | |
124 | if (end_index >= start_index) { |
125 | unsigned long count = invalidate_mapping_pages(mapping, |
126 | start_index, end_index); |
127 | |
128 | /* |
129 | * If fewer pages were invalidated than expected then |
130 | * it is possible that some of the pages were on |
131 | * a per-cpu pagevec for a remote CPU. Drain all |
132 | * pagevecs and try again. |
133 | */ |
134 | if (count < (end_index - start_index + 1)) { |
135 | lru_add_drain_all(); |
136 | invalidate_mapping_pages(mapping, start_index, |
137 | end_index); |
138 | } |
139 | } |
140 | break; |
141 | default: |
142 | ret = -EINVAL; |
143 | } |
144 | out: |
145 | fdput(f); |
146 | return ret; |
147 | } |
148 | #ifdef CONFIG_HAVE_SYSCALL_WRAPPERS |
149 | asmlinkage long SyS_fadvise64_64(long fd, loff_t offset, loff_t len, long advice) |
150 | { |
151 | return SYSC_fadvise64_64((int) fd, offset, len, (int) advice); |
152 | } |
153 | SYSCALL_ALIAS(sys_fadvise64_64, SyS_fadvise64_64); |
154 | #endif |
155 | |
156 | #ifdef __ARCH_WANT_SYS_FADVISE64 |
157 | |
158 | SYSCALL_DEFINE(fadvise64)(int fd, loff_t offset, size_t len, int advice) |
159 | { |
160 | return sys_fadvise64_64(fd, offset, len, advice); |
161 | } |
162 | #ifdef CONFIG_HAVE_SYSCALL_WRAPPERS |
163 | asmlinkage long SyS_fadvise64(long fd, loff_t offset, long len, long advice) |
164 | { |
165 | return SYSC_fadvise64((int) fd, offset, (size_t)len, (int)advice); |
166 | } |
167 | SYSCALL_ALIAS(sys_fadvise64, SyS_fadvise64); |
168 | #endif |
169 | |
170 | #endif |
171 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9