This commit is contained in:
g2px1 2025-06-20 17:44:27 +00:00
parent 212617e63f
commit 42839e6cd9
2 changed files with 62 additions and 42 deletions

81
libfs.c
View File

@ -1,7 +1,3 @@
/*
* Custom Filesystem Module - Implements the described behavior for "books" and "authors" directories.
*/
#include <linux/init.h> #include <linux/init.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/fs.h> #include <linux/fs.h>
@ -13,6 +9,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/hashtable.h> #include <linux/hashtable.h>
#include <linux/fs_context.h> #include <linux/fs_context.h>
#include <linux/statfs.h>
#define FS_MAGIC 0x20240615 #define FS_MAGIC 0x20240615
#define BOOKS_MODE 01777 #define BOOKS_MODE 01777
@ -32,7 +29,7 @@ struct link_entry {
struct inode *target; struct inode *target;
}; };
DEFINE_HASHTABLE(link_table, 6); // 64 buckets DEFINE_HASHTABLE(link_table, 6);
static void remove_links_to_inode(struct inode *inode) { static void remove_links_to_inode(struct inode *inode) {
struct link_entry *entry; struct link_entry *entry;
@ -40,6 +37,7 @@ static void remove_links_to_inode(struct inode *inode) {
int bkt; int bkt;
hash_for_each_safe(link_table, bkt, tmp, entry, node) { hash_for_each_safe(link_table, bkt, tmp, entry, node) {
if (entry->target == inode) { if (entry->target == inode) {
printk(KERN_INFO "customfs: removing hardlink to inode %lu\n", inode->i_ino);
d_delete(entry->link); d_delete(entry->link);
hash_del(&entry->node); hash_del(&entry->node);
kfree(entry); kfree(entry);
@ -57,6 +55,16 @@ static void fs_evict_inode(struct inode *inode) {
clear_inode(inode); clear_inode(inode);
} }
static int fs_statfs(struct dentry *dentry, struct kstatfs *buf) {
buf->f_type = FS_MAGIC;
return 0;
}
static const struct super_operations fs_ops = {
.evict_inode = fs_evict_inode,
.statfs = fs_statfs,
};
static ssize_t books_file_read(struct file *file, char __user *buf, size_t len, loff_t *ppos) { static ssize_t books_file_read(struct file *file, char __user *buf, size_t len, loff_t *ppos) {
return simple_read_from_buffer(buf, len, ppos, file->private_data, PAGE_SIZE); return simple_read_from_buffer(buf, len, ppos, file->private_data, PAGE_SIZE);
} }
@ -78,20 +86,18 @@ static const struct inode_operations books_file_iops = {
static const struct inode_operations author_subdir_iops; static const struct inode_operations author_subdir_iops;
static struct dentry *author_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) {
return simple_lookup(dir, dentry, flags);
}
static int author_mkdir(struct user_namespace *ns, struct inode *dir, struct dentry *dentry, umode_t mode) { static int author_mkdir(struct user_namespace *ns, struct inode *dir, struct dentry *dentry, umode_t mode) {
struct inode *inode; struct inode *inode = new_inode(dir->i_sb);
inode = new_inode(dir->i_sb);
if (!inode) if (!inode)
return -ENOMEM; return -ENOMEM;
inode->i_ino = get_next_ino(); inode->i_ino = get_next_ino();
inode_init_owner(ns, inode, dir, S_IFDIR | AUTHOR_SUBDIR_MODE); inode_init_owner(&init_user_ns, inode, dir, S_IFDIR | AUTHOR_SUBDIR_MODE);
inode->i_op = &author_subdir_iops; inode->i_op = &author_subdir_iops;
inode->i_fop = &simple_dir_operations; inode->i_fop = &simple_dir_operations;
inc_nlink(inode);
inc_nlink(dir);
d_add(dentry, inode); d_add(dentry, inode);
printk(KERN_INFO "customfs: created author subdir '%s'\n", dentry->d_name.name);
return 0; return 0;
} }
@ -106,22 +112,20 @@ static int author_link(struct dentry *old_dentry, struct inode *dir, struct dent
entry->link = dget(new_dentry); entry->link = dget(new_dentry);
entry->target = inode; entry->target = inode;
hash_add(link_table, &entry->node, inode->i_ino); hash_add(link_table, &entry->node, inode->i_ino);
printk(KERN_INFO "customfs: created hardlink '%s' to inode %lu\n",
new_dentry->d_name.name, inode->i_ino);
} }
} }
return err; return err;
} }
static const struct inode_operations author_subdir_iops = { static const struct inode_operations author_subdir_iops = {
.lookup = author_lookup, .lookup = simple_lookup,
.mkdir = author_mkdir, .mkdir = author_mkdir,
.rmdir = simple_rmdir, .rmdir = simple_rmdir,
.link = author_link, .link = author_link,
}; };
static const struct super_operations fs_ops = {
.evict_inode = fs_evict_inode,
};
static struct inode *fs_make_inode(struct super_block *sb, umode_t mode) { static struct inode *fs_make_inode(struct super_block *sb, umode_t mode) {
struct inode *inode = new_inode(sb); struct inode *inode = new_inode(sb);
if (!inode) if (!inode)
@ -131,9 +135,10 @@ static struct inode *fs_make_inode(struct super_block *sb, umode_t mode) {
inode->i_sb = sb; inode->i_sb = sb;
inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode); inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode);
if (S_ISDIR(mode) && !inode->i_op) { if (S_ISDIR(mode)) {
inode->i_op = &simple_dir_inode_operations; inode->i_op = &simple_dir_inode_operations;
inode->i_fop = &simple_dir_operations; inode->i_fop = &simple_dir_operations;
inc_nlink(inode);
} else if (S_ISREG(mode)) { } else if (S_ISREG(mode)) {
inode->i_fop = &books_file_fops; inode->i_fop = &books_file_fops;
inode->i_op = &books_file_iops; inode->i_op = &books_file_iops;
@ -159,33 +164,55 @@ static int fs_fill_super(struct super_block *sb, void *data, int silent) {
if (!root_dentry) if (!root_dentry)
return -ENOMEM; return -ENOMEM;
sb->s_root = root_dentry;
books_inode = fs_make_inode(sb, S_IFDIR | BOOKS_MODE); books_inode = fs_make_inode(sb, S_IFDIR | BOOKS_MODE);
if (!books_inode) if (!books_inode)
return -ENOMEM; goto out_root;
books_inode->i_op = &simple_dir_inode_operations; books_inode->i_op = &simple_dir_inode_operations;
books_inode->i_fop = &simple_dir_operations; books_inode->i_fop = &simple_dir_operations;
books_inode->i_mode |= S_IWUSR | S_IWGRP | S_IWOTH; inc_nlink(books_inode);
books_dentry = d_alloc_name(root_dentry, "books"); books_dentry = d_alloc_name(root_dentry, "books");
if (!books_dentry) if (!books_dentry)
return -ENOMEM; goto out_books;
d_add(books_dentry, books_inode); d_add(books_dentry, books_inode);
d_rehash(books_dentry);
printk(KERN_INFO "customfs: 'books' directory created\n");
authors_inode = fs_make_inode(sb, S_IFDIR | AUTHORS_MODE); authors_inode = fs_make_inode(sb, S_IFDIR | AUTHORS_MODE);
if (!authors_inode) if (!authors_inode)
return -ENOMEM; goto out_books_dentry;
authors_inode->i_op = &author_subdir_iops;
inc_nlink(authors_inode);
authors_dentry = d_alloc_name(root_dentry, "authors"); authors_dentry = d_alloc_name(root_dentry, "authors");
if (!authors_dentry) if (!authors_dentry)
return -ENOMEM; goto out_authors;
authors_inode->i_op = &author_subdir_iops;
d_add(authors_dentry, authors_inode); d_add(authors_dentry, authors_inode);
d_rehash(authors_dentry);
printk(KERN_INFO "customfs: 'authors' directory created\n");
sb->s_root = root_dentry;
printk(KERN_INFO "customfs: fill_super completed\n");
printk(KERN_INFO "customfs: root inode=%lu\n", root_inode->i_ino);
printk(KERN_INFO "customfs: books inode=%lu\n", books_inode->i_ino);
printk(KERN_INFO "customfs: authors inode=%lu\n", authors_inode->i_ino);
return 0; return 0;
out_authors:
iput(authors_inode);
out_books_dentry:
dput(books_dentry);
out_books:
iput(books_inode);
out_root:
dput(root_dentry);
iput(root_inode);
return -ENOMEM;
} }
static struct dentry *fs_mount(struct file_system_type *type, int flags, static struct dentry *fs_mount(struct file_system_type *type, int flags,
const char *dev, void *data) { const char *dev, void *data) {
printk(KERN_INFO "customfs: mounting\n");
return mount_nodev(type, flags, data, fs_fill_super); return mount_nodev(type, flags, data, fs_fill_super);
} }
@ -198,11 +225,13 @@ static struct file_system_type fs_type = {
static int __init fs_init(void) { static int __init fs_init(void) {
hash_init(link_table); hash_init(link_table);
printk(KERN_INFO "customfs: module loaded\n");
return register_filesystem(&fs_type); return register_filesystem(&fs_type);
} }
static void __exit fs_exit(void) { static void __exit fs_exit(void) {
unregister_filesystem(&fs_type); unregister_filesystem(&fs_type);
printk(KERN_INFO "customfs: module unloaded\n");
} }
module_init(fs_init); module_init(fs_init);

View File

@ -1,21 +1,12 @@
#!/bin/bash #!/bin/bash
set -e set -e
# Убить все процессы, использующие /mnt/test sudo umount /mnt/customfs 2>/dev/null || true
sudo fuser -km /mnt/test || true sudo rmmod libfs 2>/dev/null || true
# Подождать, пока умрут make
sleep 0.5
# Умонтировать sudo insmod libfs.ko
sudo umount /mnt/test || true sudo mount -t customfs none /mnt/customfs
ls -l /mnt/customfs
# Выгрузить модуль
sudo rmmod statsfs || true
# Подождать, пока освободится
sleep 0.5
# Вставить модуль и смонтировать
sudo insmod statsfs.ko
sudo mount -t libfs none /mnt/test