diff options
Diffstat (limited to 'components/dfs')
18 files changed, 2055 insertions, 672 deletions
diff --git a/components/dfs/Kconfig b/components/dfs/Kconfig index 6af2555a14..2c822cf779 100644 --- a/components/dfs/Kconfig +++ b/components/dfs/Kconfig @@ -45,6 +45,7 @@ endif config RT_USING_DFS_V2 bool "DFS v2.0" + select RT_USING_DEVICE_OPS endchoice if RT_USING_DFS_V1 @@ -170,6 +171,13 @@ endif depends on RT_USING_DFS_ROMFS default n +if RT_USING_SMART + config RT_USING_DFS_PTYFS + bool "Using Pseudo-Teletype Filesystem (UNIX98 PTY)" + depends on RT_USING_DFS_DEVFS + default y +endif + config RT_USING_DFS_CROMFS bool "Enable ReadOnly compressed file system on flash" default n diff --git a/components/dfs/dfs_v2/filesystems/devfs/devfs.c b/components/dfs/dfs_v2/filesystems/devfs/devfs.c index 7ebac59868..7818ae19be 100644 --- a/components/dfs/dfs_v2/filesystems/devfs/devfs.c +++ b/components/dfs/dfs_v2/filesystems/devfs/devfs.c @@ -13,6 +13,7 @@ #include <fcntl.h> #include <errno.h> +#include <sys/unistd.h> #include <dfs.h> #include <dfs_fs.h> @@ -20,663 +21,501 @@ #include <dfs_dentry.h> #include <dfs_mnt.h> -#include "devfs.h" - -struct device_dirent -{ - struct rt_device **devices; - uint32_t device_count; -}; - -int dfs_devfs_open(struct dfs_file *file); -int dfs_devfs_close(struct dfs_file *file); -off_t generic_dfs_lseek(struct dfs_file *file, off_t offset, int whence); -ssize_t dfs_devfs_read(struct dfs_file *file, void *buf, size_t count, off_t *pos); -ssize_t dfs_devfs_write(struct dfs_file *file, const void *buf, size_t count, off_t *pos); -int dfs_devfs_ioctl(struct dfs_file *file, int cmd, void *args); -int dfs_devfs_getdents(struct dfs_file *file, struct dirent *dirp, uint32_t count); -static int dfs_devfs_poll(struct dfs_file *file, struct rt_pollreq *req); -int dfs_devfs_flush(struct dfs_file *file); -off_t dfs_devfs_lseek(struct dfs_file *file, off_t offset, int wherece); -int dfs_devfs_truncate(struct dfs_file *file, off_t offset); -int dfs_devfs_mmap(struct dfs_file *file, struct lwp_avl_struct *mmap); -int dfs_devfs_lock(struct dfs_file *file, struct file_lock *flock); -int dfs_devfs_flock(struct dfs_file *file, int operation, struct file_lock *flock); - -int dfs_devfs_mount(struct dfs_mnt *mnt, unsigned long rwflag, const void *data); -int dfs_devfs_umount(struct dfs_mnt *mnt); -int dfs_devfs_unlink(struct dfs_dentry *dentry); -int dfs_devfs_stat(struct dfs_dentry *dentry, struct stat *st); -int dfs_devfs_statfs(struct dfs_mnt *mnt, struct statfs *buf); -static struct dfs_vnode *dfs_devfs_lookup(struct dfs_dentry *dentry); -struct dfs_vnode *dfs_devfs_create_vnode(struct dfs_dentry *dentry, int type, mode_t mode); -static int dfs_devfs_free_vnode(struct dfs_vnode *vnode); - -static const struct dfs_file_ops _dev_fops = -{ - .open = dfs_devfs_open, - .close = dfs_devfs_close, - .lseek = generic_dfs_lseek, - .read = dfs_devfs_read, - .write = dfs_devfs_write, - .ioctl = dfs_devfs_ioctl, - .getdents = dfs_devfs_getdents, - .poll = dfs_devfs_poll, - - .flush = dfs_devfs_flush, - .lseek = dfs_devfs_lseek, - .truncate = dfs_devfs_truncate, - .mmap = dfs_devfs_mmap, - .lock = dfs_devfs_lock, - .flock = dfs_devfs_flock, -}; - -static const struct dfs_filesystem_ops _devfs_ops = -{ - .name = "devfs", - - .default_fops = &_dev_fops, - .mount = dfs_devfs_mount, - .umount = dfs_devfs_umount, - .unlink = dfs_devfs_unlink, - .stat = dfs_devfs_stat, - .statfs = dfs_devfs_statfs, - .lookup = dfs_devfs_lookup, - .create_vnode = dfs_devfs_create_vnode, - .free_vnode = dfs_devfs_free_vnode, -}; - -static struct dfs_filesystem_type _devfs = +static int dfs_devfs_open(struct dfs_file *file) { - .fs_ops = &_devfs_ops, -}; + int ret = RT_EOK; -static int _device_to_mode(struct rt_device *device) -{ - int mode = 0; + RT_ASSERT(file != RT_NULL); + RT_ASSERT(file->vnode->ref_count > 0); - switch (device->type) + if (file->vnode->ref_count > 1) { - case RT_Device_Class_Char: - mode = S_IFCHR | 0777; - break; - case RT_Device_Class_Block: - mode = S_IFBLK | 0777; - break; - case RT_Device_Class_Pipe: - mode = S_IFIFO | 0777; - break; - default: - mode = S_IFCHR | 0777; - break; + if (file->vnode->type == FT_DIRECTORY + && !(file->flags & O_DIRECTORY)) + { + return -ENOENT; + } + file->fpos = 0; } - return mode; -} - -static int _devfs_root_dirent_update(struct dfs_vnode *vnode) -{ - rt_err_t result = RT_EOK; - - if (vnode) + if (!S_ISDIR(file->vnode->mode)) { - // result = rt_mutex_take(&vnode->lock, RT_WAITING_FOREVER); - result = dfs_file_lock(); - if (result == RT_EOK) + rt_device_t device = RT_NULL; + struct dfs_dentry *de = file->dentry; + char *device_name = rt_malloc(DFS_PATH_MAX); + + if (!device_name) { - rt_uint32_t count = 0; - struct device_dirent *root_dirent = (struct device_dirent*) vnode->data; - if (root_dirent) rt_free(root_dirent); + return -ENOMEM; + } - count = rt_object_get_length(RT_Object_Class_Device); - root_dirent = (struct device_dirent *)rt_malloc(sizeof(struct device_dirent) + count * sizeof(rt_device_t)); - if (root_dirent != RT_NULL) + /* skip `/dev` */ + rt_snprintf(device_name, DFS_PATH_MAX, "%s%s", de->mnt->fullpath + sizeof("/dev") - 1, de->pathname); + + device = rt_device_find(device_name + 1); + if (device) + { + file->vnode->data = device; +#ifdef RT_USING_POSIX_DEVIO + if (device->fops && device->fops->open) { - root_dirent->device_count = count; - if (count != 0) + ret = device->fops->open(file); + if (ret == RT_EOK || ret == -RT_ENOSYS) { - root_dirent->devices = (rt_device_t *)(root_dirent + 1); - rt_object_get_pointers(RT_Object_Class_Device, (rt_object_t *)root_dirent->devices, count); + ret = RT_EOK; } - else + } + else if (device->ops && file->vnode->ref_count == 1) +#else + if (device->ops && file->vnode->ref_count == 1) +#endif /* RT_USING_POSIX_DEVIO */ + { + ret = rt_device_open(device, RT_DEVICE_OFLAG_RDWR); + if (ret == RT_EOK || ret == -RT_ENOSYS) { - root_dirent->devices = RT_NULL; + ret = RT_EOK; } } - - vnode->data = root_dirent; - result = count; - dfs_file_unlock(); } } - return result; + return ret; } -static struct dfs_vnode *dfs_devfs_lookup(struct dfs_dentry *dentry) +static int dfs_devfs_close(struct dfs_file *file) { - rt_device_t device = RT_NULL; - struct dfs_vnode *vnode = RT_NULL; - const char *pathname = dentry->pathname; + int ret = RT_EOK; + rt_device_t device; - DLOG(msg, "devfs", "vnode", DLOG_MSG, "dfs_vnode_create"); - vnode = dfs_vnode_create(); - if (vnode) + RT_ASSERT(file != RT_NULL); + RT_ASSERT(file->vnode->ref_count > 0); + + if (file->vnode && file->vnode->data) { - if (pathname[0] == '/' && pathname[1] == '\0') - { - int count = _devfs_root_dirent_update(vnode); + /* get device handler */ + device = (rt_device_t)file->vnode->data; - vnode->mode = S_IFDIR | 0644; - vnode->size = count; - vnode->nlink = 1; - vnode->fops = &_dev_fops; - vnode->mnt = dentry->mnt; - vnode->type = FT_DIRECTORY; +#ifdef RT_USING_POSIX_DEVIO + if (device->fops && device->fops->close) + { + ret = device->fops->close(file); } - else + else if (file->vnode->ref_count == 1) +#else + if (device->ops && file->vnode->ref_count == 1) +#endif /* RT_USING_POSIX_DEVIO */ { - device = rt_device_find(&pathname[1]); - if (!device) - { - DLOG(msg, "devfs", "vnode", DLOG_MSG, "dfs_vnode_destroy(vnode), no-device"); - dfs_vnode_destroy(vnode); - vnode = RT_NULL; - } - else - { - vnode->mode = _device_to_mode(device); - vnode->size = device->ref_count; - vnode->nlink = 1; - vnode->fops = &_dev_fops; - vnode->data = device; - vnode->mnt = dentry->mnt; - vnode->type = FT_DEVICE; - } + /* close device handler */ + ret = rt_device_close(device); } } - return vnode; + return ret; } -struct dfs_vnode *dfs_devfs_create_vnode(struct dfs_dentry *dentry, int type, mode_t mode) +static ssize_t dfs_devfs_read(struct dfs_file *file, void *buf, size_t count, off_t *pos) { -#ifdef RT_USING_DEV_BUS - if (dentry && type == FT_DIRECTORY) + ssize_t ret = -RT_EIO; + rt_device_t device; + + RT_ASSERT(file != RT_NULL); + + if (file->vnode && file->vnode->data) { - /* regester bus device */ - if (rt_device_bus_create(&dentry->pathname[1], 0)) + /* get device handler */ + device = (rt_device_t)file->vnode->data; + +#ifdef RT_USING_POSIX_DEVIO + if (device->fops && device->fops->read) { - return dfs_devfs_lookup(dentry); + ret = device->fops->read(file, buf, count, pos); + } + else +#else + if (device->ops) +#endif /* RT_USING_POSIX_DEVIO */ + { + /* read device data */ + ret = rt_device_read(device, *pos, buf, count); + *pos += ret; } } -#endif - return RT_NULL; + return ret; } -int dfs_devfs_free_vnode(struct dfs_vnode *vnode) +static ssize_t dfs_devfs_write(struct dfs_file *file, const void *buf, size_t count, off_t *pos) { - if (S_ISDIR(vnode->mode)) + ssize_t ret = -RT_EIO; + rt_device_t device; + + RT_ASSERT(file != RT_NULL); + + if(file->vnode->data) { - struct device_dirent *root_dirent; + /* get device handler */ + device = (rt_device_t)file->vnode->data; - root_dirent = (struct device_dirent *)vnode->data; - RT_ASSERT(root_dirent != RT_NULL); + if ((file->dentry->pathname[0] == '/') && (file->dentry->pathname[1] == '\0')) + return -RT_ENOSYS; - /* release dirent */ - DLOG(msg, "devfs", "devfs", DLOG_MSG, "free root_dirent"); - rt_free(root_dirent); - return RT_EOK; +#ifdef RT_USING_POSIX_DEVIO + if (device->fops && device->fops->write) + { + ret = device->fops->write(file, buf, count, pos); + } + else +#else + if (device->ops) +#endif /* RT_USING_POSIX_DEVIO */ + { + /* read device data */ + ret = rt_device_write(device, *pos, buf, count); + *pos += ret; + } } - /* which is a device */ - vnode->data = RT_NULL; - return 0; + return ret; } -int dfs_devfs_mount(struct dfs_mnt *mnt, unsigned long rwflag, const void *data) +static int dfs_devfs_ioctl(struct dfs_file *file, int cmd, void *args) { - RT_ASSERT(mnt != RT_NULL); + int ret = RT_EOK; + rt_device_t device; - rt_atomic_add(&(mnt->ref_count), 1); - mnt->flags |= MNT_IS_LOCKED; + RT_ASSERT(file != RT_NULL); - return RT_EOK; -} + if (file->vnode && file->vnode->data) + { + /* get device handler */ + device = (rt_device_t)file->vnode->data; -int dfs_devfs_umount(struct dfs_mnt *mnt) -{ - return RT_EOK; + if ((file->dentry->pathname[0] == '/') && (file->dentry->pathname[1] == '\0')) + return -RT_ENOSYS; + +#ifdef RT_USING_POSIX_DEVIO + if (device->fops && device->fops->ioctl) + { + ret = device->fops->ioctl(file, cmd, args); + } + else +#endif /* RT_USING_POSIX_DEVIO */ + { + ret = rt_device_control(device, cmd, args); + } + } + + return ret; } -int dfs_devfs_statfs(struct dfs_mnt *mnt, struct statfs *buf) +static int dfs_devfs_getdents(struct dfs_file *file, struct dirent *dirp, uint32_t count) { - if (mnt && buf) - { - buf->f_bsize = 512; - buf->f_blocks = 2048 * 64; // 64M - buf->f_bfree = buf->f_blocks; - buf->f_bavail = buf->f_bfree; - } + int ret = -RT_ENOSYS; - return RT_EOK; + RT_ASSERT(file != RT_NULL); + + return ret; } -int dfs_devfs_ioctl(struct dfs_file *file, int cmd, void *args) +static int dfs_devfs_poll(struct dfs_file *file, struct rt_pollreq *req) { - rt_err_t result = RT_EOK; + int mask = 0; rt_device_t device; RT_ASSERT(file != RT_NULL); - /* get device handler */ - device = (rt_device_t)file->vnode->data; - RT_ASSERT(device != RT_NULL); - - if ((file->dentry->pathname[0] == '/') && (file->dentry->pathname[1] == '\0')) - return -RT_ENOSYS; + if (file->vnode && file->vnode->data) + { + /* get device handler */ + device = (rt_device_t)file->vnode->data; #ifdef RT_USING_POSIX_DEVIO - if (device->fops && device->fops->ioctl) - { - result = device->fops->ioctl(file, cmd, args); - } - else + if (device->fops && device->fops->poll) + { + mask = device->fops->poll(file, req); + } #endif /* RT_USING_POSIX_DEVIO */ - { - result = rt_device_control(device, cmd, args); } - return result; + return mask; } -ssize_t dfs_devfs_read(struct dfs_file *file, void *buf, size_t count, off_t *pos) +static int dfs_devfs_flush(struct dfs_file *file) { - int result = -RT_EIO; + int ret = RT_EOK; rt_device_t device; RT_ASSERT(file != RT_NULL); - /* get device handler */ - device = (rt_device_t)file->vnode->data; - RT_ASSERT(device != RT_NULL); - - if ((file->dentry->pathname[0] == '/') && (file->dentry->pathname[1] == '\0')) - return -RT_ENOSYS; + if (file->vnode && file->vnode->data) + { + /* get device handler */ + device = (rt_device_t)file->vnode->data; #ifdef RT_USING_POSIX_DEVIO - if (device->fops && device->fops->read) - { - result = device->fops->read(file, buf, count, pos); - } - else + if (device->fops && device->fops->flush) + { + ret = device->fops->flush(file); + } #endif /* RT_USING_POSIX_DEVIO */ - { - /* read device data */ - result = rt_device_read(device, *pos, buf, count); - *pos += result; } - return result; + return ret; } -ssize_t dfs_devfs_write(struct dfs_file *file, const void *buf, size_t count, off_t *pos) +static off_t dfs_devfs_lseek(struct dfs_file *file, off_t offset, int wherece) { - int result = -RT_EIO; + off_t ret = 0; rt_device_t device; RT_ASSERT(file != RT_NULL); - /* get device handler */ - device = (rt_device_t)file->vnode->data; - RT_ASSERT(device != RT_NULL); - - if ((file->dentry->pathname[0] == '/') && (file->dentry->pathname[1] == '\0')) - return -RT_ENOSYS; + if (file->vnode && file->vnode->data) + { + /* get device handler */ + device = (rt_device_t)file->vnode->data; #ifdef RT_USING_POSIX_DEVIO - if (device->fops && device->fops->write) - { - result = device->fops->write(file, buf, count, pos); - } - else + if (device->fops && device->fops->lseek) + { + ret = device->fops->lseek(file, offset, wherece); + } #endif /* RT_USING_POSIX_DEVIO */ - { - /* read device data */ - result = rt_device_write(device, *pos, buf, count); - *pos += result; } - return result; + return ret; } -int dfs_devfs_close(struct dfs_file *file) +static int dfs_devfs_truncate(struct dfs_file *file, off_t offset) { - rt_err_t result = RT_EOK; + int ret = RT_EOK; rt_device_t device; RT_ASSERT(file != RT_NULL); - if (!S_ISDIR(file->vnode->mode)) + if (file->vnode && file->vnode->data) { /* get device handler */ device = (rt_device_t)file->vnode->data; - RT_ASSERT(device != RT_NULL); #ifdef RT_USING_POSIX_DEVIO - if (device->fops && device->fops->close) + if (device->fops && device->fops->truncate) { - result = device->fops->close(file); + ret = device->fops->truncate(file, offset); } - else #endif /* RT_USING_POSIX_DEVIO */ - { - /* close device handler */ - result = rt_device_close(device); - } } - return result; + return ret; } -int dfs_devfs_open(struct dfs_file *file) +static int dfs_devfs_mmap(struct dfs_file *file, struct lwp_avl_struct *mmap) { - rt_err_t result = RT_EOK; + int ret = RT_EOK; + rt_device_t device; - /* open root directory */ - if ((file->dentry->pathname[0] == '/' && file->dentry->pathname[1] == '\0') || - (S_ISDIR(file->vnode->mode))) - { - /* re-open the root directory for re-scan devices */ - _devfs_root_dirent_update(file->vnode); - return RT_EOK; - } - else + RT_ASSERT(file != RT_NULL); + + if (file->vnode && file->vnode->data) { - rt_device_t device = RT_NULL; + /* get device handler */ + device = (rt_device_t)file->vnode->data; - device = (struct rt_device *)file->vnode->data; - if (device) - { #ifdef RT_USING_POSIX_DEVIO - if (device->fops && device->fops->open) - { - result = device->fops->open(file); - if (result == RT_EOK || result == -RT_ENOSYS) - { - file->fops = &_dev_fops; - return RT_EOK; - } - } - else -#endif /* RT_USING_POSIX_DEVIO */ - { - result = rt_device_open(device, RT_DEVICE_OFLAG_RDWR); - if (result == RT_EOK || result == -RT_ENOSYS) - { - file->fops = &_dev_fops; - return RT_EOK; - } - } + if (device->fops && device->fops->mmap) + { + ret = device->fops->mmap(file, mmap); } +#endif /* RT_USING_POSIX_DEVIO */ } - /* open device failed. */ - return -EIO; + return ret; } -int dfs_devfs_unlink(struct dfs_dentry *dentry) +static int dfs_devfs_lock(struct dfs_file *file, struct file_lock *flock) { -#ifdef RT_USING_DEV_BUS + int ret = RT_EOK; rt_device_t device; - device = rt_device_find(&dentry->pathname[1]); - if (device == RT_NULL) - { - return -1; - } - if (device->type != RT_Device_Class_Bus) - { - return -1; - } - rt_device_bus_destroy(device); -#endif - return RT_EOK; -} - -int dfs_devfs_stat(struct dfs_dentry *dentry, struct stat *st) -{ - int ret = RT_EOK; - const char *path = RT_NULL; - struct dfs_vnode *vnode = RT_NULL; + RT_ASSERT(file != RT_NULL); - if (dentry && dentry->vnode) + if (file->vnode && file->vnode->data) { - path = dentry->pathname; - vnode = dentry->vnode; + /* get device handler */ + device = (rt_device_t)file->vnode->data; - /* stat root directory */ - if ((path[0] == '/') && (path[1] == '\0')) - { - st->st_dev = 0; - st->st_gid = vnode->gid; - st->st_uid = vnode->uid; - st->st_ino = 0; - st->st_mode = vnode->mode; - st->st_nlink = vnode->nlink; - st->st_size = vnode->size; - st->st_mtim.tv_nsec = vnode->mtime.tv_nsec; - st->st_mtim.tv_sec = vnode->mtime.tv_sec; - st->st_ctim.tv_nsec = vnode->ctime.tv_nsec; - st->st_ctim.tv_sec = vnode->ctime.tv_sec; - st->st_atim.tv_nsec = vnode->atime.tv_nsec; - st->st_atim.tv_sec = vnode->atime.tv_sec; - } - else +#ifdef RT_USING_POSIX_DEVIO + if (device->fops && device->fops->lock) { - rt_device_t device; - - device = rt_device_find(&path[1]); - if (device != RT_NULL) - { - st->st_dev = 0; - st->st_gid = vnode->gid; - st->st_uid = vnode->uid; - st->st_ino = 0; - st->st_mode = vnode->mode; - st->st_nlink = vnode->nlink; - st->st_size = vnode->size; - st->st_mtim.tv_nsec = vnode->mtime.tv_nsec; - st->st_mtim.tv_sec = vnode->mtime.tv_sec; - st->st_ctim.tv_nsec = vnode->ctime.tv_nsec; - st->st_ctim.tv_sec = vnode->ctime.tv_sec; - st->st_atim.tv_nsec = vnode->atime.tv_nsec; - st->st_atim.tv_sec = vnode->atime.tv_sec; - } - else - { - ret = -ENOENT; - } + ret = device->fops->lock(file, flock); } +#endif /* RT_USING_POSIX_DEVIO */ } return ret; } -int dfs_devfs_getdents(struct dfs_file *file, struct dirent *dirp, uint32_t count) +static int dfs_devfs_flock(struct dfs_file *file, int operation, struct file_lock *flock) { - rt_uint32_t index; - rt_object_t object; - struct dirent *d; - struct device_dirent *root_dirent; - - root_dirent = (struct device_dirent *)file->vnode->data; - RT_ASSERT(root_dirent != RT_NULL); + int ret = RT_EOK; + rt_device_t device; - /* make integer count */ - count = (count / sizeof(struct dirent)); - if (count == 0) - return -EINVAL; + RT_ASSERT(file != RT_NULL); - for (index = 0; index < count && index + file->fpos < root_dirent->device_count; index ++) + if (file->vnode && file->vnode->data) { - object = (rt_object_t)root_dirent->devices[file->fpos + index]; + /* get device handler */ + device = (rt_device_t)file->vnode->data; - d = dirp + index; - d->d_type = DT_REG; - d->d_namlen = RT_NAME_MAX; - d->d_reclen = (rt_uint16_t)sizeof(struct dirent); - rt_strncpy(d->d_name, object->name, RT_NAME_MAX); - d->d_name[RT_NAME_MAX] = '\0'; +#ifdef RT_USING_POSIX_DEVIO + if (device->fops && device->fops->flock) + { + ret = device->fops->flock(file, operation, flock); + } +#endif /* RT_USING_POSIX_DEVIO */ } - file->fpos += index; - - return index * sizeof(struct dirent); + return ret; } -static int dfs_devfs_poll(struct dfs_file *file, struct rt_pollreq *req) +static const struct dfs_file_ops _dev_fops = { - int mask = 0; - rt_device_t device; + .open = dfs_devfs_open, + .close = dfs_devfs_close, + .lseek = generic_dfs_lseek, + .read = dfs_devfs_read, + .write = dfs_devfs_write, + .ioctl = dfs_devfs_ioctl, + .getdents = dfs_devfs_getdents, + .poll = dfs_devfs_poll, - /* get device handler */ - device = (rt_device_t)file->vnode->data; - RT_ASSERT(device != RT_NULL); - -#ifdef RT_USING_POSIX_DEVIO - if (device->fops && device->fops->poll) - { - mask = device->fops->poll(file, req); - } -#endif /* RT_USING_POSIX_DEVIO */ + .flush = dfs_devfs_flush, + .lseek = dfs_devfs_lseek, + .truncate = dfs_devfs_truncate, + .mmap = dfs_devfs_mmap, + .lock = dfs_devfs_lock, + .flock = dfs_devfs_flock, +}; - return mask; +const struct dfs_file_ops *dfs_devfs_fops(void) +{ + return &_dev_fops; } -int dfs_devfs_flush(struct dfs_file *file) +mode_t dfs_devfs_device_to_mode(struct rt_device *device) { - int ret = 0; - rt_device_t device; + mode_t mode = 0; - /* get device handler */ - device = (rt_device_t)file->vnode->data; - RT_ASSERT(device != RT_NULL); - -#ifdef RT_USING_POSIX_DEVIO - if (device->fops && device->fops->flush) + switch (device->type) { - ret = device->fops->flush(file); + case RT_Device_Class_Char: + mode = S_IFCHR | 0777; + break; + case RT_Device_Class_Block: + mode = S_IFBLK | 0777; + break; + case RT_Device_Class_Pipe: + mode = S_IFIFO | 0777; + break; + default: + mode = S_IFCHR | 0777; + break; } -#endif /* RT_USING_POSIX_DEVIO */ - return ret; + return mode; } -off_t dfs_devfs_lseek(struct dfs_file *file, off_t offset, int wherece) +static void dfs_devfs_mkdir(const char *fullpath, mode_t mode) { - off_t ret = 0; - rt_device_t device; + int len = rt_strlen(fullpath); + char *path = (char *)rt_malloc(len); - /* get device handler */ - device = (rt_device_t)file->vnode->data; - RT_ASSERT(device != RT_NULL); - -#ifdef RT_USING_POSIX_DEVIO - if (device->fops && device->fops->lseek) + if (path) { - ret = device->fops->lseek(file, offset, wherece); - } -#endif /* RT_USING_POSIX_DEVIO */ + int index = len - 1; - return ret; -} + rt_strcpy(path, fullpath); -int dfs_devfs_truncate(struct dfs_file *file, off_t offset) -{ - int ret = 0; - rt_device_t device; + if (path[index] == '/') + { + path[index] = '\0'; + index --; + } - /* get device handler */ - device = (rt_device_t)file->vnode->data; - RT_ASSERT(device != RT_NULL); + while (path[index] != '/' && index >= 0) + { + index --; + } -#ifdef RT_USING_POSIX_DEVIO - if (device->fops && device->fops->truncate) - { - ret = device->fops->truncate(file, offset); - } -#endif /* RT_USING_POSIX_DEVIO */ + path[index] = '\0'; - return ret; -} + if (index > 0 && access(path, 0) != 0) + { + int i = 0; -int dfs_devfs_mmap(struct dfs_file *file, struct lwp_avl_struct *mmap) -{ - int ret = 0; - rt_device_t device; + if (path[i] == '/') + { + i ++; + } - /* get device handler */ - device = (rt_device_t)file->vnode->data; - RT_ASSERT(device != RT_NULL); + while (index > i) + { + if (path[i] == '/') + { + path[i] = '\0'; + mkdir(path, mode); + path[i] = '/'; + } -#ifdef RT_USING_POSIX_DEVIO - if (device->fops && device->fops->mmap) - { - ret = device->fops->mmap(file, mmap); - } -#endif /* RT_USING_POSIX_DEVIO */ + i ++; + } - return ret; + mkdir(path, mode); + } + } } -int dfs_devfs_lock(struct dfs_file *file, struct file_lock *flock) +void dfs_devfs_device_add(rt_device_t device) { - int ret = 0; - rt_device_t device; - - /* get device handler */ - device = (rt_device_t)file->vnode->data; - RT_ASSERT(device != RT_NULL); + int fd; + char path[512]; -#ifdef RT_USING_POSIX_DEVIO - if (device->fops && device->fops->lock) + if (device) { - ret = device->fops->lock(file, flock); - } -#endif /* RT_USING_POSIX_DEVIO */ + rt_snprintf(path, 512, "/dev/%s", device->parent.name); - return ret; -} - -int dfs_devfs_flock(struct dfs_file *file, int operation, struct file_lock *flock) -{ - int ret = 0; - rt_device_t device; + if (access(path, 0) != 0) + { + mode_t mode = dfs_devfs_device_to_mode(device); - /* get device handler */ - device = (rt_device_t)file->vnode->data; - RT_ASSERT(device != RT_NULL); + dfs_devfs_mkdir(path, mode); -#ifdef RT_USING_POSIX_DEVIO - if (device->fops && device->fops->flock) - { - ret = device->fops->flock(file, operation, flock); + fd = open(path, O_RDWR | O_CREAT, mode); + if (fd >= 0) + { + close(fd); + } + } } -#endif /* RT_USING_POSIX_DEVIO */ - - return ret; } -int dfs_devfs_init(void) +int dfs_devfs_update(void) { - /* register devfs file system */ - dfs_register(&_devfs); + int count = rt_object_get_length(RT_Object_Class_Device); + if (count > 0) + { + rt_device_t *devices = rt_malloc(count * sizeof(rt_device_t)); + if (devices) + { + rt_object_get_pointers(RT_Object_Class_Device, (rt_object_t *)devices, count); - dfs_mount(RT_NULL, "/dev", "devfs", 0, RT_NULL); + for (int index = 0; index < count; index ++) + { + dfs_devfs_device_add(devices[index]); + } + rt_free(devices); + } + } - return 0; + return count; } -INIT_COMPONENT_EXPORT(dfs_devfs_init); - diff --git a/components/dfs/dfs_v2/filesystems/devfs/devfs.h b/components/dfs/dfs_v2/filesystems/devfs/devfs.h index acaae11f2f..e80b44ee09 100644 --- a/components/dfs/dfs_v2/filesystems/devfs/devfs.h +++ b/components/dfs/dfs_v2/filesystems/devfs/devfs.h @@ -10,6 +10,9 @@ #ifndef __DEVICE_FS_H__ #define __DEVICE_FS_H__ -int dfs_devfs_init(void); +const struct dfs_file_ops *dfs_devfs_fops(void); +mode_t dfs_devfs_device_to_mode(struct rt_device *device); +void dfs_devfs_device_add(rt_device_t device); +int dfs_devfs_update(void); #endif diff --git a/components/dfs/dfs_v2/filesystems/devfs/devtmpfs.c b/components/dfs/dfs_v2/filesystems/devfs/devtmpfs.c new file mode 100644 index 0000000000..3bea0c16df --- /dev/null +++ b/components/dfs/dfs_v2/filesystems/devfs/devtmpfs.c @@ -0,0 +1,678 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-10-24 flybreak the first version + * 2023-02-01 xqyjlj fix cannot open the same file repeatedly in 'w' mode + * 2023-09-20 zmq810150896 adds truncate functionality and standardized unlink adaptations + * 2023-12-02 Shell Support of dynamic device + */ + +#include <rthw.h> +#include <rtthread.h> +#include <dfs.h> +#include <dfs_fs.h> +#include <dfs_dentry.h> +#include <dfs_file.h> +#include <dfs_mnt.h> +#include <devfs.h> +#include <unistd.h> + + +#define TMPFS_MAGIC 0x0B0B0B0B +#define TMPFS_TYPE_FILE 0x00 +#define TMPFS_TYPE_DIR 0x01 +#define TMPFS_TYPE_DYN_DEV 0x02 /* dynamic device */ + +struct devtmpfs_sb; + +struct devtmpfs_file +{ + char name[DIRENT_NAME_MAX]; /* file name */ + + rt_uint32_t type; /* file type */ + rt_list_t subdirs; /* file subdir list */ + rt_list_t sibling; /* file sibling list */ + + struct devtmpfs_sb *sb; /* superblock ptr */ + + rt_uint32_t mode; + char *link; +}; + +struct devtmpfs_sb +{ + rt_uint32_t magic; /* TMPFS_MAGIC */ + struct devtmpfs_file root; /* root dir */ + rt_size_t df_size; /* df size */ + rt_list_t sibling; /* sb sibling list */ + struct rt_spinlock lock; /* tmpfs lock */ +}; + +static struct dfs_file_ops _default_fops = { 0 }; + +static int _path_separate(const char *path, char *parent_path, char *file_name) +{ + const char *path_p, *path_q; + + RT_ASSERT(path[0] == '/'); + + file_name[0] = '\0'; + path_p = path_q = &path[1]; +__next_dir: + while (*path_q != '/' && *path_q != '\0') + { + path_q++; + } + if (path_q != path_p) /*sub dir*/ + { + if (*path_q != '\0') + { + path_q++; + path_p = path_q; + goto __next_dir; + } + else /* Last level dir */ + { + rt_memcpy(parent_path, path, path_p - path - 1); + parent_path[path_p - path - 1] = '\0'; + rt_memcpy(file_name, path_p, path_q - path_p); + file_name[path_q - path_p] = '\0'; + } + } + if (parent_path[0] == 0) + { + parent_path[0] = '/'; + parent_path[1] = '\0'; + } + //LOG_D("parent_path: %s", parent_path); + //LOG_D("file_name: %s", file_name); + + return 0; +} + +static int _get_subdir(const char *path, char *name) +{ + const char *subpath = path; + while (*subpath == '/' && *subpath) + subpath ++; + while (*subpath != '/' && *subpath) + { + *name = *subpath; + name ++; + subpath ++; + } + return 0; +} + +#if 0 +static int _free_subdir(struct devtmpfs_file *dfile) +{ + struct devtmpfs_file *file; + rt_list_t *list, *temp_list; + struct devtmpfs_sb *superblock; + + RT_ASSERT(dfile->type == TMPFS_TYPE_DIR); + + rt_list_for_each_safe(list, temp_list, &dfile->subdirs) + { + file = rt_list_entry(list, struct devtmpfs_file, sibling); + if (file->type == TMPFS_TYPE_DIR) + { + _free_subdir(file); + } + + if (file->link) + { + rt_free(file->link); + } + + superblock = file->sb; + RT_ASSERT(superblock); + + rt_spin_lock(&superblock->lock); + rt_list_remove(&(file->sibling)); + rt_spin_unlock(&superblock->lock); + + rt_free(file); + } + return 0; +} +#endif + +static int devtmpfs_mount(struct dfs_mnt *mnt, unsigned long rwflag, const void *data) +{ + struct devtmpfs_sb *superblock; + + superblock = rt_calloc(1, sizeof(struct devtmpfs_sb)); + if (superblock) + { + superblock->df_size = sizeof(struct devtmpfs_sb); + superblock->magic = TMPFS_MAGIC; + rt_list_init(&superblock->sibling); + + superblock->root.name[0] = '/'; + superblock->root.sb = superblock; + superblock->root.type = TMPFS_TYPE_DIR; + superblock->root.mode = S_IFDIR | (S_IRUSR | S_IRGRP | S_IROTH) | (S_IXUSR | S_IXGRP | S_IXOTH); + rt_list_init(&superblock->root.sibling); + rt_list_init(&superblock->root.subdirs); + + rt_spin_lock_init(&superblock->lock); + + mnt->data = superblock; + } + else + { + return -RT_ERROR; + } + + return RT_EOK; +} + +static int devtmpfs_unmount(struct dfs_mnt *mnt) +{ +#if 0 + struct devtmpfs_sb *superblock; + + /* FIXME: don't unmount on busy. */ + superblock = (struct devtmpfs_sb *)mnt->data; + RT_ASSERT(superblock != NULL); + + mnt->data = NULL; + _free_subdir(&(superblock->root)); + rt_free(superblock); +#endif + return -RT_ERROR; +} + +static struct devtmpfs_file *devtmpfs_file_lookup(struct devtmpfs_sb *superblock, const char *path) +{ + const char *subpath, *curpath, *filename = RT_NULL; + char subdir_name[DIRENT_NAME_MAX]; + struct devtmpfs_file *file, *curfile; + rt_list_t *list; + + subpath = path; + while (*subpath == '/' && *subpath) + subpath ++; + + if (! *subpath) /* is root directory */ + { + return &(superblock->root); + } + + curpath = subpath; + curfile = &superblock->root; + +find_subpath: + while (*subpath != '/' && *subpath) + subpath ++; + + if (! *subpath) /* is last directory */ + filename = curpath; + else + subpath ++; /* skip '/' */ + + memset(subdir_name, 0, DIRENT_NAME_MAX); + _get_subdir(curpath, subdir_name); + + rt_spin_lock(&superblock->lock); + + rt_list_for_each(list, &curfile->subdirs) + { + file = rt_list_entry(list, struct devtmpfs_file, sibling); + if (filename) /* find file */ + { + if (rt_strcmp(file->name, filename) == 0) + { + rt_spin_unlock(&superblock->lock); + return file; + } + } + else if (rt_strcmp(file->name, subdir_name) == 0) + { + curpath = subpath; + curfile = file; + rt_spin_unlock(&superblock->lock); + goto find_subpath; + } + } + rt_spin_unlock(&superblock->lock); + /* not found */ + return NULL; +} + +static int devtmpfs_statfs(struct dfs_mnt *mnt, struct statfs *buf) +{ + struct devtmpfs_sb *superblock; + + RT_ASSERT(mnt != NULL); + RT_ASSERT(buf != NULL); + + superblock = (struct devtmpfs_sb *)mnt->data; + RT_ASSERT(superblock != NULL); + + buf->f_bsize = 512; + buf->f_blocks = (superblock->df_size + 511) / 512; + buf->f_bfree = 1; + buf->f_bavail = buf->f_bfree; + + return RT_EOK; +} + +static int devtmpfs_stat(struct dfs_dentry *dentry, struct stat *st) +{ + struct dfs_vnode *vnode; + + if (dentry && dentry->vnode) + { + vnode = dentry->vnode; + + st->st_dev = (dev_t)(long)(dentry->mnt->dev_id); + st->st_ino = (ino_t)dfs_dentry_full_path_crc32(dentry); + + st->st_gid = vnode->gid; + st->st_uid = vnode->uid; + st->st_mode = vnode->mode; + st->st_nlink = vnode->nlink; + st->st_size = vnode->size; + st->st_mtim.tv_nsec = vnode->mtime.tv_nsec; + st->st_mtim.tv_sec = vnode->mtime.tv_sec; + st->st_ctim.tv_nsec = vnode->ctime.tv_nsec; + st->st_ctim.tv_sec = vnode->ctime.tv_sec; + st->st_atim.tv_nsec = vnode->atime.tv_nsec; + st->st_atim.tv_sec = vnode->atime.tv_sec; + } + + return RT_EOK; +} + +static int devtmpfs_getdents(struct dfs_file *file, struct dirent *dirp, uint32_t count) +{ + struct devtmpfs_file *d_file; + struct devtmpfs_sb *superblock; + + RT_ASSERT(file); + RT_ASSERT(file->dentry); + RT_ASSERT(file->dentry->mnt); + + superblock = (struct devtmpfs_sb *)file->dentry->mnt->data; + RT_ASSERT(superblock); + + d_file = devtmpfs_file_lookup(superblock, file->dentry->pathname); + if (d_file) + { + rt_size_t index, end; + struct dirent *d; + struct devtmpfs_file *n_file; + rt_list_t *list; + + /* make integer count */ + count = (count / sizeof(struct dirent)); + if (count == 0) + { + return -EINVAL; + } + + end = file->fpos + count; + index = 0; + count = 0; + + rt_list_for_each(list, &d_file->subdirs) + { + if (index >= (rt_size_t)file->fpos) + { + n_file = rt_list_entry(list, struct devtmpfs_file, sibling); + + d = dirp + count; + if (n_file->type == TMPFS_TYPE_FILE) + { + d->d_type = DT_REG; + } + if (n_file->type == TMPFS_TYPE_DIR) + { + d->d_type = DT_DIR; + } + + d->d_reclen = (rt_uint16_t)sizeof(struct dirent); + rt_strncpy(d->d_name, n_file->name, DIRENT_NAME_MAX); + d->d_namlen = rt_strlen(d->d_name); + + count += 1; + file->fpos += 1; + } + index += 1; + if (index >= end) + { + break; + } + } + } + + return count * sizeof(struct dirent); +} + +static int devtmpfs_symlink(struct dfs_dentry *parent_dentry, const char *target, const char *linkpath) +{ + int ret = RT_EOK; + struct devtmpfs_file *p_file, *l_file; + struct devtmpfs_sb *superblock; + + RT_ASSERT(parent_dentry); + RT_ASSERT(parent_dentry->mnt); + + superblock = (struct devtmpfs_sb *)parent_dentry->mnt->data; + RT_ASSERT(superblock); + + p_file = devtmpfs_file_lookup(superblock, parent_dentry->pathname); + if (p_file) + { + l_file = (struct devtmpfs_file *)rt_calloc(1, sizeof(struct devtmpfs_file)); + if (l_file) + { + superblock->df_size += sizeof(struct devtmpfs_file); + + strncpy(l_file->name, linkpath, DIRENT_NAME_MAX - 1); + + rt_list_init(&(l_file->subdirs)); + rt_list_init(&(l_file->sibling)); + l_file->sb = superblock; + l_file->type = TMPFS_TYPE_FILE; + l_file->mode = p_file->mode; + l_file->mode &= ~S_IFMT; + l_file->mode |= S_IFLNK; + l_file->link = rt_strdup(target); + + rt_spin_lock(&superblock->lock); + rt_list_insert_after(&(p_file->subdirs), &(l_file->sibling)); + rt_spin_unlock(&superblock->lock); + } + } + + return ret; +} + +static int devtmpfs_readlink(struct dfs_dentry *dentry, char *buf, int len) +{ + int ret = 0; + struct devtmpfs_file *d_file; + struct devtmpfs_sb *superblock; + + RT_ASSERT(dentry); + RT_ASSERT(dentry->mnt); + + superblock = (struct devtmpfs_sb *)dentry->mnt->data; + RT_ASSERT(superblock); + + d_file = devtmpfs_file_lookup(superblock, dentry->pathname); + if (d_file) + { + if (d_file->link) + { + if (d_file->type == TMPFS_TYPE_DYN_DEV) + { + rt_device_t device = (void *)d_file->link; + buf[0] = '\0'; + ret = device->readlink(device, buf, len); + if (ret == 0) + { + buf[len - 1] = '\0'; + ret = rt_strlen(buf); + } + else + { + ret = 0; + } + } + else + { + rt_strncpy(buf, (const char *)d_file->link, len); + buf[len - 1] = '\0'; + ret = rt_strlen(buf); + } + } + } + + return ret; +} + +static int devtmpfs_unlink(struct dfs_dentry *dentry) +{ + struct devtmpfs_file *d_file; + struct devtmpfs_sb *superblock; + + RT_ASSERT(dentry); + RT_ASSERT(dentry->mnt); + + superblock = (struct devtmpfs_sb *)dentry->mnt->data; + RT_ASSERT(superblock); + + d_file = devtmpfs_file_lookup(superblock, dentry->pathname); + if (d_file) + { + if (d_file->link && d_file->type != TMPFS_TYPE_DYN_DEV) + { + rt_free(d_file->link); + } + + rt_spin_lock(&superblock->lock); + rt_list_remove(&(d_file->sibling)); + rt_spin_unlock(&superblock->lock); + + rt_free(d_file); + } + + return RT_EOK; +} + +static int devtmpfs_setattr(struct dfs_dentry *dentry, struct dfs_attr *attr) +{ + struct devtmpfs_file *d_file; + struct devtmpfs_sb *superblock; + + RT_ASSERT(dentry); + RT_ASSERT(dentry->mnt); + + superblock = (struct devtmpfs_sb *)dentry->mnt->data; + RT_ASSERT(superblock); + + d_file = devtmpfs_file_lookup(superblock, dentry->pathname); + if (d_file) + { + d_file->mode &= ~0xFFF; + d_file->mode |= attr->st_mode & 0xFFF; + return RT_EOK; + } + + return -RT_ERROR; +} + +static struct dfs_vnode *devtmpfs_create_vnode(struct dfs_dentry *dentry, int type, mode_t mode) +{ + struct dfs_vnode *vnode = RT_NULL; + struct devtmpfs_sb *superblock; + struct devtmpfs_file *d_file, *p_file; + char parent_path[DFS_PATH_MAX], file_name[DIRENT_NAME_MAX]; + + if (dentry == NULL || dentry->mnt == NULL || dentry->mnt->data == NULL) + { + return NULL; + } + + superblock = (struct devtmpfs_sb *)dentry->mnt->data; + RT_ASSERT(superblock != NULL); + + vnode = dfs_vnode_create(); + if (vnode) + { + /* find parent file */ + _path_separate(dentry->pathname, parent_path, file_name); + if (file_name[0] == '\0') /* it's root dir */ + { + dfs_vnode_destroy(vnode); + return NULL; + } + + /* open parent directory */ + p_file = devtmpfs_file_lookup(superblock, parent_path); + if (p_file == NULL) + { + dfs_vnode_destroy(vnode); + return NULL; + } + + /* create a file entry */ + d_file = (struct devtmpfs_file *)rt_calloc(1, sizeof(struct devtmpfs_file)); + if (d_file == NULL) + { + dfs_vnode_destroy(vnode); + return NULL; + } + + superblock->df_size += sizeof(struct devtmpfs_file); + + strncpy(d_file->name, file_name, DIRENT_NAME_MAX); + + rt_list_init(&(d_file->subdirs)); + rt_list_init(&(d_file->sibling)); + d_file->sb = superblock; + + vnode->nlink = 1; + vnode->size = 0; + vnode->mode = mode; + vnode->mnt = dentry->mnt; + vnode->fops = &_default_fops; + + if (type == FT_DIRECTORY) + { + d_file->type = TMPFS_TYPE_DIR; + vnode->type = FT_DIRECTORY; + vnode->mode &= ~S_IFMT; + vnode->mode |= S_IFDIR; + } + else + { + d_file->type = TMPFS_TYPE_FILE; + vnode->type = FT_DEVICE; + } + + d_file->mode = vnode->mode; + + rt_spin_lock(&superblock->lock); + rt_list_insert_after(&(p_file->subdirs), &(d_file->sibling)); + rt_spin_unlock(&superblock->lock); + } + + return vnode; +} + +static struct dfs_vnode *devtmpfs_lookup(struct dfs_dentry *dentry) +{ + struct dfs_vnode *vnode = RT_NULL; + struct devtmpfs_sb *superblock; + struct devtmpfs_file *d_file; + + if (dentry == NULL || dentry->mnt == NULL || dentry->mnt->data == NULL) + { + return NULL; + } + + superblock = (struct devtmpfs_sb *)dentry->mnt->data; + + d_file = devtmpfs_file_lookup(superblock, dentry->pathname); + if (d_file) + { + vnode = dfs_vnode_create(); + if (vnode) + { + vnode->nlink = 1; + vnode->size = 0; + vnode->mnt = dentry->mnt; + vnode->fops = &_default_fops; + vnode->mode = d_file->mode; + + if (d_file->type == TMPFS_TYPE_DIR) + { + vnode->type = FT_DIRECTORY; + } + else if (d_file->link) + { + vnode->type = FT_SYMLINK; + } + else + { + vnode->type = FT_DEVICE; + } + } + } + else + { + rt_device_t device = RT_NULL; + + device = rt_device_find(&dentry->pathname[1]); + if (device) + { + vnode = devtmpfs_create_vnode(dentry, FT_REGULAR, dfs_devfs_device_to_mode(device)); + if (device->flag & RT_DEVICE_FLAG_DYNAMIC) + { + d_file = devtmpfs_file_lookup(superblock, dentry->pathname); + d_file->type = TMPFS_TYPE_DYN_DEV; + d_file->link = (char *)device; + } + } + } + + return vnode; +} + +static int devtmpfs_free_vnode(struct dfs_vnode *vnode) +{ + return RT_EOK; +} + +static const struct dfs_filesystem_ops _devtmpfs_ops = +{ + .name = "devtmpfs", + .flags = DFS_FS_FLAG_DEFAULT, + .default_fops = &_default_fops, + + .mount = devtmpfs_mount, + .umount = devtmpfs_unmount, + + .symlink = devtmpfs_symlink, + .readlink = devtmpfs_readlink, + + .unlink = devtmpfs_unlink, + .setattr = devtmpfs_setattr, + + .statfs = devtmpfs_statfs, + .stat = devtmpfs_stat, + + .lookup = devtmpfs_lookup, + .create_vnode = devtmpfs_create_vnode, + .free_vnode = devtmpfs_free_vnode +}; + +static struct dfs_filesystem_type _devtmpfs = +{ + .fs_ops = &_devtmpfs_ops, +}; + +int dfs_devtmpfs_init(void) +{ + _default_fops = *dfs_devfs_fops(); + _default_fops.getdents = devtmpfs_getdents; + + /* register file system */ + dfs_register(&_devtmpfs); + + dfs_mount(RT_NULL, "/dev", "devtmpfs", 0, RT_NULL); + dfs_devfs_update(); + + return 0; +} +INIT_COMPONENT_EXPORT(dfs_devtmpfs_init); diff --git a/components/dfs/dfs_v2/filesystems/mqueue/dfs_mqueue.c b/components/dfs/dfs_v2/filesystems/mqueue/dfs_mqueue.c index 70b34ef3cb..4546455a31 100644 --- a/components/dfs/dfs_v2/filesystems/mqueue/dfs_mqueue.c +++ b/components/dfs/dfs_v2/filesystems/mqueue/dfs_mqueue.c @@ -145,7 +145,7 @@ static struct dfs_vnode *dfs_mqueue_create_vnode(struct dfs_dentry *dentry, int } mq_file->msg_size = 8192; mq_file->max_msgs = 10; - strncpy(mq_file->name, dentry->pathname + 1, RT_NAME_MAX); + strncpy(mq_file->name, dentry->pathname + 1, RT_NAME_MAX - 1); dfs_mqueue_insert_after(&(mq_file->list)); } diff --git a/components/dfs/dfs_v2/filesystems/ptyfs/README.md b/components/dfs/dfs_v2/filesystems/ptyfs/README.md new file mode 100644 index 0000000000..1f805df80c --- /dev/null +++ b/components/dfs/dfs_v2/filesystems/ptyfs/README.md @@ -0,0 +1,5 @@ +# The Pseudo Terminal Filesystem + +The device register on ptyfs is also registered in device frameworks with `rt_device_register()`. + +It's possible to mount a new ptyfs instance on another path. Each instance is isolated to each other. And they don't share the id system. But generally speaking, you have to mount the ptyfs on `/dev` root, since all the file nodes in ptyfs are devices. diff --git a/components/dfs/dfs_v2/filesystems/ptyfs/SConscript b/components/dfs/dfs_v2/filesystems/ptyfs/SConscript new file mode 100644 index 0000000000..c0f8f39587 --- /dev/null +++ b/components/dfs/dfs_v2/filesystems/ptyfs/SConscript @@ -0,0 +1,11 @@ +# RT-Thread building script for component + +from building import * + +cwd = GetCurrentDir() +src = Glob('*.c') +CPPPATH = [cwd] + +group = DefineGroup('Filesystem', src, depend = ['RT_USING_DFS', 'RT_USING_DFS_PTYFS'], CPPPATH = CPPPATH) + +Return('group') diff --git a/components/dfs/dfs_v2/filesystems/ptyfs/ptyfs.c b/components/dfs/dfs_v2/filesystems/ptyfs/ptyfs.c new file mode 100644 index 0000000000..c6f4f3d52d --- /dev/null +++ b/components/dfs/dfs_v2/filesystems/ptyfs/ptyfs.c @@ -0,0 +1,658 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-12-02 Shell init ver. + */ +#define DBG_TAG "filesystem.ptyfs" +#define DBG_LVL DBG_INFO +#include <rtdbg.h> + +#include "ptyfs.h" + +#include <dfs.h> +#include <dfs_fs.h> +#include <dfs_dentry.h> +#include <dfs_file.h> +#include <dfs_mnt.h> +#include <devfs.h> +#include <rid_bitmap.h> +#include <rthw.h> +#include <rtthread.h> +#include <terminal/terminal.h> + +#include <dirent.h> +#include <unistd.h> + +#ifndef S_IRWXUGO +#define S_IRWXUGO (S_IRWXU | S_IRWXG | S_IRWXO) +#endif /* S_IRWXUGO */ +#ifndef S_IALLUGO +#define S_IALLUGO (S_ISUID | S_ISGID | S_ISVTX | S_IRWXUGO) +#endif /* S_IALLUGO */ +#ifndef S_IRUGO +#define S_IRUGO (S_IRUSR | S_IRGRP | S_IROTH) +#endif /* S_IRUGO */ +#ifndef S_IWUGO +#define S_IWUGO (S_IWUSR | S_IWGRP | S_IWOTH) +#endif /* S_IWUGO */ +#ifndef S_IXUGO +#define S_IXUGO (S_IXUSR | S_IXGRP | S_IXOTH) +#endif /* S_IXUGO */ + +#define PTYFS_MAGIC 0x9D94A07D +#define PTYFS_TYPE_DIR 0x00 +#define PTYFS_TYPE_FILE_PTMX 0x01 +#define PTYFS_TYPE_FILE_SLAVE 0x02 + +/* TODO: using Symbolic permission, but not ours */ +#define PTMX_DEFAULT_FILE_MODE (S_IFCHR | 0666) +#define PTS_DEFAULT_FILE_MODE (S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP) +#define ROOT_DEFUALT_FILE_MODE (S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR) + +struct ptyfs_sb; + +struct ptyfs_file +{ + char basename[DIRENT_NAME_MAX]; /* file name */ + rt_uint32_t mode; /* file modes allowed */ + rt_uint32_t type; /* file type */ + rt_list_t subdirs; /* file subdir list */ + rt_list_t ent_node; /* entry node in subdir list */ + struct ptyfs_sb *sb; /* superblock ptr */ + rt_device_t device; /* device binding on this file */ +}; + +struct ptyfs_sb +{ + struct rt_device ptmx_device; /* ptmx device */ + struct rt_mutex lock; /* tmpfs lock */ + struct ptyfs_file root_file; /* root dir */ + struct ptyfs_file ptmx_file; /* `/ptmx` file */ + struct rid_bitmap ptsno_pool; /* pts number pool */ + rt_uint32_t magic; /* PTYFS_MAGIC */ + rt_size_t df_size; /* df size */ + rt_list_t sibling; /* sb sibling list */ + struct dfs_mnt *mount; /* mount data */ + + /** + * Note: This upper limit is set to protect kernel memory from draining + * out by the application if it keeps allocating pty devices. + * + * Still, current implementation of bitmap can not efficiently use the + * memory + */ + rt_bitmap_t + ptsno_pool_bitset[LWP_PTY_MAX_PARIS_LIMIT / (sizeof(rt_bitmap_t) * 8)]; +}; + +static struct dfs_file_ops _default_fops; + +static int _split_out_subdir(const char *path, char *name) +{ + const char *subpath = path; + + while (*subpath == '/' && *subpath) + { + subpath++; + } + + while (*subpath != '/' && *subpath) + { + *name++ = *subpath++; + } + + *name = '\0'; + return 0; +} + +static rt_err_t ptyfile_init(struct ptyfs_file *file, struct ptyfs_sb *sb, + const char *name, rt_uint32_t type, + rt_uint32_t mode, rt_device_t device) +{ + if (name) + strncpy(file->basename, name, sizeof(file->basename)); + + file->type = type; + file->mode = mode; + rt_list_init(&file->subdirs); + rt_list_init(&file->ent_node); + file->sb = sb; + file->device = device; + + return 0; +} + +static rt_err_t ptyfile_add_to_root(struct ptyfs_sb *sb, + struct ptyfs_file *new_file) +{ + struct ptyfs_file *root_file = &sb->root_file; + + /* update super block */ + sb->df_size += sizeof(struct ptyfs_file); + + rt_mutex_take(&sb->lock, RT_WAITING_FOREVER); + rt_list_insert_after(&(root_file->subdirs), &(new_file->ent_node)); + rt_mutex_release(&sb->lock); + + return 0; +} + +static rt_err_t ptyfile_remove_from_root(struct ptyfs_sb *sb, + struct ptyfs_file *rm_file) +{ + /* update super block */ + sb->df_size -= sizeof(struct ptyfs_file); + + rt_mutex_take(&sb->lock, RT_WAITING_FOREVER); + rt_list_remove(&(rm_file->ent_node)); + rt_mutex_release(&sb->lock); + + return 0; +} + +static struct ptyfs_file *ptyfile_lookup(struct ptyfs_sb *superblock, + const char *path) +{ + const char *subpath_iter, *curpath_iter, *basename = RT_NULL; + char subdir_name[DIRENT_NAME_MAX]; + struct ptyfs_file *curfile, *found_file = RT_NULL; + rt_list_t *list; + int do_path_resolve = 1; + + subpath_iter = path; + + /* skip starting "/" */ + while (*subpath_iter == '/') subpath_iter++; + if (!*subpath_iter) + { + return &(superblock->root_file); + } + + curpath_iter = subpath_iter; + curfile = &superblock->root_file; + + /* resolve chain of files splited from path one by one */ + while (do_path_resolve) + { + do_path_resolve = 0; + + /* splitout sub-directory or basename */ + while (*subpath_iter != '/' && *subpath_iter) subpath_iter++; + if (!*subpath_iter) + { + basename = curpath_iter; + } + else + { + _split_out_subdir(curpath_iter, subdir_name); + + /* skip "/" for next search */ + subpath_iter++; + } + + rt_mutex_take(&superblock->lock, RT_WAITING_FOREVER); + rt_list_for_each(list, &curfile->subdirs) + { + struct ptyfs_file *file_iter; + file_iter = rt_list_entry(list, struct ptyfs_file, ent_node); + if (basename) + { + if (strcmp(file_iter->basename, basename) == 0) + { + found_file = file_iter; + break; + } + } + else if (strcmp(file_iter->basename, subdir_name) == 0) + { + curpath_iter = subpath_iter; + curfile = file_iter; + do_path_resolve = 1; + break; + } + } + rt_mutex_release(&superblock->lock); + } + + return found_file; +} + +const char *ptyfs_get_rootpath(rt_device_t ptmx) +{ + const char *rc; + struct ptyfs_sb *sb; + /* allocate id for it and register file */ + sb = rt_container_of(ptmx, struct ptyfs_sb, ptmx_device); + if (sb->magic != PTYFS_MAGIC) + { + rc = 0; + } + else + { + /* fullpath is always started with /dev/ */ + return sb->mount->fullpath + 5; + } + + return rc; +} + +ptsno_t ptyfs_register_pts(rt_device_t ptmx, rt_device_t pts) +{ + ptsno_t rc; + struct ptyfs_sb *sb; + struct ptyfs_file *pts_file; + struct rid_bitmap *ptsno_pool; + + /* allocate id for it and register file */ + sb = rt_container_of(ptmx, struct ptyfs_sb, ptmx_device); + if (sb->magic != PTYFS_MAGIC) + { + rc = -1; + } + else + { + ptsno_pool = &sb->ptsno_pool; + rc = rid_bitmap_get(ptsno_pool); + if (rc >= 0) + { + pts_file = rt_calloc(1, sizeof(struct ptyfs_file)); + if (pts_file) + { + snprintf(pts_file->basename, DIRENT_NAME_MAX, "%lu", rc); + ptyfile_init(pts_file, sb, 0, PTYFS_TYPE_FILE_SLAVE, + PTS_DEFAULT_FILE_MODE, pts); + ptyfile_add_to_root(sb, pts_file); + } + else + { + rid_bitmap_put(ptsno_pool, rc); + rc = -1; + } + } + /* else rc == -1 */ + } + + return rc; +} + +rt_err_t ptyfs_unregister_pts(rt_device_t ptmx, ptsno_t ptsno) +{ + ptsno_t rc; + struct ptyfs_sb *sb; + struct ptyfs_file *pts_file; + struct rid_bitmap *ptsno_pool; + char path_buf[DIRENT_NAME_MAX]; + + /* allocate id for it and register file */ + sb = rt_container_of(ptmx, struct ptyfs_sb, ptmx_device); + if (sb->magic != PTYFS_MAGIC || ptsno < 0) + { + rc = -EINVAL; + } + else + { + /* get path and findout device */ + snprintf(path_buf, sizeof(path_buf), "%lu", ptsno); + pts_file = ptyfile_lookup(sb, path_buf); + if (pts_file) + { + ptyfile_remove_from_root(sb, pts_file); + ptsno_pool = &sb->ptsno_pool; + rid_bitmap_put(ptsno_pool, ptsno); + rc = 0; + } + else + { + rc = -ENOENT; + } + } + + return rc; +} + +#define DEVFS_PREFIX "/dev/" +#define DEVFS_PREFIX_LEN (sizeof(DEVFS_PREFIX) - 1) + +/** + * Create an new instance of ptyfs, and mount on target point + * 2 basic files are created: root, ptmx. + * + * todo: support of mount options? + */ +static int ptyfs_ops_mount(struct dfs_mnt *mnt, unsigned long rwflag, + const void *data) +{ + struct ptyfs_sb *sb; + rt_device_t ptmx_device; + rt_err_t rc; + + if (strncmp(mnt->fullpath, DEVFS_PREFIX, DEVFS_PREFIX_LEN) != 0) + { + LOG_I("%s() Not mounted on `/dev/'", __func__); + return -EINVAL; + } + + sb = rt_calloc(1, sizeof(struct ptyfs_sb)); + if (sb) + { + rt_mutex_init(&sb->lock, "ptyfs", RT_IPC_FLAG_PRIO); + + /* setup the ptmx device */ + ptmx_device = &sb->ptmx_device; + rc = lwp_ptmx_init(ptmx_device, mnt->fullpath + DEVFS_PREFIX_LEN); + if (rc == RT_EOK) + { + /* setup 2 basic files */ + ptyfile_init(&sb->root_file, sb, "/", PTYFS_TYPE_DIR, + ROOT_DEFUALT_FILE_MODE, 0); + ptyfile_init(&sb->ptmx_file, sb, "ptmx", PTYFS_TYPE_FILE_PTMX, + PTMX_DEFAULT_FILE_MODE, ptmx_device); + ptyfile_add_to_root(sb, &sb->ptmx_file); + + /* setup rid */ + rid_bitmap_init(&sb->ptsno_pool, 0, LWP_PTY_MAX_PARIS_LIMIT, + sb->ptsno_pool_bitset, &sb->lock); + + /* setup properties and members */ + sb->magic = PTYFS_MAGIC; + + sb->df_size = sizeof(struct ptyfs_sb); + rt_list_init(&sb->sibling); + + /* binding superblocks and mount point */ + mnt->data = sb; + sb->mount = mnt; + rc = 0; + } + /* else just return rc */ + } + else + { + rc = -ENOMEM; + } + + return rc; +} + +static int ptyfs_ops_umount(struct dfs_mnt *mnt) +{ + /* Not supported yet */ + return -1; +} + +static int ptyfs_ops_setattr(struct dfs_dentry *dentry, struct dfs_attr *attr) +{ + struct ptyfs_file *pty_file; + struct ptyfs_sb *superblock; + + RT_ASSERT(dentry); + RT_ASSERT(dentry->mnt); + + superblock = (struct ptyfs_sb *)dentry->mnt->data; + RT_ASSERT(superblock); + + /* find the device related to current pts slave device */ + pty_file = ptyfile_lookup(superblock, dentry->pathname); + if (pty_file && pty_file->type == PTYFS_TYPE_FILE_SLAVE) + { + pty_file->mode &= ~0xFFF; + pty_file->mode |= attr->st_mode & 0xFFF; + return 0; + } + + return -1; +} + +#define OPTIMAL_BSIZE 1024 + +static int ptyfs_ops_statfs(struct dfs_mnt *mnt, struct statfs *buf) +{ + struct ptyfs_sb *superblock; + + RT_ASSERT(mnt != NULL); + RT_ASSERT(buf != NULL); + + superblock = (struct ptyfs_sb *)mnt->data; + RT_ASSERT(superblock != NULL); + + buf->f_bsize = OPTIMAL_BSIZE; + buf->f_blocks = (superblock->df_size + OPTIMAL_BSIZE - 1) / OPTIMAL_BSIZE; + buf->f_bfree = 1; + buf->f_bavail = buf->f_bfree; + + return RT_EOK; +} + +static int ptyfs_ops_stat(struct dfs_dentry *dentry, struct stat *st) +{ + struct dfs_vnode *vnode; + + if (dentry && dentry->vnode) + { + vnode = dentry->vnode; + + /* device id ? */ + st->st_dev = (dev_t)(long)(dentry->mnt->dev_id); + st->st_ino = (ino_t)dfs_dentry_full_path_crc32(dentry); + + st->st_gid = vnode->gid; + st->st_uid = vnode->uid; + st->st_mode = vnode->mode; + st->st_nlink = vnode->nlink; + st->st_size = vnode->size; + st->st_mtim.tv_nsec = vnode->mtime.tv_nsec; + st->st_mtim.tv_sec = vnode->mtime.tv_sec; + st->st_ctim.tv_nsec = vnode->ctime.tv_nsec; + st->st_ctim.tv_sec = vnode->ctime.tv_sec; + st->st_atim.tv_nsec = vnode->atime.tv_nsec; + st->st_atim.tv_sec = vnode->atime.tv_sec; + } + + return 0; +} + +static struct dfs_vnode *ptyfs_ops_lookup(struct dfs_dentry *dentry) +{ + struct dfs_vnode *vnode = RT_NULL; + struct ptyfs_sb *superblock; + struct ptyfs_file *pty_file; + + if (dentry == NULL || dentry->mnt == NULL || dentry->mnt->data == NULL) + { + return NULL; + } + + superblock = (struct ptyfs_sb *)dentry->mnt->data; + + pty_file = ptyfile_lookup(superblock, dentry->pathname); + if (pty_file) + { + vnode = dfs_vnode_create(); + if (vnode) + { + vnode->data = pty_file->device; + vnode->nlink = 1; + vnode->size = 0; + vnode->mnt = dentry->mnt; + /* if it's root directory */ + vnode->fops = &_default_fops; + vnode->mode = pty_file->mode; + vnode->type = pty_file->type == PTYFS_TYPE_DIR ? FT_DIRECTORY : FT_DEVICE; + } + } + + return vnode; +} + +static struct dfs_vnode *ptyfs_ops_create_vnode(struct dfs_dentry *dentry, + int type, mode_t mode) +{ + struct dfs_vnode *vnode = RT_NULL; + struct ptyfs_sb *sb; + struct ptyfs_file *pty_file; + char *vnode_path; + + if (dentry == NULL || dentry->mnt == NULL || dentry->mnt->data == NULL) + { + return NULL; + } + + sb = (struct ptyfs_sb *)dentry->mnt->data; + RT_ASSERT(sb != NULL); + + vnode = dfs_vnode_create(); + if (vnode) + { + vnode_path = dentry->pathname; + + /* Query if file existed. Filter out illegal open modes */ + pty_file = ptyfile_lookup(sb, vnode_path); + if (!pty_file || (~pty_file->mode & mode)) + { + dfs_vnode_destroy(vnode); + return NULL; + } + + vnode->data = pty_file->device; + vnode->nlink = 1; + vnode->size = 0; + vnode->mnt = dentry->mnt; + vnode->fops = pty_file->device ? pty_file->device->fops : RT_NULL; + vnode->mode &= pty_file->mode; + + if (type == FT_DIRECTORY) + { + vnode->mode |= S_IFDIR; + vnode->type = FT_DIRECTORY; + LOG_I("%s: S_IFDIR created", __func__); + } + else if (type == FT_REGULAR) + { + vnode->mode |= S_IFCHR; + vnode->type = FT_DEVICE; + LOG_I("%s: S_IFDIR created", __func__); + } + else + { + /* unsupported types */ + dfs_vnode_destroy(vnode); + return NULL; + } + } + + return vnode; +} + +static int ptyfs_ops_free_vnode(struct dfs_vnode *vnode) +{ + return RT_EOK; +} + +static int devpty_deffops_getdents(struct dfs_file *file, struct dirent *dirp, + uint32_t count) +{ + struct ptyfs_file *d_file; + struct ptyfs_sb *superblock; + + RT_ASSERT(file); + RT_ASSERT(file->dentry); + RT_ASSERT(file->dentry->mnt); + + superblock = (struct ptyfs_sb *)file->dentry->mnt->data; + RT_ASSERT(superblock); + + d_file = ptyfile_lookup(superblock, file->dentry->pathname); + if (d_file) + { + rt_size_t index, end; + struct dirent *d; + struct ptyfs_file *n_file; + rt_list_t *list; + + /* make integer count */ + count = (count / sizeof(struct dirent)); + if (count == 0) + { + return -EINVAL; + } + + end = file->fpos + count; + index = 0; + count = 0; + + rt_list_for_each(list, &d_file->subdirs) + { + if (index >= (rt_size_t)file->fpos) + { + n_file = rt_list_entry(list, struct ptyfs_file, ent_node); + + d = dirp + count; + if (n_file->type == PTYFS_TYPE_DIR) + { + d->d_type = DT_DIR; + } + else + { + /* ptmx(5,2) or slave(136,[0,1048575]) device, on Linux */ + d->d_type = DT_CHR; + } + + d->d_reclen = (rt_uint16_t)sizeof(struct dirent); + rt_strncpy(d->d_name, n_file->basename, DIRENT_NAME_MAX); + d->d_namlen = rt_strlen(d->d_name); + + count += 1; + file->fpos += 1; + } + index += 1; + if (index >= end) + { + break; + } + } + } + + return count * sizeof(struct dirent); +} + +static const struct dfs_filesystem_ops _ptyfs_ops = { + .name = "ptyfs", + .flags = DFS_FS_FLAG_DEFAULT, + .default_fops = &_default_fops, + + .mount = ptyfs_ops_mount, + .umount = ptyfs_ops_umount, + + /* don't allow to create symbolic link */ + .symlink = RT_NULL, + .readlink = RT_NULL, + .unlink = RT_NULL, + + .setattr = ptyfs_ops_setattr, + .statfs = ptyfs_ops_statfs, + .stat = ptyfs_ops_stat, + + .lookup = ptyfs_ops_lookup, + .create_vnode = ptyfs_ops_create_vnode, + .free_vnode = ptyfs_ops_free_vnode, +}; + +static struct dfs_filesystem_type _devptyfs = { + .fs_ops = &_ptyfs_ops, +}; + +static int _ptyfs_init(void) +{ + _default_fops = *dfs_devfs_fops(); + _default_fops.getdents = devpty_deffops_getdents; + + /* register file system */ + dfs_register(&_devptyfs); + + return 0; +} +INIT_COMPONENT_EXPORT(_ptyfs_init); diff --git a/components/dfs/dfs_v2/filesystems/ptyfs/ptyfs.h b/components/dfs/dfs_v2/filesystems/ptyfs/ptyfs.h new file mode 100644 index 0000000000..69b2fb66fd --- /dev/null +++ b/components/dfs/dfs_v2/filesystems/ptyfs/ptyfs.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-12-02 Shell init ver. + */ +#ifndef __FS_PTYFS_H__ +#define __FS_PTYFS_H__ +#include <rtthread.h> + +typedef rt_base_t ptsno_t; + +ptsno_t ptyfs_register_pts(rt_device_t ptmx, rt_device_t pts); + +rt_err_t ptyfs_unregister_pts(rt_device_t ptmx, ptsno_t ptsno); + +const char *ptyfs_get_rootpath(rt_device_t ptmx); + +#endif /* __FS_PTYFS_H__ */ diff --git a/components/dfs/dfs_v2/filesystems/romfs/romfs.c b/components/dfs/dfs_v2/filesystems/romfs/romfs.c index 91465116b3..45279bcb83 100644 --- a/components/dfs/dfs_v2/filesystems/romfs/romfs.c +++ b/components/dfs/dfs_v2/filesystems/romfs/romfs.c @@ -29,6 +29,9 @@ rt_weak const struct romfs_dirent _root_dirent[] = { {ROMFS_DIRENT_DIR, "dev", RT_NULL, 0}, {ROMFS_DIRENT_DIR, "mnt", RT_NULL, 0}, + {ROMFS_DIRENT_DIR, "proc", RT_NULL, 0}, + {ROMFS_DIRENT_DIR, "etc", RT_NULL, 0}, + {ROMFS_DIRENT_DIR, "bin", RT_NULL, 0}, {ROMFS_DIRENT_DIR, "dummy", (rt_uint8_t *)_dummy, sizeof(_dummy) / sizeof(_dummy[0])}, {ROMFS_DIRENT_FILE, "dummy.txt", _dummy_txt, sizeof(_dummy_txt)}, }; diff --git a/components/dfs/dfs_v2/filesystems/tmpfs/dfs_tmpfs.c b/components/dfs/dfs_v2/filesystems/tmpfs/dfs_tmpfs.c index f289fc4419..8644f51c26 100644 --- a/components/dfs/dfs_v2/filesystems/tmpfs/dfs_tmpfs.c +++ b/components/dfs/dfs_v2/filesystems/tmpfs/dfs_tmpfs.c @@ -202,6 +202,7 @@ int dfs_tmpfs_ioctl(struct dfs_file *file, int cmd, void *args) superblock = d_file->sb; RT_ASSERT(superblock != NULL); + RT_UNUSED(superblock); switch (cmd) { @@ -317,26 +318,21 @@ static ssize_t dfs_tmpfs_read(struct dfs_file *file, void *buf, size_t count, of return length; } -static ssize_t dfs_tmpfs_write(struct dfs_file *file, const void *buf, size_t count, off_t *pos) +static ssize_t _dfs_tmpfs_write(struct tmpfs_file *d_file, const void *buf, size_t count, off_t *pos) { - struct tmpfs_file *d_file; struct tmpfs_sb *superblock; - d_file = (struct tmpfs_file *)file->vnode->data; RT_ASSERT(d_file != NULL); superblock = d_file->sb; RT_ASSERT(superblock != NULL); - rt_mutex_take(&file->vnode->lock, RT_WAITING_FOREVER); - - if (count + *pos > file->vnode->size) + if (count + *pos > d_file->size) { rt_uint8_t *ptr; ptr = rt_realloc(d_file->data, *pos + count); if (ptr == NULL) { - rt_mutex_release(&file->vnode->lock); rt_set_errno(-ENOMEM); return 0; } @@ -347,7 +343,6 @@ static ssize_t dfs_tmpfs_write(struct dfs_file *file, const void *buf, size_t co /* update d_file and file size */ d_file->data = ptr; d_file->size = *pos + count; - file->vnode->size = d_file->size; LOG_D("tmpfile ptr:%x, size:%d", ptr, d_file->size); } @@ -356,6 +351,21 @@ static ssize_t dfs_tmpfs_write(struct dfs_file *file, const void *buf, size_t co /* update file current position */ *pos += count; + + return count; +} + +static ssize_t dfs_tmpfs_write(struct dfs_file *file, const void *buf, size_t count, off_t *pos) +{ + struct tmpfs_file *d_file; + + d_file = (struct tmpfs_file *)file->vnode->data; + RT_ASSERT(d_file != NULL); + + rt_mutex_take(&file->vnode->lock, RT_WAITING_FOREVER); + + count = _dfs_tmpfs_write(d_file, buf, count, pos); + rt_mutex_release(&file->vnode->lock); return count; @@ -504,6 +514,7 @@ static int dfs_tmpfs_getdents(struct dfs_file *file, superblock = d_file->sb; RT_ASSERT(superblock != RT_NULL); + RT_UNUSED(superblock); /* make integer count */ count = (count / sizeof(struct dirent)); @@ -797,6 +808,8 @@ static ssize_t dfs_tmp_page_read(struct dfs_file *file, struct dfs_page *page) ssize_t dfs_tmp_page_write(struct dfs_page *page) { + off_t pos; + size_t count = 0; struct tmpfs_file *d_file; if (page->aspace->vnode->type == FT_DIRECTORY) @@ -806,13 +819,16 @@ ssize_t dfs_tmp_page_write(struct dfs_page *page) d_file = (struct tmpfs_file *)(page->aspace->vnode->data); RT_ASSERT(d_file != RT_NULL); + rt_mutex_take(&page->aspace->vnode->lock, RT_WAITING_FOREVER); if (page->len > 0) - memcpy(d_file->data + page->fpos, page->page, page->len); - + { + pos = page->fpos; + count = _dfs_tmpfs_write(d_file, page->page, page->len, &pos); + } rt_mutex_release(&page->aspace->vnode->lock); - return F_OK; + return count; } #endif diff --git a/components/dfs/dfs_v2/include/dfs.h b/components/dfs/dfs_v2/include/dfs.h index 6815f5e0ab..8b8c80188f 100644 --- a/components/dfs/dfs_v2/include/dfs.h +++ b/components/dfs/dfs_v2/include/dfs.h @@ -25,6 +25,10 @@ #include <rtatomic.h> #include <rtdevice.h> +#ifndef ATTR_MODE_SET +#define ATTR_MODE_SET (1 << 6) +#endif + #ifndef ATTR_ATIME_SET #define ATTR_ATIME_SET (1 << 7) #endif @@ -33,6 +37,14 @@ #define ATTR_MTIME_SET (1 << 8) #endif +#ifndef ATTR_UID_SET +#define ATTR_UID_SET (1 << 9) +#endif + +#ifndef ATTR_GID_SET +#define ATTR_GID_SET (1 << 10) +#endif + #ifndef AT_SYMLINK_NOFOLLOW #define AT_SYMLINK_NOFOLLOW 0x100 #endif diff --git a/components/dfs/dfs_v2/include/dfs_file.h b/components/dfs/dfs_v2/include/dfs_file.h index d62aec1e89..72539f3bbe 100644 --- a/components/dfs/dfs_v2/include/dfs_file.h +++ b/components/dfs/dfs_v2/include/dfs_file.h @@ -175,20 +175,25 @@ int dfs_file_isdir(const char *path); int dfs_file_access(const char *path, mode_t mode); int dfs_file_chdir(const char *path); char *dfs_file_getcwd(char *buf, size_t size); -char *dfs_nolink_path(struct dfs_mnt **mnt, char *fullpath, int mode); + #ifdef RT_USING_SMART int dfs_file_mmap2(struct dfs_file *file, struct dfs_mmap2_args *mmap2); int dfs_file_mmap(struct dfs_file *file, struct dfs_mmap2_args *mmap2); #endif -char *dfs_nolink_path(struct dfs_mnt **mnt, char *fullpath, int mode); - /* 0x5254 is just a magic number to make these relatively unique ("RT") */ #define RT_FIOFTRUNCATE 0x52540000U #define RT_FIOGETADDR 0x52540001U #define RT_FIOMMAP2 0x52540002U +/* dfs_file_realpath mode */ +#define DFS_REALPATH_EXCEPT_LAST 0 +#define DFS_REALPATH_EXCEPT_NONE 1 +#define DFS_REALPATH_ONLY_LAST 3 + +char *dfs_file_realpath(struct dfs_mnt **mnt, const char *fullpath, int mode); + #ifdef __cplusplus } #endif diff --git a/components/dfs/dfs_v2/include/dfs_fs.h b/components/dfs/dfs_v2/include/dfs_fs.h index 9dc99ee367..d30967aac5 100644 --- a/components/dfs/dfs_v2/include/dfs_fs.h +++ b/components/dfs/dfs_v2/include/dfs_fs.h @@ -32,7 +32,9 @@ struct dfs_partition struct dfs_attr { unsigned int ia_valid; - mode_t st_mode; + uid_t st_uid; + gid_t st_gid; + mode_t st_mode; struct timespec ia_atime; struct timespec ia_mtime; }; diff --git a/components/dfs/dfs_v2/include/dfs_pcache.h b/components/dfs/dfs_v2/include/dfs_pcache.h index 356df6c4f9..01abfe3150 100644 --- a/components/dfs/dfs_v2/include/dfs_pcache.h +++ b/components/dfs/dfs_v2/include/dfs_pcache.h @@ -23,6 +23,8 @@ extern "C" { #endif +struct rt_varea; +struct rt_aspace; struct dfs_vnode; struct dfs_dentry; struct dfs_aspace; @@ -30,7 +32,8 @@ struct dfs_aspace; struct dfs_mmap { rt_list_t mmap_node; - struct rt_varea *varea; + struct rt_aspace *aspace; + void *vaddr; }; struct dfs_page diff --git a/components/dfs/dfs_v2/src/dfs.c b/components/dfs/dfs_v2/src/dfs.c index ad90822b93..939e4dd66e 100644 --- a/components/dfs/dfs_v2/src/dfs.c +++ b/components/dfs/dfs_v2/src/dfs.c @@ -557,6 +557,111 @@ exit: return newfd; } +/** + * @brief The fd in the current process dup to designate fd table. + * + * @param oldfd is the fd in current process. + * + * @param fdtab is the fd table to dup, if empty, use global (_fdtab). + * + * @return -1 on failed or the allocated file descriptor. + */ +int dfs_dup_to(int oldfd, struct dfs_fdtable *fdtab) +{ + int newfd = -1; + struct dfs_fdtable *fdt = NULL; + + if (dfs_file_lock() != RT_EOK) + { + return -RT_ENOSYS; + } + + if (fdtab == NULL) + { + fdtab = &_fdtab; + } + + /* check old fd */ + fdt = dfs_fdtable_get(); + if ((oldfd < 0) || (oldfd >= fdt->maxfd)) + { + goto exit; + } + if (!fdt->fds[oldfd]) + { + goto exit; + } + /* get a new fd*/ + newfd = _fdt_slot_alloc(fdtab, DFS_STDIO_OFFSET); + if (newfd >= 0) + { + fdtab->fds[newfd] = fdt->fds[oldfd]; + + /* inc ref_count */ + rt_atomic_add(&(fdtab->fds[newfd]->ref_count), 1); + } +exit: + dfs_file_unlock(); + + return newfd; +} + +/** + * @brief The fd in the designate fd table dup to current process. + * + * @param oldfd is the fd in the designate fd table. + * + * @param fdtab is the fd table for oldfd, if empty, use global (_fdtab). + * + * @return -1 on failed or the allocated file descriptor. + */ +int dfs_dup_from(int oldfd, struct dfs_fdtable *fdtab) +{ + int newfd = -1; + struct dfs_file *file; + + if (dfs_file_lock() != RT_EOK) + { + return -RT_ENOSYS; + } + + if (fdtab == NULL) + { + fdtab = &_fdtab; + } + + /* check old fd */ + if ((oldfd < 0) || (oldfd >= fdtab->maxfd)) + { + goto exit; + } + if (!fdtab->fds[oldfd]) + { + goto exit; + } + /* get a new fd*/ + newfd = fd_new(); + file = fd_get(newfd); + if (newfd >= 0 && file) + { + file->mode = fdtab->fds[oldfd]->mode; + file->flags = fdtab->fds[oldfd]->flags; + file->fops = fdtab->fds[oldfd]->fops; + file->dentry = dfs_dentry_ref(fdtab->fds[oldfd]->dentry); + file->vnode = fdtab->fds[oldfd]->vnode; + file->mmap_context = RT_NULL; + file->data = fdtab->fds[oldfd]->data; + } + + dfs_file_close(fdtab->fds[oldfd]); + +exit: + fdt_fd_release(fdtab, oldfd); + dfs_file_unlock(); + + return newfd; +} + #ifdef RT_USING_SMART sysret_t sys_dup(int oldfd) #else @@ -856,7 +961,11 @@ int dfs_fd_dump(int argc, char** argv) { int index; - dfs_file_lock(); + if (dfs_file_lock() != RT_EOK) + { + return -RT_ENOSYS; + } + for (index = 0; index < _fdtab.maxfd; index++) { struct dfs_file *file = _fdtab.fds[index]; diff --git a/components/dfs/dfs_v2/src/dfs_file.c b/components/dfs/dfs_v2/src/dfs_file.c index 5f55eaaba1..c51208a5f2 100644 --- a/components/dfs/dfs_v2/src/dfs_file.c +++ b/components/dfs/dfs_v2/src/dfs_file.c @@ -29,22 +29,86 @@ #define MAX_RW_COUNT 0xfffc0000 -rt_inline int _find_path_node(const char *path) +rt_inline int _first_path_len(const char *path) { int i = 0; - while (path[i] != '\0') + if (path[i] == '/') { - if ('/' == path[i++]) + i++; + while (path[i] != '\0' && path[i] != '/') { - break; + i++; } } - /* return path-note length */ return i; } +static int _get_parent_path(const char *fullpath, char *path) +{ + int len = 0; + char *str = 0; + + str = strrchr(fullpath, '/'); + if (str) + { + len = str - fullpath; + if (len > 0) + { + rt_memcpy(path, fullpath, len); + path[len] = '\0'; + } + } + + return len; +} + +static int _try_readlink(const char *path, struct dfs_mnt *mnt, char *link) +{ + int ret = -1; + struct dfs_dentry *dentry = dfs_dentry_lookup(mnt, path, 0); + + if (dentry && dentry->vnode->type == FT_SYMLINK) + { + if (mnt->fs_ops->readlink) + { + if (dfs_is_mounted(mnt) == 0) + { + ret = mnt->fs_ops->readlink(dentry, link, DFS_PATH_MAX); + } + } + } + dfs_dentry_unref(dentry); + + return ret; +} + +static int _insert_link_path(const char *link_fn, int link_len, char *tmp_path, int *index) +{ + int ret = -1; + + if (link_fn[0] != '/') + { + if (link_len + 1 <= *index) + { + *index -= link_len; + rt_memcpy(tmp_path + *index, link_fn, link_len); + *index -= 1; + tmp_path[*index] = '/'; + ret = 0; + } + } + else if (link_len <= *index) + { + *index -= link_len; + rt_memcpy(tmp_path + *index, link_fn, link_len); + ret = 1; + } + + return ret; +} + /* * rw_verify_area doesn't like huge counts. We limit * them to something that fits in "int" so that others @@ -149,166 +213,97 @@ 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) - { - char *buf = NULL; - - buf = (char *)rt_malloc(DFS_PATH_MAX); - if (buf) - { - do - { - 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(tmp); - - /* is the relative directory */ - if (dir) - { - char *fullpath = dfs_normalize_path(dir, buf); - if (fullpath) - { - strncpy(buf, fullpath, DFS_PATH_MAX); - - rt_free(fullpath); - } - rt_free(dir); - } - } - - mnt = dfs_mnt_lookup(buf); - if (mnt) - { - struct dfs_dentry *de = dfs_dentry_lookup(mnt, buf, 0); - - /* release the old dentry */ - dfs_dentry_unref(tmp); - tmp = de; - } - } - else - { - break; - } - } while (tmp && tmp->vnode->type == FT_SYMLINK); - } - - rt_free(buf); - } - - return tmp; -} - /* * this function is creat a nolink path. * * @param mnt * @param fullpath - * @param mode 0 middle path nolink; 1 all path nolink. + * @param mode * * @return new path. */ -char *dfs_nolink_path(struct dfs_mnt **mnt, char *fullpath, int mode) +char *dfs_file_realpath(struct dfs_mnt **mnt, const char *fullpath, int mode) { - int index = 0; - char *path = RT_NULL; - char *link_fn; - struct dfs_dentry *dentry = RT_NULL; - - path = (char *)rt_malloc((DFS_PATH_MAX * 2) + 2); // path + \0 + link_fn + \0 - if (!path) - { - return path; - } - link_fn = path + DFS_PATH_MAX + 1; + int path_len = 0, index = 0; + char *path = RT_NULL, *link_fn, *tmp_path; + struct dfs_mnt *tmp_mnt; if (*mnt && fullpath) { - int i = 0; - char *fp = fullpath; + int len, link_len; + + path = (char *)rt_malloc((DFS_PATH_MAX * 3) + 3); // path + \0 + link_fn + \0 + tmp_path + \0 + if (!path) + { + return RT_NULL; + } + + link_fn = path + DFS_PATH_MAX + 1; + tmp_path = link_fn + (DFS_PATH_MAX + 1); + + len = rt_strlen(fullpath); + if (len > DFS_PATH_MAX) + { + goto _ERR_RET; + } + + index = (DFS_PATH_MAX - len); + rt_strcpy(tmp_path + index, fullpath); + + if (mode == DFS_REALPATH_ONLY_LAST) + { + path_len = _get_parent_path(fullpath, path); + index += path_len; + } - while ((i = _find_path_node(fp)) > 0) + while ((len = _first_path_len(tmp_path + index)) > 0) { - if (i + index > DFS_PATH_MAX) + if (len + path_len > DFS_PATH_MAX) { goto _ERR_RET; } - rt_memcpy(path + index, fp, i); - path[index + i] = '\0'; + rt_memcpy(path + path_len, tmp_path + index, len); + path[path_len + len] = '\0'; + index += len; - /* the last should by mode process. */ - if ((fp[i] == '\0') && (!mode)) + tmp_mnt = dfs_mnt_lookup(path); + if (tmp_mnt == RT_NULL) { - break; + goto _ERR_RET; } - fp += i; + *mnt = tmp_mnt; - dentry = dfs_dentry_lookup(*mnt, path, 0); - if (dentry && dentry->vnode->type == FT_SYMLINK) + /* the last should by mode process. */ + if ((tmp_path[index] == '\0') && (mode == DFS_REALPATH_EXCEPT_LAST)) { - int ret = -1; + break; + } - if ((*mnt)->fs_ops->readlink) - { - if (dfs_is_mounted((*mnt)) == 0) - { - ret = (*mnt)->fs_ops->readlink(dentry, link_fn, DFS_PATH_MAX); - } - } + link_len = _try_readlink(path, *mnt, link_fn); + if (link_len > 0) + { + int ret = _insert_link_path(link_fn, link_len, tmp_path, &index); - if (ret > 0) + if (ret == 1) { - int len = rt_strlen(link_fn); - - if (link_fn[0] != '/') - { - path[index] = '/'; - } - else - { - index = 0; - } - - if (len + index + 1 >= DFS_PATH_MAX) - { - goto _ERR_RET; - } - - rt_memcpy(path + index, link_fn, len); - index += len; - path[index] = '\0'; - *mnt = dfs_mnt_lookup(path); + /* link_fn[0] == '/' */ + path_len = 0; } - else + else if (ret < 0) { goto _ERR_RET; } } else { - index += i; + path_len += len; } - dfs_dentry_unref(dentry); } - } - else - { + + return path; + _ERR_RET: rt_free(path); path = RT_NULL; @@ -349,7 +344,7 @@ int dfs_file_open(struct dfs_file *file, const char *path, int oflags, mode_t mo mnt = dfs_mnt_lookup(fullpath); if (mnt) { - char *tmp = dfs_nolink_path(&mnt, fullpath, 0); + char *tmp = dfs_file_realpath(&mnt, fullpath, DFS_REALPATH_EXCEPT_LAST); if (tmp) { rt_free(fullpath); @@ -370,9 +365,12 @@ int dfs_file_open(struct dfs_file *file, const char *path, int oflags, mode_t mo else { struct dfs_dentry *target_dentry = RT_NULL; - - /* follow symbol link */ - target_dentry = dfs_file_follow_link(dentry); + char *path = dfs_file_realpath(&mnt, fullpath, DFS_REALPATH_ONLY_LAST); + if (path) + { + target_dentry = dfs_dentry_lookup(mnt, path, oflags); + rt_free(path); + } dfs_dentry_unref(dentry); dentry = target_dentry; } @@ -507,7 +505,7 @@ int dfs_file_open(struct dfs_file *file, const char *path, int oflags, mode_t mo if (ret < 0) { - LOG_E("open %s failed in file system: %s", path, dentry->mnt->fs_ops->name); + LOG_I("open %s failed in file system: %s", path, dentry->mnt->fs_ops->name); DLOG(msg, mnt->fs_ops->name, "dfs_file", DLOG_MSG_RET, "open failed."); dfs_file_unref(file); } @@ -791,7 +789,7 @@ int dfs_file_stat(const char *path, struct stat *buf) mnt = dfs_mnt_lookup(fullpath); if (mnt) { - char *tmp = dfs_nolink_path(&mnt, fullpath, 1); + char *tmp = dfs_file_realpath(&mnt, fullpath, DFS_REALPATH_EXCEPT_NONE); if (tmp) { rt_free(fullpath); @@ -845,7 +843,7 @@ int dfs_file_lstat(const char *path, struct stat *buf) mnt = dfs_mnt_lookup(fullpath); if (mnt) { - char *tmp = dfs_nolink_path(&mnt, fullpath, 0); + char *tmp = dfs_file_realpath(&mnt, fullpath, DFS_REALPATH_EXCEPT_LAST); if (tmp) { rt_free(fullpath); @@ -924,7 +922,7 @@ int dfs_file_setattr(const char *path, struct dfs_attr *attr) mnt = dfs_mnt_lookup(fullpath); if (mnt) { - char *tmp = dfs_nolink_path(&mnt, fullpath, 0); + char *tmp = dfs_file_realpath(&mnt, fullpath, DFS_REALPATH_EXCEPT_LAST); if (tmp) { rt_free(fullpath); @@ -1097,7 +1095,7 @@ int dfs_file_unlink(const char *path) mnt = dfs_mnt_lookup(fullpath); if (mnt) { - char *tmp = dfs_nolink_path(&mnt, fullpath, 0); + char *tmp = dfs_file_realpath(&mnt, fullpath, DFS_REALPATH_EXCEPT_LAST); if (tmp) { rt_free(fullpath); @@ -1199,7 +1197,7 @@ int dfs_file_link(const char *oldname, const char *newname) return -1; } - char *tmp = dfs_nolink_path(&mnt, old_fullpath, 0); + char *tmp = dfs_file_realpath(&mnt, old_fullpath, DFS_REALPATH_EXCEPT_LAST); if (tmp) { rt_free(old_fullpath); @@ -1210,7 +1208,7 @@ int dfs_file_link(const char *oldname, const char *newname) new_fullpath = dfs_normalize_path(NULL, newname); if (new_fullpath) { - char *tmp = dfs_nolink_path(&mnt, new_fullpath, 0); + char *tmp = dfs_file_realpath(&mnt, new_fullpath, DFS_REALPATH_EXCEPT_LAST); if (tmp) { rt_free(new_fullpath); @@ -1310,7 +1308,7 @@ int dfs_file_symlink(const char *target, const char *linkpath) mnt = dfs_mnt_lookup(parent); if (mnt) { - char *tmp = dfs_nolink_path(&mnt, parent, 0); + char *tmp = dfs_file_realpath(&mnt, parent, DFS_REALPATH_EXCEPT_LAST); if (tmp) { rt_free(parent); @@ -1318,7 +1316,7 @@ int dfs_file_symlink(const char *target, const char *linkpath) } DLOG(msg, "dfs_file", "dentry", DLOG_MSG, "dfs_dentry_lookup(mnt, %s)", fullpath); - dentry = dfs_dentry_lookup(mnt, parent, 0); + dentry = dfs_dentry_lookup(mnt, parent, DFS_REALPATH_EXCEPT_LAST); if (dentry) { if (dentry->mnt->fs_ops->symlink) @@ -1326,17 +1324,6 @@ int dfs_file_symlink(const char *target, const char *linkpath) char *path = dfs_normalize_path(parent, target); if (path) { - char *tmp = dfs_nolink_path(&mnt, path, 0); - if (tmp) - { - rt_free(path); - path = tmp; - } - else - { - tmp = path; - } - ret = rt_strncmp(parent, path, strlen(parent)); if (ret == 0) { @@ -1346,6 +1333,10 @@ int dfs_file_symlink(const char *target, const char *linkpath) tmp ++; } } + else + { + tmp = path; + } if (dfs_is_mounted(mnt) == 0) { @@ -1401,7 +1392,7 @@ int dfs_file_readlink(const char *path, char *buf, int bufsize) mnt = dfs_mnt_lookup(fullpath); if (mnt) { - char *tmp = dfs_nolink_path(&mnt, fullpath, 0); + char *tmp = dfs_file_realpath(&mnt, fullpath, DFS_REALPATH_EXCEPT_LAST); if (tmp) { rt_free(fullpath); @@ -1466,7 +1457,7 @@ int dfs_file_rename(const char *old_file, const char *new_file) return -1; } - char *tmp = dfs_nolink_path(&mnt, old_fullpath, 0); + char *tmp = dfs_file_realpath(&mnt, old_fullpath, DFS_REALPATH_EXCEPT_LAST); if (tmp) { rt_free(old_fullpath); @@ -1477,7 +1468,7 @@ int dfs_file_rename(const char *old_file, const char *new_file) new_fullpath = dfs_normalize_path(NULL, new_file); if (new_fullpath) { - char *tmp = dfs_nolink_path(&mnt, new_fullpath, 0); + char *tmp = dfs_file_realpath(&mnt, new_fullpath, DFS_REALPATH_EXCEPT_LAST); if (tmp) { rt_free(new_fullpath); @@ -1652,7 +1643,7 @@ int dfs_file_isdir(const char *path) mnt = dfs_mnt_lookup(fullpath); if (mnt) { - char *tmp = dfs_nolink_path(&mnt, fullpath, 1); + char *tmp = dfs_file_realpath(&mnt, fullpath, DFS_REALPATH_EXCEPT_NONE); if (tmp) { rt_free(fullpath); @@ -1853,7 +1844,7 @@ void ls(const char *pathname) mnt = dfs_mnt_lookup(fullpath); if (mnt) { - char *tmp = dfs_nolink_path(&mnt, fullpath, 0); + char *tmp = dfs_file_realpath(&mnt, fullpath, DFS_REALPATH_EXCEPT_LAST); if (tmp) { char *index; diff --git a/components/dfs/dfs_v2/src/dfs_pcache.c b/components/dfs/dfs_v2/src/dfs_pcache.c index 11f6172d08..57f4510e93 100644 --- a/components/dfs/dfs_v2/src/dfs_pcache.c +++ b/components/dfs/dfs_v2/src/dfs_pcache.c @@ -269,7 +269,6 @@ static void dfs_pcache_thread(void *parameter) { page->len = page->size; } - //rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, page->page, page->size); if (aspace->ops->write) { aspace->ops->write(page); @@ -676,9 +675,14 @@ static int dfs_page_unmap(struct dfs_page *page) if (map) { - void *vaddr = dfs_aspace_vaddr(map->varea, page->fpos); - //rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, vaddr, ARCH_PAGE_SIZE); - rt_varea_unmap_page(map->varea, vaddr); + rt_varea_t varea; + void *vaddr; + + varea = rt_aspace_query(map->aspace, map->vaddr); + RT_ASSERT(varea); + vaddr = dfs_aspace_vaddr(varea, page->fpos); + + rt_varea_unmap_page(varea, vaddr); rt_free(map); } @@ -741,7 +745,6 @@ static void dfs_page_release(struct dfs_page *page) { page->len = page->size; } - //rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, page->page, page->size); if (aspace->ops->write) { aspace->ops->write(page); @@ -995,7 +998,6 @@ static struct dfs_page *dfs_aspace_load_page(struct dfs_file *file, off_t pos) page->size = ARCH_PAGE_SIZE; page->fpos = pos / ARCH_PAGE_SIZE * ARCH_PAGE_SIZE; aspace->ops->read(file, page); - //rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, page->page, page->size); page->ref_count ++; dfs_page_insert(page); @@ -1105,7 +1107,6 @@ int dfs_aspace_read(struct dfs_file *file, void *buf, size_t count, off_t *pos) len = count > len ? len : count; if (len) { - //rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, page->page, page->size); rt_memcpy(ptr, page->page + *pos - page->fpos, len); ptr += len; *pos += len; @@ -1158,7 +1159,6 @@ int dfs_aspace_write(struct dfs_file *file, const void *buf, size_t count, off_t len = page->fpos + ARCH_PAGE_SIZE - *pos; len = count > len ? len : count; rt_memcpy(page->page + *pos - page->fpos, ptr, len); - //rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, page->page, page->size); ptr += len; *pos += len; count -= len; @@ -1225,7 +1225,7 @@ int dfs_aspace_flush(struct dfs_aspace *aspace) { page->len = page->size; } - //rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, page->page, page->size); + if (aspace->ops->write) { aspace->ops->write(page); @@ -1277,6 +1277,7 @@ void *dfs_aspace_mmap(struct dfs_file *file, struct rt_varea *varea, void *vaddr void *ret = RT_NULL; struct dfs_page *page; struct dfs_aspace *aspace = file->vnode->aspace; + rt_aspace_t target_aspace = varea->aspace; page = dfs_page_lookup(file, dfs_aspace_fpos(varea, vaddr)); if (page) @@ -1284,7 +1285,8 @@ void *dfs_aspace_mmap(struct dfs_file *file, struct rt_varea *varea, void *vaddr struct dfs_mmap *map = (struct dfs_mmap *)rt_calloc(1, sizeof(struct dfs_mmap)); if (map) { - void *pg_paddr = rt_kmem_v2p(page->page); + void *pg_vaddr = page->page; + void *pg_paddr = rt_kmem_v2p(pg_vaddr); int err = rt_varea_map_range(varea, vaddr, pg_paddr, page->size); if (err == RT_EOK) { @@ -1301,10 +1303,12 @@ void *dfs_aspace_mmap(struct dfs_file *file, struct rt_varea *varea, void *vaddr * fetching of the next instruction can see the coherent data with the data cache, * TLB, MMU, main memory, and all the other observers in the computer system. */ + rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, vaddr, ARCH_PAGE_SIZE); rt_hw_cpu_icache_ops(RT_HW_CACHE_INVALIDATE, vaddr, ARCH_PAGE_SIZE); - ret = page->page; - map->varea = varea; + ret = pg_vaddr; + map->aspace = target_aspace; + map->vaddr = vaddr; dfs_aspace_lock(aspace); rt_list_insert_after(&page->mmap_head, &map->mmap_node); dfs_page_release(page); @@ -1329,6 +1333,8 @@ int dfs_aspace_unmap(struct dfs_file *file, struct rt_varea *varea) { struct dfs_vnode *vnode = file->vnode; struct dfs_aspace *aspace = vnode->aspace; + void *unmap_start = varea->start; + void *unmap_end = (char *)unmap_start + varea->size; if (aspace) { @@ -1347,20 +1353,32 @@ int dfs_aspace_unmap(struct dfs_file *file, struct rt_varea *varea) { rt_list_t *node, *tmp; struct dfs_mmap *map; + rt_varea_t map_varea = RT_NULL; node = page->mmap_head.next; while (node != &page->mmap_head) { + rt_aspace_t map_aspace; map = rt_list_entry(node, struct dfs_mmap, mmap_node); tmp = node; node = node->next; - if (map && varea == map->varea) + if (map && varea->aspace == map->aspace + && map->vaddr >= unmap_start && map->vaddr < unmap_end) { - void *vaddr = dfs_aspace_vaddr(map->varea, page->fpos); + void *vaddr = map->vaddr; + map_aspace = map->aspace; + + if (!map_varea || map_varea->aspace != map_aspace || + vaddr < map_varea->start || + vaddr >= map_varea->start + map_varea->size) + { + /* lock the tree so we don't access uncompleted data */ + map_varea = rt_aspace_query(map_aspace, vaddr); + } - rt_varea_unmap_page(map->varea, vaddr); + rt_varea_unmap_page(map_varea, vaddr); if (varea->attr == MMU_MAP_U_RWCB && page->fpos < page->aspace->vnode->size) { @@ -1405,7 +1423,7 @@ int dfs_aspace_page_unmap(struct dfs_file *file, struct rt_varea *varea, void *v tmp = node; node = node->next; - if (map && varea == map->varea) + if (map && varea->aspace == map->aspace && vaddr == map->vaddr) { if (varea->attr == MMU_MAP_U_RWCB) { |
