#endif
+afs_int32 afs_bkvolpref = 0;
afs_int32 afs_bulkStatsDone;
static int bulkStatCounter = 0; /* counter for bulk stat seq. numbers */
int afs_fakestat_enable = 0; /* 1: fakestat-all, 2: fakestat-crosscell */
struct cell *tcell;
char *cpos, *volnamep;
char type, *buf;
- afs_int32 prefetchRO; /* 1=>No 2=>Yes */
+ afs_int32 prefetch; /* 1=>None 2=>RO 3=>BK */
afs_int32 mtptCell, assocCell, hac = 0;
afs_int32 samecell, roname, len;
&& (avc->fid.Cell ==
assocCell));
- /* Decide whether to prefetch the RO. Also means we want the RO.
- * If this is a regular mountpoint with a RW volume name and
- * we cross a cell boundary -or- start from a RO volume, then we will
- * want to prefetch the RO volume when we get the RW below.
+ /* Decide whether to prefetch the BK, or RO. Also means we want the BK or
+ * RO.
+ * If this is a regular mountpoint with a RW volume name
+ * - If BK preference is enabled AND we remain within the same cell AND
+ * start from a BK volume, then we will want to prefetch the BK volume.
+ * - If we cross a cell boundary OR start from a RO volume, then we will
+ * want to prefetch the RO volume.
*/
- if ((type == '#') && !roname && (!samecell || (avc->states & CRO))) {
- prefetchRO = 2; /* Yes, prefetch the RO */
+ 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 */
} else {
- prefetchRO = 1; /* No prefetch of the RO */
+ prefetch = 1; /* Do not prefetch */
}
/* Get the volume struct. Unless this volume name has ".readonly" or
* ".backup" in it, this will get the volume struct for the RW volume.
* The RO volume will be prefetched if requested (but not returned).
*/
- tvp =
- afs_GetVolumeByName(volnamep, mtptCell, prefetchRO, areq, WRITE_LOCK);
+ tvp = afs_GetVolumeByName(volnamep, mtptCell, prefetch, areq, WRITE_LOCK);
/* If no volume was found in this cell, try the associated linked cell */
if (!tvp && hac && areq->volumeError) {
tvp =
- afs_GetVolumeByName(volnamep, assocCell, prefetchRO, areq,
+ afs_GetVolumeByName(volnamep, assocCell, prefetch, areq,
WRITE_LOCK);
}
* 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 && (prefetchRO == 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");
return ENODEV;
}
- /* If we want (prefetched) the RO and it exists, then drop the
- * RW volume and get the RO. Othewise, go with the RW.
+ /* If we want (prefetched) the BK and it exists, then drop the RW volume
+ * and get the BK.
+ * Otherwise, if we want (prefetched0 the RO and it exists, then drop the
+ * RW volume and get the RO.
+ * Otherwise, go with the RW.
*/
- if ((prefetchRO == 2) && tvp->roVol) {
+ if ((prefetch == 3) && tvp->backVol) {
+ tfid.Fid.Volume = tvp->backVol; /* remember BK volume */
+ tfid.Cell = tvp->cell;
+ 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 */
+ } else if ((prefetch >= 2) && tvp->roVol) {
tfid.Fid.Volume = tvp->roVol; /* remember RO volume */
tfid.Cell = tvp->cell;
afs_PutVolume(tvp, WRITE_LOCK); /* release old volume */
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,
+Check_AtSys(register struct vcache *avc, char *aname,
struct sysname_info *state, struct vrequest *areq)
{
+ int num = 0;
+ char **sysnamelist[MAXSYSNAME];
+
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;
Next_AtSys(register struct vcache *avc, struct vrequest *areq,
struct sysname_info *state)
{
+ int num = afs_sysnamecount;
+ char **sysnamelist[MAXSYSNAME];
+
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)[state->index])
+ return 0; /* end of list */
+ }
+ strcpy(state->name + state->offset, (*sysnamelist)[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_HPUX1123_ENV)
+/* DEE should use the new afs_inode_t for all */
+extern int BlobScan(ino_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
+#endif
/* called with an unlocked directory and directory cookie. Areqp
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
- * 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)
/* 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->f, (dirCookie >> 5));
if (newIndex == 0)
break;
/* get a ptr to the dir entry */
dirEntryp =
- (struct DirEntry *)afs_dir_GetBlob(&dcp->f.inode, newIndex);
+ (struct DirEntry *)afs_dir_GetBlob(&dcp->f, newIndex);
if (!dirEntryp)
break;
afs_lookup(adp, aname, avcp, acred)
#endif /* UKERNEL */
#endif /* SUN5 || SGI */
-OSI_VC_DECL(adp);
+ OSI_VC_DECL(adp);
struct vcache **avcp;
char *aname;
struct AFS_UCRED *acred;
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);
{ /* sub-block just to reduce stack usage */
register struct dcache *tdc;
afs_size_t dirOffset, dirLen;
- ino_t theDir;
+ struct fcache *theDir;
struct VenusFid tfid;
/* now we have to lookup the next fid */
ReleaseReadLock(&tdc->lock);
ReleaseReadLock(&adp->lock);
afs_PutDCache(tdc);
+ if (tname && tname != aname)
+ osi_FreeLargeSpace(tname);
goto redo;
}
/* lookup the name in the appropriate dir, and return a cache entry
* on the resulting fid */
- theDir = tdc->f.inode;
+ theDir = &tdc->f;
code =
- afs_dir_LookupOffset(&theDir, sysState.name, &tfid.Fid,
+ afs_dir_LookupOffset(theDir, 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(theDir, sysState.name, &tfid.Fid,
&dirCookie);
tname = sysState.name;