ukernel: make web enhancements the default
[openafs.git] / src / afs / VNOPS / afs_vnop_lookup.c
index 1edeb2c..24e05a5 100644 (file)
@@ -670,9 +670,11 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp)
     long startTime;            /* time we started the call,
                                 * for callback expiration base
                                 */
+    int ftype[4] = {VNON, VREG, VDIR, VLNK}; /* verify type is as expected */
     afs_size_t statSeqNo = 0;  /* Valued of file size to detect races */
     int code;                  /* error code */
     long newIndex;             /* new index in the dir */
+    struct DirBuffer entry;    /* Buffer for dir manipulation */
     struct DirEntry *dirEntryp;        /* dir entry we are examining */
     int i;
     struct VenusFid afid;      /* file ID we are using now */
@@ -682,7 +684,6 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp)
     struct volume *volp = 0;   /* volume ptr */
     struct VenusFid dotdot = {0, {0, 0, 0}};
     int flagIndex = 0;         /* First file with bulk fetch flag set */
-    int inlinebulk = 0;                /* Did we use InlineBulk RPC or not? */
     struct rx_connection *rxconn;
     XSTATS_DECLS;
     dotdot.Cell = 0;
@@ -791,14 +792,14 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp)
        dirCookie = newIndex << 5;
 
        /* get a ptr to the dir entry */
-       dirEntryp =
-           (struct DirEntry *)afs_dir_GetBlob(dcp, newIndex);
-       if (!dirEntryp)
+       code = afs_dir_GetBlob(dcp, newIndex, &entry);
+       if (code)
            break;
+       dirEntryp = (struct DirEntry *)entry.data;
 
        /* dont copy more than we have room for */
        if (fidIndex >= nentries) {
-           DRelease(dirEntryp, 0);
+           DRelease(&entry, 0);
            break;
        }
 
@@ -817,7 +818,7 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp)
            do {
                retry = 0;
                ObtainWriteLock(&afs_xvcache, 130);
-               tvcp = afs_FindVCache(&tfid, &retry, IS_WLOCK|FIND_BULKDEAD /* no stats | LRU */ );
+               tvcp = afs_FindVCache(&tfid, &retry, IS_WLOCK /* no stats | LRU */ );
                if (tvcp && retry) {
                    ReleaseWriteLock(&afs_xvcache);
                    afs_PutVCache(tvcp);
@@ -827,19 +828,31 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp)
                tvcp = afs_NewBulkVCache(&tfid, hostp, statSeqNo);
                if (tvcp)
                {
-                       ObtainWriteLock(&tvcp->lock, 505);
-                       ReleaseWriteLock(&afs_xvcache);
-                       afs_RemoveVCB(&tfid);
-                       ReleaseWriteLock(&tvcp->lock);
+                   ObtainWriteLock(&tvcp->lock, 505);
+#ifdef AFS_DARWIN80_ENV
+                   /* use even/odd hack to guess file versus dir.
+                      let links be reaped. oh well. */
+                   if (dirEntryp->fid.vnode & 1)
+                       tvcp->f.m.Type = VDIR;
+                   else
+                       tvcp->f.m.Type = VREG;
+                   /* finalize to a best guess */
+                   afs_darwin_finalizevnode(tvcp, VTOAFS(adp), NULL, 0, 1);
+                   /* re-acquire usecount that finalizevnode disposed of */
+                   vnode_ref(AFSTOV(tvcp));
+#endif
+                   ReleaseWriteLock(&afs_xvcache);
+                   afs_RemoveVCB(&tfid);
+                   ReleaseWriteLock(&tvcp->lock);
                } else {
-                       ReleaseWriteLock(&afs_xvcache);
+                   ReleaseWriteLock(&afs_xvcache);
                }
            } else {
                ReleaseWriteLock(&afs_xvcache);
            }
            if (!tvcp)
            {
-               DRelease(dirEntryp, 0);
+               DRelease(&entry, 0);
                ReleaseReadLock(&dcp->lock);
                ReleaseReadLock(&adp->lock);
                afs_PutDCache(dcp);
@@ -898,7 +911,7 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp)
         * used by this dir entry.
         */
        temp = afs_dir_NameBlobs(dirEntryp->name) << 5;
-       DRelease(dirEntryp, 0);
+       DRelease(&entry, 0);
        if (temp <= 0)
            break;
        dirCookie += temp;
@@ -963,7 +976,6 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp)
            XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_BULKSTATUS);
 
            if (!(tcp->parent->srvr->server->flags & SNO_INLINEBULK)) {
-           retryonce:
                RX_AFS_GUNLOCK();
                code =
                    RXAFS_InlineBulkStatus(rxconn, &fidParm, &statParm,
@@ -971,29 +983,18 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp)
                RX_AFS_GLOCK();
                if (code == RXGEN_OPCODE) {
                    tcp->parent->srvr->server->flags |= SNO_INLINEBULK;
-                   inlinebulk = 0;
                    RX_AFS_GUNLOCK();
                    code =
                        RXAFS_BulkStatus(rxconn, &fidParm, &statParm,
                                         &cbParm, &volSync);
                    RX_AFS_GLOCK();
-               } else {
-                   inlinebulk = 1;
-                   if (!code && ((&statsp[0])->errorCode)) {
-                       /*
-                        * If this is an error needing retry, do so.
-                        * Retryable errors are all whole-volume or
-                        * whole-server.
-                        */
-                       if (afs_Analyze(tcp, rxconn, (&statsp[0])->errorCode,
-                                       &adp->f.fid, areqp,
-                                       AFS_STATS_FS_RPCIDX_BULKSTATUS,
-                                       SHARED_LOCK, NULL) != 0)
-                           goto retryonce;
-                   }
+               } 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 {
-               inlinebulk = 0;
                RX_AFS_GUNLOCK();
                code =
                    RXAFS_BulkStatus(rxconn, &fidParm, &statParm, &cbParm,
@@ -1110,7 +1111,7 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp)
        do {
            retry = 0;
            ObtainReadLock(&afs_xvcache);
-           tvcp = afs_FindVCache(&afid, &retry, FIND_CDEAD /* !stats&!lru */);
+           tvcp = afs_FindVCache(&afid, &retry, 0/* !stats&!lru */);
            ReleaseReadLock(&afs_xvcache);
        } while (tvcp && retry);
 
@@ -1126,9 +1127,12 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp)
         * matches the value we placed there when we set the CBulkFetching
         * flag, then someone else has done something with this node,
         * and we may not have the latest status information for this
-        * file.  Leave the entry alone.
+        * file.  Leave the entry alone. There's also a file type
+        * change here, for OSX bulkstat support.
         */
-       if (!(tvcp->f.states & CBulkFetching) || (tvcp->f.m.Length != statSeqNo)) {
+       if (!(tvcp->f.states & CBulkFetching)
+           || (tvcp->f.m.Length != statSeqNo)
+           || (ftype[(&statsp[i])->FileType] != vType(tvcp))) {
            flagIndex++;
            ReleaseWriteLock(&tvcp->lock);
            afs_PutVCache(tvcp);
@@ -1254,10 +1258,9 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp)
                afs_DequeueCallback(tvcp);
                if ((tvcp->f.states & CForeign) || (vType(tvcp) == VDIR))
                    osi_dnlc_purgedp(tvcp); /* if it (could be) a directory */
-           } else {
+           } else
                /* re-acquire the usecount that finalizevnode disposed of */
                vnode_ref(AFSTOV(tvcp));
-           }
        } else
 #endif
        ReleaseWriteLock(&afs_xcbhash);
@@ -1289,7 +1292,7 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp)
        do {
            retry = 0;
            ObtainReadLock(&afs_xvcache);
-           tvcp = afs_FindVCache(&afid, &retry, FIND_CDEAD /* !stats&!lru */);
+           tvcp = afs_FindVCache(&afid, &retry, 0 /* !stats&!lru */);
            ReleaseReadLock(&afs_xvcache);
        } while (tvcp && retry);
        if (tvcp != NULL) {
@@ -1303,16 +1306,6 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp)
     if (volp)
        afs_PutVolume(volp, READ_LOCK);
 
-    /* If we did the InlineBulk RPC pull out the return code */
-    if (inlinebulk && code == 0) {
-       if ((&statsp[0])->errorCode) {
-           afs_Analyze(tcp, rxconn, (&statsp[0])->errorCode, &adp->f.fid, areqp,
-                       AFS_STATS_FS_RPCIDX_BULKSTATUS, SHARED_LOCK, NULL);
-           code = (&statsp[0])->errorCode;
-       }
-    } else {
-       code = 0;
-    }
   done2:
     osi_FreeLargeSpace((char *)fidsp);
     osi_Free((char *)statsp, AFSCBMAX * sizeof(AFSFetchStatus));
@@ -1321,7 +1314,11 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp)
 }
 
 /* was: (AFS_DEC_ENV) || defined(AFS_OSF30_ENV) || defined(AFS_NCR_ENV) */
+#ifdef AFS_DARWIN80_ENV
+int AFSDOBULK = 1;
+#else
 static int AFSDOBULK = 1;
+#endif
 
 static_inline int
 osi_lookup_isdot(const char *aname)
@@ -1786,10 +1783,10 @@ afs_lookup(OSI_VC_DECL(adp), char *aname, struct vcache **avcp, afs_ucred_t *acr
        if (tvc->mvstat == 1 && (tvc->f.states & CMValid) && tvc->mvid != NULL)
          force_eval = 1; /* This is now almost for free, get it correct */
 
-#if defined(UKERNEL) && defined(AFS_WEB_ENHANCEMENTS)
+#if defined(UKERNEL)
        if (!(flags & AFS_LOOKUP_NOEVAL))
            /* don't eval mount points */
-#endif /* UKERNEL && AFS_WEB_ENHANCEMENTS */
+#endif /* UKERNEL */
            if (tvc->mvstat == 1 && force_eval) {
                /* a mt point, possibly unevaluated */
                struct volume *tvolp;
@@ -1897,13 +1894,13 @@ afs_lookup(OSI_VC_DECL(adp), char *aname, struct vcache **avcp, afs_ucred_t *acr
        if (afs_mariner)
            afs_AddMarinerName(aname, tvc);
 
-#if defined(UKERNEL) && defined(AFS_WEB_ENHANCEMENTS)
+#if defined(UKERNEL)
        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 */
+#endif /* UKERNEL */
            if (!hit && force_eval) {
                osi_dnlc_enter(adp, aname, tvc, &versionNo);
            } else {
@@ -1916,7 +1913,7 @@ afs_lookup(OSI_VC_DECL(adp), char *aname, struct vcache **avcp, afs_ucred_t *acr
                return 0;       /* can't have been any errors if hit and !code */
 #endif
            }
-#if defined(UKERNEL) && defined(AFS_WEB_ENHANCEMENTS)
+#if defined(UKERNEL)
        }
 #endif
     }