free inode only when noone is holding a pointer to it. should fix open-unlink-
read problem, but untested
This commit is contained in:
parent
14938f9392
commit
22bac2cb9d
79
fs.c
79
fs.c
|
@ -226,6 +226,38 @@ iunlock(struct inode *ip)
|
||||||
release(&inode_table_lock);
|
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.
|
// caller is releasing a reference to this inode.
|
||||||
// you must have the inode lock.
|
// you must have the inode lock.
|
||||||
void
|
void
|
||||||
|
@ -234,6 +266,9 @@ iput(struct inode *ip)
|
||||||
if(ip->count < 1 || ip->busy != 1)
|
if(ip->count < 1 || ip->busy != 1)
|
||||||
panic("iput");
|
panic("iput");
|
||||||
|
|
||||||
|
if ((ip->count <= 1) && (ip->nlink <= 0))
|
||||||
|
iunlink(ip);
|
||||||
|
|
||||||
acquire(&inode_table_lock);
|
acquire(&inode_table_lock);
|
||||||
|
|
||||||
ip->count -= 1;
|
ip->count -= 1;
|
||||||
|
@ -256,21 +291,6 @@ idecref(struct inode *ip)
|
||||||
release(&inode_table_lock);
|
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
|
void
|
||||||
stati(struct inode *ip, struct stat *st)
|
stati(struct inode *ip, struct stat *st)
|
||||||
{
|
{
|
||||||
|
@ -281,6 +301,8 @@ stati(struct inode *ip, struct stat *st)
|
||||||
st->st_size = ip->size;
|
st->st_size = ip->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define min(a, b) ((a) < (b) ? (a) : (b))
|
||||||
|
|
||||||
int
|
int
|
||||||
readi(struct inode *ip, char *dst, uint off, uint n)
|
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;
|
return target - n;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MIN(a, b) ((a < b) ? a : b)
|
|
||||||
|
|
||||||
int
|
int
|
||||||
writei(struct inode *ip, char *addr, uint off, uint n)
|
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;
|
if (b <= 0) return r;
|
||||||
ip->addrs[lbn] = b;
|
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));
|
bp = bread(ip->dev, bmap(ip, off / BSIZE));
|
||||||
memmove (bp->data + off % BSIZE, addr, m);
|
memmove (bp->data + off % BSIZE, addr, m);
|
||||||
bwrite (ip->dev, bp, bmap(ip, off/BSIZE));
|
bwrite (ip->dev, bp, bmap(ip, off/BSIZE));
|
||||||
|
@ -476,13 +496,14 @@ mknod(char *cp, short type, short major, short minor)
|
||||||
int
|
int
|
||||||
unlink(char *cp)
|
unlink(char *cp)
|
||||||
{
|
{
|
||||||
int i;
|
struct inode *ip;
|
||||||
struct inode *ip, *dp;
|
struct inode *dp;
|
||||||
struct dirent *ep = 0;
|
struct dirent *ep = 0;
|
||||||
int off;
|
int off;
|
||||||
struct buf *bp = 0;
|
struct buf *bp = 0;
|
||||||
uint pinum;
|
uint pinum;
|
||||||
|
|
||||||
|
|
||||||
if ((ip = namei(cp, &pinum)) == 0) {
|
if ((ip = namei(cp, &pinum)) == 0) {
|
||||||
cprintf("file to be unlinked doesn't exist\n");
|
cprintf("file to be unlinked doesn't exist\n");
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -490,24 +511,10 @@ unlink(char *cp)
|
||||||
|
|
||||||
ip->nlink--;
|
ip->nlink--;
|
||||||
if (ip->nlink > 0) {
|
if (ip->nlink > 0) {
|
||||||
iupdate(ip);
|
iput(ip);
|
||||||
iput(ip); // is this the right order?
|
|
||||||
return 0;
|
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);
|
dp = iget(rootdev, pinum);
|
||||||
for(off = 0; off < dp->size; off += BSIZE) {
|
for(off = 0; off < dp->size; off += BSIZE) {
|
||||||
bp = bread(dp->dev, bmap(dp, off / BSIZE));
|
bp = bread(dp->dev, bmap(dp, off / BSIZE));
|
||||||
|
@ -526,8 +533,8 @@ unlink(char *cp)
|
||||||
ep->inum = 0;
|
ep->inum = 0;
|
||||||
bwrite (dp->dev, bp, bmap(dp, off/BSIZE)); // write directory block
|
bwrite (dp->dev, bp, bmap(dp, off/BSIZE)); // write directory block
|
||||||
brelse(bp);
|
brelse(bp);
|
||||||
iput(ip);
|
|
||||||
iupdate (dp);
|
iupdate (dp);
|
||||||
iput(dp);
|
iput(dp);
|
||||||
|
iput(ip);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue