Module Name:    src
Committed By:   hannken
Date:           Tue Aug 23 07:39:37 UTC 2011

Modified Files:
        src/sys/fs/union: union.h union_subr.c union_vnops.c

Log Message:
Stop abusing relookup() to prepare the creation of new nodes
in the upper layer.
Replace union_relookup() with union_do_lookup() that prepares
a component, calls VOP_LOOKUP() and does the EEXIST test.


To generate a diff of this commit:
cvs rdiff -u -r1.20 -r1.21 src/sys/fs/union/union.h
cvs rdiff -u -r1.49 -r1.50 src/sys/fs/union/union_subr.c
cvs rdiff -u -r1.45 -r1.46 src/sys/fs/union/union_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/union/union.h
diff -u src/sys/fs/union/union.h:1.20 src/sys/fs/union/union.h:1.21
--- src/sys/fs/union/union.h:1.20	Fri Aug 12 17:41:17 2011
+++ src/sys/fs/union/union.h	Tue Aug 23 07:39:37 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: union.h,v 1.20 2011/08/12 17:41:17 hannken Exp $	*/
+/*	$NetBSD: union.h,v 1.21 2011/08/23 07:39:37 hannken Exp $	*/
 
 /*
  * Copyright (c) 1994 The Regents of the University of California.
@@ -144,7 +144,7 @@
 extern int union_mkshadow(struct union_mount *, struct vnode *,
     struct componentname *, struct vnode **);
 extern int union_mkwhiteout(struct union_mount *, struct vnode *,
-    struct componentname *, char *);
+    struct componentname *, struct union_node *);
 extern int union_vn_create(struct vnode **, struct union_node *,
     struct lwp *);
 extern int union_cn_close(struct vnode *, int, kauth_cred_t,

Index: src/sys/fs/union/union_subr.c
diff -u src/sys/fs/union/union_subr.c:1.49 src/sys/fs/union/union_subr.c:1.50
--- src/sys/fs/union/union_subr.c:1.49	Sat Aug 13 10:48:14 2011
+++ src/sys/fs/union/union_subr.c	Tue Aug 23 07:39:37 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: union_subr.c,v 1.49 2011/08/13 10:48:14 hannken Exp $	*/
+/*	$NetBSD: union_subr.c,v 1.50 2011/08/23 07:39:37 hannken Exp $	*/
 
 /*
  * Copyright (c) 1994
@@ -72,7 +72,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: union_subr.c,v 1.49 2011/08/13 10:48:14 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: union_subr.c,v 1.50 2011/08/23 07:39:37 hannken Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -106,10 +106,7 @@
 static kmutex_t unheadlock[NHASH];
 
 void union_updatevp(struct union_node *, struct vnode *, struct vnode *);
-static int union_relookup(struct union_mount *, struct vnode *,
-			       struct vnode **, struct componentname *,
-			       struct componentname *, char **,
-			       const char *, int);
+static int union_do_lookup(struct vnode *, struct componentname *, kauth_cred_t,    const char *, u_long);
 int union_vn_close(struct vnode *, int, kauth_cred_t, struct lwp *);
 static void union_dircache_r(struct vnode *, struct vnode ***, int *);
 struct vnode *union_dircache(struct vnode *, struct lwp *);
@@ -755,54 +752,50 @@
 
 }
 
+/*
+ * Prepare the creation of a new node in the upper layer.
+ *
+ * (dvp) is the directory in which to create the new node.
+ * it is locked on entry and exit.
+ * (cnp) is the componentname to be created.
+ * (cred, path, hash) are credentials, path and its hash to fill (cnp).
+ */
 static int
-union_relookup(
-	struct union_mount *um,
-	struct vnode *dvp,
-	struct vnode **vpp,
-	struct componentname *cnp,
-	struct componentname *cn,
-	char **pnbuf_ret,
-	const char *path,
-	int pathlen)
+union_do_lookup(struct vnode *dvp, struct componentname *cnp, kauth_cred_t cred,
+    const char *path, u_long hash)
 {
 	int error;
-	char *pnbuf;
+	const char *cp;
+	struct vnode *vp;
 
-	/*
-	 * A new componentname structure must be faked up because
-	 * there is no way to know where the upper level cnp came
-	 * from or what it is being used for.  This must duplicate
-	 * some of the work done by NDINIT, some of the work done
-	 * by namei, some of the work done by lookup and some of
-	 * the work done by VOP_LOOKUP when given a CREATE flag.
-	 * Conclusion: Horrible.
-	 */
-	cn->cn_namelen = pathlen;
-	if ((cn->cn_namelen + 1) > MAXPATHLEN)
-		return (ENAMETOOLONG);
-	pnbuf = PNBUF_GET();
-	memcpy(pnbuf, path, cn->cn_namelen);
-	pnbuf[cn->cn_namelen] = '\0';
-	*pnbuf_ret = pnbuf;
-
-	cn->cn_nameiop = CREATE;
-	cn->cn_flags = (LOCKPARENT|ISLASTCN);
-	if (um->um_op == UNMNT_ABOVE)
-		cn->cn_cred = cnp->cn_cred;
-	else
-		cn->cn_cred = um->um_cred;
-	cn->cn_nameptr = pnbuf;
-	cn->cn_hash = cnp->cn_hash;
-	cn->cn_consume = cnp->cn_consume;
+	cnp->cn_nameiop = CREATE;
+	cnp->cn_flags = LOCKPARENT | ISLASTCN;
+	cnp->cn_cred = cred;
+	cnp->cn_nameptr = path;
+	cnp->cn_namelen = strlen(path);
+	if (hash == 0) {
+		cp = NULL;
+		cnp->cn_hash = namei_hash(cnp->cn_nameptr, &cp);
+		KASSERT(*cp == 0);
+	} else {
+		cnp->cn_hash = hash;
+	}
 
-	error = relookup(dvp, vpp, cn, 0);
-	if (error) {
-		PNBUF_PUT(pnbuf);
-		*pnbuf_ret = NULL;
+	error = VOP_LOOKUP(dvp, &vp, cnp);
+
+	if (error == 0) {
+		KASSERT(vp != NULL);
+		VOP_ABORTOP(dvp, cnp);
+		if (dvp != vp)
+			vput(vp);
+		else
+			vrele(vp);
+		error = EEXIST;
+	} else if (error == EJUSTRETURN) {
+		error = 0;
 	}
 
-	return (error);
+	return error;
 }
 
 /*
@@ -829,22 +822,20 @@
 	struct componentname cn;
 	char *pnbuf;
 
+	if (cnp->cn_namelen + 1 > MAXPATHLEN)
+		return ENAMETOOLONG;
+	pnbuf = PNBUF_GET();
+	memcpy(pnbuf, cnp->cn_nameptr, cnp->cn_namelen);
+	pnbuf[cnp->cn_namelen] = '\0';
+
 	vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
-	error = union_relookup(um, dvp, vpp, cnp, &cn, &pnbuf,
-			cnp->cn_nameptr, cnp->cn_namelen);
+
+	error = union_do_lookup(dvp, &cn,
+	    (um->um_op == UNMNT_ABOVE ? cnp->cn_cred : um->um_cred), pnbuf, 0);
 	if (error) {
 		VOP_UNLOCK(dvp);
-		return (error);
-	}
-
-	if (*vpp) {
-		VOP_ABORTOP(dvp, &cn);
 		PNBUF_PUT(pnbuf);
-		if (dvp != *vpp)
-			VOP_UNLOCK(dvp);
-		vput(*vpp);
-		*vpp = NULLVP;
-		return (EEXIST);
+		return error;
 	}
 
 	/*
@@ -862,7 +853,7 @@
 	vref(dvp);
 	error = VOP_MKDIR(dvp, vpp, &cn, &va);
 	PNBUF_PUT(pnbuf);
-	return (error);
+	return error;
 }
 
 /*
@@ -873,39 +864,23 @@
  * (dvp) is the directory in which to create the whiteout.
  * it is locked on entry and exit.
  * (cnp) is the componentname to be created.
+ * (un) holds the path and its hash to be created.
  */
 int
 union_mkwhiteout(struct union_mount *um, struct vnode *dvp,
-	struct componentname *cnp, char *path)
+	struct componentname *cnp, struct union_node *un)
 {
 	int error;
-	struct vnode *wvp;
 	struct componentname cn;
-	char *pnbuf;
 
-	VOP_UNLOCK(dvp);
-	vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
-	error = union_relookup(um, dvp, &wvp, cnp, &cn, &pnbuf,
-			       path, strlen(path));
+	error = union_do_lookup(dvp, &cn,
+	    (um->um_op == UNMNT_ABOVE ? cnp->cn_cred : um->um_cred),
+	    un->un_path, un->un_hash);
 	if (error)
-		return (error);
-
-	if (wvp) {
-		VOP_ABORTOP(dvp, &cn);
-		PNBUF_PUT(pnbuf);
-		if (dvp != wvp)
-			VOP_UNLOCK(dvp);
-		vput(wvp);
-		return (EEXIST);
-	}
+		return error;
 
 	error = VOP_WHITEOUT(dvp, &cn, CREATE);
-	if (error) {
-		VOP_ABORTOP(dvp, &cn);
-	}
-
-	PNBUF_PUT(pnbuf);
-	return (error);
+	return error;
 }
 
 /*
@@ -914,7 +889,7 @@
  * in spirit to calling vn_open but it avoids calling namei().
  * the problem with calling namei is that a) it locks too many
  * things, and b) it doesn't start at the "right" directory,
- * whereas relookup is told where to start.
+ * whereas union_do_lookup is told where to start.
  */
 int
 union_vn_create(struct vnode **vpp, struct union_node *un, struct lwp *l)
@@ -927,46 +902,16 @@
 	int error;
 	int cmode = UN_FILEMODE & ~l->l_proc->p_cwdi->cwdi_cmask;
 	struct componentname cn;
-	char *pnbuf;
 
 	*vpp = NULLVP;
 
-	/*
-	 * Build a new componentname structure (for the same
-	 * reasons outlines in union_mkshadow).
-	 * The difference here is that the file is owned by
-	 * the current user, rather than by the person who
-	 * did the mount, since the current user needs to be
-	 * able to write the file (that's why it is being
-	 * copied in the first place).
-	 */
-	cn.cn_namelen = strlen(un->un_path);
-	if ((cn.cn_namelen + 1) > MAXPATHLEN)
-		return (ENAMETOOLONG);
-	pnbuf = PNBUF_GET();
-	memcpy(pnbuf, un->un_path, cn.cn_namelen+1);
-	cn.cn_nameiop = CREATE;
-	cn.cn_flags = (LOCKPARENT|ISLASTCN);
-	cn.cn_cred = l->l_cred;
-	cn.cn_nameptr = pnbuf;
-	cn.cn_hash = un->un_hash;
-	cn.cn_consume = 0;
-
 	vn_lock(un->un_dirvp, LK_EXCLUSIVE | LK_RETRY);
-	error = relookup(un->un_dirvp, &vp, &cn, 0);
+
+	error = union_do_lookup(un->un_dirvp, &cn, l->l_cred,
+	    un->un_path, un->un_hash);
 	if (error) {
-		PNBUF_PUT(pnbuf);
 		VOP_UNLOCK(un->un_dirvp);
-		return (error);
-	}
-
-	if (vp) {
-		VOP_ABORTOP(un->un_dirvp, &cn);
-		PNBUF_PUT(pnbuf);
-		if (un->un_dirvp != vp)
-			VOP_UNLOCK(un->un_dirvp);
-		vput(vp);
-		return (EEXIST);
+		return error;
 	}
 
 	/*
@@ -983,21 +928,19 @@
 	vap->va_type = VREG;
 	vap->va_mode = cmode;
 	vref(un->un_dirvp);
-	if ((error = VOP_CREATE(un->un_dirvp, &vp, &cn, vap)) != 0) {
-		PNBUF_PUT(pnbuf);
-		return (error);
-	}
+	error = VOP_CREATE(un->un_dirvp, &vp, &cn, vap);
+	if (error)
+		return error;
 
-	if ((error = VOP_OPEN(vp, fmode, cred)) != 0) {
+	error = VOP_OPEN(vp, fmode, cred);
+	if (error) {
 		vput(vp);
-		PNBUF_PUT(pnbuf);
-		return (error);
+		return error;
 	}
 
 	vp->v_writecount++;
 	*vpp = vp;
-	PNBUF_PUT(pnbuf);
-	return (0);
+	return 0;
 }
 
 int
@@ -1240,7 +1183,6 @@
 			cn.cn_nameptr = dp->d_name;
 			cn.cn_namelen = dp->d_namlen;
 			cn.cn_hash = 0;
-			cn.cn_consume = 0;
 			error = VOP_LOOKUP(un->un_uppervp, &tvp, &cn);
 			if (error == ENOENT && (cn.cn_flags & ISWHITEOUT)) {
 				error = 0;

Index: src/sys/fs/union/union_vnops.c
diff -u src/sys/fs/union/union_vnops.c:1.45 src/sys/fs/union/union_vnops.c:1.46
--- src/sys/fs/union/union_vnops.c:1.45	Fri Aug 12 17:41:17 2011
+++ src/sys/fs/union/union_vnops.c	Tue Aug 23 07:39:37 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: union_vnops.c,v 1.45 2011/08/12 17:41:17 hannken Exp $	*/
+/*	$NetBSD: union_vnops.c,v 1.46 2011/08/23 07:39:37 hannken Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993, 1994, 1995
@@ -72,7 +72,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: union_vnops.c,v 1.45 2011/08/12 17:41:17 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: union_vnops.c,v 1.46 2011/08/23 07:39:37 hannken Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -1211,7 +1211,7 @@
 		FIXUP(dun);
 		error = union_mkwhiteout(
 			MOUNTTOUNIONMOUNT(UNIONTOV(dun)->v_mount),
-			dun->un_uppervp, ap->a_cnp, un->un_path);
+			dun->un_uppervp, ap->a_cnp, un);
 		vput(ap->a_dvp);
 		vput(ap->a_vp);
 	}
@@ -1488,7 +1488,7 @@
 		FIXUP(dun);
 		error = union_mkwhiteout(
 			MOUNTTOUNIONMOUNT(UNIONTOV(dun)->v_mount),
-			dun->un_uppervp, ap->a_cnp, un->un_path);
+			dun->un_uppervp, ap->a_cnp, un);
 		vput(ap->a_dvp);
 		vput(ap->a_vp);
 	}

Reply via email to