Browse Source

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).
pull/1/head
gkostka 11 years ago
parent
commit
c109281525
  1. 6
      CMakeLists.txt
  2. 20
      Makefile
  3. 4
      blockdev/filedev/ext4_filedev.c
  4. 202
      blockdev/io_raw/io_raw.c
  5. 46
      blockdev/io_raw/io_raw.h
  6. 400
      demos/generic/main.c
  7. 89
      lwext4/ext4.c
  8. 22
      lwext4/ext4_blockdev.c
  9. 8
      lwext4/ext4_blockdev.h
  10. 2
      lwext4/ext4_fs.c

6
CMakeLists.txt

@ -25,9 +25,13 @@ add_custom_target(size ALL DEPENDS lwext4 COMMAND ${SIZE} -B liblwext4.a)
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()

20
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 @@ cortex-m4:
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

4
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 @@ 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;

202
blockdev/io_raw/io_raw.c

@ -0,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

46
blockdev/io_raw/io_raw.h

@ -0,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_ */

400
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 @@ static bool bstat = false;
/**@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 @@ static const char *usage = " \n\
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 @@ static void block_stats(void)
printf("bcache->lba[%d] = %u\n", i, (uint32_t)bc->lba[i]);
}
printf("**********************************************\n");
}
@ -201,6 +206,10 @@ static bool dir_test(int len)
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 @@ static bool dir_test(int len)
}
}
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)
{
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)
{
int option_index = 0;
int c;
int r;
int i;
uint32_t size;
ext4_file f;
#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))) {
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;
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;
case 'e':
dir_cnt = atoi(optarg);
break;
@ -280,12 +473,22 @@ int main(int argc, char **argv)
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);
@ -293,125 +496,40 @@ int main(int argc, char **argv)
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);
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();
cleanup();
if(sbstat)
mp_stats();
dir_ls("/mp/");
dir_test(dir_cnt);
/*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");
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);
fflush(stdout);
if(!dir_test(dir_cnt))
return EXIT_FAILURE;
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);
if(!file_test())
return EXIT_FAILURE;
fflush(stdout);
dir_ls("/mp/");
if(sbstat)
mp_stats();
if(cleanup_flag)
cleanup();
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;
}

89
lwext4/ext4.c

@ -793,10 +793,13 @@ int ext4_fread (ext4_file *f, void *buf, uint32_t size, uint32_t *rcnt)
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 @@ int ext4_fread (ext4_file *f, void *buf, uint32_t size, uint32_t *rcnt)
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 @@ int ext4_fread (ext4_file *f, void *buf, uint32_t size, uint32_t *rcnt)
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++;
if(!fblock_start){
fblock_start = fblock;
}
if((fblock_start + fblock_cnt) != fblock)
break;
fblock_cnt++;
}
r = ext4_block_get_direct(f->mp->fs.bdev, u8_buf, fblock);
r = ext4_blocks_get_direct(f->mp->fs.bdev, u8_buf, fblock_start, fblock_cnt);
if(r != EOK)
goto Finish;
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(rcnt)
*rcnt += block_size;
*rcnt += block_size * fblock_cnt;
sblock++;
fblock_start = fblock;
fblock_cnt = 1;
}
if(size){
@ -915,8 +931,11 @@ int ext4_fwrite(ext4_file *f, void *buf, uint32_t size, uint32_t *wcnt)
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 @@ int ext4_fwrite(ext4_file *f, void *buf, uint32_t size, uint32_t *wcnt)
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 @@ int ext4_fwrite(ext4_file *f, void *buf, uint32_t size, uint32_t *wcnt)
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)
break;
}
else {
r = ext4_fs_append_inode_block(&ref, &fblock, &sblock);
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++;
}
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*/

22
lwext4/ext4_blockdev.c

@ -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;

8
lwext4/ext4_blockdev.h

@ -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

2
lwext4/ext4_fs.c

@ -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",

Loading…
Cancel
Save