From owner-freebsd-bugs@FreeBSD.ORG Wed Feb 4 09:50:03 2009 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 2D9EF106571E for ; Wed, 4 Feb 2009 09:50:03 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id 05B3B8FC16 for ; Wed, 4 Feb 2009 09:50:03 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.14.3/8.14.3) with ESMTP id n149o2xJ010302 for ; Wed, 4 Feb 2009 09:50:02 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.3/8.14.3/Submit) id n149o2K1010296; Wed, 4 Feb 2009 09:50:02 GMT (envelope-from gnats) Resent-Date: Wed, 4 Feb 2009 09:50:02 GMT Resent-Message-Id: <200902040950.n149o2K1010296@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Yoshihiro Ota Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 0F31A106564A for ; Wed, 4 Feb 2009 09:42:29 +0000 (UTC) (envelope-from nobody@FreeBSD.org) Received: from www.freebsd.org (www.freebsd.org [IPv6:2001:4f8:fff6::21]) by mx1.freebsd.org (Postfix) with ESMTP id E61CB8FC1B for ; Wed, 4 Feb 2009 09:42:28 +0000 (UTC) (envelope-from nobody@FreeBSD.org) Received: from www.freebsd.org (localhost [127.0.0.1]) by www.freebsd.org (8.14.3/8.14.3) with ESMTP id n149gSrk045798 for ; Wed, 4 Feb 2009 09:42:28 GMT (envelope-from nobody@www.freebsd.org) Received: (from nobody@localhost) by www.freebsd.org (8.14.3/8.14.3/Submit) id n149gS0g045796; Wed, 4 Feb 2009 09:42:28 GMT (envelope-from nobody) Message-Id: <200902040942.n149gS0g045796@www.freebsd.org> Date: Wed, 4 Feb 2009 09:42:28 GMT From: Yoshihiro Ota To: freebsd-gnats-submit@FreeBSD.org X-Send-Pr-Version: www-3.1 Cc: Subject: kern/131356: [tmpfs][patch] unlink(2) on tmpfs removs wrong files with hard-links X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 04 Feb 2009 09:50:04 -0000 >Number: 131356 >Category: kern >Synopsis: [tmpfs][patch] unlink(2) on tmpfs removs wrong files with hard-links >Confidential: no >Severity: non-critical >Priority: high >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: current-users >Arrival-Date: Wed Feb 04 09:50:02 UTC 2009 >Closed-Date: >Last-Modified: >Originator: Yoshihiro Ota >Release: 7.1-RELEASE >Organization: >Environment: %uname -a FreeBSD xxxx 7.1-RELEASE-p2 FreeBSD 7.1-RELEASE-p2 #455: Sun Jan 18 14:49:21 EST 2009 root@xxxx:/usr/obj/usr/src/sys/GENERIC i386 >Description: rm/unlink removes the first i-node entry specified but not by the same. In the case below, "rm b" deletes file "a" where "a" and "b" are hard-linked and "a" is created first. >How-To-Repeat: % cat unlink.sh #!/bin/sh echo @ cleaning rm -rf a b echo @ file is created and linked echo "123" > a ln a b echo @ a and b should exist ls -lsa head a b echo @ b is removed #unlink b rm b echo @ only a should exist ls -lsa head a b On TMPFS: % cd /mnt/tmpfs % sh unlink.sh @ cleaning @ file is created and linked @ a and b should exist total 18 4 drwxrwxrwx 3 root wheel 80 1 31 04:26 . 2 drwxr-xr-x 19 root wheel 512 12 29 10:07 .. 4 -rw-r--r-- 2 uyota wheel 4 1 31 04:26 a 4 -rw-r--r-- 2 uyota wheel 4 1 31 04:26 b ==> a <== 123 ==> b <== 123 @ b is removed @ only a should exist total 14 4 drwxrwxrwx 3 root wheel 60 1 31 04:26 . 2 drwxr-xr-x 19 root wheel 512 12 29 10:07 .. 4 -rw-r--r-- 1 uyota wheel 4 1 31 04:26 b ==> a <== 123 ==> b <== 123 On UFS: % cd /mnt/ufs % sh unlink.sh @ cleaning @ file is created and linked @ a and b should exist total 8 2 drwxr-xr-x 2 uyota wheel 512 1 31 04:27 . 2 drwxrwxrwt 15 root wheel 512 1 31 04:27 .. 2 -rw-r--r-- 2 uyota wheel 4 1 31 04:27 a 2 -rw-r--r-- 2 uyota wheel 4 1 31 04:27 b ==> a <== 123 ==> b <== 123 @ b is removed @ only a should exist total 6 2 drwxr-xr-x 2 uyota wheel 512 1 31 04:27 . 2 drwxrwxrwt 15 root wheel 512 1 31 04:27 .. 2 -rw-r--r-- 1 uyota wheel 4 1 31 04:27 a ==> a <== 123 >Fix: Patch is attached. It replaces tmpfs_dir_search with a new version of tmpfs_dir_lookup. Patch attached with submission follows: Index: sys/fs/tmpfs/tmpfs.h =================================================================== RCS file: /home/ncvs/src/sys/fs/tmpfs/tmpfs.h,v retrieving revision 1.11.2.3.2.1 diff -u -u -r1.11.2.3.2.1 tmpfs.h --- sys/fs/tmpfs/tmpfs.h 25 Nov 2008 02:59:29 -0000 1.11.2.3.2.1 +++ sys/fs/tmpfs/tmpfs.h 4 Feb 2009 07:14:05 -0000 @@ -408,9 +408,8 @@ void tmpfs_dir_attach(struct vnode *, struct tmpfs_dirent *); void tmpfs_dir_detach(struct vnode *, struct tmpfs_dirent *); struct tmpfs_dirent * tmpfs_dir_lookup(struct tmpfs_node *node, + struct tmpfs_node *f, struct componentname *cnp); -struct tmpfs_dirent *tmpfs_dir_search(struct tmpfs_node *node, - struct tmpfs_node *f); int tmpfs_dir_getdotdent(struct tmpfs_node *, struct uio *); int tmpfs_dir_getdotdotdent(struct tmpfs_node *, struct uio *); struct tmpfs_dirent * tmpfs_dir_lookupbycookie(struct tmpfs_node *, off_t); Index: sys/fs/tmpfs/tmpfs_subr.c =================================================================== RCS file: /home/ncvs/src/sys/fs/tmpfs/tmpfs_subr.c,v retrieving revision 1.12.2.3.2.1 diff -u -u -r1.12.2.3.2.1 tmpfs_subr.c --- sys/fs/tmpfs/tmpfs_subr.c 25 Nov 2008 02:59:29 -0000 1.12.2.3.2.1 +++ sys/fs/tmpfs/tmpfs_subr.c 4 Feb 2009 07:14:07 -0000 @@ -572,7 +572,8 @@ * Returns a pointer to the entry when found, otherwise NULL. */ struct tmpfs_dirent * -tmpfs_dir_lookup(struct tmpfs_node *node, struct componentname *cnp) +tmpfs_dir_lookup(struct tmpfs_node *node, struct tmpfs_node *f, + struct componentname *cnp) { boolean_t found; struct tmpfs_dirent *de; @@ -584,6 +585,8 @@ found = 0; TAILQ_FOREACH(de, &node->tn_dir.tn_dirhead, td_entries) { + if (f != NULL && de->td_node != f) + continue; MPASS(cnp->cn_namelen < 0xffff); if (de->td_namelen == (uint16_t)cnp->cn_namelen && memcmp(de->td_name, cnp->cn_nameptr, de->td_namelen) == 0) { @@ -596,20 +599,6 @@ return found ? de : NULL; } -struct tmpfs_dirent * -tmpfs_dir_search(struct tmpfs_node *node, struct tmpfs_node *f) -{ - struct tmpfs_dirent *de; - - TMPFS_VALIDATE_DIR(node); - node->tn_status |= TMPFS_NODE_ACCESSED; - TAILQ_FOREACH(de, &node->tn_dir.tn_dirhead, td_entries) { - if (de->td_node == f) - return (de); - } - return (NULL); -} - /* --------------------------------------------------------------------- */ /* Index: sys/fs/tmpfs/tmpfs_vnops.c =================================================================== RCS file: /home/ncvs/src/sys/fs/tmpfs/tmpfs_vnops.c,v retrieving revision 1.11.2.4.2.1 diff -u -u -r1.11.2.4.2.1 tmpfs_vnops.c --- sys/fs/tmpfs/tmpfs_vnops.c 25 Nov 2008 02:59:29 -0000 1.11.2.4.2.1 +++ sys/fs/tmpfs/tmpfs_vnops.c 4 Feb 2009 07:14:07 -0000 @@ -104,7 +104,7 @@ *vpp = dvp; error = 0; } else { - de = tmpfs_dir_lookup(dnode, cnp); + de = tmpfs_dir_lookup(dnode, NULL, cnp); if (de == NULL) { /* The entry was not found in the directory. * This is OK if we are creating or renaming an @@ -775,7 +775,7 @@ dnode = VP_TO_TMPFS_DIR(dvp); node = VP_TO_TMPFS_NODE(vp); tmp = VFS_TO_TMPFS(vp->v_mount); - de = tmpfs_dir_search(dnode, node); + de = tmpfs_dir_lookup(dnode, node, v->a_cnp); MPASS(de != NULL); /* Files marked as immutable or append-only cannot be deleted. */ @@ -922,7 +922,7 @@ } fdnode = VP_TO_TMPFS_DIR(fdvp); fnode = VP_TO_TMPFS_NODE(fvp); - de = tmpfs_dir_search(fdnode, fnode); + de = tmpfs_dir_lookup(fdnode, fnode, fcnp); /* Avoid manipulating '.' and '..' entries. */ if (de == NULL) { @@ -1034,7 +1034,7 @@ * from the target directory. */ if (tvp != NULL) { /* Remove the old entry from the target directory. */ - de = tmpfs_dir_search(tdnode, tnode); + de = tmpfs_dir_lookup(tdnode, tnode, tcnp); tmpfs_dir_detach(tdvp, de); /* Free the directory entry we just deleted. Note that the @@ -1122,7 +1122,7 @@ /* Get the directory entry associated with node (vp). This was * filled by tmpfs_lookup while looking up the entry. */ - de = tmpfs_dir_search(dnode, node); + de = tmpfs_dir_lookup(dnode, node, v->a_cnp); MPASS(TMPFS_DIRENT_MATCHES(de, v->a_cnp->cn_nameptr, v->a_cnp->cn_namelen)); >Release-Note: >Audit-Trail: >Unformatted: