文件系統學習筆記

目錄項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");

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章