* HAMMER uses non-recursive vnode locks. Fix a case where attempting
to hardlink A to B where both already exist and point to the same
inode can result in a panic if B is not in the namecache.
HAMMER must temporarily lock the vnode it returns in the resolver
and kern_link() was already holding A locked. This all occurs
before kern_link() is able to check whether A and B are the same
so it can't be avoided.
Solve the problem by unlocking A while resolving B.
Reported-by: Goetz Isenmann <info@goetz-isenmann.de>
KKASSERT(nd->nl_flags & NLC_NCPISLOCKED);
nd->nl_flags &= ~NLC_NCPISLOCKED;
cache_unlock(&nd->nl_nch);
+ vn_unlock(vp);
linknd->nl_flags |= NLC_CREATE | NLC_REFDVP;
if ((error = nlookup(linknd)) != 0) {
- vput(vp);
+ vrele(vp);
return (error);
}
if (linknd->nl_nch.ncp->nc_vp) {
- vput(vp);
+ vrele(vp);
return (EEXIST);
}
+ if ((error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY)) != 0) {
+ vrele(vp);
+ return (error);
+ }
/*
* Finally run the new API VOP.