kern/131356: [tmpfs][patch] unlink(2) on tmpfs removs wrong files
with hard-links
Yoshihiro Ota
ota at j.email.ne.jp
Wed Feb 4 01:50:04 PST 2009
>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 at 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:
More information about the freebsd-bugs
mailing list