fixed unmount
This commit is contained in:
parent
f5cabb007f
commit
96ba11d9b2
66
statsfs.c
66
statsfs.c
@ -1,4 +1,3 @@
|
||||
// libfs.c
|
||||
#include <linux/fs.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
@ -7,6 +6,9 @@
|
||||
#include <linux/namei.h>
|
||||
#include <linux/mount.h>
|
||||
#include <linux/dcache.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/fs_context.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
#define LIBFS_MAGIC 0xA0B0C0D0
|
||||
#define LIBFS_BOOKS_MODE 01777
|
||||
@ -14,9 +16,8 @@
|
||||
#define LIBFS_SUBDIR_MODE 01777
|
||||
|
||||
static struct super_block *libfs_sb;
|
||||
|
||||
// Track books inode to monitor link targets
|
||||
static struct inode *books_inode = NULL;
|
||||
static struct vfsmount *libfs_mnt;
|
||||
|
||||
static const struct super_operations libfs_sops = {
|
||||
.statfs = simple_statfs,
|
||||
@ -39,7 +40,7 @@ static struct inode *libfs_get_inode(struct super_block *sb, umode_t mode) {
|
||||
if (S_ISDIR(mode)) {
|
||||
inode->i_fop = &simple_dir_operations;
|
||||
} else {
|
||||
inode->i_fop = &libfs_file_ops; // fallback
|
||||
inode->i_fop = &libfs_file_ops;
|
||||
}
|
||||
inode->i_mode = mode;
|
||||
return inode;
|
||||
@ -49,9 +50,51 @@ static bool is_protected_dentry(struct dentry *dentry) {
|
||||
return (strcmp(dentry->d_name.name, "books") == 0 || strcmp(dentry->d_name.name, "authors") == 0);
|
||||
}
|
||||
|
||||
struct cleanup_ctx {
|
||||
struct inode *victim;
|
||||
};
|
||||
|
||||
static void libfs_cleanup_links(struct inode *victim)
|
||||
{
|
||||
struct dentry *root = libfs_sb->s_root;
|
||||
|
||||
struct qstr authors_q = QSTR_INIT("authors", 7);
|
||||
struct dentry *authors = d_lookup(root, &authors_q);
|
||||
if (!authors || d_really_is_negative(authors)) {
|
||||
dput(authors);
|
||||
return;
|
||||
}
|
||||
|
||||
// Здесь конкретный пример: если ты сам знаешь имя линка на victim
|
||||
// То можешь через d_lookup() найти его и удалить
|
||||
struct qstr filename = QSTR_INIT("some_symlink", 12);
|
||||
struct dentry *maybe_link = d_lookup(authors, &filename);
|
||||
|
||||
if (maybe_link && maybe_link->d_inode == victim) {
|
||||
inode_lock(authors->d_inode);
|
||||
vfs_unlink(NULL, authors->d_inode, maybe_link, NULL);
|
||||
inode_unlock(authors->d_inode);
|
||||
}
|
||||
|
||||
dput(maybe_link);
|
||||
dput(authors);
|
||||
}
|
||||
|
||||
static int libfs_unlink(struct inode *dir, struct dentry *dentry) {
|
||||
if (dir == libfs_sb->s_root->d_inode && is_protected_dentry(dentry))
|
||||
return -EPERM;
|
||||
|
||||
struct inode *victim = dentry->d_inode;
|
||||
int ret = simple_unlink(dir, dentry);
|
||||
if (ret == 0 && dir == books_inode) {
|
||||
libfs_cleanup_links(victim);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int libfs_mkdir(struct mnt_idmap *idmap, struct inode *dir, struct dentry *dentry, umode_t mode) {
|
||||
if (dir == libfs_sb->s_root->d_inode) {
|
||||
return -EPERM; // no mkdir in root
|
||||
return -EPERM;
|
||||
}
|
||||
struct inode *inode = libfs_get_inode(dir->i_sb, S_IFDIR | LIBFS_SUBDIR_MODE);
|
||||
if (!inode)
|
||||
@ -62,12 +105,6 @@ static int libfs_mkdir(struct mnt_idmap *idmap, struct inode *dir, struct dentry
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int libfs_unlink(struct inode *dir, struct dentry *dentry) {
|
||||
if (dir == libfs_sb->s_root->d_inode && is_protected_dentry(dentry))
|
||||
return -EPERM;
|
||||
return simple_unlink(dir, dentry);
|
||||
}
|
||||
|
||||
static int libfs_rmdir(struct inode *dir, struct dentry *dentry) {
|
||||
if (dir == libfs_sb->s_root->d_inode && is_protected_dentry(dentry))
|
||||
return -EPERM;
|
||||
@ -145,10 +182,15 @@ static struct file_system_type libfs_type = {
|
||||
};
|
||||
|
||||
static int __init libfs_init(void) {
|
||||
return register_filesystem(&libfs_type);
|
||||
int ret = register_filesystem(&libfs_type);
|
||||
if (ret)
|
||||
return ret;
|
||||
libfs_mnt = kern_mount(&libfs_type);
|
||||
return PTR_ERR_OR_ZERO(libfs_mnt);
|
||||
}
|
||||
|
||||
static void __exit libfs_exit(void) {
|
||||
kern_unmount(libfs_mnt);
|
||||
unregister_filesystem(&libfs_type);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user