diff options
| author | kaashoek <kaashoek> | 2006-08-12 22:03:01 +0000 | 
|---|---|---|
| committer | kaashoek <kaashoek> | 2006-08-12 22:03:01 +0000 | 
| commit | 22bac2cb9d0b8050573a4b5c6cb5d8f460ee4167 (patch) | |
| tree | 20c21d87385df8433acc79958d697a01ab0cb744 | |
| parent | 14938f9392524ad1b198bf36e63d42e0e61dab85 (diff) | |
| download | xv6-labs-22bac2cb9d0b8050573a4b5c6cb5d8f460ee4167.tar.gz xv6-labs-22bac2cb9d0b8050573a4b5c6cb5d8f460ee4167.tar.bz2 xv6-labs-22bac2cb9d0b8050573a4b5c6cb5d8f460ee4167.zip | |
free inode only when noone is holding a pointer to it.  should fix open-unlink-
read problem, but untested
| -rw-r--r-- | fs.c | 79 | 
1 files changed, 43 insertions, 36 deletions
| @@ -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;  } | 
