Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/fs/union Stop abusing relookup() to prepare the creation...
details: https://anonhg.NetBSD.org/src/rev/cf3933925230
branches: trunk
changeset: 768618:cf3933925230
user: hannken <hannken%NetBSD.org@localhost>
date: Tue Aug 23 07:39:37 2011 +0000
description:
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.
diffstat:
sys/fs/union/union.h | 4 +-
sys/fs/union/union_subr.c | 200 +++++++++++++++-----------------------------
sys/fs/union/union_vnops.c | 8 +-
3 files changed, 77 insertions(+), 135 deletions(-)
diffs (truncated from 363 to 300 lines):
diff -r 8a5ba1dceafc -r cf3933925230 sys/fs/union/union.h
--- a/sys/fs/union/union.h Tue Aug 23 05:22:25 2011 +0000
+++ b/sys/fs/union/union.h Tue Aug 23 07:39:37 2011 +0000
@@ -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,
diff -r 8a5ba1dceafc -r cf3933925230 sys/fs/union/union_subr.c
--- a/sys/fs/union/union_subr.c Tue Aug 23 05:22:25 2011 +0000
+++ b/sys/fs/union/union_subr.c Tue Aug 23 07:39:37 2011 +0000
@@ -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;
-
- error = relookup(dvp, vpp, cn, 0);
- if (error) {
- PNBUF_PUT(pnbuf);
- *pnbuf_ret = NULL;
+ 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;
}
- return (error);
+ 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;
}
/*
@@ -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);
- 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)
Home |
Main Index |
Thread Index |
Old Index