hello.c
代码:
#include "hello.h"
struct inode * hello_get_inode(struct super_block *, int, struct hello_dir_entry *);
int hello_readdir(struct file * filp, void * dirent, filldir_t filldir)
{
printk("hello_readdir\n");
struct hello_dir_entry * de;
unsigned int ino;
int i;
struct inode *inode = filp-f_dentry-d_inode;
ino = inode-i_ino;
de = (struct hello_dir_entry *) inode-u.generic_ip;
if (!de)
return -EINVAL;
i = filp-f_pos;
switch (i) {
case 0:
if (filldir(dirent, ".", 1, i, ino, DT_DIR)
return 0;
i++;
filp-f_pos++;
/* fall through */
case 1:
if (filldir(dirent, "..", 2, i,
filp-f_dentry-d_parent-d_inode-i_ino,
DT_DIR)
return 0;
i++;
filp-f_pos++;
/* fall through */
default:
de = de-subdir;
i -= 2;
for (;;) {
if (!de)
return 1;
if (!i)
break;
de = de-next;
i--;
}
do {
if (filldir(dirent, de-name, de-namelen, filp-f_pos,
de-low_ino, de-mode 12)
return 0;
filp-f_pos++;
de = de-next;
} while (de);
}
return 1;
}
int hello_d_revalidate(struct dentry *res, int i){printk("d_revalidate\n");return 0;}
int hello_d_hash(struct dentry *res, struct qstr *name){printk("d_hash\n");return 0;}
int hello_d_compare(struct dentry *res, struct qstr *name, struct qstr *old)
{printk("d_compare\n");return 0;}
int hello_d_delete(struct dentry *res){printk("d_delete\n");return 0;}
void hello_d_release(struct dentry *res){printk("d_release\n");}
void hello_d_iput(struct dentry *res, struct inode *inode){printk("d_iput\n");}
struct dentry_operations hello_lookup_dops = {
/*d_revalidate:
hello_d_revalidate,
d_hash:
hello_d_hash,
d_compare:
hello_d_compare,*/
d_delete:
hello_d_delete,
d_release:
hello_d_release,
/*d_iput:
hello_d_iput*/
};
struct dentry *hello_lookup(struct inode * dir, struct dentry *dentry)
{
struct inode *inode;
struct hello_dir_entry * de;
int error;
error = -ENOENT;
inode = NULL;
de = (struct hello_dir_entry *) dir-u.generic_ip;
if (de) {
for (de = de-subdir; de ; de = de-next) {
if (!de || !de-low_ino)
continue;
if (de-namelen != dentry-d_name.len)
continue;
if (!memcmp(dentry-d_name.name, de-name, de-namelen)) {
int ino = de-low_ino;
error = -EINVAL;
inode = hello_get_inode(dir-i_sb, ino, de);
break;
}
}
}
if (inode) {
dentry-d_op = &hello_lookup_dops;
d_add(dentry, inode);
return NULL;
}
return ERR_PTR(error);
}
/************************************************************************************************************/
static struct inode_operations hello_root_inode_operations = {
lookup:
hello_lookup,
};
static struct file_operations hello_file_operations = {
readdir:
hello_readdir,
};
struct hello_dir_entry hello_root = {
low_ino:
HELLO_ROOT_INO,
namelen:
5,
name:
"/hello",
mode:
S_IFDIR | S_IRUGO | S_IXUGO,
nlink:
2,
hello_iops:
&hello_root_inode_operations,
hello_fops:
&hello_file_operations,
parent:
&hello_root,
};
struct inode * hello_get_inode(struct super_block * sb, int ino,
struct hello_dir_entry * de)
{
printk("hello_get_inode\n");
struct inode * inode;
de_get(de);
inode = iget(sb, ino);
if (!inode)
goto out_fail;
inode-u.generic_ip = (void *) de;
if (de) {
if (de-mode) {
inode-i_mode = de-mode;
inode-i_uid = de-uid;
inode-i_gid = de-gid;
}
if (de-size)
inode-i_size = de-size;
if (de-nlink)
inode-i_nlink = de-nlink;
if (de-owner)
__MOD_INC_USE_COUNT(de-owner);
if (de-hello_iops)
inode-i_op = de-hello_iops;
if (de-hello_fops)
inode-i_fop = de-hello_fops;
}
out:
return inode;
out_fail:
de_put(de);
goto out;
}
/***********************************************************************************************************/
void d_instantiate(struct dentry *entry, struct inode * inode)
{
printk("d_instantiate\n");
if (!list_empty(&entry-d_alias)) BUG();
spin_lock(&dcache_lock);
if (inode)
list_add(&entry-d_alias, &inode-i_dentry);
entry-d_inode = inode;
spin_unlock(&dcache_lock);
}
struct dentry * d_alloc_root(struct inode * root_inode)
{
struct dentry *res = NULL;
printk("d_alloc_root\n");
if (root_inode) {
res = d_alloc(NULL, &(const struct qstr) { "/", 1, 0 });
if (res) {
res-d_sb = root_inode-i_sb;
res-d_parent = res;
d_instantiate(res, root_inode);
}
}
return res;
}
void force_delete(struct inode *inode)
{
printk("force_delete\n");
struct hello_dir_entry *de = inode-u.generic_ip;
if (atomic_read(&inode-i_count) == 1)
inode-i_nlink = 0;
if (atomic_dec_and_test(&de-count))
printk("hello_root.count: %d\n", atomic_read(&de-count));
}
static void hello_delete_inode(struct inode *inode)
{
printk("hello_delete_inode\n");
struct hello_dir_entry *de = inode-u.generic_ip;
inode-i_state = I_CLEAR;
/*if (de) {
if (de-owner)
__MOD_DEC_USE_COUNT(de-owner);
de_put(de);
}*/
}
static void hello_read_inode(struct inode * inode)
{
printk("hello_read_inode\n");
inode-i_mtime = inode-i_atime = inode-i_ctime = CURRENT_TIME;
}
static int hello_statfs(struct super_block *sb, struct statfs *buf)
{
printk("hello_statfs\n");
return 0;
}
void hello_write_super(struct super_block *s)
{
printk("write_super\n");
}
static struct super_operations hello_sops = {
read_inode:
hello_read_inode,
put_inode:
force_delete,
delete_inode:
hello_delete_inode,
write_super:
hello_w