From 69d94315b8453ed1986a8a7a4cbd5835deceb3be Mon Sep 17 00:00:00 2001 From: geniusgogo <2041245+geniusgogo@users.noreply.github.com> Date: Wed, 2 Aug 2023 13:59:43 +0800 Subject: [PATCH] update dfs (#7887) --- .../dfs/dfs_v1/filesystems/tmpfs/dfs_tmpfs.c | 2 +- components/dfs/dfs_v1/src/dfs_file.c | 38 +-- .../dfs/dfs_v2/filesystems/devfs/devfs.c | 4 + .../dfs/dfs_v2/filesystems/elmfat/dfs_elm.c | 38 ++- .../dfs_v2/filesystems/mqueue/dfs_mqueue.c | 7 +- .../dfs/dfs_v2/filesystems/tmpfs/dfs_tmpfs.c | 43 ++-- components/dfs/dfs_v2/include/dfs_file.h | 2 + components/dfs/dfs_v2/include/dfs_fs.h | 4 +- components/dfs/dfs_v2/include/dfs_mnt.h | 5 + components/dfs/dfs_v2/src/dfs.c | 4 +- components/dfs/dfs_v2/src/dfs_dentry.c | 9 +- components/dfs/dfs_v2/src/dfs_file.c | 243 ++++++++++++++---- components/dfs/dfs_v2/src/dfs_fs.c | 51 ++-- components/dfs/dfs_v2/src/dfs_mnt.c | 64 +++-- components/dfs/dfs_v2/src/dfs_posix.c | 112 +++++++- 15 files changed, 458 insertions(+), 168 deletions(-) diff --git a/components/dfs/dfs_v1/filesystems/tmpfs/dfs_tmpfs.c b/components/dfs/dfs_v1/filesystems/tmpfs/dfs_tmpfs.c index f690d5750f..55d2027170 100644 --- a/components/dfs/dfs_v1/filesystems/tmpfs/dfs_tmpfs.c +++ b/components/dfs/dfs_v1/filesystems/tmpfs/dfs_tmpfs.c @@ -485,7 +485,7 @@ int dfs_tmpfs_stat(struct dfs_filesystem *fs, if (d_file == NULL) return -ENOENT; - st->st_dev = 0; + st->st_dev = (dev_t)dfs_filesystem_lookup(fs->path); st->st_mode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IWGRP | S_IWOTH; if (d_file->type == TMPFS_TYPE_DIR) diff --git a/components/dfs/dfs_v1/src/dfs_file.c b/components/dfs/dfs_v1/src/dfs_file.c index 094e26c323..e8594d8bae 100644 --- a/components/dfs/dfs_v1/src/dfs_file.c +++ b/components/dfs/dfs_v1/src/dfs_file.c @@ -591,39 +591,23 @@ int dfs_file_stat(const char *path, struct stat *buf) return -ENOENT; } - if ((fullpath[0] == '/' && fullpath[1] == '\0') || - (dfs_subdir(fs->path, fullpath) == NULL)) + if (fs->ops->stat == NULL) { - /* it's the root directory */ - buf->st_dev = 0; - - buf->st_mode = S_IRUSR | S_IRGRP | S_IROTH | - S_IWUSR | S_IWGRP | S_IWOTH; - buf->st_mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH; - - buf->st_size = 0; - buf->st_mtime = 0; - - /* release full path */ rt_free(fullpath); + LOG_E("the filesystem didn't implement this function"); - return RT_EOK; + return -ENOSYS; + } + /* get the real file path and get file stat */ + if (fs->ops->flags & DFS_FS_FLAG_FULLPATH) + { + result = fs->ops->stat(fs, fullpath, buf); } else { - if (fs->ops->stat == NULL) - { - rt_free(fullpath); - LOG_E("the filesystem didn't implement this function"); - - return -ENOSYS; - } - - /* get the real file path and get file stat */ - if (fs->ops->flags & DFS_FS_FLAG_FULLPATH) - result = fs->ops->stat(fs, fullpath, buf); - else - result = fs->ops->stat(fs, dfs_subdir(fs->path, fullpath), buf); + const char *subdir = dfs_subdir(fs->path, fullpath); + subdir = subdir ? subdir : "/"; + result = fs->ops->stat(fs, subdir, buf); } rt_free(fullpath); diff --git a/components/dfs/dfs_v2/filesystems/devfs/devfs.c b/components/dfs/dfs_v2/filesystems/devfs/devfs.c index cfd47cdcce..713ca49db7 100644 --- a/components/dfs/dfs_v2/filesystems/devfs/devfs.c +++ b/components/dfs/dfs_v2/filesystems/devfs/devfs.c @@ -232,6 +232,10 @@ int dfs_devfs_free_vnode(struct dfs_vnode *vnode) int dfs_devfs_mount(struct dfs_mnt *mnt, unsigned long rwflag, const void *data) { RT_ASSERT(mnt != RT_NULL); + + rt_atomic_add(&(mnt->ref_count), 1); + mnt->flags |= MNT_IS_LOCKED; + return RT_EOK; } diff --git a/components/dfs/dfs_v2/filesystems/elmfat/dfs_elm.c b/components/dfs/dfs_v2/filesystems/elmfat/dfs_elm.c index 5e0280d941..a5eb24ecaf 100644 --- a/components/dfs/dfs_v2/filesystems/elmfat/dfs_elm.c +++ b/components/dfs/dfs_v2/filesystems/elmfat/dfs_elm.c @@ -507,15 +507,13 @@ int dfs_elm_close(struct dfs_file *file) else if (file->vnode->type == FT_REGULAR) { FIL *fd = RT_NULL; + fd = (FIL *)(file->vnode->data); RT_ASSERT(fd != RT_NULL); - result = f_close(fd); - if (result == FR_OK) - { - /* release memory */ - rt_free(fd); - } + f_close(fd); + /* release memory */ + rt_free(fd); } return elm_result_to_dfs(result); @@ -573,8 +571,7 @@ ssize_t dfs_elm_read(struct dfs_file *file, void *buf, size_t len, off_t *pos) result = f_read(fd, buf, len, &byte_read); /* update position */ - file->fpos = fd->fptr; - *pos = file->fpos; + *pos = fd->fptr; if (result == FR_OK) return byte_read; @@ -597,8 +594,7 @@ ssize_t dfs_elm_write(struct dfs_file *file, const void *buf, size_t len, off_t result = f_write(fd, buf, len, &byte_write); /* update position and file size */ - file->fpos = fd->fptr; - *pos = file->fpos; + *pos = fd->fptr; file->vnode->size = f_size(fd); if (result == FR_OK) return byte_write; @@ -621,6 +617,24 @@ int dfs_elm_flush(struct dfs_file *file) off_t dfs_elm_lseek(struct dfs_file *file, off_t offset, int wherece) { FRESULT result = FR_OK; + + switch (wherece) + { + case SEEK_SET: + break; + + case SEEK_CUR: + offset += file->fpos; + break; + + case SEEK_END: + offset += file->vnode->size; + break; + + default: + return -EINVAL; + } + if (file->vnode->type == FT_REGULAR) { FIL *fd; @@ -633,7 +647,6 @@ off_t dfs_elm_lseek(struct dfs_file *file, off_t offset, int wherece) if (result == FR_OK) { /* return current position */ - file->fpos = fd->fptr; return fd->fptr; } } @@ -649,8 +662,7 @@ off_t dfs_elm_lseek(struct dfs_file *file, off_t offset, int wherece) if (result == FR_OK) { /* update file position */ - file->fpos = offset; - return file->fpos; + return offset; } } diff --git a/components/dfs/dfs_v2/filesystems/mqueue/dfs_mqueue.c b/components/dfs/dfs_v2/filesystems/mqueue/dfs_mqueue.c index 0dcee489ff..13719f386a 100644 --- a/components/dfs/dfs_v2/filesystems/mqueue/dfs_mqueue.c +++ b/components/dfs/dfs_v2/filesystems/mqueue/dfs_mqueue.c @@ -230,11 +230,6 @@ static struct dfs_filesystem_type _mqueue = { int dfs_mqueue_init(void) { /* register mqueue file system */ - dfs_register(&_mqueue); - mkdir("/dev/mqueue", 0x777); - if (dfs_mount(RT_NULL, "/dev/mqueue", "mqueue", 0, 0) != 0) { - rt_kprintf("Dir /dev/mqueue mount failed!\n"); - } - return 0; + return dfs_register(&_mqueue); } INIT_COMPONENT_EXPORT(dfs_mqueue_init); diff --git a/components/dfs/dfs_v2/filesystems/tmpfs/dfs_tmpfs.c b/components/dfs/dfs_v2/filesystems/tmpfs/dfs_tmpfs.c index 752fbc2513..801b6120c2 100644 --- a/components/dfs/dfs_v2/filesystems/tmpfs/dfs_tmpfs.c +++ b/components/dfs/dfs_v2/filesystems/tmpfs/dfs_tmpfs.c @@ -280,17 +280,16 @@ static ssize_t dfs_tmpfs_read(struct dfs_file *file, void *buf, size_t count, of d_file = (struct tmpfs_file *)file->vnode->data; RT_ASSERT(d_file != NULL); - if (count < file->vnode->size - file->fpos) + if (count < file->vnode->size - *pos) length = count; else - length = file->vnode->size - file->fpos; + length = file->vnode->size - *pos; if (length > 0) - memcpy(buf, &(d_file->data[file->fpos]), length); + memcpy(buf, &(d_file->data[*pos]), length); /* update file current position */ - file->fpos += length; - *pos = file->fpos; + *pos += length; return length; } @@ -306,41 +305,55 @@ static ssize_t dfs_tmpfs_write(struct dfs_file *file, const void *buf, size_t co superblock = d_file->sb; RT_ASSERT(superblock != NULL); - if (count + file->fpos > file->vnode->size) + if (count + *pos > file->vnode->size) { rt_uint8_t *ptr; - ptr = rt_realloc(d_file->data, file->fpos + count); + ptr = rt_realloc(d_file->data, *pos + count); if (ptr == NULL) { rt_set_errno(-ENOMEM); return 0; } - superblock->df_size += (file->fpos - d_file->size + count); + superblock->df_size += (*pos - d_file->size + count); /* update d_file and file size */ d_file->data = ptr; - d_file->size = file->fpos + count; + d_file->size = *pos + count; file->vnode->size = d_file->size; LOG_D("tmpfile ptr:%x, size:%d", ptr, d_file->size); } if (count > 0) - memcpy(d_file->data + file->fpos, buf, count); + memcpy(d_file->data + *pos, buf, count); /* update file current position */ - file->fpos += count; - *pos = file->fpos; + *pos += count; return count; } static off_t dfs_tmpfs_lseek(struct dfs_file *file, off_t offset, int wherece) { + switch (wherece) + { + case SEEK_SET: + break; + + case SEEK_CUR: + offset += file->fpos; + break; + + case SEEK_END: + offset += file->vnode->size; + break; + + default: + return -EINVAL; + } + if (offset <= (off_t)file->vnode->size) { - file->fpos = offset; - - return file->fpos; + return offset; } return -EIO; diff --git a/components/dfs/dfs_v2/include/dfs_file.h b/components/dfs/dfs_v2/include/dfs_file.h index 11793b2ad7..bb6551c8eb 100644 --- a/components/dfs/dfs_v2/include/dfs_file.h +++ b/components/dfs/dfs_v2/include/dfs_file.h @@ -140,6 +140,8 @@ void dfs_file_deinit(struct dfs_file *file); int dfs_file_open(struct dfs_file *file, const char *path, int flags, mode_t mode); int dfs_file_close(struct dfs_file *file); +off_t dfs_file_get_fpos(struct dfs_file *file); +void dfs_file_set_fpos(struct dfs_file *file, off_t fpos); ssize_t dfs_file_read(struct dfs_file *file, void *buf, size_t len); ssize_t dfs_file_write(struct dfs_file *file, const void *buf, size_t len); off_t generic_dfs_lseek(struct dfs_file *file, off_t offset, int whence); diff --git a/components/dfs/dfs_v2/include/dfs_fs.h b/components/dfs/dfs_v2/include/dfs_fs.h index 5146d42f7d..4a56119d51 100644 --- a/components/dfs/dfs_v2/include/dfs_fs.h +++ b/components/dfs/dfs_v2/include/dfs_fs.h @@ -77,6 +77,7 @@ struct dfs_filesystem_type struct dfs_filesystem_type *next; }; +struct dfs_filesystem_type *dfs_filesystems(void); int dfs_unregister(struct dfs_filesystem_type *fs); int dfs_register(struct dfs_filesystem_type *fs); const char *dfs_filesystem_get_mounted_path(struct rt_device *device); @@ -86,8 +87,9 @@ int dfs_mount(const char *device_name, const char *filesystemtype, unsigned long rwflag, const void *data); -int dfs_umount(const char *specialfile); +int dfs_umount(const char *specialfile, int flags); int dfs_unmount(const char *specialfile); +int dfs_is_mounted(struct dfs_mnt *mnt); int dfs_mkfs(const char *fs_name, const char *device_name); int dfs_statfs(const char *path, struct statfs *buffer); int dfs_filesystem_get_partition(struct dfs_partition *part, diff --git a/components/dfs/dfs_v2/include/dfs_mnt.h b/components/dfs/dfs_v2/include/dfs_mnt.h index c917520438..0d73051868 100644 --- a/components/dfs/dfs_v2/include/dfs_mnt.h +++ b/components/dfs/dfs_v2/include/dfs_mnt.h @@ -36,6 +36,9 @@ struct dfs_mnt #define MNT_IS_ALLOCED 0x1 /* the mnt struct is allocated */ #define MNT_IS_ADDLIST 0x2 /* the mnt struct is added into list */ #define MNT_IS_MOUNTED 0x4 /* the mnt struct is mounted */ +#define MNT_IS_UMOUNT 0x8 /* the mnt is unmount */ +#define MNT_IS_LOCKED 0x10 /* the mnt is locked */ +#define MNT_FORCE 0x20 /* the mnt force unmount */ rt_atomic_t ref_count; /* reference count */ @@ -58,6 +61,8 @@ int dfs_mnt_unref(struct dfs_mnt* mnt); rt_bool_t dfs_mnt_has_child_mnt(struct dfs_mnt *mnt, const char* fullpath); +int dfs_mnt_foreach(struct dfs_mnt* (*func)(struct dfs_mnt *mnt, void *parameter), void *parameter); + #ifdef __cplusplus } #endif diff --git a/components/dfs/dfs_v2/src/dfs.c b/components/dfs/dfs_v2/src/dfs.c index 9b25985409..bcea75e219 100644 --- a/components/dfs/dfs_v2/src/dfs.c +++ b/components/dfs/dfs_v2/src/dfs.c @@ -197,7 +197,7 @@ int fdt_fd_new(struct dfs_fdtable *fdt) dfs_file_lock(); /* find an empty fd entry */ - idx = fd_alloc(fdt, 0); + idx = fd_alloc(fdt, (fdt == &_fdtab) ? DFS_STDIO_OFFSET : 0); /* can't find an empty fd entry */ if (idx < 0) { @@ -452,7 +452,7 @@ sysret_t sys_dup(int oldfd) int sys_dup(int oldfd) #endif { - int newfd = dfs_dup(oldfd, DFS_STDIO_OFFSET); + int newfd = dfs_dup(oldfd, (dfs_fdtable_get() == &_fdtab) ? DFS_STDIO_OFFSET : 0); #ifdef RT_USING_SMART return (sysret_t)newfd; diff --git a/components/dfs/dfs_v2/src/dfs_dentry.c b/components/dfs/dfs_v2/src/dfs_dentry.c index 78c214cc67..6605f094f2 100644 --- a/components/dfs/dfs_v2/src/dfs_dentry.c +++ b/components/dfs/dfs_v2/src/dfs_dentry.c @@ -185,7 +185,7 @@ void dfs_dentry_insert(struct dfs_dentry *dentry) struct dfs_dentry *dfs_dentry_lookup(struct dfs_mnt *mnt, const char *path, uint32_t flags) { struct dfs_dentry *dentry; - struct dfs_vnode *vnode; + struct dfs_vnode *vnode = RT_NULL; int mntpoint_len = strlen(mnt->fullpath); if (rt_strncmp(mnt->fullpath, path, mntpoint_len) == 0) @@ -210,7 +210,12 @@ struct dfs_dentry *dfs_dentry_lookup(struct dfs_mnt *mnt, const char *path, uint if (dentry) { DLOG(msg, "dentry", mnt->fs_ops->name, DLOG_MSG, "vnode=fs_ops->lookup(dentry)"); - vnode = mnt->fs_ops->lookup(dentry); + + if (dfs_is_mounted(mnt) == 0) + { + vnode = mnt->fs_ops->lookup(dentry); + } + if (vnode) { DLOG(msg, mnt->fs_ops->name, "dentry", DLOG_MSG_RET, "return vnode"); diff --git a/components/dfs/dfs_v2/src/dfs_file.c b/components/dfs/dfs_v2/src/dfs_file.c index 52b1a63210..ac18caefc1 100644 --- a/components/dfs/dfs_v2/src/dfs_file.c +++ b/components/dfs/dfs_v2/src/dfs_file.c @@ -48,11 +48,28 @@ ssize_t rw_verify_area(struct dfs_file *file, off_t *ppos, size_t count) return count > MAX_RW_COUNT ? MAX_RW_COUNT : count; } +off_t dfs_file_get_fpos(struct dfs_file *file) +{ + if (file) + { + if (file->vnode->type == FT_REGULAR) + { + rt_mutex_take(&file->pos_lock, RT_WAITING_FOREVER); + } + return file->fpos; + } + + return 0; +} + void dfs_file_set_fpos(struct dfs_file *file, off_t fpos) { if (file) { - rt_mutex_take(&file->pos_lock, RT_WAITING_FOREVER); + if (file->vnode->type != FT_REGULAR) + { + rt_mutex_take(&file->pos_lock, RT_WAITING_FOREVER); + } file->fpos = fpos; rt_mutex_release(&file->pos_lock); } @@ -116,6 +133,7 @@ static void dfs_file_unref(struct dfs_file *file) struct dfs_dentry* dfs_file_follow_link(struct dfs_dentry *dentry) { int ret = 0; + struct dfs_dentry *tmp = dfs_dentry_ref(dentry); if (dentry && dentry->vnode && dentry->vnode->type == FT_SYMLINK) { @@ -126,14 +144,18 @@ struct dfs_dentry* dfs_file_follow_link(struct dfs_dentry *dentry) { do { - ret = dentry->mnt->fs_ops->readlink(dentry, buf, DFS_PATH_MAX); + if (dfs_is_mounted(tmp->mnt) == 0) + { + ret = tmp->mnt->fs_ops->readlink(tmp, buf, DFS_PATH_MAX); + } + if (ret > 0) { struct dfs_mnt *mnt = NULL; if (buf[0] != '/') { - char *dir = dfs_dentry_pathname(dentry); + char *dir = dfs_dentry_pathname(tmp); /* is the relative directory */ if (dir) @@ -155,21 +177,21 @@ struct dfs_dentry* dfs_file_follow_link(struct dfs_dentry *dentry) struct dfs_dentry *de = dfs_dentry_lookup(mnt, buf, 0); /* release the old dentry */ - dfs_dentry_unref(dentry); - dentry = de; + dfs_dentry_unref(tmp); + tmp = de; } } else { break; } - } while (dentry && dentry->vnode->type == FT_SYMLINK); + } while (tmp && tmp->vnode->type == FT_SYMLINK); } rt_free(buf); } - return dentry; + return tmp; } /* @@ -215,7 +237,10 @@ static char *dfs_nolink_path(struct dfs_mnt **mnt, char *fullpath, int mode) if ((*mnt)->fs_ops->readlink) { - ret = (*mnt)->fs_ops->readlink(dentry, link_fn, DFS_PATH_MAX); + if (dfs_is_mounted((*mnt)) == 0) + { + ret = (*mnt)->fs_ops->readlink(dentry, link_fn, DFS_PATH_MAX); + } } if (ret > 0) @@ -264,7 +289,10 @@ static char *dfs_nolink_path(struct dfs_mnt **mnt, char *fullpath, int mode) if ((*mnt)->fs_ops->readlink) { - ret = (*mnt)->fs_ops->readlink(dentry, link_fn, DFS_PATH_MAX); + if (dfs_is_mounted((*mnt)) == 0) + { + ret = (*mnt)->fs_ops->readlink(dentry, link_fn, DFS_PATH_MAX); + } } if (ret > 0) @@ -316,7 +344,7 @@ static char *dfs_nolink_path(struct dfs_mnt **mnt, char *fullpath, int mode) */ int dfs_file_open(struct dfs_file *file, const char *path, int oflags, mode_t mode) { - int ret = -RT_ERROR;; + int ret = -RT_ERROR; char *fullpath = RT_NULL; struct dfs_dentry *dentry = RT_NULL; int fflags = dfs_fflags(oflags); @@ -361,10 +389,8 @@ int dfs_file_open(struct dfs_file *file, const char *path, int oflags, mode_t mo /* follow symbol link */ target_dentry = dfs_file_follow_link(dentry); - if (target_dentry) - { - dentry = target_dentry; - } + dfs_dentry_unref(dentry); + dentry = target_dentry; } } @@ -419,7 +445,11 @@ int dfs_file_open(struct dfs_file *file, const char *path, int oflags, mode_t mo { mode &= ~S_IFMT; DLOG(msg, "dfs_file", mnt->fs_ops->name, DLOG_MSG, "fs_ops->create_vnode"); - vnode = mnt->fs_ops->create_vnode(dentry, oflags & O_DIRECTORY ? FT_DIRECTORY:FT_REGULAR, mode); + + if (dfs_is_mounted(mnt) == 0) + { + vnode = mnt->fs_ops->create_vnode(dentry, oflags & O_DIRECTORY ? FT_DIRECTORY:FT_REGULAR, mode); + } if (vnode) { @@ -477,7 +507,16 @@ int dfs_file_open(struct dfs_file *file, const char *path, int oflags, mode_t mo if (permission && file->fops->open) { DLOG(msg, "dfs_file", mnt->fs_ops->name, DLOG_MSG, "fops->open(file)"); - ret = file->fops->open(file); + + if (dfs_is_mounted(file->vnode->mnt) == 0) + { + ret = file->fops->open(file); + } + else + { + ret = -EINVAL; + } + if (ret < 0) { LOG_E("open %s failed in file system: %s", path, dentry->mnt->fs_ops->name); @@ -523,7 +562,16 @@ int dfs_file_open(struct dfs_file *file, const char *path, int oflags, mode_t mo if (file->fops->truncate) { DLOG(msg, "dfs_file", dentry->mnt->fs_ops->name, DLOG_MSG, "fops->truncate(file, 0)"); - ret = file->fops->truncate(file, 0); + + if (dfs_is_mounted(file->vnode->mnt) == 0) + { + ret = file->fops->truncate(file, 0); + } + else + { + ret = -EINVAL; + } + } } @@ -552,6 +600,7 @@ int dfs_file_close(struct dfs_file *file) if (ref_count == 1 && file->fops && file->fops->close) { DLOG(msg, "dfs_file", file->dentry->mnt->fs_ops->name, DLOG_MSG, "fops->close(file)"); + ret = file->fops->close(file); if (ret == 0) /* close file sucessfully */ @@ -594,20 +643,25 @@ ssize_t dfs_file_read(struct dfs_file *file, void *buf, size_t len) } else if (file->vnode && file->vnode->type != FT_DIRECTORY) { - off_t pos; - pos = file->fpos; + /* fpos lock */ + off_t pos = dfs_file_get_fpos(file); ret = rw_verify_area(file, &pos, len); if (ret > 0) { len = ret; - ret = file->fops->read(file, buf, len, &pos); - if (ret > 0) + if (dfs_is_mounted(file->vnode->mnt) == 0) { - dfs_file_set_fpos(file, pos); + ret = file->fops->read(file, buf, len, &pos); + } + else + { + ret = -EINVAL; } } + /* fpos unlock */ + dfs_file_set_fpos(file, pos); } } @@ -632,21 +686,27 @@ ssize_t dfs_file_write(struct dfs_file *file, const void *buf, size_t len) } else if (file->vnode && file->vnode->type != FT_DIRECTORY) { - off_t pos; + /* fpos lock */ + off_t pos = dfs_file_get_fpos(file); - pos = file->fpos; ret = rw_verify_area(file, &pos, len); if (ret > 0) { len = ret; DLOG(msg, "dfs_file", file->dentry->mnt->fs_ops->name, DLOG_MSG, "dfs_file_write(fd, buf, %d)", len); - ret = file->fops->write(file, buf, len, &pos); - if (ret > 0) + + if (dfs_is_mounted(file->vnode->mnt) == 0) { - dfs_file_set_fpos(file, pos); + ret = file->fops->write(file, buf, len, &pos); + } + else + { + ret = -EINVAL; } } + /* fpos unlock */ + dfs_file_set_fpos(file, pos); } } @@ -666,25 +726,26 @@ off_t generic_dfs_lseek(struct dfs_file *file, off_t offset, int whence) else return -EINVAL; - dfs_file_set_fpos(file, foffset); - return foffset; } off_t dfs_file_lseek(struct dfs_file *file, off_t offset, int wherece) { - off_t retval; + off_t retval = -EINVAL; - if (!file) - return -EBADF; - - retval = -EINVAL; - if (file->fops->lseek) + if (file && file->fops->lseek) { - retval = file->fops->lseek(file, offset, wherece); - if (retval >= 0) + if (dfs_is_mounted(file->vnode->mnt) == 0) { - dfs_file_set_fpos(file, retval); + /* fpos lock */ + off_t pos = dfs_file_get_fpos(file); + retval = file->fops->lseek(file, offset, wherece); + if (retval >= 0) + { + pos = retval; + } + /* fpos unlock */ + dfs_file_set_fpos(file, pos); } } @@ -720,7 +781,11 @@ int dfs_file_stat(const char *path, struct stat *buf) if (mnt->fs_ops->stat) { DLOG(msg, "dfs_file", mnt->fs_ops->name, DLOG_MSG, "fs_ops->stat(dentry, buf)"); - ret = mnt->fs_ops->stat(dentry, buf); + + if (dfs_is_mounted(mnt) == 0) + { + ret = mnt->fs_ops->stat(dentry, buf); + } } /* unref dentry */ @@ -770,7 +835,11 @@ int dfs_file_lstat(const char *path, struct stat *buf) if (mnt->fs_ops->stat) { DLOG(msg, "dfs_file", mnt->fs_ops->name, DLOG_MSG, "fs_ops->stat(dentry, buf)"); - ret = mnt->fs_ops->stat(dentry, buf); + + if (dfs_is_mounted(mnt) == 0) + { + ret = mnt->fs_ops->stat(dentry, buf); + } } /* unref dentry */ @@ -845,7 +914,11 @@ int dfs_file_setattr(const char *path, struct dfs_attr *attr) if (mnt->fs_ops->setattr) { DLOG(msg, "dfs_file", mnt->fs_ops->name, DLOG_MSG, "fs_ops->setattr(dentry, attr)"); - ret = mnt->fs_ops->setattr(dentry, attr); + + if (dfs_is_mounted(mnt) == 0) + { + ret = mnt->fs_ops->setattr(dentry, attr); + } } /* unref dentry */ @@ -870,7 +943,14 @@ int dfs_file_ioctl(struct dfs_file *file, int cmd, void *args) { if (file->fops && file->fops->ioctl) { - ret = file->fops->ioctl(file, cmd, args); + if (dfs_is_mounted(file->vnode->mnt) == 0) + { + ret = file->fops->ioctl(file, cmd, args); + } + else + { + ret = -EINVAL; + } } else { @@ -953,7 +1033,14 @@ int dfs_file_fsync(struct dfs_file *file) { if (file->fops->flush) { - ret = file->fops->flush(file); + if (dfs_is_mounted(file->vnode->mnt) == 0) + { + ret = file->fops->flush(file); + } + else + { + ret = -EINVAL; + } } } @@ -997,7 +1084,10 @@ int dfs_file_unlink(const char *path) if (mnt->fs_ops->unlink) { - ret = mnt->fs_ops->unlink(dentry); + if (dfs_is_mounted(mnt) == 0) + { + ret = mnt->fs_ops->unlink(dentry); + } } } else @@ -1096,7 +1186,10 @@ int dfs_file_link(const char *oldname, const char *newname) { if (mnt->fs_ops->link) { - ret = mnt->fs_ops->link(old_dentry, new_dentry); + if (dfs_is_mounted(mnt) == 0) + { + ret = mnt->fs_ops->link(old_dentry, new_dentry); + } } } @@ -1211,7 +1304,10 @@ int dfs_file_symlink(const char *target, const char *linkpath) } } - ret = mnt->fs_ops->symlink(dentry, tmp, index + 1); + if (dfs_is_mounted(mnt) == 0) + { + ret = mnt->fs_ops->symlink(dentry, tmp, index + 1); + } } else { @@ -1280,7 +1376,10 @@ int dfs_file_readlink(const char *path, char *buf, int bufsize) { if (mnt->fs_ops->readlink) { - ret = mnt->fs_ops->readlink(dentry, buf, bufsize); + if (dfs_is_mounted(mnt) == 0) + { + ret = mnt->fs_ops->readlink(dentry, buf, bufsize); + } } else { @@ -1361,7 +1460,10 @@ int dfs_file_rename(const char *old_file, const char *new_file) { if (mnt->fs_ops->rename) { - ret = mnt->fs_ops->rename(old_dentry, new_dentry); + if (dfs_is_mounted(mnt) == 0) + { + ret = mnt->fs_ops->rename(old_dentry, new_dentry); + } } } @@ -1390,7 +1492,14 @@ int dfs_file_ftruncate(struct dfs_file *file, off_t length) { if (file->fops->truncate) { - ret = file->fops->truncate(file, length); + if (dfs_is_mounted(file->vnode->mnt) == 0) + { + ret = file->fops->truncate(file, length); + } + else + { + ret = -EINVAL; + } } else { @@ -1413,7 +1522,14 @@ int dfs_file_flush(struct dfs_file *file) { if (file->fops->flush) { - ret = file->fops->flush(file); + if (dfs_is_mounted(file->vnode->mnt) == 0) + { + ret = file->fops->flush(file); + } + else + { + ret = -EINVAL; + } } else { @@ -1439,7 +1555,15 @@ int dfs_file_getdents(struct dfs_file *file, struct dirent *dirp, size_t nbytes) if (file->fops && file->fops->getdents) { DLOG(msg, "dfs_file", file->dentry->mnt->fs_ops->name, DLOG_MSG, "fops->getdents()"); - ret = file->fops->getdents(file, dirp, nbytes); + + if (dfs_is_mounted(file->vnode->mnt) == 0) + { + ret = file->fops->getdents(file, dirp, nbytes); + } + else + { + ret = -EINVAL; + } } } } @@ -1488,7 +1612,12 @@ int dfs_file_isdir(const char *path) { struct stat stat = {0}; DLOG(msg, "dfs_file", mnt->fs_ops->name, DLOG_MSG, "fs_ops->stat(dentry, buf)"); - ret = mnt->fs_ops->stat(dentry, &stat); + + if (dfs_is_mounted(mnt) == 0) + { + ret = mnt->fs_ops->stat(dentry, &stat); + } + if (ret == RT_EOK && S_ISDIR(stat.st_mode)) { ret = RT_EOK; @@ -1547,7 +1676,15 @@ int dfs_file_mmap2(struct dfs_file *file, struct dfs_mmap2_args *mmap2) } else if (file->vnode->type == FT_DEVICE && file->vnode->fops->ioctl) { - ret = file->vnode->fops->ioctl(file, RT_FIOMMAP2, mmap2); + if (dfs_is_mounted(file->vnode->mnt) == 0) + { + ret = file->vnode->fops->ioctl(file, RT_FIOMMAP2, mmap2); + } + else + { + ret = EINVAL; + } + if (ret != 0) { ret = ret > 0 ? ret : -ret; diff --git a/components/dfs/dfs_v2/src/dfs_fs.c b/components/dfs/dfs_v2/src/dfs_fs.c index ffedc44fca..8c28dbe7ef 100644 --- a/components/dfs/dfs_v2/src/dfs_fs.c +++ b/components/dfs/dfs_v2/src/dfs_fs.c @@ -43,6 +43,11 @@ static struct dfs_filesystem_type **_find_filesystem(const char *name) return type; } +struct dfs_filesystem_type *dfs_filesystems(void) +{ + return file_systems; +} + int dfs_register(struct dfs_filesystem_type *fs) { int ret = 0; @@ -160,6 +165,8 @@ int dfs_mount(const char *device_name, DLOG(msg, type->fs_ops->name, "dfs", DLOG_MSG_RET, "mount OK, ret root_dentry"); mnt_child = mnt_parent; + mnt_child->flags |= MNT_IS_MOUNTED; + DLOG(note_right, "mnt", "mount sucessfully"); DLOG(msg, "dfs", "mnt", DLOG_MSG, "dfs_mnt_insert(, mnt_child)"); dfs_mnt_insert(RT_NULL, mnt_child); @@ -202,7 +209,7 @@ int dfs_mount(const char *device_name, ret = -1; } } - else if (strcmp(mnt_parent->fullpath, fullpath) != 0) + else if (mnt_parent && (strcmp(mnt_parent->fullpath, fullpath) != 0)) { DLOG(msg, "dfs", "dentry", DLOG_MSG, "mntpoint_dentry = dfs_dentry_lookup(mnt_parent, %s, 0)", fullpath); mntpoint_dentry = dfs_dentry_lookup(mnt_parent, fullpath, 0); @@ -224,6 +231,8 @@ int dfs_mount(const char *device_name, ret = mnt_child->fs_ops->mount(mnt_child, rwflag, data); if (ret == RT_EOK) { + mnt_child->flags |= MNT_IS_MOUNTED; + LOG_D("mount %s sucessfully", fullpath); DLOG(msg, mnt_child->fs_ops->name, "dfs", DLOG_MSG_RET, "mount OK"); @@ -285,7 +294,7 @@ int dfs_mount(const char *device_name, return ret; } -int dfs_umount(const char *specialfile) +int dfs_umount(const char *specialfile, int flags) { int ret = -RT_ERROR; char *fullpath = RT_NULL; @@ -301,22 +310,13 @@ int dfs_umount(const char *specialfile) if (strcmp(mnt->fullpath, fullpath) == 0) { /* is the mount point */ + rt_atomic_t ref_count = rt_atomic_load(&(mnt->ref_count)); - if (rt_atomic_load(&(mnt->ref_count)) == 1 && rt_list_isempty(&mnt->child)) + if (!(mnt->flags & MNT_IS_LOCKED) && rt_list_isempty(&mnt->child) && (ref_count == 1 || (flags & MNT_FORCE))) { - DLOG(msg, "dfs", mnt->fs_ops->name, DLOG_MSG, "fs_ops->umount(mnt)"); - ret = mnt->fs_ops->umount(mnt); - if (ret == 0) - { - DLOG(msg, mnt->fs_ops->name, "dfs", DLOG_MSG_RET, "return OK"); - /* destroy this mount point */ - DLOG(msg, "dfs", "mnt", DLOG_MSG, "dfs_mnt_destroy(mnt)"); - dfs_mnt_destroy(mnt); - } - else - { - LOG_E("umount file system: %s failed.", fullpath); - } + /* destroy this mount point */ + DLOG(msg, "dfs", "mnt", DLOG_MSG, "dfs_mnt_destroy(mnt)"); + ret = dfs_mnt_destroy(mnt); } else { @@ -345,7 +345,19 @@ int dfs_umount(const char *specialfile) /* for compatibility */ int dfs_unmount(const char *specialfile) { - return dfs_umount(specialfile); + return dfs_umount(specialfile, 0); +} + +int dfs_is_mounted(struct dfs_mnt *mnt) +{ + int ret = 0; + + if (mnt && !(mnt->flags & MNT_IS_MOUNTED)) + { + ret = -1; + } + + return ret; } int dfs_mkfs(const char *fs_name, const char *device_name) @@ -407,7 +419,10 @@ int dfs_statfs(const char *path, struct statfs *buffer) { if (mnt->fs_ops->statfs) { - ret = mnt->fs_ops->statfs(mnt, buffer); + if (dfs_is_mounted(mnt) == 0) + { + ret = mnt->fs_ops->statfs(mnt, buffer); + } } } diff --git a/components/dfs/dfs_v2/src/dfs_mnt.c b/components/dfs/dfs_v2/src/dfs_mnt.c index 759fed5598..379606d9ce 100644 --- a/components/dfs/dfs_v2/src/dfs_mnt.c +++ b/components/dfs/dfs_v2/src/dfs_mnt.c @@ -67,6 +67,7 @@ int dfs_mnt_insert(struct dfs_mnt* mnt, struct dfs_mnt* child) { /* it's root mnt */ mnt = child; + mnt->flags |= MNT_IS_LOCKED; /* ref to gobal root */ if (_root_mnt) @@ -194,22 +195,34 @@ int dfs_mnt_unref(struct dfs_mnt* mnt) if (mnt) { - ret = dfs_lock(); - if (ret == RT_EOK) - { - rt_atomic_sub(&(mnt->ref_count), 1); + rt_atomic_sub(&(mnt->ref_count), 1); - if (rt_atomic_load(&(mnt->ref_count)) < 0) + if (rt_atomic_load(&(mnt->ref_count)) == 0) + { + dfs_lock(); + + if (mnt->flags & MNT_IS_UMOUNT) { - LOG_W("bug on mnt(%s) release ref_count(%d).", mnt->fullpath, mnt->ref_count); + mnt->fs_ops->umount(mnt); } - DLOG(note, "mnt", "mnt(%s),ref_count=%d", mnt->fs_ops->name, rt_atomic_load(&(mnt->ref_count))); + + /* free full path */ + rt_free(mnt->fullpath); + mnt->fullpath = RT_NULL; + + /* destroy self and the ref_count should be 0 */ + DLOG(msg, "mnt", "mnt", DLOG_MSG, "free mnt(%s)", mnt->fs_ops->name); + rt_free(mnt); dfs_unlock(); } + else + { + DLOG(note, "mnt", "mnt(%s),ref_count=%d", mnt->fs_ops->name, rt_atomic_load(&(mnt->ref_count))); + } } - return 0; + return ret; } int dfs_mnt_destroy(struct dfs_mnt* mnt) @@ -218,33 +231,21 @@ int dfs_mnt_destroy(struct dfs_mnt* mnt) if (mnt) { - ret = dfs_lock(); - if (ret == RT_EOK) + if (mnt->flags & MNT_IS_MOUNTED) { - if (rt_atomic_load(&(mnt->ref_count)) != 1) - { - LOG_W("bug on mnt(%s) ref_count(%d).", mnt->fullpath, mnt->ref_count); - } - + mnt->flags &= ~MNT_IS_MOUNTED; + mnt->flags |= MNT_IS_UMOUNT; /* remote it from mnt list */ if (mnt->flags & MNT_IS_ADDLIST) { dfs_mnt_remove(mnt); } - - /* free full path */ - rt_free(mnt->fullpath); - mnt->fullpath = RT_NULL; - - dfs_unlock(); - - /* destroy self and the ref_count should be 0 */ - DLOG(msg, "mnt", "mnt", DLOG_MSG, "free mnt(%s)", mnt->fs_ops->name); - rt_free(mnt); } + + dfs_mnt_unref(mnt); } - return 0; + return ret; } static struct dfs_mnt* _dfs_mnt_foreach(struct dfs_mnt *mnt, struct dfs_mnt* (*func)(struct dfs_mnt *mnt, void *parameter), void *parameter) @@ -384,3 +385,14 @@ int dfs_mnt_list(struct dfs_mnt *mnt) return 0; } + +int dfs_mnt_foreach(struct dfs_mnt* (*func)(struct dfs_mnt *mnt, void *parameter), void *parameter) +{ + /* lock file system */ + dfs_lock(); + _dfs_mnt_foreach(_root_mnt, func, parameter); + /* unlock file system */ + dfs_unlock(); + + return 0; +} diff --git a/components/dfs/dfs_v2/src/dfs_posix.c b/components/dfs/dfs_v2/src/dfs_posix.c index a9c822c5c8..fa5f6dc9f0 100644 --- a/components/dfs/dfs_v2/src/dfs_posix.c +++ b/components/dfs/dfs_v2/src/dfs_posix.c @@ -412,7 +412,7 @@ RTM_EXPORT(stat); */ int fstat(int fildes, struct stat *buf) { - int ret = 0; + int ret = -1; struct dfs_file *file; if (buf == NULL) @@ -430,7 +430,10 @@ int fstat(int fildes, struct stat *buf) return -1; } - ret = file->dentry->mnt->fs_ops->stat(file->dentry, buf); + if (dfs_is_mounted(file->dentry->mnt) == 0) + { + ret = file->dentry->mnt->fs_ops->stat(file->dentry, buf); + } return ret; } @@ -624,7 +627,7 @@ RTM_EXPORT(statfs); */ int fstatfs(int fildes, struct statfs *buf) { - int ret = 0; + int ret = -1; struct dfs_file *file; if (buf == NULL) @@ -642,7 +645,10 @@ int fstatfs(int fildes, struct statfs *buf) return -1; } - ret = file->dentry->mnt->fs_ops->statfs(file->dentry->mnt, buf); + if (dfs_is_mounted(file->dentry->mnt) == 0) + { + ret = file->dentry->mnt->fs_ops->statfs(file->dentry->mnt, buf); + } return ret; } @@ -1223,4 +1229,102 @@ char *getcwd(char *buf, size_t size) } RTM_EXPORT(getcwd); +/** + * this function is a POSIX compliant version, which will read specified data + * buffer length for an open file descriptor. + * + * @param fd the file descriptor. + * @param buf the buffer to save the read data. + * @param len the maximal length of data buffer + * @param offset the file pos + * + * @return the actual read data buffer length. If the returned value is 0, it + * may be reach the end of file, please check errno. + */ +ssize_t pread(int fd, void *buf, size_t len, off_t offset) +{ + ssize_t result; + off_t fpos; + struct dfs_file *file; + + if (buf == NULL) + { + rt_set_errno(-EBADF); + return -1; + } + + file = fd_get(fd); + if (file == NULL) + { + rt_set_errno(-EBADF); + + return -1; + } + + /* fpos lock */ + fpos = dfs_file_get_fpos(file); + dfs_file_lseek(file, offset, SEEK_SET); + result = dfs_file_read(file, buf, len); + dfs_file_lseek(file, fpos, SEEK_SET); + /* fpos unlock */ + dfs_file_set_fpos(file, fpos); + if (result < 0) + { + rt_set_errno(result); + + return -1; + } + + return result; +} +RTM_EXPORT(pread); + +/** + * this function is a POSIX compliant version, which will write specified data + * buffer length for an open file descriptor. + * + * @param fd the file descriptor + * @param buf the data buffer to be written. + * @param len the data buffer length. + * @param offset the file pos + * + * @return the actual written data buffer length. + */ +ssize_t pwrite(int fd, const void *buf, size_t len, off_t offset) +{ + ssize_t result; + off_t fpos; + struct dfs_file *file; + + if (buf == NULL) + { + rt_set_errno(-EBADF); + return -1; + } + + file = fd_get(fd); + if (file == NULL) + { + rt_set_errno(-EBADF); + + return -1; + } + /* fpos lock */ + fpos = dfs_file_get_fpos(file); + dfs_file_lseek(file, offset, SEEK_SET); + result = dfs_file_write(file, buf, len); + dfs_file_lseek(file, fpos, SEEK_SET); + /* fpos unlock */ + dfs_file_set_fpos(file, fpos); + if (result < 0) + { + rt_set_errno(result); + + return -1; + } + + return result; +} +RTM_EXPORT(pwrite); + /**@}*/