提交 51097e28 创建 作者: Nickolai Zeldovich's avatar Nickolai Zeldovich

fix race condition in vmnode::allocpg

上级 c5573403
...@@ -10,10 +10,10 @@ using std::atomic; ...@@ -10,10 +10,10 @@ using std::atomic;
enum vmntype { EAGER, ONDEMAND }; enum vmntype { EAGER, ONDEMAND };
struct vmnode { struct vmnode {
u64 npages; const u64 npages;
char *page[128]; atomic<char*> page[128];
atomic<u64> ref; atomic<u64> ref;
enum vmntype type; const enum vmntype type;
struct inode *ip; struct inode *ip;
u64 offset; u64 offset;
u64 sz; u64 sz;
......
...@@ -55,9 +55,18 @@ int ...@@ -55,9 +55,18 @@ int
vmnode::allocpg() vmnode::allocpg()
{ {
for(u64 i = 0; i < npages; i++) { for(u64 i = 0; i < npages; i++) {
if((page[i] = kalloc()) == 0) if (page[i])
continue;
char *p = kalloc();
if (!p) {
cprintf("allocpg: out of memory, leaving half-filled vmnode\n");
return -1; return -1;
memset((char *) page[i], 0, PGSIZE); }
memset(p, 0, PGSIZE);
if(!cmpxch(&page[i], (char*) 0, p))
kfree(p);
} }
return 0; return 0;
} }
...@@ -66,24 +75,27 @@ vmnode * ...@@ -66,24 +75,27 @@ vmnode *
vmnode::copy() vmnode::copy()
{ {
vmnode *c = new vmnode(npages, type); vmnode *c = new vmnode(npages, type);
if(c != 0) { if(c == 0)
c->type = type; return 0;
if (type == ONDEMAND) {
c->ip = idup(ip); if (type == ONDEMAND) {
c->offset = offset; c->ip = idup(ip);
c->sz = c->sz; c->offset = offset;
} c->sz = c->sz;
if (page[0]) { // If the first page is present, all of them are present }
if (c->allocpg() < 0) {
cprintf("vmn_copy: out of memory\n"); if (!page[0]) // If first page is absent, all pages are absent
delete c; return c;
return 0;
} if (c->allocpg() < 0) {
for(u64 i = 0; i < npages; i++) { cprintf("vmn_copy: out of memory\n");
memmove(c->page[i], page[i], PGSIZE); delete c;
} return 0;
}
} }
for(u64 i = 0; i < npages; i++)
if (page[i])
memmove(c->page[i], page[i], PGSIZE);
return c; return c;
} }
...@@ -97,6 +109,11 @@ vmnode::demand_load() ...@@ -97,6 +109,11 @@ vmnode::demand_load()
n = sz - i; n = sz - i;
else else
n = PGSIZE; n = PGSIZE;
/*
* Possible race condition with concurrent demand_load() calls,
* if the underlying inode's contents change..
*/
if (readi(ip, p, offset+i, n) != n) if (readi(ip, p, offset+i, n) != n)
return -1; return -1;
} }
......
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论