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).
This commit is contained in:
parent
6839411995
commit
f68873a343
@ -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_alloc_file(vnode_t *dvp, vnode_t **vpp, struct vattr *vap,
|
||||
{
|
||||
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 @@ tmpfs_alloc_file(vnode_t *dvp, vnode_t **vpp, struct vattr *vap,
|
||||
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 @@ tmpfs_dir_attach(vnode_t *dvp, tmpfs_dirent_t *de, tmpfs_node_t *node)
|
||||
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++;
|
||||
|
||||
|
@ -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 @@ const struct vnodeopv_entry_desc tmpfs_vnodeop_entries[] = {
|
||||
{ &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 @@ tmpfs_remove(void *v)
|
||||
|
||||
/*
|
||||
* 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 @@ tmpfs_rmdir(void *v)
|
||||
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 @@ tmpfs_rmdir(void *v)
|
||||
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 @@ tmpfs_putpages(void *v)
|
||||
return error;
|
||||
}
|
||||
|
||||
#ifdef TMPFS_WHITEOUT
|
||||
int
|
||||
tmpfs_whiteout(void *v)
|
||||
{
|
||||
@ -2544,7 +2564,6 @@ tmpfs_whiteout(void *v)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
tmpfs_print(void *v)
|
||||
|
Loading…
Reference in New Issue
Block a user