Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
X
xv6-public
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
统计图
问题
0
问题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
银宸时代
OS Lab Group
奖励实验
xv6-public
提交
3a2a1212
提交
3a2a1212
3月 24, 2012
创建
作者:
Nickolai Zeldovich
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
avoid bumping inode refcounts, use rcu instead, with a mostly-unimplemented
plan for eviction.
上级
07cad277
隐藏空白字符变更
内嵌
并排
正在显示
2 个修改的文件
包含
52 行增加
和
76 行删除
+52
-76
kernel.hh
include/kernel.hh
+1
-0
fs.cc
kernel/fs.cc
+51
-76
没有找到文件。
include/kernel.hh
浏览文件 @
3a2a1212
...
...
@@ -91,6 +91,7 @@ struct inode* ialloc(u32, short);
struct
inode
*
namei
(
inode
*
cwd
,
const
char
*
);
void
iput
(
struct
inode
*
);
struct
inode
*
iget
(
u32
dev
,
u32
inum
);
struct
inode
*
igetnoref
(
u32
dev
,
u32
inum
);
void
ilock
(
struct
inode
*
,
int
writer
);
void
iunlockput
(
struct
inode
*
);
void
iupdate
(
struct
inode
*
);
...
...
kernel/fs.cc
浏览文件 @
3a2a1212
...
...
@@ -10,6 +10,22 @@
// routines. The (higher-level) system call implementations
// are in sysfile.c.
/*
* inode cache will be RCU-managed:
*
* - to evict, mark inode as a victim
* - lookups that encounter a victim inode must return an error (-E_RETRY)
* - E_RETRY rolls back to the beginning of syscall/pagefault and retries
* - out-of-memory error should be treated like -E_RETRY
* - once an inode is marked as victim, it can be gc_delayed()
* - the do_gc() method should remove inode from the namespace & free it
*
* - inodes have a refcount that lasts beyond a GC epoch
* - to bump refcount, first bump, then check victim flag
* - if victim flag is set, reduce the refcount and -E_RETRY
*
*/
#include "types.h"
#include "stat.h"
#include "mmu.h"
...
...
@@ -239,72 +255,36 @@ inode::~inode()
struct
inode
*
iget
(
u32
dev
,
u32
inum
)
{
struct
inode
*
ip
;
struct
inode
*
ip
=
igetnoref
(
dev
,
inum
);
if
(
ip
)
idup
(
ip
);
return
ip
;
}
struct
inode
*
igetnoref
(
u32
dev
,
u32
inum
)
{
retry
:
// Try for cached inode.
gc_begin_epoch
();
ip
=
ins
->
lookup
(
mkpair
(
dev
,
inum
));
if
(
ip
)
{
// tricky: first bump ref, then check free flag
ip
->
ref
++
;
if
(
ip
->
flags
&
I_FREE
)
{
gc_end_epoch
();
ip
->
ref
--
;
goto
retry
;
}
gc_end_epoch
();
if
(
!
(
ip
->
flags
&
I_VALID
))
{
acquire
(
&
ip
->
lock
);
while
((
ip
->
flags
&
I_VALID
)
==
0
)
cv_sleep
(
&
ip
->
cv
,
&
ip
->
lock
);
release
(
&
ip
->
lock
);
}
{
scoped_gc_epoch
e
;
struct
inode
*
ip
=
ins
->
lookup
(
mkpair
(
dev
,
inum
));
if
(
ip
)
{
if
(
!
(
ip
->
flags
&
I_VALID
))
{
acquire
(
&
ip
->
lock
);
while
((
ip
->
flags
&
I_VALID
)
==
0
)
cv_sleep
(
&
ip
->
cv
,
&
ip
->
lock
);
release
(
&
ip
->
lock
);
}
return
ip
;
}
gc_end_epoch
();
// Allocate fresh inode cache slot.
retry_evict
:
(
void
)
0
;
u32
cur_free
=
icache_free
[
mycpu
()
->
id
].
x
;
if
(
cur_free
==
0
)
{
struct
inode
*
victim
=
0
;
ins
->
enumerate
([
&
victim
](
const
pair
<
u32
,
u32
>&
,
inode
*
eip
)
->
bool
{
if
(
eip
->
ref
||
eip
->
type
==
T_DIR
)
return
false
;
acquire
(
&
eip
->
lock
);
if
(
eip
->
ref
==
0
&&
eip
->
type
!=
T_DIR
&&
!
(
eip
->
flags
&
(
I_FREE
|
I_BUSYR
|
I_BUSYW
)))
{
victim
=
eip
;
return
true
;
}
release
(
&
eip
->
lock
);
return
false
;
});
if
(
!
victim
)
panic
(
"iget out of space"
);
// tricky: first flag as free, then check refcnt, then remove from ns
victim
->
flags
|=
I_FREE
;
if
(
victim
->
ref
>
0
)
{
victim
->
flags
&=
~
(
I_FREE
);
release
(
&
victim
->
lock
);
goto
retry_evict
;
}
release
(
&
victim
->
lock
);
ins
->
remove
(
mkpair
(
victim
->
dev
,
victim
->
inum
),
&
victim
);
gc_delayed
(
victim
);
}
else
{
if
(
!
cmpxch
(
&
icache_free
[
mycpu
()
->
id
].
x
,
cur_free
,
cur_free
-
1
))
goto
retry_evict
;
}
ip
=
new
inode
();
// Allocate fresh inode cache slot.
struct
inode
*
ip
=
new
inode
();
ip
->
dev
=
dev
;
ip
->
inum
=
inum
;
ip
->
ref
=
1
;
ip
->
ref
=
0
;
ip
->
flags
=
I_BUSYR
|
I_BUSYW
;
ip
->
readbusy
=
1
;
snprintf
(
ip
->
lockname
,
sizeof
(
ip
->
lockname
),
"cv:ino:%d"
,
ip
->
inum
);
...
...
@@ -366,7 +346,7 @@ ilock(struct inode *ip, int writer)
void
iunlock
(
struct
inode
*
ip
)
{
if
(
ip
==
0
||
!
(
ip
->
flags
&
(
I_BUSYR
|
I_BUSYW
))
||
ip
->
ref
<
1
)
if
(
ip
==
0
||
!
(
ip
->
flags
&
(
I_BUSYR
|
I_BUSYW
)))
panic
(
"iunlock"
);
acquire
(
&
ip
->
lock
);
...
...
@@ -407,6 +387,9 @@ iput(struct inode *ip)
ip
->
flags
|=
(
I_BUSYR
|
I_BUSYW
);
ip
->
readbusy
++
;
// XXX: use gc_delayed() to truncate the inode later.
// flag it as a victim in the meantime.
release
(
&
ip
->
lock
);
itrunc
(
ip
);
...
...
@@ -751,12 +734,12 @@ namex(inode *cwd, const char *path, int nameiparent, char *name)
{
struct
inode
*
ip
,
*
next
;
int
r
;
scoped_gc_epoch
e
;
gc_begin_epoch
();
if
(
*
path
==
'/'
)
ip
=
iget
(
ROOTDEV
,
ROOTINO
);
ip
=
iget
noref
(
ROOTDEV
,
ROOTINO
);
else
ip
=
idup
(
cwd
)
;
ip
=
cwd
;
while
((
r
=
skipelem
(
&
path
,
name
))
==
1
){
// XXX Doing this here requires some annoying reasoning about all
...
...
@@ -773,32 +756,24 @@ namex(inode *cwd, const char *path, int nameiparent, char *name)
if
(
next
==
0
){
if
(
ip
->
type
==
0
)
panic
(
"namex"
);
if
(
ip
->
type
!=
T_DIR
){
iput
(
ip
);
gc_end_epoch
();
if
(
ip
->
type
!=
T_DIR
)
return
0
;
}
if
(
nameiparent
&&
*
path
==
'\0'
){
// Stop one level early.
gc_end_epoch
(
);
idup
(
ip
);
return
ip
;
}
if
((
next
=
dirlookup
(
ip
,
name
))
==
0
){
iput
(
ip
);
gc_end_epoch
();
if
((
next
=
dirlookup
(
ip
,
name
))
==
0
)
return
0
;
}
iput
(
ip
);
}
ip
=
next
;
}
if
(
r
==
-
1
||
nameiparent
){
iput
(
ip
);
gc_end_epoch
();
if
(
r
==
-
1
||
nameiparent
)
return
0
;
}
mtreadavar
(
"inode:%x.%x"
,
ip
->
dev
,
ip
->
inum
);
gc_end_epoch
(
);
idup
(
ip
);
return
ip
;
}
...
...
编写
预览
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论