+ inode = file->inode;
+
+ /*
+ * Prevent dead lock.
+ * This happened when process is terminated while blocking on read.
+ * In that case, the process is still holding the inode lock and it
+ will never get released.
+ * The unlocking should also include ownership check.
+ *
+ * To see why, consider two process both open the same file both with
+ * fd=x.
+ * Process A: busy on reading x
+ * Process B: do nothing with x
+ * Assuming that, after a very short time, process B get terminated
+ * while process A is still busy in it's reading business. By this
+ * design, the inode lock of this file x is get released by B rather
+ * than A. And this will cause a probable race condition on A if other
+ * process is writing to this file later after B exit.
+ */
+
+ mutex_unlock_for(&inode->lock, pid);
+
+ if (file->ref_count > 1) {
+ atomic_fetch_sub(&file->ref_count, 1);
+ return 0;
+ }
+
+ if ((errno = file->ops->close(file))) {
+ goto done;
+ }
+
+ atomic_fetch_sub(&file->dnode->ref_count, 1);
+ mnt_chillax(file->dnode->mnt);
+ cake_release(file_pile, file);
+
+ /*
+ if the current inode is not being locked by other
+ threads that does not share same open context,
+ then we can try to do sync opportunistically
+ */
+ if (mutex_on_hold(&inode->lock)) {
+ goto done;
+ }
+
+ lock_inode(inode);
+
+ pcache_commit_all(inode);
+ inode->open_count--;
+
+ if (!inode->open_count) {
+ __sync_inode_nolock(inode);