diff --git a/fs.c b/fs.c index 13fc935..fe65338 100644 --- a/fs.c +++ b/fs.c @@ -141,6 +141,53 @@ iinit(void) initlock(&icache.lock, "icache"); } +static struct inode* iget(uint dev, uint inum); + +//PAGEBREAK! +// Allocate a new inode with the given type on device dev. +struct inode* +ialloc(uint dev, short type) +{ + int inum; + struct buf *bp; + struct dinode *dip; + struct superblock sb; + + readsb(dev, &sb); + for(inum = 1; inum < sb.ninodes; inum++){ // loop over inode blocks + bp = bread(dev, IBLOCK(inum)); + dip = (struct dinode*)bp->data + inum%IPB; + if(dip->type == 0){ // a free inode + memset(dip, 0, sizeof(*dip)); + dip->type = type; + bwrite(bp); // mark it allocated on the disk + brelse(bp); + return iget(dev, inum); + } + brelse(bp); + } + panic("ialloc: no inodes"); +} + +// Copy inode, which has changed, from memory to disk. +void +iupdate(struct inode *ip) +{ + struct buf *bp; + struct dinode *dip; + + bp = bread(ip->dev, IBLOCK(ip->inum)); + dip = (struct dinode*)bp->data + ip->inum%IPB; + dip->type = ip->type; + dip->major = ip->major; + dip->minor = ip->minor; + dip->nlink = ip->nlink; + dip->size = ip->size; + memmove(dip->addrs, ip->addrs, sizeof(ip->addrs)); + bwrite(bp); + brelse(bp); +} + // Find the inode with number inum on device dev // and return the in-memory copy. static struct inode* @@ -262,51 +309,6 @@ iunlockput(struct inode *ip) iput(ip); } -//PAGEBREAK! -// Allocate a new inode with the given type on device dev. -struct inode* -ialloc(uint dev, short type) -{ - int inum; - struct buf *bp; - struct dinode *dip; - struct superblock sb; - - readsb(dev, &sb); - for(inum = 1; inum < sb.ninodes; inum++){ // loop over inode blocks - bp = bread(dev, IBLOCK(inum)); - dip = (struct dinode*)bp->data + inum%IPB; - if(dip->type == 0){ // a free inode - memset(dip, 0, sizeof(*dip)); - dip->type = type; - bwrite(bp); // mark it allocated on the disk - brelse(bp); - return iget(dev, inum); - } - brelse(bp); - } - panic("ialloc: no inodes"); -} - -// Copy inode, which has changed, from memory to disk. -void -iupdate(struct inode *ip) -{ - struct buf *bp; - struct dinode *dip; - - bp = bread(ip->dev, IBLOCK(ip->inum)); - dip = (struct dinode*)bp->data + ip->inum%IPB; - dip->type = ip->type; - dip->major = ip->major; - dip->minor = ip->minor; - dip->nlink = ip->nlink; - dip->size = ip->size; - memmove(dip->addrs, ip->addrs, sizeof(ip->addrs)); - bwrite(bp); - brelse(bp); -} - //PAGEBREAK! // Inode contents // @@ -336,7 +338,6 @@ bmap(struct inode *ip, uint bn) ip->addrs[NDIRECT] = addr = balloc(ip->dev); bp = bread(ip->dev, addr); a = (uint*)bp->data; - if((addr = a[bn]) == 0){ a[bn] = addr = balloc(ip->dev); bwrite(bp); @@ -571,7 +572,7 @@ skipelem(char *path, char *name) // If parent != 0, return the inode for the parent and copy the final // path element into name, which must have room for DIRSIZ bytes. static struct inode* -namex(char *path, int parent, char *name) +namex(char *path, int nameiparent, char *name) { struct inode *ip, *next; @@ -586,7 +587,7 @@ namex(char *path, int parent, char *name) iunlockput(ip); return 0; } - if(parent && *path == '\0'){ + if(nameiparent && *path == '\0'){ // Stop one level early. iunlock(ip); return ip; @@ -598,7 +599,7 @@ namex(char *path, int parent, char *name) iunlockput(ip); ip = next; } - if(parent){ + if(nameiparent){ iput(ip); return 0; } diff --git a/initcode.S b/initcode.S index 984d29f..41e84f4 100644 --- a/initcode.S +++ b/initcode.S @@ -8,7 +8,7 @@ start: pushl $argv pushl $init - pushl $0 + pushl $0 // where caller pc would be movl $SYS_exec, %eax int $T_SYSCALL diff --git a/kalloc.c b/kalloc.c index 6c6ca7e..2730d57 100644 --- a/kalloc.c +++ b/kalloc.c @@ -22,21 +22,20 @@ struct { // Initialize free list of physical pages. // This code cheats by just considering one megabyte of -// pages after _end. Real systems would determine the +// pages after end. Real systems would determine the // amount of memory available in the system and use it all. void kinit(void) { - extern int end; - uint mem; - char *start; + extern char end[]; + uint len; + char *p; initlock(&kmem.lock, "kmem"); - start = (char*) &end; - start = (char*) (((uint)start + PAGE) & ~(PAGE-1)); - mem = 256; // assume computer has 256 pages of RAM - cprintf("mem = %d\n", mem * PAGE); - kfree(start, mem * PAGE); + p = (char*)(((uint)end + PAGE) & ~(PAGE-1)); + len = 256*PAGE; // assume computer has 256 pages of RAM, 1 MB + cprintf("mem = %d\n", len); + kfree(p, len); } // Free the len bytes of memory pointed at by v, @@ -61,13 +60,7 @@ kfree(char *v, int len) rend = (struct run*)((char*)r + r->len); if(r <= p && p < rend) panic("freeing free page"); - if(pend == r){ // p next to r: replace r with p - p->len = len + r->len; - p->next = r->next; - *rp = p; - goto out; - } - if(rend == p){ // r next to p: replace p with r + if(rend == p){ // r before p: expand r to include p r->len += len; if(r->next && r->next == pend){ // r now next to r->next? r->len += r->next->len; @@ -75,6 +68,12 @@ kfree(char *v, int len) } goto out; } + if(pend == r){ // p before r: expand p to include, replace r + p->len = len + r->len; + p->next = r->next; + *rp = p; + goto out; + } } // Insert p before r in list. p->len = len; @@ -99,14 +98,11 @@ kalloc(int n) acquire(&kmem.lock); for(rp=&kmem.freelist; (r=*rp) != 0; rp=&r->next){ - if(r->len == n){ - *rp = r->next; - release(&kmem.lock); - return (char*)r; - } - if(r->len > n){ + if(r->len >= n){ r->len -= n; p = (char*)r + r->len; + if(r->len == 0) + *rp = r->next; release(&kmem.lock); return p; } diff --git a/sysfile.c b/sysfile.c index efc42b0..4d891c1 100644 --- a/sysfile.c +++ b/sysfile.c @@ -44,6 +44,20 @@ fdalloc(struct file *f) return -1; } +int +sys_dup(void) +{ + struct file *f; + int fd; + + if(argfd(0, 0, &f) < 0) + return -1; + if((fd=fdalloc(f)) < 0) + return -1; + filedup(f); + return fd; +} + int sys_read(void) { @@ -68,20 +82,6 @@ sys_write(void) return filewrite(f, p, n); } -int -sys_dup(void) -{ - struct file *f; - int fd; - - if(argfd(0, 0, &f) < 0) - return -1; - if((fd=fdalloc(f)) < 0) - return -1; - filedup(f); - return fd; -} - int sys_close(void) { @@ -225,17 +225,15 @@ create(char *path, short type, short major, short minor) if((ip = dirlookup(dp, name, &off)) != 0){ iunlockput(dp); ilock(ip); - if(ip->type != type || type != T_FILE){ - iunlockput(ip); - return 0; - } - return ip; - } - - if((ip = ialloc(dp->dev, type)) == 0){ - iunlockput(dp); + if(type == T_FILE && ip->type == T_FILE) + return ip; + iunlockput(ip); return 0; } + + if((ip = ialloc(dp->dev, type)) == 0) + panic("create: ialloc"); + ilock(ip); ip->major = major; ip->minor = minor; @@ -298,6 +296,18 @@ sys_open(void) return fd; } +int +sys_mkdir(void) +{ + char *path; + struct inode *ip; + + if(argstr(0, &path) < 0 || (ip = create(path, T_DIR, 0, 0)) == 0) + return -1; + iunlockput(ip); + return 0; +} + int sys_mknod(void) { @@ -315,18 +325,6 @@ sys_mknod(void) return 0; } -int -sys_mkdir(void) -{ - char *path; - struct inode *ip; - - if(argstr(0, &path) < 0 || (ip = create(path, T_DIR, 0, 0)) == 0) - return -1; - iunlockput(ip); - return 0; -} - int sys_chdir(void) {