extent-io-tests.c 11 KB

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