diff --git a/fs.c b/fs.c index d5cc899..4d32aa8 100644 --- a/fs.c +++ b/fs.c @@ -226,6 +226,38 @@ iunlock(struct inode *ip) release(&inode_table_lock); } +uint +bmap(struct inode *ip, uint bn) +{ + unsigned x; + + if(bn >= NDIRECT) + panic("bmap 1"); + x = ip->addrs[bn]; + if(x == 0) + panic("bmap 2"); + return x; +} + +void +iunlink(struct inode *ip) +{ + int i; + + // free inode, its blocks, and remove dir entry + for (i = 0; i < NDIRECT; i++) { + if (ip->addrs[i] != 0) { + bfree(ip->dev, ip->addrs[i]); + ip->addrs[i] = 0; + } + } + ip->size = 0; + ip->major = 0; + ip->minor = 0; + iupdate(ip); + ifree(ip); // is this the right order? +} + // caller is releasing a reference to this inode. // you must have the inode lock. void @@ -234,6 +266,9 @@ iput(struct inode *ip) if(ip->count < 1 || ip->busy != 1) panic("iput"); + if ((ip->count <= 1) && (ip->nlink <= 0)) + iunlink(ip); + acquire(&inode_table_lock); ip->count -= 1; @@ -256,21 +291,6 @@ idecref(struct inode *ip) release(&inode_table_lock); } -uint -bmap(struct inode *ip, uint bn) -{ - unsigned x; - - if(bn >= NDIRECT) - panic("bmap 1"); - x = ip->addrs[bn]; - if(x == 0) - panic("bmap 2"); - return x; -} - -#define min(a, b) ((a) < (b) ? (a) : (b)) - void stati(struct inode *ip, struct stat *st) { @@ -281,6 +301,8 @@ stati(struct inode *ip, struct stat *st) st->st_size = ip->size; } +#define min(a, b) ((a) < (b) ? (a) : (b)) + int readi(struct inode *ip, char *dst, uint off, uint n) { @@ -307,8 +329,6 @@ readi(struct inode *ip, char *dst, uint off, uint n) return target - n; } -#define MIN(a, b) ((a < b) ? a : b) - int writei(struct inode *ip, char *addr, uint off, uint n) { @@ -330,7 +350,7 @@ writei(struct inode *ip, char *addr, uint off, uint n) if (b <= 0) return r; ip->addrs[lbn] = b; } - m = MIN(BSIZE - off % BSIZE, n-r); + m = min(BSIZE - off % BSIZE, n-r); bp = bread(ip->dev, bmap(ip, off / BSIZE)); memmove (bp->data + off % BSIZE, addr, m); bwrite (ip->dev, bp, bmap(ip, off/BSIZE)); @@ -476,12 +496,13 @@ mknod(char *cp, short type, short major, short minor) int unlink(char *cp) { - int i; - struct inode *ip, *dp; + struct inode *ip; + struct inode *dp; struct dirent *ep = 0; int off; struct buf *bp = 0; uint pinum; + if ((ip = namei(cp, &pinum)) == 0) { cprintf("file to be unlinked doesn't exist\n"); @@ -490,24 +511,10 @@ unlink(char *cp) ip->nlink--; if (ip->nlink > 0) { - iupdate(ip); - iput(ip); // is this the right order? + iput(ip); return 0; } - // free inode, its blocks, and remove dir entry - for (i = 0; i < NDIRECT; i++) { - if (ip->addrs[i] != 0) { - bfree(ip->dev, ip->addrs[i]); - ip->addrs[i] = 0; - } - } - ip->size = 0; - ip->major = 0; - ip->minor = 0; - iupdate(ip); - ifree(ip); // is this the right order? - dp = iget(rootdev, pinum); for(off = 0; off < dp->size; off += BSIZE) { bp = bread(dp->dev, bmap(dp, off / BSIZE)); @@ -526,8 +533,8 @@ unlink(char *cp) ep->inum = 0; bwrite (dp->dev, bp, bmap(dp, off/BSIZE)); // write directory block brelse(bp); - iput(ip); iupdate (dp); iput(dp); + iput(ip); return 0; }