libafs: avoid contaminating the return of lookup vnop
[openafs.git] / src / afs / VNOPS / afs_vnop_lookup.c
index 0faae09..11713d1 100644 (file)
@@ -861,7 +861,7 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp)
                    else
                        tvcp->f.m.Type = VREG;
                    /* finalize to a best guess */
-                   afs_darwin_finalizevnode(tvcp, VTOAFS(adp), NULL, 0, 1);
+                   afs_darwin_finalizevnode(tvcp, AFSTOV(adp), NULL, 0, 1);
                    /* re-acquire usecount that finalizevnode disposed of */
                    vnode_ref(AFSTOV(tvcp));
 #endif
@@ -1012,11 +1012,6 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp)
                        RXAFS_BulkStatus(rxconn, &fidParm, &statParm,
                                         &cbParm, &volSync);
                    RX_AFS_GLOCK();
-               } else if (!code) {
-                   /* The InlineBulkStatus call itself succeeded, but we
-                    * may have failed to stat the first entry. Use the error
-                    * from the first entry for processing. */
-                   code = (&statsp[0])->errorCode;
                }
            } else {
                RX_AFS_GUNLOCK();
@@ -1032,8 +1027,13 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp)
            }
        } else
            code = -1;
+       /* make sure we give afs_Analyze a chance to retry,
+        * but if the RPC succeeded we may have entries to merge.
+        * if we wipe code with one entry's status we get bogus failures.
+        */
     } while (afs_Analyze
-            (tcp, rxconn, code, &adp->f.fid, areqp, AFS_STATS_FS_RPCIDX_BULKSTATUS,
+            (tcp, rxconn, code ? code : (&statsp[0])->errorCode,
+             &adp->f.fid, areqp, AFS_STATS_FS_RPCIDX_BULKSTATUS,
              SHARED_LOCK, NULL));
 
     /* now, if we didnt get the info, bail out. */
@@ -1373,7 +1373,7 @@ afs_lookup(OSI_VC_DECL(adp), char *aname, struct vcache **avcp, afs_ucred_t *acr
 afs_lookup(OSI_VC_DECL(adp), char *aname, struct vcache **avcp, afs_ucred_t *acred)
 #endif
 {
-    struct vrequest treq;
+    struct vrequest *treq = NULL;
     char *tname = NULL;
     struct vcache *tvc = 0;
     afs_int32 code;
@@ -1393,8 +1393,8 @@ afs_lookup(OSI_VC_DECL(adp), char *aname, struct vcache **avcp, afs_ucred_t *acr
     afs_InitFakeStat(&fakestate);
 
     AFS_DISCON_LOCK();
-    
-    if ((code = afs_InitReq(&treq, acred)))
+
+    if ((code = afs_CreateReq(&treq, acred)))
        goto done;
 
     if (afs_fakestat_enable && adp->mvstat == 1) {
@@ -1419,9 +1419,9 @@ afs_lookup(OSI_VC_DECL(adp), char *aname, struct vcache **avcp, afs_ucred_t *acr
 #endif
 
     if (tryEvalOnly)
-       code = afs_TryEvalFakeStat(&adp, &fakestate, &treq);
+       code = afs_TryEvalFakeStat(&adp, &fakestate, treq);
     else
-       code = afs_EvalFakeStat(&adp, &fakestate, &treq);
+       code = afs_EvalFakeStat(&adp, &fakestate, treq);
 
     /*printf("Code is %d\n", code);*/
     
@@ -1437,7 +1437,7 @@ afs_lookup(OSI_VC_DECL(adp), char *aname, struct vcache **avcp, afs_ucred_t *acr
     bulkcode = 0;
 
     if (!(adp->f.states & CStatd) && !afs_InReadDir(adp)) {
-       if ((code = afs_VerifyVCache2(adp, &treq))) {
+       if ((code = afs_VerifyVCache2(adp, treq))) {
            goto done;
        }
     } else
@@ -1452,7 +1452,7 @@ afs_lookup(OSI_VC_DECL(adp), char *aname, struct vcache **avcp, afs_ucred_t *acr
        }
        /* otherwise we have the fid here, so we use it */
        /*printf("Getting vcache\n");*/
-       tvc = afs_GetVCache(adp->mvid, &treq, NULL, NULL);
+       tvc = afs_GetVCache(adp->mvid, treq, NULL, NULL);
        afs_Trace3(afs_iclSetp, CM_TRACE_GETVCDOTDOT, ICL_TYPE_FID, adp->mvid,
                   ICL_TYPE_POINTER, tvc, ICL_TYPE_INT32, code);
        *avcp = tvc;
@@ -1468,18 +1468,18 @@ afs_lookup(OSI_VC_DECL(adp), char *aname, struct vcache **avcp, afs_ucred_t *acr
     }
 
     /* now check the access */
-    if (treq.uid != adp->last_looker) {
-       if (!afs_AccessOK(adp, PRSFS_LOOKUP, &treq, CHECK_MODE_BITS)) {
+    if (treq->uid != adp->last_looker) {
+       if (!afs_AccessOK(adp, PRSFS_LOOKUP, treq, CHECK_MODE_BITS)) {
            *avcp = NULL;
            code = EACCES;
            goto done;
        } else
-           adp->last_looker = treq.uid;
+           adp->last_looker = treq->uid;
     }
 
     /* Check for read access as well.  We need read access in order to
      * stat files, but not to stat subdirectories. */
-    if (!afs_AccessOK(adp, PRSFS_READ, &treq, CHECK_MODE_BITS))
+    if (!afs_AccessOK(adp, PRSFS_READ, treq, CHECK_MODE_BITS))
        no_read_access = 1;
 
     /* special case lookup of ".".  Can we check for it sooner in this code,
@@ -1532,7 +1532,7 @@ afs_lookup(OSI_VC_DECL(adp), char *aname, struct vcache **avcp, afs_ucred_t *acr
        struct VenusFid tfid;
        afs_uint32 cellidx, volid, vnoid, uniq;
 
-       code = EvalMountData('%', aname, 0, 0, NULL, &treq, &cellidx, &volid, &vnoid, &uniq);
+       code = EvalMountData('%', aname, 0, 0, NULL, treq, &cellidx, &volid, &vnoid, &uniq);
        if (code)
            goto done;
        /* If a vnode was returned, it's not a real mount point */
@@ -1548,7 +1548,7 @@ afs_lookup(OSI_VC_DECL(adp), char *aname, struct vcache **avcp, afs_ucred_t *acr
            tfid.Fid.Vnode = VNUM_FROM_TYPEID(VN_TYPE_MOUNT, cellidx << 2);
            tfid.Fid.Unique = volid;
        }
-       *avcp = tvc = afs_GetVCache(&tfid, &treq, NULL, NULL);
+       *avcp = tvc = afs_GetVCache(&tfid, treq, NULL, NULL);
        code = (tvc ? 0 : ENOENT);
        hit = 1;
        goto done;
@@ -1564,14 +1564,14 @@ afs_lookup(OSI_VC_DECL(adp), char *aname, struct vcache **avcp, afs_ucred_t *acr
        struct VenusFid tfid;
 
        afs_GetDynrootMountFid(&tfid);
-       *avcp = tvc = afs_GetVCache(&tfid, &treq, NULL, NULL);
+       *avcp = tvc = afs_GetVCache(&tfid, treq, NULL, NULL);
        code = 0;
        hit = 1;
        goto done;
     }
 #endif
 
-    Check_AtSys(adp, aname, &sysState, &treq);
+    Check_AtSys(adp, aname, &sysState, treq);
     tname = sysState.name;
 
     /* 1st Check_AtSys and lookup by tname is required here, for now,
@@ -1616,7 +1616,7 @@ afs_lookup(OSI_VC_DECL(adp), char *aname, struct vcache **avcp, afs_ucred_t *acr
        if (afs_InReadDir(adp))
            tdc = adp->dcreaddir;
        else
-           tdc = afs_GetDCache(adp, (afs_size_t) 0, &treq,
+           tdc = afs_GetDCache(adp, (afs_size_t) 0, treq,
                                &dirOffset, &dirLen, 1);
        if (!tdc) {
            *avcp = NULL;       /* redundant, but harmless */
@@ -1681,7 +1681,7 @@ afs_lookup(OSI_VC_DECL(adp), char *aname, struct vcache **avcp, afs_ucred_t *acr
                                 &dirCookie);
 
        /* If the first lookup doesn't succeed, maybe it's got @sys in the name */
-       while (code == ENOENT && Next_AtSys(adp, &treq, &sysState))
+       while (code == ENOENT && Next_AtSys(adp, treq, &sysState))
            code =
                afs_dir_LookupOffset(tdc, sysState.name, &tfid.Fid,
                                     &dirCookie);
@@ -1750,7 +1750,7 @@ afs_lookup(OSI_VC_DECL(adp), char *aname, struct vcache **avcp, afs_ucred_t *acr
            } while (tvc && retry);
 
            if (!tvc || !(tvc->f.states & CStatd))
-               bulkcode = afs_DoBulkStat(adp, dirCookie, &treq);
+               bulkcode = afs_DoBulkStat(adp, dirCookie, treq);
            else
                bulkcode = 0;
 
@@ -1774,10 +1774,10 @@ afs_lookup(OSI_VC_DECL(adp), char *aname, struct vcache **avcp, afs_ucred_t *acr
        if (!tvc) {
            afs_int32 cached = 0;
            if (!tfid.Fid.Unique && (adp->f.states & CForeign)) {
-               tvc = afs_LookupVCache(&tfid, &treq, &cached, adp, tname);
+               tvc = afs_LookupVCache(&tfid, treq, &cached, adp, tname);
            }
            if (!tvc && !bulkcode) {    /* lookup failed or wasn't called */
-               tvc = afs_GetVCache(&tfid, &treq, &cached, NULL);
+               tvc = afs_GetVCache(&tfid, treq, &cached, NULL);
            }
        }                       /* if !tvc */
     }                          /* sub-block just to reduce stack usage */
@@ -1793,7 +1793,7 @@ afs_lookup(OSI_VC_DECL(adp), char *aname, struct vcache **avcp, afs_ucred_t *acr
            ObtainSharedLock(&tvc->lock, 680);
            if (!tvc->linkData) {
                UpgradeSToWLock(&tvc->lock, 681);
-               code = afs_HandleLink(tvc, &treq);
+               code = afs_HandleLink(tvc, treq);
                ConvertWToRLock(&tvc->lock);
            } else {
                ConvertSToRLock(&tvc->lock);
@@ -1815,7 +1815,7 @@ afs_lookup(OSI_VC_DECL(adp), char *aname, struct vcache **avcp, afs_ucred_t *acr
                struct volume *tvolp;
 
                ObtainWriteLock(&tvc->lock, 133);
-               code = EvalMountPoint(tvc, adp, &tvolp, &treq);
+               code = EvalMountPoint(tvc, adp, &tvolp, treq);
                ReleaseWriteLock(&tvc->lock);
 
                if (code) {
@@ -1837,9 +1837,9 @@ afs_lookup(OSI_VC_DECL(adp), char *aname, struct vcache **avcp, afs_ucred_t *acr
                    if (tvolp && (tvolp->states & VForeign)) {
                        /* XXXX tvolp has ref cnt on but not locked! XXX */
                        tvc =
-                           afs_GetRootVCache(tvc->mvid, &treq, NULL, tvolp);
+                           afs_GetRootVCache(tvc->mvid, treq, NULL, tvolp);
                    } else {
-                       tvc = afs_GetVCache(tvc->mvid, &treq, NULL, NULL);
+                       tvc = afs_GetVCache(tvc->mvid, treq, NULL, NULL);
                    }
                    afs_PutVCache(uvc); /* we're done with it */
 
@@ -1886,7 +1886,7 @@ afs_lookup(OSI_VC_DECL(adp), char *aname, struct vcache **avcp, afs_ucred_t *acr
        if (!AFS_IS_DISCONNECTED) {
            if (pass == 0) {
                struct volume *tv;
-               tv = afs_GetVolume(&adp->f.fid, &treq, READ_LOCK);
+               tv = afs_GetVolume(&adp->f.fid, treq, READ_LOCK);
                if (tv) {
                    if (tv->states & VRO) {
                        pass = 1;       /* try this *once* */
@@ -1929,9 +1929,10 @@ afs_lookup(OSI_VC_DECL(adp), char *aname, struct vcache **avcp, afs_ucred_t *acr
            } else {
 #ifdef AFS_LINUX20_ENV
                /* So Linux inode cache is up to date. */
-               code = afs_VerifyVCache(tvc, &treq);
+               code = afs_VerifyVCache(tvc, treq);
 #else
                afs_PutFakeStat(&fakestate);
+               afs_DestroyReq(treq);
                AFS_DISCON_UNLOCK();
                return 0;       /* can't have been any errors if hit and !code */
 #endif
@@ -1943,7 +1944,7 @@ afs_lookup(OSI_VC_DECL(adp), char *aname, struct vcache **avcp, afs_ucred_t *acr
     if (bulkcode)
        code = bulkcode;
 
-    code = afs_CheckCode(code, &treq, 19);
+    code = afs_CheckCode(code, treq, 19);
     if (code) {
        /* If there is an error, make sure *avcp is null.
         * Alphas panic otherwise - defect 10719.
@@ -1952,6 +1953,7 @@ afs_lookup(OSI_VC_DECL(adp), char *aname, struct vcache **avcp, afs_ucred_t *acr
     }
 
     afs_PutFakeStat(&fakestate);
+    afs_DestroyReq(treq);
     AFS_DISCON_UNLOCK();
     return code;
 }