From ffb796f2aa4c7933dbce539865d90e7db00fabf4 Mon Sep 17 00:00:00 2001 From: gkostka Date: Sun, 20 Oct 2013 17:55:17 +0000 Subject: [PATCH] 1. Directory opreations: - ext4_dir_rm - delete dir recursive - ext4_dir_mk - make dir 2. Bugfix in ext4_dir (bad iterator behaviour). 3. Comments inr ext4.h. 4. Demo app has directory operations test. 5. Better ext4_femove implementation. 6. Most file functions base on ext4_open_generic. 7. Extent feature preprocessor switches. --- demos/generic/main.c | 108 ++++++++++--- ext4.h | 93 ++++++++--- lwext4/ext4.c | 360 +++++++++++++++++++++++++++++++------------ lwext4/ext4_dir.c | 16 +- lwext4/ext4_fs.c | 27 ++-- 5 files changed, 447 insertions(+), 157 deletions(-) diff --git a/demos/generic/main.c b/demos/generic/main.c index 6602422..ab24bd7 100644 --- a/demos/generic/main.c +++ b/demos/generic/main.c @@ -46,6 +46,9 @@ static int rw_szie = 1024; /**@brief Read-write size*/ static int rw_count = 1024; +/**@brief Directory test count*/ +static int dir_cnt = 10; + static bool cache_mode = false; @@ -65,10 +68,11 @@ 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 = 1024) \n\ - -cache - 0 static, 1 dynamic (default = 0) \n\ + -i - input file (default = ext2) \n\ + -rws - single R/W size (default = 1024) \n\ + -rwc - R/W count (default = 1024) \n\ + -cache - 0 static, 1 dynamic (default = 0) \n\ + -dirs - directory test count (default = 0) \n\ \n"; static char* entry_to_str(uint8_t type) @@ -106,7 +110,7 @@ static void dir_ls(const char *path) printf("**********************************************\n"); ext4_dir_open(&d, path); - de = ext4_entry_get(&d, j++); + de = ext4_dir_entry_get(&d, j++); printf("ls %s\n", path); while(de){ @@ -115,7 +119,7 @@ static void dir_ls(const char *path) printf(entry_to_str(de->inode_type)); printf(sss); printf("\n"); - de = ext4_entry_get(&d, j++); + de = ext4_dir_entry_get(&d, j++); } printf("**********************************************\n"); ext4_dir_close(&d); @@ -128,14 +132,14 @@ static void mp_stats(void) printf("**********************************************\n"); printf("ext4_mount_point_stats\n"); - printf("inodes_count = %d\n", stats.inodes_count); - printf("free_inodes_count = %d\n", stats.free_inodes_count); - printf("blocks_count = %d\n", stats.blocks_count); - printf("free_blocks_count = %d\n", stats.free_blocks_count); - printf("block_size = %d\n", stats.block_size); - printf("block_group_count = %d\n", stats.block_group_count); - printf("blocks_per_group = %d\n", stats.blocks_per_group); - printf("inodes_per_group = %d\n", stats.inodes_per_group); + printf("inodes_count = %u\n", stats.inodes_count); + printf("free_inodes_count = %u\n", stats.free_inodes_count); + printf("blocks_count = %u\n", (uint32_t)stats.blocks_count); + printf("free_blocks_count = %u\n", (uint32_t)stats.free_blocks_count); + printf("block_size = %u\n", stats.block_size); + printf("block_group_count = %u\n", stats.block_group_count); + printf("blocks_per_group = %u\n", stats.blocks_per_group); + printf("inodes_per_group = %u\n", stats.inodes_per_group); printf("volume_name = %s\n", stats.volume_name); printf("**********************************************\n"); @@ -148,22 +152,22 @@ static void block_stats(void) printf("**********************************************\n"); printf("ext4 blockdev stats\n"); - printf("bdev->bread_ctr = %d\n", bd->bread_ctr); - printf("bdev->bwrite_ctr = %d\n", bd->bwrite_ctr); + printf("bdev->bread_ctr = %u\n", bd->bread_ctr); + printf("bdev->bwrite_ctr = %u\n", bd->bwrite_ctr); - printf("bcache->ref_blocks = %d\n", bc->ref_blocks); - printf("bcache->max_ref_blocks = %d\n", bc->max_ref_blocks); - printf("bcache->lru_ctr = %d\n", bc->lru_ctr); + printf("bcache->ref_blocks = %u\n", bc->ref_blocks); + printf("bcache->max_ref_blocks = %u\n", bc->max_ref_blocks); + printf("bcache->lru_ctr = %u\n", bc->lru_ctr); printf("\n"); for (i = 0; i < bc->cnt; ++i) { - printf("bcache->refctr[%d] = %d\n", i, bc->refctr[i]); + printf("bcache->refctr[%d] = %u\n", i, bc->refctr[i]); } printf("\n"); for (i = 0; i < bc->cnt; ++i) { - printf("bcache->lru_id[%d] = %d\n", i, bc->lru_id[i]); + printf("bcache->lru_id[%d] = %u\n", i, bc->lru_id[i]); } printf("\n"); @@ -173,7 +177,7 @@ static void block_stats(void) printf("\n"); for (i = 0; i < bc->cnt; ++i) { - printf("bcache->lba[%d] = %d\n", i, bc->lba[i]); + printf("bcache->lba[%d] = %u\n", i, (uint32_t)bc->lba[i]); } @@ -181,6 +185,59 @@ static void block_stats(void) printf("**********************************************\n"); } +static bool dir_test(int len) +{ + ext4_file f; + int r; + int i; + char path[64]; + + printf("Remove directory /mp/dir1\n"); + ext4_dir_rm("/mp/dir1"); + + + printf("Directory create: /mp/dir1\n"); + r = ext4_dir_mk("/mp/dir1"); + if(r != EOK){ + printf("Unable to create directory: /mp/dir1\n"); + return false; + } + + + printf("Add files to: /mp/dir1\n"); + for (i = 0; i < len; ++i) { + sprintf(path, "/mp/dir1/f%d", i); + r = ext4_fopen(&f, path, "wb"); + if(r != EOK){ + printf("Unable to create file in directory: /mp/dir1\n"); + return false; + } + } + + printf("Add directories to: /mp/dir1\n"); + for (i = 0; i < len; ++i) { + sprintf(path, "/mp/dir1/d%d", i); + r = ext4_dir_mk(path); + if(r != EOK){ + printf("Unable to create directory in directory: /mp/dir1\n"); + return false; + } + } + + printf("Add file directories in: /mp/dir1\n"); + + for (i = 0; i < len; ++i) { + sprintf(path, "/mp/dir1/d%d/ff", i); + r = ext4_fopen(&f, path, "wb"); + if(r != EOK){ + printf("Unable to create file in directory: /mp/dir1\n"); + return false; + } + } + + dir_ls("/mp/dir1"); + return true; +} int main(int argc, char **argv) { @@ -197,10 +254,11 @@ int main(int argc, char **argv) {"rws", required_argument, 0, 'b'}, {"rwc", required_argument, 0, 'c'}, {"cache", required_argument, 0, 'd'}, + {"dirs", required_argument, 0, 'e'}, {0, 0, 0, 0} }; - while(-1 != (c = getopt_long (argc, argv, "a:b:c:d:", long_options, &option_index))) { + while(-1 != (c = getopt_long (argc, argv, "a:b:c:d:e:", long_options, &option_index))) { switch(c){ case 'a': @@ -215,6 +273,9 @@ int main(int argc, char **argv) case 'd': cache_mode = atoi(optarg); break; + case 'e': + dir_cnt = atoi(optarg); + break; default: printf(usage); return EXIT_FAILURE; @@ -262,6 +323,7 @@ int main(int argc, char **argv) return EXIT_FAILURE; } + dir_test(dir_cnt); ext4_fremove("/mp/hello.txt"); ext4_fremove("/mp/test1"); diff --git a/ext4.h b/ext4.h index 3d0cc2a..730d73f 100644 --- a/ext4.h +++ b/ext4.h @@ -42,34 +42,34 @@ #include #include -/********************************FILE OPEN FLAGS********************************/ +/********************************FILE OPEN FLAGS*****************************/ #ifndef O_RDONLY -#define O_RDONLY 00 +#define O_RDONLY 00 #endif #ifndef O_WRONLY -#define O_WRONLY 01 +#define O_WRONLY 01 #endif #ifndef O_RDWR -#define O_RDWR 02 +#define O_RDWR 02 #endif #ifndef O_CREAT -#define O_CREAT 0100 +#define O_CREAT 0100 #endif #ifndef O_EXCL -#define O_EXCL 0200 +#define O_EXCL 0200 #endif #ifndef O_TRUNC -#define O_TRUNC 01000 +#define O_TRUNC 01000 #endif #ifndef O_APPEND -#define O_APPEND 02000 +#define O_APPEND 02000 #endif /********************************FILE SEEK FLAGS*****************************/ @@ -133,7 +133,7 @@ enum { EXT4_DIRENTRY_SYMLINK }; -/**@brief Directory entry descriptor. Copy from ext4_types.h*/ +/**@brief Directory entry descriptor. Copy from ext4_types.h*/ typedef struct { uint32_t inode; uint16_t entry_length; @@ -182,7 +182,7 @@ int ext4_mount(const char * dev_name, char *mount_point); int ext4_umount(char *mount_point); -/**@brief Some of the filesystem params.*/ +/**@brief Some of the filesystem stats.*/ struct ext4_mount_stats { uint32_t inodes_count; uint32_t free_inodes_count; @@ -197,12 +197,18 @@ struct ext4_mount_stats { char volume_name[16]; }; +/**@brief Get file system params. + * @param mount_point mount path + * @param stats ext fs stats + * @return standard error code */ int ext4_mount_point_stats(const char *mount_point, struct ext4_mount_stats *stats); /********************************FILE OPERATIONS*****************************/ -/**@brief */ +/**@brief Remove file by path. + * @param path path to file + * @return standard error code */ int ext4_fremove(const char *path); /**@brief File open function. @@ -226,39 +232,76 @@ int ext4_fremove(const char *path); * @return standard error code*/ int ext4_fopen (ext4_file *f, const char *path, const char *flags); -/**@brief */ +/**@brief File close function. + * @param f file handle + * @return standard error code*/ int ext4_fclose(ext4_file *f); -/**@brief */ +/**@brief Read data from file. + * @param f file handle + * @param buf output buffer + * @param size bytes to read + * @param rcnt readed bytes (may be NULL) + * @return standard error code*/ int ext4_fread (ext4_file *f, void *buf, uint32_t size, uint32_t *rcnt); -/**@brief */ +/**@brief Write data to file. + * @param f file handle + * @param buf data to write + * @param size write length + * @param wcnt bytes written (may be NULL) + * @return standard error code*/ int ext4_fwrite(ext4_file *f, void *buf, uint32_t size, uint32_t *wcnt); -/**@brief */ +/**@brief File seek operation. + * @param f file handle + * @param offset offset to seek + * @param origin seek type: + * @ref SEEK_SET + * @ref SEEK_CUR + * @ref SEEK_END + * @return standard error code*/ int ext4_fseek (ext4_file *f, uint64_t offset, uint32_t origin); -/**@brief */ +/**@brief Get file position. + * @param f file handle + * @return actual file position */ uint64_t ext4_ftell (ext4_file *f); -/**@brief */ +/**@brief Get file size. + * @param f file handle + * @return file size */ uint64_t ext4_fsize (ext4_file *f); /*********************************DIRECTORY OPERATION***********************/ -/**@brief */ -int ext4_mkdir(const char *path); -/**@brief */ -int ext4_rmdir(const char *path); +/**@brief Recursive directory remove. + * @param path directory path to remove + * @return standard error code*/ +int ext4_dir_rm(const char *path); -/**@brief */ +/**@brief Create new directory. + * @param name new directory name + * @return standard error code*/ +int ext4_dir_mk(const char *path); + +/**@brief Directory open. + * @param d directory handle + * @param path directory path + * @return standard error code*/ int ext4_dir_open (ext4_dir *d, const char *path); -/**@brief */ +/**@brief Directory close. + * @param d directory handle + * @return standard error code*/ int ext4_dir_close(ext4_dir *d); -/**@brief */ -ext4_direntry* ext4_entry_get(ext4_dir *d, uint32_t id); + +/**@brief Return directory entry by id. + * @param d directory handle + * @param id entry id + * @return directory entry id (NULL id no entry)*/ +ext4_direntry* ext4_dir_entry_get(ext4_dir *d, uint32_t id); #endif /* EXT4_H_ */ diff --git a/lwext4/ext4.c b/lwext4/ext4.c index a0ceecf..5136fde 100644 --- a/lwext4/ext4.c +++ b/lwext4/ext4.c @@ -52,11 +52,11 @@ /**@brief Mount point OS dependent lock*/ #define EXT4_MP_LOCK(_m) \ - do { (_m)->os_locks ? (_m)->os_locks->lock() : 0; }while(0) + do { (_m)->os_locks ? (_m)->os_locks->lock() : 0; }while(0) /**@brief Mount point OS dependent unlock*/ #define EXT4_MP_UNLOCK(_m) \ - do { (_m)->os_locks ? (_m)->os_locks->unlock() : 0; }while(0) + do { (_m)->os_locks ? (_m)->os_locks->unlock() : 0; }while(0) /**@brief Mount point descrpitor.*/ struct ext4_mountpoint { @@ -491,7 +491,6 @@ static int ext4_path_check(const char *path, bool* is_goal) return 0; } - static bool ext4_parse_flags(const char *flags, uint32_t *file_flags) { if(!flags) @@ -533,7 +532,7 @@ static bool ext4_parse_flags(const char *flags, uint32_t *file_flags) /****************************************************************************/ static int ext4_generic_open (ext4_file *f, const char *path, - const char *flags, bool file_expect) + const char *flags, bool file_expect, uint32_t *parent_inode, uint32_t *name_off) { struct ext4_mountpoint *mp = ext4_get_mount(path); struct ext4_directory_search_result result; @@ -554,7 +553,8 @@ static int ext4_generic_open (ext4_file *f, const char *path, /*Skip mount point*/ path += strlen(mp->name); - EXT4_MP_LOCK(mp); + if(name_off) + *name_off = strlen(mp->name); /*Load root*/ r = ext4_fs_get_inode_ref(&mp->fs, EXT4_INODE_ROOT_INDEX, &ref); @@ -562,17 +562,20 @@ static int ext4_generic_open (ext4_file *f, const char *path, if(r != EOK) return r; - int len = ext4_path_check(path, &is_goal); + if(parent_inode) + *parent_inode = ref.index; - /*If root open was request.*/ - if(!len && is_goal) - goto IsGoal; + int len = ext4_path_check(path, &is_goal); while(1){ len = ext4_path_check(path, &is_goal); if(!len){ + /*If root open was request.*/ + if(is_goal && !file_expect) + break; + r = ENOENT; break; } @@ -586,9 +589,9 @@ static int ext4_generic_open (ext4_file *f, const char *path, if(!(f->flags & O_CREAT)) break; - /*O_CREAT allows to create new entry*/ + /*O_CREAT allows create new entry*/ struct ext4_inode_ref child_ref; - r = ext4_fs_alloc_inode(&mp->fs, &child_ref, !is_goal); + r = ext4_fs_alloc_inode(&mp->fs, &child_ref, is_goal ? !file_expect : true); if(r != EOK) break; @@ -612,6 +615,9 @@ static int ext4_generic_open (ext4_file *f, const char *path, continue; } + if(parent_inode) + *parent_inode = ref.index; + next_inode = result.dentry->inode; inode_type = ext4_dir_entry_ll_get_inode_type(&mp->fs.sb, result.dentry); @@ -645,18 +651,20 @@ static int ext4_generic_open (ext4_file *f, const char *path, break; path += len + 1; + + if(name_off) + *name_off += len + 1; }; if(r != EOK){ ext4_fs_put_inode_ref(&ref); - EXT4_MP_UNLOCK(mp); return r; } - IsGoal: if(is_goal){ - if(f->flags & O_TRUNC){ + if((f->flags & O_TRUNC) && + (inode_type == EXT4_DIRECTORY_FILETYPE_REG_FILE)){ /*Turncate.*/ ext4_block_delay_cache_flush(mp->fs.bdev, 1); /*Truncate may be IO heavy. @@ -666,7 +674,6 @@ static int ext4_generic_open (ext4_file *f, const char *path, if(r != EOK){ ext4_fs_put_inode_ref(&ref); - EXT4_MP_UNLOCK(mp); return r; } } @@ -682,7 +689,6 @@ static int ext4_generic_open (ext4_file *f, const char *path, } r = ext4_fs_put_inode_ref(&ref); - EXT4_MP_UNLOCK(mp); return r; } @@ -690,97 +696,37 @@ static int ext4_generic_open (ext4_file *f, const char *path, int ext4_fremove(const char *path) { + ext4_file f; + uint32_t parent_inode; + uint32_t name_off; + int r; + int len; + bool is_goal; struct ext4_mountpoint *mp = ext4_get_mount(path); - struct ext4_directory_search_result result; - bool is_goal = false; - uint8_t inode_type; - int r = ENOENT; - uint32_t next_inode; - struct ext4_inode_ref parent; - struct ext4_inode_ref child; - int len = 0; + struct ext4_inode_ref child; + struct ext4_inode_ref parent; if(!mp) return ENOENT; - - /*Skip mount point*/ - path += strlen(mp->name); - - /*Lock mountpoint*/ EXT4_MP_LOCK(mp); - - /*Load root*/ - r = ext4_fs_get_inode_ref(&mp->fs, EXT4_INODE_ROOT_INDEX, &parent); - + r = ext4_generic_open(&f, path, "r", true, &parent_inode, &name_off); if(r != EOK){ EXT4_MP_UNLOCK(mp); return r; } - while(1){ - - len = ext4_path_check(path, &is_goal); - - if(!len){ - r = ENOENT; - break; - } - - r = ext4_dir_find_entry(&result, &parent, path, len); - if(r != EOK){ - ext4_dir_destroy_result(&parent, &result); - break; - } - - next_inode = result.dentry->inode; - inode_type = ext4_dir_entry_ll_get_inode_type(&mp->fs.sb, - result.dentry); - - r = ext4_dir_destroy_result(&parent, &result); - if(r != EOK) - break; - - /*If expected file error*/ - if((inode_type == EXT4_DIRECTORY_FILETYPE_REG_FILE) && !is_goal){ - r = ENOENT; - break; - } - - /*If expected directory error*/ - if((inode_type == EXT4_DIRECTORY_FILETYPE_DIR) && is_goal){ - r = ENOENT; - break; - } - - if(is_goal) - break; - - r = ext4_fs_put_inode_ref(&parent); - if(r != EOK) - break; - - - r = ext4_fs_get_inode_ref(&mp->fs, next_inode, &parent); - if(r != EOK) - break; - - path += len + 1; - }; - + /*Load parent*/ + r = ext4_fs_get_inode_ref(&mp->fs, parent_inode, &parent); if(r != EOK){ - /*No entry or other error.*/ - ext4_fs_put_inode_ref(&parent); EXT4_MP_UNLOCK(mp); return r; } - /*We have file to delete. Load it.*/ - r = ext4_fs_get_inode_ref(&mp->fs, next_inode, &child); + r = ext4_fs_get_inode_ref(&mp->fs, f.inode, &child); if(r != EOK){ - /*Parent free*/ ext4_fs_put_inode_ref(&parent); EXT4_MP_UNLOCK(mp); return r; @@ -788,14 +734,18 @@ int ext4_fremove(const char *path) /*Turncate.*/ ext4_block_delay_cache_flush(mp->fs.bdev, 1); - /*Truncate may be IO heavy. Do it with delayed cache flush mode.*/ r = ext4_fs_truncate_inode(&child, 0); - ext4_block_delay_cache_flush(mp->fs.bdev, 0); + if(r != EOK) goto Finish; + /*Set path*/ + path += name_off; + + len = ext4_path_check(path, &is_goal); + /*Unlink from parent.*/ r = ext4_unlink(mp, &parent, &child, path, len); if(r != EOK) @@ -805,7 +755,6 @@ int ext4_fremove(const char *path) if(r != EOK) goto Finish; - Finish: ext4_fs_put_inode_ref(&child); ext4_fs_put_inode_ref(&parent); @@ -816,7 +765,16 @@ int ext4_fremove(const char *path) int ext4_fopen (ext4_file *f, const char *path, const char *flags) { - return ext4_generic_open(f, path, flags, true); + struct ext4_mountpoint *mp = ext4_get_mount(path); + int r; + + if(!mp) + return ENOENT; + + EXT4_MP_LOCK(mp); + r = ext4_generic_open(f, path, flags, true, 0, 0); + EXT4_MP_UNLOCK(mp); + return r; } int ext4_fclose(ext4_file *f) @@ -1144,9 +1102,222 @@ uint64_t ext4_fsize (ext4_file *f) /*********************************DIRECTORY OPERATION************************/ +int ext4_dir_rm(const char *path) +{ + int r; + int len; + ext4_file f; + struct ext4_mountpoint *mp = ext4_get_mount(path); + struct ext4_inode_ref current; + struct ext4_inode_ref child; + + struct ext4_directory_iterator it; + uint32_t name_off; + uint32_t inode_up; + uint32_t inode_current; + uint32_t depth = 1; + bool has_children; + bool is_goal; + bool dir_end; + + if(!mp) + return ENOENT; + + EXT4_MP_LOCK(mp); + + /*Check if exist.*/ + r = ext4_generic_open(&f, path, "r", false, &inode_up, &name_off); + if(r != EOK){ + EXT4_MP_UNLOCK(mp); + return r; + } + + path += name_off; + len = ext4_path_check(path, &is_goal); + + inode_current = f.inode; + dir_end = false; + do { + /*Load directory node.*/ + r = ext4_fs_get_inode_ref(&f.mp->fs, inode_current, ¤t); + if(r != EOK){ + break; + } + + /*Initialize iterator.*/ + r = ext4_dir_iterator_init(&it, ¤t, 0); + if(r != EOK){ + ext4_fs_put_inode_ref(¤t); + break; + } + + while(r == EOK){ + + if(!it.current){ + dir_end = true; + break; + } + + /*Get up directory inode when ".." entry*/ + if((it.current->name_length == 2) && + ext4_is_dots(it.current->name, it.current->name_length)){ + inode_up = it.current->inode; + } + + /*If directory or file entry, but not "." ".." entry*/ + if(!ext4_is_dots(it.current->name, it.current->name_length)){ + + /*Get child inode reference do unlink directory/file.*/ + r = ext4_fs_get_inode_ref(&f.mp->fs, it.current->inode, &child); + if(r != EOK) + break; + + /*If directory with no leaf children*/ + r = ext4_has_children(&has_children, &child); + if(r != EOK){ + ext4_fs_put_inode_ref(&child); + break; + } + + if(has_children){ + /*Has directory children. Go into this tirectory.*/ + inode_up = inode_current; + inode_current = it.current->inode; + depth++; + ext4_fs_put_inode_ref(&child); + break; + } + + /*Directory is empty. Truncate it.*/ + r = ext4_fs_truncate_inode(&child, 0); + if(r != EOK){ + ext4_fs_put_inode_ref(&child); + break; + } + + /*No children in child directory or file. Just unlink.*/ + r = ext4_unlink(f.mp, ¤t, &child, + (char *)it.current->name, it.current->name_length); + if(r != EOK){ + ext4_fs_put_inode_ref(&child); + break; + } + + r = ext4_fs_free_inode(&child); + if(r != EOK){ + ext4_fs_put_inode_ref(&child); + break; + } + + r = ext4_fs_put_inode_ref(&child); + if(r != EOK) + break; + } + + r = ext4_dir_iterator_next(&it); + } + + if(dir_end){ + /*Directory iterator reached last entry*/ + ext4_has_children(&has_children, ¤t); + if(!has_children){ + inode_current = inode_up; + if(depth) + depth--; + } + /*Last unlink*/ + if(!depth){ + /*Load parent.*/ + struct ext4_inode_ref parent; + r = ext4_fs_get_inode_ref(&f.mp->fs, inode_up, &parent); + if(r != EOK) + goto End; + + r = ext4_fs_truncate_inode(¤t, 0); + if(r != EOK){ + ext4_fs_put_inode_ref(&parent); + goto End; + } + + /* In this place all directories should be unlinked. + * Last unlink from root of current directory*/ + r = ext4_unlink(f.mp, &parent, ¤t, (char *)path, len); + if(r != EOK){ + ext4_fs_put_inode_ref(&parent); + goto End; + } + + r = ext4_fs_free_inode(¤t); + if(r != EOK){ + ext4_fs_put_inode_ref(&parent); + goto End; + } + + r = ext4_fs_put_inode_ref(&parent); + if(r != EOK) + goto End; + } + } + + End: + ext4_dir_iterator_fini(&it); + ext4_fs_put_inode_ref(¤t); + dir_end = false; + + /*When something goes wrong. End loop.*/ + if(r != EOK) + break; + + }while(depth); + + + EXT4_MP_UNLOCK(mp); + return r; +} + +int ext4_dir_mk(const char *path) +{ + int r; + ext4_file f; + + struct ext4_mountpoint *mp = ext4_get_mount(path); + + if(!mp) + return ENOENT; + + EXT4_MP_LOCK(mp); + + /*Check if exist.*/ + r = ext4_generic_open(&f, path, "r", false, 0, 0); + if(r == EOK){ + /*Directory already created*/ + EXT4_MP_UNLOCK(mp); + return r; + } + + /*Create new dir*/ + r = ext4_generic_open(&f, path, "w", false, 0, 0); + if(r != EOK){ + EXT4_MP_UNLOCK(mp); + return r; + } + + EXT4_MP_UNLOCK(mp); + return r; +} + int ext4_dir_open (ext4_dir *d, const char *path) { - return ext4_generic_open(&d->f, path, "r", false); + struct ext4_mountpoint *mp = ext4_get_mount(path); + int r; + + if(!mp) + return ENOENT; + + EXT4_MP_LOCK(mp); + r = ext4_generic_open(&d->f, path, "r", false, 0, 0); + EXT4_MP_UNLOCK(mp); + return r; } int ext4_dir_close(ext4_dir *d) @@ -1154,7 +1325,7 @@ int ext4_dir_close(ext4_dir *d) return ext4_fclose(&d->f); } -ext4_direntry* ext4_entry_get(ext4_dir *d, uint32_t id) +ext4_direntry* ext4_dir_entry_get(ext4_dir *d, uint32_t id) { int r; uint32_t i; @@ -1187,7 +1358,6 @@ ext4_direntry* ext4_entry_get(ext4_dir *d, uint32_t id) break; } - i++; r = ext4_dir_iterator_next(&it); } diff --git a/lwext4/ext4_dir.c b/lwext4/ext4_dir.c index 4f02119..ecce197 100644 --- a/lwext4/ext4_dir.c +++ b/lwext4/ext4_dir.c @@ -228,9 +228,21 @@ int ext4_dir_iterator_init(struct ext4_directory_iterator *it, int ext4_dir_iterator_next(struct ext4_directory_iterator *it) { - uint16_t skip = ext4_dir_entry_ll_get_entry_length(it->current); + int r = EOK; + uint16_t skip; - return ext4_dir_iterator_seek(it, it->current_offset + skip); + while(r == EOK){ + skip = ext4_dir_entry_ll_get_entry_length(it->current); + r = ext4_dir_iterator_seek(it, it->current_offset + skip); + + if(!it->current) + break; + /*Skip NULL referenced entry*/ + if(it->current->inode != 0) + break; + } + + return r; } int ext4_dir_iterator_fini(struct ext4_directory_iterator *it) diff --git a/lwext4/ext4_fs.c b/lwext4/ext4_fs.c index 677780f..1516f6a 100644 --- a/lwext4/ext4_fs.c +++ b/lwext4/ext4_fs.c @@ -546,7 +546,7 @@ int ext4_fs_alloc_inode(struct ext4_fs *fs, struct ext4_inode_ref *inode_ref, for (i = 0; i < EXT4_INODE_BLOCKS; i++) inode->blocks[i] = 0; -#if 0 +#if CONFIG_EXTENT_ENABLE /* Initialize extents if needed */ if (ext4_sb_check_feature_incompatible( &fs->sb, EXT4_FEATURE_INCOMPAT_EXTENTS)) { @@ -577,6 +577,7 @@ int ext4_fs_free_inode(struct ext4_inode_ref *inode_ref) struct ext4_fs *fs = inode_ref->fs; uint32_t offset; uint32_t suboffset; +#if CONFIG_EXTENT_ENABLE /* For extents must be data block destroyed by other way */ if ((ext4_sb_check_feature_incompatible(&fs->sb, EXT4_FEATURE_INCOMPAT_EXTENTS)) && @@ -584,7 +585,7 @@ int ext4_fs_free_inode(struct ext4_inode_ref *inode_ref) /* Data structures are released during truncate operation... */ goto finish; } - +#endif /* Release all indirect (no data) blocks */ /* 1) Single indirect */ @@ -739,18 +740,20 @@ int ext4_fs_truncate_inode(struct ext4_inode_ref *inode_ref, uint32_t old_blocks_count = old_size / block_size; if (old_size % block_size != 0) old_blocks_count++; - +#if CONFIG_EXTENT_ENABLE if ((ext4_sb_check_feature_incompatible(sb, EXT4_FEATURE_INCOMPAT_EXTENTS)) && (ext4_inode_has_flag(inode_ref->inode, EXT4_INODE_FLAG_EXTENTS))) { -#if 0 + /* Extents require special operation */ int rc = ext4_extent_release_blocks_from(inode_ref, old_blocks_count - diff_blocks_count); if (rc != EOK) return rc; + + } else #endif - } else { + { /* Release data blocks from the end of file */ /* Starting from 1 because of logical blocks are numbered from 0 */ @@ -781,21 +784,21 @@ int ext4_fs_get_inode_data_block_index(struct ext4_inode_ref *inode_ref, } uint32_t current_block; - +#if CONFIG_EXTENT_ENABLE /* Handle i-node using extents */ if ((ext4_sb_check_feature_incompatible(&fs->sb, EXT4_FEATURE_INCOMPAT_EXTENTS)) && (ext4_inode_has_flag(inode_ref->inode, EXT4_INODE_FLAG_EXTENTS))) { -#if 0 + int rc = ext4_extent_find_block(inode_ref, iblock, ¤t_block); if (rc != EOK) return rc; *fblock = current_block; return EOK; -#endif } +#endif struct ext4_inode *inode = inode_ref->inode; @@ -882,6 +885,7 @@ int ext4_fs_set_inode_data_block_index(struct ext4_inode_ref *inode_ref, { struct ext4_fs *fs = inode_ref->fs; +#if CONFIG_EXTENT_ENABLE /* Handle inode using extents */ if ((ext4_sb_check_feature_incompatible(&fs->sb, EXT4_FEATURE_INCOMPAT_EXTENTS)) && @@ -889,6 +893,7 @@ int ext4_fs_set_inode_data_block_index(struct ext4_inode_ref *inode_ref, /* Not reachable */ return ENOTSUP; } +#endif /* Handle simple case when we are dealing with direct reference */ if (iblock < EXT4_INODE_DIRECT_BLOCK_COUNT) { @@ -1136,16 +1141,14 @@ int ext4_fs_release_inode_block(struct ext4_inode_ref *inode_ref, int ext4_fs_append_inode_block(struct ext4_inode_ref *inode_ref, uint32_t *fblock, uint32_t *iblock) { +#if CONFIG_EXTENT_ENABLE /* Handle extents separately */ if ((ext4_sb_check_feature_incompatible(&inode_ref->fs->sb, EXT4_FEATURE_INCOMPAT_EXTENTS)) && (ext4_inode_has_flag(inode_ref->inode, EXT4_INODE_FLAG_EXTENTS))){ - -#if 0 return ext4_extent_append_block(inode_ref, iblock, fblock, true); -#endif } - +#endif struct ext4_sblock *sb = &inode_ref->fs->sb; /* Compute next block index and allocate data block */ -- 2.30.2