* is just a performance hit.
*/
-#ifdef AFS_DISCON_ENV
static int
afs_DisconCreateSymlink(struct vcache *avc, char *aname,
struct vrequest *areq) {
tdc = afs_GetDCache(avc, 0, areq, &offset, &len, 0);
if (!tdc) {
- printf("afs_DisconCreateSymlink: can't get new dcache for symlink.\n");
- return ENOENT;
+ /* printf("afs_DisconCreateSymlink: can't get new dcache for symlink.\n"); */
+ return ENETDOWN;
}
len = strlen(aname);
afs_AdjustSize(tdc, len);
tdc->validPos = len;
tfile = afs_CFileOpen(&tdc->f.inode);
+ osi_Assert(tfile);
afs_CFileWrite(tfile, 0, aname, len);
afs_CFileClose(tfile);
ReleaseWriteLock(&tdc->lock);
return 0;
}
-#endif
/* don't set CDirty in here because RPC is called synchronously */
int
afs_symlink(OSI_VC_DECL(adp), char *aname, struct vattr *attrs,
- char *atargetName, AFS_UCRED *acred)
+ char *atargetName, struct vcache **tvcp, afs_ucred_t *acred)
{
afs_uint32 now = 0;
- struct vrequest treq;
+ struct vrequest *treq = NULL;
afs_int32 code = 0;
struct afs_conn *tc;
struct VenusFid newFid;
struct server *hostp = 0;
struct vcache *tvc;
struct AFSStoreStatus InStatus;
- struct AFSFetchStatus OutFidStatus, OutDirStatus;
+ struct AFSFetchStatus *OutFidStatus, *OutDirStatus;
struct AFSCallBack CallBack;
struct AFSVolSync tsync;
struct volume *volp = 0;
struct afs_fakestat_state fakestate;
+ struct rx_connection *rxconn;
XSTATS_DECLS;
OSI_VC_CONVERT(adp);
afs_Trace2(afs_iclSetp, CM_TRACE_SYMLINK, ICL_TYPE_POINTER, adp,
ICL_TYPE_STRING, aname);
- if ((code = afs_InitReq(&treq, acred)))
+ OutFidStatus = osi_AllocSmallSpace(sizeof(struct AFSFetchStatus));
+ OutDirStatus = osi_AllocSmallSpace(sizeof(struct AFSFetchStatus));
+ memset(&InStatus, 0, sizeof(InStatus));
+
+ if ((code = afs_CreateReq(&treq, acred)))
goto done2;
afs_InitFakeStat(&fakestate);
AFS_DISCON_LOCK();
- code = afs_EvalFakeStat(&adp, &fakestate, &treq);
+ code = afs_EvalFakeStat(&adp, &fakestate, treq);
if (code)
goto done;
goto done;
}
- code = afs_VerifyVCache(adp, &treq);
+ code = afs_VerifyVCache(adp, treq);
if (code) {
- code = afs_CheckCode(code, &treq, 30);
+ code = afs_CheckCode(code, treq, 30);
goto done;
}
InStatus.UnixModeBits = 0755;
alen++; /* add in the null */
}
- tdc = afs_GetDCache(adp, (afs_size_t) 0, &treq, &offset, &len, 1);
+ tdc = afs_GetDCache(adp, (afs_size_t) 0, treq, &offset, &len, 1);
volp = afs_FindVolume(&adp->f.fid, READ_LOCK); /*parent is also in same vol */
ObtainWriteLock(&adp->lock, 156);
if (tdc)
ObtainWriteLock(&tdc->lock, 636);
- ObtainSharedLock(&afs_xvcache, 17); /* prevent others from creating this entry */
- /* XXX Pay attention to afs_xvcache around the whole thing!! XXX */
+ /* No further locks: if the SymLink succeeds, it does not matter what happens
+ * to our local copy of the directory. If somebody tampers with it in the meantime,
+ * the copy will be invalidated */
if (!AFS_IS_DISCON_RW) {
do {
- tc = afs_Conn(&adp->f.fid, &treq, SHARED_LOCK);
+ tc = afs_Conn(&adp->f.fid, treq, SHARED_LOCK, &rxconn);
if (tc) {
- hostp = tc->srvr->server;
+ hostp = tc->parent->srvr->server;
XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_SYMLINK);
if (adp->f.states & CForeign) {
now = osi_Time();
RX_AFS_GUNLOCK();
code =
- RXAFS_DFSSymlink(tc->id,
+ RXAFS_DFSSymlink(rxconn,
(struct AFSFid *)&adp->f.fid.Fid,
aname, atargetName, &InStatus,
(struct AFSFid *)&newFid.Fid,
- &OutFidStatus, &OutDirStatus,
+ OutFidStatus, OutDirStatus,
&CallBack, &tsync);
RX_AFS_GLOCK();
} else {
RX_AFS_GUNLOCK();
code =
- RXAFS_Symlink(tc->id, (struct AFSFid *)&adp->f.fid.Fid,
+ RXAFS_Symlink(rxconn, (struct AFSFid *)&adp->f.fid.Fid,
aname, atargetName, &InStatus,
(struct AFSFid *)&newFid.Fid,
- &OutFidStatus, &OutDirStatus, &tsync);
+ OutFidStatus, OutDirStatus, &tsync);
RX_AFS_GLOCK();
}
XSTATS_END_TIME;
} else
code = -1;
} while (afs_Analyze
- (tc, code, &adp->f.fid, &treq, AFS_STATS_FS_RPCIDX_SYMLINK,
+ (tc, rxconn, code, &adp->f.fid, treq, AFS_STATS_FS_RPCIDX_SYMLINK,
SHARED_LOCK, NULL));
} else {
-#ifdef AFS_DISCON_ENV
newFid.Cell = adp->f.fid.Cell;
newFid.Fid.Volume = adp->f.fid.Fid.Volume;
afs_GenFakeFid(&newFid, VREG, 0);
-#endif
}
- UpgradeSToWLock(&afs_xvcache, 40);
+ ObtainWriteLock(&afs_xvcache, 40);
if (code) {
if (code < 0) {
- ObtainWriteLock(&afs_xcbhash, 499);
- afs_DequeueCallback(adp);
- adp->f.states &= ~CStatd;
- ReleaseWriteLock(&afs_xcbhash);
- osi_dnlc_purgedp(adp);
+ afs_StaleVCache(adp);
}
ReleaseWriteLock(&adp->lock);
ReleaseWriteLock(&afs_xvcache);
goto done;
}
/* otherwise, we should see if we can make the change to the dir locally */
- if (AFS_IS_DISCON_RW || afs_LocalHero(adp, tdc, &OutDirStatus, 1)) {
+ if (AFS_IS_DISCON_RW || afs_LocalHero(adp, tdc, OutDirStatus, 1)) {
/* we can do it locally */
ObtainWriteLock(&afs_xdcache, 293);
+ /* If the following fails because the name has been created in the meantime, the
+ * directory is out-of-date - the file server knows best! */
code = afs_dir_Create(tdc, aname, &newFid.Fid);
ReleaseWriteLock(&afs_xdcache);
if (code && !AFS_IS_DISCON_RW) {
ReleaseWriteLock(&afs_xcbhash);
if (AFS_IS_DISCON_RW) {
-#ifdef AFS_DISCON_ENV
attrs->va_mode = InStatus.UnixModeBits;
- afs_GenDisconStatus(adp, tvc, &newFid, attrs, &treq, VLNK);
- code = afs_DisconCreateSymlink(tvc, atargetName, &treq);
+ afs_GenDisconStatus(adp, tvc, &newFid, attrs, treq, VLNK);
+ code = afs_DisconCreateSymlink(tvc, atargetName, treq);
if (code) {
/* XXX - When this goes wrong, we need to tidy up the changes we made to
* the parent, and get rid of the vcache we just created */
goto done;
}
afs_DisconAddDirty(tvc, VDisconCreate, 0);
-#endif
} else {
- afs_ProcessFS(tvc, &OutFidStatus, &treq);
+ afs_ProcessFS(tvc, OutFidStatus, treq);
}
if (!tvc->linkData) {
- tvc->linkData = (char *)afs_osi_Alloc(alen);
+ tvc->linkData = afs_osi_Alloc(alen);
+ osi_Assert(tvc->linkData != NULL);
strncpy(tvc->linkData, atargetName, alen - 1);
tvc->linkData[alen - 1] = 0;
}
ReleaseWriteLock(&tvc->lock);
ReleaseWriteLock(&afs_xvcache);
- afs_PutVCache(tvc);
+ if (tvcp)
+ *tvcp = tvc;
+ else
+ afs_PutVCache(tvc);
code = 0;
done:
afs_PutFakeStat(&fakestate);
if (volp)
afs_PutVolume(volp, READ_LOCK);
AFS_DISCON_UNLOCK();
- code = afs_CheckCode(code, &treq, 31);
+ code = afs_CheckCode(code, treq, 31);
+ afs_DestroyReq(treq);
done2:
+ osi_FreeSmallSpace(OutFidStatus);
+ osi_FreeSmallSpace(OutDirStatus);
return code;
}
int
-afs_MemHandleLink(register struct vcache *avc, struct vrequest *areq)
+afs_MemHandleLink(struct vcache *avc, struct vrequest *areq)
{
- register struct dcache *tdc;
- register char *tp, *rbuf;
+ struct dcache *tdc;
+ char *tp, *rbuf;
afs_size_t offset, len;
afs_int32 tlen, alen;
- register afs_int32 code;
+ afs_int32 code;
AFS_STATCNT(afs_MemHandleLink);
/* two different formats, one for links protected 644, have a "." at
alen = len + 1; /* regular link */
else
alen = len; /* mt point */
- rbuf = (char *)osi_AllocLargeSpace(AFS_LRALLOCSIZ);
+ rbuf = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
ObtainReadLock(&tdc->lock);
addr = afs_MemCacheOpen(&tdc->f.inode);
tlen = len;
rbuf[alen - 1] = 0;
alen = strlen(rbuf) + 1;
tp = afs_osi_Alloc(alen); /* make room for terminating null */
+ osi_Assert(tp != NULL);
memcpy(tp, rbuf, alen);
osi_FreeLargeSpace(rbuf);
if (code != len) {
}
int
-afs_UFSHandleLink(register struct vcache *avc, struct vrequest *areq)
+afs_UFSHandleLink(struct vcache *avc, struct vrequest *areq)
{
- register struct dcache *tdc;
- register char *tp, *rbuf;
+ struct dcache *tdc;
+ char *tp, *rbuf;
void *tfile;
afs_size_t offset, len;
afs_int32 tlen, alen;
- register afs_int32 code;
+ afs_int32 code;
/* two different formats, one for links protected 644, have a "." at the
* end of the file name, which we turn into a null. Others, protected
alen = len + 1; /* regular link */
else
alen = len; /* mt point */
- rbuf = (char *)osi_AllocLargeSpace(AFS_LRALLOCSIZ);
+ rbuf = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
tlen = len;
ObtainReadLock(&tdc->lock);
tfile = osi_UFSOpen(&tdc->f.inode);
+ if (!tfile) {
+ ReleaseReadLock(&tdc->lock);
+ afs_PutDCache(tdc);
+ osi_FreeLargeSpace(rbuf);
+ return EIO;
+ }
code = afs_osi_Read(tfile, -1, rbuf, tlen);
osi_UFSClose(tfile);
ReleaseReadLock(&tdc->lock);
rbuf[alen - 1] = '\0';
alen = strlen(rbuf) + 1;
tp = afs_osi_Alloc(alen); /* make room for terminating null */
+ osi_Assert(tp != NULL);
memcpy(tp, rbuf, alen);
osi_FreeLargeSpace(rbuf);
if (code != tlen) {
}
int
-afs_readlink(OSI_VC_DECL(avc), struct uio *auio, AFS_UCRED *acred)
+afs_readlink(OSI_VC_DECL(avc), struct uio *auio, afs_ucred_t *acred)
{
- register afs_int32 code;
- struct vrequest treq;
- register char *tp;
+ afs_int32 code;
+ struct vrequest *treq = NULL;
+ char *tp;
struct afs_fakestat_state fakestat;
OSI_VC_CONVERT(avc);
AFS_STATCNT(afs_readlink);
afs_Trace1(afs_iclSetp, CM_TRACE_READLINK, ICL_TYPE_POINTER, avc);
- if ((code = afs_InitReq(&treq, acred)))
+ if ((code = afs_CreateReq(&treq, acred)))
return code;
afs_InitFakeStat(&fakestat);
AFS_DISCON_LOCK();
- code = afs_EvalFakeStat(&avc, &fakestat, &treq);
+ code = afs_EvalFakeStat(&avc, &fakestat, treq);
if (code)
goto done;
- code = afs_VerifyVCache(avc, &treq);
+ code = afs_VerifyVCache(avc, treq);
if (code)
goto done;
if (vType(avc) != VLNK) {
goto done;
}
ObtainWriteLock(&avc->lock, 158);
- code = afs_HandleLink(avc, &treq);
+ code = afs_HandleLink(avc, treq);
/* finally uiomove it to user-land */
if (code == 0) {
tp = avc->linkData;
done:
afs_PutFakeStat(&fakestat);
AFS_DISCON_UNLOCK();
- code = afs_CheckCode(code, &treq, 32);
+ code = afs_CheckCode(code, treq, 32);
+ afs_DestroyReq(treq);
return code;
}