unlink(2) bug on tmpfs のパッチ2009年02月03日 23時52分10秒

unlink(2) のバグは、tmpfs_dir_search がファイル名を見ずに探していること。tmpfs_dir_lookup がそれを行なっている。しかし、それだと計算量が増えて、折角の高速化のために書かれた tmpfs_dir_search が無駄になってしまう。そこで、二つの関数を合わせた物を作った。

以下のがパッチだ。



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 のスクリプトが正しい結果を出すようになった。

前回

コメント

コメントをどうぞ

※メールアドレスとURLの入力は必須ではありません。 入力されたメールアドレスは記事に反映されず、ブログの管理者のみが参照できます。

※なお、送られたコメントはブログの管理者が確認するまで公開されません。

名前:
メールアドレス:
URL:
コメント:

トラックバック

このエントリのトラックバックURL: http://uyota.asablo.jp/blog/2009/02/03/4098542/tb

※なお、送られたトラックバックはブログの管理者が確認するまで公開されません。