From owner-freebsd-hackers Fri May 10 13:13:31 2002 Delivered-To: freebsd-hackers@freebsd.org Received: from viola.sinor.ru (viola.sinor.ru [217.70.106.9]) by hub.freebsd.org (Postfix) with ESMTP id 0E71637B405; Fri, 10 May 2002 13:13:09 -0700 (PDT) Received: from tlg5-ppp59.sibnet.ru (tlg5-ppp59.sibnet.ru [217.70.97.60]) by viola.sinor.ru (8.9.3/8.9.3) with ESMTP id DAA05084; Sat, 11 May 2002 03:13:01 +0700 Date: Sat, 11 May 2002 03:12:56 +0700 (NOVST) From: "Semen A. Ustimenko" X-X-Sender: semenu@def.the.net To: freebsd-fs@FreeBSD.org Cc: freebsd-hackers@FreeBSD.org, "Flood, Jim" Subject: NULLFS-related possible deadlock + fix proposal Message-ID: <20020511005932.S1705-100000@def.the.net> MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Sender: owner-freebsd-hackers@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG Hi! Preface: Same directory is null-mounted to "/mnt" and "/mnt2". The directory contain "dir/foofile". Two processes concurently lookup "/mnt/dir/foofile" and "/mnt2/dir/foofile". Action: P1: in lookup(): in VOP_LOOKUP(dvp (== "/mnt/dir"), "foofile"): in null_lookup(): in null_node_create(): in malloc() | getnewvnode() | somewhere(): in tsleep() -> P1 is preempted by P2 (Note, that "foofile"'s lower vnode is locked by P1, "dir"'s lower vnode is unlocked, thus "/mnt2/dir" is also unlocked) P2: in lookup(): in VOP_LOOKUP(dvp (== "/mnt2/dir"), "foofile): in null_lookup(): in VOP_LOOKUP(lowerdvp, "foofile"): in tsleep(), waiting for "foofile"'s lower vnode, held by P1 (Note, the "/mnt2/dir"'s vnode and thus its lower vnode is still locked by P2, the "foofile"'s lower vnode is locked by P1) P1: in lookup(): in vrele(dvp (== "/mnt/dir")): in vn_lock(dvp): in tsleep(), waiting for "/mnt/dir"'s lower vnode, held by P2 DEADLOCK... Analysis: The lookup() routine can call vrele(), in its turn vrele() can vn_lock() parent directory, while holding lock on file from this directory. This isn't a problem for nonstacking FSes as vrele() will only vn_lock if it were the last reference. For NULLFS this is a problem because completely different vnodes can share the lock structure. Solution: Make vn_lock() in vrele() lock vnode only LK_THISLAYER. Obviously, the NULLFS and other stacking FSes will have to deal with this in their VOP_INACTIVE() handlers. This changes won't touch real FSes as they ignore the LK_THISLAYER, don't they? Bye! To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-hackers" in the body of the message