11 3
时间:2010-11-03 来源:harryxiyou
Today is good. Do some hacking about fs. It is so cool. That feeling i can not describe. :) Following is code.
Attention: code is from brother Wuting and Xu zhen wen.
#include <linux/module.h>
#include <linux/pagemap.h>
#include <linux/fs.h>
#include <linux/fsnotify.h>
#include <linux/init.h>
#include <linux/namei.h>
#include <linux/kobject.h>
#include <linux/magic.h>
#include <linux/mount.h>
//#include "auditfs.h"
/*
* typedef int __kernel_ssize_t;
* typedef __kernel_ssize_t ssize_t;
* */
#define XUXFS_MAGIC 0x3966477 /* It is interesting, which called magic number. :). It used for fill superblock so that we can know its fs type*/
/*
#define XUXFS_DIR 0x0001
#define PAGE_CACHE_MASK PAGE_MASK
#define PAGE_MASK (~(PAGE_SIZE-1))
*/
static struct vfsmount *auditfs_mount;
static int auditfs_mount_count;
/*struct super_block * auditfs_sb = NULL;*/
static bool auditfs_registered;
static const struct super_operations sysfs_ops = {
.statfs = simple_statfs, /*get fs's statistical information. Also, simple_statfs is for fs writers, which located in linux-*.*.?/fs/libfs.c. */
.drop_inode = generic_delete_inode, /*release inode. generic_delete_inode is in linux-?.?.?/fs/inode.c. hack :) */
};
static ssize_t default_read_file(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
return 0;
}
static ssize_t default_write_file(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
return count;
}
static int default_open(struct inode *inode, struct file *file)
{
if (inode->i_private)
file->private_data = inode->i_private;
return 0;
}
const struct file_operations auditfs_file_operations = {
.read = default_read_file,
.write = default_write_file,
.open = default_open,
};
static struct inode *auditfs_get_inode(struct super_block *sb, int mode, dev_t dev)
{
struct inode *inode = new_inode(sb);
if (inode) {
inode->i_mode = mode;
inode->i_uid = 0;
inode->i_gid = 0;
inode->i_blocks = 0;
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
inode->i_fop = &auditfs_file_operations;
}
return inode;
}
/**
* d_instantiate - fill in inode information for a dentry
* @entry: dentry to complete
* @inode: inode to attach to this dentry
*
* Fill in inode information in the entry.
*
* This turns negative dentries into productive full members
* of society.
*
* NOTE! This assumes that the inode count has been incremented
* (or otherwise set) by the caller to indicate that it is now
* in use by the dcache.
*/
static int auditfs_mknod(struct inode *dir, struct dentry *dentry,
int mode, dev_t dev)
{
struct inode *inode;
int error = -EPERM; /*operations are not permitted*/
if (dentry->d_inode)
return -EEXIST; /*file exist*/
inode = auditfs_get_inode(dir->i_sb, mode, dev);
if (inode) {
d_instantiate(dentry, inode);
dget(dentry);
error = 0;
}
return error;
}
static int auditfs_create(struct inode *dir, struct dentry *dentry, int mode)
{
int res;
mode = (mode & S_IALLUGO) | S_IFREG;
res = auditfs_mknod(dir, dentry, mode, 0);
if (!res)
fsnotify_create(dir, dentry);
return res;
}
static inline int auditfs_positive(struct dentry *dentry)
{
return dentry->d_inode && !d_unhashed(dentry);
}
static int auditfs_fill_super(struct super_block *sb, void *data, int silent)
{
static struct tree_descr auditfs_files[] = {{""}};
return simple_fill_super(sb, XUXFS_MAGIC, auditfs_files);
}
static int audit_get_sb(struct file_system_type *fs_type,
int flags, const char *dev_name,
void *data, struct vfsmount *mnt)
{
return get_sb_single(fs_type, flags, data, auditfs_fill_super, mnt);
}
static struct file_system_type audit_fs_type = {
.owner = THIS_MODULE,
.name = "auditfs",
.get_sb = audit_get_sb,
.kill_sb = kill_litter_super,
};
static int auditfs_create_by_name(const char *name, mode_t mode,
struct dentry *parent,
struct dentry **dentry)
{
int error = 0;
if (!parent) {
if (auditfs_mount && auditfs_mount->mnt_sb) {
parent = auditfs_mount->mnt_sb->s_root;
}
}
if (!parent) {
return -EFAULT;
}
*dentry = NULL;
*dentry = lookup_one_len(name, parent, strlen(name));
error = auditfs_create(parent->d_inode, *dentry, mode);
dput(*dentry); /* dput release a dentry*/
return error;
}
struct dentry *auditfs_create_file(const char *name, mode_t mode,
struct dentry *parent, void *data,
const struct file_operations *fops)
{
struct dentry *dentry = NULL;
int error;
error = simple_pin_fs(&audit_fs_type, &auditfs_mount,
&auditfs_mount_count);
if (error)
goto exit;
error = auditfs_create_by_name(name, mode, parent, &dentry);
if (error) {
dentry = NULL;
simple_release_fs(&auditfs_mount, &auditfs_mount_count);
goto exit;
}
if (dentry->d_inode) {
if (data)
dentry->d_inode->i_private = data;
if (fops)
dentry->d_inode->i_fop = fops;
}
exit:
return dentry;
}
EXPORT_SYMBOL_GPL(auditfs_create_file);
struct dentry *auditfs_create_dir(const char *name, struct dentry *parent)
{
return auditfs_create_file(name,
S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,
parent, NULL, NULL);
}
EXPORT_SYMBOL_GPL(auditfs_create_dir); /*export the symbol so that other moudules can use the function*/
static int __init auditfs_init(void) /*init the file system, in fact, it is important :) */
{
int retval;
retval = register_filesystem(&audit_fs_type);
if (!retval) {
auditfs_mount = vfs_kern_mount(&audit_fs_type,MS_KERNMOUNT,(&audit_fs_type)->name,NULL);/*MS_KERNMOUNT is a kernel_mount call*/
if (IS_ERR(auditfs_mount)) {
printk(KERN_ERR "auditfs: could not mount!\n");
retval= PTR_ERR(auditfs_mount);
auditfs_mount = NULL;
unregister_filesystem(&audit_fs_type);
return retval;
}
}
return 0;
}
static void __exit auditfs_exit(void) /*exit the file system*/
{
auditfs_registered = false;
simple_release_fs(&auditfs_mount, &auditfs_mount_count);
unregister_filesystem(&audit_fs_type); /*Zero is okay, or failure*/
}
module_init(auditfs_init); /*the kernel module things*/
module_exit(auditfs_exit);
MODULE_LICENSE("GPL");
Any question can communicate with me, thanks.
Bye :)
Attention: code is from brother Wuting and Xu zhen wen.
#include <linux/module.h>
#include <linux/pagemap.h>
#include <linux/fs.h>
#include <linux/fsnotify.h>
#include <linux/init.h>
#include <linux/namei.h>
#include <linux/kobject.h>
#include <linux/magic.h>
#include <linux/mount.h>
//#include "auditfs.h"
/*
* typedef int __kernel_ssize_t;
* typedef __kernel_ssize_t ssize_t;
* */
#define XUXFS_MAGIC 0x3966477 /* It is interesting, which called magic number. :). It used for fill superblock so that we can know its fs type*/
/*
#define XUXFS_DIR 0x0001
#define PAGE_CACHE_MASK PAGE_MASK
#define PAGE_MASK (~(PAGE_SIZE-1))
*/
static struct vfsmount *auditfs_mount;
static int auditfs_mount_count;
/*struct super_block * auditfs_sb = NULL;*/
static bool auditfs_registered;
static const struct super_operations sysfs_ops = {
.statfs = simple_statfs, /*get fs's statistical information. Also, simple_statfs is for fs writers, which located in linux-*.*.?/fs/libfs.c. */
.drop_inode = generic_delete_inode, /*release inode. generic_delete_inode is in linux-?.?.?/fs/inode.c. hack :) */
};
static ssize_t default_read_file(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
return 0;
}
static ssize_t default_write_file(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
return count;
}
static int default_open(struct inode *inode, struct file *file)
{
if (inode->i_private)
file->private_data = inode->i_private;
return 0;
}
const struct file_operations auditfs_file_operations = {
.read = default_read_file,
.write = default_write_file,
.open = default_open,
};
static struct inode *auditfs_get_inode(struct super_block *sb, int mode, dev_t dev)
{
struct inode *inode = new_inode(sb);
if (inode) {
inode->i_mode = mode;
inode->i_uid = 0;
inode->i_gid = 0;
inode->i_blocks = 0;
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
inode->i_fop = &auditfs_file_operations;
}
return inode;
}
/**
* d_instantiate - fill in inode information for a dentry
* @entry: dentry to complete
* @inode: inode to attach to this dentry
*
* Fill in inode information in the entry.
*
* This turns negative dentries into productive full members
* of society.
*
* NOTE! This assumes that the inode count has been incremented
* (or otherwise set) by the caller to indicate that it is now
* in use by the dcache.
*/
static int auditfs_mknod(struct inode *dir, struct dentry *dentry,
int mode, dev_t dev)
{
struct inode *inode;
int error = -EPERM; /*operations are not permitted*/
if (dentry->d_inode)
return -EEXIST; /*file exist*/
inode = auditfs_get_inode(dir->i_sb, mode, dev);
if (inode) {
d_instantiate(dentry, inode);
dget(dentry);
error = 0;
}
return error;
}
static int auditfs_create(struct inode *dir, struct dentry *dentry, int mode)
{
int res;
mode = (mode & S_IALLUGO) | S_IFREG;
res = auditfs_mknod(dir, dentry, mode, 0);
if (!res)
fsnotify_create(dir, dentry);
return res;
}
static inline int auditfs_positive(struct dentry *dentry)
{
return dentry->d_inode && !d_unhashed(dentry);
}
static int auditfs_fill_super(struct super_block *sb, void *data, int silent)
{
static struct tree_descr auditfs_files[] = {{""}};
return simple_fill_super(sb, XUXFS_MAGIC, auditfs_files);
}
static int audit_get_sb(struct file_system_type *fs_type,
int flags, const char *dev_name,
void *data, struct vfsmount *mnt)
{
return get_sb_single(fs_type, flags, data, auditfs_fill_super, mnt);
}
static struct file_system_type audit_fs_type = {
.owner = THIS_MODULE,
.name = "auditfs",
.get_sb = audit_get_sb,
.kill_sb = kill_litter_super,
};
static int auditfs_create_by_name(const char *name, mode_t mode,
struct dentry *parent,
struct dentry **dentry)
{
int error = 0;
if (!parent) {
if (auditfs_mount && auditfs_mount->mnt_sb) {
parent = auditfs_mount->mnt_sb->s_root;
}
}
if (!parent) {
return -EFAULT;
}
*dentry = NULL;
*dentry = lookup_one_len(name, parent, strlen(name));
error = auditfs_create(parent->d_inode, *dentry, mode);
dput(*dentry); /* dput release a dentry*/
return error;
}
struct dentry *auditfs_create_file(const char *name, mode_t mode,
struct dentry *parent, void *data,
const struct file_operations *fops)
{
struct dentry *dentry = NULL;
int error;
error = simple_pin_fs(&audit_fs_type, &auditfs_mount,
&auditfs_mount_count);
if (error)
goto exit;
error = auditfs_create_by_name(name, mode, parent, &dentry);
if (error) {
dentry = NULL;
simple_release_fs(&auditfs_mount, &auditfs_mount_count);
goto exit;
}
if (dentry->d_inode) {
if (data)
dentry->d_inode->i_private = data;
if (fops)
dentry->d_inode->i_fop = fops;
}
exit:
return dentry;
}
EXPORT_SYMBOL_GPL(auditfs_create_file);
struct dentry *auditfs_create_dir(const char *name, struct dentry *parent)
{
return auditfs_create_file(name,
S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,
parent, NULL, NULL);
}
EXPORT_SYMBOL_GPL(auditfs_create_dir); /*export the symbol so that other moudules can use the function*/
static int __init auditfs_init(void) /*init the file system, in fact, it is important :) */
{
int retval;
retval = register_filesystem(&audit_fs_type);
if (!retval) {
auditfs_mount = vfs_kern_mount(&audit_fs_type,MS_KERNMOUNT,(&audit_fs_type)->name,NULL);/*MS_KERNMOUNT is a kernel_mount call*/
if (IS_ERR(auditfs_mount)) {
printk(KERN_ERR "auditfs: could not mount!\n");
retval= PTR_ERR(auditfs_mount);
auditfs_mount = NULL;
unregister_filesystem(&audit_fs_type);
return retval;
}
}
return 0;
}
static void __exit auditfs_exit(void) /*exit the file system*/
{
auditfs_registered = false;
simple_release_fs(&auditfs_mount, &auditfs_mount_count);
unregister_filesystem(&audit_fs_type); /*Zero is okay, or failure*/
}
module_init(auditfs_init); /*the kernel module things*/
module_exit(auditfs_exit);
MODULE_LICENSE("GPL");
Any question can communicate with me, thanks.
Bye :)
相关阅读 更多 +