mirror of
https://github.com/RT-Thread/rt-thread.git
synced 2025-12-25 16:57:20 +00:00
feat: add support for dfs remount functionality
This patch introduces a remount feature for the DFS, allowing for the modification of mount parameters without unmounting the filesystem, the remount functionality helps modify certain mount flags (like `MS_RDONLY`) without requiring an unmount, providing more control over mounted filesystems in the system. The updates is essential for user space init proc to cleanup the runtime resource, ensuring clean handling of cached data and enhancing system robustness during power down processing. Changes: - Defined new constants for remount flags in `dfs_fs.h`. - Added the `dfs_remount()` function in `dfs_fs.c` to handle remount operations. - Introduced a check for unsupported flags and handle error conditions such as invalid paths or non-directory targets. - Updated the `dfs_mnt` structure in `dfs_mnt.h` to include a read-only flag (`MNT_RDONLY`). - The `dfs_remount()` function allows changing the read-only status of a mounted filesystem. - Added `MNT_LAZY_UMNT` and `MNT_RDONLY` flags to `dfs_mnt` structure. - Introduced `dfs_mnt_setflags` function for dynamic flag management. - Updated `dfs_remount` to utilize `dfs_mnt_setflags` for flag setting. - Enhanced unmount operations with `dfs_mnt_umount_iter` and lazy unmounting. - Added `dfs_pcache_clean` to handle cache cleanup for read-only mounts. - Improved error reporting in `dfs_umount` for better user feedback. - Refactored `sys_mount` to streamline parameter handling and support remounts. - Introduced `_cp_from_usr_string` helper for user-space string operations. - Updated internal APIs to ensure consistency in reference count management. Signed-off-by: Shell <smokewood@qq.com>
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user