checkpoint - simpler namei interface

This commit is contained in:
rsc 2007-08-20 19:37:15 +00:00
parent ef30c2c749
commit e2a620da49
4 changed files with 136 additions and 122 deletions

6
defs.h
View file

@ -128,12 +128,14 @@ void itrunc(struct inode*);
void idecref(struct inode*); void idecref(struct inode*);
struct inode* iincref(struct inode*); struct inode* iincref(struct inode*);
void iput(struct inode*); void iput(struct inode*);
struct inode* namei(char*, int, uint*, char**, struct inode**); struct inode* namei(char*);
struct inode* nameiparent(char*, char**, int*);
void stati(struct inode*, struct stat*); void stati(struct inode*, struct stat*);
int readi(struct inode*, char*, uint, uint); int readi(struct inode*, char*, uint, uint);
int writei(struct inode*, char*, uint, uint); int writei(struct inode*, char*, uint, uint);
struct inode* mknod(char*, short, short, short); struct inode* mknod(char*, short, short, short);
struct inode* mknod1(struct inode*, char*, short, short, short); struct inode* dircreat(struct inode*, char*, int, short, short, short);
int dirlookup(struct inode*, char*, int, uint*, uint*);
int unlink(char*); int unlink(char*);
void iupdate(struct inode*); void iupdate(struct inode*);
int link(char*, char*); int link(char*, char*);

172
fs.c
View file

@ -465,7 +465,7 @@ writei(struct inode *ip, char *src, uint off, uint n)
// set *poff to the byte offset of the directory entry // set *poff to the byte offset of the directory entry
// set *pinum to the inode number // set *pinum to the inode number
// return 0. // return 0.
static int int
dirlookup(struct inode *dp, char *name, int namelen, uint *poff, uint *pinum) dirlookup(struct inode *dp, char *name, int namelen, uint *poff, uint *pinum)
{ {
uint off; uint off;
@ -485,8 +485,10 @@ dirlookup(struct inode *dp, char *name, int namelen, uint *poff, uint *pinum)
if(memcmp(name, de->name, namelen) == 0 && if(memcmp(name, de->name, namelen) == 0 &&
(namelen == DIRSIZ || de->name[namelen]== 0)){ (namelen == DIRSIZ || de->name[namelen]== 0)){
// entry matches path element // entry matches path element
*poff = off + (uchar*)de - bp->data; if(poff)
*pinum = de->inum; *poff = off + (uchar*)de - bp->data;
if(pinum)
*pinum = de->inum;
brelse(bp); brelse(bp);
return 0; return 0;
} }
@ -499,9 +501,9 @@ dirlookup(struct inode *dp, char *name, int namelen, uint *poff, uint *pinum)
// Write a new directory entry (name, ino) into the directory dp. // Write a new directory entry (name, ino) into the directory dp.
// Caller must have locked dp. // Caller must have locked dp.
void void
dirwrite(struct inode *dp, char *name, uint ino) dirwrite(struct inode *dp, char *name, int namelen, uint ino)
{ {
int i, off; int off;
struct dirent de; struct dirent de;
// Look for an empty dirent. // Look for an empty dirent.
@ -513,15 +515,37 @@ dirwrite(struct inode *dp, char *name, uint ino)
} }
de.inum = ino; de.inum = ino;
for(i = 0; i < DIRSIZ && name[i]; i++) if(namelen > DIRSIZ)
de.name[i] = name[i]; namelen = DIRSIZ;
for(; i < DIRSIZ; i++) memmove(de.name, name, namelen);
de.name[i] = '\0'; memset(de.name+namelen, 0, DIRSIZ-namelen);
if(writei(dp, (char*)&de, off, sizeof(de)) != sizeof(de)) if(writei(dp, (char*)&de, off, sizeof(de)) != sizeof(de))
panic("dirwrite"); panic("dirwrite");
} }
// Create a new inode named name inside dp
// and return its locked inode structure.
// If name already exists, return 0.
struct inode*
dircreat(struct inode *dp, char *name, int namelen, short type, short major, short minor)
{
struct inode *ip;
ip = ialloc(dp->dev, type);
if(ip == 0)
return 0;
ip->major = major;
ip->minor = minor;
ip->size = 0;
ip->nlink = 1;
iupdate(ip);
dirwrite(dp, name, namelen, ip->inum);
return ip;
}
// Paths // Paths
// Skip over the next path element in path, // Skip over the next path element in path,
@ -564,21 +588,13 @@ skipelem(char *path, char **name, int *len)
// NAMEI_DELETE: return locked parent inode, offset of dirent in *ret_off. // NAMEI_DELETE: return locked parent inode, offset of dirent in *ret_off.
// return 0 if name doesn't exist. // return 0 if name doesn't exist.
struct inode* struct inode*
namei(char *path, int mode, uint *ret_off, _namei(char *path, int parent, char **pname, int *pnamelen)
char **ret_last, struct inode **ret_ip)
{ {
struct inode *dp; struct inode *dp;
char *name; char *name;
int namelen; int namelen;
uint off, dev, inum; uint off, dev, inum;
if(ret_off)
*ret_off = 0xffffffff;
if(ret_last)
*ret_last = 0;
if(ret_ip)
*ret_ip = 0;
if(*path == '/') if(*path == '/')
dp = igetroot(); dp = igetroot();
else { else {
@ -593,83 +609,63 @@ namei(char *path, int mode, uint *ret_off,
if(dp->type != T_DIR) if(dp->type != T_DIR)
goto fail; goto fail;
if(dirlookup(dp, name, namelen, &off, &inum) < 0){ if(parent && *path == '\0'){
if(mode == NAMEI_CREATE && *path == '\0'){ // Stop one level early.
*ret_last = name; *pname = name;
return dp; *pnamelen = namelen;
}
goto fail;
}
if(mode == NAMEI_DELETE && *path == '\0'){
// can't unlink . and ..
if((namelen == 1 && memcmp(name, ".", 1) == 0) ||
(namelen == 2 && memcmp(name, "..", 2) == 0)){
goto fail;
}
*ret_off = off;
return dp; return dp;
} }
if(dirlookup(dp, name, namelen, &off, &inum) < 0)
goto fail;
dev = dp->dev; dev = dp->dev;
iput(dp); iput(dp);
dp = iget(dev, inum); dp = iget(dev, inum);
if(dp->type == 0 || dp->nlink < 1) if(dp->type == 0 || dp->nlink < 1)
panic("namei"); panic("namei");
} }
if(parent)
if(mode == NAMEI_LOOKUP)
return dp;
if(mode == NAMEI_CREATE && ret_ip){
*ret_ip = dp;
return 0; return 0;
} return dp;
goto fail;
fail: fail:
iput(dp); iput(dp);
return 0; return 0;
} }
struct inode*
namei(char *path)
{
return _namei(path, 0, 0, 0);
}
struct inode*
nameiparent(char *path, char **name, int *namelen)
{
return _namei(path, 1, name, namelen);
}
// Create the path and return its locked inode structure. // Create the path and return its locked inode structure.
// If cp already exists, return 0. // If cp already exists, return 0.
struct inode* struct inode*
mknod(char *path, short type, short major, short minor) mknod(char *path, short type, short major, short minor)
{ {
struct inode *ip, *dp; struct inode *ip, *dp;
char *last; char *name;
int namelen;
if((dp = namei(path, NAMEI_CREATE, 0, &last, 0)) == 0) if((dp = nameiparent(path, &name, &namelen)) == 0)
return 0; return 0;
if(dirlookup(dp, name, namelen, 0, 0) >= 0){
ip = mknod1(dp, last, type, major, minor); iput(dp);
return 0;
}
ip = dircreat(dp, name, namelen, type, major, minor);
iput(dp); iput(dp);
return ip;
}
// Create a new inode named name inside dp
// and return its locked inode structure.
// If name already exists, return 0.
struct inode*
mknod1(struct inode *dp, char *name, short type, short major, short minor)
{
struct inode *ip;
ip = ialloc(dp->dev, type);
if(ip == 0)
return 0;
ip->major = major;
ip->minor = minor;
ip->size = 0;
ip->nlink = 1;
iupdate(ip); // write new inode to disk
dirwrite(dp, name, ip->inum);
return ip; return ip;
} }
@ -680,12 +676,15 @@ unlink(char *path)
struct inode *ip, *dp; struct inode *ip, *dp;
struct dirent de; struct dirent de;
uint off, inum, dev; uint off, inum, dev;
char *name;
int namelen;
dp = namei(path, NAMEI_DELETE, &off, 0, 0); if((dp = nameiparent(path, &name, &namelen)) == 0)
if(dp == 0)
return -1; return -1;
if(dirlookup(dp, name, namelen, &off, 0) < 0){
dev = dp->dev; iput(dp);
return -1;
}
if(readi(dp, (char*)&de, off, sizeof(de)) != sizeof(de) || de.inum == 0) if(readi(dp, (char*)&de, off, sizeof(de)) != sizeof(de) || de.inum == 0)
panic("unlink no entry"); panic("unlink no entry");
@ -702,16 +701,13 @@ unlink(char *path)
if(writei(dp, (char*)&de, off, sizeof(de)) != sizeof(de)) if(writei(dp, (char*)&de, off, sizeof(de)) != sizeof(de))
panic("unlink dir write"); panic("unlink dir write");
iupdate(dp); dev = dp->dev;
iput(dp); iput(dp);
ip = iget(dev, inum); ip = iget(dev, inum);
if(ip->nlink < 1) if(ip->nlink < 1)
panic("unlink nlink < 1"); panic("unlink nlink < 1");
ip->nlink--; ip->nlink--;
iupdate(ip); iupdate(ip);
iput(ip); iput(ip);
@ -720,21 +716,26 @@ unlink(char *path)
// Create the path new as a link to the same inode as old. // Create the path new as a link to the same inode as old.
int int
link(char *name1, char *name2) link(char *old, char *new)
{ {
struct inode *ip, *dp; struct inode *ip, *dp;
char *last; char *name;
int namelen;
if((ip = namei(name1, NAMEI_LOOKUP, 0, 0, 0)) == 0) if((ip = namei(old)) == 0)
return -1; return -1;
if(ip->type == T_DIR){ if(ip->type == T_DIR){
iput(ip); iput(ip);
return -1; return -1;
} }
iunlock(ip); iunlock(ip);
if((dp = namei(name2, NAMEI_CREATE, 0, &last, 0)) == 0) { if((dp = nameiparent(new, &name, &namelen)) == 0){
idecref(ip);
return -1;
}
if(dirlookup(dp, name, namelen, 0, 0) >= 0){
iput(dp);
idecref(ip); idecref(ip);
return -1; return -1;
} }
@ -744,11 +745,12 @@ link(char *name1, char *name2)
return -1; return -1;
} }
// LOCKING ERROR HERE! TWO LOCKS HELD AT ONCE.
ilock(ip); ilock(ip);
ip->nlink++; ip->nlink++;
iupdate(ip); iupdate(ip);
dirwrite(dp, last, ip->inum); dirwrite(dp, name, namelen, ip->inum);
iput(dp); iput(dp);
iput(ip); iput(ip);

13
proc.c
View file

@ -203,7 +203,6 @@ scheduler(void)
void void
sched(void) sched(void)
{ {
if(cp->state == RUNNING) if(cp->state == RUNNING)
panic("sched running"); panic("sched running");
if(!holding(&proc_table_lock)) if(!holding(&proc_table_lock))
@ -219,7 +218,6 @@ sched(void)
void void
yield(void) yield(void)
{ {
acquire(&proc_table_lock); acquire(&proc_table_lock);
cp->state = RUNNABLE; cp->state = RUNNABLE;
sched(); sched();
@ -422,9 +420,10 @@ procdump(void)
[RUNNING] "run ", [RUNNING] "run ",
[ZOMBIE] "zombie" [ZOMBIE] "zombie"
}; };
int i; int i, j;
struct proc *p; struct proc *p;
char *state; char *state;
uint pc[10];
for(i = 0; i < NPROC; i++) { for(i = 0; i < NPROC; i++) {
p = &proc[i]; p = &proc[i];
@ -434,7 +433,13 @@ procdump(void)
state = states[p->state]; state = states[p->state];
else else
state = "???"; state = "???";
cprintf("%d %s %s\n", p->pid, state, p->name); cprintf("%d %s %s", p->pid, state, p->name);
if(p->state == SLEEPING) {
getcallerpcs((uint*)p->jmpbuf.ebp+2, pc);
for(j=0; j<10 && pc[j] != 0; j++)
cprintf(" %p", pc[j]);
}
cprintf("\n");
} }
} }

View file

@ -115,34 +115,41 @@ int
sys_open(void) sys_open(void)
{ {
struct inode *ip, *dp; struct inode *ip, *dp;
char *path; char *path, *name;
int namelen;
int omode; int omode;
int fd; int fd, dev;
uint inum;
struct file *f; struct file *f;
char *last;
if(argstr(0, &path) < 0 || argint(1, &omode) < 0) if(argstr(0, &path) < 0 || argint(1, &omode) < 0)
return -1; return -1;
if(omode & O_CREATE){ switch(omode & O_CREATE){
dp = namei(path, NAMEI_CREATE, 0, &last, &ip); default:
if(dp){ case 0: // regular open
ip = mknod1(dp, last, T_FILE, 0, 0); if((ip = namei(path)) == 0)
return -1;
break;
case O_CREATE:
if((dp = nameiparent(path, &name, &namelen)) == 0)
return -1;
if(dirlookup(dp, name, namelen, 0, &inum) >= 0){
dev = dp->dev;
iput(dp); iput(dp);
if(ip == 0) ip = iget(dev, inum);
}else{
if((ip = dircreat(dp, name, namelen, T_FILE, 0, 0)) == 0){
iput(dp);
return -1; return -1;
} else if(ip == 0){ }
return -1; iput(dp);
} else if(ip->type == T_DIR){
iput(ip);
return -1;
} }
} else { break;
ip = namei(path, NAMEI_LOOKUP, 0, 0, 0);
if(ip == 0)
return -1;
} }
if(ip->type == T_DIR && ((omode & O_RDWR) || (omode & O_WRONLY))){
if(ip->type == T_DIR && (omode & (O_RDWR|O_WRONLY|O_CREATE))){
iput(ip); iput(ip);
return -1; return -1;
} }
@ -201,18 +208,22 @@ sys_mkdir(void)
{ {
struct inode *nip; struct inode *nip;
struct inode *dp; struct inode *dp;
char *path; char *name, *path;
struct dirent de; struct dirent de;
char *last; int namelen;
if(argstr(0, &path) < 0) if(argstr(0, &path) < 0)
return -1; return -1;
dp = namei(path, NAMEI_CREATE, 0, &last, 0); dp = nameiparent(path, &name, &namelen);
if(dp == 0) if(dp == 0)
return -1; return -1;
if(dirlookup(dp, name, namelen, 0, 0) >= 0){
iput(dp);
return -1;
}
nip = mknod1(dp, last, T_DIR, 0, 0); nip = dircreat(dp, name, namelen, T_DIR, 0, 0);
if(nip == 0){ if(nip == 0){
iput(dp); iput(dp);
return -1; return -1;
@ -245,22 +256,17 @@ sys_chdir(void)
if(argstr(0, &path) < 0) if(argstr(0, &path) < 0)
return -1; return -1;
if((ip = namei(path, NAMEI_LOOKUP, 0, 0, 0)) == 0) if((ip = namei(path)) == 0)
return -1; return -1;
if(ip == cp->cwd) {
iput(ip);
return 0;
}
if(ip->type != T_DIR) { if(ip->type != T_DIR) {
iput(ip); iput(ip);
return -1; return -1;
} }
iunlock(ip);
idecref(cp->cwd); idecref(cp->cwd);
cp->cwd = ip; cp->cwd = ip;
iunlock(cp->cwd);
return 0; return 0;
} }
@ -324,8 +330,7 @@ sys_exec(void)
if(argstr(0, &path) < 0 || argint(1, (int*)&argv) < 0) if(argstr(0, &path) < 0 || argint(1, (int*)&argv) < 0)
return -1; return -1;
ip = namei(path, NAMEI_LOOKUP, 0, 0, 0); if((ip = namei(path)) == 0)
if(ip == 0)
return -1; return -1;
if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf)) if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf))