io_update.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. /*
  2. * Copyright (c) International Business Machines Corp., 2006
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
  12. * the GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. *
  18. * Author: Artem B. Bityutskiy
  19. *
  20. * Test UBI volume update and atomic LEB change
  21. */
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <errno.h>
  25. #include <string.h>
  26. #include <unistd.h>
  27. #include <sys/types.h>
  28. #include <sys/stat.h>
  29. #include <fcntl.h>
  30. #include <libubi.h>
  31. #include <mtd/ubi-user.h>
  32. #define PROGRAM_NAME "io_update"
  33. #include "common.h"
  34. #include "helpers.h"
  35. static libubi_t libubi;
  36. static struct ubi_dev_info dev_info;
  37. const char *node;
  38. #define SEQUENCES(io, s) { \
  39. {3*(s)-(io)-1, 1}, \
  40. {512}, \
  41. {666}, \
  42. {2048}, \
  43. {(io), (io), MAX_NAND_PAGE_SIZE}, \
  44. {(io)+1, (io)+1, MAX_NAND_PAGE_SIZE}, \
  45. {MAX_NAND_PAGE_SIZE}, \
  46. {MAX_NAND_PAGE_SIZE-1}, \
  47. {MAX_NAND_PAGE_SIZE+(io)}, \
  48. {(s)}, \
  49. {(s)-1}, \
  50. {(s)+1}, \
  51. {(io), (s)+1}, \
  52. {(s)+(io), MAX_NAND_PAGE_SIZE}, \
  53. {2*(s), MAX_NAND_PAGE_SIZE}, \
  54. {MAX_NAND_PAGE_SIZE, 2*(s), 1}, \
  55. {MAX_NAND_PAGE_SIZE, 2*(s)}, \
  56. {2*(s)-1, 2*(s)-1}, \
  57. {3*(s), MAX_NAND_PAGE_SIZE + 1}, \
  58. {1, MAX_NAND_PAGE_SIZE}, \
  59. {(io), (s)} \
  60. }
  61. #define SEQ_SZ 21
  62. /*
  63. * test_update1 - helper function for test_update().
  64. */
  65. static int test_update1(struct ubi_vol_info *vol_info, int leb_change)
  66. {
  67. long long total_len = leb_change ? vol_info->leb_size
  68. : vol_info->rsvd_bytes;
  69. int sequences[SEQ_SZ][3] = SEQUENCES(dev_info.min_io_size,
  70. leb_change ? dev_info.min_io_size * 2
  71. : vol_info->leb_size);
  72. char vol_node[strlen(UBI_VOLUME_PATTERN) + 100];
  73. unsigned char *buf = NULL;
  74. unsigned char *buf1 = NULL;
  75. int fd, i, j;
  76. int ret1 = -1;
  77. buf = malloc(total_len);
  78. if (!buf) {
  79. failed("malloc");
  80. goto out;
  81. }
  82. buf1 = malloc(total_len);
  83. if (!buf1) {
  84. failed("malloc");
  85. goto out;
  86. }
  87. sprintf(vol_node, UBI_VOLUME_PATTERN, dev_info.dev_num,
  88. vol_info->vol_id);
  89. fd = open(vol_node, O_RDWR);
  90. if (fd == -1) {
  91. failed("open");
  92. errorm("cannot open \"%s\"\n", node);
  93. goto out;
  94. }
  95. for (i = 0; i < SEQ_SZ; i++) {
  96. int ret, stop = 0, len = 0;
  97. off_t off = 0;
  98. long long test_len;
  99. /*
  100. * test_len is LEB size (if we test atomic LEB change) or
  101. * volume size (if we test update). For better test coverage,
  102. * use a little smaller LEB change/update length.
  103. */
  104. test_len = total_len - (rand() % (total_len / 10));
  105. if (leb_change) {
  106. if (ubi_leb_change_start(libubi, fd, 0, test_len)) {
  107. failed("ubi_update_start");
  108. goto close;
  109. }
  110. } else {
  111. if (ubi_update_start(libubi, fd, test_len)) {
  112. failed("ubi_update_start");
  113. goto close;
  114. }
  115. }
  116. for (j = 0; off < test_len; j++) {
  117. int n, rnd_len, l;
  118. if (!stop) {
  119. if (sequences[i][j] != 0)
  120. l = len = sequences[i][j];
  121. else
  122. stop = 1;
  123. }
  124. /*
  125. * Fill some part of the write buffer with random data,
  126. * and the other part with 0xFFs to test how UBI
  127. * stripes 0xFFs multiple of I/O unit size.
  128. */
  129. if (off + l > test_len)
  130. l = test_len - off;
  131. rnd_len = rand() % (l + 1);
  132. for (n = 0; n < rnd_len; n++)
  133. buf[off + n] = (unsigned char)rand();
  134. memset(buf + off + rnd_len, 0xFF, l - rnd_len);
  135. /*
  136. * Deliberately pass len instead of l (len may be
  137. * greater then l if this is the last chunk) because
  138. * UBI have to read only l bytes anyway.
  139. */
  140. ret = write(fd, buf + off, len);
  141. if (ret < 0) {
  142. failed("write");
  143. errorm("failed to write %d bytes at offset "
  144. "%lld", len, (long long)off);
  145. goto close;
  146. }
  147. len = l;
  148. if (ret != len) {
  149. errorm("failed to write %d bytes at offset "
  150. "%lld, wrote %d", len, (long long)off, ret);
  151. goto close;
  152. }
  153. off += len;
  154. }
  155. /* Check data */
  156. if ((ret = lseek(fd, 0, SEEK_SET)) != 0) {
  157. failed("lseek");
  158. errorm("cannot seek to 0");
  159. goto close;
  160. }
  161. memset(buf1, 0x01, test_len);
  162. if (vol_info->type == UBI_STATIC_VOLUME)
  163. /*
  164. * Static volume must not let use read more then it
  165. * contains.
  166. */
  167. ret = read(fd, buf1, test_len + 100);
  168. else
  169. ret = read(fd, buf1, test_len);
  170. if (ret < 0) {
  171. failed("read");
  172. errorm("failed to read %lld bytes", test_len);
  173. goto close;
  174. }
  175. if (ret != test_len) {
  176. errorm("failed to read %lld bytes, read %d", test_len, ret);
  177. goto close;
  178. }
  179. if (memcmp(buf, buf1, test_len)) {
  180. errorm("data corruption");
  181. goto close;
  182. }
  183. }
  184. ret1 = 0;
  185. close:
  186. close(fd);
  187. out:
  188. free(buf);
  189. free(buf1);
  190. return ret1;
  191. }
  192. /**
  193. * test_update - check volume update and atomic LEB change capabilities.
  194. *
  195. * @type volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME)
  196. *
  197. * This function returns %0 in case of success and %-1 in case of failure.
  198. */
  199. static int test_update(int type)
  200. {
  201. struct ubi_mkvol_request req;
  202. const char *name = PROGRAM_NAME ":io_update()";
  203. int alignments[] = ALIGNMENTS(dev_info.leb_size);
  204. struct ubi_vol_info vol_info;
  205. char vol_node[strlen(UBI_VOLUME_PATTERN) + 100];
  206. unsigned int i;
  207. for (i = 0; i < sizeof(alignments)/sizeof(int); i++) {
  208. int leb_size;
  209. req.vol_id = UBI_VOL_NUM_AUTO;
  210. req.vol_type = type;
  211. req.name = name;
  212. req.flags = 0;
  213. req.alignment = alignments[i];
  214. req.alignment -= req.alignment % dev_info.min_io_size;
  215. if (req.alignment == 0)
  216. req.alignment = dev_info.min_io_size;
  217. leb_size = dev_info.leb_size - dev_info.leb_size % req.alignment;
  218. req.bytes = MIN_AVAIL_EBS * leb_size;
  219. if (ubi_mkvol(libubi, node, &req)) {
  220. failed("ubi_mkvol");
  221. return -1;
  222. }
  223. sprintf(vol_node, UBI_VOLUME_PATTERN, dev_info.dev_num,
  224. req.vol_id);
  225. if (ubi_get_vol_info(libubi, vol_node, &vol_info)) {
  226. failed("ubi_get_vol_info");
  227. goto remove;
  228. }
  229. if (test_update1(&vol_info, 0)) {
  230. errorm("alignment = %d", req.alignment);
  231. goto remove;
  232. }
  233. if (vol_info.type != UBI_STATIC_VOLUME) {
  234. if (test_update1(&vol_info, 1)) {
  235. errorm("alignment = %d", req.alignment);
  236. goto remove;
  237. }
  238. }
  239. if (ubi_rmvol(libubi, node, req.vol_id)) {
  240. failed("ubi_rmvol");
  241. return -1;
  242. }
  243. }
  244. return 0;
  245. remove:
  246. ubi_rmvol(libubi, node, req.vol_id);
  247. return -1;
  248. }
  249. int main(int argc, char * const argv[])
  250. {
  251. seed_random_generator();
  252. if (initial_check(argc, argv))
  253. return 1;
  254. node = argv[1];
  255. libubi = libubi_open();
  256. if (libubi == NULL) {
  257. failed("libubi_open");
  258. return 1;
  259. }
  260. if (ubi_get_dev_info(libubi, node, &dev_info)) {
  261. failed("ubi_get_dev_info");
  262. goto close;
  263. }
  264. if (test_update(UBI_DYNAMIC_VOLUME))
  265. goto close;
  266. if (test_update(UBI_STATIC_VOLUME))
  267. goto close;
  268. libubi_close(libubi);
  269. return 0;
  270. close:
  271. libubi_close(libubi);
  272. return 1;
  273. }