lab9 file system
lab9 file system
实验结果
我电脑性能不好,且安装的虚拟机性能也不太行。跑bigfile会timeout,网上查找可以通过修改gradelib.py来避免timeout,但我目的是验证我做的对不对,又不是让make grade通过,所以结果变成如下。
bigfile结果


Symbolic links结果


实验
large files
思路

上图就是inode的结果,理解上图就会做了。当然这是别的操作系统inode的结构,题目中block size是1024,inode直接块要求为11个,1个间接块,1个二级间接块。
代码
在./kernel/fs.h 中修改NDIRECT, 修改MAXFILE,修改dnidode。
#define NDIRECT 11
#define NINDIRECT (BSIZE / sizeof(uint))
#define DOUBLE_NINDIRECT ((NINDIRECT) * (NINDIRECT))
#define MAXFILE (NDIRECT + NINDIRECT + DOUBLE_NINDIRECT)
// On-disk inode structure
struct dinode {
short type; // File type
short major; // Major device number (T_DEVICE only)
short minor; // Minor device number (T_DEVICE only)
short nlink; // Number of links to inode in file system
uint size; // Size of file (bytes)
uint addrs[NDIRECT+2]; // Data block addresses
};
在./kernel/file.h 中修改idode。
// in-memory copy of an inode
struct inode {
uint dev; // Device number
uint inum; // Inode number
int ref; // Reference count
struct sleeplock lock; // protects everything below here
int valid; // inode has been read from disk?
short type; // copy of disk inode
short major;
short minor;
short nlink;
uint size;
uint addrs[NDIRECT+2];
};
在./kernel/fs.c 中修改bmap和itrunc
static uint
bmap(struct inode *ip, uint bn)
{
uint addr, *a, DoubleIndex;
struct buf *bp;
struct buf* bp2;
if(bn < NDIRECT){
if((addr = ip->addrs[bn]) == 0)
ip->addrs[bn] = addr = balloc(ip->dev);
return addr;
}
bn -= NDIRECT;
if(bn < NINDIRECT){
// Load indirect block, allocating if necessary.
if((addr = ip->addrs[NDIRECT]) == 0)
ip->addrs[NDIRECT] = addr = balloc(ip->dev);
bp = bread(ip->dev, addr);
a = (uint*)bp->data;
if((addr = a[bn]) == 0){
a[bn] = addr = balloc(ip->dev);
log_write(bp);
}
brelse(bp);
return addr;
}
bn = bn - NINDIRECT;
if (bn < DOUBLE_NINDIRECT)
{
addr = ip->addrs[NDIRECT + 1];
if (addr == 0)//没有一级索引块
{
addr = balloc(ip->dev);//balloc 不分配出block,在里面就会panic了,分配的块set 0
ip->addrs[NDIRECT + 1] = addr;
}
bp = bread(ip->dev, addr);
a = (uint*)bp->data;
DoubleIndex = (uint)(bn / NINDIRECT);
addr = a[DoubleIndex];
if (addr == 0)//没有索引块
{
addr = balloc(ip->dev);
a[DoubleIndex] = addr;
log_write(bp);
}
bp2 = bread(ip->dev, addr);
a = (uint*)bp2->data;
DoubleIndex = bn - NINDIRECT * DoubleIndex;
addr = a[DoubleIndex];
if (addr == 0)//没有数据块
{
addr = balloc(ip->dev);
a[DoubleIndex] = addr;
log_write(bp2);
}
brelse(bp2);
brelse(bp);
return addr;
}
panic("bmap: out of range");
}
// Truncate inode (discard contents).
// Caller must hold ip->lock.
void
itrunc(struct inode *ip)
{
int i, j;
struct buf *bp, *bp2;
uint *a, *b;
uint addr;
for(i = 0; i < NDIRECT; i++){
if(ip->addrs[i]){
bfree(ip->dev, ip->addrs[i]);
ip->addrs[i] = 0;
}
}
if(ip->addrs[NDIRECT]){
bp = bread(ip->dev, ip->addrs[NDIRECT]);
a = (uint*)bp->data;
for(j = 0; j < NINDIRECT; j++){
if(a[j])
bfree(ip->dev, a[j]);
}
brelse(bp);
bfree(ip->dev, ip->addrs[NDIRECT]);
ip->addrs[NDIRECT] = 0;
}
if (ip->addrs[NDIRECT + 1])
{
bp = bread(ip->dev, ip->addrs[NDIRECT + 1]);
a = (uint*)bp->data;
for (i = 0; i < NINDIRECT; i++)//扫描一级索引块
{
addr = a[i];
if (addr != 0)//有索引块
{
bp2 = bread(ip->dev, addr);
for (j = 0; j < NINDIRECT; j++)//扫描索引块
{
b = (uint*)bp2->data;
if (b[j] != 0)//有的话释放
{
bfree(ip->dev, b[j]);
}
}
brelse(bp2);
bfree(ip->dev, a[i]);
}
}
brelse(bp);
bfree(ip->dev, ip->addrs[NDIRECT + 1]);
ip->addrs[NDIRECT + 1] = 0;
}
ip->size = 0;
iupdate(ip);
}
Symbolic links
做该实验,要想清楚如下问题。
1:一个pathname,例如/xxxx/ttt/ccc/abc,如果在里面存在软链接,那么只会是abc。因为在ccc时软链接,那么跳走别的文件(目录),目录文件中没有cc,你要怎么办,事实上会有个逻辑bug。
2:soft link保存在那里?比如soft在一个dirct中,我要从哪里去寻找soft link所指向的那个字符串呢?放在direct的结构体,那么假设14个文件都是soft link呢?而且namei,nameparent是给定一个path,返回一定的parent,我现在要返回一个字符串,与底层提供的接口都不符,难道我要重写很多接口??你会发现,direct也是一个inode,然后它的文件数据被存储到inode所对应block中。硬链接里,新产生的pathname还是指向原本的那个inode;软链接通过新产生的pathname,可以得到文件原本的pathname,但并没有说soft link的pathname不用inode,所以soft link的原文件的pathname存储到soft link的inode的data block中,而且如果soft link不是一个inode,“Other system calls (e.g., link and unlink) must not follow symbolic links; these system calls operate on the symbolic link itself.”这句话怎么解决,link unlink open write等我都要重新修改?而sfot link用inode就可以符合xv6的设计,为啥要自讨苦吃
3:对错误情况的处理。target只要存在,不管怎么样的形式,都可以保存在data block中,而path,例如出现aas/sss/的情况要怎么处理?xv6 对于path name的处理主要用namei,nameparent这两个api,观察namex函数。知道如果nameparent为0,输入/as/ae,返回的是ae所对应的inode,输入/as/ae/,返回的也是ae说对应的inode。
4:systemlink输入的path是包括了文件名还是放在哪个path下呢?还是两种情况都要考虑,我觉得是放在哪个现实下的应该不靠谱,参考linux 命令ln。
5: 如果该文件已存在,是要修改file data还是返回-1,选择返回-1吧,偷偷修改可能会产生很严重的bug。
问题

首先确定哪里出现问题ilock, no type。

就是在ilock中ip-type等于0才会导致,但是我记得ialloc中已经对inode的type赋值了?
// Allocate an inode on device dev.
// Mark it as allocated by giving it type type.
// Returns an unlocked but allocated and referenced inode.
struct inode*
ialloc(uint dev, short type)
{
int inum;
struct buf *bp;
struct dinode *dip;
for(inum = 1; inum < sb.ninodes; inum++){
bp = bread(dev, IBLOCK(inum, sb));
dip = (struct dinode*)bp->data + inum%IPB;
if(dip->type == 0){ // a free inode
memset(dip, 0, sizeof(*dip));
dip->type = type;
log_write(bp); // mark it allocated on the disk
brelse(bp);
return iget(dev, inum);
}
brelse(bp);
}
panic("ialloc: no inodes");
}
观察ialloc函数,是有个dip->type赋值type,为啥没有呢?因为最初是观察create制造一个inode,
发现create函数中,ialloc后,是有对 major,minor,nlink这3个属性赋值的,major,minor看create可能是0,而且似乎跟device文件有关,先不管。nlink特别重要,要是nlink0,ref0,那么这个inode就是存储文件,也没程序正在使用了,所以nlink应该赋值**,查看iget中,也没对nlink进行操作,于是参考cretae, nlink=1,iupdate,成功解决。
xv6文件系统相关知识后面再叙述吧!

浙公网安备 33010602011771号