integ.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781
  1. #define _LARGEFILE64_SOURCE
  2. #include <sys/types.h>
  3. #include <sys/stat.h>
  4. #include <fcntl.h>
  5. #include <unistd.h>
  6. #include <stdlib.h>
  7. #include <stdio.h>
  8. #include <stdint.h>
  9. #include <string.h>
  10. #include <errno.h>
  11. #include <sys/ioctl.h>
  12. #include <sys/stat.h>
  13. #include "libubi.h"
  14. #define PROGRAM_NAME "integ"
  15. #include "common.h"
  16. #include "helpers.h"
  17. struct erase_block_info;
  18. struct volume_info;
  19. struct ubi_device_info;
  20. struct write_info
  21. {
  22. struct write_info *next;
  23. struct erase_block_info *erase_block;
  24. int offset_within_block; /* Offset within erase block */
  25. off_t offset; /* Offset within volume */
  26. int size;
  27. int random_seed;
  28. };
  29. struct erase_block_info
  30. {
  31. struct volume_info *volume;
  32. int block_number;
  33. off_t offset; /* Offset within volume */
  34. off_t top_of_data;
  35. int touched; /* Have we done anything at all with this erase block */
  36. int erased; /* This erased block is currently erased */
  37. struct write_info *writes;
  38. };
  39. struct volume_fd
  40. {
  41. struct volume_fd *next;
  42. struct volume_info *volume;
  43. int fd;
  44. };
  45. struct volume_info
  46. {
  47. struct volume_info *next;
  48. struct ubi_device_info *ubi_device;
  49. struct volume_fd *fds;
  50. struct erase_block_info *erase_blocks;
  51. const char *device_file_name;
  52. struct ubi_vol_info info;
  53. };
  54. struct ubi_device_info
  55. {
  56. struct volume_info *volumes;
  57. const char *device_file_name;
  58. struct ubi_dev_info info;
  59. };
  60. struct open_volume_fd
  61. {
  62. struct open_volume_fd *next;
  63. struct volume_fd *vol_fd;
  64. };
  65. #define MAX_UBI_DEVICES 64
  66. static libubi_t libubi;
  67. static struct ubi_info info;
  68. static struct ubi_device_info ubi_array[MAX_UBI_DEVICES];
  69. static uint64_t total_written = 0;
  70. static uint64_t total_space = 0;
  71. static struct open_volume_fd *open_volumes;
  72. static int open_volume_count = 0;
  73. static const char *ubi_module_load_string;
  74. static unsigned char *write_buffer = NULL;
  75. static unsigned char *read_buffer = NULL;
  76. static long long max_ebs_per_vol = 0; /* max number of ebs per vol (zero => no max) */
  77. static unsigned long next_seed = 1;
  78. static unsigned get_next_seed()
  79. {
  80. next_seed = next_seed * 1103515245 + 12345;
  81. return ((unsigned) (next_seed / 65536) % 32768);
  82. }
  83. static void error_exit(const char *msg)
  84. {
  85. int eno = errno;
  86. fprintf(stderr,"UBI Integrity Test Error: %s\n",msg);
  87. if (eno) {
  88. fprintf(stderr, "errno = %d\n", eno);
  89. fprintf(stderr, "strerror = %s\n", strerror(eno));
  90. }
  91. exit(1);
  92. }
  93. static void *allocate(size_t n)
  94. {
  95. void *p = malloc(n);
  96. if (!p)
  97. error_exit("Memory allocation failure");
  98. memset(p, 0, n);
  99. return p;
  100. }
  101. static unsigned get_random_number(unsigned n)
  102. {
  103. uint64_t r, b;
  104. if (n < 1)
  105. return 0;
  106. r = rand();
  107. r *= n;
  108. b = RAND_MAX;
  109. b += 1;
  110. r /= b;
  111. return r;
  112. }
  113. static struct volume_fd *open_volume(struct volume_info *vol)
  114. {
  115. struct volume_fd *s;
  116. struct open_volume_fd *ofd;
  117. int fd;
  118. if (vol->fds) {
  119. /* If already open dup it */
  120. fd = dup(vol->fds->fd);
  121. if (fd == -1)
  122. error_exit("Failed to dup volume device file des");
  123. } else {
  124. fd = open(vol->device_file_name, O_RDWR | O_LARGEFILE);
  125. if (fd == -1)
  126. error_exit("Failed to open volume device file");
  127. }
  128. s = allocate(sizeof(*s));
  129. s->fd = fd;
  130. s->volume = vol;
  131. s->next = vol->fds;
  132. vol->fds = s;
  133. /* Add to open volumes list */
  134. ofd = allocate(sizeof(*ofd));
  135. ofd->vol_fd = s;
  136. ofd->next = open_volumes;
  137. open_volumes = ofd;
  138. open_volume_count += 1;
  139. return 0;
  140. }
  141. static void close_volume(struct volume_fd *vol_fd)
  142. {
  143. struct volume_fd *vfd, *vfd_last;
  144. struct open_volume_fd *ofd, *ofd_last;
  145. int fd = vol_fd->fd;
  146. /* Remove from open volumes list */
  147. ofd_last = NULL;
  148. ofd = open_volumes;
  149. while (ofd) {
  150. if (ofd->vol_fd == vol_fd) {
  151. if (ofd_last)
  152. ofd_last->next = ofd->next;
  153. else
  154. open_volumes = ofd->next;
  155. free(ofd);
  156. open_volume_count -= 1;
  157. break;
  158. }
  159. ofd_last = ofd;
  160. ofd = ofd->next;
  161. }
  162. /* Remove from volume fd list */
  163. vfd_last = NULL;
  164. vfd = vol_fd->volume->fds;
  165. while (vfd) {
  166. if (vfd == vol_fd) {
  167. if (vfd_last)
  168. vfd_last->next = vfd->next;
  169. else
  170. vol_fd->volume->fds = vfd->next;
  171. free(vfd);
  172. break;
  173. }
  174. vfd_last = vfd;
  175. vfd = vfd->next;
  176. }
  177. /* Close volume device file */
  178. if (close(fd) == -1)
  179. error_exit("Failed to close volume file descriptor");
  180. }
  181. static void set_random_data(unsigned seed, unsigned char *buf, int size)
  182. {
  183. int i;
  184. unsigned r;
  185. r = rand();
  186. srand(seed);
  187. for (i = 0; i < size; ++i)
  188. buf[i] = rand();
  189. srand(r);
  190. }
  191. static void check_erase_block(struct erase_block_info *erase_block, int fd)
  192. {
  193. struct write_info *w;
  194. off_t gap_end;
  195. int leb_size = erase_block->volume->info.leb_size;
  196. ssize_t bytes_read;
  197. w = erase_block->writes;
  198. gap_end = erase_block->offset + leb_size;
  199. while (w) {
  200. if (w->offset + w->size < gap_end) {
  201. /* There is a gap. Check all 0xff */
  202. off_t gap_start = w->offset + w->size;
  203. ssize_t size = gap_end - gap_start;
  204. if (lseek(fd, gap_start, SEEK_SET) != gap_start)
  205. error_exit("lseek failed");
  206. memset(read_buffer, 0 , size);
  207. errno = 0;
  208. bytes_read = read(fd, read_buffer, size);
  209. if (bytes_read != size)
  210. error_exit("read failed in gap");
  211. while (size)
  212. if (read_buffer[--size] != 0xff) {
  213. fprintf(stderr, "block no. = %d\n" , erase_block->block_number);
  214. fprintf(stderr, "offset = %lld\n" , (long long)gap_start);
  215. fprintf(stderr, "size = %ld\n" , (long) bytes_read);
  216. error_exit("verify 0xff failed");
  217. }
  218. }
  219. if (lseek(fd, w->offset, SEEK_SET) != w->offset)
  220. error_exit("lseek failed");
  221. memset(read_buffer, 0 , w->size);
  222. errno = 0;
  223. bytes_read = read(fd, read_buffer, w->size);
  224. if (bytes_read != w->size) {
  225. fprintf(stderr, "offset = %lld\n" , (long long)w->offset);
  226. fprintf(stderr, "size = %ld\n" , (long) w->size);
  227. fprintf(stderr, "bytes_read = %ld\n" , (long) bytes_read);
  228. error_exit("read failed");
  229. }
  230. set_random_data(w->random_seed, write_buffer, w->size);
  231. if (memcmp(read_buffer, write_buffer, w->size))
  232. error_exit("verify failed");
  233. gap_end = w->offset;
  234. w = w->next;
  235. }
  236. if (gap_end > erase_block->offset) {
  237. /* Check all 0xff */
  238. off_t gap_start = erase_block->offset;
  239. ssize_t size = gap_end - gap_start;
  240. if (lseek(fd, gap_start, SEEK_SET) != gap_start)
  241. error_exit("lseek failed");
  242. memset(read_buffer, 0 , size);
  243. errno = 0;
  244. bytes_read = read(fd, read_buffer, size);
  245. if (bytes_read != size)
  246. error_exit("read failed in gap");
  247. while (size)
  248. if (read_buffer[--size] != 0xff) {
  249. fprintf(stderr, "block no. = %d\n" , erase_block->block_number);
  250. fprintf(stderr, "offset = %lld\n" , (long long)gap_start);
  251. fprintf(stderr, "size = %ld\n" , (long) bytes_read);
  252. error_exit("verify 0xff failed!");
  253. }
  254. }
  255. }
  256. static int write_to_erase_block(struct erase_block_info *erase_block, int fd)
  257. {
  258. int page_size = erase_block->volume->ubi_device->info.min_io_size;
  259. int leb_size = erase_block->volume->info.leb_size;
  260. int next_offset = 0;
  261. int space, size;
  262. off_t offset;
  263. unsigned seed;
  264. struct write_info *w;
  265. if (erase_block->writes)
  266. next_offset = erase_block->writes->offset_within_block + erase_block->writes->size;
  267. space = leb_size - next_offset;
  268. if (space <= 0)
  269. return 0; /* No space */
  270. if (!get_random_number(10)) {
  271. /* 1 time in 10 leave a gap */
  272. next_offset += get_random_number(space);
  273. next_offset = (next_offset / page_size) * page_size;
  274. space = leb_size - next_offset;
  275. }
  276. if (get_random_number(2))
  277. size = 1 * page_size;
  278. else if (get_random_number(2))
  279. size = 2 * page_size;
  280. else if (get_random_number(2))
  281. size = 3 * page_size;
  282. else if (get_random_number(2))
  283. size = 4 * page_size;
  284. else {
  285. if (get_random_number(4))
  286. size = get_random_number(space);
  287. else
  288. size = space;
  289. size = (size / page_size) * page_size;
  290. }
  291. if (size == 0 || size > space)
  292. size = page_size;
  293. if (next_offset + size > leb_size)
  294. error_exit("internal error");
  295. offset = erase_block->offset + next_offset;
  296. if (offset < erase_block->top_of_data)
  297. error_exit("internal error!");
  298. if (lseek(fd, offset, SEEK_SET) != offset)
  299. error_exit("lseek failed");
  300. /* Do write */
  301. seed = get_next_seed();
  302. if (!seed)
  303. seed = 1;
  304. set_random_data(seed, write_buffer, size);
  305. if (write(fd, write_buffer, size) != size)
  306. error_exit("write failed");
  307. erase_block->top_of_data = offset + size;
  308. /* Make write info and add to eb */
  309. w = allocate(sizeof(*w));
  310. w->offset_within_block = next_offset;
  311. w->offset = offset;
  312. w->size = size;
  313. w->random_seed = seed;
  314. w->next = erase_block->writes;
  315. erase_block->writes = w;
  316. erase_block->touched = 1;
  317. erase_block->erased = 0;
  318. total_written += size;
  319. return 1;
  320. }
  321. static void erase_erase_block(struct erase_block_info *erase_block, int fd)
  322. {
  323. struct write_info *w;
  324. uint32_t eb_no;
  325. int res;
  326. eb_no = erase_block->block_number;
  327. res = ioctl(fd, UBI_IOCEBER, &eb_no);
  328. if (res)
  329. error_exit("Failed to erase an erase block");
  330. /* Remove writes from this eb */
  331. while (erase_block->writes) {
  332. w = erase_block->writes;
  333. erase_block->writes = erase_block->writes->next;
  334. free(w);
  335. }
  336. erase_block->erased = 1;
  337. erase_block->touched = 1;
  338. erase_block->top_of_data = erase_block->offset;
  339. }
  340. static void operate_on_erase_block(struct erase_block_info *erase_block, int fd)
  341. {
  342. /*
  343. Possible operations:
  344. read from it and verify
  345. write to it
  346. erase it
  347. */
  348. int work_done = 1;
  349. static int no_work_done_count = 0;
  350. if (!get_random_number(10) && no_work_done_count <= 5) {
  351. check_erase_block(erase_block, fd);
  352. work_done = 0;
  353. } else if (get_random_number(100)) {
  354. if (!write_to_erase_block(erase_block, fd)) {
  355. /* The erase block was full */
  356. if (get_random_number(2) || no_work_done_count > 5)
  357. erase_erase_block(erase_block, fd);
  358. else
  359. work_done = 0;
  360. }
  361. } else
  362. erase_erase_block(erase_block, fd);
  363. if (work_done)
  364. no_work_done_count = 0;
  365. else
  366. no_work_done_count += 1;
  367. }
  368. static void operate_on_open_volume(struct volume_fd *vol_fd)
  369. {
  370. /*
  371. Possible operations:
  372. operate on an erase block
  373. close volume
  374. */
  375. if (get_random_number(100) == 0)
  376. close_volume(vol_fd);
  377. else {
  378. /* Pick an erase block at random */
  379. int eb_no = get_random_number(vol_fd->volume->info.rsvd_lebs);
  380. operate_on_erase_block(&vol_fd->volume->erase_blocks[eb_no], vol_fd->fd);
  381. }
  382. }
  383. static void operate_on_volume(struct volume_info *vol)
  384. {
  385. /*
  386. Possible operations:
  387. open it
  388. resize it (must close fd's first) <- TODO
  389. delete it (must close fd's first) <- TODO
  390. */
  391. open_volume(vol);
  392. }
  393. static int ubi_major(const char *device_file_name)
  394. {
  395. struct stat buf;
  396. static int maj = 0;
  397. if (maj)
  398. return maj;
  399. if (stat(device_file_name, &buf) == -1)
  400. error_exit("Failed to stat ubi device file");
  401. maj = major(buf.st_rdev);
  402. return maj;
  403. }
  404. static void operate_on_ubi_device(struct ubi_device_info *ubi_device)
  405. {
  406. /*
  407. TODO:
  408. Possible operations:
  409. create a new volume
  410. operate on existing volume
  411. */
  412. /*
  413. Simplified operation (i.e. only have 1 volume):
  414. If there are no volumes create 1 volumne
  415. Then operate on the volume
  416. */
  417. if (ubi_device->info.vol_count == 0) {
  418. /* Create the one-and-only volume we will use */
  419. char dev_name[1024];
  420. int i, n, maj, fd;
  421. struct volume_info *s;
  422. struct ubi_mkvol_request req;
  423. req.vol_id = UBI_VOL_NUM_AUTO;
  424. req.alignment = 1; /* TODO: What is this? */
  425. req.bytes = ubi_device->info.leb_size * max_ebs_per_vol;
  426. req.flags = 0;
  427. if (req.bytes == 0 || req.bytes > ubi_device->info.avail_bytes)
  428. req.bytes = ubi_device->info.avail_bytes;
  429. req.vol_type = UBI_DYNAMIC_VOLUME;
  430. req.name = "integ-test-vol";
  431. if (ubi_mkvol(libubi, ubi_device->device_file_name, &req))
  432. error_exit("ubi_mkvol failed");
  433. s = allocate(sizeof(*s));
  434. s->ubi_device = ubi_device;
  435. if (ubi_get_vol_info1(libubi, ubi_device->info.dev_num, req.vol_id, &s->info))
  436. error_exit("ubi_get_vol_info failed");
  437. n = s->info.rsvd_lebs;
  438. s->erase_blocks = allocate(sizeof(struct erase_block_info) * n);
  439. for (i = 0; i < n; ++i) {
  440. s->erase_blocks[i].volume = s;
  441. s->erase_blocks[i].block_number = i;
  442. s->erase_blocks[i].offset = i * (off_t) s->info.leb_size;
  443. s->erase_blocks[i].top_of_data = s->erase_blocks[i].offset;
  444. }
  445. /* FIXME: Correctly get device file name */
  446. sprintf(dev_name, "%s_%d", ubi_device->device_file_name, req.vol_id);
  447. s->device_file_name = strdup(dev_name);
  448. ubi_device->volumes = s;
  449. ubi_device->info.vol_count += 1;
  450. sleep(1);
  451. fd = open(s->device_file_name, O_RDONLY);
  452. if (fd == -1) {
  453. /* FIXME: Correctly make node */
  454. maj = ubi_major(ubi_device->device_file_name);
  455. sprintf(dev_name, "mknod %s c %d %d", s->device_file_name, maj, req.vol_id + 1);
  456. if (system(dev_name))
  457. error_exit("Failed to create device file");
  458. } else if (close(fd) == -1)
  459. error_exit("Failed to close volume device file");
  460. }
  461. operate_on_volume(ubi_device->volumes);
  462. }
  463. static void do_an_operation(void)
  464. {
  465. int too_few = (open_volume_count < info.dev_count * 3);
  466. int too_many = (open_volume_count > info.dev_count * 5);
  467. if (too_many || (!too_few && get_random_number(1000) > 0)) {
  468. /* Operate on an open volume */
  469. size_t pos;
  470. struct open_volume_fd *ofd;
  471. pos = get_random_number(open_volume_count);
  472. for (ofd = open_volumes; pos && ofd && ofd->next; --pos)
  473. ofd = ofd->next;
  474. operate_on_open_volume(ofd->vol_fd);
  475. } else if (info.dev_count > 0) {
  476. /* Operate on a ubi device */
  477. size_t ubi_pos = 0;
  478. if (info.dev_count > 1)
  479. ubi_pos = get_random_number(info.dev_count - 1);
  480. operate_on_ubi_device(&ubi_array[ubi_pos]);
  481. } else
  482. error_exit("Internal error");
  483. }
  484. static void get_ubi_devices_info(void)
  485. {
  486. int i, ubi_pos = 0;
  487. char dev_name[1024];
  488. ssize_t buf_size = 1024 * 128;
  489. if (ubi_get_info(libubi, &info))
  490. error_exit("ubi_get_info failed");
  491. if (info.dev_count > MAX_UBI_DEVICES)
  492. error_exit("Too many ubi devices");
  493. for (i = info.lowest_dev_num; i <= info.highest_dev_num; ++i) {
  494. struct ubi_device_info *s;
  495. s = &ubi_array[ubi_pos++];
  496. if (ubi_get_dev_info1(libubi, i, &s->info))
  497. error_exit("ubi_get_dev_info1 failed");
  498. if (s->info.vol_count)
  499. error_exit("There are existing volumes");
  500. /* FIXME: Correctly get device file name */
  501. sprintf(dev_name, "/dev/ubi%d", i);
  502. s->device_file_name = strdup(dev_name);
  503. if (buf_size < s->info.leb_size)
  504. buf_size = s->info.leb_size;
  505. if (max_ebs_per_vol && s->info.leb_size * max_ebs_per_vol < s->info.avail_bytes)
  506. total_space += s->info.leb_size * max_ebs_per_vol;
  507. else
  508. total_space += s->info.avail_bytes;
  509. }
  510. write_buffer = allocate(buf_size);
  511. read_buffer = allocate(buf_size);
  512. }
  513. static void load_ubi(void)
  514. {
  515. if (system("modprobe -r ubi"))
  516. error_exit("Failed to unload UBI module");
  517. if (system(ubi_module_load_string) != 0)
  518. error_exit("Failed to load UBI module");
  519. sleep(1);
  520. }
  521. static void do_some_operations(void)
  522. {
  523. unsigned i = 0;
  524. total_written = 0;
  525. printf("Total space: %llu\n", (unsigned long long) total_space);
  526. while (total_written < total_space * 3) {
  527. do_an_operation();
  528. if (i++ % 10000 == 0)
  529. printf("Total written: %llu\n", (unsigned long long) total_written);
  530. }
  531. printf("Total written: %llu\n", (unsigned long long) total_written);
  532. }
  533. static void reload_ubi(void)
  534. {
  535. /* Remove module */
  536. if (system("rmmod ubi") != 0)
  537. error_exit("Failed to remove UBI module");
  538. /* Install module */
  539. if (system(ubi_module_load_string) != 0)
  540. error_exit("Failed to load UBI module");
  541. sleep(1);
  542. }
  543. static void integ_check_volume(struct volume_info *vol)
  544. {
  545. struct erase_block_info *eb = vol->erase_blocks;
  546. int pos;
  547. int fd;
  548. fd = open(vol->device_file_name, O_RDWR | O_LARGEFILE);
  549. if (fd == -1)
  550. error_exit("Failed to open volume device file");
  551. for (pos = 0; pos < vol->info.rsvd_lebs; ++pos)
  552. check_erase_block(eb++, fd);
  553. if (close(fd) == -1)
  554. error_exit("Failed to close volume device file");
  555. }
  556. static void check_ubi_device(struct ubi_device_info *ubi_device)
  557. {
  558. struct volume_info *vol;
  559. vol = ubi_device->volumes;
  560. while (vol) {
  561. integ_check_volume(vol);
  562. vol = vol->next;
  563. }
  564. }
  565. static void check_ubi(void)
  566. {
  567. int i;
  568. for (i = 0; i < info.dev_count; ++i)
  569. check_ubi_device(&ubi_array[i]);
  570. }
  571. static int is_all_digits(const char *s)
  572. {
  573. const char *digits = "0123456789";
  574. if (!s || !*s)
  575. return 0;
  576. for (;*s;++s)
  577. if (!strchr(digits,*s))
  578. return 0;
  579. return 1;
  580. }
  581. static int get_short_arg(int *pos,const char *name,long long *result,int argc,char *argv[])
  582. {
  583. const char *p = NULL;
  584. int i = *pos;
  585. size_t n = strlen(name);
  586. if (strlen(argv[i]) > n)
  587. p = argv[i] + n;
  588. else if (++i < argc)
  589. p = argv[i];
  590. if (!is_all_digits(p))
  591. return 1;
  592. *result = atoll(p);
  593. *pos = i;
  594. return 0;
  595. }
  596. static int get_long_arg(int *pos,const char *name,long long *result,int argc,char *argv[])
  597. {
  598. const char *p = NULL;
  599. int i = *pos;
  600. size_t n = strlen(name);
  601. if (strlen(argv[i]) > n)
  602. p = argv[i] + n;
  603. else if (++i < argc)
  604. p = argv[i];
  605. if (p && *p == '=') {
  606. p += 1;
  607. if (!*p && ++i < argc)
  608. p = argv[i];
  609. }
  610. if (!is_all_digits(p))
  611. return 1;
  612. *result = atoll(p);
  613. *pos = i;
  614. return 0;
  615. }
  616. static int remove_all_volumes(void)
  617. {
  618. int i;
  619. for (i = 0; i < info.dev_count; ++i) {
  620. struct ubi_device_info *ubi_device = &ubi_array[i];
  621. struct volume_info *vol;
  622. vol = ubi_device->volumes;
  623. while (vol) {
  624. int res = ubi_rmvol(libubi,
  625. ubi_device->device_file_name,
  626. vol->info.vol_id);
  627. if (res)
  628. return res;
  629. vol = vol->next;
  630. }
  631. }
  632. return 0;
  633. }
  634. int main(int argc,char *argv[])
  635. {
  636. int i;
  637. long long r, repeat = 1;
  638. int initial_seed = 1, args_ok = 1;
  639. printf("UBI Integrity Test\n");
  640. /* Get arguments */
  641. ubi_module_load_string = 0;
  642. for (i = 1; i < argc; ++i) {
  643. if (strncmp(argv[i], "-h", 2) == 0)
  644. args_ok = 0;
  645. else if (strncmp(argv[i], "--help", 6) == 0)
  646. args_ok = 0;
  647. else if (strncmp(argv[i], "-n", 2) == 0) {
  648. if (get_short_arg(&i, "-n", &repeat, argc, argv))
  649. args_ok = 0;
  650. } else if (strncmp(argv[i], "--repeat", 8) == 0) {
  651. if (get_long_arg(&i, "--repeat", &repeat, argc, argv))
  652. args_ok = 0;
  653. } else if (strncmp(argv[i], "-m", 2) == 0) {
  654. if (get_short_arg(&i,"-m", &max_ebs_per_vol, argc, argv))
  655. args_ok = 0;
  656. } else if (strncmp(argv[i], "--maxebs", 8) == 0) {
  657. if (get_long_arg(&i, "--maxebs", &max_ebs_per_vol, argc, argv))
  658. args_ok = 0;
  659. } else if (!ubi_module_load_string)
  660. ubi_module_load_string = argv[i];
  661. else
  662. args_ok = 0;
  663. }
  664. if (!args_ok || !ubi_module_load_string) {
  665. fprintf(stderr, "Usage is: ubi_integ [<options>] <UBI Module load command>\n");
  666. fprintf(stderr, " Options: \n");
  667. fprintf(stderr, " -h, --help Help\n");
  668. fprintf(stderr, " -n arg, --repeat=arg Repeat test arg times\n");
  669. fprintf(stderr, " -m arg, --maxebs=arg Max no. of erase blocks\n");
  670. return 1;
  671. }
  672. next_seed = initial_seed = seed_random_generator();
  673. printf("Initial seed = %u\n", (unsigned) initial_seed);
  674. load_ubi();
  675. libubi = libubi_open();
  676. if (!libubi)
  677. error_exit("Failed to open libubi");
  678. get_ubi_devices_info();
  679. r = 0;
  680. while (repeat == 0 || r++ < repeat) {
  681. printf("Cycle %lld\n", r);
  682. do_some_operations();
  683. /* Close all volumes */
  684. while (open_volumes)
  685. close_volume(open_volumes->vol_fd);
  686. check_ubi();
  687. libubi_close(libubi);
  688. reload_ubi();
  689. libubi = libubi_open();
  690. if (!libubi)
  691. error_exit("Failed to open libubi");
  692. check_ubi();
  693. }
  694. if (remove_all_volumes())
  695. error_exit("Failed to remove all volumes");
  696. libubi_close(libubi);
  697. printf("UBI Integrity Test completed ok\n");
  698. return 0;
  699. }