FEATURES:
authorgkostka <kostka.grzegorz@gmail.com>
Sun, 27 Oct 2013 11:48:48 +0000 (11:48 +0000)
committergkostka <kostka.grzegorz@gmail.com>
Sun, 27 Oct 2013 11:48:48 +0000 (11:48 +0000)
1. New io_raw block device. Allows to access windows partitions.
2. Demo app timings. Windows ext2/3/4 volume access.
3. Faster big file read/write operations (multi block mode).

CMakeLists.txt
Makefile
blockdev/filedev/ext4_filedev.c
blockdev/io_raw/io_raw.c [new file with mode: 0644]
blockdev/io_raw/io_raw.h [new file with mode: 0644]
demos/generic/main.c
lwext4/ext4.c
lwext4/ext4_blockdev.c
lwext4/ext4_blockdev.h
lwext4/ext4_fs.c

index 55310905727792aa816c2a700c1370518eb33f15..9fb297ef30735e348cb29988a6bd259ee81b6c87 100644 (file)
@@ -25,9 +25,13 @@ add_custom_target(size ALL DEPENDS lwext4 COMMAND ${SIZE} -B liblwext4.a)
 else()\r
 #Generic example target\r
 include_directories(blockdev/filedev)\r
+include_directories(blockdev/io_raw)\r
+\r
 aux_source_directory(blockdev/filedev FILEDEV_SRC)\r
+aux_source_directory(blockdev/io_raw IORAW_SRC)\r
 aux_source_directory(demos/generic GENERIC_SRC)\r
-add_executable(fileimage_demo ${GENERIC_SRC} ${FILEDEV_SRC})\r
+\r
+add_executable(fileimage_demo ${GENERIC_SRC} ${FILEDEV_SRC} ${IORAW_SRC})\r
 target_link_libraries(fileimage_demo lwext4)\r
 add_custom_target(size ALL DEPENDS lwext4 COMMAND size -B liblwext4.a)\r
 endif()\r
index a08f7d7a553337505e53dcd1e3847bbeba1d1117..b2cfb491d5d13e12bc4f02d6d40421e316b2b592 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,10 @@
 \r
-all: generic bf518 cortex-m3 cortex-m4 generic\r
-\r
+generic:\r
+       rm -R -f build_generic\r
+       mkdir build_generic\r
+       cd build_generic && cmake -G"Unix Makefiles" ../\r
+       cd build_generic && make\r
+       \r
 bf518:\r
        rm -R -f build_bf518\r
        mkdir build_bf518\r
@@ -18,14 +22,10 @@ cortex-m4:
        mkdir build_cortex-m4\r
        cd build_cortex-m4 && cmake -G"Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE=../toolchain/cortex-m4.cmake ..\r
        cd build_cortex-m4 && make\r
-       \r
-       \r
-generic:\r
-       rm -R -f build_generic\r
-       mkdir build_generic\r
-       cd build_generic && cmake -G"Unix Makefiles" ../\r
-       cd build_generic && make\r
-       \r
+\r
+all: generic bf518 cortex-m3 cortex-m4 generic\r
+\r
+\r
        \r
 clean:\r
        rm -R -f build_bf518\r
index 091ae6b80e65629b22b219301c969f04c5cf7fbb..bc88c908beeea1f202684062b938e27a905908d2 100644 (file)
@@ -33,7 +33,7 @@
 #include <string.h>
 
 /**@brief      Default filename.*/
-const char *fname = "ext2";
+static const char *fname = "ext2";
 
 /**@brief      Image block size.*/
 #define EXT4_FILEDEV_BSIZE             512
@@ -71,7 +71,7 @@ static int filedev_open(struct ext4_blockdev *bdev)
        dev_file = fopen(fname, "r+b");
 
        if(!dev_file)
-               return ENOENT;
+               return EIO;
 
        if(fseek(dev_file, 0, SEEK_END))
                return EFAULT;
diff --git a/blockdev/io_raw/io_raw.c b/blockdev/io_raw/io_raw.c
new file mode 100644 (file)
index 0000000..febd832
--- /dev/null
@@ -0,0 +1,202 @@
+/*\r
+ * Copyright (c) 2013 Grzegorz Kostka (kostka.grzegorz@gmail.com)\r
+ * All rights reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions\r
+ * are met:\r
+ *\r
+ * - Redistributions of source code must retain the above copyright\r
+ *   notice, this list of conditions and the following disclaimer.\r
+ * - Redistributions in binary form must reproduce the above copyright\r
+ *   notice, this list of conditions and the following disclaimer in the\r
+ *   documentation and/or other materials provided with the distribution.\r
+ * - The name of the author may not be used to endorse or promote products\r
+ *   derived from this software without specific prior written permission.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\r
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\r
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\r
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\r
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\r
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\r
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
+\r
+#include <ext4_config.h>\r
+#include <ext4_blockdev.h>\r
+#include <ext4_errno.h>\r
+#include <stdio.h>\r
+#include <stdbool.h>\r
+#include <string.h>\r
+\r
+#ifdef WIN32\r
+#include <windows.h>\r
+#include <winioctl.h>\r
+\r
+\r
+/**@brief   Default filename.*/\r
+static const char *fname = "ext2";\r
+\r
+/**@brief   IO block size.*/\r
+#define EXT4_IORAW_BSIZE      512\r
+\r
+/**@brief   Image file descriptor.*/\r
+static HANDLE dev_file;\r
+\r
+\r
+/**********************BLOCKDEV INTERFACE**************************************/\r
+static int io_raw_open(struct ext4_blockdev *bdev);\r
+static int io_raw_bread(struct ext4_blockdev *bdev, void *buf, uint64_t blk_id,\r
+    uint32_t blk_cnt);\r
+static int io_raw_bwrite(struct ext4_blockdev *bdev, const void *buf,\r
+    uint64_t blk_id, uint32_t blk_cnt);\r
+static int io_raw_close(struct  ext4_blockdev *bdev);\r
+\r
+\r
+\r
+\r
+/******************************************************************************/\r
+EXT4_BLOCKDEV_STATIC_INSTANCE(\r
+    _filedev,\r
+    EXT4_IORAW_BSIZE,\r
+    0,\r
+    io_raw_open,\r
+    io_raw_bread,\r
+    io_raw_bwrite,\r
+    io_raw_close\r
+);\r
+\r
+/******************************************************************************/\r
+EXT4_BCACHE_STATIC_INSTANCE(__cache, 8, 1024);\r
+\r
+/******************************************************************************/\r
+static int io_raw_open(struct ext4_blockdev *bdev)\r
+{\r
+    char path[64];\r
+    DISK_GEOMETRY   pdg;\r
+    uint64_t disk_size;\r
+    BOOL bResult   = FALSE;\r
+    DWORD junk;\r
+\r
+    sprintf(path, "\\\\.\\%s", fname);\r
+\r
+    dev_file = CreateFile (path,\r
+            GENERIC_READ | GENERIC_WRITE,\r
+            FILE_SHARE_WRITE | FILE_SHARE_READ,\r
+            NULL,\r
+            OPEN_EXISTING,\r
+            0,\r
+            NULL);\r
+\r
+    if (dev_file == INVALID_HANDLE_VALUE){\r
+        return EIO;\r
+    }\r
+\r
+    bResult = DeviceIoControl(dev_file,\r
+            IOCTL_DISK_GET_DRIVE_GEOMETRY,\r
+            NULL, 0,\r
+            &pdg, sizeof(pdg),\r
+            &junk,\r
+            (LPOVERLAPPED) NULL);\r
+\r
+    if(bResult == FALSE){\r
+        CloseHandle(dev_file);\r
+        return EIO;\r
+    }\r
+\r
+\r
+    disk_size = pdg.Cylinders.QuadPart * (ULONG)pdg.TracksPerCylinder *\r
+            (ULONG)pdg.SectorsPerTrack * (ULONG)pdg.BytesPerSector;\r
+\r
+    _filedev.ph_bsize = pdg.BytesPerSector;\r
+    _filedev.ph_bcnt  = disk_size / pdg.BytesPerSector;\r
+\r
+\r
+    return EOK;\r
+}\r
+\r
+/******************************************************************************/\r
+\r
+static int io_raw_bread(struct  ext4_blockdev *bdev, void *buf, uint64_t blk_id,\r
+    uint32_t blk_cnt)\r
+{\r
+    long hipart = blk_id >> (32-9);\r
+    long lopart = blk_id << 9;\r
+    long err;\r
+\r
+    SetLastError (0);\r
+    lopart = SetFilePointer (dev_file, lopart, &hipart, FILE_BEGIN);\r
+\r
+    if (lopart == -1  &&  NO_ERROR != (err = GetLastError ()))\r
+    {\r
+        return EIO;\r
+    }\r
+\r
+    DWORD   n;\r
+\r
+    if (!ReadFile (dev_file, buf, blk_cnt * 512, &n, NULL))\r
+    {\r
+        err = GetLastError ();\r
+        return EIO;\r
+    }\r
+    return EOK;\r
+}\r
+\r
+/******************************************************************************/\r
+static int io_raw_bwrite(struct ext4_blockdev *bdev, const void *buf,\r
+    uint64_t blk_id, uint32_t blk_cnt)\r
+{\r
+    long hipart = blk_id >> (32-9);\r
+    long lopart = blk_id << 9;\r
+    long err;\r
+\r
+    SetLastError (0);\r
+    lopart = SetFilePointer (dev_file, lopart, &hipart, FILE_BEGIN);\r
+\r
+    if (lopart == -1  &&  NO_ERROR != (err = GetLastError ()))\r
+    {\r
+        return EIO;\r
+    }\r
+\r
+    DWORD   n;\r
+\r
+    if (!WriteFile (dev_file, buf, blk_cnt * 512, &n, NULL))\r
+    {\r
+        err = GetLastError ();\r
+        return EIO;\r
+    }\r
+    return EOK;\r
+}\r
+\r
+/******************************************************************************/\r
+static int io_raw_close(struct  ext4_blockdev *bdev)\r
+{\r
+    CloseHandle(dev_file);\r
+    return EOK;\r
+}\r
+\r
+\r
+/******************************************************************************/\r
+\r
+struct  ext4_bcache* ext4_io_raw_cache_get(void)\r
+{\r
+    return &__cache;\r
+}\r
+/******************************************************************************/\r
+struct  ext4_blockdev* ext4_io_raw_dev_get(void)\r
+{\r
+    return &_filedev;\r
+}\r
+/******************************************************************************/\r
+void ext4_io_raw_filename(const char *n)\r
+{\r
+    fname = n;\r
+}\r
+\r
+/******************************************************************************/\r
+#endif\r
+\r
diff --git a/blockdev/io_raw/io_raw.h b/blockdev/io_raw/io_raw.h
new file mode 100644 (file)
index 0000000..cf097aa
--- /dev/null
@@ -0,0 +1,46 @@
+/*\r
+ * Copyright (c) 2013 Grzegorz Kostka (kostka.grzegorz@gmail.com)\r
+ * All rights reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions\r
+ * are met:\r
+ *\r
+ * - Redistributions of source code must retain the above copyright\r
+ *   notice, this list of conditions and the following disclaimer.\r
+ * - Redistributions in binary form must reproduce the above copyright\r
+ *   notice, this list of conditions and the following disclaimer in the\r
+ *   documentation and/or other materials provided with the distribution.\r
+ * - The name of the author may not be used to endorse or promote products\r
+ *   derived from this software without specific prior written permission.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\r
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\r
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\r
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\r
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\r
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\r
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
+#ifndef IO_RAW_H_\r
+#define IO_RAW_H_\r
+\r
+#include <ext4_config.h>\r
+#include <ext4_blockdev.h>\r
+\r
+#include <stdint.h>\r
+#include <stdbool.h>\r
+\r
+\r
+/**@brief   IO raw get.*/\r
+struct  ext4_bcache*   ext4_io_raw_cache_get(void);\r
+\r
+/**@brief   IO raw blockdev get.*/\r
+struct  ext4_blockdev* ext4_io_raw_dev_get(void);\r
+\r
+void    ext4_io_raw_filename(const char *n);\r
+\r
+#endif /* IO_RAW_H_ */\r
index a4d8eca2e351f653a48b8883a31df991a19c80bd..c20283a674eec111612436c8e8bb607f88667bcd 100644 (file)
 #include <unistd.h>\r
 #include <getopt.h>\r
 #include <stdbool.h>\r
+#include <time.h>\r
 \r
 #include <ext4_filedev.h>\r
+#include <io_raw.h>\r
 #include <ext4.h>\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
+static int rw_szie  = 1024 * 1024;\r
 \r
 /**@brief      Read-write size*/\r
-static int rw_count = 10000;\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 = false;\r
+static bool cache_mode = true;\r
 \r
 /**@brief   Cleanup after test.*/\r
 static bool cleanup_flag = false;\r
@@ -59,6 +62,9 @@ static bool bstat = false;
 /**@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
 \r
@@ -75,14 +81,15 @@ static const char *usage = "                                                                        \n\
 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 = 10000)                         \n\\r
-       -cache  - 0 static, 1 dynamic  (default = 0)                \n\\r
-    -dirs   - directory test count (default = 10)               \n\\r
-    -clean  - clean up after test                               \n\\r
-    -bstat  - block device stats                                \n\\r
-    -sbstat - superblock stats                                  \n\\r
+    --i   - input file             (default = ext2)                            \n\\r
+    --rws - single R/W size        (default = 1024)                            \n\\r
+    --rwc - R/W count              (default = 10000)                   \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
 static char* entry_to_str(uint8_t type)\r
@@ -190,8 +197,6 @@ 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
@@ -201,6 +206,10 @@ static bool dir_test(int len)
     int       r;\r
     int       i;\r
     char path[64];\r
+    clock_t diff;\r
+    clock_t stop;\r
+    clock_t start;\r
+    start = clock() / (CLOCKS_PER_SEC / 1000);\r
 \r
     printf("Directory create: /mp/dir1\n");\r
     r = ext4_dir_mk("/mp/dir1");\r
@@ -220,54 +229,238 @@ static bool dir_test(int len)
         }\r
     }\r
 \r
+    stop = clock() / (CLOCKS_PER_SEC / 1000);\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
+\r
+static bool file_test(void)\r
+{\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
+\r
+    printf("ext4_fopen: test1\n");\r
+\r
+    start = clock() / (CLOCKS_PER_SEC / 1000);\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("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
+        if((r != EOK) || (size != rw_szie))\r
+            break;\r
+    }\r
+\r
+    if(i != rw_count){\r
+        printf("ERROR: rw_count = %d\n", i);\r
+        return false;\r
+    }\r
+\r
+    printf("OK\n");\r
+    stop = clock() / (CLOCKS_PER_SEC / 1000);\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 = clock() / (CLOCKS_PER_SEC / 1000);\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
+    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((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 = clock() / (CLOCKS_PER_SEC / 1000);\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
+    return true;\r
+\r
+}\r
 static void cleanup(void)\r
 {\r
+    clock_t start;\r
+    clock_t stop;\r
+    clock_t diff;\r
+\r
     ext4_fremove("/mp/hello.txt");\r
+\r
+    printf("cleanup: remove /mp/test1\n");\r
+    start = clock() / (CLOCKS_PER_SEC / 1000);\r
     ext4_fremove("/mp/test1");\r
+    stop = clock() / (CLOCKS_PER_SEC / 1000);\r
+    diff = stop - start;\r
+    printf("cleanup: time: %d ms\n", (int)diff);\r
+\r
+\r
+    printf("cleanup: remove /mp/test1\n");\r
+    start = clock() / (CLOCKS_PER_SEC / 1000);\r
     ext4_dir_rm("/mp/dir1");\r
+    stop = clock() / (CLOCKS_PER_SEC / 1000);\r
+    diff = stop - start;\r
+    printf("cleanup: time: %d ms\n", (int)diff);\r
 }\r
 \r
-int main(int argc, char **argv)\r
+static bool open_filedev(void)\r
+{\r
+    ext4_filedev_filename(input_name);\r
+    bd = ext4_filedev_get();\r
+    bc = ext4_filecache_get();\r
+    if(!bd || !bc){\r
+        printf("Block device ERROR\n");\r
+        return false;\r
+    }\r
+    return true;\r
+}\r
+\r
+static bool open_winpartition(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
+#ifdef WIN32\r
+    ext4_io_raw_filename(input_name);\r
+    bd = ext4_io_raw_dev_get();\r
+    bc = ext4_io_raw_cache_get();\r
+    if(!bd || !bc){\r
+        printf("Block device ERROR\n");\r
+        return false;\r
+    }\r
+    return true;\r
+#else\r
+    printf("open_winpartition: this mode shouls be used only under windows !\n");\r
+    return false;\r
+#endif\r
+}\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
+    }\r
+    wr_buff = malloc(rw_szie);\r
+    rd_buff = malloc(rw_szie);\r
+\r
+    if(!wr_buff || !rd_buff){\r
+        printf("Read-Write allocation ERROR\n");\r
+        return EXIT_FAILURE;\r
+    }\r
+\r
+    ext4_dmask_set(EXT4_DEBUG_ALL);\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 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
+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
     static struct option long_options[] =\r
       {\r
-        {"in",         required_argument, 0, 'a'},\r
+        {"in",      required_argument, 0, 'a'},\r
         {"rws",     required_argument, 0, 'b'},\r
-        {"rwc",                required_argument, 0, 'c'},\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:fgh", 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
+    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
@@ -280,12 +473,22 @@ int main(int argc, char **argv)
             case 'h':\r
                 sbstat = true;\r
                 break;\r
-               default:\r
-                       printf(usage);\r
-                       return EXIT_FAILURE;\r
+            case 'i':\r
+                winpart = true;\r
+                break;\r
+            default:\r
+                printf(usage);\r
+                return false;\r
 \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
@@ -293,125 +496,40 @@ int main(int argc, char **argv)
     printf("RW count: %d\n", rw_count);\r
     printf("Cache mode: %s\n", cache_mode ? "dynamic" : "static");\r
 \r
+    if(!mount())\r
+        return EXIT_FAILURE;\r
 \r
 \r
-    ext4_filedev_filename(input_name);\r
-\r
-    wr_buff = malloc(rw_szie);\r
-    rd_buff = malloc(rw_szie);\r
-\r
-    if(!wr_buff || !rd_buff){\r
-       printf("Read-Write allocation ERROR\n");\r
-       return EXIT_FAILURE;\r
-    }\r
-\r
-       bd = ext4_filedev_get();\r
-       bc = ext4_filecache_get();\r
-\r
-    if(!bd || !bc){\r
-       printf("Block device ERROR\n");\r
-       return EXIT_FAILURE;\r
-    }\r
-\r
-       ext4_dmask_set(EXT4_DEBUG_ALL);\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
-       r = ext4_mount("ext4_filesim", "/mp/");\r
-       if(r != EOK){\r
-               printf("ext4_mount ERROR = %d\n", r);\r
-               return EXIT_FAILURE;\r
-       }\r
-\r
-       cleanup();\r
+    cleanup();\r
 \r
     if(sbstat)\r
         mp_stats();\r
 \r
-\r
     dir_ls("/mp/");\r
-       dir_test(dir_cnt);\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
-\r
-\r
-       printf("ext4_fopen: test1\n");\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
-\r
-       printf("ext4_write: %d * %d ..." , rw_count, rw_szie);\r
+    fflush(stdout);\r
+    if(!dir_test(dir_cnt))\r
+           return EXIT_FAILURE;\r
 \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
-               if((r != EOK) || (size != 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
-\r
-       printf("OK\n");\r
-       r = ext4_fclose(&f);\r
-       printf("ext4_fopen: test1\n");\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
-\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((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 EXIT_FAILURE;\r
-       }\r
-\r
-       printf("OK\n");\r
-       r = ext4_fclose(&f);\r
+    fflush(stdout);\r
+       if(!file_test())\r
+           return EXIT_FAILURE;\r
 \r
+       fflush(stdout);\r
        dir_ls("/mp/");\r
 \r
        if(sbstat)\r
            mp_stats();\r
 \r
-\r
        if(cleanup_flag)\r
            cleanup();\r
 \r
     if(bstat)\r
         block_stats();\r
 \r
-       r = ext4_umount("/mp/");\r
-       printf("Test finish: OK\n");\r
+    if(!umount())\r
+        return EXIT_FAILURE;\r
+\r
+    printf("Test finish: OK\n");\r
     return EXIT_SUCCESS;\r
 \r
 }\r
index 5136fde2269e292f1fa8346687f7a28ca2cd76e0..0e62d9899f22fdef4303b845b0db5e979fe04a14 100644 (file)
@@ -793,10 +793,13 @@ int       ext4_fread (ext4_file *f, void *buf, uint32_t size, uint32_t *rcnt)
     int                 r = EOK;\r
     uint32_t u;\r
     uint32_t fblock;\r
+    uint32_t fblock_start;\r
+    uint32_t fblock_cnt;\r
     struct ext4_block b;\r
     uint8_t    *u8_buf = buf;\r
     struct ext4_inode_ref ref;\r
     uint32_t sblock;\r
+    uint32_t sblock_end;\r
     uint32_t block_size;\r
 \r
     ext4_assert(f && f->mp);\r
@@ -824,9 +827,8 @@ int ext4_fread (ext4_file *f, void *buf, uint32_t size, uint32_t *rcnt)
 \r
     block_size = ext4_sb_get_block_size(&f->mp->fs.sb);\r
     size = size > (f->fsize - f->fpos) ? (f->fsize - f->fpos) : size;\r
-\r
     sblock     = (f->fpos) / block_size;\r
-\r
+    sblock_end = (f->fpos + size) / block_size;\r
     u = (f->fpos) % block_size;\r
 \r
 \r
@@ -858,25 +860,39 @@ int       ext4_fread (ext4_file *f, void *buf, uint32_t size, uint32_t *rcnt)
         sblock++;\r
     }\r
 \r
+    fblock_start = 0;\r
+    fblock_cnt = 0;\r
     while(size >= block_size){\r
+        while(sblock < sblock_end){\r
+            r = ext4_fs_get_inode_data_block_index(&ref, sblock, &fblock);\r
+            if(r != EOK)\r
+                goto Finish;\r
 \r
-        r = ext4_fs_get_inode_data_block_index(&ref, sblock, &fblock);\r
-        if(r != EOK)\r
-            goto Finish;\r
+            sblock++;\r
+\r
+            if(!fblock_start){\r
+                fblock_start = fblock;\r
+            }\r
+\r
+            if((fblock_start + fblock_cnt) != fblock)\r
+                break;\r
+\r
+            fblock_cnt++;\r
+        }\r
 \r
-        r = ext4_block_get_direct(f->mp->fs.bdev, u8_buf, fblock);\r
+        r = ext4_blocks_get_direct(f->mp->fs.bdev, u8_buf, fblock_start, fblock_cnt);\r
         if(r != EOK)\r
             goto Finish;\r
 \r
-\r
-        u8_buf  += block_size;\r
-        size    -= block_size;\r
-        f->fpos += block_size;\r
+        size    -= block_size * fblock_cnt;\r
+        u8_buf  += block_size * fblock_cnt;\r
+        f->fpos += block_size * fblock_cnt;\r
 \r
         if(rcnt)\r
-            *rcnt += block_size;\r
+            *rcnt += block_size * fblock_cnt;\r
 \r
-        sblock++;\r
+        fblock_start = fblock;\r
+        fblock_cnt = 1;\r
     }\r
 \r
     if(size){\r
@@ -915,8 +931,11 @@ int        ext4_fwrite(ext4_file *f, void *buf, uint32_t size, uint32_t *wcnt)
     uint8_t    *u8_buf = buf;\r
     struct ext4_inode_ref ref;\r
     uint32_t sblock;\r
+    uint32_t sblock_end;\r
     uint32_t file_blocks;\r
     uint32_t block_size;\r
+    uint32_t fblock_start;\r
+    uint32_t fblock_cnt;\r
 \r
     ext4_assert(f && f->mp);\r
 \r
@@ -942,6 +961,8 @@ int ext4_fwrite(ext4_file *f, void *buf, uint32_t size, uint32_t *wcnt)
 \r
     block_size = ext4_sb_get_block_size(&f->mp->fs.sb);\r
 \r
+    sblock_end = (f->fpos + size) > f->fsize ? (f->fpos + size) : f->fsize;\r
+    sblock_end /= block_size;\r
     file_blocks = (f->fsize / block_size);\r
 \r
     if(f->fsize % block_size)\r
@@ -986,31 +1007,47 @@ int      ext4_fwrite(ext4_file *f, void *buf, uint32_t size, uint32_t *wcnt)
     if(r != EOK)\r
         goto Finish;\r
 \r
+    fblock_start = 0;\r
+    fblock_cnt = 0;\r
     while(size >= block_size){\r
 \r
-        if(sblock < file_blocks){\r
-            r = ext4_fs_get_inode_data_block_index(&ref, sblock, &fblock);\r
-            if(r != EOK)\r
-                break;\r
-        }\r
-        else {\r
-            r = ext4_fs_append_inode_block(&ref, &fblock, &sblock);\r
-            if(r != EOK)\r
+        while(sblock < sblock_end){\r
+            if(sblock < file_blocks){\r
+                r = ext4_fs_get_inode_data_block_index(&ref, sblock, &fblock);\r
+                if(r != EOK)\r
+                    break;\r
+            }\r
+            else {\r
+                r = ext4_fs_append_inode_block(&ref, &fblock, &sblock);\r
+                if(r != EOK)\r
+                    break;\r
+            }\r
+\r
+            sblock++;\r
+\r
+            if(!fblock_start){\r
+                fblock_start = fblock;\r
+            }\r
+\r
+            if((fblock_start + fblock_cnt) != fblock)\r
                 break;\r
+\r
+            fblock_cnt++;\r
         }\r
 \r
-        r = ext4_block_set_direct(f->mp->fs.bdev, u8_buf, fblock);\r
+        r = ext4_blocks_set_direct(f->mp->fs.bdev, u8_buf, fblock_start, fblock_cnt);\r
         if(r != EOK)\r
             break;\r
 \r
-        u8_buf  += block_size;\r
-        size    -= block_size;\r
-        f->fpos += block_size;\r
+        size    -= block_size * fblock_cnt;\r
+        u8_buf  += block_size * fblock_cnt;\r
+        f->fpos += block_size * fblock_cnt;\r
 \r
         if(wcnt)\r
-            *wcnt += block_size;\r
+            *wcnt += block_size * fblock_cnt;\r
 \r
-        sblock++;\r
+        fblock_start = fblock;\r
+        fblock_cnt = 1;\r
     }\r
 \r
     /*Stop delay cache flush mode*/\r
index ec35c376c37a6f6e0c62eb4abb5621935effefbb..a6c7323fbc88cc8fb77d46d0606f695e2887f502 100644 (file)
@@ -53,7 +53,7 @@ int   ext4_block_init(struct  ext4_blockdev *bdev)
 
     /*Low level block init*/
     rc = bdev->open(bdev);
-    if(EOK != rc)
+    if(rc != EOK)
         return rc;
 
     bdev->flags |= EXT4_BDEV_INITIALIZED;
@@ -120,9 +120,9 @@ int ext4_block_get(struct   ext4_blockdev *bdev, struct     ext4_block *b,
                 continue;
 
             /*Buffer free was delayed and have no reference. Flush it.*/
-            r = ext4_block_set_direct(bdev,
+            r = ext4_blocks_set_direct(bdev,
                     bdev->bc->data + bdev->bc->itemsize * i,
-                    bdev->bc->lba[i]);
+                    bdev->bc->lba[i], 1);
             if(r != EOK)
                 return r;
 
@@ -207,8 +207,8 @@ int ext4_block_set(struct   ext4_blockdev *bdev, struct     ext4_block *b)
     return EOK;
 }
 
-int ext4_block_get_direct(struct       ext4_blockdev *bdev, void *buf,
-    uint64_t lba)
+int ext4_blocks_get_direct(struct      ext4_blockdev *bdev, void *buf,
+    uint64_t lba, uint32_t cnt)
 {
     uint64_t pba;
     uint32_t pb_cnt;
@@ -220,13 +220,13 @@ int ext4_block_get_direct(struct  ext4_blockdev *bdev, void *buf,
 
     bdev->bread_ctr++;
 
-    return bdev->bread(bdev, buf, pba, pb_cnt);
+    return bdev->bread(bdev, buf, pba, pb_cnt * cnt);
 }
 
 
 
-int ext4_block_set_direct(struct       ext4_blockdev *bdev, const void *buf,
-    uint64_t lba)
+int ext4_blocks_set_direct(struct      ext4_blockdev *bdev, const void *buf,
+    uint64_t lba, uint32_t cnt)
 {
     uint64_t pba;
     uint32_t pb_cnt;
@@ -238,7 +238,7 @@ int ext4_block_set_direct(struct    ext4_blockdev *bdev, const void *buf,
 
     bdev->bwrite_ctr++;
 
-    return bdev->bwrite(bdev, buf, pba, pb_cnt);
+    return bdev->bwrite(bdev, buf, pba, pb_cnt * cnt);
 }
 
 
@@ -424,9 +424,9 @@ int         ext4_block_delay_cache_flush(struct     ext4_blockdev *bdev,
                 continue;
 
             /*Buffer free was delayed and have no reference. Flush it.*/
-            r = ext4_block_set_direct(bdev,
+            r = ext4_blocks_set_direct(bdev,
                     bdev->bc->data + bdev->bc->itemsize * i,
-                    bdev->bc->lba[i]);
+                    bdev->bc->lba[i], 1);
             if(r != EOK)
                 return r;
 
index 289a879e082f016b4582edf3c3d83c5005773bf6..28f2a9b2e8f67043b8f206d8e9b85b588c7115f3 100644 (file)
@@ -164,8 +164,8 @@ int ext4_block_set(struct   ext4_blockdev *bdev, struct     ext4_block *b);
  * @param      buf output buffer
  * @param      lba logical block adderss
  * @return     standard error code*/
-int ext4_block_get_direct(struct       ext4_blockdev *bdev, void *buf,
-    uint64_t lba);
+int ext4_blocks_get_direct(struct   ext4_blockdev *bdev, void *buf,
+    uint64_t lba, uint32_t cnt);
 
 
 /**@brief      Block write procedure (without cache)
@@ -173,8 +173,8 @@ int ext4_block_get_direct(struct    ext4_blockdev *bdev, void *buf,
  * @param      buf output buffer
  * @param      lba logical block address
  * @return     standard error code*/
-int ext4_block_set_direct(struct       ext4_blockdev *bdev, const void *buf,
-    uint64_t lba);
+int ext4_blocks_set_direct(struct      ext4_blockdev *bdev, const void *buf,
+    uint64_t lba, uint32_t cnt);
 
 /**@brief      Write to block device (by direct adress).
  * @param      bdev block device descriptor
index c06f43dc8eb0e0a7c09e3a8a7efb3fd2df922fa3..7bfd3e65112fad0f617165159578f1419945208b 100644 (file)
@@ -267,7 +267,7 @@ int ext4_fs_check_features(struct ext4_fs *fs, bool *read_only)
         return EOK;
     }
     ext4_dprintf(EXT4_DEBUG_FS,
-        "\nSblock rev_level: \n%d\n", ext4_get32(&fs->sb, rev_level) );
+        "\nSblock rev_level: \n%d\n", (int)ext4_get32(&fs->sb, rev_level));
 
     ext4_dprintf(EXT4_DEBUG_FS,
         "\nSblock minor_rev_level: \n%d\n",