summaryrefslogtreecommitdiff
path: root/tests/ubi-tests/integ.c
diff options
context:
space:
mode:
authorArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2007-12-20 17:34:55 +0200
committerArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2007-12-20 17:34:55 +0200
commit1ba6959299cb386faf178317b21ffd61689246b5 (patch)
treeb98d5f6d9aeadeb30e2d614aa174346529ae3b27 /tests/ubi-tests/integ.c
parentb722adcdb1eb8d0321eb5c4112db925c815450fc (diff)
ubi-utils: move UBI tests to tests/ubi-tests/
Clean-up ubi-utils a little by moving tests to a proper place. Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Diffstat (limited to 'tests/ubi-tests/integ.c')
-rw-r--r--tests/ubi-tests/integ.c783
1 files changed, 783 insertions, 0 deletions
diff --git a/tests/ubi-tests/integ.c b/tests/ubi-tests/integ.c
new file mode 100644
index 0000000..4da7121
--- /dev/null
+++ b/tests/ubi-tests/integ.c
@@ -0,0 +1,783 @@
+#define _LARGEFILE64_SOURCE
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+
+#include "libubi.h"
+
+struct erase_block_info;
+struct volume_info;
+struct ubi_device_info;
+
+struct write_info
+{
+ struct write_info *next;
+ struct erase_block_info *erase_block;
+ int offset_within_block; /* Offset within erase block */
+ off64_t offset; /* Offset within volume */
+ int size;
+ int random_seed;
+};
+
+struct erase_block_info
+{
+ struct volume_info *volume;
+ int block_number;
+ off64_t offset; /* Offset within volume */
+ off64_t top_of_data;
+ int touched; /* Have we done anything at all with this erase block */
+ int erased; /* This erased block is currently erased */
+ struct write_info *writes;
+};
+
+struct volume_fd
+{
+ struct volume_fd *next;
+ struct volume_info *volume;
+ int fd;
+};
+
+struct volume_info
+{
+ struct volume_info *next;
+ struct ubi_device_info *ubi_device;
+ struct volume_fd *fds;
+ struct erase_block_info *erase_blocks;
+ const char *device_file_name;
+ struct ubi_vol_info info;
+};
+
+struct ubi_device_info
+{
+ struct volume_info *volumes;
+ const char *device_file_name;
+ struct ubi_dev_info info;
+};
+
+struct open_volume_fd
+{
+ struct open_volume_fd *next;
+ struct volume_fd *vol_fd;
+};
+
+#define MAX_UBI_DEVICES 64
+
+static libubi_t libubi;
+
+static struct ubi_info info;
+static struct ubi_device_info ubi_array[MAX_UBI_DEVICES];
+
+static uint64_t total_written = 0;
+static uint64_t total_space = 0;
+
+static struct open_volume_fd *open_volumes;
+static size_t open_volume_count = 0;
+
+static const char *ubi_module_load_string;
+
+static unsigned char *write_buffer = NULL;
+static unsigned char *read_buffer = NULL;
+
+static long long max_ebs_per_vol = 0; /* max number of ebs per vol (zero => no max) */
+
+static unsigned long next_seed = 1;
+
+static unsigned get_next_seed()
+{
+ next_seed = next_seed * 1103515245 + 12345;
+ return ((unsigned) (next_seed / 65536) % 32768);
+}
+
+static void error_exit(const char *msg)
+{
+ int eno = errno;
+ fprintf(stderr,"UBI Integrity Test Error: %s\n",msg);
+ if (eno) {
+ fprintf(stderr, "errno = %d\n", eno);
+ fprintf(stderr, "strerror = %s\n", strerror(eno));
+ }
+ exit(1);
+}
+
+static void *allocate(size_t n)
+{
+ void *p = malloc(n);
+ if (!p)
+ error_exit("Memory allocation failure");
+ memset(p, 0, n);
+ return p;
+}
+
+static unsigned get_random_number(unsigned n)
+{
+ uint64_t r, b;
+
+ if (n < 1)
+ return 0;
+ r = rand();
+ r *= n;
+ b = RAND_MAX;
+ b += 1;
+ r /= b;
+ return r;
+}
+
+static struct volume_fd *open_volume(struct volume_info *vol)
+{
+ struct volume_fd *s;
+ struct open_volume_fd *ofd;
+ int fd;
+
+ if (vol->fds) {
+ /* If already open dup it */
+ fd = dup(vol->fds->fd);
+ if (fd == -1)
+ error_exit("Failed to dup volume device file des");
+ } else {
+ fd = open(vol->device_file_name, O_RDWR | O_LARGEFILE);
+ if (fd == -1)
+ error_exit("Failed to open volume device file");
+ }
+ s = allocate(sizeof(*s));
+ s->fd = fd;
+ s->volume = vol;
+ s->next = vol->fds;
+ vol->fds = s;
+ /* Add to open volumes list */
+ ofd = allocate(sizeof(*ofd));
+ ofd->vol_fd = s;
+ ofd->next = open_volumes;
+ open_volumes = ofd;
+ open_volume_count += 1;
+ return 0;
+}
+
+static void close_volume(struct volume_fd *vol_fd)
+{
+ struct volume_fd *vfd, *vfd_last;
+ struct open_volume_fd *ofd, *ofd_last;
+ int fd = vol_fd->fd;
+
+ /* Remove from open volumes list */
+ ofd_last = NULL;
+ ofd = open_volumes;
+ while (ofd) {
+ if (ofd->vol_fd == vol_fd) {
+ if (ofd_last)
+ ofd_last->next = ofd->next;
+ else
+ open_volumes = ofd->next;
+ free(ofd);
+ open_volume_count -= 1;
+ break;
+ }
+ ofd_last = ofd;
+ ofd = ofd->next;
+ }
+ /* Remove from volume fd list */
+ vfd_last = NULL;
+ vfd = vol_fd->volume->fds;
+ while (vfd) {
+ if (vfd == vol_fd) {
+ if (vfd_last)
+ vfd_last->next = vfd->next;
+ else
+ vol_fd->volume->fds = vfd->next;
+ free(vfd);
+ break;
+ }
+ vfd_last = vfd;
+ vfd = vfd->next;
+ }
+ /* Close volume device file */
+ if (close(fd) == -1)
+ error_exit("Failed to close volume file descriptor");
+}
+
+static void set_random_data(unsigned seed, unsigned char *buf, int size)
+{
+ int i;
+ unsigned r;
+
+ r = rand();
+ srand(seed);
+ for (i = 0; i < size; ++i)
+ buf[i] = rand();
+ srand(r);
+}
+
+#if 0
+static void print_write_info(struct write_info *w)
+{
+ printf("Offset: %lld Size:%d Seed:%u\n", w->offset, w->size, w->random_seed);
+ fflush(stdout);
+}
+#endif
+
+static void check_erase_block(struct erase_block_info *erase_block, int fd)
+{
+ struct write_info *w;
+ off64_t gap_end;
+ int eb_size = erase_block->volume->info.eb_size;
+ ssize_t bytes_read;
+
+ w = erase_block->writes;
+ gap_end = erase_block->offset + eb_size;
+ while (w) {
+ if (w->offset + w->size < gap_end) {
+ /* There is a gap. Check all 0xff */
+ off64_t gap_start = w->offset + w->size;
+ size_t size = gap_end - gap_start;
+ if (lseek64(fd, gap_start, SEEK_SET) != gap_start)
+ error_exit("lseek64 failed");
+ memset(read_buffer, 0 , size);
+ errno = 0;
+ bytes_read = read(fd, read_buffer, size);
+ if (bytes_read != size)
+ error_exit("read failed in gap");
+ while (size)
+ if (read_buffer[--size] != 0xff) {
+ fprintf(stderr, "block no. = %d\n" , erase_block->block_number);
+ fprintf(stderr, "offset = %lld\n" , (long long) gap_start);
+ fprintf(stderr, "size = %ld\n" , (long) bytes_read);
+ error_exit("verify 0xff failed");
+ }
+ }
+ if (lseek64(fd, w->offset, SEEK_SET) != w->offset)
+ error_exit("lseek64 failed");
+ memset(read_buffer, 0 , w->size);
+ errno = 0;
+ bytes_read = read(fd, read_buffer, w->size);
+ if (bytes_read != w->size) {
+ fprintf(stderr, "offset = %lld\n" , (long long) w->offset);
+ fprintf(stderr, "size = %ld\n" , (long) w->size);
+ fprintf(stderr, "bytes_read = %ld\n" , (long) bytes_read);
+ error_exit("read failed");
+ }
+ set_random_data(w->random_seed, write_buffer, w->size);
+ if (memcmp(read_buffer, write_buffer, w->size))
+ error_exit("verify failed");
+ gap_end = w->offset;
+ w = w->next;
+ }
+ if (gap_end > erase_block->offset) {
+ /* Check all 0xff */
+ off64_t gap_start = erase_block->offset;
+ size_t size = gap_end - gap_start;
+ if (lseek64(fd, gap_start, SEEK_SET) != gap_start)
+ error_exit("lseek64 failed");
+ memset(read_buffer, 0 , size);
+ errno = 0;
+ bytes_read = read(fd, read_buffer, size);
+ if (bytes_read != size)
+ error_exit("read failed in gap");
+ while (size)
+ if (read_buffer[--size] != 0xff) {
+ fprintf(stderr, "block no. = %d\n" , erase_block->block_number);
+ fprintf(stderr, "offset = %lld\n" , (long long) gap_start);
+ fprintf(stderr, "size = %ld\n" , (long) bytes_read);
+ error_exit("verify 0xff failed!");
+ }
+ }
+}
+
+static int write_to_erase_block(struct erase_block_info *erase_block, int fd)
+{
+ int page_size = erase_block->volume->ubi_device->info.min_io_size;
+ int eb_size = erase_block->volume->info.eb_size;
+ int next_offset = 0;
+ int space, size;
+ off64_t offset;
+ unsigned seed;
+ struct write_info *w;
+
+ if (erase_block->writes)
+ next_offset = erase_block->writes->offset_within_block + erase_block->writes->size;
+ space = eb_size - next_offset;
+ if (space <= 0)
+ return 0; /* No space */
+ if (!get_random_number(10)) {
+ /* 1 time in 10 leave a gap */
+ next_offset += get_random_number(space);
+ next_offset = (next_offset / page_size) * page_size;
+ space = eb_size - next_offset;
+ }
+ if (get_random_number(2))
+ size = 1 * page_size;
+ else if (get_random_number(2))
+ size = 2 * page_size;
+ else if (get_random_number(2))
+ size = 3 * page_size;
+ else if (get_random_number(2))
+ size = 4 * page_size;
+ else {
+ if (get_random_number(4))
+ size = get_random_number(space);
+ else
+ size = space;
+ size = (size / page_size) * page_size;
+ }
+ if (size == 0 || size > space)
+ size = page_size;
+ if (next_offset + size > eb_size)
+ error_exit("internal error");
+ offset = erase_block->offset + next_offset;
+ if (offset < erase_block->top_of_data)
+ error_exit("internal error!");
+ if (lseek64(fd, offset, SEEK_SET) != offset)
+ error_exit("lseek64 failed");
+ /* Do write */
+ seed = get_next_seed();
+ if (!seed)
+ seed = 1;
+ set_random_data(seed, write_buffer, size);
+ if (write(fd, write_buffer, size) != size)
+ error_exit("write failed");
+ erase_block->top_of_data = offset + size;
+ /* Make write info and add to eb */
+ w = allocate(sizeof(*w));
+ w->offset_within_block = next_offset;
+ w->offset = offset;
+ w->size = size;
+ w->random_seed = seed;
+ w->next = erase_block->writes;
+ erase_block->writes = w;
+ erase_block->touched = 1;
+ erase_block->erased = 0;
+ total_written += size;
+ return 1;
+}
+
+static void erase_erase_block(struct erase_block_info *erase_block, int fd)
+{
+ struct write_info *w;
+ uint32_t eb_no;
+ int res;
+
+ eb_no = erase_block->block_number;
+ res = ioctl(fd, UBI_IOCEBER, &eb_no);
+ if (res)
+ error_exit("Failed to erase an erase block");
+ /* Remove writes from this eb */
+ while (erase_block->writes) {
+ w = erase_block->writes;
+ erase_block->writes = erase_block->writes->next;
+ free(w);
+ }
+ erase_block->erased = 1;
+ erase_block->touched = 1;
+ erase_block->top_of_data = erase_block->offset;
+}
+
+static void operate_on_erase_block(struct erase_block_info *erase_block, int fd)
+{
+ /*
+ Possible operations:
+ read from it and verify
+ write to it
+ erase it
+ */
+ int work_done = 1;
+ static int no_work_done_count = 0;
+
+ if (!get_random_number(10) && no_work_done_count <= 5) {
+ check_erase_block(erase_block, fd);
+ work_done = 0;
+ } else if (get_random_number(100)) {
+ if (!write_to_erase_block(erase_block, fd)) {
+ /* The erase block was full */
+ if (get_random_number(2) || no_work_done_count > 5)
+ erase_erase_block(erase_block, fd);
+ else
+ work_done = 0;
+ }
+ } else
+ erase_erase_block(erase_block, fd);
+ if (work_done)
+ no_work_done_count = 0;
+ else
+ no_work_done_count += 1;
+}
+
+static void operate_on_open_volume(struct volume_fd *vol_fd)
+{
+ /*
+ Possible operations:
+ operate on an erase block
+ close volume
+ */
+ if (get_random_number(100) == 0)
+ close_volume(vol_fd);
+ else {
+ /* Pick an erase block at random */
+ int eb_no = get_random_number(vol_fd->volume->info.rsvd_ebs);
+ operate_on_erase_block(&vol_fd->volume->erase_blocks[eb_no], vol_fd->fd);
+ }
+}
+
+static void operate_on_volume(struct volume_info *vol)
+{
+ /*
+ Possible operations:
+ open it
+ resize it (must close fd's first) <- TODO
+ delete it (must close fd's first) <- TODO
+ */
+ open_volume(vol);
+}
+
+static int ubi_major(const char *device_file_name)
+{
+ struct stat buf;
+ static int maj = 0;
+
+ if (maj)
+ return maj;
+ if (stat(device_file_name, &buf) == -1)
+ error_exit("Failed to stat ubi device file");
+ maj = major(buf.st_rdev);
+ return maj;
+}
+
+static void operate_on_ubi_device(struct ubi_device_info *ubi_device)
+{
+ /*
+ TODO:
+ Possible operations:
+ create a new volume
+ operate on existing volume
+ */
+ /*
+ Simplified operation (i.e. only have 1 volume):
+ If there are no volumes create 1 volumne
+ Then operate on the volume
+ */
+ if (ubi_device->info.vol_count == 0) {
+ /* Create the one-and-only volume we will use */
+ char dev_name[1024];
+ int i, n, maj, fd;
+ struct volume_info *s;
+ struct ubi_mkvol_request req;
+
+ req.vol_id = UBI_VOL_NUM_AUTO;
+ req.alignment = 1; /* TODO: What is this? */
+ req.bytes = ubi_device->info.eb_size * max_ebs_per_vol;
+ if (req.bytes == 0 || req.bytes > ubi_device->info.avail_bytes)
+ req.bytes = ubi_device->info.avail_bytes;
+ req.vol_type = UBI_DYNAMIC_VOLUME;
+ req.name = "integ-test-vol";
+ if (ubi_mkvol(libubi, ubi_device->device_file_name, &req))
+ error_exit("ubi_mkvol failed");
+ s = allocate(sizeof(*s));
+ s->ubi_device = ubi_device;
+ if (ubi_get_vol_info1(libubi, ubi_device->info.dev_num, req.vol_id, &s->info))
+ error_exit("ubi_get_vol_info failed");
+ n = s->info.rsvd_ebs;
+ s->erase_blocks = allocate(sizeof(struct erase_block_info) * n);
+ for (i = 0; i < n; ++i) {
+ s->erase_blocks[i].volume = s;
+ s->erase_blocks[i].block_number = i;
+ s->erase_blocks[i].offset = i * (off64_t) s->info.eb_size;
+ s->erase_blocks[i].top_of_data = s->erase_blocks[i].offset;
+ }
+ /* FIXME: Correctly get device file name */
+ sprintf(dev_name, "%s_%d", ubi_device->device_file_name, req.vol_id);
+ s->device_file_name = strdup(dev_name);
+ ubi_device->volumes = s;
+ ubi_device->info.vol_count += 1;
+ sleep(1);
+ fd = open(s->device_file_name, O_RDONLY);
+ if (fd == -1) {
+ /* FIXME: Correctly make node */
+ maj = ubi_major(ubi_device->device_file_name);
+ sprintf(dev_name, "mknod %s c %d %d", s->device_file_name, maj, req.vol_id + 1);
+ system(dev_name);
+ } else if (close(fd) == -1)
+ error_exit("Failed to close volume device file");
+ }
+ operate_on_volume(ubi_device->volumes);
+}
+
+static void do_an_operation(void)
+{
+ int too_few = (open_volume_count < info.dev_count * 3);
+ int too_many = (open_volume_count > info.dev_count * 5);
+
+ if (too_many || (!too_few && get_random_number(1000) > 0)) {
+ /* Operate on an open volume */
+ size_t pos;
+ struct open_volume_fd *ofd;
+ pos = get_random_number(open_volume_count);
+ for (ofd = open_volumes; pos && ofd && ofd->next; --pos)
+ ofd = ofd->next;
+ operate_on_open_volume(ofd->vol_fd);
+ } else if (info.dev_count > 0) {
+ /* Operate on a ubi device */
+ size_t ubi_pos = 0;
+ if (info.dev_count > 1)
+ ubi_pos = get_random_number(info.dev_count - 1);
+ operate_on_ubi_device(&ubi_array[ubi_pos]);
+ } else
+ error_exit("Internal error");
+}
+
+static void get_ubi_devices_info(void)
+{
+ int i, ubi_pos = 0;
+ char dev_name[1024];
+ size_t buf_size = 1024 * 128;
+
+ if (ubi_get_info(libubi, &info))
+ error_exit("ubi_get_info failed");
+ if (info.dev_count > MAX_UBI_DEVICES)
+ error_exit("Too many ubi devices");
+ for (i = info.lowest_dev_num; i <= info.highest_dev_num; ++i) {
+ struct ubi_device_info *s;
+ s = &ubi_array[ubi_pos++];
+ if (ubi_get_dev_info1(libubi, i, &s->info))
+ error_exit("ubi_get_dev_info1 failed");
+ if (s->info.vol_count)
+ error_exit("There are existing volumes");
+ /* FIXME: Correctly get device file name */
+ sprintf(dev_name, "/dev/ubi%d", i);
+ s->device_file_name = strdup(dev_name);
+ if (buf_size < s->info.eb_size)
+ buf_size = s->info.eb_size;
+ if (max_ebs_per_vol && s->info.eb_size * max_ebs_per_vol < s->info.avail_bytes)
+ total_space += s->info.eb_size * max_ebs_per_vol;
+ else
+ total_space += s->info.avail_bytes;
+ }
+ write_buffer = allocate(buf_size);
+ read_buffer = allocate(buf_size);
+}
+
+static void load_ubi(void)
+{
+ system("rmmod ubi");
+ if (system(ubi_module_load_string) != 0)
+ error_exit("Failed to load UBI module");
+ sleep(1);
+}
+
+static void do_some_operations(void)
+{
+ unsigned i = 0;
+ total_written = 0;
+ printf("Total space: %llu\n", (unsigned long long) total_space);
+ while (total_written < total_space * 3) {
+ do_an_operation();
+ if (i++ % 10000 == 0)
+ printf("Total written: %llu\n", (unsigned long long) total_written);
+ }
+ printf("Total written: %llu\n", (unsigned long long) total_written);
+}
+
+static void reload_ubi(void)
+{
+ /* Remove module */
+ if (system("rmmod ubi") != 0)
+ error_exit("Failed to remove UBI module");
+ /* Install module */
+ if (system(ubi_module_load_string) != 0)
+ error_exit("Failed to load UBI module");
+ sleep(1);
+}
+
+static void check_volume(struct volume_info *vol)
+{
+ struct erase_block_info *eb = vol->erase_blocks;
+ int pos;
+ int fd;
+
+ fd = open(vol->device_file_name, O_RDWR | O_LARGEFILE);
+ if (fd == -1)
+ error_exit("Failed to open volume device file");
+ for (pos = 0; pos < vol->info.rsvd_ebs; ++pos)
+ check_erase_block(eb++, fd);
+ if (close(fd) == -1)
+ error_exit("Failed to close volume device file");
+}
+
+static void check_ubi_device(struct ubi_device_info *ubi_device)
+{
+ struct volume_info *vol;
+
+ vol = ubi_device->volumes;
+ while (vol) {
+ check_volume(vol);
+ vol = vol->next;
+ }
+}
+
+static void check_ubi(void)
+{
+ int i;
+
+ for (i = 0; i < info.dev_count; ++i)
+ check_ubi_device(&ubi_array[i]);
+}
+
+static int is_all_digits(const char *s)
+{
+ const char *digits = "0123456789";
+ if (!s || !*s)
+ return 0;
+ for (;*s;++s)
+ if (!strchr(digits,*s))
+ return 0;
+ return 1;
+}
+
+static int get_short_arg(int *pos,const char *name,long long *result,int argc,char *argv[])
+{
+ const char *p = NULL;
+ int i = *pos;
+ size_t n = strlen(name);
+
+ if (strlen(argv[i]) > n)
+ p = argv[i] + n;
+ else if (++i < argc)
+ p = argv[i];
+ if (!is_all_digits(p))
+ return 1;
+ *result = atoll(p);
+ *pos = i;
+ return 0;
+}
+
+static int get_long_arg(int *pos,const char *name,long long *result,int argc,char *argv[])
+{
+ const char *p = NULL;
+ int i = *pos;
+ size_t n = strlen(name);
+
+ if (strlen(argv[i]) > n)
+ p = argv[i] + n;
+ else if (++i < argc)
+ p = argv[i];
+ if (p && *p == '=') {
+ p += 1;
+ if (!*p && ++i < argc)
+ p = argv[i];
+ }
+ if (!is_all_digits(p))
+ return 1;
+ *result = atoll(p);
+ *pos = i;
+ return 0;
+}
+
+static int remove_all_volumes(void)
+{
+ int i;
+
+ for (i = 0; i < info.dev_count; ++i) {
+ struct ubi_device_info *ubi_device = &ubi_array[i];
+ struct volume_info *vol;
+ vol = ubi_device->volumes;
+ while (vol) {
+ int res = ubi_rmvol(libubi,
+ ubi_device->device_file_name,
+ vol->info.vol_id);
+ if (res)
+ return res;
+ vol = vol->next;
+ }
+ }
+ return 0;
+}
+
+int main(int argc,char *argv[])
+{
+ int i;
+ long long r, repeat = 1;
+ int initial_seed = 1, args_ok = 1;
+
+ printf("UBI Integrity Test\n");
+
+ /* Get arguments */
+ ubi_module_load_string = 0;
+ for (i = 1; i < argc; ++i) {
+ if (strncmp(argv[i], "-h", 2) == 0)
+ args_ok = 0;
+ else if (strncmp(argv[i], "--help", 6) == 0)
+ args_ok = 0;
+ else if (strncmp(argv[i], "-n", 2) == 0) {
+ if (get_short_arg(&i, "-n", &repeat, argc, argv))
+ args_ok = 0;
+ } else if (strncmp(argv[i], "--repeat", 8) == 0) {
+ if (get_long_arg(&i, "--repeat", &repeat, argc, argv))
+ args_ok = 0;
+ } else if (strncmp(argv[i], "-m", 2) == 0) {
+ if (get_short_arg(&i,"-m", &max_ebs_per_vol, argc, argv))
+ args_ok = 0;
+ } else if (strncmp(argv[i], "--maxebs", 8) == 0) {
+ if (get_long_arg(&i, "--maxebs", &max_ebs_per_vol, argc, argv))
+ args_ok = 0;
+ } else if (!ubi_module_load_string)
+ ubi_module_load_string = argv[i];
+ else
+ args_ok = 0;
+ }
+ if (!args_ok || !ubi_module_load_string) {
+ fprintf(stderr, "Usage is: ubi_integ [<options>] <UBI Module load command>\n");
+ fprintf(stderr, " Options: \n");
+ fprintf(stderr, " -h, --help Help\n");
+ fprintf(stderr, " -n arg, --repeat=arg Repeat test arg times\n");
+ fprintf(stderr, " -m arg, --maxebs=arg Max no. of erase blocks\n");
+ return 1;
+ }
+
+ initial_seed = getpid();
+ printf("Initial seed = %u\n", (unsigned) initial_seed);
+ next_seed = initial_seed;
+ srand(initial_seed);
+ load_ubi();
+
+ libubi = libubi_open();
+ if (!libubi)
+ error_exit("Failed to open libubi");
+
+ get_ubi_devices_info();
+
+ r = 0;
+ while (repeat == 0 || r++ < repeat) {
+ printf("Cycle %lld\n", r);
+ do_some_operations();
+
+ /* Close all volumes */
+ while (open_volumes)
+ close_volume(open_volumes->vol_fd);
+
+ check_ubi();
+
+ libubi_close(libubi);
+
+ reload_ubi();
+
+ libubi = libubi_open();
+ if (!libubi)
+ error_exit("Failed to open libubi");
+
+ check_ubi();
+ }
+
+ if (remove_all_volumes())
+ error_exit("Failed to remove all volumes");
+
+ libubi_close(libubi);
+
+ printf("UBI Integrity Test completed ok\n");
+ return 0;
+}