checksysname-stack-usage-20050721
[openafs.git] / src / afs / VNOPS / afs_vnop_lookup.c
index e9d760a..be887e7 100644 (file)
@@ -31,10 +31,6 @@ RCSID
 
 extern struct DirEntry *afs_dir_GetBlob();
 
-#ifdef AFS_LINUX22_ENV
-extern struct inode_operations afs_symlink_iops, afs_dir_iops;
-#endif
-
 
 afs_int32 afs_bkvolpref = 0;
 afs_int32 afs_bulkStatsDone;
@@ -64,11 +60,11 @@ EvalMountPoint(register struct vcache *avc, struct vcache *advc,
     struct volume *tvp = 0;
     struct VenusFid tfid;
     struct cell *tcell;
-    char   *cpos, *volnamep;
-    char   type, *buf;
-    afs_int32  prefetch;          /* 1=>None  2=>RO  3=>BK */
-    afs_int32  mtptCell, assocCell, hac = 0;
-    afs_int32  samecell, roname, len;
+    char *cpos, *volnamep;
+    char type, *buf;
+    afs_int32 prefetch;                /* 1=>None  2=>RO  3=>BK */
+    afs_int32 mtptCell, assocCell = 0, hac = 0;
+    afs_int32 samecell, roname, len;
 
     AFS_STATCNT(EvalMountPoint);
 #ifdef notdef
@@ -121,14 +117,14 @@ EvalMountPoint(register struct vcache *avc, struct vcache *advc,
      *   want to prefetch the RO volume.
      */
     if ((type == '#') && !roname) {
-       if (afs_bkvolpref && samecell && (avc->states & CBackup))
-           prefetch = 3; /* Prefetch the BK */
-       else if (!samecell || (avc->states & CRO))
-           prefetch = 2; /* Prefetch the RO */
-       else
-           prefetch = 1; /* Do not prefetch */
+       if (afs_bkvolpref && samecell && (avc->states & CBackup))
+           prefetch = 3;       /* Prefetch the BK */
+       else if (!samecell || (avc->states & CRO))
+           prefetch = 2;       /* Prefetch the RO */
+       else
+           prefetch = 1;       /* Do not prefetch */
     } else {
-       prefetch = 1; /* Do not prefetch */
+       prefetch = 1;           /* Do not prefetch */
     }
 
     /* Get the volume struct. Unless this volume name has ".readonly" or
@@ -139,7 +135,7 @@ EvalMountPoint(register struct vcache *avc, struct vcache *advc,
 
     /* If no volume was found in this cell, try the associated linked cell */
     if (!tvp && hac && areq->volumeError) {
-       tvp =
+       tvp =
            afs_GetVolumeByName(volnamep, assocCell, prefetch, areq,
                                WRITE_LOCK);
     }
@@ -148,8 +144,8 @@ EvalMountPoint(register struct vcache *avc, struct vcache *advc,
      * doesn't exist? Try adding ".readonly" to volname and look for that.
      * Don't know why we do this. Would have still found it in above call - jpm.
      */
-    if (!tvp && (prefetch == 2)) {
-       buf = (char *)osi_AllocSmallSpace(strlen(volnamep) + 10);
+    if (!tvp && (prefetch == 2) && len < AFS_SMALLOCSIZ - 10) {
+       buf = (char *)osi_AllocSmallSpace(len + 10);
 
        strcpy(buf, volnamep);
        afs_strcat(buf, ".readonly");
@@ -191,7 +187,7 @@ EvalMountPoint(register struct vcache *avc, struct vcache *advc,
        afs_PutVolume(tvp, WRITE_LOCK); /* release old volume */
        tvp = afs_GetVolume(&tfid, areq, WRITE_LOCK);   /* get the new one */
        if (!tvp)
-          return ENODEV;       /* oops, can't do it */
+           return ENODEV;      /* oops, can't do it */
     }
 
     if (avc->mvid == 0)
@@ -400,45 +396,55 @@ afs_ENameOK(register char *aname)
     return 1;
 }
 
-int
+static int
 afs_getsysname(register struct vrequest *areq, register struct vcache *adp,
-              register char *bufp)
+              register char *bufp, int *num, char **sysnamelist[])
 {
     register struct unixuser *au;
     register afs_int32 error;
 
-    if (!afs_nfsexporter) {
-       strcpy(bufp, afs_sysname);
-       return 0;
-    }
     AFS_STATCNT(getsysname);
-    au = afs_GetUser(areq->uid, adp->fid.Cell, 0);
-    afs_PutUser(au, 0);
-    if (au->exporter) {
-       error = EXP_SYSNAME(au->exporter, NULL, bufp);
-       if (error)
-           strcpy(bufp, "@sys");
-       return -1;
-    } else {
-       strcpy(bufp, afs_sysname);
-       return 0;
+
+    *sysnamelist = afs_sysnamelist;
+
+    if (!afs_nfsexporter)
+       strcpy(bufp, (*sysnamelist)[0]);
+    else {
+       au = afs_GetUser(areq->uid, adp->fid.Cell, 0);
+       if (au->exporter) {
+           error = EXP_SYSNAME(au->exporter, (char *)0, sysnamelist, num);
+           if (error) {
+               strcpy(bufp, "@sys");
+               afs_PutUser(au, 0);
+               return -1;
+           } else {
+               strcpy(bufp, (*sysnamelist)[0]);
+           }
+       } else
+           strcpy(bufp, afs_sysname);
+       afs_PutUser(au, 0);
     }
+    return 0;
 }
 
 void
 Check_AtSys(register struct vcache *avc, const char *aname,
            struct sysname_info *state, struct vrequest *areq)
 {
+    int num = 0;
+    char **sysnamelist[MAXNUMSYSNAMES];
+
     if (AFS_EQ_ATSYS(aname)) {
        state->offset = 0;
        state->name = (char *)osi_AllocLargeSpace(AFS_SMALLOCSIZ);
        state->allocked = 1;
-       state->index = afs_getsysname(areq, avc, state->name);
+       state->index =
+           afs_getsysname(areq, avc, state->name, &num, sysnamelist);
     } else {
        state->offset = -1;
        state->allocked = 0;
        state->index = 0;
-       state->name = aname;
+       state->name = (char *)aname;
     }
 }
 
@@ -446,43 +452,58 @@ int
 Next_AtSys(register struct vcache *avc, struct vrequest *areq,
           struct sysname_info *state)
 {
+    int num = afs_sysnamecount;
+    char **sysnamelist[MAXNUMSYSNAMES];
+
     if (state->index == -1)
        return 0;               /* No list */
 
     /* Check for the initial state of aname != "@sys" in Check_AtSys */
     if (state->offset == -1 && state->allocked == 0) {
        register char *tname;
+
        /* Check for .*@sys */
        for (tname = state->name; *tname; tname++)
            /*Move to the end of the string */ ;
+
        if ((tname > state->name + 4) && (AFS_EQ_ATSYS(tname - 4))) {
            state->offset = (tname - 4) - state->name;
            tname = (char *)osi_AllocLargeSpace(AFS_LRALLOCSIZ);
            strncpy(tname, state->name, state->offset);
            state->name = tname;
            state->allocked = 1;
+           num = 0;
            state->index =
-               afs_getsysname(areq, avc, state->name + state->offset);
+               afs_getsysname(areq, avc, state->name + state->offset, &num,
+                              sysnamelist);
            return 1;
        } else
            return 0;           /* .*@sys doesn't match either */
-    } else if (++(state->index) >= afs_sysnamecount
-              || !afs_sysnamelist[(int)state->index])
-       return 0;               /* end of list */
-    strcpy(state->name + state->offset, afs_sysnamelist[(int)state->index]);
+    } else {
+       register struct unixuser *au;
+       register afs_int32 error;
+
+       *sysnamelist = afs_sysnamelist;
+
+       if (afs_nfsexporter) {
+           au = afs_GetUser(areq->uid, avc->fid.Cell, 0);
+           if (au->exporter) {
+               error =
+                   EXP_SYSNAME(au->exporter, (char *)0, sysnamelist, num);
+               if (error) {
+                   return 0;
+               }
+           }
+           afs_PutUser(au, 0);
+       }
+       if (++(state->index) >= num || !(*sysnamelist)[(unsigned int)state->index])
+           return 0;           /* end of list */
+    }
+    strcpy(state->name + state->offset, (*sysnamelist)[(unsigned int)state->index]);
     return 1;
 }
 
-#if (defined(AFS_SGI62_ENV) || defined(AFS_SUN57_64BIT_ENV))
-extern int BlobScan(ino64_t * afile, afs_int32 ablob);
-#else
-#if defined AFS_LINUX_64BIT_KERNEL
-extern int BlobScan(long *afile, afs_int32 ablob);
-#else
-extern int BlobScan(afs_int32 * afile, afs_int32 ablob);
-#endif
-#endif
-
+extern int BlobScan(struct dcache * afile, afs_int32 ablob);
 
 /* called with an unlocked directory and directory cookie.  Areqp
  * describes who is making the call.
@@ -521,14 +542,14 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp)
     struct afs_q *tq;          /* temp queue variable */
     AFSCBFids fidParm;         /* file ID parm for bulk stat */
     AFSBulkStats statParm;     /* stat info parm for bulk stat */
-    int fidIndex;              /* which file were stating */
-    struct conn *tcp;          /* conn for call */
+    int fidIndex = 0;          /* which file were stating */
+    struct conn *tcp = 0;      /* conn for call */
     AFSCBs cbParm;             /* callback parm for bulk stat */
     struct server *hostp = 0;  /* host we got callback from */
     long startTime;            /* time we started the call,
                                 * for callback expiration base
                                 */
-    afs_size_t statSeqNo;      /* Valued of file size to detect races */
+    afs_size_t statSeqNo = 0;  /* Valued of file size to detect races */
     int code;                  /* error code */
     long newIndex;             /* new index in the dir */
     struct DirEntry *dirEntryp;        /* dir entry we are examining */
@@ -539,15 +560,15 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp)
     long volStates;            /* flags from vol structure */
     struct volume *volp = 0;   /* volume ptr */
     struct VenusFid dotdot;
-    int flagIndex;             /* First file with bulk fetch flag set */
+    int flagIndex = 0;         /* 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
-        * than a fraction of the cache in any given call, and we want to preserve
-        * a portion of the LRU queue in any event, so as to avoid thrashing
-        * the entire stat cache (we will at least leave some of it alone).
-        * presently dont stat more than 1/8 the cache in any one call.      */
-       nentries = afs_cacheStats / 8;
+    XSTATS_DECLS;
+    /* first compute some basic parameters.  We dont want to prefetch more
+     * than a fraction of the cache in any given call, and we want to preserve
+     * a portion of the LRU queue in any event, so as to avoid thrashing
+     * the entire stat cache (we will at least leave some of it alone).
+     * presently dont stat more than 1/8 the cache in any one call.      */
+    nentries = afs_cacheStats / 8;
 
     /* dont bother prefetching more than one calls worth of info */
     if (nentries > AFSCBMAX)
@@ -581,12 +602,12 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp)
   tagain:
     code = afs_VerifyVCache(adp, areqp);
     if (code)
-       goto done;
+       goto done2;
 
     dcp = afs_GetDCache(adp, (afs_size_t) 0, areqp, &temp, &temp, 1);
     if (!dcp) {
        code = ENOENT;
-       goto done;
+       goto done2;
     }
 
     /* lock the directory cache entry */
@@ -635,7 +656,7 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp)
        /* look for first safe entry to examine in the directory.  BlobScan
         * looks for a the 1st allocated dir after the dirCookie slot.
         */
-       newIndex = BlobScan(&dcp->f.inode, (dirCookie >> 5));
+       newIndex = BlobScan(dcp, (dirCookie >> 5));
        if (newIndex == 0)
            break;
 
@@ -644,7 +665,7 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp)
 
        /* get a ptr to the dir entry */
        dirEntryp =
-           (struct DirEntry *)afs_dir_GetBlob(&dcp->f.inode, newIndex);
+           (struct DirEntry *)afs_dir_GetBlob(dcp, newIndex);
        if (!dirEntryp)
            break;
 
@@ -949,12 +970,8 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp)
         * We only do this if the entry looks clear.
         */
        afs_ProcessFS(tvcp, &statsp[i], areqp);
-#ifdef AFS_LINUX22_ENV
-       /* overwrite the ops if it's a directory or symlink. */
-       if (vType(tvcp) == VDIR)
-           tvcp->v.v_op = &afs_dir_iops;
-       else if (vType(tvcp) == VLNK)
-           tvcp->v.v_op = &afs_symlink_iops;
+#if defined(AFS_LINUX22_ENV)
+       afs_fill_inode(AFSTOV(tvcp), NULL);     /* reset inode operations */
 #endif
 
        /* do some accounting for bulk stats: mark this entry as
@@ -1042,6 +1059,7 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp)
     } else {
        code = 0;
     }
+  done2:
     osi_FreeLargeSpace(statMemp);
     osi_FreeLargeSpace(cbfMemp);
     return code;
@@ -1051,36 +1069,16 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp)
 static int AFSDOBULK = 1;
 
 int
-#ifdef AFS_OSF_ENV
-afs_lookup(adp, ndp)
-     struct vcache *adp;
-     struct nameidata *ndp;
-{
-    char aname[MAXNAMLEN + 1]; /* XXX */
-    struct vcache **avcp = (struct vcache **)&(ndp->ni_vp);
-    struct ucred *acred = ndp->ni_cred;
-    int wantparent = ndp->ni_nameiop & WANTPARENT;
-    int opflag = ndp->ni_nameiop & OPFLAG;
-#else                          /* AFS_OSF_ENV */
-#if    defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
-afs_lookup(OSI_VC_ARG(adp), aname, avcp, pnp, flags, rdir, acred)
-     struct pathname *pnp;
-     int flags;
-     struct vnode *rdir;
-#else
-#if defined(UKERNEL)
-afs_lookup(adp, aname, avcp, acred, flags)
-     int flags;
+#ifdef AFS_OSF_ENV
+afs_lookup(OSI_VC_DECL(adp), char *aname, struct vcache **avcp, struct AFS_UCRED *acred, int opflag, int wantparent)
+#elif defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
+afs_lookup(OSI_VC_DECL(adp), char *aname, struct vcache **avcp, struct pathname *pnp, int flags, struct vnode *rdir, struct AFS_UCRED *acred)
+#elif defined(UKERNEL)
+afs_lookup(OSI_VC_DECL(adp), char *aname, struct vcache **avcp, struct AFS_UCRED *acred, int flags)
 #else
-afs_lookup(adp, aname, avcp, acred)
-#endif                         /* UKERNEL */
-#endif                         /* SUN5 || SGI */
-OSI_VC_DECL(adp);
-     struct vcache **avcp;
-     char *aname;
-     struct AFS_UCRED *acred;
-{
+afs_lookup(OSI_VC_DECL(adp), char *aname, struct vcache **avcp, struct AFS_UCRED *acred)
 #endif
+{
     struct vrequest treq;
     char *tname = NULL;
     register struct vcache *tvc = 0;
@@ -1089,13 +1087,13 @@ OSI_VC_DECL(adp);
     int pass = 0, hit = 0;
     long dirCookie;
     extern afs_int32 afs_mariner;      /*Writing activity to log? */
-    OSI_VC_CONVERT(adp)
     afs_hyper_t versionNo;
     int no_read_access = 0;
     struct sysname_info sysState;      /* used only for @sys checking */
     int dynrootRetry = 1;
     struct afs_fakestat_state fakestate;
     int tryEvalOnly = 0;
+    OSI_VC_CONVERT(adp);
 
     AFS_STATCNT(afs_lookup);
     afs_InitFakeStat(&fakestate);
@@ -1105,8 +1103,6 @@ OSI_VC_DECL(adp);
 
 #ifdef AFS_OSF_ENV
     ndp->ni_dvp = AFSTOV(adp);
-    memcpy(aname, ndp->ni_ptr, ndp->ni_namelen);
-    aname[ndp->ni_namelen] = '\0';
 #endif /* AFS_OSF_ENV */
 
 #if defined(AFS_DARWIN_ENV)
@@ -1194,7 +1190,7 @@ OSI_VC_DECL(adp);
 
     /* 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_LOOKUP, &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,
@@ -1237,7 +1233,7 @@ OSI_VC_DECL(adp);
        }
 #ifdef AFS_LINUX22_ENV
        if (tvc->mvstat == 2) { /* we don't trust the dnlc for root vcaches */
-           AFS_RELE(tvc);
+           AFS_RELE(AFSTOV(tvc));
            *avcp = 0;
        } else {
            code = 0;
@@ -1254,7 +1250,6 @@ OSI_VC_DECL(adp);
     {                          /* sub-block just to reduce stack usage */
        register struct dcache *tdc;
        afs_size_t dirOffset, dirLen;
-       ino_t theDir;
        struct VenusFid tfid;
 
        /* now we have to lookup the next fid */
@@ -1291,6 +1286,8 @@ OSI_VC_DECL(adp);
            ReleaseReadLock(&tdc->lock);
            ReleaseReadLock(&adp->lock);
            afs_PutDCache(tdc);
+           if (tname && tname != aname)
+               osi_FreeLargeSpace(tname);
            goto redo;
        }
 
@@ -1310,15 +1307,14 @@ OSI_VC_DECL(adp);
 
        /* lookup the name in the appropriate dir, and return a cache entry
         * on the resulting fid */
-       theDir = tdc->f.inode;
        code =
-           afs_dir_LookupOffset(&theDir, sysState.name, &tfid.Fid,
+           afs_dir_LookupOffset(tdc, sysState.name, &tfid.Fid,
                                 &dirCookie);
 
        /* If the first lookup doesn't succeed, maybe it's got @sys in the name */
        while (code == ENOENT && Next_AtSys(adp, &treq, &sysState))
            code =
-               afs_dir_LookupOffset(&theDir, sysState.name, &tfid.Fid,
+               afs_dir_LookupOffset(tdc, sysState.name, &tfid.Fid,
                                     &dirCookie);
        tname = sysState.name;