]> git.michaelhowe.org Git - packages/o/openafs.git/commitdiff
STABLE12-darwin-mount-and-disk-arbitration-enhancements-20030515
authorAlexei Kosut <akosut@cs.stanford.edu>
Thu, 15 May 2003 16:09:00 +0000 (16:09 +0000)
committerDerrick Brashear <shadow@dementia.org>
Thu, 15 May 2003 16:09:00 +0000 (16:09 +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.

(cherry picked from commit 26ee3fcc3947c8df88b5e95d413b5144f13c7e6a)

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

index 785e8cec698ec25be6815f508e46a4be17bc30f2..2ca43a862d9078e85ce856e1952a8d910876342a 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,18 +177,24 @@ 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 (!(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 +204,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,
@@ -165,7 +232,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 5a510c075715b716b66fc8c44de3ced67eeba930..81982745bdeaa044ed46b78d09bdcf48f47a48d1 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;
@@ -858,25 +855,6 @@ afs_vop_rename(ap)
     register struct vnode *fdvp = ap->a_fdvp;
     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.
@@ -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 ad47c04d1ce2f839010bb7c35d5b60e2eb827221..272e0049936a124559115cc27a2a906ca542126e 100644 (file)
@@ -731,8 +731,10 @@ long parm, parm2, parm3, parm4, parm5, parm6;
 #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 9d4ab45422da6a5aa47bbd2f07838a63250532cb..f07062e07cb0cdd9ca4a00fa988244527767b1dc 100644 (file)
@@ -52,6 +52,8 @@ afsd: afsd.o $(AFSLIBS)
                ${CC} ${CFLAGS} -g -o afsd afsd.o $(NON_SHARED) $(LDFLAGS) $(AFSLIBS) ${XLIBS} /usr/lib/libdwarf.a /usr/lib/libelf.a ;; \
        sgi_64 | sgi_65 ) \
                ${CC} ${CFLAGS} -g -o afsd afsd.o $(NON_SHARED) $(LDFLAGS) $(AFSLIBS) ${XLIBS} /usr/lib32/libdwarf.a /usr/lib32/libelf.a ;; \
+       ppc_darwin* ) \
+               ${CC} ${CFLAGS} -g -o afsd afsd.o $(NON_SHARED) $(LDFLAGS) $(AFSLIBS) ${XLIBS} -F/System/Library/PrivateFrameworks -framework DiskArbitration ;; \
        * ) \
                ${CC} ${CFLAGS} -g -o afsd afsd.o $(NON_SHARED) $(LDFLAGS) $(AFSLIBS) ${XLIBS} ;; \
        esac
index 5afd464b076ae4a57d3a7daae3b05210f20d6535..a9ec41dbc38214f3c93dfcd1457f20af086c028d 100644 (file)
@@ -146,6 +146,27 @@ void set_staticaddrs(void);
 #ifdef AFS_LINUX20_ENV
 #include <sys/resource.h>
 #endif
+#ifdef AFS_DARWIN_ENV
+#include <mach/mach.h>
+/* Relevant definitions from DiskArbitration.h (not included with Mac OS X) */
+#ifndef __DISKARBITRATION_H
+typedef char    DiskArbDiskIdentifier[1024];
+typedef char    DiskArbMountpoint[1024];
+kern_return_t   DiskArbStart(mach_port_t * portPtr);
+kern_return_t   DiskArbDiskAppearedWithMountpointPing_auto(
+    DiskArbDiskIdentifier diskIdentifier,
+    unsigned flags,
+    DiskArbMountpoint mountpoint);
+kern_return_t   DiskArbDiskDisappearedPing_auto(
+    DiskArbDiskIdentifier diskIdentifier,
+    unsigned flags);
+enum {
+    kDiskArbDiskAppearedNoFlags = 0x00000000,
+    kDiskArbDiskAppearedEjectableMask = 1 << 1,
+    kDiskArbDiskAppearedNetworkDiskMask = 1 << 3
+};
+#endif /* __DISKARBITRATION_H */
+#endif /* AFS_DARWIN_ENV */
 
 #ifndef MOUNT_AFS
 #define        MOUNT_AFS AFS_MOUNT_AFS
@@ -246,6 +267,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
@@ -1343,6 +1365,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
@@ -1811,6 +1837,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
@@ -1893,6 +1921,8 @@ mainproc(as, arock)
 
     HandleMTab();
 
+    }
+
     if (afsd_rmtsys) {
        if (afsd_verbose)
            printf("%s: Forking 'rmtsys' daemon.\n", rn);
@@ -1956,6 +1986,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));
 }
 
@@ -2029,6 +2060,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",
+                    kDiskArbDiskAppearedNetworkDiskMask, cacheMountDir);
+    }
+
+    return status;
+#endif /* AFS_DARWIN_ENV */
     return 0;
 }