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