From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.4 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,NICE_REPLY_A, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,UNPARSEABLE_RELAY,USER_AGENT_SANE_1 autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 11584C55179 for ; Tue, 27 Oct 2020 09:16:31 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 9E69E2225C for ; Tue, 27 Oct 2020 09:16:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2443825AbgJ0JQ0 (ORCPT ); Tue, 27 Oct 2020 05:16:26 -0400 Received: from out30-45.freemail.mail.aliyun.com ([115.124.30.45]:37808 "EHLO out30-45.freemail.mail.aliyun.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2441288AbgJ0JQZ (ORCPT ); Tue, 27 Oct 2020 05:16:25 -0400 X-Alimail-AntiSpam: AC=PASS;BC=-1|-1;BR=01201311R721e4;CH=green;DM=||false|;DS=||;FP=0|-1|-1|-1|0|-1|-1|-1;HT=e01e01424;MF=zoucao@linux.alibaba.com;NM=1;PH=DS;RN=3;SR=0;TI=SMTPD_---0UDLxwF3_1603790175; Received: from ali-6c96cfe06eab.local(mailfrom:zoucao@linux.alibaba.com fp:SMTPD_---0UDLxwF3_1603790175) by smtp.aliyun-inc.com(127.0.0.1); Tue, 27 Oct 2020 17:16:16 +0800 Subject: Re: [PATCH 1/2] fs:regfs: add register easy filesystem To: viro@zeniv.linux.org.uk Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org References: <1603175408-96164-1-git-send-email-zoucao@linux.alibaba.com> <00513aa5-1cc5-bc1c-1ca7-d5cd6e3f1ed6@linux.alibaba.com> From: zc Message-ID: <17f16578-170c-82ab-0054-4ff10e5c6595@linux.alibaba.com> Date: Tue, 27 Oct 2020 17:16:15 +0800 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:68.0) Gecko/20100101 Thunderbird/68.10.0 MIME-Version: 1.0 In-Reply-To: <00513aa5-1cc5-bc1c-1ca7-d5cd6e3f1ed6@linux.alibaba.com> Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org pending ? 在 2020/10/23 上午10:57, zc 写道: > Hi viro: > >   Through regfs is very sample and easy,  but i think it is a Interest > ,  could give  some suggestions? > > > Regards, > > zc > > 在 2020/10/20 下午2:30, Zou Cao 写道: >> register filesystem is mapping the register into file dentry, it >> will use the io readio to get the register val. DBT file is use >> to decript the register tree, you can use it as follow: >> >>     mount -t regfs -o dtb=test.dtb none /mnt >> >>     test.dts: >>     / { >> >>     compatible = "hisilicon,hi6220-hikey", "hisilicon,hi6220"; >>     #address-cells = <0x2>; >>     #size-cells = <0x2>; >>     model = "HiKey Development Board"; >> >>     gic-v3-dist{ >>         reg = <0x0 0x8000000 0x0 0x10000>; >>         GIC_CTRL { >>             offset = <0x0>; >>         }; >>         GICD_TYPER { >>             offset = <0x4>; >>         }; >>        }; >>     }; >> >> it will create all regiter dentry file in /mnt >> >> Signed-off-by: Zou Cao >> --- >>   fs/Kconfig             |   1 + >>   fs/Makefile            |   1 + >>   fs/regfs/Kconfig       |   7 + >>   fs/regfs/Makefile      |   8 ++ >>   fs/regfs/file.c        | 107 +++++++++++++++ >>   fs/regfs/inode.c       | 354 >> +++++++++++++++++++++++++++++++++++++++++++++++++ >>   fs/regfs/internal.h    |  32 +++++ >>   fs/regfs/regfs_inode.h |  32 +++++ >>   fs/regfs/supper.c      |  71 ++++++++++ >>   9 files changed, 613 insertions(+) >>   create mode 100644 fs/regfs/Kconfig >>   create mode 100644 fs/regfs/Makefile >>   create mode 100644 fs/regfs/file.c >>   create mode 100644 fs/regfs/inode.c >>   create mode 100644 fs/regfs/internal.h >>   create mode 100644 fs/regfs/regfs_inode.h >>   create mode 100644 fs/regfs/supper.c >> >> diff --git a/fs/Kconfig b/fs/Kconfig >> index a88aa3a..d95acaf 100644 >> --- a/fs/Kconfig >> +++ b/fs/Kconfig >> @@ -324,6 +324,7 @@ endif # NETWORK_FILESYSTEMS >>   source "fs/nls/Kconfig" >>   source "fs/dlm/Kconfig" >>   source "fs/unicode/Kconfig" >> +source "fs/regfs/Kconfig" >>     config IO_WQ >>       bool >> diff --git a/fs/Makefile b/fs/Makefile >> index 2ce5112..24f3878 100644 >> --- a/fs/Makefile >> +++ b/fs/Makefile >> @@ -136,3 +136,4 @@ obj-$(CONFIG_EFIVAR_FS)        += efivarfs/ >>   obj-$(CONFIG_EROFS_FS)        += erofs/ >>   obj-$(CONFIG_VBOXSF_FS)        += vboxsf/ >>   obj-$(CONFIG_ZONEFS_FS)        += zonefs/ >> +obj-$(CONFIG_REGFS_FS)        += zonefs/ >> diff --git a/fs/regfs/Kconfig b/fs/regfs/Kconfig >> new file mode 100644 >> index 0000000..74ba85b >> --- /dev/null >> +++ b/fs/regfs/Kconfig >> @@ -0,0 +1,7 @@ >> +config REGFS_FS >> +    tristate "registers filesystem support" >> +    depends on ARM64 >> +    help >> +      regfs support the read and write register of device resource by >> +      dentry filesystem, it is more easy to support bsp debug. it also >> +      support to printk the register val when panic >> diff --git a/fs/regfs/Makefile b/fs/regfs/Makefile >> new file mode 100644 >> index 0000000..26d5eef >> --- /dev/null >> +++ b/fs/regfs/Makefile >> @@ -0,0 +1,8 @@ >> +# SPDX-License-Identifier: GPL-2.0-only >> +# >> +#Makefile for the linux ramfs routines. >> +# >> + >> +obj-y += regfs.o >> + >> +regfs-objs += inode.o file.o supper.o >> diff --git a/fs/regfs/file.c b/fs/regfs/file.c >> new file mode 100644 >> index 0000000..6cd9f3d >> --- /dev/null >> +++ b/fs/regfs/file.c >> @@ -0,0 +1,107 @@ >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> + >> +#include "regfs_inode.h" >> +#include "internal.h" >> + >> +ssize_t regfs_file_write_iter(struct kiocb *iocb, struct iov_iter >> *from) >> +{ >> +    struct file *file = iocb->ki_filp; >> +    struct inode *inode = file->f_mapping->host; >> +    ssize_t ret; >> + >> +    inode_lock(inode); >> +    ret = generic_write_checks(iocb, from); >> +    if (ret > 0) >> +        ret = __generic_file_write_iter(iocb, from); >> +    inode_unlock(inode); >> + >> +    if (ret > 0) >> +        ret = generic_write_sync(iocb, ret); >> +    return ret; >> +} >> + >> +static ssize_t regfs_file_read(struct file *file, char __user *buf, >> size_t len, loff_t *ppos) >> +{ >> +    struct address_space *mapping = file->f_mapping; >> +    struct regfs_inode_info  *info = REGFS_I(mapping->host); >> +    char str[64]; >> +    unsigned long val; >> + >> +    val = readl_relaxed(info->base + info->offset); >> + >> +    loc_debug("name:%s base:%p val:%lx\n" >> +            , file->f_path.dentry->d_iname >> +            , info->base + info->offset >> +            , val); >> + >> +    snprintf(str, 64, "%lx", val); >> + >> +    return simple_read_from_buffer(buf, len, ppos, str, strlen(str)); >> +} >> + >> +static ssize_t regfs_file_write(struct file *file, const char __user >> *buf, size_t len, loff_t *ppos) >> +{ >> +    struct address_space *mapping = file->f_mapping; >> +    struct regfs_inode_info  *info = REGFS_I(mapping->host); >> +    char str[67]; >> +    unsigned long val = 0; >> +    loff_t pos = *ppos; >> +    size_t res; >> + >> +    if (pos < 0) >> +        return -EINVAL; >> +    if (pos >= len || len > 66) >> +        return 0; >> + >> +    res = copy_from_user(str, buf, len); >> +    if (res) >> +        return -EFAULT; >> +    str[len] = 0; >> + >> +    if (kstrtoul(str, 16, &val) < 0) >> +        return -EINVAL; >> + >> +    writel_relaxed(val, info->base + info->offset); >> + >> +    loc_debug("name:%s base:%p val:%lx\n" >> +            , file->f_path.dentry->d_iname >> +            , info->base + info->offset >> +            , val); >> + >> +    return len; >> +} >> + >> +const struct file_operations regfs_file_operations = { >> +    .read = regfs_file_read, >> +    .write = regfs_file_write, >> +}; >> + >> +const struct inode_operations regfs_file_inode_operations = { >> +    .setattr    = simple_setattr, >> +    .getattr    = simple_getattr, >> +}; >> + >> +const struct address_space_operations regfs_aops = { >> +    .readpage   = simple_readpage, >> +    .write_begin    = simple_write_begin, >> +    .write_end  = simple_write_end, >> +    .set_page_dirty = __set_page_dirty_buffers, >> +}; >> + >> diff --git a/fs/regfs/inode.c b/fs/regfs/inode.c >> new file mode 100644 >> index 0000000..1643fcd >> --- /dev/null >> +++ b/fs/regfs/inode.c >> @@ -0,0 +1,354 @@ >> +/* >> + * Resizable simple ram filesystem for Linux. >> + * >> + * Copyright (C) 2000 Linus Torvalds. >> + *               2000 Transmeta Corp. >> + * >> + * Usage limits added by David Gibson, Linuxcare Australia. >> + * This file is released under the GPL. >> + */ >> + >> +/* >> + * NOTE! This filesystem is probably most useful >> + * not as a real filesystem, but as an example of >> + * how virtual filesystems can be written. >> + * >> + * It doesn't get much simpler than this. Consider >> + * that this file implements the full semantics of >> + * a POSIX-compliant read-write filesystem. >> + * >> + * Note in particular how the filesystem does not >> + * need to implement any data structures of its own >> + * to keep track of the virtual data: using the VFS >> + * caches is sufficient. >> + */ >> + >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include "regfs_inode.h" >> +#include "internal.h" >> + >> +static LIST_HEAD(regfs_head); >> + >> +static const struct inode_operations regfs_dir_inode_operations; >> +int regfs_debug; >> +module_param(regfs_debug, int, S_IRUGO); >> +MODULE_PARM_DESC(regfs_debug, "enable regfs debug mode"); >> + >> +struct inode *regfs_get_inode(struct super_block *sb, const struct >> inode *dir, umode_t mode, dev_t dev) >> +{ >> +    struct inode *inode = new_inode(sb); >> + >> +    if (inode) { >> +        inode->i_ino = get_next_ino(); >> +        inode_init_owner(inode, dir, mode); >> +        inode->i_mapping->a_ops = ®fs_aops; >> +        //inode->i_mapping->backing_dev_info = ®fs_backing_dev_info; >> +        mapping_set_gfp_mask(inode->i_mapping, GFP_HIGHUSER); >> +        mapping_set_unevictable(inode->i_mapping); >> +        inode->i_atime = inode->i_mtime = inode->i_ctime = >> current_time(inode); >> +        switch (mode & S_IFMT) { >> +        default: >> +            init_special_inode(inode, mode, dev); >> +            break; >> +        case S_IFREG: >> +            inode->i_op = ®fs_file_inode_operations; >> +            inode->i_fop = ®fs_file_operations; >> +            break; >> +        case S_IFDIR: >> +            inode->i_op = ®fs_dir_inode_operations; >> +            inode->i_fop = &simple_dir_operations; >> + >> +            /* directory inodes start off with i_nlink == 2 (for "." >> entry) */ >> +            inc_nlink(inode); >> +            break; >> +        case S_IFLNK: >> +            inode->i_op = &page_symlink_inode_operations; >> +            break; >> +        } >> +    } >> + >> +    return inode; >> +} >> + >> +static const struct inode_operations regfs_dir_inode_operations = { >> +    .lookup        = simple_lookup, >> +}; >> + >> +static struct dentry *new_dentry_create(struct super_block *sb, >> struct dentry *parent, >> +         const char *name, bool is_dir, struct res_data *res) >> +{ >> +    struct dentry *dentry; >> +    struct inode *inode; >> +    struct regfs_inode_info *ei; >> +    struct regfs_fs_info *fsi = sb->s_fs_info; >> + >> +    dentry = d_alloc_name(parent, name); >> +    if (!dentry) >> +        return NULL; >> + >> +    inode = new_inode(sb); >> +    if (!inode) >> +        goto out; >> + >> +    ei = REGFS_I(inode); >> +    inode->i_ino = get_next_ino();; >> +    inode->i_mtime = inode->i_atime = inode->i_ctime = >> current_time(inode); >> +    inode->i_uid =  GLOBAL_ROOT_UID; >> +    inode->i_gid =  GLOBAL_ROOT_GID; >> +    if (is_dir) { >> +        inode->i_mode = S_IFDIR | S_IRUGO | S_IWUSR; >> +        inode->i_op = ®fs_dir_inode_operations; >> +        inode->i_fop = &simple_dir_operations; >> +        list_add(&ei->list, &fsi->list); >> +    } else { >> +        inode->i_mode = S_IFREG | S_IRUGO | S_IWUSR; >> +        inode->i_op = ®fs_file_inode_operations; >> +        inode->i_fop = ®fs_file_operations; >> +        inc_nlink(inode); >> +    } >> +    ei->base = (void *)res->base; >> +    ei->offset = res->offset; >> +    ei->type = res->type; >> + >> +    d_add(dentry, inode); >> + >> +    loc_debug("new dentry io base:%llx offset:%llx ei:%llx\n", >> (u64)ei->base, (u64)ei->offset, (u64)ei); >> +    return dentry; >> +out: >> +    dput(dentry); >> +    return NULL; >> +} >> + >> +static void node_transfer_dentry(struct super_block *sb) >> +{ >> +    struct regfs_fs_info *fsi = sb->s_fs_info; >> +    void *blob = fsi->dtb_buf; >> +    const char *pathp; >> +    int node_offset, depth = -1; >> +    struct dentry *parent = NULL; >> +    u64 parent_base; >> + >> +    for (node_offset = fdt_next_node(blob, -1, &depth); >> +        node_offset >= 0 && depth >= 0; >> +        node_offset = fdt_next_node(blob, node_offset, &depth)) { >> + >> +        const struct fdt_property *prop; >> +        struct res_data res; >> + >> +        pathp = fdt_get_name(blob, node_offset, NULL); >> +        prop = (void *)fdt_getprop(blob, node_offset, "reg", NULL); >> + >> +        if (prop) { >> +            unsigned long phys; >> + >> +            phys = fdt32_to_cpu(((const __be32 *)prop)[1]); >> +            res.type = RES_TYPE_RANGE; >> +            res.offset = fdt32_to_cpu(((const __be32 *)prop)[3]); >> +            res.base = (u64)ioremap(phys, res.offset); >> + >> +            if (!res.base) { >> +                parent = NULL; >> +                parent_base = 0; >> +                continue; >> +            } >> + >> +            loc_debug("%s reg:%lx size:%lx map:%llx\n\n", pathp >> +                 , (unsigned long) fdt32_to_cpu(((const __be32 >> *)prop)[1]) >> +                 , (unsigned long) fdt32_to_cpu(((const __be32 >> *)prop)[3]) >> +                 , (u64)res.base); >> + >> +            parent = new_dentry_create(sb, sb->s_root, (const char >> *)pathp, true, &res); >> +            parent_base = res.base; >> + >> +        } else { >> +            // parent dentry is create failed, igonre all child dentry >> +            if (!parent) >> +                continue; >> + >> +            prop = (void *)fdt_getprop(blob, node_offset, "offset", >> NULL); >> +            if (prop) { >> + >> +                res.offset = fdt32_to_cpu(*(const __be32 *)prop); >> +                res.base = parent_base; >> +                res.type = RES_TYPE_ITEM; >> + >> +                new_dentry_create(sb, parent, (const char *) pathp, >> false, &res); >> +                loc_debug("%s offset:%lx\n", pathp, (unsigned >> long)fdt32_to_cpu(*(const __be32 *)prop)); >> +            } >> +        } >> +    } >> +} >> + >> +static int parse_options(char *options, struct super_block *sb) >> +{ >> +    char *p; >> +    int ret = -EINVAL; >> +    struct regfs_fs_info *fsi; >> +    size_t msize = INT_MAX; >> + >> +    fsi = sb->s_fs_info; >> + >> +    if (!options) >> +        return -EINVAL; >> + >> +    while ((p = strsep(&options, ",")) != NULL) { >> +        char *name, *name_val; >> + >> +        name = strsep(&p, "="); >> +        if (name == NULL) >> +            goto failed; >> + >> +        name_val = strsep(&p, "="); >> +        if (name_val == NULL) >> +            goto failed; >> + >> +        //get resource address >> +        if (!strcmp(name, "dtb")) { >> +            ret = kernel_read_file_from_path(name_val, >> &fsi->dtb_buf, &fsi->dtb_len, msize, READING_UNKNOWN); >> +            if (ret) { >> +                pr_err("load %s failed\n", name_val); >> +                goto failed; >> +            } >> +        } else >> +            goto failed; >> +    }; >> + >> +    return 0; >> + >> +failed: >> +    return ret; >> +} >> + >> +int regfs_fill_super(struct super_block *sb, void *data, int silent) >> +{ >> +    struct regfs_fs_info *fsi; >> +    struct inode *inode; >> +    int err; >> + >> +    fsi = kzalloc(sizeof(struct regfs_fs_info), GFP_KERNEL); >> +    if (!fsi) >> +        return -ENOMEM; >> + >> +    sb->s_fs_info = fsi; >> +    fsi->sb = sb; >> + >> +    err = parse_options((char *)data, sb); >> +    if (err) >> +        goto out; >> + >> +    sb->s_maxbytes        = MAX_LFS_FILESIZE; >> +    sb->s_blocksize        = PAGE_SIZE; >> +    sb->s_blocksize_bits    = PAGE_SHIFT; >> +    sb->s_magic        = RAMFS_MAGIC; >> +    sb->s_op        = ®fs_ops; >> +    sb->s_time_gran        = 1; >> + >> +    inode = regfs_get_inode(sb, NULL, S_IFDIR, 0); >> +    sb->s_root = d_make_root(inode); >> +    if (!sb->s_root) >> +        goto out; >> + >> +    INIT_LIST_HEAD(&fsi->list); >> +    INIT_LIST_HEAD(&fsi->regfs_head); >> +    list_add(&fsi->regfs_head, ®fs_head); >> + >> +    return 0; >> + >> +out: >> +    if (fsi) >> +        kfree(fsi); >> + >> +    return err; >> +} >> + >> +struct dentry *regfs_mount(struct file_system_type *fs_type, >> +    int flags, const char *dev_name, void *data) >> +{ >> +    struct dentry *root_dentry; >> +    struct super_block *sb; >> + >> +    root_dentry = mount_nodev(fs_type, flags, data, regfs_fill_super); >> + >> +    sb = root_dentry->d_sb; >> + >> +    if (sb->s_root) { >> +        node_transfer_dentry(sb); >> +    } else >> +        return NULL; >> + >> +    return root_dentry; >> +} >> + >> +static void regfs_kill_sb(struct super_block *sb) >> +{ >> +    struct regfs_fs_info *fsi = sb->s_fs_info; >> +    struct regfs_inode_info *info_res; >> + >> +    list_for_each_entry(info_res,  &fsi->list, list) >> +        iounmap(info_res->base); >> + >> +    if (fsi) { >> +        if (fsi->dtb_buf) >> +            vfree(fsi->dtb_buf); >> +        list_del(&fsi->regfs_head); >> +        kfree(sb->s_fs_info); >> +    } >> +    kill_litter_super(sb); >> +} >> + >> +static struct file_system_type regfs_fs_type = { >> +    .name        = "regfs", >> +    .mount        = regfs_mount, >> +    .kill_sb    = regfs_kill_sb, >> +    .fs_flags    = FS_USERNS_MOUNT, >> +}; >> + >> +static void init_once(void *foo) >> +{ >> +    struct regfs_inode_info *ei = (struct regfs_inode_info *) foo; >> + >> +    inode_init_once(&ei->vfs_inode); >> +} >> + >> +static int __init init_regfs_fs(void) >> +{ >> + >> +    regfs_inode_cachep = >> kmem_cache_create_usercopy("regfs_inode_cache", >> +                sizeof(struct regfs_inode_info), 0, >> +                (SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD | >> SLAB_ACCOUNT), >> +                0, 0, init_once); >> + >> +    if (!regfs_inode_cachep) >> +        return -ENOMEM; >> + >> +    return  register_filesystem(®fs_fs_type); >> +} >> + >> +static void __exit exit_regfs_fs(void) >> +{ >> +    unregister_filesystem(®fs_fs_type); >> +    rcu_barrier(); >> +    kmem_cache_destroy(regfs_inode_cachep); >> +} >> + >> +module_init(init_regfs_fs); >> +module_exit(exit_regfs_fs); >> + >> +MODULE_LICENSE("GPL"); >> +MODULE_AUTHOR("Zou Cao"); >> diff --git a/fs/regfs/internal.h b/fs/regfs/internal.h >> new file mode 100644 >> index 0000000..61577bb >> --- /dev/null >> +++ b/fs/regfs/internal.h >> @@ -0,0 +1,32 @@ >> +#ifndef __INTERNAL_H__ >> +#define __INTERNAL_H__ >> + >> +#define loc_debug(fmt, ...)   \ >> +    do {                       \ >> +        if (regfs_debug)   \ >> +            printk(fmt, ##__VA_ARGS__); \ >> +    } while (0) >> + >> +struct regfs_fs_info { >> +    struct super_block *sb; >> +    void   *dtb_buf; >> +    u64      dtb_len; >> +    u64      iomem; >> +    u64  size; >> +    // supper ifs list >> +    struct list_head regfs_head; >> +    // io map list of inode >> +    struct list_head list; >> +}; >> + >> +#define RAMFS_DEFAULT_MODE    0755 >> + >> +extern int regfs_debug; >> +extern const struct address_space_operations regfs_aops; >> +extern const struct inode_operations regfs_file_inode_operations; >> +extern const struct file_operations regfs_file_operations; >> +extern const struct super_operations regfs_ops; >> +extern struct kmem_cache *regfs_inode_cachep; >> +int regfs_supper_init(void); >> + >> +#endif >> diff --git a/fs/regfs/regfs_inode.h b/fs/regfs/regfs_inode.h >> new file mode 100644 >> index 0000000..0883e05 >> --- /dev/null >> +++ b/fs/regfs/regfs_inode.h >> @@ -0,0 +1,32 @@ >> +#ifndef __REGFS_INODE_H__ >> +#define __REGFS_INODE_H__ >> + >> +enum res_type { >> +    RES_TYPE_NONE = 0, >> +    RES_TYPE_RANGE, >> +    RES_TYPE_ITEM, >> +}; >> + >> +struct regfs_inode_info { >> +    unsigned long flag; >> +    struct inode vfs_inode; >> +    void __iomem *base; >> +    u64  offset; >> +    u64  val;  //for panic save >> +    struct list_head list;  //inode list >> +    enum res_type type; >> +}; >> + >> +struct res_data { >> +    enum res_type type; >> +    u64  base; >> +    u64  offset; >> +}; >> + >> +static inline struct regfs_inode_info *REGFS_I(struct inode *inode) >> +{ >> +    return container_of(inode, struct regfs_inode_info, vfs_inode); >> +} >> + >> +#endif >> + >> diff --git a/fs/regfs/supper.c b/fs/regfs/supper.c >> new file mode 100644 >> index 0000000..35733b6 >> --- /dev/null >> +++ b/fs/regfs/supper.c >> @@ -0,0 +1,71 @@ >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include "regfs_inode.h" >> +#include "internal.h" >> + >> +struct kmem_cache *regfs_inode_cachep; >> + >> +/* >> + * Display the mount options in /proc/mounts. >> + */ >> + >> +static struct inode *regfs_alloc_inode(struct super_block *sb) >> +{ >> +    struct regfs_inode_info *ei; >> + >> +    ei = kmem_cache_alloc(regfs_inode_cachep, GFP_NOFS); >> +    if (!ei) >> +        return NULL; >> + >> +    inode_set_iversion(&ei->vfs_inode, 1); >> +    ei->type = RES_TYPE_NONE; >> + >> +    return &ei->vfs_inode; >> +} >> + >> +static void regfs_i_callback(struct rcu_head *head) >> +{ >> +    struct inode *inode = container_of(head, struct inode, i_rcu); >> + >> +    kmem_cache_free(regfs_inode_cachep, REGFS_I(inode)); >> +} >> + >> +static void regfs_destroy_inode(struct inode *inode) >> +{ >> +    call_rcu(&inode->i_rcu, regfs_i_callback); >> +} >> + >> +static int regfs_write_inode(struct inode *inode, struct >> writeback_control *wbc) >> +{ >> +    return 0; >> +} >> + >> +static int regfs_drop_inode(struct inode *inode) >> +{ >> +    return generic_drop_inode(inode); >> +} >> + >> +const struct super_operations regfs_ops = { >> +    .alloc_inode    = regfs_alloc_inode, >> +    .destroy_inode  = regfs_destroy_inode, >> +    .write_inode    = regfs_write_inode, >> +    .drop_inode = regfs_drop_inode, >> +}; >> + >> +int regfs_supper_init(void) >> +{ >> +    return 0; >> +}