summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Morris <[email protected]>2017-08-08 14:19:54 -0400
committerRobert Morris <[email protected]>2017-08-08 14:19:54 -0400
commita4ee6f7de32bfbd73499ac7da19e69ad0741e993 (patch)
tree63fd31d3aeaab27ac2f271650964658c4347eb2d
parent1c7aa960051d7bf382e1af73b1a12cf28b295de2 (diff)
downloadxv6-labs-a4ee6f7de32bfbd73499ac7da19e69ad0741e993.tar.gz
xv6-labs-a4ee6f7de32bfbd73499ac7da19e69ad0741e993.tar.bz2
xv6-labs-a4ee6f7de32bfbd73499ac7da19e69ad0741e993.zip
fix iput() to more obviously avoid deadlock
-rw-r--r--fs.c16
1 files changed, 9 insertions, 7 deletions
diff --git a/fs.c b/fs.c
index 67616a4..8bec001 100644
--- a/fs.c
+++ b/fs.c
@@ -329,20 +329,22 @@ iunlock(struct inode *ip)
void
iput(struct inode *ip)
{
- acquire(&icache.lock);
- if(ip->ref == 1){
- acquiresleep(&ip->lock);
- if(ip->valid && ip->nlink == 0){
+ acquiresleep(&ip->lock);
+ if(ip->valid && ip->nlink == 0){
+ acquire(&icache.lock);
+ int r = ip->ref;
+ release(&icache.lock);
+ if(r == 1){
// inode has no links and no other references: truncate and free.
- release(&icache.lock);
itrunc(ip);
ip->type = 0;
iupdate(ip);
ip->valid = 0;
- acquire(&icache.lock);
}
- releasesleep(&ip->lock);
}
+ releasesleep(&ip->lock);
+
+ acquire(&icache.lock);
ip->ref--;
release(&icache.lock);
}