Creating Linux virtual filesystems 学习

根据这两个网页上学习了一下Creating Linux virtual filesystems

 http://lwn.net/Articles/57369/

http://blog.chinaunix.net/uid-317451-id-92430.html


网页上的代码有点过时了,主要是inode结构体,重新修改,适合3.0.5上:

/*
   This is the "lwnfs" module source which goes along with this article on virtual filesystems from the Porting Drivers to 2.6 series. 
 */
/*
 * Demonstrate a trivial filesystem using libfs.
 *
 * Copyright 2002, 2003 Jonathan Corbet <corbet@lwn.net>
 * This file may be redistributed under the terms of the GNU GPL.
 *
 * Chances are that this code will crash your system, delete your
 * nethack high scores, and set your disk drives on fire. You have
 * been warned.
 */
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/pagemap.h> /* PAGE_CACHE_SIZE */
#include <linux/fs.h> /* This is where libfs stuff is declared */
#include <asm/atomic.h>
#include <asm/uaccess.h>    /* copy_to_user */

/*
 * Boilerplate stuff.
 */
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jonathan Corbet");

#define LFS_MAGIC 0x19980122


/*
 * Anytime we make a file or directory in our filesystem we need to
 * come up with an inode to represent it internally. This is
 * the function that does that job. All that's really interesting
 * is the "mode" parameter, which says whether this is a directory
 * or file, and gives the permissions.
 */
static struct inode *lfs_make_inode(struct super_block *sb, int mode)
{
    struct inode *ret = new_inode(sb);

    if (ret) {
        ret->i_mode = mode;
        ret->i_uid = ret->i_gid = 0;
        //ret->i_blksize = PAGE_CACHE_SIZE;
        ret->i_blocks = 0;
        ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME;
    }
    return ret;
}


/*
 * The operations on our "files".
 */

/*
 * Open a file. All we have to do here is to copy over a
 * copy of the counter pointer so it's easier to get at.
 */
static int lfs_open(struct inode *inode, struct file *filp)
{
    //filp->private_data = inode->u.generic_ip;
    filp->private_data = inode->i_private;
    return 0;
}

#define TMPSIZE 20
/*
 * Read a file. Here we increment and read the counter, then pass it
 * back to the caller. The increment only happens if the read is done
 * at the beginning of the file (offset = 0); otherwise we end up counting
 * by twos.
 */
static ssize_t lfs_read_file(struct file *filp, char *buf,
        size_t count, loff_t *offset)
{
    atomic_t *counter = (atomic_t *) filp->private_data;
    int v, len;
    char tmp[TMPSIZE];
    /*
     * Encode the value, and figure out how much of it we can pass back.
     */
    v = atomic_read(counter);
    if (*offset > 0)
        v -= 1; /* the value returned when offset was zero */
    else
        atomic_inc(counter);
    len = snprintf(tmp, TMPSIZE, "%d\n", v);
    if (*offset > len)
        return 0;
    if (count > len - *offset)
        count = len - *offset;
    /*
     * Copy it back, increment the offset, and we're done.
     */
    if (copy_to_user(buf, tmp + *offset, count))
        return -EFAULT;
    *offset += count;
    return count;
}

/*
 * Write a file.
 */
static ssize_t lfs_write_file(struct file *filp, const char *buf,
        size_t count, loff_t *offset)
{
    atomic_t *counter = (atomic_t *) filp->private_data;
    char tmp[TMPSIZE];
    /*
     * Only write from the beginning.
     */
    if (*offset != 0)
        return -EINVAL;
    /*
     * Read the value from the user.
     */
    if (count >= TMPSIZE)
        return -EINVAL;
    memset(tmp, 0, TMPSIZE);
    if (copy_from_user(tmp, buf, count))
        return -EFAULT;
    /*
     * Store it in the counter and we are done.
     */
    atomic_set(counter, simple_strtol(tmp, NULL, 10));
    return count;
}


/*
 * Now we can put together our file operations structure.
 */
static struct file_operations lfs_file_ops = {
    .open   = lfs_open,
    .read = lfs_read_file,
    .write = lfs_write_file,
};


/*
 * Create a file mapping a name to a counter.
 */
static struct dentry *lfs_create_file (struct super_block *sb,
        struct dentry *dir, const char *name,
        atomic_t *counter)
{
    struct dentry *dentry;
    struct inode *inode;
    struct qstr qname;
    /*
     * Make a hashed version of the name to go with the dentry.
     */
    qname.name = name;
    qname.len = strlen (name);
    qname.hash = full_name_hash(name, qname.len);
    /*
     * Now we can create our dentry and the inode to go with it.
     */
    dentry = d_alloc(dir, &qname);
    if (! dentry)
        goto out;
    inode = lfs_make_inode(sb, S_IFREG | 0644);
    if (! inode)
        goto out_dput;
    inode->i_fop = &lfs_file_ops;
    //inode->u.generic_ip = counter;
    inode->i_private = counter;
    /*
     * Put it all into the dentry cache and we're done.
     */
    d_add(dentry, inode);
    return dentry;
    /*
     * Then again, maybe it didn't work.
     */
out_dput:
    dput(dentry);
out:
    return 0;
}


/*
 * Create a directory which can be used to hold files. This code is
 * almost identical to the "create file" logic, except that we create
 * the inode with a different mode, and use the libfs "simple" operations.
 */
static struct dentry *lfs_create_dir (struct super_block *sb,
        struct dentry *parent, const char *name)
{
    struct dentry *dentry;
    struct inode *inode;
    struct qstr qname;

    qname.name = name;
    qname.len = strlen (name);
    qname.hash = full_name_hash(name, qname.len);
    dentry = d_alloc(parent, &qname);
    if (! dentry)
        goto out;

    inode = lfs_make_inode(sb, S_IFDIR | 0644);
    if (! inode)
        goto out_dput;
    inode->i_op = &simple_dir_inode_operations;
    inode->i_fop = &simple_dir_operations;

    d_add(dentry, inode);
    return dentry;

out_dput:
    dput(dentry);
out:
    return 0;
}



/*
 * OK, create the files that we export.
 */
static atomic_t counter, subcounter;

static void lfs_create_files (struct super_block *sb, struct dentry *root)
{
    struct dentry *subdir;
    /*
     * One counter in the top-level directory.
     */
    atomic_set(&counter, 0);
    lfs_create_file(sb, root, "counter", &counter);
    /*
     * And one in a subdirectory.
     */
    atomic_set(&subcounter, 0);
    subdir = lfs_create_dir(sb, root, "subdir");
    if (subdir)
        lfs_create_file(sb, subdir, "subcounter", &subcounter);
}



/*
 * Superblock stuff. This is all boilerplate to give the vfs something
 * that looks like a filesystem to work with.
 */

/*
 * Our superblock operations, both of which are generic kernel ops
 * that we don't have to write ourselves.
 */
static struct super_operations lfs_s_ops = {
    .statfs  = simple_statfs,
    .drop_inode = generic_delete_inode,
};

/*
 * "Fill" a superblock with mundane stuff.
 */
static int lfs_fill_super (struct super_block *sb, void *data, int silent)
{
    struct inode *root;
    struct dentry *root_dentry;
    /*
     * Basic parameters.
     */
    sb->s_blocksize = PAGE_CACHE_SIZE;
    sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
    sb->s_magic = LFS_MAGIC;
    sb->s_op = &lfs_s_ops;
    /*
     * We need to conjure up an inode to represent the root directory
     * of this filesystem. Its operations all come from libfs, so we
     * don't have to mess with actually *doing* things inside this
     * directory.
     */
    root = lfs_make_inode (sb, S_IFDIR | 0755);
    if (! root)
        goto out;
    root->i_op = &simple_dir_inode_operations;
    root->i_fop = &simple_dir_operations;
    /*
     * Get a dentry to represent the directory in core.
     */
    root_dentry = d_alloc_root(root);
    if (! root_dentry)
        goto out_iput;
    sb->s_root = root_dentry;
    /*
     * Make up the files which will be in this filesystem, and we're done.
     */
    lfs_create_files (sb, root_dentry);
    return 0;

out_iput:
    iput(root);
out:
    return -ENOMEM;
}


/*
 * Stuff to pass in when registering the filesystem.
 */
static struct dentry * lfs_get_super(struct file_system_type *fst,
        int flags, const char *devname, void *data)
{
    return mount_nodev(fst, flags, data, lfs_fill_super);
}

static struct file_system_type lfs_type = {
//    .owner = THIS_MODULE,
    .name    = "lwnfs",
    .mount  = lfs_get_super,
    .kill_sb    = kill_litter_super,
};




/*
 * Get things set up.
 */
static int __init lfs_init(void)
{
    return register_filesystem(&lfs_type);
}

static void __exit lfs_exit(void)
{
    unregister_filesystem(&lfs_type);
}

module_init(lfs_init);
module_exit(lfs_exit);

操作:

insmod lwnfs.ko

cat /proc/filesystems   //查看是否安装成功

mount -t lwnfs /mnt /mnt   //挂载到mnt目录下

/tmp # cat /mnt/counter  
3


注意:/mnt/下的文件都不可见,每次都只能手动输入文件名,不知道为啥?


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值