1 /* 2 * Copyright (C) 2013 Fusion IO. All rights reserved. 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public 6 * License v2 as published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 * General Public License for more details. 12 * 13 * You should have received a copy of the GNU General Public 14 * License along with this program; if not, write to the 15 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 16 * Boston, MA 021110-1307, USA. 17 */ 18 19 #include <linux/pagemap.h> 20 #include <linux/sched.h> 21 #include <linux/slab.h> 22 #include <linux/sizes.h> 23 #include "btrfs-tests.h" 24 #include "../extent_io.h" 25 26 #define PROCESS_UNLOCK (1 << 0) 27 #define PROCESS_RELEASE (1 << 1) 28 #define PROCESS_TEST_LOCKED (1 << 2) 29 30 static noinline int process_page_range(struct inode *inode, u64 start, u64 end, 31 unsigned long flags) 32 { 33 int ret; 34 struct page *pages[16]; 35 unsigned long index = start >> PAGE_CACHE_SHIFT; 36 unsigned long end_index = end >> PAGE_CACHE_SHIFT; 37 unsigned long nr_pages = end_index - index + 1; 38 int i; 39 int count = 0; 40 int loops = 0; 41 42 while (nr_pages > 0) { 43 ret = find_get_pages_contig(inode->i_mapping, index, 44 min_t(unsigned long, nr_pages, 45 ARRAY_SIZE(pages)), pages); 46 for (i = 0; i < ret; i++) { 47 if (flags & PROCESS_TEST_LOCKED && 48 !PageLocked(pages[i])) 49 count++; 50 if (flags & PROCESS_UNLOCK && PageLocked(pages[i])) 51 unlock_page(pages[i]); 52 page_cache_release(pages[i]); 53 if (flags & PROCESS_RELEASE) 54 page_cache_release(pages[i]); 55 } 56 nr_pages -= ret; 57 index += ret; 58 cond_resched(); 59 loops++; 60 if (loops > 100000) { 61 printk(KERN_ERR "stuck in a loop, start %Lu, end %Lu, nr_pages %lu, ret %d\n", start, end, nr_pages, ret); 62 break; 63 } 64 } 65 return count; 66 } 67 68 static int test_find_delalloc(void) 69 { 70 struct inode *inode; 71 struct extent_io_tree tmp; 72 struct page *page; 73 struct page *locked_page = NULL; 74 unsigned long index = 0; 75 u64 total_dirty = SZ_256M; 76 u64 max_bytes = SZ_128M; 77 u64 start, end, test_start; 78 u64 found; 79 int ret = -EINVAL; 80 81 test_msg("Running find delalloc tests\n"); 82 83 inode = btrfs_new_test_inode(); 84 if (!inode) { 85 test_msg("Failed to allocate test inode\n"); 86 return -ENOMEM; 87 } 88 89 extent_io_tree_init(&tmp, &inode->i_data); 90 91 /* 92 * First go through and create and mark all of our pages dirty, we pin 93 * everything to make sure our pages don't get evicted and screw up our 94 * test. 95 */ 96 for (index = 0; index < (total_dirty >> PAGE_CACHE_SHIFT); index++) { 97 page = find_or_create_page(inode->i_mapping, index, GFP_NOFS); 98 if (!page) { 99 test_msg("Failed to allocate test page\n"); 100 ret = -ENOMEM; 101 goto out; 102 } 103 SetPageDirty(page); 104 if (index) { 105 unlock_page(page); 106 } else { 107 page_cache_get(page); 108 locked_page = page; 109 } 110 } 111 112 /* Test this scenario 113 * |--- delalloc ---| 114 * |--- search ---| 115 */ 116 set_extent_delalloc(&tmp, 0, 4095, NULL, GFP_NOFS); 117 start = 0; 118 end = 0; 119 found = find_lock_delalloc_range(inode, &tmp, locked_page, &start, 120 &end, max_bytes); 121 if (!found) { 122 test_msg("Should have found at least one delalloc\n"); 123 goto out_bits; 124 } 125 if (start != 0 || end != 4095) { 126 test_msg("Expected start 0 end 4095, got start %Lu end %Lu\n", 127 start, end); 128 goto out_bits; 129 } 130 unlock_extent(&tmp, start, end); 131 unlock_page(locked_page); 132 page_cache_release(locked_page); 133 134 /* 135 * Test this scenario 136 * 137 * |--- delalloc ---| 138 * |--- search ---| 139 */ 140 test_start = SZ_64M; 141 locked_page = find_lock_page(inode->i_mapping, 142 test_start >> PAGE_CACHE_SHIFT); 143 if (!locked_page) { 144 test_msg("Couldn't find the locked page\n"); 145 goto out_bits; 146 } 147 set_extent_delalloc(&tmp, 4096, max_bytes - 1, NULL, GFP_NOFS); 148 start = test_start; 149 end = 0; 150 found = find_lock_delalloc_range(inode, &tmp, locked_page, &start, 151 &end, max_bytes); 152 if (!found) { 153 test_msg("Couldn't find delalloc in our range\n"); 154 goto out_bits; 155 } 156 if (start != test_start || end != max_bytes - 1) { 157 test_msg("Expected start %Lu end %Lu, got start %Lu, end " 158 "%Lu\n", test_start, max_bytes - 1, start, end); 159 goto out_bits; 160 } 161 if (process_page_range(inode, start, end, 162 PROCESS_TEST_LOCKED | PROCESS_UNLOCK)) { 163 test_msg("There were unlocked pages in the range\n"); 164 goto out_bits; 165 } 166 unlock_extent(&tmp, start, end); 167 /* locked_page was unlocked above */ 168 page_cache_release(locked_page); 169 170 /* 171 * Test this scenario 172 * |--- delalloc ---| 173 * |--- search ---| 174 */ 175 test_start = max_bytes + 4096; 176 locked_page = find_lock_page(inode->i_mapping, test_start >> 177 PAGE_CACHE_SHIFT); 178 if (!locked_page) { 179 test_msg("Could'nt find the locked page\n"); 180 goto out_bits; 181 } 182 start = test_start; 183 end = 0; 184 found = find_lock_delalloc_range(inode, &tmp, locked_page, &start, 185 &end, max_bytes); 186 if (found) { 187 test_msg("Found range when we shouldn't have\n"); 188 goto out_bits; 189 } 190 if (end != (u64)-1) { 191 test_msg("Did not return the proper end offset\n"); 192 goto out_bits; 193 } 194 195 /* 196 * Test this scenario 197 * [------- delalloc -------| 198 * [max_bytes]|-- search--| 199 * 200 * We are re-using our test_start from above since it works out well. 201 */ 202 set_extent_delalloc(&tmp, max_bytes, total_dirty - 1, NULL, GFP_NOFS); 203 start = test_start; 204 end = 0; 205 found = find_lock_delalloc_range(inode, &tmp, locked_page, &start, 206 &end, max_bytes); 207 if (!found) { 208 test_msg("Didn't find our range\n"); 209 goto out_bits; 210 } 211 if (start != test_start || end != total_dirty - 1) { 212 test_msg("Expected start %Lu end %Lu, got start %Lu end %Lu\n", 213 test_start, total_dirty - 1, start, end); 214 goto out_bits; 215 } 216 if (process_page_range(inode, start, end, 217 PROCESS_TEST_LOCKED | PROCESS_UNLOCK)) { 218 test_msg("Pages in range were not all locked\n"); 219 goto out_bits; 220 } 221 unlock_extent(&tmp, start, end); 222 223 /* 224 * Now to test where we run into a page that is no longer dirty in the 225 * range we want to find. 226 */ 227 page = find_get_page(inode->i_mapping, 228 (max_bytes + SZ_1M) >> PAGE_CACHE_SHIFT); 229 if (!page) { 230 test_msg("Couldn't find our page\n"); 231 goto out_bits; 232 } 233 ClearPageDirty(page); 234 page_cache_release(page); 235 236 /* We unlocked it in the previous test */ 237 lock_page(locked_page); 238 start = test_start; 239 end = 0; 240 /* 241 * Currently if we fail to find dirty pages in the delalloc range we 242 * will adjust max_bytes down to PAGE_CACHE_SIZE and then re-search. If 243 * this changes at any point in the future we will need to fix this 244 * tests expected behavior. 245 */ 246 found = find_lock_delalloc_range(inode, &tmp, locked_page, &start, 247 &end, max_bytes); 248 if (!found) { 249 test_msg("Didn't find our range\n"); 250 goto out_bits; 251 } 252 if (start != test_start && end != test_start + PAGE_CACHE_SIZE - 1) { 253 test_msg("Expected start %Lu end %Lu, got start %Lu end %Lu\n", 254 test_start, test_start + PAGE_CACHE_SIZE - 1, start, 255 end); 256 goto out_bits; 257 } 258 if (process_page_range(inode, start, end, PROCESS_TEST_LOCKED | 259 PROCESS_UNLOCK)) { 260 test_msg("Pages in range were not all locked\n"); 261 goto out_bits; 262 } 263 ret = 0; 264 out_bits: 265 clear_extent_bits(&tmp, 0, total_dirty - 1, (unsigned)-1, GFP_NOFS); 266 out: 267 if (locked_page) 268 page_cache_release(locked_page); 269 process_page_range(inode, 0, total_dirty - 1, 270 PROCESS_UNLOCK | PROCESS_RELEASE); 271 iput(inode); 272 return ret; 273 } 274 275 static int __test_eb_bitmaps(unsigned long *bitmap, struct extent_buffer *eb, 276 unsigned long len) 277 { 278 unsigned long i, x; 279 280 memset(bitmap, 0, len); 281 memset_extent_buffer(eb, 0, 0, len); 282 if (memcmp_extent_buffer(eb, bitmap, 0, len) != 0) { 283 test_msg("Bitmap was not zeroed\n"); 284 return -EINVAL; 285 } 286 287 bitmap_set(bitmap, 0, len * BITS_PER_BYTE); 288 extent_buffer_bitmap_set(eb, 0, 0, len * BITS_PER_BYTE); 289 if (memcmp_extent_buffer(eb, bitmap, 0, len) != 0) { 290 test_msg("Setting all bits failed\n"); 291 return -EINVAL; 292 } 293 294 bitmap_clear(bitmap, 0, len * BITS_PER_BYTE); 295 extent_buffer_bitmap_clear(eb, 0, 0, len * BITS_PER_BYTE); 296 if (memcmp_extent_buffer(eb, bitmap, 0, len) != 0) { 297 test_msg("Clearing all bits failed\n"); 298 return -EINVAL; 299 } 300 301 bitmap_set(bitmap, (PAGE_CACHE_SIZE - sizeof(long) / 2) * BITS_PER_BYTE, 302 sizeof(long) * BITS_PER_BYTE); 303 extent_buffer_bitmap_set(eb, PAGE_CACHE_SIZE - sizeof(long) / 2, 0, 304 sizeof(long) * BITS_PER_BYTE); 305 if (memcmp_extent_buffer(eb, bitmap, 0, len) != 0) { 306 test_msg("Setting straddling pages failed\n"); 307 return -EINVAL; 308 } 309 310 bitmap_set(bitmap, 0, len * BITS_PER_BYTE); 311 bitmap_clear(bitmap, 312 (PAGE_CACHE_SIZE - sizeof(long) / 2) * BITS_PER_BYTE, 313 sizeof(long) * BITS_PER_BYTE); 314 extent_buffer_bitmap_set(eb, 0, 0, len * BITS_PER_BYTE); 315 extent_buffer_bitmap_clear(eb, PAGE_CACHE_SIZE - sizeof(long) / 2, 0, 316 sizeof(long) * BITS_PER_BYTE); 317 if (memcmp_extent_buffer(eb, bitmap, 0, len) != 0) { 318 test_msg("Clearing straddling pages failed\n"); 319 return -EINVAL; 320 } 321 322 /* 323 * Generate a wonky pseudo-random bit pattern for the sake of not using 324 * something repetitive that could miss some hypothetical off-by-n bug. 325 */ 326 x = 0; 327 for (i = 0; i < len / sizeof(long); i++) { 328 x = (0x19660dULL * (u64)x + 0x3c6ef35fULL) & 0xffffffffUL; 329 bitmap[i] = x; 330 } 331 write_extent_buffer(eb, bitmap, 0, len); 332 333 for (i = 0; i < len * BITS_PER_BYTE; i++) { 334 int bit, bit1; 335 336 bit = !!test_bit(i, bitmap); 337 bit1 = !!extent_buffer_test_bit(eb, 0, i); 338 if (bit1 != bit) { 339 test_msg("Testing bit pattern failed\n"); 340 return -EINVAL; 341 } 342 343 bit1 = !!extent_buffer_test_bit(eb, i / BITS_PER_BYTE, 344 i % BITS_PER_BYTE); 345 if (bit1 != bit) { 346 test_msg("Testing bit pattern with offset failed\n"); 347 return -EINVAL; 348 } 349 } 350 351 return 0; 352 } 353 354 static int test_eb_bitmaps(void) 355 { 356 unsigned long len = PAGE_CACHE_SIZE * 4; 357 unsigned long *bitmap; 358 struct extent_buffer *eb; 359 int ret; 360 361 test_msg("Running extent buffer bitmap tests\n"); 362 363 bitmap = kmalloc(len, GFP_NOFS); 364 if (!bitmap) { 365 test_msg("Couldn't allocate test bitmap\n"); 366 return -ENOMEM; 367 } 368 369 eb = __alloc_dummy_extent_buffer(NULL, 0, len); 370 if (!eb) { 371 test_msg("Couldn't allocate test extent buffer\n"); 372 kfree(bitmap); 373 return -ENOMEM; 374 } 375 376 ret = __test_eb_bitmaps(bitmap, eb, len); 377 if (ret) 378 goto out; 379 380 /* Do it over again with an extent buffer which isn't page-aligned. */ 381 free_extent_buffer(eb); 382 eb = __alloc_dummy_extent_buffer(NULL, PAGE_CACHE_SIZE / 2, len); 383 if (!eb) { 384 test_msg("Couldn't allocate test extent buffer\n"); 385 kfree(bitmap); 386 return -ENOMEM; 387 } 388 389 ret = __test_eb_bitmaps(bitmap, eb, len); 390 out: 391 free_extent_buffer(eb); 392 kfree(bitmap); 393 return ret; 394 } 395 396 int btrfs_test_extent_io(void) 397 { 398 int ret; 399 400 test_msg("Running extent I/O tests\n"); 401 402 ret = test_find_delalloc(); 403 if (ret) 404 goto out; 405 406 ret = test_eb_bitmaps(); 407 out: 408 test_msg("Extent I/O tests finished\n"); 409 return ret; 410 } 411