From e2a620da49f7e01fb93761e15ed9d40b3835400c Mon Sep 17 00:00:00 2001 From: rsc Date: Mon, 20 Aug 2007 19:37:15 +0000 Subject: [PATCH] checkpoint - simpler namei interface --- defs.h | 6 +- fs.c | 172 +++++++++++++++++++++++++++--------------------------- proc.c | 13 +++-- sysfile.c | 67 +++++++++++---------- 4 files changed, 136 insertions(+), 122 deletions(-) diff --git a/defs.h b/defs.h index 074ad84..f2f8d73 100644 --- a/defs.h +++ b/defs.h @@ -128,12 +128,14 @@ void itrunc(struct inode*); void idecref(struct inode*); struct inode* iincref(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*); int readi(struct inode*, char*, uint, uint); int writei(struct inode*, char*, uint, uint); 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*); void iupdate(struct inode*); int link(char*, char*); diff --git a/fs.c b/fs.c index d8e6484..02ca8e9 100644 --- a/fs.c +++ b/fs.c @@ -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 *pinum to the inode number // return 0. -static int +int dirlookup(struct inode *dp, char *name, int namelen, uint *poff, uint *pinum) { 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 && (namelen == DIRSIZ || de->name[namelen]== 0)){ // entry matches path element - *poff = off + (uchar*)de - bp->data; - *pinum = de->inum; + if(poff) + *poff = off + (uchar*)de - bp->data; + if(pinum) + *pinum = de->inum; brelse(bp); 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. // Caller must have locked dp. 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; // Look for an empty dirent. @@ -513,15 +515,37 @@ dirwrite(struct inode *dp, char *name, uint ino) } de.inum = ino; - for(i = 0; i < DIRSIZ && name[i]; i++) - de.name[i] = name[i]; - for(; i < DIRSIZ; i++) - de.name[i] = '\0'; + if(namelen > DIRSIZ) + namelen = DIRSIZ; + memmove(de.name, name, namelen); + memset(de.name+namelen, 0, DIRSIZ-namelen); if(writei(dp, (char*)&de, off, sizeof(de)) != sizeof(de)) 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 // 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. // return 0 if name doesn't exist. struct inode* -namei(char *path, int mode, uint *ret_off, - char **ret_last, struct inode **ret_ip) +_namei(char *path, int parent, char **pname, int *pnamelen) { struct inode *dp; char *name; int namelen; uint off, dev, inum; - if(ret_off) - *ret_off = 0xffffffff; - if(ret_last) - *ret_last = 0; - if(ret_ip) - *ret_ip = 0; - if(*path == '/') dp = igetroot(); else { @@ -593,83 +609,63 @@ namei(char *path, int mode, uint *ret_off, if(dp->type != T_DIR) goto fail; - - if(dirlookup(dp, name, namelen, &off, &inum) < 0){ - if(mode == NAMEI_CREATE && *path == '\0'){ - *ret_last = name; - return dp; - } - 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; + + if(parent && *path == '\0'){ + // Stop one level early. + *pname = name; + *pnamelen = namelen; return dp; } + if(dirlookup(dp, name, namelen, &off, &inum) < 0) + goto fail; + dev = dp->dev; iput(dp); dp = iget(dev, inum); if(dp->type == 0 || dp->nlink < 1) panic("namei"); } - - if(mode == NAMEI_LOOKUP) - return dp; - if(mode == NAMEI_CREATE && ret_ip){ - *ret_ip = dp; + if(parent) return 0; - } - goto fail; + return dp; fail: iput(dp); 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. // If cp already exists, return 0. struct inode* mknod(char *path, short type, short major, short minor) { 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; - - ip = mknod1(dp, last, type, major, minor); - + if(dirlookup(dp, name, namelen, 0, 0) >= 0){ + iput(dp); + return 0; + } + ip = dircreat(dp, name, namelen, type, major, minor); 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; } @@ -680,12 +676,15 @@ unlink(char *path) struct inode *ip, *dp; struct dirent de; uint off, inum, dev; + char *name; + int namelen; - dp = namei(path, NAMEI_DELETE, &off, 0, 0); - if(dp == 0) + if((dp = nameiparent(path, &name, &namelen)) == 0) return -1; - - dev = dp->dev; + if(dirlookup(dp, name, namelen, &off, 0) < 0){ + iput(dp); + return -1; + } if(readi(dp, (char*)&de, off, sizeof(de)) != sizeof(de) || de.inum == 0) panic("unlink no entry"); @@ -702,16 +701,13 @@ unlink(char *path) if(writei(dp, (char*)&de, off, sizeof(de)) != sizeof(de)) panic("unlink dir write"); - iupdate(dp); + dev = dp->dev; iput(dp); ip = iget(dev, inum); - if(ip->nlink < 1) panic("unlink nlink < 1"); - ip->nlink--; - iupdate(ip); iput(ip); @@ -720,21 +716,26 @@ unlink(char *path) // Create the path new as a link to the same inode as old. int -link(char *name1, char *name2) +link(char *old, char *new) { 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; if(ip->type == T_DIR){ iput(ip); return -1; } - 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); return -1; } @@ -744,11 +745,12 @@ link(char *name1, char *name2) return -1; } + // LOCKING ERROR HERE! TWO LOCKS HELD AT ONCE. ilock(ip); ip->nlink++; iupdate(ip); - dirwrite(dp, last, ip->inum); + dirwrite(dp, name, namelen, ip->inum); iput(dp); iput(ip); diff --git a/proc.c b/proc.c index 074dc17..b09b738 100644 --- a/proc.c +++ b/proc.c @@ -203,7 +203,6 @@ scheduler(void) void sched(void) { - if(cp->state == RUNNING) panic("sched running"); if(!holding(&proc_table_lock)) @@ -219,7 +218,6 @@ sched(void) void yield(void) { - acquire(&proc_table_lock); cp->state = RUNNABLE; sched(); @@ -422,9 +420,10 @@ procdump(void) [RUNNING] "run ", [ZOMBIE] "zombie" }; - int i; + int i, j; struct proc *p; char *state; + uint pc[10]; for(i = 0; i < NPROC; i++) { p = &proc[i]; @@ -434,7 +433,13 @@ procdump(void) state = states[p->state]; else 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"); } } diff --git a/sysfile.c b/sysfile.c index e5d4eae..cd00494 100644 --- a/sysfile.c +++ b/sysfile.c @@ -115,34 +115,41 @@ int sys_open(void) { struct inode *ip, *dp; - char *path; + char *path, *name; + int namelen; int omode; - int fd; + int fd, dev; + uint inum; struct file *f; - char *last; if(argstr(0, &path) < 0 || argint(1, &omode) < 0) return -1; - if(omode & O_CREATE){ - dp = namei(path, NAMEI_CREATE, 0, &last, &ip); - if(dp){ - ip = mknod1(dp, last, T_FILE, 0, 0); + switch(omode & O_CREATE){ + default: + case 0: // regular open + 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); - if(ip == 0) + ip = iget(dev, inum); + }else{ + if((ip = dircreat(dp, name, namelen, T_FILE, 0, 0)) == 0){ + iput(dp); return -1; - } else if(ip == 0){ - return -1; - } else if(ip->type == T_DIR){ - iput(ip); - return -1; + } + iput(dp); } - } else { - ip = namei(path, NAMEI_LOOKUP, 0, 0, 0); - if(ip == 0) - return -1; + break; } - 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); return -1; } @@ -201,18 +208,22 @@ sys_mkdir(void) { struct inode *nip; struct inode *dp; - char *path; + char *name, *path; struct dirent de; - char *last; + int namelen; if(argstr(0, &path) < 0) return -1; - dp = namei(path, NAMEI_CREATE, 0, &last, 0); + dp = nameiparent(path, &name, &namelen); if(dp == 0) 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){ iput(dp); return -1; @@ -245,22 +256,17 @@ sys_chdir(void) if(argstr(0, &path) < 0) return -1; - if((ip = namei(path, NAMEI_LOOKUP, 0, 0, 0)) == 0) + if((ip = namei(path)) == 0) return -1; - if(ip == cp->cwd) { - iput(ip); - return 0; - } - if(ip->type != T_DIR) { iput(ip); return -1; } + iunlock(ip); idecref(cp->cwd); cp->cwd = ip; - iunlock(cp->cwd); return 0; } @@ -324,8 +330,7 @@ sys_exec(void) if(argstr(0, &path) < 0 || argint(1, (int*)&argv) < 0) return -1; - ip = namei(path, NAMEI_LOOKUP, 0, 0, 0); - if(ip == 0) + if((ip = namei(path)) == 0) return -1; if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf))