目录项dentry
dentry结构体的定义:
struct dentry {
...
struct inode *d_inode; /* Where the name belongs to - NULL is
* negative */
/*
* The next three fields are touched by __d_lookup. Place them here
* so they all fit in a cache line.
*/
struct hlist_node d_hash; /* lookup hash list */
struct dentry *d_parent; /* parent directory */
struct qstr d_name;
struct list_head d_lru; /* LRU list */
/*
* d_child and d_rcu can share memory
*/
union {
struct list_head d_child; /* child of parent list */
struct rcu_head d_rcu;
} d_u;
struct list_head d_subdirs; /* our children */
struct list_head d_alias; /* inode alias list */
unsigned long d_time; /* used by d_revalidate */
struct dentry_operations *d_op;
struct super_block *d_sb; /* The root of the dentry tree */
void *d_fsdata; /* fs-specific data */
#ifdef CONFIG_PROFILING
struct dcookie_struct *d_cookie; /* cookie, if any */
#endif
int d_mounted;
unsigned char d_iname[DNAME_INLINE_LEN_MIN]; /* small names */
};
索引节点inode
inode结构体的定义
struct inode {
struct hlist_node i_hash;
struct list_head i_list;
struct list_head i_sb_list;
struct list_head i_dentry;
unsigned long i_ino;
atomic_t i_count;
unsigned int i_nlink;
uid_t i_uid;
gid_t i_gid;
dev_t i_rdev;
unsigned long i_version;
loff_t i_size;
#ifdef __NEED_I_SIZE_ORDERED
seqcount_t i_size_seqcount;
#endif
struct timespec i_atime;
struct timespec i_mtime;
struct timespec i_ctime;
unsigned int i_blkbits;
blkcnt_t i_blocks;
unsigned short i_bytes;
umode_t i_mode;
spinlock_t i_lock; /* i_blocks, i_bytes, maybe i_size */
struct mutex i_mutex;
struct rw_semaphore i_alloc_sem;
const struct inode_operations *i_op;
const struct file_operations *i_fop; /* former ->i_op->default_file_ops */
struct super_block *i_sb;
struct file_lock *i_flock;
struct address_space *i_mapping;
struct address_space i_data;
#ifdef CONFIG_QUOTA
struct dquot *i_dquot[MAXQUOTAS];
#endif
struct list_head i_devices;
union {
struct pipe_inode_info *i_pipe;
struct block_device *i_bdev;
struct cdev *i_cdev;
};
int i_cindex;
__u32 i_generation;
#ifdef CONFIG_DNOTIFY
unsigned long i_dnotify_mask; /* Directory notify events */
struct dnotify_struct *i_dnotify; /* for directory notifications */
#endif
#ifdef CONFIG_INOTIFY
struct list_head inotify_watches; /* watches on this inode */
struct mutex inotify_mutex; /* protects the watches list */
#endif
unsigned long i_state;
unsigned long dirtied_when; /* jiffies of first dirtying */
unsigned int i_flags;
atomic_t i_writecount;
#ifdef CONFIG_SECURITY
void *i_security;
#endif
void *i_private; /* fs or device private pointer */
};
Inode结构体成员解释:
书籍中示例文件系统的代码:
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/pagemap.h>
#include <linux/mount.h>
#include <linux/init.h>
#include <linux/namei.h>
#include <linux/fs.h>
#define AUFS_MAGIC 0x64668735
static struct vfsmount *aufs_mount;
static int aufs_mount_count;
static struct inode *aufs_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 = current->fsuid;
inode->i_gid = current->fsgid;
/* 注:原文代码为i_blksize,意思是以字节为单位的块大小
* 这里的i_blkbits是以位为单位的块大小。所以乘上8
*/
inode->i_blkbits = PAGE_CACHE_SIZE * 8;
inode->i_blocks = 0;
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
switch (mode & S_IFMT) {
default:
init_special_inode(inode, mode, dev);
break;
case S_IFREG:
printk("creat a file\n");
break;
case S_IFDIR:
inode->i_op = &simple_dir_inode_operations;
inode->i_fop = &simple_dir_operations;
printk("create a dir file\n");
inode->i_nlink++;
break;
}
}
return inode;
}
/* SMP-safe */
static int aufs_mknod(struct inode *dir, struct dentry *dentry,
int mode, dev_t dev)
{
struct inode *inode;
int error = -EPERM;
if (dentry->d_inode)
return -EEXIST;
inode = aufs_get_inode(dir->i_sb, mode, dev);
if (inode) {
d_instantiate(dentry, inode);
dget(dentry);
error = 0;
}
return error;
}
static int aufs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
{
int res;
res = aufs_mknod(dir, dentry, mode | S_IFDIR, 0);
if (!res)
dir->i_nlink++;
return res;
}
static int aufs_create(struct inode *dir, struct dentry *dentry, int mode)
{
return aufs_mknod(dir, dentry, mode | S_IFREG, 0);
}
static int aufs_fill_super(struct super_block *sb, void *data ,int silent)
{
static struct tree_descr debug_files[] = {{""}};
return simple_fill_super(sb, AUFS_MAGIC, debug_files);
}
static struct super_block *aufs_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, aufs_fill_super, mnt);
}
static struct file_system_type au_fs_type = {
.owner = THIS_MODULE,
.name = "aufs",
.get_sb = aufs_get_sb,
.kill_sb = kill_litter_super,
};
static int aufs_create_by_name(const char *name, mode_t mode,
struct dentry *parent,
struct dentry **dentry)
{
int error = 0;
/* If the parent is not specified, we create it in the root,
* We need the root dentry to do this, which is in the super
* block. A pointer to that is in the struct vfsmount that we
* have around.
*/
if (!parent) {
if (aufs_mount && aufs_mount->mnt_sb) {
parent = aufs_mount->mnt_sb->s_root;
}
}
if (!parent) {
printk("AH! can not find a parent!\n");
return -EFAULT;
}
*dentry = NULL;
mutex_lock(&parent->d_inode->i_mutex);
*dentry = lookup_one_len(name, parent, strlen(name));
if (!IS_ERR(dentry)) {
if ((mode & S_IFMT) == S_IFDIR)
error = aufs_mkdir(parent->d_inode, *dentry, mode);
else
error = aufs_create(parent->d_inode, *dentry, mode);
} else
error = PTR_ERR(dentry);
mutex_unlock(&parent->d_inode->i_mutex);
return error;
}
struct dentry *aufs_create_file(const char *name, mode_t mode,
struct dentry *parent, void *data,
struct file_operations *fops)
{
struct dentry *dentry = NULL;
int error;
printk("aufs: creating file '%s'\n ", name);
error = aufs_create_by_name(name, mode, parent, &dentry);
if (error) {
dentry = NULL;
goto exit;
}
if (dentry->d_inode) {
if (data)
dentry->d_inode->i_private = data; /* 源代码是:d_inode->u.generic_ip */
if (fops)
dentry->d_inode->i_fop = fops;
}
exit:
return dentry;
}
struct dentry *aufs_create_dir(const char *name, struct dentry *parent)
{
return aufs_create_file(name,
S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,
parent, NULL, NULL);
}
static int __init aufs_init(void)
{
int retval;
struct dentry *pslot;
retval = register_filesystem(&au_fs_type);
if (!retval)
{
aufs_mount = kern_mount(&au_fs_type);
if (!aufs_mount) {
printk("kern_mount return aufs_mount is NULL\n");
}
if (IS_ERR(aufs_mount)) {
printk(KERN_ERR "aufs: could not mount!\n");
unregister_filesystem(&au_fs_type);
return retval;
}
}
pslot = aufs_create_dir("woman star", NULL);
aufs_create_file("lbb", S_IFREG | S_IRUGO, pslot, NULL, NULL);
aufs_create_file("fbb", S_IFREG | S_IRUGO, pslot, NULL, NULL);
aufs_create_file("ljl", S_IFREG | S_IRUGO, pslot, NULL, NULL);
pslot = aufs_create_dir("man star", NULL);
aufs_create_file("ldh", S_IFREG | S_IRUGO, pslot, NULL, NULL);
aufs_create_file("lcw", S_IFREG | S_IRUGO, pslot, NULL, NULL);
aufs_create_file("jw", S_IFREG | S_IRUGO, pslot, NULL, NULL);
return retval;
}
static void __exit aufs_exit(void)
{
simple_release_fs(&aufs_mount, &aufs_mount_count);
unregister_filesystem(&au_fs_type);
}
module_init(aufs_init);
module_exit(aufs_exit);
MODULE_LICENSE("GPL");