stresstest.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (C) 2006-2008 Nokia Corporation
  4. *
  5. * Test random reads, writes and erases on MTD device.
  6. *
  7. * Author: Adrian Hunter <ext-adrian.hunter@nokia.com>
  8. */
  9. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  10. #include <linux/init.h>
  11. #include <linux/module.h>
  12. #include <linux/moduleparam.h>
  13. #include <linux/err.h>
  14. #include <linux/mtd/mtd.h>
  15. #include <linux/slab.h>
  16. #include <linux/sched.h>
  17. #include <linux/vmalloc.h>
  18. #include <linux/random.h>
  19. #include "mtd_test.h"
  20. static int dev = -EINVAL;
  21. module_param(dev, int, S_IRUGO);
  22. MODULE_PARM_DESC(dev, "MTD device number to use");
  23. static int count = 10000;
  24. module_param(count, int, S_IRUGO);
  25. MODULE_PARM_DESC(count, "Number of operations to do (default is 10000)");
  26. static struct mtd_info *mtd;
  27. static unsigned char *writebuf;
  28. static unsigned char *readbuf;
  29. static unsigned char *bbt;
  30. static int *offsets;
  31. static int pgsize;
  32. static int bufsize;
  33. static int ebcnt;
  34. static int pgcnt;
  35. static int rand_eb(void)
  36. {
  37. unsigned int eb;
  38. again:
  39. eb = prandom_u32();
  40. /* Read or write up 2 eraseblocks at a time - hence 'ebcnt - 1' */
  41. eb %= (ebcnt - 1);
  42. if (bbt[eb])
  43. goto again;
  44. return eb;
  45. }
  46. static int rand_offs(void)
  47. {
  48. unsigned int offs;
  49. offs = prandom_u32();
  50. offs %= bufsize;
  51. return offs;
  52. }
  53. static int rand_len(int offs)
  54. {
  55. unsigned int len;
  56. len = prandom_u32();
  57. len %= (bufsize - offs);
  58. return len;
  59. }
  60. static int do_read(void)
  61. {
  62. int eb = rand_eb();
  63. int offs = rand_offs();
  64. int len = rand_len(offs);
  65. loff_t addr;
  66. if (bbt[eb + 1]) {
  67. if (offs >= mtd->erasesize)
  68. offs -= mtd->erasesize;
  69. if (offs + len > mtd->erasesize)
  70. len = mtd->erasesize - offs;
  71. }
  72. addr = (loff_t)eb * mtd->erasesize + offs;
  73. return mtdtest_read(mtd, addr, len, readbuf);
  74. }
  75. static int do_write(void)
  76. {
  77. int eb = rand_eb(), offs, err, len;
  78. loff_t addr;
  79. offs = offsets[eb];
  80. if (offs >= mtd->erasesize) {
  81. err = mtdtest_erase_eraseblock(mtd, eb);
  82. if (err)
  83. return err;
  84. offs = offsets[eb] = 0;
  85. }
  86. len = rand_len(offs);
  87. len = ((len + pgsize - 1) / pgsize) * pgsize;
  88. if (offs + len > mtd->erasesize) {
  89. if (bbt[eb + 1])
  90. len = mtd->erasesize - offs;
  91. else {
  92. err = mtdtest_erase_eraseblock(mtd, eb + 1);
  93. if (err)
  94. return err;
  95. offsets[eb + 1] = 0;
  96. }
  97. }
  98. addr = (loff_t)eb * mtd->erasesize + offs;
  99. err = mtdtest_write(mtd, addr, len, writebuf);
  100. if (unlikely(err))
  101. return err;
  102. offs += len;
  103. while (offs > mtd->erasesize) {
  104. offsets[eb++] = mtd->erasesize;
  105. offs -= mtd->erasesize;
  106. }
  107. offsets[eb] = offs;
  108. return 0;
  109. }
  110. static int do_operation(void)
  111. {
  112. if (prandom_u32() & 1)
  113. return do_read();
  114. else
  115. return do_write();
  116. }
  117. static int __init mtd_stresstest_init(void)
  118. {
  119. int err;
  120. int i, op;
  121. uint64_t tmp;
  122. printk(KERN_INFO "\n");
  123. printk(KERN_INFO "=================================================\n");
  124. if (dev < 0) {
  125. pr_info("Please specify a valid mtd-device via module parameter\n");
  126. pr_crit("CAREFUL: This test wipes all data on the specified MTD device!\n");
  127. return -EINVAL;
  128. }
  129. pr_info("MTD device: %d\n", dev);
  130. mtd = get_mtd_device(NULL, dev);
  131. if (IS_ERR(mtd)) {
  132. err = PTR_ERR(mtd);
  133. pr_err("error: cannot get MTD device\n");
  134. return err;
  135. }
  136. if (mtd->writesize == 1) {
  137. pr_info("not NAND flash, assume page size is 512 "
  138. "bytes.\n");
  139. pgsize = 512;
  140. } else
  141. pgsize = mtd->writesize;
  142. tmp = mtd->size;
  143. do_div(tmp, mtd->erasesize);
  144. ebcnt = tmp;
  145. pgcnt = mtd->erasesize / pgsize;
  146. pr_info("MTD device size %llu, eraseblock size %u, "
  147. "page size %u, count of eraseblocks %u, pages per "
  148. "eraseblock %u, OOB size %u\n",
  149. (unsigned long long)mtd->size, mtd->erasesize,
  150. pgsize, ebcnt, pgcnt, mtd->oobsize);
  151. if (ebcnt < 2) {
  152. pr_err("error: need at least 2 eraseblocks\n");
  153. err = -ENOSPC;
  154. goto out_put_mtd;
  155. }
  156. /* Read or write up 2 eraseblocks at a time */
  157. bufsize = mtd->erasesize * 2;
  158. err = -ENOMEM;
  159. readbuf = vmalloc(bufsize);
  160. writebuf = vmalloc(bufsize);
  161. offsets = kmalloc_array(ebcnt, sizeof(int), GFP_KERNEL);
  162. if (!readbuf || !writebuf || !offsets)
  163. goto out;
  164. for (i = 0; i < ebcnt; i++)
  165. offsets[i] = mtd->erasesize;
  166. prandom_bytes(writebuf, bufsize);
  167. bbt = kzalloc(ebcnt, GFP_KERNEL);
  168. if (!bbt)
  169. goto out;
  170. err = mtdtest_scan_for_bad_eraseblocks(mtd, bbt, 0, ebcnt);
  171. if (err)
  172. goto out;
  173. /* Do operations */
  174. pr_info("doing operations\n");
  175. for (op = 0; op < count; op++) {
  176. if ((op & 1023) == 0)
  177. pr_info("%d operations done\n", op);
  178. err = do_operation();
  179. if (err)
  180. goto out;
  181. err = mtdtest_relax();
  182. if (err)
  183. goto out;
  184. }
  185. pr_info("finished, %d operations done\n", op);
  186. out:
  187. kfree(offsets);
  188. kfree(bbt);
  189. vfree(writebuf);
  190. vfree(readbuf);
  191. out_put_mtd:
  192. put_mtd_device(mtd);
  193. if (err)
  194. pr_info("error %d occurred\n", err);
  195. printk(KERN_INFO "=================================================\n");
  196. return err;
  197. }
  198. module_init(mtd_stresstest_init);
  199. static void __exit mtd_stresstest_exit(void)
  200. {
  201. return;
  202. }
  203. module_exit(mtd_stresstest_exit);
  204. MODULE_DESCRIPTION("Stress test module");
  205. MODULE_AUTHOR("Adrian Hunter");
  206. MODULE_LICENSE("GPL");