qgroup-tests.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) 2013 Facebook. All rights reserved.
  4. */
  5. #include <linux/types.h>
  6. #include "btrfs-tests.h"
  7. #include "../ctree.h"
  8. #include "../transaction.h"
  9. #include "../disk-io.h"
  10. #include "../qgroup.h"
  11. #include "../backref.h"
  12. static int insert_normal_tree_ref(struct btrfs_root *root, u64 bytenr,
  13. u64 num_bytes, u64 parent, u64 root_objectid)
  14. {
  15. struct btrfs_trans_handle trans;
  16. struct btrfs_extent_item *item;
  17. struct btrfs_extent_inline_ref *iref;
  18. struct btrfs_tree_block_info *block_info;
  19. struct btrfs_path *path;
  20. struct extent_buffer *leaf;
  21. struct btrfs_key ins;
  22. u32 size = sizeof(*item) + sizeof(*iref) + sizeof(*block_info);
  23. int ret;
  24. btrfs_init_dummy_trans(&trans, NULL);
  25. ins.objectid = bytenr;
  26. ins.type = BTRFS_EXTENT_ITEM_KEY;
  27. ins.offset = num_bytes;
  28. path = btrfs_alloc_path();
  29. if (!path) {
  30. test_err("couldn't allocate path");
  31. return -ENOMEM;
  32. }
  33. path->leave_spinning = 1;
  34. ret = btrfs_insert_empty_item(&trans, root, path, &ins, size);
  35. if (ret) {
  36. test_err("couldn't insert ref %d", ret);
  37. btrfs_free_path(path);
  38. return ret;
  39. }
  40. leaf = path->nodes[0];
  41. item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_extent_item);
  42. btrfs_set_extent_refs(leaf, item, 1);
  43. btrfs_set_extent_generation(leaf, item, 1);
  44. btrfs_set_extent_flags(leaf, item, BTRFS_EXTENT_FLAG_TREE_BLOCK);
  45. block_info = (struct btrfs_tree_block_info *)(item + 1);
  46. btrfs_set_tree_block_level(leaf, block_info, 0);
  47. iref = (struct btrfs_extent_inline_ref *)(block_info + 1);
  48. if (parent > 0) {
  49. btrfs_set_extent_inline_ref_type(leaf, iref,
  50. BTRFS_SHARED_BLOCK_REF_KEY);
  51. btrfs_set_extent_inline_ref_offset(leaf, iref, parent);
  52. } else {
  53. btrfs_set_extent_inline_ref_type(leaf, iref, BTRFS_TREE_BLOCK_REF_KEY);
  54. btrfs_set_extent_inline_ref_offset(leaf, iref, root_objectid);
  55. }
  56. btrfs_free_path(path);
  57. return 0;
  58. }
  59. static int add_tree_ref(struct btrfs_root *root, u64 bytenr, u64 num_bytes,
  60. u64 parent, u64 root_objectid)
  61. {
  62. struct btrfs_trans_handle trans;
  63. struct btrfs_extent_item *item;
  64. struct btrfs_path *path;
  65. struct btrfs_key key;
  66. u64 refs;
  67. int ret;
  68. btrfs_init_dummy_trans(&trans, NULL);
  69. key.objectid = bytenr;
  70. key.type = BTRFS_EXTENT_ITEM_KEY;
  71. key.offset = num_bytes;
  72. path = btrfs_alloc_path();
  73. if (!path) {
  74. test_err("couldn't allocate path");
  75. return -ENOMEM;
  76. }
  77. path->leave_spinning = 1;
  78. ret = btrfs_search_slot(&trans, root, &key, path, 0, 1);
  79. if (ret) {
  80. test_err("couldn't find extent ref");
  81. btrfs_free_path(path);
  82. return ret;
  83. }
  84. item = btrfs_item_ptr(path->nodes[0], path->slots[0],
  85. struct btrfs_extent_item);
  86. refs = btrfs_extent_refs(path->nodes[0], item);
  87. btrfs_set_extent_refs(path->nodes[0], item, refs + 1);
  88. btrfs_release_path(path);
  89. key.objectid = bytenr;
  90. if (parent) {
  91. key.type = BTRFS_SHARED_BLOCK_REF_KEY;
  92. key.offset = parent;
  93. } else {
  94. key.type = BTRFS_TREE_BLOCK_REF_KEY;
  95. key.offset = root_objectid;
  96. }
  97. ret = btrfs_insert_empty_item(&trans, root, path, &key, 0);
  98. if (ret)
  99. test_err("failed to insert backref");
  100. btrfs_free_path(path);
  101. return ret;
  102. }
  103. static int remove_extent_item(struct btrfs_root *root, u64 bytenr,
  104. u64 num_bytes)
  105. {
  106. struct btrfs_trans_handle trans;
  107. struct btrfs_key key;
  108. struct btrfs_path *path;
  109. int ret;
  110. btrfs_init_dummy_trans(&trans, NULL);
  111. key.objectid = bytenr;
  112. key.type = BTRFS_EXTENT_ITEM_KEY;
  113. key.offset = num_bytes;
  114. path = btrfs_alloc_path();
  115. if (!path) {
  116. test_err("couldn't allocate path");
  117. return -ENOMEM;
  118. }
  119. path->leave_spinning = 1;
  120. ret = btrfs_search_slot(&trans, root, &key, path, -1, 1);
  121. if (ret) {
  122. test_err("didn't find our key %d", ret);
  123. btrfs_free_path(path);
  124. return ret;
  125. }
  126. btrfs_del_item(&trans, root, path);
  127. btrfs_free_path(path);
  128. return 0;
  129. }
  130. static int remove_extent_ref(struct btrfs_root *root, u64 bytenr,
  131. u64 num_bytes, u64 parent, u64 root_objectid)
  132. {
  133. struct btrfs_trans_handle trans;
  134. struct btrfs_extent_item *item;
  135. struct btrfs_path *path;
  136. struct btrfs_key key;
  137. u64 refs;
  138. int ret;
  139. btrfs_init_dummy_trans(&trans, NULL);
  140. key.objectid = bytenr;
  141. key.type = BTRFS_EXTENT_ITEM_KEY;
  142. key.offset = num_bytes;
  143. path = btrfs_alloc_path();
  144. if (!path) {
  145. test_err("couldn't allocate path");
  146. return -ENOMEM;
  147. }
  148. path->leave_spinning = 1;
  149. ret = btrfs_search_slot(&trans, root, &key, path, 0, 1);
  150. if (ret) {
  151. test_err("couldn't find extent ref");
  152. btrfs_free_path(path);
  153. return ret;
  154. }
  155. item = btrfs_item_ptr(path->nodes[0], path->slots[0],
  156. struct btrfs_extent_item);
  157. refs = btrfs_extent_refs(path->nodes[0], item);
  158. btrfs_set_extent_refs(path->nodes[0], item, refs - 1);
  159. btrfs_release_path(path);
  160. key.objectid = bytenr;
  161. if (parent) {
  162. key.type = BTRFS_SHARED_BLOCK_REF_KEY;
  163. key.offset = parent;
  164. } else {
  165. key.type = BTRFS_TREE_BLOCK_REF_KEY;
  166. key.offset = root_objectid;
  167. }
  168. ret = btrfs_search_slot(&trans, root, &key, path, -1, 1);
  169. if (ret) {
  170. test_err("couldn't find backref %d", ret);
  171. btrfs_free_path(path);
  172. return ret;
  173. }
  174. btrfs_del_item(&trans, root, path);
  175. btrfs_free_path(path);
  176. return ret;
  177. }
  178. static int test_no_shared_qgroup(struct btrfs_root *root,
  179. u32 sectorsize, u32 nodesize)
  180. {
  181. struct btrfs_trans_handle trans;
  182. struct btrfs_fs_info *fs_info = root->fs_info;
  183. struct ulist *old_roots = NULL;
  184. struct ulist *new_roots = NULL;
  185. int ret;
  186. btrfs_init_dummy_trans(&trans, fs_info);
  187. test_msg("qgroup basic add");
  188. ret = btrfs_create_qgroup(&trans, BTRFS_FS_TREE_OBJECTID);
  189. if (ret) {
  190. test_err("couldn't create a qgroup %d", ret);
  191. return ret;
  192. }
  193. /*
  194. * Since the test trans doesn't have the complicated delayed refs,
  195. * we can only call btrfs_qgroup_account_extent() directly to test
  196. * quota.
  197. */
  198. ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots,
  199. false);
  200. if (ret) {
  201. ulist_free(old_roots);
  202. test_err("couldn't find old roots: %d", ret);
  203. return ret;
  204. }
  205. ret = insert_normal_tree_ref(root, nodesize, nodesize, 0,
  206. BTRFS_FS_TREE_OBJECTID);
  207. if (ret)
  208. return ret;
  209. ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots,
  210. false);
  211. if (ret) {
  212. ulist_free(old_roots);
  213. ulist_free(new_roots);
  214. test_err("couldn't find old roots: %d", ret);
  215. return ret;
  216. }
  217. ret = btrfs_qgroup_account_extent(&trans, nodesize, nodesize, old_roots,
  218. new_roots);
  219. if (ret) {
  220. test_err("couldn't account space for a qgroup %d", ret);
  221. return ret;
  222. }
  223. if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID,
  224. nodesize, nodesize)) {
  225. test_err("qgroup counts didn't match expected values");
  226. return -EINVAL;
  227. }
  228. old_roots = NULL;
  229. new_roots = NULL;
  230. ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots,
  231. false);
  232. if (ret) {
  233. ulist_free(old_roots);
  234. test_err("couldn't find old roots: %d", ret);
  235. return ret;
  236. }
  237. ret = remove_extent_item(root, nodesize, nodesize);
  238. if (ret)
  239. return -EINVAL;
  240. ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots,
  241. false);
  242. if (ret) {
  243. ulist_free(old_roots);
  244. ulist_free(new_roots);
  245. test_err("couldn't find old roots: %d", ret);
  246. return ret;
  247. }
  248. ret = btrfs_qgroup_account_extent(&trans, nodesize, nodesize, old_roots,
  249. new_roots);
  250. if (ret) {
  251. test_err("couldn't account space for a qgroup %d", ret);
  252. return -EINVAL;
  253. }
  254. if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID, 0, 0)) {
  255. test_err("qgroup counts didn't match expected values");
  256. return -EINVAL;
  257. }
  258. return 0;
  259. }
  260. /*
  261. * Add a ref for two different roots to make sure the shared value comes out
  262. * right, also remove one of the roots and make sure the exclusive count is
  263. * adjusted properly.
  264. */
  265. static int test_multiple_refs(struct btrfs_root *root,
  266. u32 sectorsize, u32 nodesize)
  267. {
  268. struct btrfs_trans_handle trans;
  269. struct btrfs_fs_info *fs_info = root->fs_info;
  270. struct ulist *old_roots = NULL;
  271. struct ulist *new_roots = NULL;
  272. int ret;
  273. btrfs_init_dummy_trans(&trans, fs_info);
  274. test_msg("qgroup multiple refs test");
  275. /*
  276. * We have BTRFS_FS_TREE_OBJECTID created already from the
  277. * previous test.
  278. */
  279. ret = btrfs_create_qgroup(&trans, BTRFS_FIRST_FREE_OBJECTID);
  280. if (ret) {
  281. test_err("couldn't create a qgroup %d", ret);
  282. return ret;
  283. }
  284. ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots,
  285. false);
  286. if (ret) {
  287. ulist_free(old_roots);
  288. test_err("couldn't find old roots: %d", ret);
  289. return ret;
  290. }
  291. ret = insert_normal_tree_ref(root, nodesize, nodesize, 0,
  292. BTRFS_FS_TREE_OBJECTID);
  293. if (ret)
  294. return ret;
  295. ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots,
  296. false);
  297. if (ret) {
  298. ulist_free(old_roots);
  299. ulist_free(new_roots);
  300. test_err("couldn't find old roots: %d", ret);
  301. return ret;
  302. }
  303. ret = btrfs_qgroup_account_extent(&trans, nodesize, nodesize, old_roots,
  304. new_roots);
  305. if (ret) {
  306. test_err("couldn't account space for a qgroup %d", ret);
  307. return ret;
  308. }
  309. if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID,
  310. nodesize, nodesize)) {
  311. test_err("qgroup counts didn't match expected values");
  312. return -EINVAL;
  313. }
  314. ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots,
  315. false);
  316. if (ret) {
  317. ulist_free(old_roots);
  318. test_err("couldn't find old roots: %d", ret);
  319. return ret;
  320. }
  321. ret = add_tree_ref(root, nodesize, nodesize, 0,
  322. BTRFS_FIRST_FREE_OBJECTID);
  323. if (ret)
  324. return ret;
  325. ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots,
  326. false);
  327. if (ret) {
  328. ulist_free(old_roots);
  329. ulist_free(new_roots);
  330. test_err("couldn't find old roots: %d", ret);
  331. return ret;
  332. }
  333. ret = btrfs_qgroup_account_extent(&trans, nodesize, nodesize, old_roots,
  334. new_roots);
  335. if (ret) {
  336. test_err("couldn't account space for a qgroup %d", ret);
  337. return ret;
  338. }
  339. if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID,
  340. nodesize, 0)) {
  341. test_err("qgroup counts didn't match expected values");
  342. return -EINVAL;
  343. }
  344. if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FIRST_FREE_OBJECTID,
  345. nodesize, 0)) {
  346. test_err("qgroup counts didn't match expected values");
  347. return -EINVAL;
  348. }
  349. ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &old_roots,
  350. false);
  351. if (ret) {
  352. ulist_free(old_roots);
  353. test_err("couldn't find old roots: %d", ret);
  354. return ret;
  355. }
  356. ret = remove_extent_ref(root, nodesize, nodesize, 0,
  357. BTRFS_FIRST_FREE_OBJECTID);
  358. if (ret)
  359. return ret;
  360. ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots,
  361. false);
  362. if (ret) {
  363. ulist_free(old_roots);
  364. ulist_free(new_roots);
  365. test_err("couldn't find old roots: %d", ret);
  366. return ret;
  367. }
  368. ret = btrfs_qgroup_account_extent(&trans, nodesize, nodesize, old_roots,
  369. new_roots);
  370. if (ret) {
  371. test_err("couldn't account space for a qgroup %d", ret);
  372. return ret;
  373. }
  374. if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FIRST_FREE_OBJECTID,
  375. 0, 0)) {
  376. test_err("qgroup counts didn't match expected values");
  377. return -EINVAL;
  378. }
  379. if (btrfs_verify_qgroup_counts(fs_info, BTRFS_FS_TREE_OBJECTID,
  380. nodesize, nodesize)) {
  381. test_err("qgroup counts didn't match expected values");
  382. return -EINVAL;
  383. }
  384. return 0;
  385. }
  386. int btrfs_test_qgroups(u32 sectorsize, u32 nodesize)
  387. {
  388. struct btrfs_fs_info *fs_info = NULL;
  389. struct btrfs_root *root;
  390. struct btrfs_root *tmp_root;
  391. int ret = 0;
  392. fs_info = btrfs_alloc_dummy_fs_info(nodesize, sectorsize);
  393. if (!fs_info) {
  394. test_err("couldn't allocate dummy fs info");
  395. return -ENOMEM;
  396. }
  397. root = btrfs_alloc_dummy_root(fs_info);
  398. if (IS_ERR(root)) {
  399. test_err("couldn't allocate root");
  400. ret = PTR_ERR(root);
  401. goto out;
  402. }
  403. /* We are using this root as our extent root */
  404. root->fs_info->extent_root = root;
  405. /*
  406. * Some of the paths we test assume we have a filled out fs_info, so we
  407. * just need to add the root in there so we don't panic.
  408. */
  409. root->fs_info->tree_root = root;
  410. root->fs_info->quota_root = root;
  411. set_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags);
  412. /*
  413. * Can't use bytenr 0, some things freak out
  414. * *cough*backref walking code*cough*
  415. */
  416. root->node = alloc_test_extent_buffer(root->fs_info, nodesize);
  417. if (IS_ERR(root->node)) {
  418. test_err("couldn't allocate dummy buffer");
  419. ret = PTR_ERR(root->node);
  420. goto out;
  421. }
  422. btrfs_set_header_level(root->node, 0);
  423. btrfs_set_header_nritems(root->node, 0);
  424. root->alloc_bytenr += 2 * nodesize;
  425. tmp_root = btrfs_alloc_dummy_root(fs_info);
  426. if (IS_ERR(tmp_root)) {
  427. test_err("couldn't allocate a fs root");
  428. ret = PTR_ERR(tmp_root);
  429. goto out;
  430. }
  431. tmp_root->root_key.objectid = BTRFS_FS_TREE_OBJECTID;
  432. root->fs_info->fs_root = tmp_root;
  433. ret = btrfs_insert_fs_root(root->fs_info, tmp_root);
  434. if (ret) {
  435. test_err("couldn't insert fs root %d", ret);
  436. goto out;
  437. }
  438. tmp_root = btrfs_alloc_dummy_root(fs_info);
  439. if (IS_ERR(tmp_root)) {
  440. test_err("couldn't allocate a fs root");
  441. ret = PTR_ERR(tmp_root);
  442. goto out;
  443. }
  444. tmp_root->root_key.objectid = BTRFS_FIRST_FREE_OBJECTID;
  445. ret = btrfs_insert_fs_root(root->fs_info, tmp_root);
  446. if (ret) {
  447. test_err("couldn't insert fs root %d", ret);
  448. goto out;
  449. }
  450. test_msg("running qgroup tests");
  451. ret = test_no_shared_qgroup(root, sectorsize, nodesize);
  452. if (ret)
  453. goto out;
  454. ret = test_multiple_refs(root, sectorsize, nodesize);
  455. out:
  456. btrfs_free_dummy_root(root);
  457. btrfs_free_dummy_fs_info(fs_info);
  458. return ret;
  459. }