1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19#include <linux/pagemap.h>
20#include <linux/sched.h>
21#include "btrfs-tests.h"
22#include "../extent_io.h"
23
24#define PROCESS_UNLOCK (1 << 0)
25#define PROCESS_RELEASE (1 << 1)
26#define PROCESS_TEST_LOCKED (1 << 2)
27
28static noinline int process_page_range(struct inode *inode, u64 start, u64 end,
29 unsigned long flags)
30{
31 int ret;
32 struct page *pages[16];
33 unsigned long index = start >> PAGE_CACHE_SHIFT;
34 unsigned long end_index = end >> PAGE_CACHE_SHIFT;
35 unsigned long nr_pages = end_index - index + 1;
36 int i;
37 int count = 0;
38 int loops = 0;
39
40 while (nr_pages > 0) {
41 ret = find_get_pages_contig(inode->i_mapping, index,
42 min_t(unsigned long, nr_pages,
43 ARRAY_SIZE(pages)), pages);
44 for (i = 0; i < ret; i++) {
45 if (flags & PROCESS_TEST_LOCKED &&
46 !PageLocked(pages[i]))
47 count++;
48 if (flags & PROCESS_UNLOCK && PageLocked(pages[i]))
49 unlock_page(pages[i]);
50 page_cache_release(pages[i]);
51 if (flags & PROCESS_RELEASE)
52 page_cache_release(pages[i]);
53 }
54 nr_pages -= ret;
55 index += ret;
56 cond_resched();
57 loops++;
58 if (loops > 100000) {
59 printk(KERN_ERR "stuck in a loop, start %Lu, end %Lu, nr_pages %lu, ret %d\n", start, end, nr_pages, ret);
60 break;
61 }
62 }
63 return count;
64}
65
66static int test_find_delalloc(void)
67{
68 struct inode *inode;
69 struct extent_io_tree tmp;
70 struct page *page;
71 struct page *locked_page = NULL;
72 unsigned long index = 0;
73 u64 total_dirty = 256 * 1024 * 1024;
74 u64 max_bytes = 128 * 1024 * 1024;
75 u64 start, end, test_start;
76 u64 found;
77 int ret = -EINVAL;
78
79 inode = btrfs_new_test_inode();
80 if (!inode) {
81 test_msg("Failed to allocate test inode\n");
82 return -ENOMEM;
83 }
84
85 extent_io_tree_init(&tmp, &inode->i_data);
86
87
88
89
90
91
92 for (index = 0; index < (total_dirty >> PAGE_CACHE_SHIFT); index++) {
93 page = find_or_create_page(inode->i_mapping, index, GFP_NOFS);
94 if (!page) {
95 test_msg("Failed to allocate test page\n");
96 ret = -ENOMEM;
97 goto out;
98 }
99 SetPageDirty(page);
100 if (index) {
101 unlock_page(page);
102 } else {
103 page_cache_get(page);
104 locked_page = page;
105 }
106 }
107
108
109
110
111
112 set_extent_delalloc(&tmp, 0, 4095, NULL, GFP_NOFS);
113 start = 0;
114 end = 0;
115 found = find_lock_delalloc_range(inode, &tmp, locked_page, &start,
116 &end, max_bytes);
117 if (!found) {
118 test_msg("Should have found at least one delalloc\n");
119 goto out_bits;
120 }
121 if (start != 0 || end != 4095) {
122 test_msg("Expected start 0 end 4095, got start %Lu end %Lu\n",
123 start, end);
124 goto out_bits;
125 }
126 unlock_extent(&tmp, start, end);
127 unlock_page(locked_page);
128 page_cache_release(locked_page);
129
130
131
132
133
134
135
136 test_start = 64 * 1024 * 1024;
137 locked_page = find_lock_page(inode->i_mapping,
138 test_start >> PAGE_CACHE_SHIFT);
139 if (!locked_page) {
140 test_msg("Couldn't find the locked page\n");
141 goto out_bits;
142 }
143 set_extent_delalloc(&tmp, 4096, max_bytes - 1, NULL, GFP_NOFS);
144 start = test_start;
145 end = 0;
146 found = find_lock_delalloc_range(inode, &tmp, locked_page, &start,
147 &end, max_bytes);
148 if (!found) {
149 test_msg("Couldn't find delalloc in our range\n");
150 goto out_bits;
151 }
152 if (start != test_start || end != max_bytes - 1) {
153 test_msg("Expected start %Lu end %Lu, got start %Lu, end "
154 "%Lu\n", test_start, max_bytes - 1, start, end);
155 goto out_bits;
156 }
157 if (process_page_range(inode, start, end,
158 PROCESS_TEST_LOCKED | PROCESS_UNLOCK)) {
159 test_msg("There were unlocked pages in the range\n");
160 goto out_bits;
161 }
162 unlock_extent(&tmp, start, end);
163
164 page_cache_release(locked_page);
165
166
167
168
169
170
171 test_start = max_bytes + 4096;
172 locked_page = find_lock_page(inode->i_mapping, test_start >>
173 PAGE_CACHE_SHIFT);
174 if (!locked_page) {
175 test_msg("Could'nt find the locked page\n");
176 goto out_bits;
177 }
178 start = test_start;
179 end = 0;
180 found = find_lock_delalloc_range(inode, &tmp, locked_page, &start,
181 &end, max_bytes);
182 if (found) {
183 test_msg("Found range when we shouldn't have\n");
184 goto out_bits;
185 }
186 if (end != (u64)-1) {
187 test_msg("Did not return the proper end offset\n");
188 goto out_bits;
189 }
190
191
192
193
194
195
196
197
198 set_extent_delalloc(&tmp, max_bytes, total_dirty - 1, NULL, GFP_NOFS);
199 start = test_start;
200 end = 0;
201 found = find_lock_delalloc_range(inode, &tmp, locked_page, &start,
202 &end, max_bytes);
203 if (!found) {
204 test_msg("Didn't find our range\n");
205 goto out_bits;
206 }
207 if (start != test_start || end != total_dirty - 1) {
208 test_msg("Expected start %Lu end %Lu, got start %Lu end %Lu\n",
209 test_start, total_dirty - 1, start, end);
210 goto out_bits;
211 }
212 if (process_page_range(inode, start, end,
213 PROCESS_TEST_LOCKED | PROCESS_UNLOCK)) {
214 test_msg("Pages in range were not all locked\n");
215 goto out_bits;
216 }
217 unlock_extent(&tmp, start, end);
218
219
220
221
222
223 page = find_get_page(inode->i_mapping, (max_bytes + (1 * 1024 * 1024))
224 >> PAGE_CACHE_SHIFT);
225 if (!page) {
226 test_msg("Couldn't find our page\n");
227 goto out_bits;
228 }
229 ClearPageDirty(page);
230 page_cache_release(page);
231
232
233 lock_page(locked_page);
234 start = test_start;
235 end = 0;
236
237
238
239
240
241
242 found = find_lock_delalloc_range(inode, &tmp, locked_page, &start,
243 &end, max_bytes);
244 if (!found) {
245 test_msg("Didn't find our range\n");
246 goto out_bits;
247 }
248 if (start != test_start && end != test_start + PAGE_CACHE_SIZE - 1) {
249 test_msg("Expected start %Lu end %Lu, got start %Lu end %Lu\n",
250 test_start, test_start + PAGE_CACHE_SIZE - 1, start,
251 end);
252 goto out_bits;
253 }
254 if (process_page_range(inode, start, end, PROCESS_TEST_LOCKED |
255 PROCESS_UNLOCK)) {
256 test_msg("Pages in range were not all locked\n");
257 goto out_bits;
258 }
259 ret = 0;
260out_bits:
261 clear_extent_bits(&tmp, 0, total_dirty - 1, (unsigned)-1, GFP_NOFS);
262out:
263 if (locked_page)
264 page_cache_release(locked_page);
265 process_page_range(inode, 0, total_dirty - 1,
266 PROCESS_UNLOCK | PROCESS_RELEASE);
267 iput(inode);
268 return ret;
269}
270
271int btrfs_test_extent_io(void)
272{
273 test_msg("Running find delalloc tests\n");
274 return test_find_delalloc();
275}
276