macos: fix race in afs_root
authorDerrick Brashear <shadow@dementix.org>
Mon, 15 Aug 2011 16:17:06 +0000 (12:17 -0400)
committerDerrick Brashear <shadow@dementix.org>
Mon, 15 Aug 2011 19:04:26 +0000 (12:04 -0700)
same race on PutVCache in afs_root as we had on other platforms,
for instance FreeBSD. use a local variable instead to avoid the race.
additionally, make sure we end up with the root flagged VROOT.

Change-Id: I45ac36f12565320576070fd1c6d1f99ac6db8a63
Reviewed-on: http://gerrit.openafs.org/5278
Tested-by: Derrick Brashear <shadow@dementix.org>
Reviewed-by: Derrick Brashear <shadow@dementix.org>

src/afs/DARWIN/osi_vfsops.c
src/afs/DARWIN/osi_vnodeops.c
src/afs/afs_vcache.c

index 919a3d0..d0efb8c 100644 (file)
@@ -222,9 +222,10 @@ afs_root(struct mount *mp, struct vnode **vpp)
     int error;
     struct vrequest treq;
     struct vcache *tvp = 0;
+    struct vcache *gvp;
+    int needref=0;
 #ifdef AFS_DARWIN80_ENV
     struct ucred *cr = vfs_context_ucred(ctx);
-    int needref=0;
 #else
     struct proc *p = current_proc();
     struct ucred _cr;
@@ -236,13 +237,13 @@ afs_root(struct mount *mp, struct vnode **vpp)
 #endif
     AFS_GLOCK();
     AFS_STATCNT(afs_root);
+
+again:
     if (mdata == NULL && afs_globalVp
        && (afs_globalVp->f.states & CStatd)) {
        tvp = afs_globalVp;
        error = 0;
-#ifdef AFS_DARWIN80_ENV
         needref=1;
-#endif
     } else if (mdata == (qaddr_t) - 1) {
        error = ENOENT;
     } else {
@@ -266,36 +267,46 @@ afs_root(struct mount *mp, struct vnode **vpp)
            /* we really want this to stay around */
            if (tvp) {
                if (mdata == NULL) {
-                   if (afs_globalVp) {
-                       afs_PutVCache(afs_globalVp);
-                       afs_globalVp = NULL;
-                   }
+                   gvp = afs_globalVp;
                    afs_globalVp = tvp;
-#ifdef AFS_DARWIN80_ENV
+                   if (gvp) {
+                       afs_PutVCache(gvp);
+                       if (tvp != afs_globalVp) {
+                           /* someone else got there before us! */
+                           afs_PutVCache(tvp);
+                           tvp = 0;
+                           goto again;
+                       }
+                   }
                     needref=1;
-#endif
                 }
            } else
                error = ENOENT;
        }
     }
     if (tvp) {
-#ifndef AFS_DARWIN80_ENV /* DARWIN80 caller does not need a usecount reference */
+#ifndef AFS_DARWIN80_ENV /* KPI callers don't need a usecount reference */
        osi_vnhold(tvp, 0);
        AFS_GUNLOCK();
        vn_lock(AFSTOV(tvp), LK_EXCLUSIVE | LK_RETRY, p);
        AFS_GLOCK();
 #endif
+
+        if (needref)
 #ifdef AFS_DARWIN80_ENV
-        if (needref) /* this iocount is for the caller. the initial iocount
-                        is for the eventual afs_PutVCache. for mdata != null,
-                        there will not be a PutVCache, so the caller gets the
-                        initial (from GetVCache or finalizevnode) iocount*/
-           vnode_get(AFSTOV(tvp));
+           /* This iocount is for the caller. the initial iocount
+            * is for the eventual afs_PutVCache. for mdata != null,
+            * there will not be a PutVCache, so the caller gets the
+            * initial (from GetVCache or finalizevnode) iocount
+            */
+           vnode_get(AFSTOV(tvp));
+#else
+           ;
 #endif
-       if (mdata == NULL) {
+
+       if (mdata == NULL)
            afs_globalVFS = mp;
-       }
+
        *vpp = AFSTOV(tvp);
 #ifndef AFS_DARWIN80_ENV 
        AFSTOV(tvp)->v_flag |= VROOT;
index 108474b..1d8a163 100644 (file)
@@ -2163,10 +2163,7 @@ afs_darwin_finalizevnode(struct vcache *avc, struct vnode *dvp,
     }
     ovp = AFSTOV(avc);
 
-    /* if the type changed, we still need to do a fixup, for bulkstat */
-    if (!isroot && (vnode_vtype(ovp) == avc->f.m.Type &&
-                   !(avc->f.states & CDeadVnode) && vnode_vtype(ovp) != VNON))
-    {
+    if (!(avc->f.states & CDeadVnode) && vnode_vtype(ovp) != VNON) {
        AFS_GUNLOCK();
 #if 0 /* unsupported */
         if (dvp && cnp)
index aac212b..d93ed55 100644 (file)
@@ -1526,12 +1526,8 @@ afs_ProcessFS(struct vcache *avc,
        }
     }
 #ifdef AFS_DARWIN80_ENV
-    if (fixup) {
-       /* perform type correction on underlying vnode */
-       afs_darwin_finalizevnode(avc, NULL, NULL, 0, 1);
-       /* re-acquire the usecount that finalizevnode disposed of */
-       vnode_ref(AFSTOV(avc));
-    }
+    if (fixup)
+       printf("found mistyped vnode!\n");
 #endif
     avc->f.anyAccess = astat->AnonymousAccess;
 #ifdef badidea