PERFORCE change 127977 for review
John Birrell
jb at FreeBSD.org
Tue Oct 23 14:58:49 PDT 2007
http://perforce.freebsd.org/chv.cgi?CH=127977
Change 127977 by jb at jb_freebsd1 on 2007/10/23 21:57:58
IF6
Affected files ...
.. //depot/projects/dtrace6/src/sbin/mount_unionfs/mount_unionfs.8#2 integrate
.. //depot/projects/dtrace6/src/sys/ddb/db_command.c#3 integrate
.. //depot/projects/dtrace6/src/sys/fs/nullfs/null_subr.c#2 integrate
.. //depot/projects/dtrace6/src/sys/fs/nullfs/null_vnops.c#2 integrate
.. //depot/projects/dtrace6/src/sys/fs/unionfs/union.h#2 integrate
.. //depot/projects/dtrace6/src/sys/fs/unionfs/union_subr.c#2 integrate
.. //depot/projects/dtrace6/src/sys/fs/unionfs/union_vfsops.c#2 integrate
.. //depot/projects/dtrace6/src/sys/fs/unionfs/union_vnops.c#2 integrate
Differences ...
==== //depot/projects/dtrace6/src/sbin/mount_unionfs/mount_unionfs.8#2 (text+ko) ====
@@ -29,7 +29,7 @@
.\" SUCH DAMAGE.
.\"
.\" @(#)mount_union.8 8.6 (Berkeley) 3/27/94
-.\" $FreeBSD: src/sbin/mount_unionfs/mount_unionfs.8,v 1.20.2.1 2007/02/13 05:56:43 rodrigc Exp $
+.\" $FreeBSD: src/sbin/mount_unionfs/mount_unionfs.8,v 1.20.2.2 2007/10/23 03:37:09 daichi Exp $
.\"
.Dd November 30, 2006
.Dt MOUNT_UNIONFS 8
@@ -98,6 +98,10 @@
mode, see
.Sx MASQUERADE MODE
below.
+.It Sm Cm whiteout No = Cm always | whenneeded Sm
+Specifies whether whiteouts should always be made in the upper layer
+when removing a file or directory or only when it already exists in the
+lower layer.
.It Cm udir Ns = Ns Ar mode
Specifies directory mode bits in octal for
.Cm masquerade
==== //depot/projects/dtrace6/src/sys/ddb/db_command.c#3 (text+ko) ====
@@ -32,7 +32,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/ddb/db_command.c,v 1.60.2.3 2007/10/19 16:48:43 obrien Exp $");
+__FBSDID("$FreeBSD: src/sys/ddb/db_command.c,v 1.60.2.4 2007/10/23 16:07:30 obrien Exp $");
#include <sys/param.h>
#include <sys/linker_set.h>
@@ -75,8 +75,65 @@
static db_cmdfcn_t db_stack_trace_all;
static db_cmdfcn_t db_watchdog;
-/* XXX this is actually forward-static. */
-extern struct command db_show_cmds[];
+/*
+ * 'show' commands
+ */
+
+static struct command db_show_all_cmds[] = {
+ { "procs", db_ps, 0, 0 },
+ { (char *)0 }
+};
+
+static struct command db_show_cmds[] = {
+ { "all", 0, 0, db_show_all_cmds },
+ { "registers", db_show_regs, 0, 0 },
+ { "breaks", db_listbreak_cmd, 0, 0 },
+ { "threads", db_show_threads, 0, 0 },
+ { (char *)0, }
+};
+
+static struct command db_command_table[] = {
+ { "print", db_print_cmd, 0, 0 },
+ { "p", db_print_cmd, 0, 0 },
+ { "examine", db_examine_cmd, CS_SET_DOT, 0 },
+ { "x", db_examine_cmd, CS_SET_DOT, 0 },
+ { "search", db_search_cmd, CS_OWN|CS_SET_DOT, 0 },
+ { "set", db_set_cmd, CS_OWN, 0 },
+ { "write", db_write_cmd, CS_MORE|CS_SET_DOT, 0 },
+ { "w", db_write_cmd, CS_MORE|CS_SET_DOT, 0 },
+ { "delete", db_delete_cmd, 0, 0 },
+ { "d", db_delete_cmd, 0, 0 },
+ { "break", db_breakpoint_cmd, 0, 0 },
+ { "dwatch", db_deletewatch_cmd, 0, 0 },
+ { "watch", db_watchpoint_cmd, CS_MORE,0 },
+ { "dhwatch", db_deletehwatch_cmd, 0, 0 },
+ { "hwatch", db_hwatchpoint_cmd, 0, 0 },
+ { "step", db_single_step_cmd, 0, 0 },
+ { "s", db_single_step_cmd, 0, 0 },
+ { "continue", db_continue_cmd, 0, 0 },
+ { "c", db_continue_cmd, 0, 0 },
+ { "until", db_trace_until_call_cmd,0, 0 },
+ { "next", db_trace_until_matching_cmd,0, 0 },
+ { "match", db_trace_until_matching_cmd,0, 0 },
+ { "trace", db_stack_trace, CS_OWN, 0 },
+ { "alltrace", db_stack_trace_all, 0, 0 },
+ { "where", db_stack_trace, CS_OWN, 0 },
+ { "bt", db_stack_trace, CS_OWN, 0 },
+ { "call", db_fncall, CS_OWN, 0 },
+ { "show", 0, 0, db_show_cmds },
+ { "ps", db_ps, 0, 0 },
+ { "gdb", db_gdb, 0, 0 },
+ { "halt", db_halt, 0, 0 },
+ { "reboot", db_reset, 0, 0 },
+ { "reset", db_reset, 0, 0 },
+ { "kill", db_kill, CS_OWN, 0 },
+ { "watchdog", db_watchdog, 0, 0 },
+ { "thread", db_set_thread, CS_OWN, 0 },
+ { (char *)0, }
+};
+
+static struct command *db_last_command = 0;
+
/*
* if 'ed' style: 'dot' is set at start of last item printed,
@@ -374,65 +431,6 @@
}
/*
- * 'show' commands
- */
-
-static struct command db_show_all_cmds[] = {
- { "procs", db_ps, 0, 0 },
- { (char *)0 }
-};
-
-static struct command db_show_cmds[] = {
- { "all", 0, 0, db_show_all_cmds },
- { "registers", db_show_regs, 0, 0 },
- { "breaks", db_listbreak_cmd, 0, 0 },
- { "threads", db_show_threads, 0, 0 },
- { (char *)0, }
-};
-
-static struct command db_command_table[] = {
- { "print", db_print_cmd, 0, 0 },
- { "p", db_print_cmd, 0, 0 },
- { "examine", db_examine_cmd, CS_SET_DOT, 0 },
- { "x", db_examine_cmd, CS_SET_DOT, 0 },
- { "search", db_search_cmd, CS_OWN|CS_SET_DOT, 0 },
- { "set", db_set_cmd, CS_OWN, 0 },
- { "write", db_write_cmd, CS_MORE|CS_SET_DOT, 0 },
- { "w", db_write_cmd, CS_MORE|CS_SET_DOT, 0 },
- { "delete", db_delete_cmd, 0, 0 },
- { "d", db_delete_cmd, 0, 0 },
- { "break", db_breakpoint_cmd, 0, 0 },
- { "dwatch", db_deletewatch_cmd, 0, 0 },
- { "watch", db_watchpoint_cmd, CS_MORE,0 },
- { "dhwatch", db_deletehwatch_cmd, 0, 0 },
- { "hwatch", db_hwatchpoint_cmd, 0, 0 },
- { "step", db_single_step_cmd, 0, 0 },
- { "s", db_single_step_cmd, 0, 0 },
- { "continue", db_continue_cmd, 0, 0 },
- { "c", db_continue_cmd, 0, 0 },
- { "until", db_trace_until_call_cmd,0, 0 },
- { "next", db_trace_until_matching_cmd,0, 0 },
- { "match", db_trace_until_matching_cmd,0, 0 },
- { "trace", db_stack_trace, CS_OWN, 0 },
- { "alltrace", db_stack_trace_all, 0, 0 },
- { "where", db_stack_trace, CS_OWN, 0 },
- { "bt", db_stack_trace, CS_OWN, 0 },
- { "call", db_fncall, CS_OWN, 0 },
- { "show", 0, 0, db_show_cmds },
- { "ps", db_ps, 0, 0 },
- { "gdb", db_gdb, 0, 0 },
- { "halt", db_halt, 0, 0 },
- { "reboot", db_reset, 0, 0 },
- { "reset", db_reset, 0, 0 },
- { "kill", db_kill, CS_OWN, 0 },
- { "watchdog", db_watchdog, 0, 0 },
- { "thread", db_set_thread, CS_OWN, 0 },
- { (char *)0, }
-};
-
-static struct command *db_last_command = 0;
-
-/*
* At least one non-optional command must be implemented using
* DB_COMMAND() so that db_cmd_set gets created. Here is one.
*/
==== //depot/projects/dtrace6/src/sys/fs/nullfs/null_subr.c#2 (text+ko) ====
@@ -31,7 +31,7 @@
*
* @(#)null_subr.c 8.7 (Berkeley) 5/14/95
*
- * $FreeBSD: src/sys/fs/nullfs/null_subr.c,v 1.48.2.1 2006/03/13 03:05:17 jeff Exp $
+ * $FreeBSD: src/sys/fs/nullfs/null_subr.c,v 1.48.2.2 2007/10/23 03:38:31 daichi Exp $
*/
#include <sys/param.h>
@@ -283,6 +283,7 @@
char *fil;
int lno;
{
+ int interlock = 0;
struct null_node *a = VTONULL(vp);
#ifdef notyet
/*
@@ -306,6 +307,10 @@
while (null_checkvp_barrier) /*WAIT*/ ;
panic("null_checkvp");
}
+ if (mtx_owned(VI_MTX(vp)) != 0) {
+ VI_UNLOCK(vp);
+ interlock = 1;
+ }
if (vrefcnt(a->null_lowervp) < 1) {
int i; u_long *p;
printf("vp = %p, unref'ed lowervp\n", (void *)vp);
@@ -316,6 +321,8 @@
while (null_checkvp_barrier) /*WAIT*/ ;
panic ("null with unref'ed lowervp");
};
+ if (interlock != 0)
+ VI_LOCK(vp);
#ifdef notyet
printf("null %x/%d -> %x/%d [%s, %d]\n",
NULLTOV(a), vrefcnt(NULLTOV(a)),
==== //depot/projects/dtrace6/src/sys/fs/nullfs/null_vnops.c#2 (text+ko) ====
@@ -36,7 +36,7 @@
* ...and...
* @(#)null_vnodeops.c 1.20 92/07/07 UCLA Ficus project
*
- * $FreeBSD: src/sys/fs/nullfs/null_vnops.c,v 1.87.2.3 2006/03/13 03:05:26 jeff Exp $
+ * $FreeBSD: src/sys/fs/nullfs/null_vnops.c,v 1.87.2.4 2007/10/23 03:38:32 daichi Exp $
*/
/*
@@ -587,20 +587,33 @@
{
struct vnode *vp = ap->a_vp;
int flags = ap->a_flags;
+ int mtxlkflag = 0;
struct thread *td = ap->a_td;
struct null_node *nn;
struct vnode *lvp;
int error;
- if ((flags & LK_INTERLOCK) != 0) {
- VI_UNLOCK(vp);
- ap->a_flags = flags &= ~LK_INTERLOCK;
+ if ((flags & LK_INTERLOCK) != 0)
+ mtxlkflag = 1;
+ else if (mtx_owned(VI_MTX(vp)) == 0) {
+ VI_LOCK(vp);
+ mtxlkflag = 2;
}
nn = VTONULL(vp);
- if (nn != NULL && (lvp = NULLVPTOLOWERVP(vp)) != NULL)
+ if (nn != NULL && (lvp = NULLVPTOLOWERVP(vp)) != NULL) {
+ VI_LOCK_FLAGS(lvp, MTX_DUPOK);
+ flags |= LK_INTERLOCK;
+ vholdl(lvp);
+ VI_UNLOCK(vp);
error = VOP_UNLOCK(lvp, flags, td);
- else
+ vdrop(lvp);
+ if (mtxlkflag == 0)
+ VI_LOCK(vp);
+ } else {
+ if (mtxlkflag == 2)
+ VI_UNLOCK(vp);
error = vop_stdunlock(ap);
+ }
return (error);
}
==== //depot/projects/dtrace6/src/sys/fs/unionfs/union.h#2 (text+ko) ====
@@ -33,7 +33,7 @@
* SUCH DAMAGE.
*
* @(#)union.h 8.9 (Berkeley) 12/10/94
- * $FreeBSD: src/sys/fs/unionfs/union.h,v 1.31.2.1 2007/02/13 05:56:42 rodrigc Exp $
+ * $FreeBSD: src/sys/fs/unionfs/union.h,v 1.31.2.3 2007/10/23 03:37:09 daichi Exp $
*/
#ifdef _KERNEL
@@ -45,11 +45,18 @@
UNIONFS_MASQUERADE
} unionfs_copymode;
+/* whiteout policy of upper layer */
+typedef enum _unionfs_whitemode {
+ UNIONFS_WHITE_ALWAYS = 0,
+ UNIONFS_WHITE_WHENNEEDED
+} unionfs_whitemode;
+
struct unionfs_mount {
struct vnode *um_lowervp; /* VREFed once */
struct vnode *um_uppervp; /* VREFed once */
struct vnode *um_rootvp; /* ROOT vnode */
unionfs_copymode um_copymode;
+ unionfs_whitemode um_whitemode;
uid_t um_uid;
gid_t um_gid;
u_short um_udir;
@@ -73,7 +80,6 @@
/* A cache of vnode references */
struct unionfs_node {
- LIST_ENTRY(unionfs_node) un_hash; /* Hash list */
struct vnode *un_lowervp; /* lower side vnode */
struct vnode *un_uppervp; /* upper side vnode */
struct vnode *un_dvp; /* parent unionfs vnode */
@@ -83,10 +89,12 @@
int un_flag; /* unionfs node flag */
};
-/* unionfs node flags */
-#define UNIONFS_CACHED 0x01 /* is cached */
-#define UNIONFS_OPENEXTL 0x02 /* openextattr (lower) */
-#define UNIONFS_OPENEXTU 0x04 /* openextattr (upper) */
+/*
+ * unionfs node flags
+ * It needs the vnode with exclusive lock, when changing the un_flag variable.
+ */
+#define UNIONFS_OPENEXTL 0x01 /* openextattr (lower) */
+#define UNIONFS_OPENEXTU 0x02 /* openextattr (upper) */
#define MOUNTTOUNIONFSMOUNT(mp) ((struct unionfs_mount *)((mp)->mnt_data))
#define VTOUNIONFS(vp) ((struct unionfs_node *)(vp)->v_data)
@@ -95,7 +103,7 @@
int unionfs_init(struct vfsconf *vfsp);
int unionfs_uninit(struct vfsconf *vfsp);
int unionfs_nodeget(struct mount *mp, struct vnode *uppervp, struct vnode *lowervp, struct vnode *dvp, struct vnode **vpp, struct componentname *cnp, struct thread *td);
-void unionfs_hashrem(struct vnode *vp, struct thread *td);
+void unionfs_noderem(struct vnode *vp, struct thread *td);
void unionfs_get_node_status(struct unionfs_node *unp, struct thread *td, struct unionfs_node_status **unspp);
void unionfs_tryrem_node_status(struct unionfs_node *unp, struct thread *td, struct unionfs_node_status *unsp);
==== //depot/projects/dtrace6/src/sys/fs/unionfs/union_subr.c#2 (text+ko) ====
@@ -33,7 +33,7 @@
* SUCH DAMAGE.
*
* @(#)union_subr.c 8.20 (Berkeley) 5/20/95
- * $FreeBSD: src/sys/fs/unionfs/union_subr.c,v 1.86.2.1 2007/02/13 05:56:42 rodrigc Exp $
+ * $FreeBSD: src/sys/fs/unionfs/union_subr.c,v 1.86.2.3 2007/10/23 03:28:22 daichi Exp $
*/
#include <sys/param.h>
@@ -60,135 +60,29 @@
#include <fs/unionfs/union.h>
-#define NUNIONFSNODECACHE 32
-
-#define UNIONFS_NHASH(upper, lower) \
- (&unionfs_node_hashtbl[(((uintptr_t)upper + (uintptr_t)lower) >> 8) & unionfs_node_hash])
-
-static LIST_HEAD(unionfs_node_hashhead, unionfs_node) *unionfs_node_hashtbl;
-static u_long unionfs_node_hash;
-struct mtx unionfs_hashmtx;
-
-static MALLOC_DEFINE(M_UNIONFSHASH, "UNIONFS hash", "UNIONFS hash table");
MALLOC_DEFINE(M_UNIONFSNODE, "UNIONFS node", "UNIONFS vnode private part");
MALLOC_DEFINE(M_UNIONFSPATH, "UNIONFS path", "UNIONFS path private part");
/*
- * Initialize cache headers
+ * Initialize
*/
int
unionfs_init(struct vfsconf *vfsp)
{
UNIONFSDEBUG("unionfs_init\n"); /* printed during system boot */
- unionfs_node_hashtbl = hashinit(NUNIONFSNODECACHE, M_UNIONFSHASH, &unionfs_node_hash);
- mtx_init(&unionfs_hashmtx, "unionfs", NULL, MTX_DEF);
-
return (0);
}
/*
- * Destroy cache headers
+ * Uninitialize
*/
int
unionfs_uninit(struct vfsconf *vfsp)
{
- mtx_destroy(&unionfs_hashmtx);
- free(unionfs_node_hashtbl, M_UNIONFSHASH);
return (0);
}
/*
- * Return a VREF'ed alias for unionfs vnode if already exists, else 0.
- */
-static struct vnode *
-unionfs_hashget(struct mount *mp, struct vnode *uppervp,
- struct vnode *lowervp, struct vnode *dvp, char *path,
- int lkflags, struct thread *td)
-{
- struct unionfs_node_hashhead *hd;
- struct unionfs_node *unp;
- struct vnode *vp;
- int error;
-
- if (lkflags & LK_TYPE_MASK)
- lkflags |= LK_RETRY;
- hd = UNIONFS_NHASH(uppervp, lowervp);
-
- mtx_lock(&unionfs_hashmtx);
- LIST_FOREACH(unp, hd, un_hash) {
- if (unp->un_uppervp == uppervp &&
- unp->un_lowervp == lowervp &&
- unp->un_dvp == dvp &&
- UNIONFSTOV(unp)->v_mount == mp &&
- (!path || !(unp->un_path) || !strcmp(unp->un_path, path))) {
- vp = UNIONFSTOV(unp);
- VI_LOCK(vp);
- mtx_unlock(&unionfs_hashmtx);
- /*
- * We need to clear the OWEINACT flag here as this
- * may lead vget() to try to lock our vnode which is
- * already locked via vp.
- */
- vp->v_iflag &= ~VI_OWEINACT;
- error = vget(vp, LK_INTERLOCK, td);
- if (error != 0)
- panic("unionfs_hashget: vget error %d", error);
- if (lkflags & LK_TYPE_MASK)
- vn_lock(vp, lkflags, td);
- return (vp);
- }
- }
-
- mtx_unlock(&unionfs_hashmtx);
-
- return (NULLVP);
-}
-
-/*
- * Act like unionfs_hashget, but add passed unionfs_node to hash if no existing
- * node found.
- */
-static struct vnode *
-unionfs_hashins(struct mount *mp, struct unionfs_node *uncp,
- char *path, int lkflags, struct thread *td)
-{
- struct unionfs_node_hashhead *hd;
- struct unionfs_node *unp;
- struct vnode *vp;
- int error;
-
- if (lkflags & LK_TYPE_MASK)
- lkflags |= LK_RETRY;
- hd = UNIONFS_NHASH(uncp->un_uppervp, uncp->un_lowervp);
-
- mtx_lock(&unionfs_hashmtx);
- LIST_FOREACH(unp, hd, un_hash) {
- if (unp->un_uppervp == uncp->un_uppervp &&
- unp->un_lowervp == uncp->un_lowervp &&
- unp->un_dvp == uncp->un_dvp &&
- UNIONFSTOV(unp)->v_mount == mp &&
- (!path || !(unp->un_path) || !strcmp(unp->un_path, path))) {
- vp = UNIONFSTOV(unp);
- VI_LOCK(vp);
- mtx_unlock(&unionfs_hashmtx);
- vp->v_iflag &= ~VI_OWEINACT;
- error = vget(vp, LK_INTERLOCK, td);
- if (error)
- panic("unionfs_hashins: vget error %d", error);
- if (lkflags & LK_TYPE_MASK)
- vn_lock(vp, lkflags, td);
- return (vp);
- }
- }
-
- LIST_INSERT_HEAD(hd, uncp, un_hash);
- uncp->un_flag |= UNIONFS_CACHED;
- mtx_unlock(&unionfs_hashmtx);
-
- return (NULLVP);
-}
-
-/*
* Make a new or get existing unionfs node.
*
* uppervp and lowervp should be unlocked. Because if new unionfs vnode is
@@ -210,20 +104,15 @@
ump = MOUNTTOUNIONFSMOUNT(mp);
lkflags = (cnp ? cnp->cn_lkflags : 0);
- path = (cnp ? cnp->cn_nameptr : "");
+ path = (cnp ? cnp->cn_nameptr : NULL);
if (uppervp == NULLVP && lowervp == NULLVP)
panic("unionfs_nodeget: upper and lower is null");
/* If it has no ISLASTCN flag, path check is skipped. */
- if (!cnp || !(cnp->cn_flags & ISLASTCN))
+ if (cnp && !(cnp->cn_flags & ISLASTCN))
path = NULL;
- /* Lookup the hash first. */
- *vpp = unionfs_hashget(mp, uppervp, lowervp, dvp, path, lkflags, td);
- if (*vpp != NULLVP)
- return (0);
-
if ((uppervp == NULLVP || ump->um_uppervp != uppervp) ||
(lowervp == NULLVP || ump->um_lowervp != lowervp)) {
if (dvp == NULLVP)
@@ -239,7 +128,7 @@
M_UNIONFSNODE, M_WAITOK | M_ZERO);
error = getnewvnode("unionfs", mp, &unionfs_vnodeops, &vp);
- if (error) {
+ if (error != 0) {
FREE(unp, M_UNIONFSNODE);
return (error);
}
@@ -259,9 +148,9 @@
else
vp->v_vnlock = lowervp->v_vnlock;
- if (cnp) {
+ if (path != NULL) {
unp->un_path = (char *)
- malloc(cnp->cn_namelen +1, M_UNIONFSPATH, M_WAITOK | M_ZERO);
+ malloc(cnp->cn_namelen +1, M_UNIONFSPATH, M_WAITOK|M_ZERO);
bcopy(cnp->cn_nameptr, unp->un_path, cnp->cn_namelen);
unp->un_path[cnp->cn_namelen] = '\0';
}
@@ -272,23 +161,6 @@
(lowervp != NULLVP && ump->um_lowervp == lowervp))
vp->v_vflag |= VV_ROOT;
- *vpp = unionfs_hashins(mp, unp, path, lkflags, td);
- if (*vpp != NULLVP) {
- if (dvp != NULLVP)
- vrele(dvp);
- if (uppervp != NULLVP)
- vrele(uppervp);
- if (lowervp != NULLVP)
- vrele(lowervp);
-
- unp->un_uppervp = NULLVP;
- unp->un_lowervp = NULLVP;
- unp->un_dvp = NULLVP;
- vrele(vp);
-
- return (0);
- }
-
if (lkflags & LK_TYPE_MASK)
vn_lock(vp, lkflags | LK_RETRY, td);
@@ -298,10 +170,10 @@
}
/*
- * Remove node from hash.
+ * Clean up the unionfs node.
*/
void
-unionfs_hashrem(struct vnode *vp, struct thread *td)
+unionfs_noderem(struct vnode *vp, struct thread *td)
{
int vfslocked;
struct unionfs_node *unp;
@@ -326,13 +198,6 @@
VOP_UNLOCK(lvp, 0, td);
if (uvp != NULLVP)
VOP_UNLOCK(uvp, 0, td);
-
- mtx_lock(&unionfs_hashmtx);
- if (unp->un_flag & UNIONFS_CACHED) {
- LIST_REMOVE(unp, un_hash);
- unp->un_flag &= ~UNIONFS_CACHED;
- }
- mtx_unlock(&unionfs_hashmtx);
vp->v_object = NULL;
if (lvp != NULLVP) {
@@ -687,16 +552,6 @@
VI_UNLOCK(vp);
for (count = 1; count < lockcnt; count++)
vn_lock(uvp, LK_EXCLUSIVE | LK_CANRECURSE | LK_RETRY, td);
-
- /*
- * cache update
- */
- mtx_lock(&unionfs_hashmtx);
- if (unp->un_flag & UNIONFS_CACHED)
- LIST_REMOVE(unp, un_hash);
- LIST_INSERT_HEAD(UNIONFS_NHASH(uvp, lvp), unp, un_hash);
- unp->un_flag |= UNIONFS_CACHED;
- mtx_unlock(&unionfs_hashmtx);
}
/*
@@ -1105,6 +960,12 @@
return (0);
/* open vnode */
+#ifdef MAC
+ if ((error = mac_check_vnode_open(cred, vp, VEXEC|VREAD)) != 0)
+ return (error);
+#endif
+ if ((error = VOP_ACCESS(vp, VEXEC|VREAD, cred, td)) != 0)
+ return (error);
if ((error = VOP_OPEN(vp, FREAD, cred, td, -1)) != 0)
return (error);
==== //depot/projects/dtrace6/src/sys/fs/unionfs/union_vfsops.c#2 (text+ko) ====
@@ -33,7 +33,7 @@
* SUCH DAMAGE.
*
* @(#)union_vfsops.c 8.20 (Berkeley) 5/20/95
- * $FreeBSD: src/sys/fs/unionfs/union_vfsops.c,v 1.76.2.2 2007/02/13 05:56:42 rodrigc Exp $
+ * $FreeBSD: src/sys/fs/unionfs/union_vfsops.c,v 1.76.2.5 2007/10/23 03:37:09 daichi Exp $
*/
#include <sys/param.h>
@@ -124,6 +124,7 @@
u_short udir;
u_short ufile;
unionfs_copymode copymode;
+ unionfs_whitemode whitemode;
struct componentname fakecn;
struct nameidata nd, *ndp;
struct vattr va;
@@ -137,6 +138,7 @@
udir = 0;
ufile = 0;
copymode = UNIONFS_TRADITIONAL; /* default */
+ whitemode = UNIONFS_WHITE_ALWAYS;
ndp = &nd;
if (mp->mnt_flag & MNT_ROOTFS) {
@@ -238,6 +240,20 @@
return (EINVAL);
}
}
+ if (vfs_getopt(mp->mnt_optnew, "whiteout", (void **)&tmp,
+ NULL) == 0) {
+ if (tmp == NULL) {
+ vfs_mount_error(mp, "Invalid whiteout mode");
+ return (EINVAL);
+ } else if (strcasecmp(tmp, "always") == 0)
+ whitemode = UNIONFS_WHITE_ALWAYS;
+ else if (strcasecmp(tmp, "whenneeded") == 0)
+ whitemode = UNIONFS_WHITE_WHENNEEDED;
+ else {
+ vfs_mount_error(mp, "Invalid whiteout mode");
+ return (EINVAL);
+ }
+ }
}
/* If copymode is UNIONFS_TRADITIONAL, uid/gid is mounted user. */
if (copymode == UNIONFS_TRADITIONAL) {
@@ -287,7 +303,13 @@
ump->um_udir = udir;
ump->um_ufile = ufile;
ump->um_copymode = copymode;
+ ump->um_whitemode = whitemode;
+ MNT_ILOCK(mp);
+ if ((lowerrootvp->v_mount->mnt_kern_flag & MNTK_MPSAFE) &&
+ (upperrootvp->v_mount->mnt_kern_flag & MNTK_MPSAFE))
+ mp->mnt_kern_flag |= MNTK_MPSAFE;
+ MNT_IUNLOCK(mp);
mp->mnt_data = (qaddr_t)ump;
/*
@@ -325,8 +347,8 @@
*/
error = unionfs_nodeget(mp, ump->um_uppervp, ump->um_lowervp,
NULLVP, &(ump->um_rootvp), NULL, td);
+ vrele(upperrootvp);
if (error) {
- vrele(upperrootvp);
free(ump, M_UNIONFSMNT);
mp->mnt_data = NULL;
return (error);
==== //depot/projects/dtrace6/src/sys/fs/unionfs/union_vnops.c#2 (text+ko) ====
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)union_vnops.c 8.32 (Berkeley) 6/23/95
- * $FreeBSD: src/sys/fs/unionfs/union_vnops.c,v 1.132.2.1 2007/02/13 05:56:42 rodrigc Exp $
+ * $FreeBSD: src/sys/fs/unionfs/union_vnops.c,v 1.132.2.8 2007/10/23 03:37:10 daichi Exp $
*
*/
@@ -88,7 +88,7 @@
static int
-unionfs_lookup(struct vop_lookup_args *ap)
+unionfs_lookup(struct vop_cachedlookup_args *ap)
{
int iswhiteout;
int lockflag;
@@ -171,7 +171,9 @@
vn_lock(dunp->un_dvp, cnp->cn_lkflags | LK_RETRY, td);
vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, td);
- }
+ } else if (error == ENOENT && (cnflags & MAKEENTRY) &&
+ nameiop != CREATE)
+ cache_enter(dvp, NULLVP, cnp);
UNIONFS_INTERNAL_DEBUG("unionfs_lookup: leave (%d)\n", error);
@@ -318,12 +320,18 @@
*(ap->a_vpp) = vp;
+ if (cnflags & MAKEENTRY)
+ cache_enter(dvp, vp, cnp);
+
unionfs_lookup_out:
if (uvp != NULLVP)
vrele(uvp);
if (lvp != NULLVP)
vrele(lvp);
+ if (error == ENOENT && (cnflags & MAKEENTRY) && nameiop != CREATE)
+ cache_enter(dvp, NULLVP, cnp);
+
UNIONFS_INTERNAL_DEBUG("unionfs_lookup: leave (%d)\n", error);
return (error);
@@ -874,6 +882,7 @@
unp = VTOUNIONFS(ap->a_vp);
unionfs_get_node_status(unp, ap->a_td, &unsp);
ovp = (unsp->uns_upper_opencnt ? unp->un_uppervp : unp->un_lowervp);
+ unionfs_tryrem_node_status(unp, ap->a_td, unsp);
VOP_UNLOCK(ap->a_vp, 0, ap->a_td);
if (ovp == NULLVP)
@@ -898,6 +907,7 @@
unp = VTOUNIONFS(ap->a_vp);
unionfs_get_node_status(unp, ap->a_td, &unsp);
ovp = (unsp->uns_upper_opencnt ? unp->un_uppervp : unp->un_lowervp);
+ unionfs_tryrem_node_status(unp, ap->a_td, unsp);
VOP_UNLOCK(ap->a_vp, 0, ap->a_td);
if (ovp == NULLVP)
@@ -916,6 +926,7 @@
unp = VTOUNIONFS(ap->a_vp);
unionfs_get_node_status(unp, ap->a_td, &unsp);
ovp = (unsp->uns_upper_opencnt ? unp->un_uppervp : unp->un_lowervp);
+ unionfs_tryrem_node_status(unp, ap->a_td, unsp);
if (ovp == NULLVP)
return (EBADF);
@@ -929,6 +940,7 @@
int error;
struct unionfs_node *dunp;
struct unionfs_node *unp;
+ struct unionfs_mount *ump;
struct vnode *udvp;
struct vnode *uvp;
struct vnode *lvp;
@@ -950,7 +962,9 @@
return (EROFS);
if (uvp != NULLVP) {
- cnp->cn_flags |= DOWHITEOUT;
+ ump = MOUNTTOUNIONFSMOUNT(ap->a_vp->v_mount);
+ if (ump->um_whitemode == UNIONFS_WHITE_ALWAYS || lvp != NULLVP)
+ cnp->cn_flags |= DOWHITEOUT;
error = VOP_REMOVE(udvp, uvp, cnp);
} else if (lvp != NULLVP)
error = unionfs_mkwhiteout(udvp, cnp, td, unp->un_path);
@@ -1176,22 +1190,29 @@
error = VOP_RENAME(rfdvp, rfvp, fcnp, rtdvp, rtvp, tcnp);
+ if (error == 0) {
+ if (rtvp != NULLVP && rtvp->v_type == VDIR)
+ cache_purge(tdvp);
+ if (fvp->v_type == VDIR && fdvp != tdvp)
+ cache_purge(fdvp);
+ }
+
if (fdvp != rfdvp)
vrele(fdvp);
if (fvp != rfvp)
vrele(fvp);
+ if (ltdvp != NULLVP)
+ VOP_UNLOCK(ltdvp, 0, td);
if (tdvp != rtdvp)
vrele(tdvp);
+ if (ltvp != NULLVP)
+ VOP_UNLOCK(ltvp, 0, td);
if (tvp != rtvp && tvp != NULLVP) {
if (rtvp == NULLVP)
vput(tvp);
else
vrele(tvp);
}
- if (ltdvp != NULLVP)
- VOP_UNLOCK(ltdvp, 0, td);
- if (ltvp != NULLVP)
- VOP_UNLOCK(ltvp, 0, td);
UNIONFS_INTERNAL_DEBUG("unionfs_rename: leave (%d)\n", error);
@@ -1273,6 +1294,7 @@
int error;
struct unionfs_node *dunp;
struct unionfs_node *unp;
+ struct unionfs_mount *ump;
struct componentname *cnp;
struct thread *td;
struct vnode *udvp;
@@ -1302,12 +1324,19 @@
if (error != 0)
return (error);
}
- cnp->cn_flags |= DOWHITEOUT;
+ ump = MOUNTTOUNIONFSMOUNT(ap->a_vp->v_mount);
+ if (ump->um_whitemode == UNIONFS_WHITE_ALWAYS || lvp != NULLVP)
+ cnp->cn_flags |= DOWHITEOUT;
error = VOP_RMDIR(udvp, uvp, cnp);
}
else if (lvp != NULLVP)
error = unionfs_mkwhiteout(udvp, cnp, td, unp->un_path);
+ if (error == 0) {
+ cache_purge(ap->a_dvp);
+ cache_purge(ap->a_vp);
+ }
+
UNIONFS_INTERNAL_DEBUG("unionfs_rmdir: leave (%d)\n", error);
return (error);
@@ -1386,41 +1415,41 @@
/* check opaque */
if (uvp != NULLVP && lvp != NULLVP) {
if ((error = VOP_GETATTR(uvp, &va, ap->a_cred, td)) != 0)
- return (error);
+ goto unionfs_readdir_exit;
if (va.va_flags & OPAQUE)
lvp = NULLVP;
}
+ /* check the open count. unionfs needs to open before readdir. */
if (VOP_ISLOCKED(ap->a_vp, td) != LK_EXCLUSIVE) {
vn_lock(ap->a_vp, LK_UPGRADE | LK_RETRY, td);
locked = 1;
}
- unionfs_get_node_status(unp, curthread, &unsp);
+ unionfs_get_node_status(unp, td, &unsp);
+ if ((uvp != NULLVP && unsp->uns_upper_opencnt <= 0) ||
+ (lvp != NULLVP && unsp->uns_lower_opencnt <= 0)) {
+ unionfs_tryrem_node_status(unp, td, unsp);
+ error = EBADF;
+ }
if (locked == 1)
vn_lock(ap->a_vp, LK_DOWNGRADE | LK_RETRY, td);
+ if (error != 0)
+ goto unionfs_readdir_exit;
/* upper only */
if (uvp != NULLVP && lvp == NULLVP) {
- if (unsp->uns_upper_opencnt <= 0)
- error = EBADF;
- else {
- error = VOP_READDIR(uvp, uio, ap->a_cred, ap->a_eofflag,
- ap->a_ncookies, ap->a_cookies);
- unsp->uns_readdir_status = 0;
- }
+ error = VOP_READDIR(uvp, uio, ap->a_cred, ap->a_eofflag,
+ ap->a_ncookies, ap->a_cookies);
+ unsp->uns_readdir_status = 0;
goto unionfs_readdir_exit;
}
/* lower only */
if (uvp == NULLVP && lvp != NULLVP) {
- if (unsp->uns_lower_opencnt <= 0)
- error = EBADF;
- else {
- error = VOP_READDIR(lvp, uio, ap->a_cred, ap->a_eofflag,
- ap->a_ncookies, ap->a_cookies);
- unsp->uns_readdir_status = 2;
- }
+ error = VOP_READDIR(lvp, uio, ap->a_cred, ap->a_eofflag,
+ ap->a_ncookies, ap->a_cookies);
+ unsp->uns_readdir_status = 2;
goto unionfs_readdir_exit;
}
@@ -1428,11 +1457,8 @@
/*
* readdir upper and lower
*/
- if (unsp->uns_lower_opencnt <= 0 || unsp->uns_upper_opencnt <= 0) {
- error = EBADF;
- goto unionfs_readdir_exit;
- }
-
+ KASSERT(uvp != NULLVP, ("unionfs_readdir: null upper vp"));
+ KASSERT(lvp != NULLVP, ("unionfs_readdir: null lower vp"));
if (uio->uio_offset == 0)
unsp->uns_readdir_status = 0;
@@ -1441,10 +1467,8 @@
error = VOP_READDIR(uvp, uio, ap->a_cred, &eofflag,
ap->a_ncookies, ap->a_cookies);
- if (error != 0 || eofflag == 0) {
- UNIONFS_INTERNAL_DEBUG("unionfs_readdir: leave (%d)\n", error);
- return (error);
- }
+ if (error != 0 || eofflag == 0)
+ goto unionfs_readdir_exit;
unsp->uns_readdir_status = 1;
/*
@@ -1453,10 +1477,8 @@
* size of DIRBLKSIZ equals DEV_BSIZE.
* (see: ufs/ufs/ufs_vnops.c ufs_readdir func , ufs/ufs/dir.h)
*/
- if (uio->uio_resid <= (uio->uio_resid & (DEV_BSIZE -1))) {
- UNIONFS_INTERNAL_DEBUG("unionfs_readdir: leave (%d)\n", error);
- return (0);
- }
+ if (uio->uio_resid <= (uio->uio_resid & (DEV_BSIZE -1)))
+ goto unionfs_readdir_exit;
/*
* backup cookies
@@ -1506,6 +1528,9 @@
}
unionfs_readdir_exit:
+ if (error != 0 && ap->a_eofflag != NULL)
+ *(ap->a_eofflag) = 1;
+
UNIONFS_INTERNAL_DEBUG("unionfs_readdir: leave (%d)\n", error);
return (error);
@@ -1568,13 +1593,8 @@
static int
unionfs_inactive(struct vop_inactive_args *ap)
{
- struct unionfs_node *unp;
-
- unp = VTOUNIONFS(ap->a_vp);
-
- if (unp == NULL || !(unp->un_flag & UNIONFS_CACHED))
- vgone(ap->a_vp);
-
+ ap->a_vp->v_object = NULL;
+ vrecycle(ap->a_vp, ap->a_td);
return (0);
}
@@ -1583,7 +1603,7 @@
{
/* UNIONFS_INTERNAL_DEBUG("unionfs_reclaim: enter\n"); */
- unionfs_hashrem(ap->a_vp, ap->a_td);
+ unionfs_noderem(ap->a_vp, ap->a_td);
/* UNIONFS_INTERNAL_DEBUG("unionfs_reclaim: leave\n"); */
@@ -1636,6 +1656,7 @@
int flags;
int revlock;
int uhold;
+ struct mount *mp;
struct unionfs_mount *ump;
struct unionfs_node *unp;
struct vnode *vp;
@@ -1655,16 +1676,24 @@
if ((revlock = unionfs_get_llt_revlock(flags)) == 0)
panic("unknown lock type: 0x%x", flags & LK_TYPE_MASK);
- if (!(flags & LK_INTERLOCK))
+ if ((flags & LK_INTERLOCK) == 0)
VI_LOCK(vp);
- ump = MOUNTTOUNIONFSMOUNT(vp->v_mount);
+ mp = vp->v_mount;
+ if (mp == NULL)
+ goto unionfs_lock_null_vnode;
+
>>> TRUNCATED FOR MAIL (1000 lines) <<<
More information about the p4-projects
mailing list