kernel - Fix recursive lockmgr lock panic when creating a hardlink
authorMatthew Dillon <dillon@apollo.backplane.com>
Fri, 4 Dec 2009 22:32:48 +0000 (14:32 -0800)
committerMatthew Dillon <dillon@apollo.backplane.com>
Fri, 4 Dec 2009 22:32:48 +0000 (14:32 -0800)
* 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>
sys/kern/vfs_syscalls.c

index b8f19f3..4862ddd 100644 (file)
@@ -2100,16 +2100,21 @@ kern_link(struct nlookupdata *nd, struct nlookupdata *linknd)
        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.