New targets for:
[lwext4.git] / demos / generic / main.c
index ab24bd753b885bbca3ff24fe96e35c8c74250bc6..de0e7f84b1fac3d3ecb6f4bda894edd2eca603c0 100644 (file)
 #include <unistd.h>\r
 #include <getopt.h>\r
 #include <stdbool.h>\r
+#include <time.h>\r
+#include <unistd.h>\r
+#include <sys/time.h>\r
 \r
 #include <ext4_filedev.h>\r
+#include <io_raw.h>\r
 #include <ext4.h>\r
 \r
+#ifdef WIN32\r
+#include <windows.h>\r
+#endif\r
 \r
-\r
+/**@brief   Input stream name.*/\r
 char input_name[128] = "ext2";\r
 \r
-/**@brief      Read-write size*/\r
-static int rw_szie  = 1024;\r
+/**@brief   Read-write size*/\r
+static int rw_szie  = 1024 * 1024;\r
 \r
-/**@brief      Read-write size*/\r
-static int rw_count = 1024;\r
+/**@brief   Read-write size*/\r
+static int rw_count = 10;\r
 \r
 /**@brief   Directory test count*/\r
-static int dir_cnt  = 10;\r
+static int dir_cnt  = 0;\r
+\r
+/**@brief   Static or dynamic cache mode*/\r
+static bool cache_mode = true;\r
+\r
+/**@brief   Cleanup after test.*/\r
+static bool cleanup_flag = false;\r
+\r
+/**@brief   Block device stats.*/\r
+static bool bstat = false;\r
 \r
-static bool cache_mode = false;\r
+/**@brief   Superblock stats.*/\r
+static bool sbstat = false;\r
 \r
+/**@brief   Indicates that input is windows partition.*/\r
+static bool winpart = false;\r
 \r
-/**@brief      File write buffer*/\r
-static uint8_t *wr_buff;\r
+/**@brief   File write buffer*/\r
+static uint8_t *wr_buff;\r
 \r
-/**@brief      File read buffer.*/\r
-static uint8_t *rd_buff;\r
+/**@brief   File read buffer.*/\r
+static uint8_t *rd_buff;\r
 \r
-/**@brief      Block device handle.*/\r
+/**@brief   Block device handle.*/\r
 static struct ext4_blockdev *bd;\r
 \r
-/**@brief      Block cache handle.*/\r
-static struct ext4_bcache   *bc;\r
-\r
-static const char *usage = "                                                                   \n\\r
-Welcome in ext4 generic demo.                                                                  \n\\r
-Copyright (c) 2013 Grzegorz Kostka (kostka.grzegorz@gmail.com) \n\\r
-Usage:                                                                                                                 \n\\r
-       -i   - input file             (default = ext2)                          \n\\r
-       -rws - single R/W size        (default = 1024)                          \n\\r
-       -rwc - R/W count              (default = 1024)                          \n\\r
-       -cache - 0 static, 1 dynamic  (default = 0)                                     \n\\r
-    -dirs  - directory test count (default = 0)                 \n\\r
+/**@brief   Static cache instance*/\r
+EXT4_BCACHE_STATIC_INSTANCE(_lwext4_cache, CONFIG_BLOCK_DEV_CACHE_SIZE, 1024);\r
+\r
+/**@brief   Block cache handle.*/\r
+static struct ext4_bcache   *bc = &_lwext4_cache;\r
+\r
+static const char *usage = "                                    \n\\r
+Welcome in ext4 generic demo.                                   \n\\r
+Copyright (c) 2013 Grzegorz Kostka (kostka.grzegorz@gmail.com)  \n\\r
+Usage:                                                          \n\\r
+    --i   - input file              (default = ext2)            \n\\r
+    --rws - single R/W size         (default = 1024 * 1024)     \n\\r
+    --rwc - R/W count               (default = 10)              \n\\r
+    --cache  - 0 static, 1 dynamic  (default = 1)               \n\\r
+    --dirs   - directory test count (default = 0)               \n\\r
+    --clean  - clean up after test                              \n\\r
+    --bstat  - block device stats                               \n\\r
+    --sbstat - superblock stats                                 \n\\r
+    --wpart  - windows partition mode                           \n\\r
 \n";\r
 \r
+\r
+\r
+\r
+\r
 static char* entry_to_str(uint8_t type)\r
 {\r
-       switch(type){\r
-       case EXT4_DIRENTRY_UNKNOWN:\r
-               return "[UNK] ";\r
-       case EXT4_DIRENTRY_REG_FILE:\r
-               return "[FIL] ";\r
-       case EXT4_DIRENTRY_DIR:\r
-               return "[DIR] ";\r
-       case EXT4_DIRENTRY_CHRDEV:\r
-               return "[CHA] ";\r
-       case EXT4_DIRENTRY_BLKDEV:\r
-               return "[BLK] ";\r
-       case EXT4_DIRENTRY_FIFO:\r
-               return "[FIF] ";\r
-       case EXT4_DIRENTRY_SOCK:\r
-               return "[SOC] ";\r
-       case EXT4_DIRENTRY_SYMLINK:\r
-               return "[SYM] ";\r
-       default:\r
-               break;\r
-       }\r
-       return "[???]";\r
+    switch(type){\r
+    case EXT4_DIRENTRY_UNKNOWN:\r
+        return "[UNK] ";\r
+    case EXT4_DIRENTRY_REG_FILE:\r
+        return "[FIL] ";\r
+    case EXT4_DIRENTRY_DIR:\r
+        return "[DIR] ";\r
+    case EXT4_DIRENTRY_CHRDEV:\r
+        return "[CHA] ";\r
+    case EXT4_DIRENTRY_BLKDEV:\r
+        return "[BLK] ";\r
+    case EXT4_DIRENTRY_FIFO:\r
+        return "[FIF] ";\r
+    case EXT4_DIRENTRY_SOCK:\r
+        return "[SOC] ";\r
+    case EXT4_DIRENTRY_SYMLINK:\r
+        return "[SYM] ";\r
+    default:\r
+        break;\r
+    }\r
+    return "[???]";\r
 }\r
 \r
 static void dir_ls(const char *path)\r
 {\r
-       int j = 0;\r
-       char sss[255];\r
-       ext4_dir d;\r
-       ext4_direntry *de;\r
-\r
-       printf("**********************************************\n");\r
-\r
-       ext4_dir_open(&d, path);\r
-       de = ext4_dir_entry_get(&d, j++);\r
-       printf("ls %s\n", path);\r
-\r
-       while(de){\r
-               memcpy(sss, de->name, de->name_length);\r
-               sss[de->name_length] = 0;\r
-               printf(entry_to_str(de->inode_type));\r
-               printf(sss);\r
-               printf("\n");\r
-               de = ext4_dir_entry_get(&d, j++);\r
-       }\r
-       printf("**********************************************\n");\r
-       ext4_dir_close(&d);\r
+    int j = 0;\r
+    char sss[255];\r
+    ext4_dir d;\r
+    ext4_direntry *de;\r
+\r
+    printf("**********************************************\n");\r
+\r
+    ext4_dir_open(&d, path);\r
+    de = ext4_dir_entry_get(&d, j++);\r
+    printf("ls %s\n", path);\r
+\r
+    while(de){\r
+        memcpy(sss, de->name, de->name_length);\r
+        sss[de->name_length] = 0;\r
+        printf("%s", entry_to_str(de->inode_type));\r
+        printf("%s", sss);\r
+        printf("\n");\r
+        de = ext4_dir_entry_get(&d, j++);\r
+    }\r
+    printf("**********************************************\n");\r
+    ext4_dir_close(&d);\r
 }\r
 \r
 static void mp_stats(void)\r
@@ -180,21 +210,26 @@ static void block_stats(void)
         printf("bcache->lba[%d]        = %u\n", i, (uint32_t)bc->lba[i]);\r
     }\r
 \r
-\r
-\r
     printf("**********************************************\n");\r
 }\r
 \r
+static clock_t get_ms(void)\r
+{\r
+    struct timeval t;\r
+    gettimeofday(&t, NULL);\r
+    return (t.tv_sec * 1000) + (t.tv_usec / 1000);\r
+}\r
+\r
 static bool dir_test(int len)\r
 {\r
     ext4_file f;\r
     int       r;\r
     int       i;\r
     char path[64];\r
-\r
-    printf("Remove directory /mp/dir1\n");\r
-    ext4_dir_rm("/mp/dir1");\r
-\r
+    clock_t diff;\r
+    clock_t stop;\r
+    clock_t start;\r
+    start = get_ms();\r
 \r
     printf("Directory create: /mp/dir1\n");\r
     r = ext4_dir_mk("/mp/dir1");\r
@@ -204,6 +239,7 @@ static bool dir_test(int len)
     }\r
 \r
 \r
+    ext4_cache_write_back("/mp/", 1);\r
     printf("Add files to: /mp/dir1\n");\r
     for (i = 0; i < len; ++i) {\r
         sprintf(path, "/mp/dir1/f%d", i);\r
@@ -213,194 +249,307 @@ static bool dir_test(int len)
             return false;\r
         }\r
     }\r
+    ext4_cache_write_back("/mp/", 0);\r
 \r
-    printf("Add directories to: /mp/dir1\n");\r
-    for (i = 0; i < len; ++i) {\r
-        sprintf(path, "/mp/dir1/d%d", i);\r
-        r = ext4_dir_mk(path);\r
-        if(r != EOK){\r
-            printf("Unable to create directory in directory: /mp/dir1\n");\r
-            return false;\r
-        }\r
-    }\r
-\r
-    printf("Add file directories in: /mp/dir1\n");\r
-\r
-    for (i = 0; i < len; ++i) {\r
-        sprintf(path, "/mp/dir1/d%d/ff", i);\r
-        r = ext4_fopen(&f, path, "wb");\r
-        if(r != EOK){\r
-            printf("Unable to create file in directory: /mp/dir1\n");\r
-            return false;\r
-        }\r
-    }\r
-\r
+    stop =  get_ms();\r
+    diff = stop - start;\r
     dir_ls("/mp/dir1");\r
+    printf("dir_test time: %d ms\n", (int)diff);\r
     return true;\r
 }\r
 \r
-int main(int argc, char **argv)\r
+\r
+static bool file_test(void)\r
 {\r
-       int option_index = 0;\r
-       int     c;\r
-       int     r;\r
-       int     i;\r
-       uint32_t  size;\r
-       ext4_file f;\r
+    int r;\r
+    uint32_t  size;\r
+    ext4_file f;\r
+    int i;\r
+    clock_t start;\r
+    clock_t stop;\r
+    clock_t diff;\r
+    uint32_t kbps;\r
+    uint64_t size_bytes;\r
+    /*Add hello world file.*/\r
+    r = ext4_fopen(&f, "/mp/hello.txt", "wb");\r
+    r = ext4_fwrite(&f, "Hello World !\n", strlen("Hello World !\n"), 0);\r
+    r = ext4_fclose(&f);\r
 \r
-    static struct option long_options[] =\r
-      {\r
-        {"in",         required_argument, 0, 'a'},\r
-        {"rws",     required_argument, 0, 'b'},\r
-        {"rwc",                required_argument, 0, 'c'},\r
-        {"cache",   required_argument, 0, 'd'},\r
-        {"dirs",   required_argument,  0, 'e'},\r
-        {0, 0, 0, 0}\r
-      };\r
-\r
-    while(-1 != (c = getopt_long (argc, argv, "a:b:c:d:e:", long_options, &option_index))) {\r
-\r
-       switch(c){\r
-               case 'a':\r
-                       strcpy(input_name, optarg);\r
-                       break;\r
-               case 'b':\r
-                       rw_szie = atoi(optarg);\r
-                       break;\r
-               case 'c':\r
-                       rw_count = atoi(optarg);\r
-                       break;\r
-               case 'd':\r
-                       cache_mode = atoi(optarg);\r
-                       break;\r
-            case 'e':\r
-                dir_cnt = atoi(optarg);\r
-                break;\r
-               default:\r
-                       printf(usage);\r
-                       return EXIT_FAILURE;\r
-\r
-       }\r
+\r
+    printf("ext4_fopen: test1\n");\r
+\r
+    start = get_ms();\r
+    r = ext4_fopen(&f, "/mp/test1", "wb");\r
+    if(r != EOK){\r
+        printf("ext4_fopen ERROR = %d\n", r);\r
+        return false;\r
     }\r
 \r
-    printf("Test conditions:\n");\r
-    printf("Imput name: %s\n", input_name);\r
-    printf("RW size: %d\n",  rw_szie);\r
-    printf("RW count: %d\n", rw_count);\r
-    printf("Cache mode: %s\n", cache_mode ? "dynamic" : "static");\r
+    printf("ext4_write: %d * %d ..." , rw_szie, rw_count);\r
+    for (i = 0; i < rw_count; ++i) {\r
 \r
+        memset(wr_buff, i % 10 + '0', rw_szie);\r
 \r
+        r = ext4_fwrite(&f, wr_buff, rw_szie, &size);\r
 \r
-    ext4_filedev_filename(input_name);\r
+        if((r != EOK) || (size != rw_szie))\r
+            break;\r
+    }\r
 \r
-    wr_buff = malloc(rw_szie);\r
-    rd_buff = malloc(rw_szie);\r
+    if(i != rw_count){\r
+        printf("ERROR: rw_count = %d\n", i);\r
+        return false;\r
+    }\r
 \r
-    if(!wr_buff || !rd_buff){\r
-       printf("Read-Write allocation ERROR\n");\r
-       return EXIT_FAILURE;\r
+    printf("OK\n");\r
+    stop = get_ms();\r
+    diff = stop - start;\r
+    size_bytes = rw_szie * rw_count;\r
+    size_bytes = (size_bytes * 1000) / 1024;\r
+    kbps = (size_bytes) / (diff + 1);\r
+    printf("file_test write time: %d ms\n", (int)diff);\r
+    printf("file_test write speed: %d KB/s\n", kbps);\r
+    r = ext4_fclose(&f);\r
+    printf("ext4_fopen: test1\n");\r
+\r
+\r
+    start = get_ms();\r
+    r = ext4_fopen(&f, "/mp/test1", "r+");\r
+    if(r != EOK){\r
+        printf("ext4_fopen ERROR = %d\n", r);\r
+        return false;\r
     }\r
 \r
-       bd = ext4_filedev_get();\r
-       bc = ext4_filecache_get();\r
+    printf("ext4_read: %d * %d ..." , rw_szie, rw_count);\r
+\r
+    for (i = 0; i < rw_count; ++i) {\r
+        memset(wr_buff, i % 10 + '0', rw_szie);\r
+        r = ext4_fread(&f, rd_buff, rw_szie, &size);\r
 \r
-    if(!bd || !bc){\r
-       printf("Block device ERROR\n");\r
-       return EXIT_FAILURE;\r
+        if((r != EOK) || (size != rw_szie))\r
+            break;\r
+\r
+        if(memcmp(rd_buff, wr_buff, rw_szie)){\r
+            break;\r
+        }\r
     }\r
+    if(i != rw_count){\r
+        printf("ERROR: rw_count = %d\n", i);\r
+        return false;\r
+    }\r
+    printf("OK\n");\r
+    stop = get_ms();\r
+    diff = stop - start;\r
+    size_bytes = rw_szie * rw_count;\r
+    size_bytes = (size_bytes * 1000) / 1024;\r
+    kbps = (size_bytes) / (diff + 1);\r
+    printf("file_test read time: %d ms\n", (int)diff);\r
+    printf("file_test read speed: %d KB/s\n", kbps);\r
+    r = ext4_fclose(&f);\r
 \r
-       ext4_dmask_set(EXT4_DEBUG_ALL);\r
+    return true;\r
 \r
-       r = ext4_device_register(bd, cache_mode ? 0 : bc, "ext4_filesim");\r
-       if(r != EOK){\r
-               printf("ext4_device_register ERROR = %d\n", r);\r
-               return EXIT_FAILURE;\r
-       }\r
+}\r
+static void cleanup(void)\r
+{\r
+    clock_t start;\r
+    clock_t stop;\r
+    clock_t diff;\r
 \r
-       r = ext4_mount("ext4_filesim", "/mp/");\r
-       if(r != EOK){\r
-               printf("ext4_mount ERROR = %d\n", r);\r
-               return EXIT_FAILURE;\r
-       }\r
+    ext4_fremove("/mp/hello.txt");\r
 \r
-       dir_test(dir_cnt);\r
+    printf("cleanup: remove /mp/test1\n");\r
+    start = get_ms();\r
+    ext4_fremove("/mp/test1");\r
+    stop = get_ms();\r
+    diff = stop - start;\r
+    printf("cleanup: time: %d ms\n", (int)diff);\r
 \r
-       ext4_fremove("/mp/hello.txt");\r
-       ext4_fremove("/mp/test1");\r
-       mp_stats();\r
-       dir_ls("/mp/");\r
 \r
-    /*Add hello world file.*/\r
-    r = ext4_fopen(&f, "/mp/hello.txt", "wb");\r
-    r = ext4_fwrite(&f, "Hello World !\n", strlen("Hello World !\n"), 0);\r
-    r = ext4_fclose(&f);\r
+    printf("cleanup: remove /mp/dir1\n");\r
+    start =get_ms();\r
+    ext4_dir_rm("/mp/dir1");\r
+    stop = get_ms();\r
+    diff = stop - start;\r
+    printf("cleanup: time: %d ms\n", (int)diff);\r
+}\r
 \r
+static bool open_filedev(void)\r
+{\r
+    ext4_filedev_filename(input_name);\r
+    bd = ext4_filedev_get();\r
+    if(!bd){\r
+        printf("Block device ERROR\n");\r
+        return false;\r
+    }\r
+    return true;\r
+}\r
 \r
-       printf("ext4_fopen: test1\n");\r
+static bool open_winpartition(void)\r
+{\r
+#ifdef WIN32\r
+    ext4_io_raw_filename(input_name);\r
+    bd = ext4_io_raw_dev_get();\r
+    if(!bd){\r
+        printf("Block device ERROR\n");\r
+        return false;\r
+    }\r
+    return true;\r
+#else\r
+    printf("open_winpartition: this mode should be used only under windows !\n");\r
+    return false;\r
+#endif\r
+}\r
 \r
-       r = ext4_fopen(&f, "/mp/test1", "wb");\r
-       if(r != EOK){\r
-               printf("ext4_fopen ERROR = %d\n", r);\r
-               return EXIT_FAILURE;\r
-       }\r
+static bool mount(void)\r
+{\r
+    int r;\r
+    if(winpart){\r
+        if(!open_winpartition())\r
+            return false;\r
+    }else{\r
+        if(!open_filedev())\r
+            return false;\r
 \r
-       printf("ext4_write: %d * %d ..." , rw_count, rw_szie);\r
+    }\r
+    wr_buff = malloc(rw_szie);\r
+    rd_buff = malloc(rw_szie);\r
 \r
-       for (i = 0; i < rw_count; ++i) {\r
+    if(!wr_buff || !rd_buff){\r
+        printf("Read-Write allocation ERROR\n");\r
+        return EXIT_FAILURE;\r
+    }\r
 \r
-               memset(wr_buff, i & 0xFF, rw_szie);\r
+    ext4_dmask_set(EXT4_DEBUG_ALL);\r
 \r
-               r = ext4_fwrite(&f, wr_buff, rw_szie, &size);\r
+    r = ext4_device_register(bd, cache_mode ? 0 : bc, "ext4_filesim");\r
+    if(r != EOK){\r
+        printf("ext4_device_register ERROR = %d\n", r);\r
+        return false;\r
+    }\r
+\r
+    r = ext4_mount("ext4_filesim", "/mp/");\r
+    if(r != EOK){\r
+        printf("ext4_mount ERROR = %d\n", r);\r
+        return false;\r
+    }\r
+\r
+    return true;\r
+}\r
 \r
-               if((r != EOK) || (size != rw_szie))\r
-                       break;\r
-       }\r
+static bool umount(void)\r
+{\r
+    int r = ext4_umount("/mp/");\r
+    if(r != EOK){\r
+        printf("ext4_umount: FAIL %d", r);\r
+        return false;\r
+    }\r
+    return true;\r
+}\r
+\r
+static bool parse_opt(int argc, char **argv)\r
+{\r
+    int option_index = 0;\r
+    int c;\r
 \r
-       if(i != rw_count){\r
-               printf("ERROR: rw_count = %d\n", i);\r
-               return EXIT_FAILURE;\r
-       }\r
+    static struct option long_options[] =\r
+    {\r
+            {"in",      required_argument, 0, 'a'},\r
+            {"rws",     required_argument, 0, 'b'},\r
+            {"rwc",     required_argument, 0, 'c'},\r
+            {"cache",   required_argument, 0, 'd'},\r
+            {"dirs",    required_argument, 0, 'e'},\r
+            {"clean",   no_argument,       0, 'f'},\r
+            {"bstat",   no_argument,       0, 'g'},\r
+            {"sbstat",  no_argument,       0, 'h'},\r
+            {"wpart",   no_argument,       0, 'i'},\r
+            {0, 0, 0, 0}\r
+    };\r
+\r
+    while(-1 != (c = getopt_long (argc, argv, "a:b:c:d:e:fghi", long_options, &option_index))) {\r
+\r
+        switch(c){\r
+        case 'a':\r
+            strcpy(input_name, optarg);\r
+            break;\r
+        case 'b':\r
+            rw_szie = atoi(optarg);\r
+            break;\r
+        case 'c':\r
+            rw_count = atoi(optarg);\r
+            break;\r
+        case 'd':\r
+            cache_mode = atoi(optarg);\r
+            break;\r
+        case 'e':\r
+            dir_cnt = atoi(optarg);\r
+            break;\r
+        case 'f':\r
+            cleanup_flag = true;\r
+            break;\r
+        case 'g':\r
+            bstat = true;\r
+            break;\r
+        case 'h':\r
+            sbstat = true;\r
+            break;\r
+        case 'i':\r
+            winpart = true;\r
+            break;\r
+        default:\r
+            printf("%s", usage);\r
+            return false;\r
+\r
+        }\r
+    }\r
+    return true;\r
+}\r
+\r
+int main(int argc, char **argv)\r
+{\r
+    if(!parse_opt(argc, argv))\r
+        return EXIT_FAILURE;\r
+\r
+    printf("Test conditions:\n");\r
+    printf("Imput name: %s\n", input_name);\r
+    printf("RW size: %d\n",  rw_szie);\r
+    printf("RW count: %d\n", rw_count);\r
+    printf("Cache mode: %s\n", cache_mode ? "dynamic" : "static");\r
 \r
-       printf("OK\n");\r
-       r = ext4_fclose(&f);\r
-       printf("ext4_fopen: test1\n");\r
+    if(!mount())\r
+        return EXIT_FAILURE;\r
 \r
-       r = ext4_fopen(&f, "/mp/test1", "r+");\r
-       if(r != EOK){\r
-               printf("ext4_fopen ERROR = %d\n", r);\r
-               return EXIT_FAILURE;\r
-       }\r
 \r
-       printf("ext4_read: %d * %d ..." , rw_count, rw_szie);\r
+    cleanup();\r
 \r
-       for (i = 0; i < rw_count; ++i) {\r
-               memset(wr_buff, i & 0xFF, rw_szie);\r
-               r = ext4_fread(&f, rd_buff, rw_szie, &size);\r
+    if(sbstat)\r
+        mp_stats();\r
 \r
-               if((r != EOK) || (size != rw_szie))\r
-                       break;\r
+    dir_ls("/mp/");\r
+    fflush(stdout);\r
+    if(!dir_test(dir_cnt))\r
+        return EXIT_FAILURE;\r
 \r
-               if(memcmp(rd_buff, wr_buff, rw_szie)){\r
-                       break;\r
-               }\r
-       }\r
-       if(i != rw_count){\r
-               printf("ERROR: rw_count = %d\n", i);\r
-               return EXIT_FAILURE;\r
-       }\r
+    fflush(stdout);\r
+    if(!file_test())\r
+        return EXIT_FAILURE;\r
 \r
-       printf("OK\n");\r
+    fflush(stdout);\r
+    dir_ls("/mp/");\r
 \r
-       r = ext4_fclose(&f);\r
+    if(sbstat)\r
+        mp_stats();\r
 \r
+    if(cleanup_flag)\r
+        cleanup();\r
 \r
-       mp_stats();\r
-       dir_ls("/mp/");\r
+    if(bstat)\r
+        block_stats();\r
 \r
-       block_stats();\r
-       r = ext4_umount("/mp/");\r
+    if(!umount())\r
+        return EXIT_FAILURE;\r
 \r
-       printf("Test finish: OK\n");\r
+    printf("Test finish: OK\n");\r
     return EXIT_SUCCESS;\r
 \r
 }\r