darwin-mount-and-disk-arbitration-enhancements-20030515
authorAlexei Kosut <akosut@cs.stanford.edu>
Thu, 15 May 2003 16:00:27 +0000 (16:00 +0000)
committerDerrick Brashear <shadow@dementia.org>
Thu, 15 May 2003 16:00:27 +0000 (16:00 +0000)
FIXES 1363

* Allow AFS to be mounted multiple times, each mountpoint with its
  own root volume.  This allows usage similar to the Windows client,
  e.g., mounting a drive that contains only the user's home
  directory.  Our users find this much easier to work with than
  having to navigate the entire AFS tree in the Finder or open/save
  dialog.

* Have afsd register /afs with the DiskArbitration system
  when mounting it.  This means that the root afs volume shows up in
  the Finder immediately, and prevents the Finder from getting
  confused by additional AFS volumes later on.

* Add a "-nomount" option to afsd, which prevents afsd from
  mounting /afs.  We use this by default on our Mac OS X client, so
  that AFS doesn't show up in the interface at all unless the user
  explicitly asks for an AFS volume to be mounted.  This is
  especially handy for portable or remote users who don't always
  have a network connection, since there isn't an AFS filesystem
  around to hang the Finder if the AFS servers can't be contacted
  (the cache manager may still hang, but since there are no AFS
  volumes mounted, the rest of the OS doesn't notice).

* Make it so that /afs (mounted by afsd) will not unmount unless
  MNT_FORCE is given.  This prevents the user from accidentally
  ejecting /afs in the Finder, and also works around a DiskArb bug in
  Mac OS X (possibly fixed in 10.2) where autodiskmount would sometimes
  unmount /afs when logging out, even though it's marked as
  non-ejectable.

src/afs/DARWIN/osi_vfsops.c
src/afs/DARWIN/osi_vnodeops.c
src/afs/afs_call.c
src/afsd/Makefile.in
src/afsd/afsd.c
src/cf/osconf.m4
src/config/Makefile.config.in

index de87135..705cc42 100644 (file)
@@ -67,7 +67,7 @@ struct proc *p;
     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,51 @@ struct proc *p;
     (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 {
+           struct cell *localcell = afs_GetPrimaryCell(READ_LOCK);
+           if (localcell == NULL) {
+               AFS_GUNLOCK();
+               return ENODEV;
+           }
+
+           /* Set the volume identifier to "AFS:volume.name" */
+           snprintf(mp->mnt_stat.f_mntfromname, MNAMELEN-1, "AFS:%s",
+                    volName);
+           tvp = afs_GetVolumeByName(volName, localcell->cellNum, 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->cellNum;
+               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 +140,23 @@ struct proc *p;
     
     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,10 +177,16 @@ afs_root(struct mount *mp,
     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 (afs_globalVp) {
            afs_PutVCache(afs_globalVp);
            afs_globalVp = NULL;
@@ -130,10 +194,11 @@ afs_root(struct mount *mp,
 
        if (!(error = afs_InitReq(&treq, &cr)) &&
            !(error = afs_CheckInit())) {
-           tvp = afs_GetVCache(&afs_rootFid, &treq, NULL, NULL);
+           tvp = afs_GetVCache(rootFid, &treq, NULL, NULL);
            /* we really want this to stay around */
            if (tvp) {
-               afs_globalVp = tvp;
+               if (mp->mnt_data == NULL)
+                   afs_globalVp = tvp;
            } else
                error = ENOENT;
        }
@@ -143,9 +208,12 @@ afs_root(struct mount *mp,
     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,
@@ -168,7 +236,7 @@ int lfl;
     }
     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 16ddb4b..0e583c7 100644 (file)
@@ -173,6 +173,7 @@ struct vop_lookup_args /* {
        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 @@ afs_vop_create(ap)
 
     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))
@@ -810,11 +812,6 @@ afs_vop_link(ap)
 
     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;
@@ -859,25 +856,6 @@ afs_vop_rename(ap)
     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())
@@ -885,7 +863,18 @@ abortit:
     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. */
@@ -968,6 +957,7 @@ afs_vop_mkdir(ap)
     }
     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;
index ce08d29..ac5ccb0 100644 (file)
@@ -736,10 +736,12 @@ long parm, parm2, parm3, parm4, parm5, parm6;
     else if (parm == AFSOP_SHUTDOWN) {
        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! Call aborted\n");
            code = EACCES;
        } else
+#endif
            afs_shutdown();
     }
     else if (parm == AFSOP_AFS_VFSMOUNT) {
index a274a57..a1d2a90 100644 (file)
@@ -23,7 +23,7 @@ all: afsd vsys
 AFSLIBS=${TOP_LIBDIR}/libauth.a ${TOP_LIBDIR}/libcmd.a ${TOP_LIBDIR}/libsys.a ${TOP_LIBDIR}/util.a ${TOP_LIBDIR}/librx.a ${TOP_LIBDIR}/liblwp.a ${TOP_LIBDIR}/util.a
 
 afsd: afsd.o $(AFSLIBS) $(AFSD_LIBS)
-       ${CC} ${CFLAGS} -o afsd afsd.o $(NON_SHARED) $(LDFLAGS) $(AFSLIBS) ${XLIBS} ${AFSD_LIBS}
+       ${CC} ${CFLAGS} -o afsd afsd.o $(NON_SHARED) $(LDFLAGS) $(AFSD_LDFLAGS) $(AFSLIBS) ${XLIBS} ${AFSD_LIBS}
 
 vsys: vsys.o
        ${CC} ${CFLAGS} -o vsys vsys.o ${TOP_LIBDIR}/libsys.a $(LDFLAGS) ${XLIBS}
index 46296c8..85ae976 100644 (file)
@@ -146,6 +146,14 @@ void set_staticaddrs(void);
 #ifdef AFS_LINUX20_ENV
 #include <sys/resource.h>
 #endif
+#ifdef AFS_DARWIN_ENV
+#include <mach/mach.h>
+/* Symbols from the DiskArbitration framework */
+kern_return_t DiskArbStart(mach_port_t *);
+kern_return_t DiskArbDiskAppearedWithMountpointPing_auto(char *, unsigned int,
+                                                        char *);
+#define DISK_ARB_NETWORK_DISK_FLAG 8
+#endif /* AFS_DARWIN_ENV */
 
 #ifndef MOUNT_AFS
 #define        MOUNT_AFS AFS_MOUNT_AFS
@@ -250,6 +258,7 @@ static int enable_afsdb = 0;                /* enable AFSDB support */
 #endif
 static int enable_dynroot = 0;         /* enable dynroot support */
 static int enable_fakestat = 0;                /* enable fakestat support */
+static int enable_nomount = 0;         /* do not mount */
 #ifdef notdef
 static int inodes = 60;                        /* VERY conservative, but has to be */
 #endif
@@ -1347,6 +1356,10 @@ mainproc(as, arock)
        /* -fakestat-all */
        enable_fakestat = 1;
     }
+    if (as->parms[29].items) {
+       /* -nomount */
+       enable_nomount = 1;
+    }
 
     /*
      * Pull out all the configuration info for the workstation's AFS cache and
@@ -1846,6 +1859,8 @@ mainproc(as, arock)
        exit(1);
     }
 
+    if (!enable_nomount) {
+
     mountFlags = 0;    /* Read/write file system, can do setuid() */
 #if    defined(AFS_SUN_ENV) || defined(AFS_SUN5_ENV)
 #ifdef AFS_SUN5_ENV
@@ -1928,6 +1943,8 @@ mainproc(as, arock)
 
     HandleMTab();
 
+    }
+
     if (afsd_rmtsys) {
        if (afsd_verbose)
            printf("%s: Forking 'rmtsys' daemon.\n", rn);
@@ -1991,6 +2008,7 @@ char **argv; {
     cmd_AddParm(ts, "-dynroot", CMD_FLAG, CMD_OPTIONAL, "Enable dynroot support");
     cmd_AddParm(ts, "-fakestat", CMD_FLAG, CMD_OPTIONAL, "Enable fakestat support for cross-cell mounts");
     cmd_AddParm(ts, "-fakestat-all", CMD_FLAG, CMD_OPTIONAL, "Enable fakestat support for all mounts");
+    cmd_AddParm(ts, "-nomount", CMD_FLAG, CMD_OPTIONAL, "Do not mount AFS");
     return (cmd_Dispatch(argc, argv));
 }
 
@@ -2064,6 +2082,18 @@ static int HandleMTab() {
 #endif /* AFS_SGI_ENV */
 #endif /* AFS_SUN5_ENV */
 #endif /* unreasonable systems */
+#ifdef AFS_DARWIN_ENV
+    mach_port_t diskarb_port;
+    kern_return_t status;
+
+    status = DiskArbStart(&diskarb_port);
+    if (status == KERN_SUCCESS) {
+       status = DiskArbDiskAppearedWithMountpointPing_auto("AFS",
+                    DISK_ARB_NETWORK_DISK_FLAG, cacheMountDir);
+    }
+
+    return status;
+#endif /* AFS_DARWIN_ENV */
     return 0;
 }
 
index 67a2451..d7421b5 100644 (file)
@@ -350,12 +350,14 @@ case $AFS_SYSNAME in
                ;;
 
        ppc_darwin_12)
+               AFSD_LDFLAGS="-F/System/Library/PrivateFrameworks -framework DiskArbitration"
                LEX="lex -l"
                REGEX_OBJ="regex.o"
                XCFLAGS="-traditional-cpp"
                ;;
 
        ppc_darwin_13)
+               AFSD_LDFLAGS="-F/System/Library/PrivateFrameworks -framework DiskArbitration"
                LEX="lex -l"
                LWP_OPTMZ="-O2"
                REGEX_OBJ="regex.o"
@@ -363,6 +365,7 @@ case $AFS_SYSNAME in
                ;;
 
        ppc_darwin_14)
+               AFSD_LDFLAGS="-F/System/Library/PrivateFrameworks -framework DiskArbitration"
                LEX="lex -l"
                LWP_OPTMZ="-O2"
                REGEX_OBJ="regex.o"
@@ -370,6 +373,7 @@ case $AFS_SYSNAME in
                ;;
 
        ppc_darwin_60)
+               AFSD_LDFLAGS="-F/System/Library/PrivateFrameworks -framework DiskArbitration"
                LEX="lex -l"
                LWP_OPTMZ="-O2"
                REGEX_OBJ="regex.o"
@@ -778,6 +782,7 @@ fi
 
 AC_SUBST(CCXPG2)
 AC_SUBST(AFSD_LIBS)
+AC_SUBST(AFSD_LDFLAGS)
 AC_SUBST(AR)
 AC_SUBST(AS)
 AC_SUBST(CP)
index ce0e9ca..cff607e 100644 (file)
@@ -30,6 +30,7 @@ viceetcdir=@viceetcdir@
 AR = @AR@
 AS = @AS@
 AFSD_LIBS = @AFSD_LIBS@
+AFSD_LDFLAGS = @AFSD_LDFLAGS@
 CC = @CC@
 CCXPG2 = @CCXPG2@
 CFLAGS = @CFLAGS@