diff options
author | Robert Morris <[email protected]> | 2019-06-06 10:38:11 -0400 |
---|---|---|
committer | Robert Morris <[email protected]> | 2019-06-06 10:38:11 -0400 |
commit | 8607051b5fc79fffa319b913b19e99bc5b90e063 (patch) | |
tree | 53e4198c3768a90a5c3b88ccae965f6904c6a28e /fs.c | |
parent | 31ef85f55280b8cef6b71831ddffef1fb292c32e (diff) | |
download | xv6-labs-8607051b5fc79fffa319b913b19e99bc5b90e063.tar.gz xv6-labs-8607051b5fc79fffa319b913b19e99bc5b90e063.tar.bz2 xv6-labs-8607051b5fc79fffa319b913b19e99bc5b90e063.zip |
fix a create()/unlink() deadlock
Diffstat (limited to 'fs.c')
-rw-r--r-- | fs.c | 31 |
1 files changed, 18 insertions, 13 deletions
@@ -330,22 +330,27 @@ iunlock(struct inode *ip) void iput(struct inode *ip) { - acquiresleep(&ip->lock); - if(ip->valid && ip->nlink == 0){ - acquire(&icache.lock); - int r = ip->ref; + acquire(&icache.lock); + + if(ip->ref == 1 && ip->valid && ip->nlink == 0){ + // inode has no links and no other references: truncate and free. + + // ip->ref == 1 means no other process can have ip locked, + // so this acquiresleep() won't block (or deadlock). + acquiresleep(&ip->lock); + release(&icache.lock); - if(r == 1){ - // inode has no links and no other references: truncate and free. - itrunc(ip); - ip->type = 0; - iupdate(ip); - ip->valid = 0; - } + + itrunc(ip); + ip->type = 0; + iupdate(ip); + ip->valid = 0; + + releasesleep(&ip->lock); + + acquire(&icache.lock); } - releasesleep(&ip->lock); - acquire(&icache.lock); ip->ref--; release(&icache.lock); } |