ref: c109281525bd972c75050db10980fe42ffdc80b7
parent: 5aa75f97a60f95b53a11caf31044363434227f07
author: gkostka <kostka.grzegorz@gmail.com>
date: Sun Oct 27 07:48:48 EDT 2013
FEATURES: 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).
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -25,9 +25,13 @@
else()
#Generic example target
include_directories(blockdev/filedev)
+include_directories(blockdev/io_raw)
+
aux_source_directory(blockdev/filedev FILEDEV_SRC)
+aux_source_directory(blockdev/io_raw IORAW_SRC)
aux_source_directory(demos/generic GENERIC_SRC)
-add_executable(fileimage_demo ${GENERIC_SRC} ${FILEDEV_SRC})
+
+add_executable(fileimage_demo ${GENERIC_SRC} ${FILEDEV_SRC} ${IORAW_SRC})
target_link_libraries(fileimage_demo lwext4)
add_custom_target(size ALL DEPENDS lwext4 COMMAND size -B liblwext4.a)
endif()
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,10 @@
-all: generic bf518 cortex-m3 cortex-m4 generic
-
+generic:
+ rm -R -f build_generic
+ mkdir build_generic
+ cd build_generic && cmake -G"Unix Makefiles" ../
+ cd build_generic && make
+
bf518:
rm -R -f build_bf518
mkdir build_bf518
@@ -18,14 +22,10 @@
mkdir build_cortex-m4
cd build_cortex-m4 && cmake -G"Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE=../toolchain/cortex-m4.cmake ..
cd build_cortex-m4 && make
-
-
-generic:
- rm -R -f build_generic
- mkdir build_generic
- cd build_generic && cmake -G"Unix Makefiles" ../
- cd build_generic && make
-
+
+all: generic bf518 cortex-m3 cortex-m4 generic
+
+
clean:
rm -R -f build_bf518
--- a/blockdev/filedev/ext4_filedev.c
+++ b/blockdev/filedev/ext4_filedev.c
@@ -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 @@
dev_file = fopen(fname, "r+b");
if(!dev_file)
- return ENOENT;
+ return EIO;
if(fseek(dev_file, 0, SEEK_END))
return EFAULT;
--- /dev/null
+++ b/blockdev/io_raw/io_raw.c
@@ -1,0 +1,202 @@
+/*
+ * Copyright (c) 2013 Grzegorz Kostka (kostka.grzegorz@gmail.com)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <ext4_config.h>
+#include <ext4_blockdev.h>
+#include <ext4_errno.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <string.h>
+
+#ifdef WIN32
+#include <windows.h>
+#include <winioctl.h>
+
+
+/**@brief Default filename.*/
+static const char *fname = "ext2";
+
+/**@brief IO block size.*/
+#define EXT4_IORAW_BSIZE 512
+
+/**@brief Image file descriptor.*/
+static HANDLE dev_file;
+
+
+/**********************BLOCKDEV INTERFACE**************************************/
+static int io_raw_open(struct ext4_blockdev *bdev);
+static int io_raw_bread(struct ext4_blockdev *bdev, void *buf, uint64_t blk_id,
+ uint32_t blk_cnt);
+static int io_raw_bwrite(struct ext4_blockdev *bdev, const void *buf,
+ uint64_t blk_id, uint32_t blk_cnt);
+static int io_raw_close(struct ext4_blockdev *bdev);
+
+
+
+
+/******************************************************************************/
+EXT4_BLOCKDEV_STATIC_INSTANCE(
+ _filedev,
+ EXT4_IORAW_BSIZE,
+ 0,
+ io_raw_open,
+ io_raw_bread,
+ io_raw_bwrite,
+ io_raw_close
+);
+
+/******************************************************************************/
+EXT4_BCACHE_STATIC_INSTANCE(__cache, 8, 1024);
+
+/******************************************************************************/
+static int io_raw_open(struct ext4_blockdev *bdev)
+{
+ char path[64];
+ DISK_GEOMETRY pdg;
+ uint64_t disk_size;
+ BOOL bResult = FALSE;
+ DWORD junk;
+
+ sprintf(path, "\\\\.\\%s", fname);
+
+ dev_file = CreateFile (path,
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_WRITE | FILE_SHARE_READ,
+ NULL,
+ OPEN_EXISTING,
+ 0,
+ NULL);
+
+ if (dev_file == INVALID_HANDLE_VALUE){
+ return EIO;
+ }
+
+ bResult = DeviceIoControl(dev_file,
+ IOCTL_DISK_GET_DRIVE_GEOMETRY,
+ NULL, 0,
+ &pdg, sizeof(pdg),
+ &junk,
+ (LPOVERLAPPED) NULL);
+
+ if(bResult == FALSE){
+ CloseHandle(dev_file);
+ return EIO;
+ }
+
+
+ disk_size = pdg.Cylinders.QuadPart * (ULONG)pdg.TracksPerCylinder *
+ (ULONG)pdg.SectorsPerTrack * (ULONG)pdg.BytesPerSector;
+
+ _filedev.ph_bsize = pdg.BytesPerSector;
+ _filedev.ph_bcnt = disk_size / pdg.BytesPerSector;
+
+
+ return EOK;
+}
+
+/******************************************************************************/
+
+static int io_raw_bread(struct ext4_blockdev *bdev, void *buf, uint64_t blk_id,
+ uint32_t blk_cnt)
+{
+ long hipart = blk_id >> (32-9);
+ long lopart = blk_id << 9;
+ long err;
+
+ SetLastError (0);
+ lopart = SetFilePointer (dev_file, lopart, &hipart, FILE_BEGIN);
+
+ if (lopart == -1 && NO_ERROR != (err = GetLastError ()))
+ {
+ return EIO;
+ }
+
+ DWORD n;
+
+ if (!ReadFile (dev_file, buf, blk_cnt * 512, &n, NULL))
+ {
+ err = GetLastError ();
+ return EIO;
+ }
+ return EOK;
+}
+
+/******************************************************************************/
+static int io_raw_bwrite(struct ext4_blockdev *bdev, const void *buf,
+ uint64_t blk_id, uint32_t blk_cnt)
+{
+ long hipart = blk_id >> (32-9);
+ long lopart = blk_id << 9;
+ long err;
+
+ SetLastError (0);
+ lopart = SetFilePointer (dev_file, lopart, &hipart, FILE_BEGIN);
+
+ if (lopart == -1 && NO_ERROR != (err = GetLastError ()))
+ {
+ return EIO;
+ }
+
+ DWORD n;
+
+ if (!WriteFile (dev_file, buf, blk_cnt * 512, &n, NULL))
+ {
+ err = GetLastError ();
+ return EIO;
+ }
+ return EOK;
+}
+
+/******************************************************************************/
+static int io_raw_close(struct ext4_blockdev *bdev)
+{
+ CloseHandle(dev_file);
+ return EOK;
+}
+
+
+/******************************************************************************/
+
+struct ext4_bcache* ext4_io_raw_cache_get(void)
+{
+ return &__cache;
+}
+/******************************************************************************/
+struct ext4_blockdev* ext4_io_raw_dev_get(void)
+{
+ return &_filedev;
+}
+/******************************************************************************/
+void ext4_io_raw_filename(const char *n)
+{
+ fname = n;
+}
+
+/******************************************************************************/
+#endif
+
--- /dev/null
+++ b/blockdev/io_raw/io_raw.h
@@ -1,0 +1,46 @@
+/*
+ * Copyright (c) 2013 Grzegorz Kostka (kostka.grzegorz@gmail.com)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef IO_RAW_H_
+#define IO_RAW_H_
+
+#include <ext4_config.h>
+#include <ext4_blockdev.h>
+
+#include <stdint.h>
+#include <stdbool.h>
+
+
+/**@brief IO raw get.*/
+struct ext4_bcache* ext4_io_raw_cache_get(void);
+
+/**@brief IO raw blockdev get.*/
+struct ext4_blockdev* ext4_io_raw_dev_get(void);
+
+void ext4_io_raw_filename(const char *n);
+
+#endif /* IO_RAW_H_ */
--- a/demos/generic/main.c
+++ b/demos/generic/main.c
@@ -32,23 +32,26 @@
#include <unistd.h>
#include <getopt.h>
#include <stdbool.h>
+#include <time.h>
#include <ext4_filedev.h>
+#include <io_raw.h>
#include <ext4.h>
+/**@brief Input stream name.*/
char input_name[128] = "ext2";
/**@brief Read-write size*/
-static int rw_szie = 1024;
+static int rw_szie = 1024 * 1024;
/**@brief Read-write size*/
-static int rw_count = 10000;
+static int rw_count = 10;
/**@brief Directory test count*/
-static int dir_cnt = 10;
+static int dir_cnt = 0;
/**@brief Static or dynamic cache mode*/
-static bool cache_mode = false;
+static bool cache_mode = true;
/**@brief Cleanup after test.*/
static bool cleanup_flag = false;
@@ -59,6 +62,9 @@
/**@brief Superblock stats.*/
static bool sbstat = false;
+/**@brief Indicates that input is windows partition.*/
+static bool winpart = false;
+
/**@brief File write buffer*/
static uint8_t *wr_buff;
@@ -75,14 +81,15 @@
Welcome in ext4 generic demo. \n\
Copyright (c) 2013 Grzegorz Kostka (kostka.grzegorz@gmail.com) \n\
Usage: \n\
- -i - input file (default = ext2) \n\
- -rws - single R/W size (default = 1024) \n\
- -rwc - R/W count (default = 10000) \n\
- -cache - 0 static, 1 dynamic (default = 0) \n\
- -dirs - directory test count (default = 10) \n\
- -clean - clean up after test \n\
- -bstat - block device stats \n\
- -sbstat - superblock stats \n\
+ --i - input file (default = ext2) \n\
+ --rws - single R/W size (default = 1024) \n\
+ --rwc - R/W count (default = 10000) \n\
+ --cache - 0 static, 1 dynamic (default = 1) \n\
+ --dirs - directory test count (default = 0) \n\
+ --clean - clean up after test \n\
+ --bstat - block device stats \n\
+ --sbstat - superblock stats \n\
+ --wpart - windows partition mode \n\
\n";
static char* entry_to_str(uint8_t type)
@@ -190,8 +197,6 @@
printf("bcache->lba[%d] = %u\n", i, (uint32_t)bc->lba[i]);
}
-
-
printf("**********************************************\n");
}
@@ -201,6 +206,10 @@
int r;
int i;
char path[64];
+ clock_t diff;
+ clock_t stop;
+ clock_t start;
+ start = clock() / (CLOCKS_PER_SEC / 1000);
printf("Directory create: /mp/dir1\n");
r = ext4_dir_mk("/mp/dir1");
@@ -220,54 +229,238 @@
}
}
+ stop = clock() / (CLOCKS_PER_SEC / 1000);
+ diff = stop - start;
dir_ls("/mp/dir1");
+ printf("dir_test time: %d ms\n", (int)diff);
return true;
}
+
+static bool file_test(void)
+{
+ int r;
+ uint32_t size;
+ ext4_file f;
+ int i;
+ clock_t start;
+ clock_t stop;
+ clock_t diff;
+ uint32_t kbps;
+ uint64_t size_bytes;
+ /*Add hello world file.*/
+ r = ext4_fopen(&f, "/mp/hello.txt", "wb");
+ r = ext4_fwrite(&f, "Hello World !\n", strlen("Hello World !\n"), 0);
+ r = ext4_fclose(&f);
+
+
+ printf("ext4_fopen: test1\n");
+
+ start = clock() / (CLOCKS_PER_SEC / 1000);
+ r = ext4_fopen(&f, "/mp/test1", "wb");
+ if(r != EOK){
+ printf("ext4_fopen ERROR = %d\n", r);
+ return false;
+ }
+
+ printf("ext4_write: %d * %d ..." , rw_szie, rw_count);
+ for (i = 0; i < rw_count; ++i) {
+
+ memset(wr_buff, i % 10 + '0', rw_szie);
+
+ r = ext4_fwrite(&f, wr_buff, rw_szie, &size);
+
+ if((r != EOK) || (size != rw_szie))
+ break;
+ }
+
+ if(i != rw_count){
+ printf("ERROR: rw_count = %d\n", i);
+ return false;
+ }
+
+ printf("OK\n");
+ stop = clock() / (CLOCKS_PER_SEC / 1000);
+ diff = stop - start;
+ size_bytes = rw_szie * rw_count;
+ size_bytes = (size_bytes * 1000) / 1024;
+ kbps = (size_bytes) / (diff + 1);
+ printf("file_test write time: %d ms\n", (int)diff);
+ printf("file_test write speed: %d KB/s\n", kbps);
+ r = ext4_fclose(&f);
+ printf("ext4_fopen: test1\n");
+
+
+ start = clock() / (CLOCKS_PER_SEC / 1000);
+ r = ext4_fopen(&f, "/mp/test1", "r+");
+ if(r != EOK){
+ printf("ext4_fopen ERROR = %d\n", r);
+ return false;
+ }
+
+ printf("ext4_read: %d * %d ..." , rw_szie, rw_count);
+
+ for (i = 0; i < rw_count; ++i) {
+ memset(wr_buff, i % 10 + '0', rw_szie);
+ r = ext4_fread(&f, rd_buff, rw_szie, &size);
+
+ if((r != EOK) || (size != rw_szie))
+ break;
+
+ if(memcmp(rd_buff, wr_buff, rw_szie)){
+ break;
+ }
+ }
+ if(i != rw_count){
+ printf("ERROR: rw_count = %d\n", i);
+ return false;
+ }
+ printf("OK\n");
+ stop = clock() / (CLOCKS_PER_SEC / 1000);
+ diff = stop - start;
+ size_bytes = rw_szie * rw_count;
+ size_bytes = (size_bytes * 1000) / 1024;
+ kbps = (size_bytes) / (diff + 1);
+ printf("file_test read time: %d ms\n", (int)diff);
+ printf("file_test read speed: %d KB/s\n", kbps);
+ r = ext4_fclose(&f);
+
+ return true;
+
+}
static void cleanup(void)
{
+ clock_t start;
+ clock_t stop;
+ clock_t diff;
+
ext4_fremove("/mp/hello.txt");
+
+ printf("cleanup: remove /mp/test1\n");
+ start = clock() / (CLOCKS_PER_SEC / 1000);
ext4_fremove("/mp/test1");
+ stop = clock() / (CLOCKS_PER_SEC / 1000);
+ diff = stop - start;
+ printf("cleanup: time: %d ms\n", (int)diff);
+
+
+ printf("cleanup: remove /mp/test1\n");
+ start = clock() / (CLOCKS_PER_SEC / 1000);
ext4_dir_rm("/mp/dir1");
+ stop = clock() / (CLOCKS_PER_SEC / 1000);
+ diff = stop - start;
+ printf("cleanup: time: %d ms\n", (int)diff);
}
-int main(int argc, char **argv)
+static bool open_filedev(void)
{
- int option_index = 0;
- int c;
- int r;
- int i;
- uint32_t size;
- ext4_file f;
+ ext4_filedev_filename(input_name);
+ bd = ext4_filedev_get();
+ bc = ext4_filecache_get();
+ if(!bd || !bc){
+ printf("Block device ERROR\n");
+ return false;
+ }
+ return true;
+}
+static bool open_winpartition(void)
+{
+#ifdef WIN32
+ ext4_io_raw_filename(input_name);
+ bd = ext4_io_raw_dev_get();
+ bc = ext4_io_raw_cache_get();
+ if(!bd || !bc){
+ printf("Block device ERROR\n");
+ return false;
+ }
+ return true;
+#else
+ printf("open_winpartition: this mode shouls be used only under windows !\n");
+ return false;
+#endif
+}
+
+static bool mount(void)
+{
+ int r;
+ if(winpart){
+ if(!open_winpartition())
+ return false;
+ }else{
+ if(!open_filedev())
+ return false;
+
+ }
+ wr_buff = malloc(rw_szie);
+ rd_buff = malloc(rw_szie);
+
+ if(!wr_buff || !rd_buff){
+ printf("Read-Write allocation ERROR\n");
+ return EXIT_FAILURE;
+ }
+
+ ext4_dmask_set(EXT4_DEBUG_ALL);
+
+ r = ext4_device_register(bd, cache_mode ? 0 : bc, "ext4_filesim");
+ if(r != EOK){
+ printf("ext4_device_register ERROR = %d\n", r);
+ return false;
+ }
+
+ r = ext4_mount("ext4_filesim", "/mp/");
+ if(r != EOK){
+ printf("ext4_mount ERROR = %d\n", r);
+ return false;
+ }
+
+ return true;
+}
+
+static bool umount(void)
+{
+ int r = ext4_umount("/mp/");
+ if(r != EOK){
+ printf("ext4_umount: FAIL %d", r);
+ return false;
+ }
+ return true;
+}
+
+static bool parse_opt(int argc, char **argv)
+{
+ int option_index = 0;
+ int c;
+
static struct option long_options[] =
{
- {"in", required_argument, 0, 'a'},
+ {"in", required_argument, 0, 'a'},
{"rws", required_argument, 0, 'b'},
- {"rwc", required_argument, 0, 'c'},
+ {"rwc", required_argument, 0, 'c'},
{"cache", required_argument, 0, 'd'},
{"dirs", required_argument, 0, 'e'},
{"clean", no_argument, 0, 'f'},
{"bstat", no_argument, 0, 'g'},
{"sbstat", no_argument, 0, 'h'},
+ {"wpart", no_argument, 0, 'i'},
{0, 0, 0, 0}
};
- while(-1 != (c = getopt_long (argc, argv, "a:b:c:d:e:fgh", long_options, &option_index))) {
+ while(-1 != (c = getopt_long (argc, argv, "a:b:c:d:e:fghi", long_options, &option_index))) {
- switch(c){
- case 'a':
- strcpy(input_name, optarg);
- break;
- case 'b':
- rw_szie = atoi(optarg);
- break;
- case 'c':
- rw_count = atoi(optarg);
- break;
- case 'd':
- cache_mode = atoi(optarg);
- break;
+ switch(c){
+ case 'a':
+ strcpy(input_name, optarg);
+ break;
+ case 'b':
+ rw_szie = atoi(optarg);
+ break;
+ case 'c':
+ rw_count = atoi(optarg);
+ break;
+ case 'd':
+ cache_mode = atoi(optarg);
+ break;
case 'e':
dir_cnt = atoi(optarg);
break;
@@ -280,13 +473,23 @@
case 'h':
sbstat = true;
break;
- default:
- printf(usage);
- return EXIT_FAILURE;
+ case 'i':
+ winpart = true;
+ break;
+ default:
+ printf(usage);
+ return false;
- }
+ }
}
+ return true;
+}
+int main(int argc, char **argv)
+{
+ if(!parse_opt(argc, argv))
+ return EXIT_FAILURE;
+
printf("Test conditions:\n");
printf("Imput name: %s\n", input_name);
printf("RW size: %d\n", rw_szie);
@@ -293,117 +496,30 @@
printf("RW count: %d\n", rw_count);
printf("Cache mode: %s\n", cache_mode ? "dynamic" : "static");
+ if(!mount())
+ return EXIT_FAILURE;
- ext4_filedev_filename(input_name);
+ cleanup();
- wr_buff = malloc(rw_szie);
- rd_buff = malloc(rw_szie);
-
- if(!wr_buff || !rd_buff){
- printf("Read-Write allocation ERROR\n");
- return EXIT_FAILURE;
- }
-
- bd = ext4_filedev_get();
- bc = ext4_filecache_get();
-
- if(!bd || !bc){
- printf("Block device ERROR\n");
- return EXIT_FAILURE;
- }
-
- ext4_dmask_set(EXT4_DEBUG_ALL);
-
- r = ext4_device_register(bd, cache_mode ? 0 : bc, "ext4_filesim");
- if(r != EOK){
- printf("ext4_device_register ERROR = %d\n", r);
- return EXIT_FAILURE;
- }
-
- r = ext4_mount("ext4_filesim", "/mp/");
- if(r != EOK){
- printf("ext4_mount ERROR = %d\n", r);
- return EXIT_FAILURE;
- }
-
- cleanup();
-
if(sbstat)
mp_stats();
-
dir_ls("/mp/");
- dir_test(dir_cnt);
+ fflush(stdout);
+ if(!dir_test(dir_cnt))
+ return EXIT_FAILURE;
- /*Add hello world file.*/
- r = ext4_fopen(&f, "/mp/hello.txt", "wb");
- r = ext4_fwrite(&f, "Hello World !\n", strlen("Hello World !\n"), 0);
- r = ext4_fclose(&f);
+ fflush(stdout);
+ if(!file_test())
+ return EXIT_FAILURE;
-
- printf("ext4_fopen: test1\n");
-
- r = ext4_fopen(&f, "/mp/test1", "wb");
- if(r != EOK){
- printf("ext4_fopen ERROR = %d\n", r);
- return EXIT_FAILURE;
- }
-
- printf("ext4_write: %d * %d ..." , rw_count, rw_szie);
-
- for (i = 0; i < rw_count; ++i) {
-
- memset(wr_buff, i % 10 + '0', rw_szie);
-
- r = ext4_fwrite(&f, wr_buff, rw_szie, &size);
-
- if((r != EOK) || (size != rw_szie))
- break;
- }
-
- if(i != rw_count){
- printf("ERROR: rw_count = %d\n", i);
- return EXIT_FAILURE;
- }
-
- printf("OK\n");
- r = ext4_fclose(&f);
- printf("ext4_fopen: test1\n");
-
- r = ext4_fopen(&f, "/mp/test1", "r+");
- if(r != EOK){
- printf("ext4_fopen ERROR = %d\n", r);
- return EXIT_FAILURE;
- }
-
- printf("ext4_read: %d * %d ..." , rw_count, rw_szie);
-
- for (i = 0; i < rw_count; ++i) {
- memset(wr_buff, i % 10 + '0', rw_szie);
- r = ext4_fread(&f, rd_buff, rw_szie, &size);
-
- if((r != EOK) || (size != rw_szie))
- break;
-
- if(memcmp(rd_buff, wr_buff, rw_szie)){
- break;
- }
- }
- if(i != rw_count){
- printf("ERROR: rw_count = %d\n", i);
- return EXIT_FAILURE;
- }
-
- printf("OK\n");
- r = ext4_fclose(&f);
-
+ fflush(stdout);
dir_ls("/mp/");
if(sbstat)
mp_stats();
-
if(cleanup_flag)
cleanup();
@@ -410,8 +526,10 @@
if(bstat)
block_stats();
- r = ext4_umount("/mp/");
- printf("Test finish: OK\n");
+ if(!umount())
+ return EXIT_FAILURE;
+
+ printf("Test finish: OK\n");
return EXIT_SUCCESS;
}
--- a/lwext4/ext4.c
+++ b/lwext4/ext4.c
@@ -793,10 +793,13 @@
int r = EOK;
uint32_t u;
uint32_t fblock;
+ uint32_t fblock_start;
+ uint32_t fblock_cnt;
struct ext4_block b;
uint8_t *u8_buf = buf;
struct ext4_inode_ref ref;
uint32_t sblock;
+ uint32_t sblock_end;
uint32_t block_size;
ext4_assert(f && f->mp);
@@ -824,9 +827,8 @@
block_size = ext4_sb_get_block_size(&f->mp->fs.sb);
size = size > (f->fsize - f->fpos) ? (f->fsize - f->fpos) : size;
-
sblock = (f->fpos) / block_size;
-
+ sblock_end = (f->fpos + size) / block_size;
u = (f->fpos) % block_size;
@@ -858,25 +860,39 @@
sblock++;
}
+ fblock_start = 0;
+ fblock_cnt = 0;
while(size >= block_size){
+ while(sblock < sblock_end){
+ r = ext4_fs_get_inode_data_block_index(&ref, sblock, &fblock);
+ if(r != EOK)
+ goto Finish;
- r = ext4_fs_get_inode_data_block_index(&ref, sblock, &fblock);
- if(r != EOK)
- goto Finish;
+ sblock++;
- r = ext4_block_get_direct(f->mp->fs.bdev, u8_buf, fblock);
+ if(!fblock_start){
+ fblock_start = fblock;
+ }
+
+ if((fblock_start + fblock_cnt) != fblock)
+ break;
+
+ fblock_cnt++;
+ }
+
+ r = ext4_blocks_get_direct(f->mp->fs.bdev, u8_buf, fblock_start, fblock_cnt);
if(r != EOK)
goto Finish;
+ size -= block_size * fblock_cnt;
+ u8_buf += block_size * fblock_cnt;
+ f->fpos += block_size * fblock_cnt;
- u8_buf += block_size;
- size -= block_size;
- f->fpos += block_size;
-
if(rcnt)
- *rcnt += block_size;
+ *rcnt += block_size * fblock_cnt;
- sblock++;
+ fblock_start = fblock;
+ fblock_cnt = 1;
}
if(size){
@@ -915,8 +931,11 @@
uint8_t *u8_buf = buf;
struct ext4_inode_ref ref;
uint32_t sblock;
+ uint32_t sblock_end;
uint32_t file_blocks;
uint32_t block_size;
+ uint32_t fblock_start;
+ uint32_t fblock_cnt;
ext4_assert(f && f->mp);
@@ -942,6 +961,8 @@
block_size = ext4_sb_get_block_size(&f->mp->fs.sb);
+ sblock_end = (f->fpos + size) > f->fsize ? (f->fpos + size) : f->fsize;
+ sblock_end /= block_size;
file_blocks = (f->fsize / block_size);
if(f->fsize % block_size)
@@ -986,31 +1007,47 @@
if(r != EOK)
goto Finish;
+ fblock_start = 0;
+ fblock_cnt = 0;
while(size >= block_size){
- if(sblock < file_blocks){
- r = ext4_fs_get_inode_data_block_index(&ref, sblock, &fblock);
- if(r != EOK)
+ while(sblock < sblock_end){
+ if(sblock < file_blocks){
+ r = ext4_fs_get_inode_data_block_index(&ref, sblock, &fblock);
+ if(r != EOK)
+ break;
+ }
+ else {
+ r = ext4_fs_append_inode_block(&ref, &fblock, &sblock);
+ if(r != EOK)
+ break;
+ }
+
+ sblock++;
+
+ if(!fblock_start){
+ fblock_start = fblock;
+ }
+
+ if((fblock_start + fblock_cnt) != fblock)
break;
+
+ fblock_cnt++;
}
- else {
- r = ext4_fs_append_inode_block(&ref, &fblock, &sblock);
- if(r != EOK)
- break;
- }
- r = ext4_block_set_direct(f->mp->fs.bdev, u8_buf, fblock);
+ r = ext4_blocks_set_direct(f->mp->fs.bdev, u8_buf, fblock_start, fblock_cnt);
if(r != EOK)
break;
- u8_buf += block_size;
- size -= block_size;
- f->fpos += block_size;
+ size -= block_size * fblock_cnt;
+ u8_buf += block_size * fblock_cnt;
+ f->fpos += block_size * fblock_cnt;
if(wcnt)
- *wcnt += block_size;
+ *wcnt += block_size * fblock_cnt;
- sblock++;
+ fblock_start = fblock;
+ fblock_cnt = 1;
}
/*Stop delay cache flush mode*/
--- a/lwext4/ext4_blockdev.c
+++ b/lwext4/ext4_blockdev.c
@@ -53,7 +53,7 @@
/*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 @@
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 @@
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 @@
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 @@
bdev->bwrite_ctr++;
- return bdev->bwrite(bdev, buf, pba, pb_cnt);
+ return bdev->bwrite(bdev, buf, pba, pb_cnt * cnt);
}
@@ -424,9 +424,9 @@
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;
--- a/lwext4/ext4_blockdev.h
+++ b/lwext4/ext4_blockdev.h
@@ -164,8 +164,8 @@
* @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 @@
* @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
--- a/lwext4/ext4_fs.c
+++ b/lwext4/ext4_fs.c
@@ -267,7 +267,7 @@
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",