Index: src/afs/afs_call.c
===================================================================
RCS file: /cvs/openafs/src/afs/afs_call.c,v
retrieving revision 1.14.2.14
diff -u -r1.14.2.14 afs_call.c
--- src/afs/afs_call.c	2002/09/11 16:17:31	1.14.2.14
+++ src/afs/afs_call.c	2002/11/09 14:18:01
@@ -718,8 +718,10 @@
 #endif
 	afs_cold_shutdown = 0;
 	if (parm == 1) afs_cold_shutdown = 1;
+#ifndef AFS_DARWIN_ENV
 	if (afs_globalVFS != 0) 
 	    afs_warn("AFS isn't unmounted yet!\n");
+#endif
 
 	afs_shutdown();
     }
Index: src/afs/DARWIN/osi_vfsops.c
===================================================================
RCS file: /cvs/openafs/src/afs/DARWIN/osi_vfsops.c,v
retrieving revision 1.4.2.1
diff -u -r1.4.2.1 osi_vfsops.c
--- src/afs/DARWIN/osi_vfsops.c	2002/04/24 01:41:22	1.4.2.1
+++ src/afs/DARWIN/osi_vfsops.c	2002/11/09 14:18:01
@@ -67,7 +67,7 @@
     AFS_GLOCK();
     AFS_STATCNT(afs_mount);
 
-    if (afs_globalVFS) { /* Don't allow remounts. */
+    if (data == NULL && afs_globalVFS) { /* Don't allow remounts. */
 	AFS_GUNLOCK();
 	return (EBUSY);
     }
@@ -80,8 +80,45 @@
     (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN-1, &size);
     memset(mp->mnt_stat.f_mntonname + size, 0, MNAMELEN - size);
     memset(mp->mnt_stat.f_mntfromname, 0, MNAMELEN);
-    strcpy(mp->mnt_stat.f_mntfromname, "AFS");
-    /* null terminated string "AFS" will fit, just leave it be. */
+
+    if (data == NULL) {
+	strcpy(mp->mnt_stat.f_mntfromname, "AFS");
+	/* null terminated string "AFS" will fit, just leave it be. */
+	mp->mnt_data = (qaddr_t)NULL;
+    } else {
+	struct VenusFid *rootFid = NULL;
+	struct volume *tvp;
+	char volName[MNAMELEN];
+
+	(void) copyinstr((char *)data, volName, MNAMELEN-1, &size);
+	memset(volName + size, 0, MNAMELEN - size);
+
+	if (volName[0] == 0) {
+	    strcpy(mp->mnt_stat.f_mntfromname, "AFS");
+	    mp->mnt_data = (qaddr_t)&afs_rootFid;	    
+	} else {
+	    /* Set the volume identifier to "AFS:volume.name" */
+	    snprintf(mp->mnt_stat.f_mntfromname, MNAMELEN-1, "AFS:%s",
+		     volName);
+	    tvp = afs_GetVolumeByName(volName, LOCALCELL, 1,
+				      (struct vrequest *)0, READ_LOCK);
+	    
+	    if (tvp) {
+		int volid = (tvp->roVol ? tvp->roVol : tvp->volume);
+		MALLOC(rootFid, struct VenusFid *, sizeof(*rootFid), 
+		       M_UFSMNT, M_WAITOK);
+		rootFid->Cell = LOCALCELL;
+		rootFid->Fid.Volume = volid;
+		rootFid->Fid.Vnode = 1;
+		rootFid->Fid.Unique = 1;
+	    } else {
+		AFS_GUNLOCK();
+		return ENODEV;
+	    }
+	
+	    mp->mnt_data = (qaddr_t)rootFid;
+	}
+    }
     strcpy(mp->mnt_stat.f_fstypename, "afs");
     AFS_GUNLOCK();
     (void) afs_statfs(mp, &mp->mnt_stat, p);
@@ -97,8 +134,23 @@
     
     AFS_GLOCK();
     AFS_STATCNT(afs_unmount);
-    afs_globalVFS = 0;
-    afs_shutdown();
+
+    if (mp->mnt_data != (qaddr_t)-1) {
+	if (mp->mnt_data != NULL) {
+	    FREE(mp->mnt_data, M_UFSMNT);
+	    mp->mnt_data = (qaddr_t)-1;
+	} else {
+	    if (flags & MNT_FORCE) {
+		afs_globalVFS = 0;
+		afs_shutdown();
+	    } else {
+		AFS_GUNLOCK();
+		return EBUSY;
+	    }
+	}
+	mp->mnt_flag &= ~MNT_LOCAL;
+    }
+
     AFS_GUNLOCK();
 
     return 0;
@@ -119,18 +171,24 @@
     pcred_unlock(p);
     AFS_GLOCK();
     AFS_STATCNT(afs_root);
-    if (afs_globalVp && (afs_globalVp->states & CStatd)) {
+    if (mp->mnt_data == NULL
+	&& afs_globalVp && (afs_globalVp->states & CStatd)) {
 	tvp = afs_globalVp;
         error=0;
+    } else if (mp->mnt_data == (qaddr_t)-1) {
+	error = ENOENT;
     } else {
+	struct VenusFid *rootFid = (mp->mnt_data == NULL)
+	    ? &afs_rootFid : (struct VenusFid *)mp->mnt_data;
 	
 	if (!(error = afs_InitReq(&treq, &cr)) &&
 	    !(error = afs_CheckInit())) {
-	    tvp = afs_GetVCache(&afs_rootFid, &treq, (afs_int32 *)0,
+	    tvp = afs_GetVCache(rootFid, &treq, (afs_int32 *)0,
 	                        (struct vcache*)0, WRITE_LOCK);
 	    /* we really want this to stay around */
 	    if (tvp) {
-	        afs_globalVp = tvp;
+		if (mp->mnt_data == NULL)
+		    afs_globalVp = tvp;
 	    } else
 	        error = ENOENT;
 	}
@@ -140,9 +198,12 @@
     AFS_GUNLOCK();
         vn_lock(AFSTOV(tvp), LK_EXCLUSIVE | LK_RETRY, p);
     AFS_GLOCK();
-	afs_globalVFS = mp;
+        if (mp->mnt_data == NULL) {
+	    afs_globalVFS = mp;
+	}	
 	*vpp = AFSTOV(tvp);
         AFSTOV(tvp)->v_flag |= VROOT;
+	AFSTOV(tvp)->v_vfsp = mp;
     }
 
     afs_Trace2(afs_iclSetp, CM_TRACE_VFSROOT, ICL_TYPE_POINTER, *vpp,
@@ -165,7 +226,7 @@
     }
     error = vget(vp, lfl, current_proc());
     if (!error)
-	insmntque(vp, afs_globalVFS);   /* take off free list */
+	insmntque(vp, mp);   /* take off free list */
     return error;
 }
 
Index: src/afs/DARWIN/osi_vnodeops.c
===================================================================
RCS file: /cvs/openafs/src/afs/DARWIN/osi_vnodeops.c,v
retrieving revision 1.4.2.4
diff -u -r1.4.2.4 osi_vnodeops.c
--- src/afs/DARWIN/osi_vnodeops.c	2002/08/21 20:53:22	1.4.2.4
+++ src/afs/DARWIN/osi_vnodeops.c	2002/11/09 14:18:02
@@ -173,6 +173,7 @@
 	return (error);
     }
     vp = AFSTOV(vcp);  /* always get a node if no error */
+    vp->v_vfsp = dvp->v_vfsp;
 
     /* The parent directory comes in locked.  We unlock it on return
        unless the caller wants it left locked.
@@ -237,6 +238,7 @@
 
     if (vcp) {
 	*ap->a_vpp = AFSTOV(vcp);
+	(*ap->a_vpp)->v_vfsp = dvp->v_vfsp;
 	vn_lock(*ap->a_vpp, LK_EXCLUSIVE| LK_RETRY, p);
         if (UBCINFOMISSING(*ap->a_vpp) ||
             UBCINFORECLAIMED(*ap->a_vpp))
@@ -805,11 +807,6 @@
 
     GETNAME();
     p=cnp->cn_proc;
-    if (dvp->v_mount != vp->v_mount) {
-	VOP_ABORTOP(vp, cnp);
-	error = EXDEV;
-	goto out;
-    }
     if (vp->v_type == VDIR) {
 	VOP_ABORTOP(vp, cnp);
 	error = EISDIR;
@@ -854,25 +851,6 @@
     struct proc *p=fcnp->cn_proc;
 
     /*
-     * Check for cross-device rename.
-     */
-    if ((fvp->v_mount != tdvp->v_mount) ||
-	(tvp && (fvp->v_mount != tvp->v_mount))) {
-	error = EXDEV;
-abortit:
-	VOP_ABORTOP(tdvp, tcnp); /* XXX, why not in NFS? */
-	if (tdvp == tvp)
-	    vrele(tdvp);
-	else
-	    vput(tdvp);
-	if (tvp)
-	    vput(tvp);
-	VOP_ABORTOP(fdvp, fcnp); /* XXX, why not in NFS? */
-	vrele(fdvp);
-	vrele(fvp);
-	return (error);
-    }
-    /*
      * if fvp == tvp, we're just removing one name of a pair of
      * directory entries for the same element.  convert call into rename.
      ( (pinched from NetBSD 1.0's ufs_rename())
@@ -880,7 +858,18 @@
     if (fvp == tvp) {
 	if (fvp->v_type == VDIR) {
 	    error = EINVAL;
-	    goto abortit;
+	abortit:
+	    VOP_ABORTOP(tdvp, tcnp); /* XXX, why not in NFS? */
+	    if (tdvp == tvp)
+		vrele(tdvp);
+	    else
+		vput(tdvp);
+	    if (tvp)
+		vput(tvp);
+	    VOP_ABORTOP(fdvp, fcnp); /* XXX, why not in NFS? */
+	    vrele(fdvp);
+	    vrele(fvp);
+	    return (error);
 	}
 
 	/* Release destination completely. */
@@ -963,6 +952,7 @@
     }
     if (vcp) {
 	*ap->a_vpp = AFSTOV(vcp);
+	(*ap->a_vpp)->v_vfsp = dvp->v_vfsp;
 	vn_lock(*ap->a_vpp, LK_EXCLUSIVE|LK_RETRY, p);
     } else
 	*ap->a_vpp = 0;
