未验证 提交 5686967f 编写于 作者: O openeuler-ci-bot 提交者: Gitee

!149 [openEuler-22.09] Add sysfs file for overlayfs

Merge Pull Request from: @hiixfj 
 
In the actual production environment, Overlayfs often occurs some problems, such as continuous growth of quota statistics. There is no good way to define this category for the current environment. Overlayfs has many restrictions in the actual use process but it has not directly restricted at the code level. Therefore, some strange problems introduced in operation errors will occur during the use process. It is time-consuming. Based on this background, Overlayfs's maintenance function needs to be enhanced.

This patch add sysfs file for overlayfs to recording the mount information. The sysfs file will be deleted only when Overlayfs is truly unloaded.

category: feature
bugzilla:<https://gitee.com/openeuler/kernel/issues/I5WIS5>
CVE: NA

--------------------------------

Put a hook function in file_system_type,
and register sysfs after do_add_mount().

Signed-off-by: hiyoyolumi 862127279@qq.com 
 
Link:https://gitee.com/openeuler/kernel/pulls/149 
Reviewed-by: Zheng Zengkai <zhengzengkai@huawei.com> 
Signed-off-by: Zheng Zengkai <zhengzengkai@huawei.com> 
...@@ -2900,6 +2900,8 @@ static int do_new_mount(struct path *path, const char *fstype, int sb_flags, ...@@ -2900,6 +2900,8 @@ static int do_new_mount(struct path *path, const char *fstype, int sb_flags,
err = vfs_get_tree(fc); err = vfs_get_tree(fc);
if (!err) if (!err)
err = do_new_mount_fc(fc, path, mnt_flags); err = do_new_mount_fc(fc, path, mnt_flags);
if (!err && type->mount_end)
err = type->mount_end(fc, path);
put_fs_context(fc); put_fs_context(fc);
return err; return err;
......
...@@ -6,4 +6,4 @@ ...@@ -6,4 +6,4 @@
obj-$(CONFIG_OVERLAY_FS) += overlay.o obj-$(CONFIG_OVERLAY_FS) += overlay.o
overlay-objs := super.o namei.o util.o inode.o file.o dir.o readdir.o \ overlay-objs := super.o namei.o util.o inode.o file.o dir.o readdir.o \
copy_up.o export.o copy_up.o export.o sysfs.o
...@@ -546,3 +546,10 @@ int ovl_set_origin(struct dentry *dentry, struct dentry *lower, ...@@ -546,3 +546,10 @@ int ovl_set_origin(struct dentry *dentry, struct dentry *lower,
/* export.c */ /* export.c */
extern const struct export_operations ovl_export_operations; extern const struct export_operations ovl_export_operations;
/* sysfs.c */
int __init ovl_init_sysfs(void);
void ovl_exit_sysfs(void);
int ovl_register_sysfs(struct super_block *sb);
void ovl_unregister_sysfs(struct super_block *sb);
int ovl_mergedir_backup(struct super_block *sb, const char *str);
...@@ -5,10 +5,13 @@ ...@@ -5,10 +5,13 @@
* Copyright (C) 2016 Red Hat, Inc. * Copyright (C) 2016 Red Hat, Inc.
*/ */
#include <linux/kobject.h>
struct ovl_config { struct ovl_config {
char *lowerdir; char *lowerdir;
char *upperdir; char *upperdir;
char *workdir; char *workdir;
char *mergedir;
bool default_permissions; bool default_permissions;
bool redirect_dir; bool redirect_dir;
bool redirect_follow; bool redirect_follow;
...@@ -81,6 +84,8 @@ struct ovl_fs { ...@@ -81,6 +84,8 @@ struct ovl_fs {
struct dentry *whiteout; struct dentry *whiteout;
/* r/o snapshot of upperdir sb's only taken on volatile mounts */ /* r/o snapshot of upperdir sb's only taken on volatile mounts */
errseq_t errseq; errseq_t errseq;
struct kobject kobj;
struct completion kobj_unregister;
}; };
static inline struct vfsmount *ovl_upper_mnt(struct ovl_fs *ofs) static inline struct vfsmount *ovl_upper_mnt(struct ovl_fs *ofs)
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/posix_acl_xattr.h> #include <linux/posix_acl_xattr.h>
#include <linux/exportfs.h> #include <linux/exportfs.h>
#include <linux/fs_context.h>
#include "overlayfs.h" #include "overlayfs.h"
MODULE_AUTHOR("Miklos Szeredi <miklos@szeredi.hu>"); MODULE_AUTHOR("Miklos Szeredi <miklos@szeredi.hu>");
...@@ -244,9 +245,14 @@ static void ovl_free_fs(struct ovl_fs *ofs) ...@@ -244,9 +245,14 @@ static void ovl_free_fs(struct ovl_fs *ofs)
kfree(ofs->config.lowerdir); kfree(ofs->config.lowerdir);
kfree(ofs->config.upperdir); kfree(ofs->config.upperdir);
kfree(ofs->config.workdir); kfree(ofs->config.workdir);
kfree(ofs->config.mergedir);
kfree(ofs->config.redirect_mode); kfree(ofs->config.redirect_mode);
if (ofs->creator_cred) if (ofs->creator_cred)
put_cred(ofs->creator_cred); put_cred(ofs->creator_cred);
kobject_put(&ofs->kobj);
wait_for_completion(&ofs->kobj_unregister);
kfree(ofs); kfree(ofs);
} }
...@@ -254,6 +260,8 @@ static void ovl_put_super(struct super_block *sb) ...@@ -254,6 +260,8 @@ static void ovl_put_super(struct super_block *sb)
{ {
struct ovl_fs *ofs = sb->s_fs_info; struct ovl_fs *ofs = sb->s_fs_info;
ovl_unregister_sysfs(sb);
ovl_free_fs(ofs); ovl_free_fs(ofs);
} }
...@@ -2054,11 +2062,32 @@ static struct dentry *ovl_mount(struct file_system_type *fs_type, int flags, ...@@ -2054,11 +2062,32 @@ static struct dentry *ovl_mount(struct file_system_type *fs_type, int flags,
return mount_nodev(fs_type, flags, raw_data, ovl_fill_super); return mount_nodev(fs_type, flags, raw_data, ovl_fill_super);
} }
static int ovl_mount_end(struct fs_context *fc, struct path *path)
{
char buffer[PATH_MAX];
const char *tmp;
int err;
err = ovl_register_sysfs(fc->root->d_sb);
if (err)
return err;
tmp = dentry_path_raw(path->dentry, buffer, PATH_MAX);
if (IS_ERR_OR_NULL(tmp))
tmp = path->dentry->d_name.name;
err = ovl_mergedir_backup(fc->root->d_sb, tmp);
if (err)
return err;
return err;
}
static struct file_system_type ovl_fs_type = { static struct file_system_type ovl_fs_type = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = "overlay", .name = "overlay",
.mount = ovl_mount, .mount = ovl_mount,
.kill_sb = kill_anon_super, .kill_sb = kill_anon_super,
.mount_end = ovl_mount_end,
}; };
MODULE_ALIAS_FS("overlay"); MODULE_ALIAS_FS("overlay");
...@@ -2081,6 +2110,12 @@ static int __init ovl_init(void) ...@@ -2081,6 +2110,12 @@ static int __init ovl_init(void)
if (ovl_inode_cachep == NULL) if (ovl_inode_cachep == NULL)
return -ENOMEM; return -ENOMEM;
err = ovl_init_sysfs();
if (err) {
kmem_cache_destroy(ovl_inode_cachep);
return err;
}
err = ovl_aio_request_cache_init(); err = ovl_aio_request_cache_init();
if (!err) { if (!err) {
err = register_filesystem(&ovl_fs_type); err = register_filesystem(&ovl_fs_type);
...@@ -2089,6 +2124,7 @@ static int __init ovl_init(void) ...@@ -2089,6 +2124,7 @@ static int __init ovl_init(void)
ovl_aio_request_cache_destroy(); ovl_aio_request_cache_destroy();
} }
ovl_exit_sysfs();
kmem_cache_destroy(ovl_inode_cachep); kmem_cache_destroy(ovl_inode_cachep);
return err; return err;
...@@ -2105,6 +2141,8 @@ static void __exit ovl_exit(void) ...@@ -2105,6 +2141,8 @@ static void __exit ovl_exit(void)
rcu_barrier(); rcu_barrier();
kmem_cache_destroy(ovl_inode_cachep); kmem_cache_destroy(ovl_inode_cachep);
ovl_aio_request_cache_destroy(); ovl_aio_request_cache_destroy();
ovl_exit_sysfs();
} }
module_init(ovl_init); module_init(ovl_init);
......
// SPDX-License-Identifier: GPL-2.0
/*
* fs/overlayfs/sysfs.c
*
* This file is used for creating a sysfs file for the
* overlay file system
*
* Based significantly on the fs/ext4/sysfs.c
*/
#include <linux/kobject.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/sysfs.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/dcache.h>
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/namei.h>
#include "ovl_entry.h"
static struct kobject *ovl_root;
enum attr_id_t {
attr_upper,
attr_lower,
attr_work,
attr_merge,
};
struct ovl_attr {
struct attribute attr;
short attr_id;
};
#define OVL_ATTR(_name, _mode) \
static struct ovl_attr ovl_attr_##_name = { \
.attr = { .name = __stringify(_name), .mode = _mode }, \
.attr_id = attr_##_name, \
}
#define ATTR_LIST(name) &ovl_attr_##name.attr
OVL_ATTR(upper, 0440);
OVL_ATTR(lower, 0440);
OVL_ATTR(work, 0440);
OVL_ATTR(merge, 0440);
static struct attribute *default_attrs[] = {
ATTR_LIST(upper),
ATTR_LIST(lower),
ATTR_LIST(work),
ATTR_LIST(merge),
NULL
};
int ovl_mergedir_backup(struct super_block *sb, const char *str)
{
struct ovl_fs *ofs = sb->s_fs_info;
ofs->config.mergedir = kstrdup(str, GFP_KERNEL);
if (!ofs->config.mergedir)
return -ENOMEM;
return 0;
}
static ssize_t ovl_sysfs_show(struct kobject *kobj, struct attribute *attr, char *buf)
{
struct ovl_fs *ofs = container_of(kobj, struct ovl_fs, kobj);
struct ovl_attr *ovl_attribute =
container_of(attr, struct ovl_attr, attr);
switch (ovl_attribute->attr_id) {
case attr_upper:
return snprintf(buf, PAGE_SIZE, "%s\n",
ofs->config.upperdir);
case attr_lower:
return snprintf(buf, PAGE_SIZE, "%s\n",
ofs->config.lowerdir);
case attr_work:
return snprintf(buf, PAGE_SIZE, "%s\n",
ofs->config.workdir);
case attr_merge:
return snprintf(buf, PAGE_SIZE, "%s\n",
ofs->config.mergedir);
default:
return -EPERM;
}
}
static void ovl_kobj_release(struct kobject *kobj)
{
struct ovl_fs *ofs = container_of(kobj, struct ovl_fs, kobj);
complete(&ofs->kobj_unregister);
}
static struct sysfs_ops ovl_sysfs_ops = {
.show = ovl_sysfs_show
};
static struct kobj_type ovl_sb_ktype = {
.sysfs_ops = &ovl_sysfs_ops,
.default_attrs = default_attrs,
.release = ovl_kobj_release
};
int ovl_register_sysfs(struct super_block *sb)
{
struct ovl_fs *ofs = OVL_FS(sb);
int err;
init_completion(&ofs->kobj_unregister);
err = kobject_init_and_add(&ofs->kobj, &ovl_sb_ktype,
ovl_root, "merge_%d_%d",
MAJOR(sb->s_dev), MINOR(sb->s_dev));
if (err) {
kobject_put(&ofs->kobj);
wait_for_completion(&ofs->kobj_unregister);
}
return err;
}
void ovl_unregister_sysfs(struct super_block *sb)
{
kobject_del(&OVL_FS(sb)->kobj);
}
int __init ovl_init_sysfs(void)
{
ovl_root = kobject_create_and_add("overlayfs", fs_kobj);
if (!ovl_root)
return -ENOMEM;
return 0;
}
void ovl_exit_sysfs(void)
{
kobject_put(ovl_root);
ovl_root = NULL;
}
...@@ -2316,7 +2316,11 @@ struct file_system_type { ...@@ -2316,7 +2316,11 @@ struct file_system_type {
struct lock_class_key i_mutex_key; struct lock_class_key i_mutex_key;
struct lock_class_key i_mutex_dir_key; struct lock_class_key i_mutex_dir_key;
#ifndef __GENKSYMS__
int (*mount_end) (struct fs_context *, struct path *);
#else
KABI_RESERVE(1) KABI_RESERVE(1)
#endif
KABI_RESERVE(2) KABI_RESERVE(2)
KABI_RESERVE(3) KABI_RESERVE(3)
KABI_RESERVE(4) KABI_RESERVE(4)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册