diff options
| author | Robert Morris <rtm@csail.mit.edu> | 2019-06-06 10:38:11 -0400 | 
|---|---|---|
| committer | Robert Morris <rtm@csail.mit.edu> | 2019-06-06 10:38:11 -0400 | 
| commit | 8607051b5fc79fffa319b913b19e99bc5b90e063 (patch) | |
| tree | 53e4198c3768a90a5c3b88ccae965f6904c6a28e | |
| parent | 31ef85f55280b8cef6b71831ddffef1fb292c32e (diff) | |
| download | xv6-labs-8607051b5fc79fffa319b913b19e99bc5b90e063.tar.gz xv6-labs-8607051b5fc79fffa319b913b19e99bc5b90e063.tar.bz2 xv6-labs-8607051b5fc79fffa319b913b19e99bc5b90e063.zip | |
fix a create()/unlink() deadlock
| -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);  } | 
