From 6a5d19930a7f8a9e232db8207dcb14cdf0f1b45b Mon Sep 17 00:00:00 2001 From: Ted McCabe Date: Tue, 5 Jun 2001 15:46:24 +0000 Subject: [PATCH] sysname-list-instead-of-simple-name-20010605 allow a sysname list which is interated in lookup instead of a simple namespace ==================== This delta was composed from multiple commits as part of the CVS->Git migration. The checkin message with each commit was inconsistent. The following are the additional commit messages. ==================== remove bit which leaked in --- src/afs/VNOPS/afs_vnop_lookup.c | 207 +++++++++++++++----------------- src/afs/afs.h | 6 + src/afs/afs_init.c | 11 +- src/afs/afs_pioctl.c | 105 ++++++++++++---- src/venus/fs.c | 25 ++-- 5 files changed, 209 insertions(+), 145 deletions(-) diff --git a/src/afs/VNOPS/afs_vnop_lookup.c b/src/afs/VNOPS/afs_vnop_lookup.c index 289c15b9c..93980d2e6 100644 --- a/src/afs/VNOPS/afs_vnop_lookup.c +++ b/src/afs/VNOPS/afs_vnop_lookup.c @@ -40,6 +40,8 @@ extern afs_rwlock_t afs_xvcache; extern afs_rwlock_t afs_xcbhash; extern struct afs_exporter *afs_nfsexporter; extern char *afs_sysname; +extern char *afs_sysnamelist[]; +extern int afs_sysnamecount; extern struct afs_q VLRU; /*vcache LRU*/ #ifdef AFS_LINUX22_ENV extern struct inode_operations afs_symlink_iops, afs_dir_iops; @@ -242,85 +244,82 @@ afs_ENameOK(aname) return 1; } -Check_AtSys(avc, aname, outb, areq) - register struct vcache *avc; - char *aname, **outb; - struct vrequest *areq; -{ - register char *tname; - register int error = 0, offset = -1; - - for (tname=aname; *tname; tname++) /*Move to the end of the string*/; - - /* - * If the current string is 4 chars long or more, check to see if the - * tail end is "@sys". - */ - if ((tname >= aname + 4) && (AFS_EQ_ATSYS(tname-4))) - offset = (tname - 4) - aname; - if (offset < 0) { - tname = aname; - } else { - tname = (char *) osi_AllocLargeSpace(AFS_LRALLOCSIZ); - if (offset) - strncpy(tname, aname, offset); - if (!afs_nfsexporter) - strcpy(tname+offset, (afs_sysname ? afs_sysname : SYS_NAME )); - else { - register struct unixuser *au; - register afs_int32 error; - au = afs_GetUser(areq->uid, avc->fid.Cell, 0); afs_PutUser(au, 0); - if (au->exporter) { - error = EXP_SYSNAME(au->exporter, (char *)0, tname+offset); - if (error) - strcpy(tname+offset, "@sys"); - } else { - strcpy(tname+offset, (afs_sysname ? afs_sysname : SYS_NAME )); - } - } - error = 1; - } - *outb = tname; - return error; -} - - -char *afs_getsysname(areq, adp) +afs_getsysname(areq, adp, bufp) register struct vrequest *areq; - register struct vcache *adp; { + register struct vcache *adp; + register char *bufp; +{ static char sysname[MAXSYSNAME]; register struct unixuser *au; register afs_int32 error; + if (!afs_nfsexporter) { + strcpy(bufp, afs_sysname); + return 0; + } AFS_STATCNT(getsysname); - /* this whole interface is wrong, it should take a buffer ptr and copy - * the data out. - */ au = afs_GetUser(areq->uid, adp->fid.Cell, 0); afs_PutUser(au, 0); if (au->exporter) { - error = EXP_SYSNAME(au->exporter, (char *)0, sysname); - if (error) return "@sys"; - else return sysname; + error = EXP_SYSNAME(au->exporter, (char *)0, bufp); + if (error) + strcpy(bufp, "@sys"); + return -1; } else { - return (afs_sysname == 0? SYS_NAME : afs_sysname); + strcpy(bufp, afs_sysname); + return 0; } } -void afs_HandleAtName(aname, aresult, areq, adp) - register char *aname; - register char *aresult; - register struct vrequest *areq; - register struct vcache *adp; { - register int tlen; - AFS_STATCNT(HandleAtName); - tlen = strlen(aname); - if (tlen >= 4 && strcmp(aname+tlen-4, "@sys")==0) { - strncpy(aresult, aname, tlen-4); - strcpy(aresult+tlen-4, afs_getsysname(areq, adp)); - } - else strcpy(aresult, aname); +Check_AtSys(avc, aname, state, areq) + register struct vcache *avc; + char *aname; + struct sysname_info *state; + struct vrequest *areq; +{ + 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); + } else { + state->offset = -1; + state->allocked = 0; + state->index = 0; + state->name = aname; } +} + +Next_AtSys(avc, areq, state) + register struct vcache *avc; + struct vrequest *areq; + struct sysname_info *state; +{ + 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; + state->index = afs_getsysname(areq, avc, state->name+state->offset); + return 1; + } else + return 0; /* .*@sys doesn't match either */ + } else if (++(state->index) >= afs_sysnamecount + || !afs_sysnamelist[state->index]) + return 0; /* end of list */ + strcpy(state->name+state->offset, afs_sysnamelist[state->index]); + return 1; +} #if (defined(AFS_SGI62_ENV) || defined(AFS_SUN57_64BIT_ENV)) extern int BlobScan(ino64_t *afile, afs_int32 ablob); @@ -884,6 +883,7 @@ afs_lookup(adp, aname, avcp, acred) OSI_VC_CONVERT(adp) afs_hyper_t versionNo; int no_read_access = 0; + struct sysname_info sysState; /* used only for @sys checking */ AFS_STATCNT(afs_lookup); #ifdef AFS_OSF_ENV @@ -898,39 +898,6 @@ afs_lookup(adp, aname, avcp, acred) goto done; } - /* lookup the name aname in the appropriate dir, and return a cache entry - on the resulting fid */ - - /* - * check for, and handle "@sys" if it's there. We should be able - * to avoid the alloc and the strcpy with a little work, but it's - * not pressing. If there aren't any remote users (ie, via the - * NFS translator), we have a slightly easier job. - * the faster way to do this is to check for *aname == '@' and if - * it's there, check for @sys, otherwise, assume there's no @sys - * then, if the lookup fails, check for .*@sys... - */ - if (!AFS_EQ_ATSYS(aname)) { - tname = aname; - } - else { - tname = (char *) osi_AllocLargeSpace(AFS_SMALLOCSIZ); - if (!afs_nfsexporter) - strcpy(tname, (afs_sysname ? afs_sysname : SYS_NAME )); - else { - register struct unixuser *au; - register afs_int32 error; - au = afs_GetUser(treq.uid, adp->fid.Cell, 0); afs_PutUser(au, 0); - if (au->exporter) { - error = EXP_SYSNAME(au->exporter, (char *)0, tname); - if (error) - strcpy(tname, "@sys"); - } else { - strcpy(tname, (afs_sysname ? afs_sysname : SYS_NAME )); - } - } - } - /* come back to here if we encounter a non-existent object in a read-only volume's directory */ @@ -944,7 +911,7 @@ afs_lookup(adp, aname, avcp, acred) else code = 0; /* watch for ".." in a volume root */ - if (adp->mvstat == 2 && tname[0] == '.' && tname[1] == '.' && !tname[2]) { + if (adp->mvstat == 2 && aname[0] == '.' && aname[1] == '.' && !aname[2]) { /* looking up ".." in root via special hacks */ if (adp->mvid == (struct VenusFid *) 0 || adp->mvid->Fid.Volume == 0) { #ifdef AFS_OSF_ENV @@ -1001,7 +968,7 @@ afs_lookup(adp, aname, avcp, acred) * I'm not fiddling with the LRUQ here, either, perhaps I should, or else * invent a lightweight version of GetVCache. */ - if (tname[0] == '.' && !tname[1]) { /* special case */ + if (aname[0] == '.' && !aname[1]) { /* special case */ ObtainReadLock(&afs_xvcache); osi_vnhold(adp, 0); ReleaseReadLock(&afs_xvcache); @@ -1014,6 +981,16 @@ afs_lookup(adp, aname, avcp, acred) goto done; } + Check_AtSys(adp, aname, &sysState, &treq); + tname = sysState.name; + + /* 1st Check_AtSys and lookup by tname is required here, for now, + because the dnlc is *not* told to remove entries for the parent + dir of file/dir op that afs_LocalHero likes, but dnlc is informed + if the cached entry for the parent dir is invalidated for a + non-local change. + Otherwise, we'd be able to do a dnlc lookup on an entry ending + w/@sys and know the dnlc was consistent with reality. */ tvc = osi_dnlc_lookup (adp, tname, WRITE_LOCK); *avcp = tvc; /* maybe wasn't initialized, but it is now */ if (tvc) { @@ -1057,7 +1034,6 @@ afs_lookup(adp, aname, avcp, acred) /* now we will just call dir package with appropriate inode. Dirs are always fetched in their entirety for now */ - /* If the first lookup doesn't succeed, maybe it's got @sys in the name */ ObtainReadLock(&adp->lock); /* @@ -1084,17 +1060,28 @@ afs_lookup(adp, aname, avcp, acred) /* Save the version number for when we call osi_dnlc_enter */ hset(versionNo, tdc->f.versionNo); + /* + * check for, and handle "@sys" if it's there. We should be able + * to avoid the alloc and the strcpy with a little work, but it's + * not pressing. If there aren't any remote users (ie, via the + * NFS translator), we have a slightly easier job. + * the faster way to do this is to check for *aname == '@' and if + * it's there, check for @sys, otherwise, assume there's no @sys + * then, if the lookup fails, check for .*@sys... + */ + /* above now implemented by Check_AtSys and Next_AtSys */ + + /* 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, tname, &tfid.Fid, &dirCookie); - if (code == ENOENT && tname == aname) { - int len; - len = strlen(aname); - if (len >= 4 && AFS_EQ_ATSYS(aname+len-4)) { - tname = (char *) osi_AllocLargeSpace(AFS_LRALLOCSIZ); - afs_HandleAtName(aname, tname, &treq, adp); - code = afs_dir_LookupOffset(&theDir, tname, &tfid.Fid, &dirCookie); - } + code = 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, &dirCookie); } + tname = sysState.name; + ReleaseReadLock(&adp->lock); afs_PutDCache(tdc); diff --git a/src/afs/afs.h b/src/afs/afs.h index 8a957a687..121ccd50c 100644 --- a/src/afs/afs.h +++ b/src/afs/afs.h @@ -63,6 +63,7 @@ extern int afs_shuttingdown; #define PIGGYSIZE 1350 /* max piggyback size */ #define MAXVOLS 128 /* max vols we can store */ #define MAXSYSNAME 128 /* max sysname (i.e. @sys) size */ +#define MAXNUMSYSNAMES 16 /* max that current constants allow */ #define NOTOKTIMEOUT (2*3600) /* time after which to timeout conns sans tokens */ #define NOPAG 0xffffffff #define AFS_NCBRS 300 /* max # of call back return entries */ @@ -74,6 +75,11 @@ extern int afs_shuttingdown; #define AFS_RXDEADTIME 50 #define AFS_HARDDEADTIME 120 +struct sysname_info { + char *name; + short offset; + char index, allocked; +}; /* flags to use with AFSOP_CACHEINIT */ #define AFSCALL_INIT_MEMCACHE 0x1 /* use a memory-based cache */ diff --git a/src/afs/afs_init.c b/src/afs/afs_init.c index 6276984ec..482bf9201 100644 --- a/src/afs/afs_init.c +++ b/src/afs/afs_init.c @@ -108,6 +108,8 @@ struct vfs *afs_cacheVfsp=0; afs_rwlock_t afs_puttofileLock; /* not used */ char *afs_sysname = 0; /* So that superuser may change the * local value of @sys */ +char *afs_sysnamelist[MAXNUMSYSNAMES]; /* For support of a list of sysname */ +int afs_sysnamecount = 0; struct volume *Initialafs_freeVolList; int afs_memvolumes = 0; @@ -525,8 +527,11 @@ afs_ResourceInit(preallocs) afs_resourceinit_flag = 1; for (i=0;if.inode, bufp, &tfid.Fid); + Check_AtSys(avc, ain, &sysState, areq); + do { + code = afs_dir_Lookup(&tdc->f.inode, sysState.name, &tfid.Fid); + } while (code == ENOENT && Next_AtSys(avc, areq, &sysState)); + bufp = sysState.name; if (code) { afs_PutDCache(tdc); goto out; @@ -1717,7 +1721,7 @@ static PNewStatMount(avc, afun, areq, ain, aout, ainSize, aoutSize) ReleaseWriteLock(&tvc->lock); afs_PutVCache(tvc, WRITE_LOCK); out: - if (hasatsys) osi_FreeLargeSpace(bufp); + if (sysState.allocked) osi_FreeLargeSpace(bufp); return code; } @@ -2341,8 +2345,9 @@ static PRemoveMount(avc, afun, areq, ain, aout, ainSize, aoutSize) afs_int32 ainSize; afs_int32 *aoutSize; /* set this */ { register afs_int32 code; - char *bufp = 0; - afs_int32 offset, len, hasatsys = 0; + char *bufp; + struct sysname_info sysState; + afs_int32 offset, len; register struct conn *tc; register struct dcache *tdc; register struct vcache *tvc; @@ -2362,8 +2367,11 @@ static PRemoveMount(avc, afun, areq, ain, aout, ainSize, aoutSize) tdc = afs_GetDCache(avc, 0, areq, &offset, &len, 1); /* test for error below */ if (!tdc) return ENOENT; - hasatsys = Check_AtSys(avc, ain, &bufp, areq); - code = afs_dir_Lookup(&tdc->f.inode, bufp, &tfid.Fid); + Check_AtSys(avc, ain, &sysState, areq); + do { + code = afs_dir_Lookup(&tdc->f.inode, sysState.name, &tfid.Fid); + } while (code == ENOENT && Next_AtSys(avc, areq, &sysState)); + bufp = sysState.name; if (code) { afs_PutDCache(tdc); goto out; @@ -2446,7 +2454,7 @@ static PRemoveMount(avc, afun, areq, ain, aout, ainSize, aoutSize) ReleaseWriteLock(&avc->lock); code = 0; out: - if (hasatsys) osi_FreeLargeSpace(bufp); + if (sysState.allocked) osi_FreeLargeSpace(bufp); return code; } @@ -2676,7 +2684,6 @@ static PGetVnodeXStatus(avc, afun, areq, ain, aout, ainSize, aoutSize) /* (since we don't really believe remote uids anyway) */ /* outname[] shouldn't really be needed- this is left as an excercise */ /* for the reader. */ - static PSetSysName(avc, afun, areq, ain, aout, ainSize, aoutSize, acred) struct vcache *avc; int afun; @@ -2691,9 +2698,11 @@ register struct AFS_UCRED *acred; register struct afs_exporter *exporter; extern struct unixuser *afs_FindUser(); extern char *afs_sysname; + extern char *afs_sysnamelist[]; + extern int afs_sysnamecount; register struct unixuser *au; register afs_int32 pag, error; - int t; + int t, count; AFS_STATCNT(PSetSysName); @@ -2709,9 +2718,24 @@ register struct AFS_UCRED *acred; bcopy(ain, (char *)&setsysname, sizeof(afs_int32)); ain += sizeof(afs_int32); if (setsysname) { - t = strlen(ain); - if (t > MAXSYSNAME) + + /* Check my args */ + if (setsysname < 0 || setsysname > MAXNUMSYSNAMES) return EINVAL; + for(cp = ain,count = 0;count < setsysname;count++) { + /* won't go past end of ain since maxsysname*num < ain length */ + t = strlen(cp); + if (t >= MAXSYSNAME || t <= 0) + return EINVAL; + /* check for names that can shoot us in the foot */ + if (*cp == '.' && (cp[1] == 0 || (cp[1] == '.' && cp[2] == 0))) + return EINVAL; + cp += t+1; + } + /* args ok */ + + /* inname gets first entry in case we're being a translater */ + t = strlen(ain); bcopy(ain, inname, t+1); /* include terminating null */ ain += t + 1; } @@ -2738,23 +2762,50 @@ register struct AFS_UCRED *acred; else foundname = 1; afs_PutUser(au, READ_LOCK); } else { + + /* Not xlating, so local case */ if (!afs_sysname) osi_Panic("PSetSysName: !afs_sysname\n"); - if (!setsysname) { + if (!setsysname) { /* user just wants the info */ strcpy(outname, afs_sysname); - foundname = 1; - } else { - if (!afs_osi_suser(acred)) /* Local guy; only root can change sysname */ + foundname = afs_sysnamecount; + } else { /* Local guy; only root can change sysname */ + if (!afs_osi_suser(acred)) return EACCES; + + /* clear @sys entries from the dnlc, once afs_lookup can + do lookups of @sys entries and thinks it can trust them */ + /* privs ok, store the entry, ... */ strcpy(afs_sysname, inname); + if (setsysname > 1) { /* ... or list */ + cp = ain; + for(count=1; count < setsysname;++count) { + if (!afs_sysnamelist[count]) + osi_Panic("PSetSysName: no afs_sysnamelist entry to write\n"); + t = strlen(cp); + bcopy(cp, afs_sysnamelist[count], t+1); /* include null */ + cp += t+1; + } + } + afs_sysnamecount = setsysname; } } if (!setsysname) { - cp = aout; + cp = aout; /* not changing so report back the count and ... */ bcopy((char *)&foundname, cp, sizeof(afs_int32)); cp += sizeof(afs_int32); if (foundname) { - strcpy(cp, outname); + strcpy(cp, outname); /* ... the entry, ... */ cp += strlen(outname)+1; + for(count=1; count < foundname; ++count) { /* ... or list. */ + /* Note: we don't support @sys lists for exporters */ + if (!afs_sysnamelist[count]) + osi_Panic("PSetSysName: no afs_sysnamelist entry to read\n"); + t = strlen(afs_sysnamelist[count]); + if (t >= MAXSYSNAME) + osi_Panic("PSetSysName: sysname entry garbled\n"); + strcpy(cp, afs_sysnamelist[count]); + cp += t + 1; + } } *aoutSize = cp - aout; } @@ -3498,8 +3549,9 @@ static PFlushMount(avc, afun, areq, ain, aout, ainSize, aoutSize, acred) register struct vcache *tvc; register struct dcache *tdc; struct VenusFid tfid; - char *bufp = 0; - afs_int32 offset, len, hasatsys=0; + char *bufp; + struct sysname_info sysState; + afs_int32 offset, len; AFS_STATCNT(PFlushMount); if (!avc) return EINVAL; @@ -3510,8 +3562,11 @@ static PFlushMount(avc, afun, areq, ain, aout, ainSize, aoutSize, acred) } tdc = afs_GetDCache(avc, 0, areq, &offset, &len, 1); if (!tdc) return ENOENT; - hasatsys = Check_AtSys(avc, ain, &bufp, areq); - code = afs_dir_Lookup(&tdc->f.inode, bufp, &tfid.Fid); + Check_AtSys(avc, ain, &sysState, areq); + do { + code = afs_dir_Lookup(&tdc->f.inode, sysState.name, &tfid.Fid); + } while (code == ENOENT && Next_AtSys(avc, areq, &sysState)); + bufp = sysState.name; if (code) { afs_PutDCache(tdc); goto out; @@ -3556,7 +3611,7 @@ static PFlushMount(avc, afun, areq, ain, aout, ainSize, aoutSize, acred) #endif afs_PutVCache(tvc, WRITE_LOCK); out: - if (hasatsys) osi_FreeLargeSpace(bufp); + if (sysState.allocked) osi_FreeLargeSpace(bufp); return code; } diff --git a/src/venus/fs.c b/src/venus/fs.c index 9de42c6d0..2fdaf0750 100644 --- a/src/venus/fs.c +++ b/src/venus/fs.c @@ -2085,29 +2085,33 @@ static SysNameCmd(as) struct ViceIoctl blob; struct cmd_item *ti; char *input = space; - afs_int32 setp = 1; + afs_int32 setp = 0; ti = as->parms[0].items; - if (!ti) setp = 0; blob.in = space; blob.out = space; blob.out_size = MAXSIZE; blob.in_size = sizeof(afs_int32); - bcopy(&setp, input, sizeof(afs_int32)); input += sizeof(afs_int32); - if (ti) { - strcpy(input, ti->data); + for(; ti; ti=ti->next) { + setp++; blob.in_size += strlen(ti->data) + 1; + if (blob.in_size > MAXSIZE) { + fprintf(stderr, "%s: sysname%s too long.\n", pn, setp > 1 ? "s" : ""); + return 1; + } + strcpy(input, ti->data); input += strlen(ti->data); *(input++) = '\0'; } + bcopy(&setp, space, sizeof(afs_int32)); code = pioctl(0, VIOC_AFS_SYSNAME, &blob, 1); if (code) { Die(errno, 0); return 1; } if (setp) { - printf("%s: new sysname set.\n", pn); + printf("%s: new sysname%s set.\n", pn, setp > 1 ? " list" : ""); return 0; } input = space; @@ -2117,7 +2121,12 @@ static SysNameCmd(as) fprintf(stderr, "No sysname name value was found\n"); return 1; } - printf("Current sysname is '%s'\n", input); + printf("Current sysname%s is:", setp>1 ? " list" : ""); + for(;setp>0;--setp) { + printf(" %s", input); + input += strlen(input) + 1; + } + printf("\n"); return 0; } @@ -3024,7 +3033,7 @@ defect 3069 cmd_AddParm(ts, "-path", CMD_LIST, CMD_OPTIONAL, "dir/file path"); ts = cmd_CreateSyntax("sysname", SysNameCmd, 0, "get/set sysname (i.e. @sys) value"); - cmd_AddParm(ts, "-newsys", CMD_SINGLE, CMD_OPTIONAL, "new sysname"); + cmd_AddParm(ts, "-newsys", CMD_LIST, CMD_OPTIONAL, "new sysname"); ts = cmd_CreateSyntax("exportafs", ExportAfsCmd, 0, "enable/disable translators to AFS"); cmd_AddParm(ts, "-type", CMD_SINGLE, 0, "exporter name"); -- 2.39.5