mballoc-test.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * KUnit test of ext4 multiblocks allocation.
  4. */
  5. #include <kunit/test.h>
  6. #include <kunit/static_stub.h>
  7. #include <linux/random.h>
  8. #include "ext4.h"
  9. #include "mballoc.h"
  10. struct mbt_grp_ctx {
  11. struct buffer_head bitmap_bh;
  12. /* desc and gd_bh are just the place holders for now */
  13. struct ext4_group_desc desc;
  14. struct buffer_head gd_bh;
  15. };
  16. struct mbt_ctx {
  17. struct mbt_grp_ctx *grp_ctx;
  18. };
  19. struct mbt_ext4_super_block {
  20. struct ext4_super_block es;
  21. struct ext4_sb_info sbi;
  22. struct mbt_ctx mbt_ctx;
  23. };
  24. #define MBT_SB(_sb) (container_of((_sb)->s_fs_info, struct mbt_ext4_super_block, sbi))
  25. #define MBT_CTX(_sb) (&MBT_SB(_sb)->mbt_ctx)
  26. #define MBT_GRP_CTX(_sb, _group) (&MBT_CTX(_sb)->grp_ctx[_group])
  27. static struct inode *mbt_alloc_inode(struct super_block *sb)
  28. {
  29. struct ext4_inode_info *ei;
  30. ei = kmalloc_obj(struct ext4_inode_info);
  31. if (!ei)
  32. return NULL;
  33. INIT_LIST_HEAD(&ei->i_orphan);
  34. init_rwsem(&ei->xattr_sem);
  35. init_rwsem(&ei->i_data_sem);
  36. inode_init_once(&ei->vfs_inode);
  37. ext4_fc_init_inode(&ei->vfs_inode);
  38. return &ei->vfs_inode;
  39. }
  40. static void mbt_free_inode(struct inode *inode)
  41. {
  42. kfree(EXT4_I(inode));
  43. }
  44. static const struct super_operations mbt_sops = {
  45. .alloc_inode = mbt_alloc_inode,
  46. .free_inode = mbt_free_inode,
  47. };
  48. static void mbt_kill_sb(struct super_block *sb)
  49. {
  50. generic_shutdown_super(sb);
  51. }
  52. static struct file_system_type mbt_fs_type = {
  53. .name = "mballoc test",
  54. .kill_sb = mbt_kill_sb,
  55. };
  56. static int mbt_mb_init(struct super_block *sb)
  57. {
  58. ext4_fsblk_t block;
  59. int ret;
  60. /* needed by ext4_mb_init->bdev_nonrot(sb->s_bdev) */
  61. sb->s_bdev = kzalloc_obj(*sb->s_bdev);
  62. if (sb->s_bdev == NULL)
  63. return -ENOMEM;
  64. sb->s_bdev->bd_queue = kzalloc_obj(struct request_queue);
  65. if (sb->s_bdev->bd_queue == NULL) {
  66. kfree(sb->s_bdev);
  67. return -ENOMEM;
  68. }
  69. /*
  70. * needed by ext4_mb_init->ext4_mb_init_backend-> sbi->s_buddy_cache =
  71. * new_inode(sb);
  72. */
  73. INIT_LIST_HEAD(&sb->s_inodes);
  74. sb->s_op = &mbt_sops;
  75. ret = ext4_mb_init(sb);
  76. if (ret != 0)
  77. goto err_out;
  78. block = ext4_count_free_clusters(sb);
  79. ret = percpu_counter_init(&EXT4_SB(sb)->s_freeclusters_counter, block,
  80. GFP_KERNEL);
  81. if (ret != 0)
  82. goto err_mb_release;
  83. ret = percpu_counter_init(&EXT4_SB(sb)->s_dirtyclusters_counter, 0,
  84. GFP_KERNEL);
  85. if (ret != 0)
  86. goto err_freeclusters;
  87. return 0;
  88. err_freeclusters:
  89. percpu_counter_destroy(&EXT4_SB(sb)->s_freeclusters_counter);
  90. err_mb_release:
  91. ext4_mb_release(sb);
  92. err_out:
  93. kfree(sb->s_bdev->bd_queue);
  94. kfree(sb->s_bdev);
  95. return ret;
  96. }
  97. static void mbt_mb_release(struct super_block *sb)
  98. {
  99. percpu_counter_destroy(&EXT4_SB(sb)->s_dirtyclusters_counter);
  100. percpu_counter_destroy(&EXT4_SB(sb)->s_freeclusters_counter);
  101. ext4_mb_release(sb);
  102. kfree(sb->s_bdev->bd_queue);
  103. kfree(sb->s_bdev);
  104. }
  105. static int mbt_set(struct super_block *sb, void *data)
  106. {
  107. return 0;
  108. }
  109. static struct super_block *mbt_ext4_alloc_super_block(void)
  110. {
  111. struct mbt_ext4_super_block *fsb;
  112. struct super_block *sb;
  113. struct ext4_sb_info *sbi;
  114. fsb = kzalloc_obj(*fsb);
  115. if (fsb == NULL)
  116. return NULL;
  117. sb = sget(&mbt_fs_type, NULL, mbt_set, 0, NULL);
  118. if (IS_ERR(sb))
  119. goto out;
  120. sbi = &fsb->sbi;
  121. sbi->s_blockgroup_lock =
  122. kzalloc_obj(struct blockgroup_lock);
  123. if (!sbi->s_blockgroup_lock)
  124. goto out_deactivate;
  125. bgl_lock_init(sbi->s_blockgroup_lock);
  126. sbi->s_es = &fsb->es;
  127. sbi->s_sb = sb;
  128. sb->s_fs_info = sbi;
  129. up_write(&sb->s_umount);
  130. return sb;
  131. out_deactivate:
  132. deactivate_locked_super(sb);
  133. out:
  134. kfree(fsb);
  135. return NULL;
  136. }
  137. static void mbt_ext4_free_super_block(struct super_block *sb)
  138. {
  139. struct mbt_ext4_super_block *fsb = MBT_SB(sb);
  140. struct ext4_sb_info *sbi = EXT4_SB(sb);
  141. kfree(sbi->s_blockgroup_lock);
  142. deactivate_super(sb);
  143. kfree(fsb);
  144. }
  145. struct mbt_ext4_block_layout {
  146. unsigned char blocksize_bits;
  147. unsigned int cluster_bits;
  148. uint32_t blocks_per_group;
  149. ext4_group_t group_count;
  150. uint16_t desc_size;
  151. };
  152. static void mbt_init_sb_layout(struct super_block *sb,
  153. struct mbt_ext4_block_layout *layout)
  154. {
  155. struct ext4_sb_info *sbi = EXT4_SB(sb);
  156. struct ext4_super_block *es = sbi->s_es;
  157. sb->s_blocksize = 1UL << layout->blocksize_bits;
  158. sb->s_blocksize_bits = layout->blocksize_bits;
  159. sbi->s_groups_count = layout->group_count;
  160. sbi->s_blocks_per_group = layout->blocks_per_group;
  161. sbi->s_cluster_bits = layout->cluster_bits;
  162. sbi->s_cluster_ratio = 1U << layout->cluster_bits;
  163. sbi->s_clusters_per_group = layout->blocks_per_group >>
  164. layout->cluster_bits;
  165. sbi->s_desc_size = layout->desc_size;
  166. sbi->s_desc_per_block_bits =
  167. sb->s_blocksize_bits - (fls(layout->desc_size) - 1);
  168. sbi->s_desc_per_block = 1 << sbi->s_desc_per_block_bits;
  169. es->s_first_data_block = cpu_to_le32(0);
  170. es->s_blocks_count_lo = cpu_to_le32(layout->blocks_per_group *
  171. layout->group_count);
  172. }
  173. static int mbt_grp_ctx_init(struct super_block *sb,
  174. struct mbt_grp_ctx *grp_ctx)
  175. {
  176. ext4_grpblk_t max = EXT4_CLUSTERS_PER_GROUP(sb);
  177. grp_ctx->bitmap_bh.b_data = kzalloc(EXT4_BLOCK_SIZE(sb), GFP_KERNEL);
  178. if (grp_ctx->bitmap_bh.b_data == NULL)
  179. return -ENOMEM;
  180. mb_set_bits(grp_ctx->bitmap_bh.b_data, max, sb->s_blocksize * 8 - max);
  181. ext4_free_group_clusters_set(sb, &grp_ctx->desc, max);
  182. return 0;
  183. }
  184. static void mbt_grp_ctx_release(struct mbt_grp_ctx *grp_ctx)
  185. {
  186. kfree(grp_ctx->bitmap_bh.b_data);
  187. grp_ctx->bitmap_bh.b_data = NULL;
  188. }
  189. static void mbt_ctx_mark_used(struct super_block *sb, ext4_group_t group,
  190. unsigned int start, unsigned int len)
  191. {
  192. struct mbt_grp_ctx *grp_ctx = MBT_GRP_CTX(sb, group);
  193. mb_set_bits(grp_ctx->bitmap_bh.b_data, start, len);
  194. }
  195. static void *mbt_ctx_bitmap(struct super_block *sb, ext4_group_t group)
  196. {
  197. struct mbt_grp_ctx *grp_ctx = MBT_GRP_CTX(sb, group);
  198. return grp_ctx->bitmap_bh.b_data;
  199. }
  200. /* called after mbt_init_sb_layout */
  201. static int mbt_ctx_init(struct super_block *sb)
  202. {
  203. struct mbt_ctx *ctx = MBT_CTX(sb);
  204. ext4_group_t i, ngroups = ext4_get_groups_count(sb);
  205. ctx->grp_ctx = kzalloc_objs(struct mbt_grp_ctx, ngroups);
  206. if (ctx->grp_ctx == NULL)
  207. return -ENOMEM;
  208. for (i = 0; i < ngroups; i++)
  209. if (mbt_grp_ctx_init(sb, &ctx->grp_ctx[i]))
  210. goto out;
  211. /*
  212. * first data block(first cluster in first group) is used by
  213. * metadata, mark it used to avoid to alloc data block at first
  214. * block which will fail ext4_sb_block_valid check.
  215. */
  216. mb_set_bits(ctx->grp_ctx[0].bitmap_bh.b_data, 0, 1);
  217. ext4_free_group_clusters_set(sb, &ctx->grp_ctx[0].desc,
  218. EXT4_CLUSTERS_PER_GROUP(sb) - 1);
  219. return 0;
  220. out:
  221. while (i-- > 0)
  222. mbt_grp_ctx_release(&ctx->grp_ctx[i]);
  223. kfree(ctx->grp_ctx);
  224. return -ENOMEM;
  225. }
  226. static void mbt_ctx_release(struct super_block *sb)
  227. {
  228. struct mbt_ctx *ctx = MBT_CTX(sb);
  229. ext4_group_t i, ngroups = ext4_get_groups_count(sb);
  230. for (i = 0; i < ngroups; i++)
  231. mbt_grp_ctx_release(&ctx->grp_ctx[i]);
  232. kfree(ctx->grp_ctx);
  233. }
  234. static struct buffer_head *
  235. ext4_read_block_bitmap_nowait_stub(struct super_block *sb, ext4_group_t block_group,
  236. bool ignore_locked)
  237. {
  238. struct mbt_grp_ctx *grp_ctx = MBT_GRP_CTX(sb, block_group);
  239. /* paired with brelse from caller of ext4_read_block_bitmap_nowait */
  240. get_bh(&grp_ctx->bitmap_bh);
  241. return &grp_ctx->bitmap_bh;
  242. }
  243. static int ext4_wait_block_bitmap_stub(struct super_block *sb,
  244. ext4_group_t block_group,
  245. struct buffer_head *bh)
  246. {
  247. /*
  248. * real ext4_wait_block_bitmap will set these flags and
  249. * functions like ext4_mb_init_cache will verify the flags.
  250. */
  251. set_buffer_uptodate(bh);
  252. set_bitmap_uptodate(bh);
  253. set_buffer_verified(bh);
  254. return 0;
  255. }
  256. static struct ext4_group_desc *
  257. ext4_get_group_desc_stub(struct super_block *sb, ext4_group_t block_group,
  258. struct buffer_head **bh)
  259. {
  260. struct mbt_grp_ctx *grp_ctx = MBT_GRP_CTX(sb, block_group);
  261. if (bh != NULL)
  262. *bh = &grp_ctx->gd_bh;
  263. return &grp_ctx->desc;
  264. }
  265. static int
  266. ext4_mb_mark_context_stub(handle_t *handle, struct super_block *sb, bool state,
  267. ext4_group_t group, ext4_grpblk_t blkoff,
  268. ext4_grpblk_t len, int flags,
  269. ext4_grpblk_t *ret_changed)
  270. {
  271. struct mbt_grp_ctx *grp_ctx = MBT_GRP_CTX(sb, group);
  272. struct buffer_head *bitmap_bh = &grp_ctx->bitmap_bh;
  273. if (state)
  274. mb_set_bits(bitmap_bh->b_data, blkoff, len);
  275. else
  276. mb_clear_bits_test(bitmap_bh->b_data, blkoff, len);
  277. return 0;
  278. }
  279. #define TEST_GOAL_GROUP 1
  280. static int mbt_kunit_init(struct kunit *test)
  281. {
  282. struct mbt_ext4_block_layout *layout =
  283. (struct mbt_ext4_block_layout *)(test->param_value);
  284. struct super_block *sb;
  285. int ret;
  286. sb = mbt_ext4_alloc_super_block();
  287. if (sb == NULL)
  288. return -ENOMEM;
  289. mbt_init_sb_layout(sb, layout);
  290. ret = mbt_ctx_init(sb);
  291. if (ret != 0) {
  292. mbt_ext4_free_super_block(sb);
  293. return ret;
  294. }
  295. test->priv = sb;
  296. kunit_activate_static_stub(test,
  297. ext4_read_block_bitmap_nowait,
  298. ext4_read_block_bitmap_nowait_stub);
  299. kunit_activate_static_stub(test,
  300. ext4_wait_block_bitmap,
  301. ext4_wait_block_bitmap_stub);
  302. kunit_activate_static_stub(test,
  303. ext4_get_group_desc,
  304. ext4_get_group_desc_stub);
  305. kunit_activate_static_stub(test,
  306. ext4_mb_mark_context,
  307. ext4_mb_mark_context_stub);
  308. /* stub function will be called in mbt_mb_init->ext4_mb_init */
  309. if (mbt_mb_init(sb) != 0) {
  310. mbt_ctx_release(sb);
  311. mbt_ext4_free_super_block(sb);
  312. return -ENOMEM;
  313. }
  314. return 0;
  315. }
  316. static void mbt_kunit_exit(struct kunit *test)
  317. {
  318. struct super_block *sb = (struct super_block *)test->priv;
  319. mbt_mb_release(sb);
  320. mbt_ctx_release(sb);
  321. mbt_ext4_free_super_block(sb);
  322. }
  323. static void test_new_blocks_simple(struct kunit *test)
  324. {
  325. struct super_block *sb = (struct super_block *)test->priv;
  326. struct inode *inode;
  327. struct ext4_allocation_request ar;
  328. ext4_group_t i, goal_group = TEST_GOAL_GROUP;
  329. int err = 0;
  330. ext4_fsblk_t found;
  331. struct ext4_sb_info *sbi = EXT4_SB(sb);
  332. inode = kunit_kzalloc(test, sizeof(*inode), GFP_KERNEL);
  333. if (!inode)
  334. return;
  335. inode->i_sb = sb;
  336. ar.inode = inode;
  337. /* get block at goal */
  338. ar.goal = ext4_group_first_block_no(sb, goal_group);
  339. found = ext4_mb_new_blocks_simple_test(&ar, &err);
  340. KUNIT_ASSERT_EQ_MSG(test, ar.goal, found,
  341. "failed to alloc block at goal, expected %llu found %llu",
  342. ar.goal, found);
  343. /* get block after goal in goal group */
  344. ar.goal = ext4_group_first_block_no(sb, goal_group);
  345. found = ext4_mb_new_blocks_simple_test(&ar, &err);
  346. KUNIT_ASSERT_EQ_MSG(test, ar.goal + EXT4_C2B(sbi, 1), found,
  347. "failed to alloc block after goal in goal group, expected %llu found %llu",
  348. ar.goal + 1, found);
  349. /* get block after goal group */
  350. mbt_ctx_mark_used(sb, goal_group, 0, EXT4_CLUSTERS_PER_GROUP(sb));
  351. ar.goal = ext4_group_first_block_no(sb, goal_group);
  352. found = ext4_mb_new_blocks_simple_test(&ar, &err);
  353. KUNIT_ASSERT_EQ_MSG(test,
  354. ext4_group_first_block_no(sb, goal_group + 1), found,
  355. "failed to alloc block after goal group, expected %llu found %llu",
  356. ext4_group_first_block_no(sb, goal_group + 1), found);
  357. /* get block before goal group */
  358. for (i = goal_group; i < ext4_get_groups_count(sb); i++)
  359. mbt_ctx_mark_used(sb, i, 0, EXT4_CLUSTERS_PER_GROUP(sb));
  360. ar.goal = ext4_group_first_block_no(sb, goal_group);
  361. found = ext4_mb_new_blocks_simple_test(&ar, &err);
  362. KUNIT_ASSERT_EQ_MSG(test,
  363. ext4_group_first_block_no(sb, 0) + EXT4_C2B(sbi, 1), found,
  364. "failed to alloc block before goal group, expected %llu found %llu",
  365. ext4_group_first_block_no(sb, 0 + EXT4_C2B(sbi, 1)), found);
  366. /* no block available, fail to allocate block */
  367. for (i = 0; i < ext4_get_groups_count(sb); i++)
  368. mbt_ctx_mark_used(sb, i, 0, EXT4_CLUSTERS_PER_GROUP(sb));
  369. ar.goal = ext4_group_first_block_no(sb, goal_group);
  370. found = ext4_mb_new_blocks_simple_test(&ar, &err);
  371. KUNIT_ASSERT_NE_MSG(test, err, 0,
  372. "unexpectedly get block when no block is available");
  373. }
  374. #define TEST_RANGE_COUNT 8
  375. struct test_range {
  376. ext4_grpblk_t start;
  377. ext4_grpblk_t len;
  378. };
  379. static void
  380. mbt_generate_test_ranges(struct super_block *sb, struct test_range *ranges,
  381. int count)
  382. {
  383. ext4_grpblk_t start, len, max;
  384. int i;
  385. max = EXT4_CLUSTERS_PER_GROUP(sb) / count;
  386. for (i = 0; i < count; i++) {
  387. start = get_random_u32() % max;
  388. len = get_random_u32() % max;
  389. len = min(len, max - start);
  390. ranges[i].start = start + i * max;
  391. ranges[i].len = len;
  392. }
  393. }
  394. static void
  395. validate_free_blocks_simple(struct kunit *test, struct super_block *sb,
  396. ext4_group_t goal_group, ext4_grpblk_t start,
  397. ext4_grpblk_t len)
  398. {
  399. void *bitmap;
  400. ext4_grpblk_t bit, max = EXT4_CLUSTERS_PER_GROUP(sb);
  401. ext4_group_t i;
  402. for (i = 0; i < ext4_get_groups_count(sb); i++) {
  403. if (i == goal_group)
  404. continue;
  405. bitmap = mbt_ctx_bitmap(sb, i);
  406. bit = mb_find_next_zero_bit_test(bitmap, max, 0);
  407. KUNIT_ASSERT_EQ_MSG(test, bit, max,
  408. "free block on unexpected group %d", i);
  409. }
  410. bitmap = mbt_ctx_bitmap(sb, goal_group);
  411. bit = mb_find_next_zero_bit_test(bitmap, max, 0);
  412. KUNIT_ASSERT_EQ(test, bit, start);
  413. bit = mb_find_next_bit_test(bitmap, max, bit + 1);
  414. KUNIT_ASSERT_EQ(test, bit, start + len);
  415. }
  416. static void
  417. test_free_blocks_simple_range(struct kunit *test, ext4_group_t goal_group,
  418. ext4_grpblk_t start, ext4_grpblk_t len)
  419. {
  420. struct super_block *sb = (struct super_block *)test->priv;
  421. struct ext4_sb_info *sbi = EXT4_SB(sb);
  422. struct inode *inode;
  423. ext4_fsblk_t block;
  424. inode = kunit_kzalloc(test, sizeof(*inode), GFP_KERNEL);
  425. if (!inode)
  426. return;
  427. inode->i_sb = sb;
  428. if (len == 0)
  429. return;
  430. block = ext4_group_first_block_no(sb, goal_group) +
  431. EXT4_C2B(sbi, start);
  432. ext4_free_blocks_simple_test(inode, block, len);
  433. validate_free_blocks_simple(test, sb, goal_group, start, len);
  434. mbt_ctx_mark_used(sb, goal_group, 0, EXT4_CLUSTERS_PER_GROUP(sb));
  435. }
  436. static void test_free_blocks_simple(struct kunit *test)
  437. {
  438. struct super_block *sb = (struct super_block *)test->priv;
  439. ext4_grpblk_t max = EXT4_CLUSTERS_PER_GROUP(sb);
  440. ext4_group_t i;
  441. struct test_range ranges[TEST_RANGE_COUNT];
  442. for (i = 0; i < ext4_get_groups_count(sb); i++)
  443. mbt_ctx_mark_used(sb, i, 0, max);
  444. mbt_generate_test_ranges(sb, ranges, TEST_RANGE_COUNT);
  445. for (i = 0; i < TEST_RANGE_COUNT; i++)
  446. test_free_blocks_simple_range(test, TEST_GOAL_GROUP,
  447. ranges[i].start, ranges[i].len);
  448. }
  449. static void
  450. test_mark_diskspace_used_range(struct kunit *test,
  451. struct ext4_allocation_context *ac,
  452. ext4_grpblk_t start,
  453. ext4_grpblk_t len)
  454. {
  455. struct super_block *sb = (struct super_block *)test->priv;
  456. int ret;
  457. void *bitmap;
  458. ext4_grpblk_t i, max;
  459. /* ext4_mb_mark_diskspace_used will BUG if len is 0 */
  460. if (len == 0)
  461. return;
  462. ac->ac_b_ex.fe_group = TEST_GOAL_GROUP;
  463. ac->ac_b_ex.fe_start = start;
  464. ac->ac_b_ex.fe_len = len;
  465. bitmap = mbt_ctx_bitmap(sb, TEST_GOAL_GROUP);
  466. memset(bitmap, 0, sb->s_blocksize);
  467. ret = ext4_mb_mark_diskspace_used_test(ac, NULL);
  468. KUNIT_ASSERT_EQ(test, ret, 0);
  469. max = EXT4_CLUSTERS_PER_GROUP(sb);
  470. i = mb_find_next_bit_test(bitmap, max, 0);
  471. KUNIT_ASSERT_EQ(test, i, start);
  472. i = mb_find_next_zero_bit_test(bitmap, max, i + 1);
  473. KUNIT_ASSERT_EQ(test, i, start + len);
  474. i = mb_find_next_bit_test(bitmap, max, i + 1);
  475. KUNIT_ASSERT_EQ(test, max, i);
  476. }
  477. static void test_mark_diskspace_used(struct kunit *test)
  478. {
  479. struct super_block *sb = (struct super_block *)test->priv;
  480. struct inode *inode;
  481. struct ext4_allocation_context ac;
  482. struct test_range ranges[TEST_RANGE_COUNT];
  483. int i;
  484. mbt_generate_test_ranges(sb, ranges, TEST_RANGE_COUNT);
  485. inode = kunit_kzalloc(test, sizeof(*inode), GFP_KERNEL);
  486. if (!inode)
  487. return;
  488. inode->i_sb = sb;
  489. ac.ac_status = AC_STATUS_FOUND;
  490. ac.ac_sb = sb;
  491. ac.ac_inode = inode;
  492. for (i = 0; i < TEST_RANGE_COUNT; i++)
  493. test_mark_diskspace_used_range(test, &ac, ranges[i].start,
  494. ranges[i].len);
  495. }
  496. static void mbt_generate_buddy(struct super_block *sb, void *buddy,
  497. void *bitmap, struct ext4_group_info *grp)
  498. {
  499. struct ext4_sb_info *sbi = EXT4_SB(sb);
  500. uint32_t order, off;
  501. void *bb, *bb_h;
  502. int max;
  503. memset(buddy, 0xff, sb->s_blocksize);
  504. memset(grp, 0, offsetof(struct ext4_group_info,
  505. bb_counters[MB_NUM_ORDERS(sb)]));
  506. bb = bitmap;
  507. max = EXT4_CLUSTERS_PER_GROUP(sb);
  508. bb_h = buddy + sbi->s_mb_offsets[1];
  509. off = mb_find_next_zero_bit_test(bb, max, 0);
  510. grp->bb_first_free = off;
  511. while (off < max) {
  512. grp->bb_counters[0]++;
  513. grp->bb_free++;
  514. if (!(off & 1) && !mb_test_bit_test(off + 1, bb)) {
  515. grp->bb_free++;
  516. grp->bb_counters[0]--;
  517. mb_clear_bit_test(off >> 1, bb_h);
  518. grp->bb_counters[1]++;
  519. grp->bb_largest_free_order = 1;
  520. off++;
  521. }
  522. off = mb_find_next_zero_bit_test(bb, max, off + 1);
  523. }
  524. for (order = 1; order < MB_NUM_ORDERS(sb) - 1; order++) {
  525. bb = buddy + sbi->s_mb_offsets[order];
  526. bb_h = buddy + sbi->s_mb_offsets[order + 1];
  527. max = max >> 1;
  528. off = mb_find_next_zero_bit_test(bb, max, 0);
  529. while (off < max) {
  530. if (!(off & 1) && !mb_test_bit_test(off + 1, bb)) {
  531. mb_set_bits(bb, off, 2);
  532. grp->bb_counters[order] -= 2;
  533. mb_clear_bit_test(off >> 1, bb_h);
  534. grp->bb_counters[order + 1]++;
  535. grp->bb_largest_free_order = order + 1;
  536. off++;
  537. }
  538. off = mb_find_next_zero_bit_test(bb, max, off + 1);
  539. }
  540. }
  541. max = EXT4_CLUSTERS_PER_GROUP(sb);
  542. off = mb_find_next_zero_bit_test(bitmap, max, 0);
  543. while (off < max) {
  544. grp->bb_fragments++;
  545. off = mb_find_next_bit_test(bitmap, max, off + 1);
  546. if (off + 1 >= max)
  547. break;
  548. off = mb_find_next_zero_bit_test(bitmap, max, off + 1);
  549. }
  550. }
  551. static void
  552. mbt_validate_group_info(struct kunit *test, struct ext4_group_info *grp1,
  553. struct ext4_group_info *grp2)
  554. {
  555. struct super_block *sb = (struct super_block *)test->priv;
  556. int i;
  557. KUNIT_ASSERT_EQ(test, grp1->bb_first_free,
  558. grp2->bb_first_free);
  559. KUNIT_ASSERT_EQ(test, grp1->bb_fragments,
  560. grp2->bb_fragments);
  561. KUNIT_ASSERT_EQ(test, grp1->bb_free, grp2->bb_free);
  562. KUNIT_ASSERT_EQ(test, grp1->bb_largest_free_order,
  563. grp2->bb_largest_free_order);
  564. for (i = 1; i < MB_NUM_ORDERS(sb); i++) {
  565. KUNIT_ASSERT_EQ_MSG(test, grp1->bb_counters[i],
  566. grp2->bb_counters[i],
  567. "bb_counters[%d] diffs, expected %d, generated %d",
  568. i, grp1->bb_counters[i],
  569. grp2->bb_counters[i]);
  570. }
  571. }
  572. static void
  573. do_test_generate_buddy(struct kunit *test, struct super_block *sb, void *bitmap,
  574. void *mbt_buddy, struct ext4_group_info *mbt_grp,
  575. void *ext4_buddy, struct ext4_group_info *ext4_grp)
  576. {
  577. int i;
  578. mbt_generate_buddy(sb, mbt_buddy, bitmap, mbt_grp);
  579. for (i = 0; i < MB_NUM_ORDERS(sb); i++)
  580. ext4_grp->bb_counters[i] = 0;
  581. /* needed by validation in ext4_mb_generate_buddy */
  582. ext4_grp->bb_free = mbt_grp->bb_free;
  583. memset(ext4_buddy, 0xff, sb->s_blocksize);
  584. ext4_mb_generate_buddy_test(sb, ext4_buddy, bitmap, TEST_GOAL_GROUP,
  585. ext4_grp);
  586. KUNIT_ASSERT_EQ(test, memcmp(mbt_buddy, ext4_buddy, sb->s_blocksize),
  587. 0);
  588. mbt_validate_group_info(test, mbt_grp, ext4_grp);
  589. }
  590. static void test_mb_generate_buddy(struct kunit *test)
  591. {
  592. struct super_block *sb = (struct super_block *)test->priv;
  593. void *bitmap, *expected_bb, *generate_bb;
  594. struct ext4_group_info *expected_grp, *generate_grp;
  595. struct test_range ranges[TEST_RANGE_COUNT];
  596. int i;
  597. bitmap = kunit_kzalloc(test, sb->s_blocksize, GFP_KERNEL);
  598. KUNIT_ASSERT_NOT_ERR_OR_NULL(test, bitmap);
  599. expected_bb = kunit_kzalloc(test, sb->s_blocksize, GFP_KERNEL);
  600. KUNIT_ASSERT_NOT_ERR_OR_NULL(test, expected_bb);
  601. generate_bb = kunit_kzalloc(test, sb->s_blocksize, GFP_KERNEL);
  602. KUNIT_ASSERT_NOT_ERR_OR_NULL(test, generate_bb);
  603. expected_grp = kunit_kzalloc(test, offsetof(struct ext4_group_info,
  604. bb_counters[MB_NUM_ORDERS(sb)]), GFP_KERNEL);
  605. KUNIT_ASSERT_NOT_ERR_OR_NULL(test, expected_grp);
  606. generate_grp = ext4_get_group_info(sb, TEST_GOAL_GROUP);
  607. KUNIT_ASSERT_NOT_NULL(test, generate_grp);
  608. mbt_generate_test_ranges(sb, ranges, TEST_RANGE_COUNT);
  609. for (i = 0; i < TEST_RANGE_COUNT; i++) {
  610. mb_set_bits(bitmap, ranges[i].start, ranges[i].len);
  611. do_test_generate_buddy(test, sb, bitmap, expected_bb,
  612. expected_grp, generate_bb, generate_grp);
  613. }
  614. }
  615. static void
  616. test_mb_mark_used_range(struct kunit *test, struct ext4_buddy *e4b,
  617. ext4_grpblk_t start, ext4_grpblk_t len, void *bitmap,
  618. void *buddy, struct ext4_group_info *grp)
  619. {
  620. struct super_block *sb = (struct super_block *)test->priv;
  621. struct ext4_free_extent ex;
  622. int i;
  623. /* mb_mark_used only accepts non-zero len */
  624. if (len == 0)
  625. return;
  626. ex.fe_start = start;
  627. ex.fe_len = len;
  628. ex.fe_group = TEST_GOAL_GROUP;
  629. ext4_lock_group(sb, TEST_GOAL_GROUP);
  630. mb_mark_used_test(e4b, &ex);
  631. ext4_unlock_group(sb, TEST_GOAL_GROUP);
  632. mb_set_bits(bitmap, start, len);
  633. /* bypass bb_free validatoin in ext4_mb_generate_buddy */
  634. grp->bb_free -= len;
  635. memset(buddy, 0xff, sb->s_blocksize);
  636. for (i = 0; i < MB_NUM_ORDERS(sb); i++)
  637. grp->bb_counters[i] = 0;
  638. ext4_mb_generate_buddy_test(sb, buddy, bitmap, 0, grp);
  639. KUNIT_ASSERT_EQ(test, memcmp(buddy, e4b->bd_buddy, sb->s_blocksize),
  640. 0);
  641. mbt_validate_group_info(test, grp, e4b->bd_info);
  642. }
  643. static void test_mb_mark_used(struct kunit *test)
  644. {
  645. struct ext4_buddy e4b;
  646. struct super_block *sb = (struct super_block *)test->priv;
  647. void *bitmap, *buddy;
  648. struct ext4_group_info *grp;
  649. int ret;
  650. struct test_range ranges[TEST_RANGE_COUNT];
  651. int i;
  652. /* buddy cache assumes that each page contains at least one block */
  653. if (sb->s_blocksize > PAGE_SIZE)
  654. kunit_skip(test, "blocksize exceeds pagesize");
  655. bitmap = kunit_kzalloc(test, sb->s_blocksize, GFP_KERNEL);
  656. KUNIT_ASSERT_NOT_ERR_OR_NULL(test, bitmap);
  657. buddy = kunit_kzalloc(test, sb->s_blocksize, GFP_KERNEL);
  658. KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buddy);
  659. grp = kunit_kzalloc(test, offsetof(struct ext4_group_info,
  660. bb_counters[MB_NUM_ORDERS(sb)]), GFP_KERNEL);
  661. KUNIT_ASSERT_NOT_ERR_OR_NULL(test, grp);
  662. ret = ext4_mb_load_buddy_test(sb, TEST_GOAL_GROUP, &e4b);
  663. KUNIT_ASSERT_EQ(test, ret, 0);
  664. grp->bb_free = EXT4_CLUSTERS_PER_GROUP(sb);
  665. grp->bb_largest_free_order = -1;
  666. grp->bb_avg_fragment_size_order = -1;
  667. mbt_generate_test_ranges(sb, ranges, TEST_RANGE_COUNT);
  668. for (i = 0; i < TEST_RANGE_COUNT; i++)
  669. test_mb_mark_used_range(test, &e4b, ranges[i].start,
  670. ranges[i].len, bitmap, buddy, grp);
  671. ext4_mb_unload_buddy_test(&e4b);
  672. }
  673. static void
  674. test_mb_free_blocks_range(struct kunit *test, struct ext4_buddy *e4b,
  675. ext4_grpblk_t start, ext4_grpblk_t len, void *bitmap,
  676. void *buddy, struct ext4_group_info *grp)
  677. {
  678. struct super_block *sb = (struct super_block *)test->priv;
  679. int i;
  680. /* mb_free_blocks will WARN if len is 0 */
  681. if (len == 0)
  682. return;
  683. ext4_lock_group(sb, e4b->bd_group);
  684. mb_free_blocks_test(NULL, e4b, start, len);
  685. ext4_unlock_group(sb, e4b->bd_group);
  686. mb_clear_bits_test(bitmap, start, len);
  687. /* bypass bb_free validatoin in ext4_mb_generate_buddy */
  688. grp->bb_free += len;
  689. memset(buddy, 0xff, sb->s_blocksize);
  690. for (i = 0; i < MB_NUM_ORDERS(sb); i++)
  691. grp->bb_counters[i] = 0;
  692. ext4_mb_generate_buddy_test(sb, buddy, bitmap, 0, grp);
  693. KUNIT_ASSERT_EQ(test, memcmp(buddy, e4b->bd_buddy, sb->s_blocksize),
  694. 0);
  695. mbt_validate_group_info(test, grp, e4b->bd_info);
  696. }
  697. static void test_mb_free_blocks(struct kunit *test)
  698. {
  699. struct ext4_buddy e4b;
  700. struct super_block *sb = (struct super_block *)test->priv;
  701. void *bitmap, *buddy;
  702. struct ext4_group_info *grp;
  703. struct ext4_free_extent ex;
  704. int ret;
  705. int i;
  706. struct test_range ranges[TEST_RANGE_COUNT];
  707. /* buddy cache assumes that each page contains at least one block */
  708. if (sb->s_blocksize > PAGE_SIZE)
  709. kunit_skip(test, "blocksize exceeds pagesize");
  710. bitmap = kunit_kzalloc(test, sb->s_blocksize, GFP_KERNEL);
  711. KUNIT_ASSERT_NOT_ERR_OR_NULL(test, bitmap);
  712. buddy = kunit_kzalloc(test, sb->s_blocksize, GFP_KERNEL);
  713. KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buddy);
  714. grp = kunit_kzalloc(test, offsetof(struct ext4_group_info,
  715. bb_counters[MB_NUM_ORDERS(sb)]), GFP_KERNEL);
  716. KUNIT_ASSERT_NOT_ERR_OR_NULL(test, grp);
  717. ret = ext4_mb_load_buddy_test(sb, TEST_GOAL_GROUP, &e4b);
  718. KUNIT_ASSERT_EQ(test, ret, 0);
  719. ex.fe_start = 0;
  720. ex.fe_len = EXT4_CLUSTERS_PER_GROUP(sb);
  721. ex.fe_group = TEST_GOAL_GROUP;
  722. ext4_lock_group(sb, TEST_GOAL_GROUP);
  723. mb_mark_used_test(&e4b, &ex);
  724. ext4_unlock_group(sb, TEST_GOAL_GROUP);
  725. grp->bb_free = 0;
  726. grp->bb_largest_free_order = -1;
  727. grp->bb_avg_fragment_size_order = -1;
  728. memset(bitmap, 0xff, sb->s_blocksize);
  729. mbt_generate_test_ranges(sb, ranges, TEST_RANGE_COUNT);
  730. for (i = 0; i < TEST_RANGE_COUNT; i++)
  731. test_mb_free_blocks_range(test, &e4b, ranges[i].start,
  732. ranges[i].len, bitmap, buddy, grp);
  733. ext4_mb_unload_buddy_test(&e4b);
  734. }
  735. #define COUNT_FOR_ESTIMATE 100000
  736. static void test_mb_mark_used_cost(struct kunit *test)
  737. {
  738. struct ext4_buddy e4b;
  739. struct super_block *sb = (struct super_block *)test->priv;
  740. struct ext4_free_extent ex;
  741. int ret;
  742. struct test_range ranges[TEST_RANGE_COUNT];
  743. int i, j;
  744. unsigned long start, end, all = 0;
  745. /* buddy cache assumes that each page contains at least one block */
  746. if (sb->s_blocksize > PAGE_SIZE)
  747. kunit_skip(test, "blocksize exceeds pagesize");
  748. ret = ext4_mb_load_buddy_test(sb, TEST_GOAL_GROUP, &e4b);
  749. KUNIT_ASSERT_EQ(test, ret, 0);
  750. ex.fe_group = TEST_GOAL_GROUP;
  751. for (j = 0; j < COUNT_FOR_ESTIMATE; j++) {
  752. mbt_generate_test_ranges(sb, ranges, TEST_RANGE_COUNT);
  753. start = jiffies;
  754. for (i = 0; i < TEST_RANGE_COUNT; i++) {
  755. if (ranges[i].len == 0)
  756. continue;
  757. ex.fe_start = ranges[i].start;
  758. ex.fe_len = ranges[i].len;
  759. ext4_lock_group(sb, TEST_GOAL_GROUP);
  760. mb_mark_used_test(&e4b, &ex);
  761. ext4_unlock_group(sb, TEST_GOAL_GROUP);
  762. }
  763. end = jiffies;
  764. all += (end - start);
  765. for (i = 0; i < TEST_RANGE_COUNT; i++) {
  766. if (ranges[i].len == 0)
  767. continue;
  768. ext4_lock_group(sb, TEST_GOAL_GROUP);
  769. mb_free_blocks_test(NULL, &e4b, ranges[i].start,
  770. ranges[i].len);
  771. ext4_unlock_group(sb, TEST_GOAL_GROUP);
  772. }
  773. }
  774. kunit_info(test, "costed jiffies %lu\n", all);
  775. ext4_mb_unload_buddy_test(&e4b);
  776. }
  777. static const struct mbt_ext4_block_layout mbt_test_layouts[] = {
  778. {
  779. .blocksize_bits = 10,
  780. .cluster_bits = 3,
  781. .blocks_per_group = 8192,
  782. .group_count = 4,
  783. .desc_size = 64,
  784. },
  785. {
  786. .blocksize_bits = 12,
  787. .cluster_bits = 3,
  788. .blocks_per_group = 8192,
  789. .group_count = 4,
  790. .desc_size = 64,
  791. },
  792. {
  793. .blocksize_bits = 16,
  794. .cluster_bits = 3,
  795. .blocks_per_group = 8192,
  796. .group_count = 4,
  797. .desc_size = 64,
  798. },
  799. };
  800. static void mbt_show_layout(const struct mbt_ext4_block_layout *layout,
  801. char *desc)
  802. {
  803. snprintf(desc, KUNIT_PARAM_DESC_SIZE, "block_bits=%d cluster_bits=%d "
  804. "blocks_per_group=%d group_count=%d desc_size=%d\n",
  805. layout->blocksize_bits, layout->cluster_bits,
  806. layout->blocks_per_group, layout->group_count,
  807. layout->desc_size);
  808. }
  809. KUNIT_ARRAY_PARAM(mbt_layouts, mbt_test_layouts, mbt_show_layout);
  810. static struct kunit_case mbt_test_cases[] = {
  811. KUNIT_CASE_PARAM(test_new_blocks_simple, mbt_layouts_gen_params),
  812. KUNIT_CASE_PARAM(test_free_blocks_simple, mbt_layouts_gen_params),
  813. KUNIT_CASE_PARAM(test_mb_generate_buddy, mbt_layouts_gen_params),
  814. KUNIT_CASE_PARAM(test_mb_mark_used, mbt_layouts_gen_params),
  815. KUNIT_CASE_PARAM(test_mb_free_blocks, mbt_layouts_gen_params),
  816. KUNIT_CASE_PARAM(test_mark_diskspace_used, mbt_layouts_gen_params),
  817. KUNIT_CASE_PARAM_ATTR(test_mb_mark_used_cost, mbt_layouts_gen_params,
  818. { .speed = KUNIT_SPEED_SLOW }),
  819. {}
  820. };
  821. static struct kunit_suite mbt_test_suite = {
  822. .name = "ext4_mballoc_test",
  823. .init = mbt_kunit_init,
  824. .exit = mbt_kunit_exit,
  825. .test_cases = mbt_test_cases,
  826. };
  827. kunit_test_suites(&mbt_test_suite);
  828. MODULE_LICENSE("GPL");