当前仓库属于关闭状态,部分功能使用受限,详情请查阅 仓库状态说明
7 Star 7 Fork 8

openEuler/eulerfs
关闭

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
super.c 18.58 KB
一键复制 编辑 原始数据 按行查看 历史
Yu Kuai 提交于 2021-11-30 16:31 . eulerfs: initial import
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2021. Huawei Technologies Co., Ltd. All rights reserved.
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/module.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/parser.h>
#include <linux/vfs.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include <linux/seq_file.h>
#include <linux/mount.h>
#include <linux/mm.h>
#include <linux/ctype.h>
#include <linux/bitops.h>
#include <linux/magic.h>
#include <linux/exportfs.h>
#include <linux/random.h>
#include <linux/cred.h>
#include <linux/backing-dev.h>
#include <linux/list.h>
#include <linux/pfn_t.h>
#include <linux/dax.h>
#include <linux/genhd.h>
#include <linux/cdev.h>
#include <uapi/linux/mount.h>
#include "euler.h"
#include "dht.h"
#include "dep.h"
#include "nvalloc.h"
#include "wear.h"
int support_clwb;
int support_clflushopt;
int support_clflush;
int force_nocache_write;
int persist_period = -4;
int persisters_per_socket = 1;
int max_dirty_inodes = 1000000;
int max_dep_nodes = 1000000;
int wear_control;
int wear_threshold = 100000;
int wear_alloc_threshold = 10000;
module_param(persisters_per_socket, int, 0444);
MODULE_PARM_DESC(persisters_per_socket, "Num of Persisters per socket");
module_param(force_nocache_write, int, 0444);
MODULE_PARM_DESC(force_nocache_write, "Force to use nocache data write");
module_param(persist_period, int, 0444);
MODULE_PARM_DESC(persist_period, "Period to wake persisters up");
module_param(max_dirty_inodes, int, 0444);
MODULE_PARM_DESC(max_dirty_inodes,
"Limit the max number of dirty inodes allowed");
module_param(max_dep_nodes, int, 0444);
MODULE_PARM_DESC(max_dep_nodes, "Limit the max number of dep nodes allowed");
module_param(wear_control, int, 0444);
MODULE_PARM_DESC(wear_control, "Control wear leveling");
module_param(wear_threshold, int, 0444);
MODULE_PARM_DESC(wear_threshold, "Wear leveling threshold");
module_param(wear_alloc_threshold, int, 0444);
MODULE_PARM_DESC(wear_alloc_threshold,
"Wear leveling threshold for allocation");
int num_sockets;
static struct super_operations eufs_sops;
void eufs_error_mng(struct super_block *sb, const char *fmt, ...)
{
va_list args;
eufs_info("euler error: ");
va_start(args, fmt);
vprintk(fmt, args);
va_end(args);
pr_crit("euler err: remounting filesystem read-only");
sb->s_flags |= MS_RDONLY;
}
static void eufs_show_params(void)
{
eufs_info("params: force_nocache_write=%d\n", force_nocache_write);
eufs_info("params: persist_period=%d\n", persist_period);
eufs_info("params: persisters_per_socket=%d\n", persisters_per_socket);
}
static void eufs_detect_features(void)
{
support_clwb = support_clflushopt = support_clflush = 0;
if (arch_has_clwb()) {
eufs_info("arch has CLWB support\n");
support_clwb = 1;
}
if (arch_has_clflushopt()) {
eufs_info("arch has CLFLUSHOPT support\n");
support_clflushopt = 1;
}
if (arch_has_clflush()) {
eufs_info("arch has CLFLUSH support\n");
support_clflush = 1;
}
if (!support_clwb && !support_clflushopt && !support_clflush)
eufs_info("arch has no cache flush support\n");
}
static int eufs_get_block_info(struct super_block *sb, struct eufs_sb_info *sbi)
{
void *virt_addr = NULL;
pfn_t pfn;
long size;
struct dax_device *dax_dev;
int srcu_id;
if (!bdev_dax_supported(sb->s_bdev, PAGE_SIZE)) {
eufs_err(sb, "device does not support DAX\n");
return -EINVAL;
}
dax_dev = dax_get_by_host(sb->s_bdev->bd_disk->disk_name);
if (!dax_dev) {
eufs_err(sb, "device does not support DAX\n");
return -EINVAL;
}
srcu_id = dax_read_lock();
size = dax_direct_access(
dax_dev, 0, i_size_read(sb->s_bdev->bd_inode) >> PAGE_SHIFT,
&virt_addr, &pfn);
dax_read_unlock(srcu_id);
if (size < 0) {
fs_put_dax(dax_dev);
eufs_err(sb, "device DAX error %ld\n", size);
return size;
}
sbi->s_dax_dev = dax_dev;
sbi->s_bdev = sb->s_bdev;
sbi->virt_addr = virt_addr;
sbi->phys_addr = pfn_t_to_pfn(pfn) << PAGE_SHIFT;
sbi->initsize = (u64)size << PAGE_SHIFT;
eufs_info("dev %s virt_addr %px phys_addr %llx size %ld\n",
sb->s_bdev->bd_disk->disk_name, sbi->virt_addr,
sbi->phys_addr, sbi->initsize);
return 0;
}
enum {
Opt_init,
Opt_dax,
Opt_err
};
static const match_table_t tokens = {
{ Opt_init, "init" },
{ Opt_dax, "dax" }, /* DAX is always on. This is for compatibility. */
{ Opt_err, NULL },
};
static int eufs_parse_options(char *options, struct eufs_sb_info *sbi,
bool remount)
{
char *p;
substring_t args[MAX_OPT_ARGS];
if (!options)
return 0;
while ((p = strsep(&options, ",")) != NULL) {
int token;
if (!*p)
continue;
token = match_token(p, tokens, args);
switch (token) {
case Opt_init:
if (remount)
goto bad_opt;
set_opt(sbi->s_mount_opt, FORMAT);
break;
case Opt_dax:
break;
default:
goto bad_opt;
}
}
return 0;
bad_opt:
eufs_info("Bad mount option: \"%s\"\n", p);
return -EINVAL;
}
static bool eufs_check_size(struct super_block *sb, unsigned long size)
{
unsigned long minimum_size;
/* For Super Block */
minimum_size = 2 << sb->s_blocksize_bits;
/* For Bitmaps */
minimum_size += size / EUFS_BLOCK_SIZE / 8;
if (size < minimum_size)
return false;
return true;
}
static __always_inline int eufs_check_super(struct eufs_super_block *ps,
const char *typ)
{
u16 save_crc = 0;
u16 calc_crc = 0;
struct eufs_super_block scratch;
memcpy(&scratch, ps, sizeof(*ps));
save_crc = scratch.s_sum;
scratch.s_sum = 0;
scratch.s_safe_umount = 0;
calc_crc = crc16(~0, (__u8 *)&scratch, sizeof(scratch));
if (save_crc != calc_crc) {
eufs_warn("Recognizing %s super block failed: crc %x mismatch (%x expected)",
typ, calc_crc, save_crc);
return -EIO;
}
if (scratch.s_magic != EUFS_SUPER_MAGIC) {
eufs_warn("Recognizing %s super block failed: magic %x mismatch (%x expected)",
typ, scratch.s_magic, EUFS_SUPER_MAGIC);
return -EIO;
}
return 0;
}
static __always_inline int eufs_recognize_fs(struct super_block *sb)
{
struct eufs_super_block *super;
struct eufs_super_block *super2;
int err;
super = eufs_get_super(sb);
super2 = (void *)super + EUFS_SB2_OFFSET;
err = eufs_check_super(super, "primary");
if (err) {
err = eufs_check_super(super2, "secondary");
if (err)
return -EIO;
eufs_info("Secondary super block recognized, syncing back to the primary.\n");
memcpy(super, super2, sizeof(struct eufs_super_block));
eufs_flush_buffer(super2, sizeof(*super2), false);
eufs_pbarrier();
}
return 0;
}
static __always_inline void eufs_sync_super(struct eufs_super_block *ps)
{
u16 crc = 0;
__le32 saved_safe_umount = ps->s_safe_umount;
ps->s_safe_umount = 0;
ps->s_wtime = cpu_to_le32(get_seconds());
ps->s_sum = 0;
crc = crc16(~0, (__u8 *)ps, sizeof(struct eufs_super_block));
ps->s_sum = cpu_to_le16(crc);
eufs_flush_buffer(ps, sizeof(*ps), false);
eufs_pbarrier();
/* Keep sync redundant super block */
memcpy((void *)ps + EUFS_SB2_OFFSET, (void *)ps,
sizeof(struct eufs_super_block));
eufs_flush_buffer((void *)ps + EUFS_SB2_OFFSET, sizeof(*ps), false);
eufs_pbarrier();
ps->s_safe_umount = saved_safe_umount;
}
static struct eufs_inode *eufs_init(struct super_block *sb, unsigned long size)
{
struct eufs_inode __pmem *root_i;
struct eufs_super_block __pmem *super;
struct eufs_sb_info *sbi = EUFS_SB(sb);
struct nv_dict *dict;
eufs_info("creating an empty eulerfs of size %lu\n", size);
sbi->block_start = 0;
sbi->block_end = ((unsigned long)(size) >> PAGE_SHIFT);
if (!sbi->virt_addr) {
eufs_err(sb, "mapping eulerfs image failed\n");
return ERR_PTR(-EINVAL);
}
sb->s_blocksize_bits = EUFS_BLOCK_SIZE_BITS;
sbi->blocksize = EUFS_BLOCK_SIZE;
if (!eufs_check_size(sb, size)) {
eufs_err(sb, "Specified size too small 0x%lx for EulerFS\n",
size);
return ERR_PTR(-EINVAL);
}
super = eufs_get_super(sb);
super->s_sum = 0;
super->s_magic = cpu_to_le16(EUFS_SUPER_MAGIC);
super->s_safe_umount = 0;
super->s_flag = 0;
super->s_fs_version = cpu_to_le16(1);
super->s_size = cpu_to_le64(size);
super->s_virt_addr = cpu_to_le64(sbi->virt_addr);
sbi->s_crash_ver = 1;
super->s_crash_ver = cpu_to_le64(1);
nv_init(sb, true);
super->s_page_map = cpu_to_le64(p2o(sb, sbi->page_map));
super->s_mtime = 0;
root_i = eufs_malloc_pinode(sb);
if (!root_i)
return ERR_PTR(-ENOSPC);
eufs_info("root_i: %px\n", root_i);
eufs_alloc_persist(sb, root_i, false);
super->s_root_pi = p2s(sb, root_i);
eufs_sync_super(super);
/* ================ init root dir =============== */
eufs_iwrite_flags(root_i, 0);
eufs_iwrite_mode(root_i, S_IRUGO | S_IXUGO | S_IWUSR | S_IFDIR);
eufs_iwrite_version(root_i, 1);
eufs_iwrite_ctime(root_i, get_seconds());
eufs_iwrite_ctime_nsec(root_i, 0);
eufs_iwrite_uid(root_i, from_kuid(&init_user_ns, current_fsuid()));
eufs_iwrite_gid(root_i, from_kgid(&init_user_ns, current_fsgid()));
eufs_iwrite_dotdot(root_i, p2o(sb, root_i));
eufs_iwrite_ext(root_i, 0); /* no ext here */
eufs_iwrite_generation(root_i, 0);
eufs_iwrite_nlink(root_i, 2);
eufs_iwrite_mtime(root_i, get_seconds());
eufs_iwrite_atime(root_i, get_seconds());
eufs_iwrite_mtime_nsec(root_i, 0);
eufs_iwrite_atime_nsec(root_i, 0);
dict = eufs_zalloc_htable(sb);
if (!dict)
return ERR_PTR(-ENOSPC);
eufs_alloc_persist(sb, dict, false);
eufs_flush_range(dict, sizeof(struct nv_dict));
eufs_iwrite_dict(root_i, p2o(sb, dict));
eufs_iwrite_size(root_i, 0);
root_i->i_fresh = 2;
eufs_flush_cacheline(root_i);
eufs_flush_cacheline(&root_i->i_fresh);
EUFS_TWIN_PI(root_i)->i_fresh = 1;
eufs_flush_cacheline(&EUFS_TWIN_PI(root_i)->i_fresh);
eufs_pbarrier();
return root_i;
}
static void eufs_destroy_super(struct super_block *sb)
{
struct eufs_sb_info *sbi = EUFS_SB(sb);
wear_fini(sb);
dep_fini(sb);
nv_fini(sb);
if (sbi->virt_addr)
sbi->virt_addr = NULL;
if (sbi->s_dax_dev)
fs_put_dax(sbi->s_dax_dev);
sb->s_fs_info = NULL;
kfree(sbi);
}
static int eufs_fill_super(struct super_block *sb, void *data, int silent)
{
struct eufs_super_block __pmem *super;
struct eufs_inode __pmem *root_pi;
struct eufs_sb_info *sbi = NULL;
struct inode *root_i = NULL;
u32 random = 0;
int err;
BUILD_BUG_ON(sizeof(struct eufs_super_block) > EUFS_SB_SIZE);
BUILD_BUG_ON(sizeof(struct eufs_inode) != 2 * CACHELINE_SIZE);
BUILD_BUG_ON(sizeof(struct nv_dict_entry) != CACHELINE_SIZE);
eufs_detect_features();
sbi = kzalloc(sizeof(struct eufs_sb_info), GFP_KERNEL);
if (!sbi)
return -ENOMEM;
sbi->s_draining = false;
init_waitqueue_head(&sbi->s_draining_wq);
atomic_set(&sbi->s_nr_dirty_inodes, 0);
atomic_set(&sbi->s_nr_dep_nodes, 0);
sb->s_fs_info = sbi;
err = eufs_get_block_info(sb, sbi);
if (err)
goto out;
get_random_bytes(&random, sizeof(u32));
atomic_set(&sbi->next_generation, random);
mutex_init(&sbi->s_lock);
mutex_init(&sbi->gather_mutex);
mutex_init(&sbi->sync_mutex);
err = eufs_parse_options(data, sbi, 0);
if (err)
goto out;
super = eufs_get_super(sb);
/* Init a new EulerFS instance */
if (test_opt(sb, FORMAT)) {
root_pi = eufs_init(sb, sbi->initsize);
if (IS_ERR(root_pi)) {
err = PTR_ERR(root_pi);
goto out;
}
goto setup_sb;
}
err = eufs_recognize_fs(sb);
if (err) {
eufs_crit("No valid EulerFS found. Are you trying to mount a wrong fs?\n");
goto out;
}
sbi->block_start = 0;
sbi->block_end = ((unsigned long)(super->s_size) >> PAGE_SHIFT);
sb->s_blocksize_bits = EUFS_BLOCK_SIZE_BITS;
sbi->blocksize = EUFS_BLOCK_SIZE;
sbi->page_map = (void *)o2p(sb, super->s_page_map);
sbi->initsize = (u64)super->s_size;
eufs_get_layout(sb, false);
sbi->s_crash_ver = le64_to_cpu(super->s_crash_ver);
if (!super->s_safe_umount) {
super->s_crash_ver = cpu_to_le64(++sbi->s_crash_ver);
eufs_flush_cacheline(&super->s_crash_ver);
eufs_pbarrier();
}
nv_init(sb, false);
root_pi = (struct eufs_inode *)s2p(sb, super->s_root_pi);
setup_sb:
super->s_safe_umount = 0;
eufs_flush_cacheline(&super->s_safe_umount);
eufs_pbarrier();
sbi->s_crash_ver = le64_to_cpu(super->s_crash_ver);
sb->s_magic = le16_to_cpu(super->s_magic);
sb->s_op = &eufs_sops;
sb->s_maxbytes = EUFS_MAX_FILE_SIZE;
sb->s_time_gran = NSEC_PER_SEC;
err = dep_init(sb);
if (err)
goto out;
wear_init(sb);
root_i = eufs_iget(sb, root_pi);
if (IS_ERR(root_i)) {
err = PTR_ERR(root_i);
goto out;
}
sb->s_root = d_make_root(root_i);
if (!sb->s_root) {
eufs_err(sb, "alloc root dentry failed\n");
err = -ENOMEM;
goto out;
}
if (!(sb->s_flags & MS_RDONLY)) {
u64 mnt_write_time;
/* update mount time and write time atomically. */
mnt_write_time = (get_seconds() & 0xFFFFFFFF);
mnt_write_time = mnt_write_time | (mnt_write_time << 32);
super->s_mtime = mnt_write_time;
eufs_flush_buffer(&super->s_mtime, 8, false);
eufs_pbarrier();
}
return 0;
out:
eufs_destroy_super(sb);
return err;
}
static int eufs_statfs(struct dentry *d, struct kstatfs *buf)
{
struct super_block *sb = d->d_sb;
struct eufs_sb_info *sbi = (struct eufs_sb_info *)sb->s_fs_info;
u64 npage, ncl;
nv_stat(sbi, &npage, &ncl);
buf->f_type = EUFS_SUPER_MAGIC;
buf->f_bsize = PAGE_SIZE;
buf->f_blocks = sbi->block_end;
buf->f_bfree = npage;
buf->f_bavail = npage;
buf->f_files = ncl;
buf->f_ffree = ncl;
buf->f_namelen = EUFS_MAX_NAME_LEN;
print_stats(sbi);
return 0;
}
static int eufs_show_options(struct seq_file *seq, struct dentry *root)
{
seq_puts(seq, ",dax");
return 0;
}
static int eufs_remount(struct super_block *sb, int *mntflags, char *data)
{
unsigned long old_sb_flags;
unsigned long old_mount_opt;
struct eufs_super_block *ps;
struct eufs_sb_info *sbi = EUFS_SB(sb);
int ret = -EINVAL;
/* Store the old options */
mutex_lock(&sbi->s_lock);
old_sb_flags = sb->s_flags;
old_mount_opt = sbi->s_mount_opt;
if (eufs_parse_options(data, sbi, 1))
goto restore_opt;
if ((*mntflags & MS_RDONLY) != (sb->s_flags & MS_RDONLY)) {
u64 mnt_write_time;
ps = eufs_get_super(sb);
/* update mount time and write time atomically. */
mnt_write_time = (get_seconds() & 0xFFFFFFFF);
mnt_write_time = mnt_write_time | (mnt_write_time << 32);
ps->s_mtime = mnt_write_time;
eufs_flush_buffer(&ps->s_mtime, 8, false);
eufs_pbarrier();
}
mutex_unlock(&sbi->s_lock);
ret = 0;
return ret;
restore_opt:
sb->s_flags = old_sb_flags;
sbi->s_mount_opt = old_mount_opt;
mutex_unlock(&sbi->s_lock);
return ret;
}
static void eufs_put_super(struct super_block *sb)
{
struct eufs_super_block *super;
super = eufs_get_super(sb);
eufs_sync_super(super);
super->s_safe_umount = 1;
eufs_flush_cacheline(&super->s_safe_umount);
eufs_pbarrier();
eufs_info("safe unmount.\n");
eufs_destroy_super(sb);
}
static struct inode *eufs_alloc_inode(struct super_block *sb)
{
struct eufs_inode_info *vi;
vi = eufs_alloc_vi();
if (!vi)
return NULL;
INIT_LIST_HEAD(&vi->i_dep_list);
vi->i_next_dep_seq = 1;
vi->i_persisted_dep_seq = 0;
spin_lock_init(&vi->i_owner_lock);
INIT_LIST_HEAD(&vi->i_owner_list);
vi->i_lock_transferred = I_TRANS_NONE;
vi->i_is_persisting = false;
vi->i_is_dirty = false;
vi->i_volatile_root = NULL;
vi->i_volatile_height = 0;
vi->i_dotdot = 0;
atomic64_set(&vi->vfs_inode.i_version, 1);
vi->page_batch.size = 0;
vi->page_batch.n_used = -1;
vi->page_batch.batch = NULL;
INIT_LIST_HEAD(&vi->page_batch.list);
vi->i_volatile_dict = NULL;
mutex_init(&vi->i_urgent_mutex);
mutex_init(&vi->i_dep_lock);
mutex_init(&vi->i_header_lock);
init_rwsem(&vi->mmap_rwsem);
spin_lock_init(&vi->i_dentry_persist_lock);
mutex_init(&vi->i_leaf_lock);
return &vi->vfs_inode;
}
static void eufs_i_callback(struct rcu_head *head)
{
struct inode *inode = container_of(head, struct inode, i_rcu);
eufs_alloc_batch_fini(&EUFS_I(inode)->page_batch);
eufs_free_vi(EUFS_I(inode));
}
static void eufs_destroy_inode(struct inode *inode)
{
if (EUFS_I(inode)->i_volatile_dict) {
eufs_free_page(EUFS_I(inode)->i_volatile_dict);
EUFS_I(inode)->i_volatile_dict = NULL;
}
call_rcu(&inode->i_rcu, eufs_i_callback);
}
static int eufs_sync_fs(struct super_block *sb, int sync)
{
struct eufs_sb_info *sbi = EUFS_SB(sb);
int i;
int num_persisters = num_sockets * persisters_per_socket;
int wait_flag;
if (!sync)
return 0;
mutex_lock(&sbi->sync_mutex);
for (i = 0; i < num_persisters; i++)
sbi->need_sync[i] = true;
/* FIXME: Persisters may miss the wake-up message. */
for (i = 0; i < num_persisters; ++i)
wake_up_process(sbi->persisters[i]);
do {
wait_flag = false;
for (i = 0; i < num_persisters; i++) {
if (sbi->need_sync[i] == false)
continue;
wait_flag = true;
wait_event_interruptible(sbi->sync_wq,
(sbi->need_sync[i] == false));
}
} while (wait_flag);
mutex_unlock(&sbi->sync_mutex);
return 0;
}
/*
* the super block writes are all done "on the fly", so the
* super block is never in a "dirty" state, so there's no need
* for write_super.
*/
static struct super_operations eufs_sops = {
.alloc_inode = eufs_alloc_inode,
.destroy_inode = eufs_destroy_inode,
.write_inode = eufs_write_inode,
.evict_inode = eufs_evict_inode,
.put_super = eufs_put_super,
.statfs = eufs_statfs,
.remount_fs = eufs_remount,
.show_options = eufs_show_options,
.sync_fs = eufs_sync_fs,
};
static struct dentry *eufs_mount(struct file_system_type *fs_type, int flags,
const char *dev_name, void *data)
{
return mount_bdev(fs_type, flags, dev_name, data, eufs_fill_super);
}
static struct file_system_type eufs_fs_type = {
.owner = THIS_MODULE,
.name = "eulerfs",
.mount = eufs_mount,
.kill_sb = kill_block_super,
};
static int __init init_eufs_fs(void)
{
int rc = 0;
int cpu;
BUILD_BUG_ON(sizeof(struct eufs_renamej) != 2 * CACHELINE_SIZE);
rc = init_page_cache();
if (rc)
goto out1;
rc = init_inodecache();
if (rc)
goto out2;
rc = init_dep_node_cache();
if (rc)
goto out3;
rc = register_filesystem(&eufs_fs_type);
if (rc)
goto out4;
num_sockets = 0;
for_each_possible_cpu(cpu) {
int sock = cpu_to_node(cpu);
if (sock > num_sockets)
num_sockets = sock;
}
num_sockets += 1;
eufs_info("Num socket: %d\n", num_sockets);
eufs_show_params();
return 0;
out4:
destroy_dep_node_cache();
out3:
destroy_inodecache();
out2:
destroy_page_cache();
out1:
return rc;
}
static void __exit exit_eufs_fs(void)
{
unregister_filesystem(&eufs_fs_type);
destroy_inodecache();
destroy_dep_node_cache();
destroy_page_cache();
}
module_init(init_eufs_fs);
module_exit(exit_eufs_fs);
MODULE_DESCRIPTION("EulerFS");
MODULE_LICENSE("GPL");
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/openeuler/eulerfs.git
git@gitee.com:openeuler/eulerfs.git
openeuler
eulerfs
eulerfs
master

搜索帮助