想法: 想要得到目前所有在VFS中注册过的文件系统,并且得到某个文件系统instance的super_block. 以及其自己实现的super_block.
其实
cat /proc/filesystems就能查看当前在kernel中已经注册的文件系统. 通过get_fs_type()可以拿到一个文件系统的file_system_type.但是我想要所有的fs type.
因为VFS通过一个非入侵式的list来存放所有已注册的文件系统,位于fs/filesystems.c中.
该list是static的,那么不妨添加一个non-static函数将其暴露出来.然后使用EXPORT_SYMBOL()导出给模块使用.
还有一点需要知道的是: 当某个文件系统mount后, VFS会将其该类型的所有挂载上的实例(super_block)都加入到struct file_system_type的fs_supers成员. fs_supers是一个hlist
在fs/filesystems.c文件下添加函数
struct file_system_type *LuChao_getfilesystems() {
return file_systems;
}
EXPORT_SYMBOL(LuChao_getfilesystems);
在include/linux/fs.h中添加函数声明
extern struct file_system_type *LuChao_getfilesystems(void);
回到kernel的根目录下编译
make然后make install
重新制作启动项然后重启(非UEFI)
sudo grub2-mkconfig -o /boot/grub2/grub.cfg
查看是否成功导出符号
cat /proc/kallsyms | grep LuChao
[root@localhost linux]# cat /proc/kallsyms | grep LuChao
ffffffffa50bcb40 T LuChao_getfilesystems
ffffffffa5f5ebc8 r __ksymtab_LuChao_getfilesystems
ffffffffa5f852ab r __kstrtab_LuChao_getfilesystems
最后就是编写一个模块来得到fs instance的super block对象. 以nova file system为例.
懒得弄头文件包含路径,直接将super_block的定义拷贝过来用.
super.h
#ifndef __SUPER_H__
#define __SUPER_H__
/*
* * NOVA super-block data in DRAM
* */
struct nova_sb_info {
struct super_block *sb; /* VFS super block */
struct nova_super_block *nova_sb; /* DRAM copy of SB */
struct block_device *s_bdev;
struct dax_device *s_dax_dev;
/*
* * base physical and virtual address of NOVA (which is also
* * the pointer to the super block)
* */
phys_addr_t phys_addr;
void *virt_addr;
void *replica_reserved_inodes_addr;
void *replica_sb_addr;
unsigned long num_blocks;
/* TODO: Remove this, since it's unused */
/*
* * Backing store option:
* * 1 = no load, 2 = no store,
* * else do both
* */
unsigned int nova_backing_option;
/* Mount options */
unsigned long bpi;
unsigned long blocksize;
unsigned long initsize;
unsigned long s_mount_opt;
kuid_t uid; /* Mount uid for root directory */
kgid_t gid; /* Mount gid for root directory */
umode_t mode; /* Mount mode for root directory */
atomic_t next_generation;
/* inode tracking */
unsigned long s_inodes_used_count;
unsigned long head_reserved_blocks;
unsigned long tail_reserved_blocks;
struct mutex s_lock; /* protects the SB's buffer-head */
int cpus;
struct proc_dir_entry *s_proc;
/* Snapshot related */
struct nova_inode_info *snapshot_si;
struct radix_tree_root snapshot_info_tree;
int num_snapshots;
/* Current epoch. volatile guarantees visibility */
volatile u64 s_epoch_id;
volatile int snapshot_taking;
int mount_snapshot;
u64 mount_snapshot_epoch_id;
struct task_struct *snapshot_cleaner_thread;
wait_queue_head_t snapshot_cleaner_wait;
wait_queue_head_t snapshot_mmap_wait;
void *curr_clean_snapshot_info;
/* DAX-mmap snapshot structures */
struct mutex vma_mutex;
struct list_head mmap_sih_list;
/* ZEROED page for cache page initialized */
void *zeroed_page;
/* Checksum and parity for zero block */
u32 zero_csum[8];
void *zero_parity;
/* Per-CPU journal lock */
spinlock_t *journal_locks;
/* Per-CPU inode map */
struct inode_map *inode_maps;
/* Decide new inode map id */
unsigned long map_id;
/* Per-CPU free block list */
struct free_list *free_lists;
unsigned long per_list_blocks;
};
struct nova_super_block {
/* static fields. they never change after file system creation.
* * checksum only validates up to s_start_dynamic field below
* */
__le32 s_sum; /* checksum of this sb */
__le32 s_magic; /* magic signature */
__le32 s_padding32;
__le32 s_blocksize; /* blocksize in bytes */
__le64 s_size; /* total size of fs in bytes */
char s_volume_name[16]; /* volume name */
/* all the dynamic fields should go here */
__le64 s_epoch_id; /* Epoch ID */
/* s_mtime and s_wtime should be together and their order should not be
* * changed. we use an 8 byte write to update both of them atomically
* */
__le32 s_mtime; /* mount time */
__le32 s_wtime; /* write time */
/* Metadata and data protections */
u8 s_padding8;
u8 s_metadata_csum;
u8 s_data_csum;
u8 s_data_parity;
} __attribute((__packed__));
#endif
模块中实现的代码部分: 比如拿到nova fs的超级块实际所在的kernel space的起始地址.
struct file_system_type *cur = LuChao_getfilesystems();
struct nova_sb_info *sbi;
while (cur) {
const char *name = cur->name;
const char *module_name = cur->owner->name;
if (!strncmp(name, NOVASTR, sizeof(NOVASTR)))
{
pr_info(DBG "[fs_name = %s\tfs'module_name = %s\tfs_description = %s]", name, module_name, cur->parameters->name);
// traverse hlist of instance
struct hlist_node *pinstances = cur->fs_supers.first;
// get fs instance's super block
struct super_block *sb = container_of(pinstances, struct super_block, s_instances);
// get fs instance's implement super block
sbi = (struct nova_sb_info *)sb->s_fs_info;
break;
}
cur = cur->next;
}
// testing sbi
pr_info("nvmm phys_addr = %llx", (unsigned long long)sbi->phys_addr);
struct nova_super_block *nova_sb = sbi->nova_sb;
//pr_info("nova_sb. s_mtime = %lu, nova_sb.s_wtime = %lu", nova_sb->s_mtime, nova_sb->s_wtime);