linux文件系统初探--Day7

今天的主要内容很少,昨天我们把目录的处理换成我们指定的sfs之类的操作,今天则是涉及自定义文件操作。

源码解析

新增的代码只有inode.c中的一部分:

struct inode_operations sfs_file_inode_ops = {
	.getattr 	= simple_getattr,
};

之后在super.c中也仅仅是加上了对sfs_file_inode_ops的声明,同时在samplefs_get_inode中,当mode为S_IFREG即处理常规文件时,将i_op替换为sfs_file_inode_ops

不妨来看一看libfs.c中的simple_getattr函数:

int simple_getattr(const struct path *path, struct kstat *stat,
		   u32 request_mask, unsigned int query_flags)
{
	struct inode *inode = d_inode(path->dentry);
	generic_fillattr(inode, stat);
	stat->blocks = inode->i_mapping->nrpages << (PAGE_SHIFT - 9);
	return 0;
}
EXPORT_SYMBOL(simple_getattr);

代码很短,不妨逐行解释。

d_inode的解释是:

Get the actual inode of this dentry

很简单,就是获取某个dentry的inode,dcache.h中对d_inode的实现为:

static inline struct inode *d_inode(const struct dentry *dentry)
{
	return dentry->d_inode;
}

在fs/stat.c中,generic_fillattr定义如下:

/**
 * generic_fillattr - Fill in the basic attributes from the inode struct
 * @inode: Inode to use as the source
 * @stat: Where to fill in the attributes
 *
 * Fill in the basic attributes in the kstat structure from data that's to be
 * found on the VFS inode structure.  This is the default if no getattr inode
 * operation is supplied.
 */
void generic_fillattr(struct inode *inode, struct kstat *stat)
{
	stat->dev = inode->i_sb->s_dev;
	stat->ino = inode->i_ino;
	stat->mode = inode->i_mode;
	stat->nlink = inode->i_nlink;
	stat->uid = inode->i_uid;
	stat->gid = inode->i_gid;
	stat->rdev = inode->i_rdev;
	stat->size = i_size_read(inode);
	stat->atime = inode->i_atime;
	stat->mtime = inode->i_mtime;
	stat->ctime = inode->i_ctime;
	stat->blksize = i_blocksize(inode);
	stat->blocks = inode->i_blocks;

	if (IS_NOATIME(inode))
		stat->result_mask &= ~STATX_ATIME;
	if (IS_AUTOMOUNT(inode))
		stat->attributes |= STATX_ATTR_AUTOMOUNT;
}
EXPORT_SYMBOL(generic_fillattr);

注释写的很清楚,就是把inode中的一些属性复制到kstat中,kstat定义在stat.h中,初步看来是inode的一个小副本,包含了一些inode的基本信息。

struct kstat {
	u32		result_mask;	/* What fields the user got */
	umode_t		mode;
	unsigned int	nlink;
	uint32_t	blksize;	/* Preferred I/O size */
	u64		attributes;
	u64		attributes_mask;
#define KSTAT_ATTR_FS_IOC_FLAGS				\
	(STATX_ATTR_COMPRESSED |			\
	 STATX_ATTR_IMMUTABLE |				\
	 STATX_ATTR_APPEND |				\
	 STATX_ATTR_NODUMP |				\
	 STATX_ATTR_ENCRYPTED				\
	 )/* Attrs corresponding to FS_*_FL flags */
	u64		ino;
	dev_t		dev;
	dev_t		rdev;
	kuid_t		uid;
	kgid_t		gid;
	loff_t		size;
	struct timespec64 atime;
	struct timespec64 mtime;
	struct timespec64 ctime;
	struct timespec64 btime;			/* File creation time */
	u64		blocks;
};

在inode中i_mapping指向该inode相关的页缓存的地址空间,内核中用address_space结构表示地址空间这一概念,nrpages成员表示缓存页的总数,PAGE_SHIFT在page.h中,页大小为4KB,PAGE_SHIFT为12,这行代码修改了一下stat->blocks的值,可能的意思是,stat->blocks表示的是文件用块表示的最大长度,但是这个9具体指什么还暂时不清楚。

以上就是getattr成员的函数解析,总体上来看就是填充了一个kstat结构,根据ppt上给出的预期结果,ls命令涉及的系统调用很可能需要getattrkstat结构的支持。

结果和问题

可见,ls命令可以正常使用。

问题:touch命令有时会出现问题,而且与材料给出的预期结果不一致,touch命令也可以正常使用。而且时间戳的获取还是存在问题,目前使用的是:

struct timespec64 ts;
ktime_get_ts64(&ts);
inode->i_mtime = ts;

还是不能获取正确的时间戳。

posted @ 2021-02-02 13:52  xinze  阅读(148)  评论(0编辑  收藏  举报