io_read.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  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 read.
  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. #define PROGRAM_NAME "io_basic"
  32. #include "common.h"
  33. #include "helpers.h"
  34. static libubi_t libubi;
  35. static struct ubi_dev_info dev_info;
  36. const char *node;
  37. static int fd;
  38. /* Data lengthes to test, @io - minimal I/O unit size, @s - eraseblock size */
  39. #define LENGTHES(io, s) \
  40. {1, (io), (io)+1, 2*(io), 3*(io)-1, 3*(io), \
  41. MAX_NAND_PAGE_SIZE-1, MAX_NAND_PAGE_SIZE-(io), 2*MAX_NAND_PAGE_SIZE, 2*MAX_NAND_PAGE_SIZE-(io), \
  42. (s)/2-1, (s)/2, (s)/2+1, (s)-1, (s), (s)+1, 2*(s)-(io), 2*(s), \
  43. 2*(s)+(io), 3*(s), 3*(s)+(io)};
  44. /*
  45. * Offsets to test, @io - minimal I/O unit size, @s - eraseblock size, @sz -
  46. * volume size.
  47. */
  48. #define OFFSETS(io, s, sz) \
  49. {0, (io)-1, (io), (io)+1, 2*(io)-1, 2*(io), 3*(io)-1, 3*(io), \
  50. MAX_NAND_PAGE_SIZE-1, MAX_NAND_PAGE_SIZE-(io), 2*MAX_NAND_PAGE_SIZE, 2*MAX_NAND_PAGE_SIZE-(io), \
  51. (s)/2-1, (s)/2, (s)/2+1, (s)-1, (s), (s)+1, 2*(s)-(io), 2*(s), \
  52. 2*(s)+(io), 3*(s), (sz)-(s)-1, (sz)-(io)-1, (sz)-MAX_NAND_PAGE_SIZE-1};
  53. /**
  54. * test_static - test static volume-specific features.
  55. *
  56. * Thus function returns %0 in case of success and %-1 in case of failure.
  57. */
  58. static int test_static(void)
  59. {
  60. struct ubi_mkvol_request req;
  61. const char *name = PROGRAM_NAME ":io_basic()";
  62. char vol_node[strlen(UBI_VOLUME_PATTERN) + 100];
  63. struct ubi_vol_info vol_info;
  64. int fd, ret;
  65. char buf[20];
  66. req.vol_id = UBI_VOL_NUM_AUTO;
  67. req.alignment = 1;
  68. req.bytes = dev_info.avail_bytes;
  69. req.vol_type = UBI_STATIC_VOLUME;
  70. req.name = name;
  71. req.flags = 0;
  72. if (ubi_mkvol(libubi, node, &req)) {
  73. failed("ubi_mkvol");
  74. return -1;
  75. }
  76. sprintf(vol_node, UBI_VOLUME_PATTERN, dev_info.dev_num, req.vol_id);
  77. fd = open(vol_node, O_RDWR);
  78. if (fd == -1) {
  79. failed("open");
  80. errorm("cannot open \"%s\"\n", node);
  81. goto remove;
  82. }
  83. if (ubi_get_vol_info(libubi, vol_node, &vol_info)) {
  84. failed("ubi_get_vol_info");
  85. goto close;
  86. }
  87. /* Make sure new static volume contains no data */
  88. if (vol_info.data_bytes != 0) {
  89. errorm("data_bytes = %lld, not zero", vol_info.data_bytes);
  90. goto close;
  91. }
  92. /* Ensure read returns EOF */
  93. ret = read(fd, buf, 1);
  94. if (ret < 0) {
  95. failed("read");
  96. goto close;
  97. }
  98. if (ret != 0) {
  99. errorm("read data from free static volume");
  100. goto close;
  101. }
  102. if (ubi_update_start(libubi, fd, 10)) {
  103. failed("ubi_update_start");
  104. goto close;
  105. }
  106. ret = write(fd, buf, 10);
  107. if (ret < 0) {
  108. failed("write");
  109. goto close;
  110. }
  111. if (ret != 10) {
  112. errorm("written %d bytes", ret);
  113. goto close;
  114. }
  115. if (lseek(fd, 0, SEEK_SET) != 0) {
  116. failed("seek");
  117. goto close;
  118. }
  119. ret = read(fd, buf, 20);
  120. if (ret < 0) {
  121. failed("read");
  122. goto close;
  123. }
  124. if (ret != 10) {
  125. errorm("read %d bytes", ret);
  126. goto close;
  127. }
  128. close(fd);
  129. if (ubi_rmvol(libubi, node, req.vol_id)) {
  130. failed("ubi_rmvol");
  131. return -1;
  132. }
  133. return 0;
  134. close:
  135. close(fd);
  136. remove:
  137. ubi_rmvol(libubi, node, req.vol_id);
  138. return -1;
  139. }
  140. /*
  141. * A helper function for test_read2().
  142. */
  143. static int test_read3(const struct ubi_vol_info *vol_info, int len, off_t off)
  144. {
  145. int i, len1;
  146. unsigned char *ck_buf = NULL;
  147. unsigned char *buf = NULL;
  148. off_t new_off;
  149. int ret = -1;
  150. ck_buf = malloc(len);
  151. buf = malloc(len);
  152. if (!ck_buf || !buf) {
  153. failed("malloc");
  154. goto out;
  155. }
  156. if (off + len > vol_info->data_bytes)
  157. len1 = vol_info->data_bytes - off;
  158. else
  159. len1 = len;
  160. if (lseek(fd, off, SEEK_SET) != off) {
  161. failed("seek");
  162. errorm("len = %d", len);
  163. goto out;
  164. }
  165. if (read(fd, buf, len) != len1) {
  166. failed("read");
  167. errorm("len = %d", len);
  168. goto out;
  169. }
  170. new_off = lseek(fd, 0, SEEK_CUR);
  171. if (new_off != off + len1) {
  172. if (new_off == -1)
  173. failed("lseek");
  174. else
  175. errorm("read %d bytes from %lld, but resulting "
  176. "offset is %lld", len1, (long long) off, (long long) new_off);
  177. goto out;
  178. }
  179. for (i = 0; i < len1; i++)
  180. ck_buf[i] = (unsigned char)(off + i);
  181. if (memcmp(buf, ck_buf, len1)) {
  182. errorm("incorrect data read from offset %lld",
  183. (long long)off);
  184. errorm("len = %d", len);
  185. goto out;
  186. }
  187. ret = 0;
  188. out:
  189. free(buf);
  190. free(ck_buf);
  191. return ret;
  192. }
  193. /*
  194. * A helper function for test_read1().
  195. */
  196. static int test_read2(const struct ubi_vol_info *vol_info, int len)
  197. {
  198. int i;
  199. off_t offsets[] = OFFSETS(dev_info.min_io_size, vol_info->leb_size,
  200. vol_info->data_bytes);
  201. for (i = 0; i < sizeof(offsets)/sizeof(off_t); i++) {
  202. /* Filter invalid offset value */
  203. if (offsets[i] < 0 || offsets[i] > vol_info->data_bytes)
  204. continue;
  205. if (test_read3(vol_info, len, offsets[i])) {
  206. errorm("offset = %ld", offsets[i]);
  207. return -1;
  208. }
  209. }
  210. return 0;
  211. }
  212. /*
  213. * A helper function for test_read().
  214. */
  215. static int test_read1(struct ubi_vol_info *vol_info)
  216. {
  217. int i, written = 0;
  218. char vol_node[strlen(UBI_VOLUME_PATTERN) + 100];
  219. int lengthes[] = LENGTHES(dev_info.min_io_size, vol_info->leb_size);
  220. sprintf(vol_node, UBI_VOLUME_PATTERN, dev_info.dev_num,
  221. vol_info->vol_id);
  222. fd = open(vol_node, O_RDWR);
  223. if (fd == -1) {
  224. failed("open");
  225. errorm("cannot open \"%s\"\n", node);
  226. return -1;
  227. }
  228. /* Write some pattern to the volume */
  229. if (ubi_update_start(libubi, fd, vol_info->rsvd_bytes)) {
  230. failed("ubi_update_start");
  231. errorm("bytes = %lld", vol_info->rsvd_bytes);
  232. goto close;
  233. }
  234. while (written < vol_info->rsvd_bytes) {
  235. int i, ret;
  236. unsigned char buf[512];
  237. for (i = 0; i < 512; i++)
  238. buf[i] = (unsigned char)(written + i);
  239. ret = write(fd, buf, 512);
  240. if (ret == -1) {
  241. failed("write");
  242. errorm("written = %d, ret = %d", written, ret);
  243. goto close;
  244. }
  245. written += ret;
  246. }
  247. close(fd);
  248. if (ubi_get_vol_info(libubi, vol_node, vol_info)) {
  249. failed("ubi_get_vol_info");
  250. return -1;
  251. }
  252. fd = open(vol_node, O_RDONLY);
  253. if (fd == -1) {
  254. failed("open");
  255. errorm("cannot open \"%s\"\n", node);
  256. return -1;
  257. }
  258. for (i = 0; i < sizeof(lengthes)/sizeof(int); i++) {
  259. if (test_read2(vol_info, lengthes[i])) {
  260. errorm("length = %d", lengthes[i]);
  261. goto close;
  262. }
  263. }
  264. close(fd);
  265. return 0;
  266. close:
  267. close(fd);
  268. return -1;
  269. }
  270. /**
  271. * test_read - test UBI volume reading from different offsets.
  272. *
  273. * @type volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME)
  274. *
  275. * Thus function returns %0 in case of success and %-1 in case of failure.
  276. */
  277. static int test_read(int type)
  278. {
  279. const char *name = PROGRAM_NAME ":test_read()";
  280. int alignments[] = ALIGNMENTS(dev_info.leb_size);
  281. char vol_node[strlen(UBI_VOLUME_PATTERN) + 100];
  282. struct ubi_mkvol_request req;
  283. int i;
  284. for (i = 0; i < sizeof(alignments)/sizeof(int); i++) {
  285. int leb_size;
  286. struct ubi_vol_info vol_info;
  287. req.vol_id = UBI_VOL_NUM_AUTO;
  288. req.vol_type = type;
  289. req.name = name;
  290. req.flags = 0;
  291. req.alignment = alignments[i];
  292. req.alignment -= req.alignment % dev_info.min_io_size;
  293. if (req.alignment == 0)
  294. req.alignment = dev_info.min_io_size;
  295. leb_size = dev_info.leb_size - dev_info.leb_size % req.alignment;
  296. req.bytes = MIN_AVAIL_EBS * leb_size;
  297. if (ubi_mkvol(libubi, node, &req)) {
  298. failed("ubi_mkvol");
  299. return -1;
  300. }
  301. sprintf(vol_node, UBI_VOLUME_PATTERN, dev_info.dev_num,
  302. req.vol_id);
  303. if (ubi_get_vol_info(libubi, vol_node, &vol_info)) {
  304. failed("ubi_get_vol_info");
  305. goto remove;
  306. }
  307. if (test_read1(&vol_info)) {
  308. errorm("alignment = %d", req.alignment);
  309. goto remove;
  310. }
  311. if (ubi_rmvol(libubi, node, req.vol_id)) {
  312. failed("ubi_rmvol");
  313. return -1;
  314. }
  315. }
  316. return 0;
  317. remove:
  318. ubi_rmvol(libubi, node, req.vol_id);
  319. return -1;
  320. }
  321. int main(int argc, char * const argv[])
  322. {
  323. if (initial_check(argc, argv))
  324. return 1;
  325. node = argv[1];
  326. libubi = libubi_open();
  327. if (libubi == NULL) {
  328. failed("libubi_open");
  329. return 1;
  330. }
  331. if (ubi_get_dev_info(libubi, node, &dev_info)) {
  332. failed("ubi_get_dev_info");
  333. goto close;
  334. }
  335. if (test_static())
  336. goto close;
  337. if (test_read(UBI_DYNAMIC_VOLUME))
  338. goto close;
  339. if (test_read(UBI_STATIC_VOLUME))
  340. goto close;
  341. libubi_close(libubi);
  342. return 0;
  343. close:
  344. libubi_close(libubi);
  345. return 1;
  346. }