summary |
tags |
clone url |
shortlog |
log |
commit | commitdiff |
tree
raw |
patch |
inline | side by side (from parent 1:
c239ec2)
SCCS-vsn: sys/miscfs/union/union.h 1.7
SCCS-vsn: sys/miscfs/union/union_subr.c 1.7
SCCS-vsn: sys/miscfs/union/union_vnops.c 1.7
SCCS-vsn: sys/miscfs/union/union_vfsops.c 1.7
*
* %sccs.include.redist.c%
*
*
* %sccs.include.redist.c%
*
- * @(#)union.h 1.6 (Berkeley) %G%
+ * @(#)union.h 1.7 (Berkeley) %G%
struct vnode *un_lowervp; /* underlying object */
struct vnode *un_dirvp; /* Parent dir of uppervp */
char *un_path; /* saved component name */
struct vnode *un_lowervp; /* underlying object */
struct vnode *un_dirvp; /* Parent dir of uppervp */
char *un_path; /* saved component name */
- int un_open; /* # of opens on lowervp */
+ int un_hash; /* saved un_path hash value */
+ int un_openl; /* # of opens on lowervp */
struct componentname *, struct vnode **));
extern int union_vn_create __P((struct vnode **, struct union_node *,
struct proc *));
struct componentname *, struct vnode **));
extern int union_vn_create __P((struct vnode **, struct union_node *,
struct proc *));
+extern void union_removed_upper __P((struct union_node *un));
#define MOUNTTOUNIONMOUNT(mp) ((struct union_mount *)((mp)->mnt_data))
#define VTOUNION(vp) ((struct union_node *)(vp)->v_data)
#define MOUNTTOUNIONMOUNT(mp) ((struct union_mount *)((mp)->mnt_data))
#define VTOUNION(vp) ((struct union_node *)(vp)->v_data)
*
* %sccs.include.redist.c%
*
*
* %sccs.include.redist.c%
*
- * @(#)union_subr.c 1.6 (Berkeley) %G%
+ * @(#)union_subr.c 1.7 (Berkeley) %G%
*/
#include <sys/param.h>
*/
#include <sys/param.h>
goto loop;
if (UNIONTOV(un) != undvp)
VOP_LOCK(UNIONTOV(un));
goto loop;
if (UNIONTOV(un) != undvp)
VOP_LOCK(UNIONTOV(un));
+
+ /*
+ * Save information about the upper layer.
+ */
if (uppervp != un->un_uppervp) {
if (un->un_uppervp)
vrele(un->un_uppervp);
if (uppervp != un->un_uppervp) {
if (un->un_uppervp)
vrele(un->un_uppervp);
} else if (uppervp) {
vrele(uppervp);
}
} else if (uppervp) {
vrele(uppervp);
}
+
+ /*
+ * Save information about the lower layer.
+ * This needs to keep track of pathname
+ * and directory information which union_vn_create
+ * might need.
+ */
if (lowervp != un->un_lowervp) {
if (lowervp != un->un_lowervp) {
+ free(un->un_path, M_TEMP);
+ vrele(un->un_dirvp);
+ }
un->un_lowervp = lowervp;
un->un_lowervp = lowervp;
+ if (cnp && (lowervp != NULLVP) &&
+ (lowervp->v_type == VREG)) {
+ un->un_hash = cnp->cn_hash;
+ un->un_path = malloc(cnp->cn_namelen+1,
+ M_TEMP, M_WAITOK);
+ bcopy(cnp->cn_nameptr, un->un_path,
+ cnp->cn_namelen);
+ un->un_path[cnp->cn_namelen] = '\0';
+ VREF(dvp);
+ un->un_dirvp = dvp;
+ }
} else if (lowervp) {
vrele(lowervp);
}
} else if (lowervp) {
vrele(lowervp);
}
un->un_lowervp = lowervp;
un->un_open = 0;
un->un_flags = 0;
un->un_lowervp = lowervp;
un->un_open = 0;
un->un_flags = 0;
- if (uppervp == 0 && cnp) {
+ if (cnp && (lowervp != NULLVP) && (lowervp->v_type == VREG)) {
+ un->un_hash = cnp->cn_hash;
un->un_path = malloc(cnp->cn_namelen+1, M_TEMP, M_WAITOK);
bcopy(cnp->cn_nameptr, un->un_path, cnp->cn_namelen);
un->un_path[cnp->cn_namelen] = '\0';
VREF(dvp);
un->un_dirvp = dvp;
} else {
un->un_path = malloc(cnp->cn_namelen+1, M_TEMP, M_WAITOK);
bcopy(cnp->cn_nameptr, un->un_path, cnp->cn_namelen);
un->un_path[cnp->cn_namelen] = '\0';
VREF(dvp);
un->un_dirvp = dvp;
} else {
un->un_path = 0;
un->un_dirvp = 0;
}
un->un_path = 0;
un->un_dirvp = 0;
}
* The pathname buffer will be FREEed by VOP_MKDIR.
*/
cn.cn_pnbuf = malloc(cnp->cn_namelen+1, M_NAMEI, M_WAITOK);
* The pathname buffer will be FREEed by VOP_MKDIR.
*/
cn.cn_pnbuf = malloc(cnp->cn_namelen+1, M_NAMEI, M_WAITOK);
- bcopy(cnp->cn_nameptr, cn.cn_pnbuf, cnp->cn_namelen+1);
+ bcopy(cnp->cn_nameptr, cn.cn_pnbuf, cnp->cn_namelen);
+ cn.cn_pnbuf[cnp->cn_namelen] = '\0';
cn.cn_nameiop = CREATE;
cn.cn_flags = (LOCKPARENT|HASBUF|SAVENAME|ISLASTCN);
cn.cn_nameiop = CREATE;
cn.cn_flags = (LOCKPARENT|HASBUF|SAVENAME|ISLASTCN);
cn.cn_hash = cnp->cn_hash;
cn.cn_consume = cnp->cn_consume;
cn.cn_hash = cnp->cn_hash;
cn.cn_consume = cnp->cn_consume;
if (error = relookup(dvp, vpp, &cn))
return (error);
if (error = relookup(dvp, vpp, &cn))
return (error);
if (*vpp) {
VOP_ABORTOP(dvp, &cn);
if (*vpp) {
VOP_ABORTOP(dvp, &cn);
VATTR_NULL(&va);
va.va_type = VDIR;
VATTR_NULL(&va);
va.va_type = VDIR;
- va.va_mode = UN_DIRMODE &~ p->p_fd->fd_cmask;
+ va.va_mode = UN_DIRMODE & ~p->p_fd->fd_cmask;
/* LEASE_CHECK: dvp is locked */
LEASE_CHECK(dvp, p, p->p_ucred, LEASE_WRITE);
/* LEASE_CHECK: dvp is locked */
LEASE_CHECK(dvp, p, p->p_ucred, LEASE_WRITE);
struct vattr *vap = &vat;
int fmode = FFLAGS(O_WRONLY|O_CREAT|O_TRUNC|O_EXCL);
int error;
struct vattr *vap = &vat;
int fmode = FFLAGS(O_WRONLY|O_CREAT|O_TRUNC|O_EXCL);
int error;
- int hash;
- int cmode = UN_FILEMODE &~ p->p_fd->fd_cmask;
+ int cmode = UN_FILEMODE & ~p->p_fd->fd_cmask;
char *cp;
struct componentname cn;
char *cp;
struct componentname cn;
cn.cn_proc = p;
cn.cn_cred = p->p_ucred;
cn.cn_nameptr = cn.cn_pnbuf;
cn.cn_proc = p;
cn.cn_cred = p->p_ucred;
cn.cn_nameptr = cn.cn_pnbuf;
- for (hash = 0, cp = cn.cn_nameptr; *cp != 0 && *cp != '/'; cp++)
- hash += (unsigned char)*cp;
- cn.cn_hash = hash;
+ cn.cn_hash = un->un_hash;
if (error = relookup(un->un_dirvp, &vp, &cn))
return (error);
if (error = relookup(un->un_dirvp, &vp, &cn))
return (error);
if (vp == NULLVP) {
VATTR_NULL(vap);
vap->va_type = VREG;
if (vp == NULLVP) {
VATTR_NULL(vap);
vap->va_type = VREG;
vput(vp);
return (error);
}
vput(vp);
return (error);
}
+
+int
+union_vn_close(vp, fmode)
+ struct vnode *vp;
+ int fmode;
+{
+ if (fmode & FWRITE)
+ --vp->v_writecount;
+ return (VOP_CLOSE(vp, fmode));
+}
+
+void
+union_removed_upper(un)
+ struct union_node *un;
+{
+ vrele(un->un_uppervp);
+ un->un_uppervp = NULLVP;
+}
*
* %sccs.include.redist.c%
*
*
* %sccs.include.redist.c%
*
- * @(#)union_vfsops.c 1.6 (Berkeley) %G%
+ * @(#)union_vfsops.c 1.7 (Berkeley) %G%
*
* %sccs.include.redist.c%
*
*
* %sccs.include.redist.c%
*
- * @(#)union_vnops.c 1.6 (Berkeley) %G%
+ * @(#)union_vnops.c 1.7 (Berkeley) %G%
*/
#include <sys/param.h>
*/
#include <sys/param.h>
error = VOP_LOOKUP(dvp, &tdvp, cnp);
if (error)
return (error);
/*
error = VOP_LOOKUP(dvp, &tdvp, cnp);
if (error)
return (error);
/*
- * If going back up the directory tree, then the parent directory
- * will have been unlocked, unless lookup found the last
- * component. In which case, re-lock the node here to allow
- * it to be unlocked again (phew) in union_lookup.
+ * The parent directory will have been unlocked, unless lookup
+ * found the last component. In which case, re-lock the node
+ * here to allow it to be unlocked again (phew) in union_lookup.
- if ((cnp->cn_flags & ISDOTDOT) && !(cnp->cn_flags & ISLASTCN))
+ if (dvp != tdvp && !(cnp->cn_flags & ISLASTCN))
VOP_LOCK(dvp);
dvp = tdvp;
VOP_LOCK(dvp);
dvp = tdvp;
* whatever the bottom layer returned.
*/
* whatever the bottom layer returned.
*/
/* case 1. */
if ((uerror != 0) && (lerror != 0)) {
/* case 1. */
if ((uerror != 0) && (lerror != 0)) {
* be a loopback mount of some other filesystem...
* so open the file with exclusive create and barf if
* it already exists.
* be a loopback mount of some other filesystem...
* so open the file with exclusive create and barf if
* it already exists.
- * XXX - perhaps shoudl re-lookup the node (once more
+ * XXX - perhaps should re-lookup the node (once more
* with feeling) and simply open that. Who knows.
*/
error = union_vn_create(&vp, un, p);
* with feeling) and simply open that. Who knows.
*/
error = union_vn_create(&vp, un, p);
VOP_UNLOCK(tvp);
}
VOP_UNLOCK(un->un_uppervp);
VOP_UNLOCK(tvp);
}
VOP_UNLOCK(un->un_uppervp);
- (void) VOP_CLOSE(un->un_uppervp, FWRITE);
+ union_vn_close(un->un_uppervp, FWRITE);
VOP_LOCK(un->un_uppervp);
if (!error)
VOP_LOCK(un->un_uppervp);
if (!error)
- uprintf("union: copied up\n",
+ uprintf("union: copied up %s\n",
* the right thing with (cred) and (FREAD) though.
* Ignoring error returns is not righ, either.
*/
* the right thing with (cred) and (FREAD) though.
* Ignoring error returns is not righ, either.
*/
- for (i = 0; i < un->un_open; i++) {
+ for (i = 0; i < un->un_openl; i++) {
(void) VOP_CLOSE(tvp, FREAD);
(void) VOP_OPEN(un->un_uppervp, FREAD, cred, p);
}
(void) VOP_CLOSE(tvp, FREAD);
(void) VOP_OPEN(un->un_uppervp, FREAD, cred, p);
}
if (error == 0)
error = VOP_OPEN(un->un_uppervp, mode, cred, p);
VOP_UNLOCK(un->un_uppervp);
return (error);
}
if (error == 0)
error = VOP_OPEN(un->un_uppervp, mode, cred, p);
VOP_UNLOCK(un->un_uppervp);
return (error);
}
if (un->un_uppervp) {
vp = un->un_uppervp;
} else {
if (un->un_uppervp) {
vp = un->un_uppervp;
} else {
-#ifdef DIAGNOSTIC
- if (un->un_open <= 0)
- panic("union: un_open cnt");
+#ifdef UNION_DIAGNOSTIC
+ if (un->un_openl <= 0)
+ panic("union: un_openl cnt");
return (VOP_CLOSE(vp, ap->a_fflag, ap->a_cred, ap->a_p));
}
return (VOP_CLOSE(vp, ap->a_fflag, ap->a_cred, ap->a_p));
}
vput(ap->a_vp);
error = VOP_REMOVE(dvp, vp, ap->a_cnp);
vput(ap->a_vp);
error = VOP_REMOVE(dvp, vp, ap->a_cnp);
+ if (!error)
+ union_removed_upper(un);
+
+ /*
+ * XXX: should create a whiteout here
+ */
} else {
/*
* XXX: should create a whiteout here
} else {
/*
* XXX: should create a whiteout here
vput(ap->a_vp);
error = VOP_REMOVE(dvp, vp, ap->a_cnp);
vput(ap->a_vp);
error = VOP_REMOVE(dvp, vp, ap->a_cnp);
+ if (!error)
+ union_removed_upper(un);
+
+ /*
+ * XXX: should create a whiteout here
+ */
} else {
/*
* XXX: should create a whiteout here
} else {
/*
* XXX: should create a whiteout here
* That's too much work for now.
*/
* That's too much work for now.
*/
struct union_node *un = VTOUNION(ap->a_vp);
if (un->un_flags & UN_LOCKED)
struct union_node *un = VTOUNION(ap->a_vp);
if (un->un_flags & UN_LOCKED)