Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/fs/tmpfs Finish and enable whiteout support for tmpfs:



details:   https://anonhg.NetBSD.org/src/rev/a9ebba7abcd5
branches:  trunk
changeset: 768781:a9ebba7abcd5
user:      hannken <hannken%NetBSD.org@localhost>
date:      Sat Aug 27 15:32:28 2011 +0000

description:
Finish and enable whiteout support for tmpfs:

- Enable VOP tmpfs_whiteout().
- Support ISWHITEOUT in tmpfs_alloc_file().
- Support DOWHITEOUT in tmpfs_remove() and tmpfs_rmdir().
- Make rmdir on a directory containing whiteouts working.

Should fix PR #35112 (tmpfs doesn't play well with unionfs).

diffstat:

 sys/fs/tmpfs/tmpfs_subr.c  |  20 +++++++++++++++---
 sys/fs/tmpfs/tmpfs_vnops.c |  49 +++++++++++++++++++++++++++++++--------------
 2 files changed, 50 insertions(+), 19 deletions(-)

diffs (170 lines):

diff -r b574a3eaba06 -r a9ebba7abcd5 sys/fs/tmpfs/tmpfs_subr.c
--- a/sys/fs/tmpfs/tmpfs_subr.c Sat Aug 27 15:08:58 2011 +0000
+++ b/sys/fs/tmpfs/tmpfs_subr.c Sat Aug 27 15:32:28 2011 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: tmpfs_subr.c,v 1.76 2011/06/30 00:37:07 enami Exp $    */
+/*     $NetBSD: tmpfs_subr.c,v 1.77 2011/08/27 15:32:28 hannken Exp $  */
 
 /*
  * Copyright (c) 2005-2011 The NetBSD Foundation, Inc.
@@ -74,7 +74,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tmpfs_subr.c,v 1.76 2011/06/30 00:37:07 enami Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tmpfs_subr.c,v 1.77 2011/08/27 15:32:28 hannken Exp $");
 
 #include <sys/param.h>
 #include <sys/dirent.h>
@@ -343,7 +343,7 @@
 {
        tmpfs_mount_t *tmp = VFS_TO_TMPFS(dvp->v_mount);
        tmpfs_node_t *dnode = VP_TO_TMPFS_DIR(dvp), *node;
-       tmpfs_dirent_t *de;
+       tmpfs_dirent_t *de, *wde;
        int error;
 
        KASSERT(VOP_ISLOCKED(dvp));
@@ -381,8 +381,20 @@
                goto out;
        }
 
+       /* Remove whiteout before adding the new entry. */
+       if (cnp->cn_flags & ISWHITEOUT) {
+               wde = tmpfs_dir_lookup(dnode, cnp);
+               KASSERT(wde != NULL && wde->td_node == TMPFS_NODE_WHITEOUT);
+               tmpfs_dir_detach(dvp, wde);
+               tmpfs_free_dirent(tmp, wde);
+       }
+
        /* Associate inode and attach the entry into the directory. */
        tmpfs_dir_attach(dvp, de, node);
+
+       /* Make node opaque if requested. */
+       if (cnp->cn_flags & ISWHITEOUT)
+               node->tn_flags |= UF_OPAQUE;
 out:
        vput(dvp);
        return error;
@@ -444,8 +456,8 @@
        KASSERT(VOP_ISLOCKED(dvp));
 
        /* Associate directory entry and the inode. */
+       de->td_node = node;
        if (node != TMPFS_NODE_WHITEOUT) {
-               de->td_node = node;
                KASSERT(node->tn_links < LINK_MAX);
                node->tn_links++;
 
diff -r b574a3eaba06 -r a9ebba7abcd5 sys/fs/tmpfs/tmpfs_vnops.c
--- a/sys/fs/tmpfs/tmpfs_vnops.c        Sat Aug 27 15:08:58 2011 +0000
+++ b/sys/fs/tmpfs/tmpfs_vnops.c        Sat Aug 27 15:32:28 2011 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: tmpfs_vnops.c,v 1.89 2011/08/18 21:42:18 riastradh Exp $       */
+/*     $NetBSD: tmpfs_vnops.c,v 1.90 2011/08/27 15:32:28 hannken Exp $ */
 
 /*
  * Copyright (c) 2005, 2006, 2007 The NetBSD Foundation, Inc.
@@ -35,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tmpfs_vnops.c,v 1.89 2011/08/18 21:42:18 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tmpfs_vnops.c,v 1.90 2011/08/27 15:32:28 hannken Exp $");
 
 #include <sys/param.h>
 #include <sys/dirent.h>
@@ -103,9 +103,7 @@
        { &vop_bwrite_desc,             tmpfs_bwrite },
        { &vop_getpages_desc,           tmpfs_getpages },
        { &vop_putpages_desc,           tmpfs_putpages },
-#if TMPFS_WHITEOUT
        { &vop_whiteout_desc,           tmpfs_whiteout },
-#endif
        { NULL, NULL }
 };
 
@@ -713,11 +711,15 @@
 
        /*
         * Remove the entry from the directory (drops the link count) and
-        * destroy it.  Note: the inode referred by it will not be destroyed
+        * destroy it or replace it with a whiteout.
+        * Note: the inode referred by it will not be destroyed
         * until the vnode is reclaimed/recycled.
         */
        tmpfs_dir_detach(dvp, de);
-       tmpfs_free_dirent(VFS_TO_TMPFS(vp->v_mount), de);
+       if (ap->a_cnp->cn_flags & DOWHITEOUT)
+               tmpfs_dir_attach(dvp, de, TMPFS_NODE_WHITEOUT);
+       else
+               tmpfs_free_dirent(VFS_TO_TMPFS(vp->v_mount), de);
        error = 0;
 out:
        /* Drop the references and unlock the vnodes. */
@@ -2103,12 +2105,19 @@
        KASSERT(node->tn_spec.tn_dir.tn_parent == dnode);
 
        /*
-        * Directories with more than two entries ('.' and '..') cannot
-        * be removed.
+        * Directories with more than two non-whiteout
+        * entries ('.' and '..') cannot be removed.
         */
        if (node->tn_size > 0) {
-               error = ENOTEMPTY;
-               goto out;
+               KASSERT(error == 0);
+               TAILQ_FOREACH(de, &node->tn_spec.tn_dir.tn_dir, td_entries) {
+                       if (de->td_node != TMPFS_NODE_WHITEOUT) {
+                               error = ENOTEMPTY;
+                               break;
+                       }
+               }
+               if (error)
+                       goto out;
        }
 
        /* Lookup the directory entry (check the cached hint first). */
@@ -2136,10 +2145,22 @@
        cache_purge(dvp);
 
        /*
-        * Destroy the directory entry.  Note: the inode referred by it
-        * will not be destroyed until the vnode is reclaimed.
+        * Destroy the directory entry or replace it with a whiteout.
+        * Note: the inode referred by it will not be destroyed
+        * until the vnode is reclaimed.
         */
-       tmpfs_free_dirent(tmp, de);
+       if (ap->a_cnp->cn_flags & DOWHITEOUT)
+               tmpfs_dir_attach(dvp, de, TMPFS_NODE_WHITEOUT);
+       else
+               tmpfs_free_dirent(tmp, de);
+
+       /* Destroy the whiteout entries from the node. */
+       while ((de = TAILQ_FIRST(&node->tn_spec.tn_dir.tn_dir)) != NULL) {
+               KASSERT(de->td_node == TMPFS_NODE_WHITEOUT);
+               tmpfs_dir_detach(vp, de);
+               tmpfs_free_dirent(tmp, de);
+       }
+
        KASSERT(node->tn_links == 0);
 out:
        /* Release the nodes. */
@@ -2507,7 +2528,6 @@
        return error;
 }
 
-#ifdef TMPFS_WHITEOUT
 int
 tmpfs_whiteout(void *v)
 {
@@ -2544,7 +2564,6 @@
        }
        return 0;
 }
-#endif
 
 int
 tmpfs_print(void *v)



Home | Main Index | Thread Index | Old Index