diff --git a/components/dfs/dfs_v2/include/dfs_fs.h b/components/dfs/dfs_v2/include/dfs_fs.h index d30967aac5..dcf2fa2b98 100644 --- a/components/dfs/dfs_v2/include/dfs_fs.h +++ b/components/dfs/dfs_v2/include/dfs_fs.h @@ -20,6 +20,38 @@ extern "C" { #endif +#define MS_RDONLY 1 +#define MS_NOSUID 2 +#define MS_NODEV 4 +#define MS_NOEXEC 8 +#define MS_SYNCHRONOUS 16 +#define MS_REMOUNT 32 +#define MS_MANDLOCK 64 +#define MS_DIRSYNC 128 +#define MS_NOATIME 1024 +#define MS_NODIRATIME 2048 +#define MS_BIND 4096 +#define MS_MOVE 8192 +#define MS_REC 16384 +#define MS_SILENT 32768 +#define MS_POSIXACL (1<<16) +#define MS_UNBINDABLE (1<<17) +#define MS_PRIVATE (1<<18) +#define MS_SLAVE (1<<19) +#define MS_SHARED (1<<20) +#define MS_RELATIME (1<<21) +#define MS_KERNMOUNT (1<<22) +#define MS_I_VERSION (1<<23) +#define MS_STRICTATIME (1<<24) +#define MS_LAZYTIME (1<<25) +#define MS_NOREMOTELOCK (1<<27) +#define MS_NOSEC (1<<28) +#define MS_BORN (1<<29) +#define MS_ACTIVE (1<<30) +#define MS_NOUSER (1U<<31) + +#define MS_RMT_MASK (MS_RDONLY|MS_SYNCHRONOUS|MS_MANDLOCK|MS_I_VERSION|MS_LAZYTIME) + /* file system partition table */ struct dfs_partition { @@ -87,6 +119,7 @@ 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); +int dfs_remount(const char *path, rt_ubase_t flags, void *data); int dfs_mount(const char *device_name, const char *path, const char *filesystemtype, diff --git a/components/dfs/dfs_v2/include/dfs_mnt.h b/components/dfs/dfs_v2/include/dfs_mnt.h index 05a7458e92..da99ec2ab1 100644 --- a/components/dfs/dfs_v2/include/dfs_mnt.h +++ b/components/dfs/dfs_v2/include/dfs_mnt.h @@ -39,6 +39,8 @@ struct dfs_mnt #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 */ +#define MNT_LAZY_UMNT 0x40 /* the mnt has pending umount */ +#define MNT_RDONLY 0x80 /* the mnt is read only */ rt_atomic_t ref_count; /* reference count */ @@ -60,9 +62,13 @@ const char *dfs_mnt_get_mounted_path(struct rt_device *device); struct dfs_mnt* dfs_mnt_ref(struct dfs_mnt* mnt); int dfs_mnt_unref(struct dfs_mnt* mnt); +int dfs_mnt_umount(struct dfs_mnt *mnt, int flags); +int dfs_mnt_setflags(struct dfs_mnt *mnt, int flags); + 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); +int dfs_mnt_umount_iter(rt_bool_t (*filter)(struct dfs_mnt *mnt, void *parameter), void *parameter); typedef void (*dfs_mnt_umnt_cb_t)(struct dfs_mnt *mnt); RT_OBJECT_HOOKLIST_DECLARE(dfs_mnt_umnt_cb_t, dfs_mnt_umnt); diff --git a/components/dfs/dfs_v2/include/dfs_pcache.h b/components/dfs/dfs_v2/include/dfs_pcache.h index 01abfe3150..545219687b 100644 --- a/components/dfs/dfs_v2/include/dfs_pcache.h +++ b/components/dfs/dfs_v2/include/dfs_pcache.h @@ -118,6 +118,7 @@ int dfs_aspace_mmap_write(struct dfs_file *file, struct rt_varea *varea, void *d void dfs_pcache_release(size_t count); void dfs_pcache_unmount(struct dfs_mnt *mnt); +void dfs_pcache_clean(struct dfs_mnt *mnt); #ifdef __cplusplus } diff --git a/components/dfs/dfs_v2/src/dfs_fs.c b/components/dfs/dfs_v2/src/dfs_fs.c index 755b257191..8e5cfa004f 100644 --- a/components/dfs/dfs_v2/src/dfs_fs.c +++ b/components/dfs/dfs_v2/src/dfs_fs.c @@ -95,6 +95,52 @@ int dfs_unregister(struct dfs_filesystem_type *fs) return ret; } +#define REMNT_UNSUPP_FLAGS (~(MS_REMOUNT | MS_RMT_MASK)) +int dfs_remount(const char *path, rt_ubase_t flags, void *data) +{ + int rc = 0; + char *fullpath = RT_NULL; + struct dfs_mnt *mnt = RT_NULL; + + if (flags & REMNT_UNSUPP_FLAGS) + { + return -EINVAL; + } + + fullpath = dfs_normalize_path(RT_NULL, path); + if (!fullpath) + { + rc = -ENOENT; + } + else + { + DLOG(msg, "dfs", "mnt", DLOG_MSG, "mnt = dfs_mnt_lookup(%s)", fullpath); + mnt = dfs_mnt_lookup(fullpath); + if (mnt) + { + dfs_lock(); + dfs_mnt_setflags(mnt, flags); + dfs_unlock(); + } + else + { + struct stat buf = {0}; + if (dfs_file_stat(fullpath, &buf) == 0 && S_ISBLK(buf.st_mode)) + { + /* path was not already mounted on target */ + rc = -EINVAL; + } + else + { + /* path is not a directory */ + rc = -ENOTDIR; + } + } + } + + return rc; +} + /* * parent(mount path) * mnt_parent <- - - - - - - + @@ -314,7 +360,7 @@ int dfs_umount(const char *specialfile, int flags) if (strcmp(mnt->fullpath, fullpath) == 0) { /* is the mount point */ - rt_atomic_t ref_count = rt_atomic_load(&(mnt->ref_count)); + rt_base_t ref_count = rt_atomic_load(&(mnt->ref_count)); if (!(mnt->flags & MNT_IS_LOCKED) && rt_list_isempty(&mnt->child) && (ref_count == 1 || (flags & MNT_FORCE))) { @@ -327,17 +373,17 @@ int dfs_umount(const char *specialfile, int flags) } else { - LOG_E("the file system is busy!"); + LOG_I("the file system is busy!"); } } else { - LOG_E("the path:%s is not a mountpoint!", fullpath); + LOG_I("the path:%s is not a mountpoint!", fullpath); } } else { - LOG_E("no filesystem found."); + LOG_I("no filesystem found."); } rt_free(fullpath); } diff --git a/components/dfs/dfs_v2/src/dfs_mnt.c b/components/dfs/dfs_v2/src/dfs_mnt.c index dfae5d12ee..a2070720b0 100644 --- a/components/dfs/dfs_v2/src/dfs_mnt.c +++ b/components/dfs/dfs_v2/src/dfs_mnt.c @@ -10,11 +10,13 @@ #include -#include "dfs.h" -#include "dfs_mnt.h" -#include "dfs_dentry.h" #include "dfs_private.h" +#include +#include +#include +#include + #define DBG_TAG "DFS.mnt" #define DBG_LVL DBG_WARNING #include @@ -77,6 +79,7 @@ int dfs_mnt_insert(struct dfs_mnt* mnt, struct dfs_mnt* child) child = _root_mnt; rt_atomic_sub(&(_root_mnt->parent->ref_count), 1); rt_atomic_sub(&(_root_mnt->ref_count), 1); + _root_mnt->flags &= ~MNT_IS_LOCKED; _root_mnt = dfs_mnt_ref(mnt); mnt->parent = dfs_mnt_ref(mnt); @@ -244,15 +247,16 @@ struct dfs_mnt* dfs_mnt_ref(struct dfs_mnt* mnt) return mnt; } -int dfs_mnt_unref(struct dfs_mnt* mnt) +int dfs_mnt_unref(struct dfs_mnt *mnt) { rt_err_t ret = RT_EOK; + rt_base_t ref_count; if (mnt) { - rt_atomic_sub(&(mnt->ref_count), 1); + ref_count = rt_atomic_sub(&(mnt->ref_count), 1) - 1; - if (rt_atomic_load(&(mnt->ref_count)) == 0) + if (ref_count == 0) { dfs_lock(); @@ -282,6 +286,21 @@ int dfs_mnt_unref(struct dfs_mnt* mnt) return ret; } +int dfs_mnt_setflags(struct dfs_mnt *mnt, int flags) +{ + int error = 0; + + if (flags & MS_RDONLY) + { + mnt->flags |= MNT_RDONLY; +#ifdef RT_USING_PAGECACHE + dfs_pcache_clean(mnt); +#endif + } + + return error; +} + int dfs_mnt_destroy(struct dfs_mnt* mnt) { rt_err_t ret = RT_EOK; diff --git a/components/dfs/dfs_v2/src/dfs_pcache.c b/components/dfs/dfs_v2/src/dfs_pcache.c index 2a68c268a4..cba36d8372 100644 --- a/components/dfs/dfs_v2/src/dfs_pcache.c +++ b/components/dfs/dfs_v2/src/dfs_pcache.c @@ -162,7 +162,7 @@ void dfs_pcache_release(size_t count) dfs_pcache_unlock(); } -void dfs_pcache_unmount(struct dfs_mnt *mnt) +static void _pcache_clean(struct dfs_mnt *mnt, int (*cb)(struct dfs_aspace *aspace)) { rt_list_t *node = RT_NULL; struct dfs_aspace *aspace = RT_NULL; @@ -177,7 +177,7 @@ void dfs_pcache_unmount(struct dfs_mnt *mnt) if (aspace && aspace->mnt == mnt) { dfs_aspace_clean(aspace); - dfs_aspace_release(aspace); + cb(aspace); } } @@ -189,13 +189,28 @@ void dfs_pcache_unmount(struct dfs_mnt *mnt) if (aspace && aspace->mnt == mnt) { dfs_aspace_clean(aspace); - dfs_aspace_release(aspace); + cb(aspace); } } dfs_pcache_unlock(); } +void dfs_pcache_unmount(struct dfs_mnt *mnt) +{ + _pcache_clean(mnt, dfs_aspace_release); +} + +static int _dummy_cb(struct dfs_aspace *mnt) +{ + return 0; +} + +void dfs_pcache_clean(struct dfs_mnt *mnt) +{ + _pcache_clean(mnt, _dummy_cb); +} + static int dfs_pcache_limit_check(void) { int index = 4; @@ -1140,14 +1155,21 @@ int dfs_aspace_write(struct dfs_file *file, const void *buf, size_t count, off_t if (file && file->vnode && file->vnode->aspace) { - if (!(file->vnode->aspace->ops->write)) - return ret; struct dfs_vnode *vnode = file->vnode; struct dfs_aspace *aspace = vnode->aspace; struct dfs_page *page; char *ptr = (char *)buf; + if (!(aspace->ops->write)) + { + return ret; + } + else if (aspace->mnt && (aspace->mnt->flags & MNT_RDONLY)) + { + return -EROFS; + } + ret = 0; while (count) diff --git a/components/lwp/lwp_syscall.c b/components/lwp/lwp_syscall.c index 22aa85a779..72f5b87ba6 100644 --- a/components/lwp/lwp_syscall.c +++ b/components/lwp/lwp_syscall.c @@ -5743,79 +5743,94 @@ sysret_t sys_fstatfs64(int fd, size_t sz, struct statfs *buf) return ret; } -sysret_t sys_mount(char *source, char *target, - char *filesystemtype, - unsigned long mountflags, void *data) +static char *_cp_from_usr_string(char *dst, char *src, size_t length) { - char *copy_source; - char *copy_target; - char *copy_filesystemtype; - size_t len_source, copy_len_source; - size_t len_target, copy_len_target; - size_t len_filesystemtype, copy_len_filesystemtype; - char *tmp = NULL; - int ret = 0; - struct stat buf = {0}; - - len_source = lwp_user_strlen(source); - if (len_source <= 0) - return -EINVAL; - - len_target = lwp_user_strlen(target); - if (len_target <= 0) - return -EINVAL; - - len_filesystemtype = lwp_user_strlen(filesystemtype); - if (len_filesystemtype <= 0) - return -EINVAL; - - copy_source = (char*)rt_malloc(len_source + 1 + len_target + 1 + len_filesystemtype + 1); - if (!copy_source) + char *rc; + size_t copied_bytes; + if (length) { - return -ENOMEM; - } - copy_target = copy_source + len_source + 1; - copy_filesystemtype = copy_target + len_target + 1; - - copy_len_source = lwp_get_from_user(copy_source, source, len_source); - copy_source[copy_len_source] = '\0'; - copy_len_target = lwp_get_from_user(copy_target, target, len_target); - copy_target[copy_len_target] = '\0'; - copy_len_filesystemtype = lwp_get_from_user(copy_filesystemtype, filesystemtype, len_filesystemtype); - copy_filesystemtype[copy_len_filesystemtype] = '\0'; - - if (strcmp(copy_filesystemtype, "nfs") == 0) - { - tmp = copy_source; - copy_source = NULL; - } - if (strcmp(copy_filesystemtype, "tmp") == 0) - { - copy_source = NULL; - } - - if (copy_source && stat(copy_source, &buf) && S_ISBLK(buf.st_mode)) - { - char *dev_fullpath = dfs_normalize_path(RT_NULL, copy_source); - RT_ASSERT(rt_strncmp(dev_fullpath, "/dev/", sizeof("/dev/") - 1) == 0); - ret = dfs_mount(dev_fullpath + sizeof("/dev/") - 1, copy_target, copy_filesystemtype, 0, tmp); - if (ret < 0) - { - ret = -rt_get_errno(); - } - rt_free(copy_source); - rt_free(dev_fullpath); + copied_bytes = lwp_get_from_user(dst, src, length); + dst[copied_bytes] = '\0'; + rc = dst; } else { - ret = dfs_mount(copy_source, copy_target, copy_filesystemtype, 0, tmp); + rc = RT_NULL; + } + return rc; +} + +sysret_t sys_mount(char *source, char *target, char *filesystemtype, + unsigned long mountflags, void *data) +{ + char *kbuffer, *ksource, *ktarget, *kfs; + size_t len_source, len_target, len_fs; + char *tmp = NULL; + int ret = 0; + struct stat buf = {0}; + char *dev_fullpath = RT_NULL; + + len_source = source ? lwp_user_strlen(source) : 0; + if (len_source < 0) + return -EINVAL; + + len_target = target ? lwp_user_strlen(target) : 0; + if (len_target <= 0) + return -EINVAL; + + len_fs = filesystemtype ? lwp_user_strlen(filesystemtype) : 0; + if (len_fs < 0) + return -EINVAL; + + kbuffer = (char *)rt_malloc(len_source + 1 + len_target + 1 + len_fs + 1); + if (!kbuffer) + { + return -ENOMEM; + } + + /* get parameters from user space */ + ksource = kbuffer; + ktarget = ksource + len_source + 1; + kfs = ktarget + len_target + 1; + ksource = _cp_from_usr_string(ksource, source, len_source); + ktarget = _cp_from_usr_string(ktarget, target, len_target); + kfs = _cp_from_usr_string(kfs, filesystemtype, len_fs); + + if (mountflags & MS_REMOUNT) + { + ret = dfs_remount(ktarget, mountflags, data); + } + else + { + if (strcmp(kfs, "nfs") == 0) + { + tmp = ksource; + ksource = NULL; + } + if (strcmp(kfs, "tmp") == 0) + { + ksource = NULL; + } + + if (ksource && !dfs_file_stat(ksource, &buf) && S_ISBLK(buf.st_mode)) + { + dev_fullpath = dfs_normalize_path(RT_NULL, ksource); + RT_ASSERT(rt_strncmp(dev_fullpath, "/dev/", sizeof("/dev/") - 1) == 0); + ret = dfs_mount(dev_fullpath + sizeof("/dev/") - 1, ktarget, kfs, 0, tmp); + } + else + { + ret = dfs_mount(ksource, ktarget, kfs, 0, tmp); + } + if (ret < 0) { ret = -rt_get_errno(); } - rt_free(copy_source); } + rt_free(kbuffer); + rt_free(dev_fullpath); return ret; }