由于最近做关于PMFS文件系统的实验,实现了pmfs写文件的数据一致性,还改了PMFS的空间管理,所以想对自己近两个月所做的工作进行一个总结,以下就简单谈谈自己对于PMFS以及拓展知识的理解,如有不对之处还请指出!或者还想了解更多的可以留言讨论。
介绍
先简单介绍一下,物理块号,逻辑块号,物理地址,逻辑地址以及虚拟地址之间的关系。
这里围绕PMFS文件系统来展开介绍。假设有1T大小的内存,总共有 1T/4KB个物理块,从10G的位置开始,分出128G大小的空间用于挂载PMFS文件系统,那么PMFS文件系统的起始物理地址就为10G,其起始物理块号就为10G/4KB。还有该分区也有一个固定的起始虚拟地址。
而对于PMFS分区来说总共只有128G/4KB个物理块,那么为了管理方便,PMFS文件系统在分配块时,是从0开始计数的。这就是针对PMFS分区的块号,也就是逻辑块号。块号 * 4KB 就能算出每个块的逻辑地址。所以我对逻辑块号以及逻辑地址的理解就是它只是相对于某个区域来说的,比如说,PMFS分区相对于整个内存,一个文件相对于一个内存分区。在某种特定的时候它亦能称为物理块号和物理地址。
PMFS起始虚拟地址 virt_addr 。
文件在申请块的时候,返回的是逻辑块号logical_block_number;
逻辑地址就等于逻辑块号乘以每个块的大小。logical_address = logical_block_number << 12;
而我们在执行读写操作时都必须使用虚拟地址,虚拟地址就等于逻辑地址加上该分区的起始虚拟地址 virtual_address = logical_address + virt_addr ;
这些关系困扰了我很久,也是最近才搞清楚。
文件块组织
PMFS内存文件系统是用B512树来组织文件块的。如下图所示,B512树是一种B+树,是一种多路搜索树,非叶子结点都有512个儿子。只有叶子结点是数据块,其他都是索引块。一棵树最多只有3层,叶子结点实际为一个指针指向物理块号。
在同一个文件中,每棵树最多只有三层,每个block为4KB,那么一棵树最大能存储的文件大小为:
512 * 512 * 512 * 4KB = 512G。
索引结点的存了每个儿子的逻辑地址。通过逻辑地址又找到下一级的物理块,读取其内容,再次找到下一层结点。
下面我将通过讲写文件代码来将补充上面没说清楚的地方。
Write
write 入口函数:
ssize_t pmfs_xip_file_write(struct file *filp, const char __user *buf,
size_t len, loff_t *ppos)
{
struct address_space *mapping = filp->f_mapping;
struct inode *inode = mapping->host;
struct super_block *sb = inode->i_sb;
pmfs_transaction_t *trans;
struct pmfs_inode *pi;
ssize_t written = 0;
loff_t pos;
u64 block;
bool new_sblk = false, new_eblk = false;
size_t count, offset, eblk_offset, ret;
unsigned long start_blk, end_blk, num_blocks, max_logentries;
bool same_block;
sb_start_write(inode->i_sb);
mutex_lock(&inode->i_mutex);
if (!access_ok(VERIFY_READ, buf, len)) {
ret = -EFAULT;
goto out;
}
pos = *ppos;
count = len;
/* We can write back this queue in page reclaim */
current->ba