afs-lookup-put-back-vcache-entry-on-failed-evalmountpoint-20010927
[openafs.git] / src / afs / VNOPS / afs_vnop_lookup.c
index 93980d2..b81570c 100644 (file)
  * afs_index
  */
 
-#include "../afs/param.h"      /* Should be always first */
+#include <afsconfig.h>
+#include "../afs/param.h"
+
+RCSID("$Header$");
+
 #include "../afs/sysincludes.h"        /* Standard vendor system headers */
 #include "../afs/afsincludes.h"        /* Afs-based standard headers */
 #include "../afs/afs_stats.h" /* statistics */
@@ -129,7 +133,7 @@ EvalMountPoint(avc, advc, avolpp, areq)
        volnamep = &avc->linkData[1];
        tcell = afs_GetCell(avc->fid.Cell, READ_LOCK);
     }
-    if (!tcell) return ENOENT;
+    if (!tcell) return ENODEV;
 
     mtptCell = tcell->cell;               /* The cell for the mountpoint */
     if (tcell->lcellp) {
@@ -349,7 +353,7 @@ extern int BlobScan(afs_int32 *afile, afs_int32 ablob);
  * CForeign bit set.
  */
 struct vcache * BStvc = (struct vcache *) 0;
-void afs_DoBulkStat(adp, dirCookie, areqp)
+int afs_DoBulkStat(adp, dirCookie, areqp)
   struct vcache *adp;
   long dirCookie;
   struct vrequest *areqp;
@@ -393,6 +397,7 @@ void afs_DoBulkStat(adp, dirCookie, areqp)
     struct volume *volp=0;     /* volume ptr */
     struct VenusFid dotdot;
     int        flagIndex;              /* First file with bulk fetch flag set */
+    int inlinebulk=0;           /* Did we use InlineBulk RPC or not? */
     XSTATS_DECLS
 
     /* first compute some basic parameters.  We dont want to prefetch more
@@ -558,8 +563,7 @@ tagain:
                 * preserve the value of the file size. We could
                 * flush the pages, but it wouldn't be worthwhile.
                 */
-               bcopy((char *) &tfid.Fid, (char *)(fidsp+fidIndex),
-                     sizeof(*fidsp));
+               memcpy((char *)(fidsp+fidIndex), (char *) &tfid.Fid, sizeof(*fidsp));
                tvcp->states |= CBulkFetching;
                tvcp->m.Length = statSeqNo;
                fidIndex++;
@@ -604,8 +608,16 @@ tagain:
 #ifdef RX_ENABLE_LOCKS
            AFS_GUNLOCK();
 #endif /* RX_ENABLE_LOCKS */
-           code = RXAFS_BulkStatus(tcp->id, &fidParm, &statParm, &cbParm,
-                                   &volSync);
+           code = RXAFS_InlineBulkStatus(tcp->id, &fidParm, &statParm,
+                                         &cbParm, &volSync);
+           if (code == RXGEN_OPCODE) {
+               code = RXAFS_BulkStatus(tcp->id, &fidParm, &statParm, &cbParm,
+                                       &volSync);
+               inlinebulk=0;
+           } else {
+               inlinebulk=1;
+           }
+
 #ifdef RX_ENABLE_LOCKS
            AFS_GLOCK();
 #endif /* RX_ENABLE_LOCKS */
@@ -677,6 +689,8 @@ tagain:
      * We also have to take into account racing token revocations.
      */
     for(i=0; i<fidIndex; i++) {
+       if ((&statsp[i])->errorCode) 
+           continue;
        afid.Cell = adp->fid.Cell;
        afid.Fid.Volume = adp->fid.Fid.Volume;
        afid.Fid.Vnode = fidsp[i].Vnode;
@@ -843,8 +857,16 @@ tagain:
     if ( volp )
        afs_PutVolume(volp, READ_LOCK);
     
+    /* If we did the InlineBulk RPC pull out the return code */
+    if (inlinebulk && (&statsp[0])->errorCode) {
+       afs_Analyze(tcp, (&statsp[0])->errorCode, &adp->fid, areqp, 
+                   AFS_STATS_FS_RPCIDX_BULKSTATUS, SHARED_LOCK, 
+                   (struct cell *)0);
+       code = (&statsp[0])->errorCode;
+    }
     osi_FreeLargeSpace(statMemp);
     osi_FreeLargeSpace(cbfMemp);
+    return code;
 }
 
 /* was: (AFS_DEC_ENV) || defined(AFS_OSF30_ENV) || defined(AFS_NCR_ENV) */
@@ -866,8 +888,13 @@ afs_lookup(OSI_VC_ARG(adp), aname, avcp, pnp, flags, rdir, acred)
     int flags;
     struct vnode *rdir;
 #else
+#if defined(UKERNEL)
+afs_lookup(adp, aname, avcp, acred, flags)
+    int flags;
+#else    
 afs_lookup(adp, aname, avcp, acred)
-#endif
+#endif /* UKERNEL */
+#endif /* SUN5 || SGI */
     OSI_VC_DECL(adp);
     struct vcache **avcp;
     char *aname;
@@ -877,6 +904,7 @@ afs_lookup(adp, aname, avcp, acred)
     char *tname = (char *)0;
     register struct vcache *tvc=0;
     register afs_int32 code;
+    register afs_int32 bulkcode = 0;
     int pass = 0, hit = 0;
     long dirCookie;
     extern afs_int32 afs_mariner;                      /*Writing activity to log?*/
@@ -888,14 +916,14 @@ afs_lookup(adp, aname, avcp, acred)
     AFS_STATCNT(afs_lookup);
 #ifdef AFS_OSF_ENV
     ndp->ni_dvp = (struct vnode *)adp;
-    bcopy(ndp->ni_ptr, aname, ndp->ni_namelen);
+    memcpy(aname, ndp->ni_ptr, ndp->ni_namelen);
     aname[ndp->ni_namelen] = '\0';
 #endif /* AFS_OSF_ENV */
 
     *avcp = (struct vcache *) 0;   /* Since some callers don't initialize it */
 
     if (code = afs_InitReq(&treq, acred)) { 
-      goto done;
+       goto done;
     }
 
     /* come back to here if we encounter a non-existent object in a read-only
@@ -903,10 +931,12 @@ afs_lookup(adp, aname, avcp, acred)
 
   redo:
     *avcp = (struct vcache *) 0;   /* Since some callers don't initialize it */
+    bulkcode = 0;
 
     if (!(adp->states & CStatd)) {
-       if (code = afs_VerifyVCache2(adp, &treq))
-         goto done;
+       if (code = afs_VerifyVCache2(adp, &treq)) {
+           goto done;
+       }
     }
     else code = 0;
 
@@ -972,13 +1002,13 @@ afs_lookup(adp, aname, avcp, acred)
        ObtainReadLock(&afs_xvcache);   
        osi_vnhold(adp, 0);
        ReleaseReadLock(&afs_xvcache);  
-      code = 0;
-      *avcp = tvc = adp;
-      hit = 1;
+       code = 0;
+       *avcp = tvc = adp;
+       hit = 1;
        if (adp && !adp->vrefCount) {
            osi_Panic("TT2");
        }
-      goto done;
+       goto done;
     }
 
     Check_AtSys(adp, aname, &sysState, &treq);
@@ -994,8 +1024,8 @@ afs_lookup(adp, aname, avcp, acred)
     tvc = osi_dnlc_lookup (adp, tname, WRITE_LOCK);
     *avcp = tvc;  /* maybe wasn't initialized, but it is now */
     if (tvc) {
-       if (no_read_access && vType(tvc) != VDIR) {
-           /* need read access on dir to stat non-directory */
+       if (no_read_access && vType(tvc) != VDIR && vType(tvc) != VLNK) {
+           /* need read access on dir to stat non-directory / non-link */
            afs_PutVCache(tvc, WRITE_LOCK);
            *avcp = (struct vcache *)0;
            code = EACCES;
@@ -1114,23 +1144,26 @@ afs_lookup(adp, aname, avcp, acred)
           ReleaseReadLock(&afs_xvcache);       
         } while (tvc && retry);
 
-       if (!tvc || !(tvc->states & CStatd)) {
-           afs_DoBulkStat(adp, dirCookie, &treq);
-       }
+       if (!tvc || !(tvc->states & CStatd)) 
+           bulkcode = afs_DoBulkStat(adp, dirCookie, &treq);
+       else 
+           bulkcode = 0;
 
        /* if the vcache isn't usable, release it */
        if (tvc && !(tvc->states & CStatd)) {
            afs_PutVCache(tvc);
            tvc = (struct vcache *) 0;
        }
+    } else {
+       tvc = (struct vcache *) 0;
+       bulkcode = 0;
     }
-    else tvc = (struct vcache *) 0;
-    
+
     /* now get the status info, if we don't already have it */
     /* This is kind of weird, but we might wind up accidentally calling
      * RXAFS_Lookup because we happened upon a file which legitimately
      * has a 0 uniquifier. That is the result of allowing unique to wrap
-     * to 0. This was fixed in AFS 3.4. For CForeigh, Unique == 0 means that
+     * to 0. This was fixed in AFS 3.4. For CForeign, Unique == 0 means that
      * the file has not yet been looked up.
      */
     if (!tvc) {
@@ -1139,10 +1172,10 @@ afs_lookup(adp, aname, avcp, acred)
            tvc = afs_LookupVCache(&tfid, &treq, &cached, WRITE_LOCK, 
                                   adp, tname);
        } 
-       if (!tvc) {  /* lookup failed or wasn't called */
-           tvc = afs_GetVCache(&tfid, &treq, &cached, (struct vcache*)0,
-                               WRITE_LOCK);
-       }
+       if (!tvc && !bulkcode) {  /* lookup failed or wasn't called */
+          tvc = afs_GetVCache(&tfid, &treq, &cached, (struct vcache*)0,
+                              WRITE_LOCK);
+       } 
     } /* if !tvc */
     } /* sub-block just to reduce stack usage */
 
@@ -1152,6 +1185,11 @@ afs_lookup(adp, aname, avcp, acred)
        tvc->parentVnode = adp->fid.Fid.Vnode;
        tvc->parentUnique = adp->fid.Fid.Unique;
        tvc->states &= ~CBulkStat;
+
+#if defined(UKERNEL) && defined(AFS_WEB_ENHANCEMENTS)
+        if (!(flags & AFS_LOOKUP_NOEVAL))
+          /* don't eval mount points */
+#endif /* UKERNEL && AFS_WEB_ENHANCEMENTS */
        if (tvc->mvstat == 1) {
          /* a mt point, possibly unevaluated */
          struct volume *tvolp;
@@ -1161,6 +1199,7 @@ afs_lookup(adp, aname, avcp, acred)
            ReleaseWriteLock(&tvc->lock);
 
            if (code) {
+               afs_PutVCache(tvc, WRITE_LOCK);
                if (tvolp) afs_PutVolume(tvolp, WRITE_LOCK);
                goto done;
            }
@@ -1260,6 +1299,14 @@ done:
 
        if (afs_mariner)
          afs_AddMarinerName(aname, tvc); 
+
+#if defined(UKERNEL) && defined(AFS_WEB_ENHANCEMENTS)
+        if (!(flags & AFS_LOOKUP_NOEVAL))
+       /* Here we don't enter the name into the DNLC because we want the
+        evaluated mount dir to be there (the vcache for the mounted volume)
+        rather than the vc of the mount point itself.  we can still find the
+        mount point's vc in the vcache by its fid. */
+#endif /* UKERNEL && AFS_WEB_ENHANCEMENTS */
        if (!hit) {
          osi_dnlc_enter (adp, aname, tvc, &versionNo);
        }
@@ -1272,6 +1319,7 @@ done:
 #endif
        }
     }
+    if (bulkcode) code = bulkcode; else 
     code = afs_CheckCode(code, &treq, 19);
     if (code) {
        /* If there is an error, make sure *avcp is null.