unlink(2) bug on tmpfs のパッチ ― 2009年02月03日 23時52分10秒
以下のがパッチだ。
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));
古い tmpfs_dir_lookup を使っているところは一つしかない。tmpfs_dir_search を改造したものとほぼ同じになる為、ほぼ同じ関数を二つのも手間が増えると思い、tmpfs_node に NULL を渡した時は、無視するようにした。そして、問題のある箇所は二つ。unlink(2) と時に呼ばれる tmpfs_remove と rename(2) と時に呼ばれる tmpfs_rename の時だ。ディレクトリはハードリンクを作ることが出来ないので、この問題に遭遇するとはない。
これで、unlink.sh のスクリプトが正しい結果を出すようになった。
前回。
最近のコメント