今天的内容是关于简单的inode操作。
源码分析
今天的源码只涉及四个新函数,其中较关键的只有两个,分别是sfs_lookup
和sfs_mknod
。
#include <linux/module.h>
#include <linux/fs.h>
#include "samplefs.h"
extern struct dentry_operations sfs_dentry_ops;
extern struct dentry_operations sfs_ci_dentry_ops;
extern struct inode *samplefs_get_inode(struct super_block *sb, int mode,
dev_t dev);
/*
* Lookup the data, if the dentry didn't already exist, it must be
* negative. Set d_op to delete negative dentries to save memory
* (and since it does not help performance for in memory filesystem).
*/
static struct dentry *sfs_lookup(struct inode *dir, struct dentry *dentry, unsigned int len)
{
struct samplefs_sb_info *sfs_sb = SFS_SB(dir->i_sb);
if (dentry->d_name.len > NAME_MAX)
return ERR_PTR(-ENAMETOOLONG);
if (sfs_sb->flags & SFS_MNT_CASE)
dentry->d_op = &sfs_ci_dentry_ops;
else
dentry->d_op = &sfs_dentry_ops;
d_add(dentry, NULL);
return NULL;
}
在inode_operations中的lookup
函数主要作用是根据名称查找其inode实例,并将dentry->d_inode
指向inode实例。在实际实验中,d_op
一直为sfs_dentry_ops
。
sfs_mknod
这个函数主要是新建一个inode并将其连接到dentry上,而mknod命令被用来创建Linux中的字符设备文件和块设备文件。
static int
sfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
{
struct inode *inode = samplefs_get_inode(dir->i_sb, mode, dev);
struct timespec64 ts;
int error = -ENOSPC;
printk(KERN_INFO "samplefs: mknod
");
if (inode) {
if (dir->i_mode & S_ISGID) {
inode->i_gid = dir->i_gid;
if (S_ISDIR(mode))
inode->i_mode |= S_ISGID;
}
d_instantiate(dentry, inode);
dget(dentry); /* Extra count - pin the dentry in core */
error = 0;
ktime_get_ts64(&ts);
dir->i_mtime = dir->i_ctime = ts;
/* real filesystems would normally use i_size_write function */
dir->i_size += 0x20; /* bogus small size for each dir entry */
}
return error;
}
static int sfs_mkdir(struct inode * dir, struct dentry * dentry, umode_t mode)
{
int retval = 0;
retval = sfs_mknod(dir, dentry, mode | S_IFDIR, 0);
/* link count is two for dir, for dot and dot dot */
if (!retval)
dir->__i_nlink++;
return retval;
}
static int sfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
bool flag)
{
return sfs_mknod(dir, dentry, mode | S_IFREG, 0);
}
struct inode_operations sfs_dir_inode_ops = {
.create = sfs_create,
.lookup = sfs_lookup,
.unlink = simple_unlink,
.mkdir = sfs_mkdir,
.rmdir = simple_rmdir,
.mknod = sfs_mknod,
.rename = simple_rename,
};