Module Name: src
Committed By: hannken
Date: Sat Aug 27 15:32:28 UTC 2011
Modified Files:
src/sys/fs/tmpfs: tmpfs_subr.c tmpfs_vnops.c
Log Message:
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).
To generate a diff of this commit:
cvs rdiff -u -r1.76 -r1.77 src/sys/fs/tmpfs/tmpfs_subr.c
cvs rdiff -u -r1.89 -r1.90 src/sys/fs/tmpfs/tmpfs_vnops.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/fs/tmpfs/tmpfs_subr.c
diff -u src/sys/fs/tmpfs/tmpfs_subr.c:1.76 src/sys/fs/tmpfs/tmpfs_subr.c:1.77
--- src/sys/fs/tmpfs/tmpfs_subr.c:1.76 Thu Jun 30 00:37:07 2011
+++ src/sys/fs/tmpfs/tmpfs_subr.c Sat Aug 27 15:32:28 2011
@@ -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++;
Index: src/sys/fs/tmpfs/tmpfs_vnops.c
diff -u src/sys/fs/tmpfs/tmpfs_vnops.c:1.89 src/sys/fs/tmpfs/tmpfs_vnops.c:1.90
--- src/sys/fs/tmpfs/tmpfs_vnops.c:1.89 Thu Aug 18 21:42:18 2011
+++ src/sys/fs/tmpfs/tmpfs_vnops.c Sat Aug 27 15:32:28 2011
@@ -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)