From: Matthew Dillon Date: Mon, 9 Mar 2015 22:54:11 +0000 (-0700) Subject: hammer - Fix a vsetisdirty() race X-Git-Tag: v4.2.0rc~631 X-Git-Url: https://gitweb.dragonflybsd.org/~tuxillo/dragonfly.git/commitdiff_plain/43a7f9ab8995e4a9e00d6c76d6f61b7d5f707d00 hammer - Fix a vsetisdirty() race * Fix a vsetisdirty() race which can result in a panic by holding a lock around the operation. Reported-by: tuxillo --- diff --git a/sys/vfs/hammer/hammer_inode.c b/sys/vfs/hammer/hammer_inode.c index b3e91fc28a..717f199f50 100644 --- a/sys/vfs/hammer/hammer_inode.c +++ b/sys/vfs/hammer/hammer_inode.c @@ -2573,8 +2573,21 @@ hammer_flush_inode_done(hammer_inode_t ip, int error) } else { ip->flags &= ~HAMMER_INODE_REFLUSH; } - if (ip->flags & HAMMER_INODE_MODMASK) + + /* + * The fs token is held but the inode lock is not held. Because this + * is a backend flush it is possible that the vnode has no references + * and cause a reclaim race inside vsetisdirty() if/when it blocks. + * + * Therefore, we must lock the inode around this particular dirtying + * operation. We don't have to around other dirtying operations + * where the vnode is implicitly or explicitly held. + */ + if (ip->flags & HAMMER_INODE_MODMASK) { + hammer_lock_ex(&ip->lock); hammer_inode_dirty(ip); + hammer_unlock(&ip->lock); + } /* * Adjust the flush state.