summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs.c79
1 files changed, 43 insertions, 36 deletions
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;
}