Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
X
xv6-public
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
统计图
问题
0
问题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
银宸时代
OS Lab Group
奖励实验
xv6-public
提交
38eee5bc
提交
38eee5bc
10月 11, 2011
创建
作者:
Robert Morris
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
more FS comment clarification
上级
a5fbfe41
显示空白字符变更
内嵌
并排
正在显示
1 个修改的文件
包含
60 行增加
和
43 行删除
+60
-43
fs.c
fs.c
+60
-43
没有找到文件。
fs.c
浏览文件 @
38eee5bc
...
...
@@ -111,40 +111,50 @@ bfree(int dev, uint b)
// inodes include book-keeping information that is
// not stored on disk: ip->ref and ip->flags.
//
// ip->ref counts the number of pointer references to this cached
// inode; references are typically kept in struct file and in proc->cwd.
// When ip->ref falls to zero, the inode is no longer cached.
// It is an error to use an inode without holding a reference to it.
// An inode and its in-memory represtative go through a
// sequence of states before they can be used by the
// rest of the file system code.
//
// Processes are only allowed to read and write inode
// metadata and contents when holding the inode's lock,
// represented by the I_BUSY bit in ip->flags.
// Because inode locks are held during disk accesses,
// they are implemented using a flag rather than with
// spin locks. ilock() and iunlock() manipulate an
// inode's I_BUSY flag. Many routines in this file expect
// the caller to have already locked the inode; leaving
// this responsibility with the caller makes it possible for them
// to create arbitrarily-sized atomic operations.
// * Allocation: an inode is allocated if its type (on disk)
// is non-zero. ialloc() allocates, iput() frees if
// the link count has fallen to zero.
//
// To give maximum control over locking to the callers,
// the routines in this file that return inode pointers
// return pointers to *unlocked* inodes. It is the callers'
// responsibility to lock them before using them. A non-zero
// ip->ref keeps these unlocked inodes in the cache.
// * Referencing in cache: an entry in the inode cache
// is free if ip->ref is zero. Otherwise ip->ref tracks
// the number of in-memory pointers to the entry (open
// files and current directories). iget() to find or
// create a cache entry and increment its ref, iput()
// to decrement ref.
//
// In order for the file system code to look at an inode, the inode
// must pass through a number of states, with transitions
// driven by the indicated functions:
// * Valid: the information (type, size, &c) in an inode
// cache entry is only correct when the I_VALID bit
// is set in ip->flags. ilock() reads the inode from
// the disk and sets I_VALID, while iput() clears
// I_VALID if ip->ref has fallen to zero.
//
// * Allocated on disk, indicated by a non-zero type.
// ialloc() and iput().
// * Referenced in the cache, indicated by ip->ref > 0.
// iget() and iput().
// * Cached inode is valid, indicated by I_VALID.
// ilock() and iput().
// * Locked, indicated by I_BUSY.
// ilock() and iunlock().
// * Locked: file system code may only examine and modify
// the information in an inode and its content if it
// has first locked the inode. The I_BUSY flag indicates
// that the inode is locked. ilock() sets I_BUSY,
// while iunlock clears it.
//
// Thus a typical sequence is:
// ip = iget(dev, inum)
// ilock(ip)
// ... examine and modify ip->xxx ...
// iunlock(ip)
// iput(ip)
//
// ilock() is separate from iget() so that system calls can
// get a long-term reference to an inode (as for an open file)
// and only lock it for short periods (e.g., in read()).
// The separation also helps avoid deadlock and races during
// pathname lookup. iget() increments ip->ref so that the inode
// stays cached and pointers to it remain valid.
//
// Many internal file system functions expect the caller to
// have locked the inodes involved; this lets callers create
// multi-step atomic operations.
struct
{
struct
spinlock
lock
;
...
...
@@ -187,7 +197,7 @@ ialloc(uint dev, short type)
panic
(
"ialloc: no inodes"
);
}
// Copy
inode, which has changed, from memory
to disk.
// Copy
a modified in-memory inode
to disk.
void
iupdate
(
struct
inode
*
ip
)
{
...
...
@@ -207,7 +217,8 @@ iupdate(struct inode *ip)
}
// Find the inode with number inum on device dev
// and return the in-memory copy.
// and return the in-memory copy. Does not lock
// the inode and does not read it from disk.
static
struct
inode
*
iget
(
uint
dev
,
uint
inum
)
{
...
...
@@ -215,7 +226,7 @@ iget(uint dev, uint inum)
acquire
(
&
icache
.
lock
);
//
Try for cached inode.
//
Is the inode already cached?
empty
=
0
;
for
(
ip
=
&
icache
.
inode
[
0
];
ip
<
&
icache
.
inode
[
NINODE
];
ip
++
){
if
(
ip
->
ref
>
0
&&
ip
->
dev
==
dev
&&
ip
->
inum
==
inum
){
...
...
@@ -227,7 +238,7 @@ iget(uint dev, uint inum)
empty
=
ip
;
}
//
Allocate fresh inode
.
//
Recycle an inode cache entry
.
if
(
empty
==
0
)
panic
(
"iget: no inodes"
);
...
...
@@ -253,6 +264,7 @@ idup(struct inode *ip)
}
// Lock the given inode.
// Reads the inode from disk if necessary.
void
ilock
(
struct
inode
*
ip
)
{
...
...
@@ -297,13 +309,17 @@ iunlock(struct inode *ip)
release
(
&
icache
.
lock
);
}
// Caller holds reference to unlocked ip. Drop reference.
// Drop a reference to an in-memory inode.
// If that was the last reference, the inode cache entry can
// be recycled.
// If that was the last reference and the inode has no links
// to it, free the inode (and its content) on disk.
void
iput
(
struct
inode
*
ip
)
{
acquire
(
&
icache
.
lock
);
if
(
ip
->
ref
==
1
&&
(
ip
->
flags
&
I_VALID
)
&&
ip
->
nlink
==
0
){
// inode
is no longer used
: truncate and free inode.
// inode
has no links
: truncate and free inode.
if
(
ip
->
flags
&
I_BUSY
)
panic
(
"iput busy"
);
ip
->
flags
|=
I_BUSY
;
...
...
@@ -328,12 +344,12 @@ iunlockput(struct inode *ip)
}
//PAGEBREAK!
// Inode content
s
// Inode content
//
// The content
s
(data) associated with each inode is stored
// in
a sequence of blocks on the disk. The first NDIRECT block
s
// The content (data) associated with each inode is stored
// in
blocks on the disk. The first NDIRECT block number
s
// are listed in ip->addrs[]. The next NINDIRECT blocks are
// listed in
the
block ip->addrs[NDIRECT].
// listed in block ip->addrs[NDIRECT].
// Return the disk block address of the nth block in inode ip.
// If there is no such block, bmap allocates one.
...
...
@@ -368,8 +384,10 @@ bmap(struct inode *ip, uint bn)
}
// Truncate inode (discard contents).
// Only called after the last dirent referring
// to this inode has been erased on disk.
// Only called when the inode has no links
// to it (no directory entries referring to it)
// and has no in-memory reference to it (is
// not an open file or current directory).
static
void
itrunc
(
struct
inode
*
ip
)
{
...
...
@@ -484,7 +502,6 @@ namecmp(const char *s, const char *t)
// Look for a directory entry in a directory.
// If found, set *poff to byte offset of entry.
// Caller must have already locked dp.
struct
inode
*
dirlookup
(
struct
inode
*
dp
,
char
*
name
,
uint
*
poff
)
{
...
...
编写
预览
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论