#include <afsconfig.h>
#include "afs/param.h"
-
-
+
+
#include "afs/sysincludes.h"
#include "afsincludes.h"
#include "afs/afs_stats.h" /* statistics */
#include "afs/lock.h"
#include "afs/afs_cbqueue.h"
-#ifdef AFS_DISCON_ENV
-
#define dv_match(vc, fstat) \
((vc->f.m.DataVersion.low == fstat.DataVersion) && \
(vc->f.m.DataVersion.high == fstat.dataVersionHigh))
ObtainWriteLock(&afs_xdcache, 758);
for (index = afs_dvhashTbl[i]; index != NULLIDX;) {
if (afs_indexUnique[index] == afid->Fid.Unique) {
- tdc = afs_GetDSlot(index, NULL);
- ReleaseReadLock(&tdc->tlock);
- if (!FidCmp(&tdc->f.fid, afid)) {
- break; /* leaving refCount high for caller */
- }
- afs_PutDCache(tdc);
+ tdc = afs_GetValidDSlot(index);
+ if (!tdc) {
+ index = NULLIDX;
+ break;
+ }
+ ReleaseReadLock(&tdc->tlock);
+ if (!FidCmp(&tdc->f.fid, afid)) {
+ break; /* leaving refCount high for caller */
+ }
+ afs_PutDCache(tdc);
}
index = afs_dvnextTbl[index];
}
break;
default:
return -1;
- break;
}
return 0;
parent_vc = afs_FindVCache(&parent_fid, 0, 1);
ReleaseSharedLock(&afs_xvcache);
if (!parent_vc) {
- return ENOENT;
+ return ENETDOWN;
}
shadow_fid.Cell = parent_vc->f.fid.Cell;
code = ENOENT;
} else {
/* printf("Directory dcache not found!\n"); */
- code = ENOENT;
+ code = ENETDOWN;
}
return code;
*/
int
-afs_GetParentVCache(struct vcache *avc, int deleted, struct VenusFid *afid,
+afs_GetParentVCache(struct vcache *avc, int deleted, struct VenusFid *afid,
char *aname, struct vcache **adp)
{
int code;
if (afs_GetParentDirFid(avc, afid)) {
/* printf("afs_GetParentVCache: Couldn't find parent dir's FID.\n"); */
- return ENOENT;
+ return ENETDOWN;
}
code = afs_GetVnodeName(avc, afid, aname, deleted);
ReleaseSharedLock(&afs_xvcache);
if (!*adp) {
/* printf("afs_GetParentVCache: Couldn't find parent dir's vcache\n"); */
- code = ENOENT;
+ code = ENETDOWN;
goto end;
}
}
end:
- if (code && *adp)
+ if (code && *adp) {
afs_PutVCache(*adp);
+ *adp = NULL;
+ }
return code;
}
struct AFSFetchStatus OutOldDirStatus, OutNewDirStatus;
struct AFSVolSync tsync;
struct afs_conn *tc;
+ struct rx_connection *rxconn;
afs_uint32 code = 0;
XSTATS_DECLS;
old_pdir_fid.Fid.Unique = avc->f.oldParent.unique;
/* Get old name. */
- old_name = (char *) afs_osi_Alloc(AFSNAMEMAX);
+ old_name = afs_osi_Alloc(AFSNAMEMAX);
if (!old_name) {
/* printf("afs_ProcessOpRename: Couldn't alloc space for old name.\n"); */
return ENOMEM;
}
/* Alloc data first. */
- new_name = (char *) afs_osi_Alloc(AFSNAMEMAX);
+ new_name = afs_osi_Alloc(AFSNAMEMAX);
if (!new_name) {
/* printf("afs_ProcessOpRename: Couldn't alloc space for new name.\n"); */
code = ENOMEM;
/* Get parent dir's FID.*/
if (afs_GetParentDirFid(avc, &new_pdir_fid)) {
/* printf("afs_ProcessOpRename: Couldn't find new parent dir FID.\n"); */
- code = ENOENT;
+ code = ENETDOWN;
goto done;
}
}
/* Send to data to server. */
do {
- tc = afs_Conn(&old_pdir_fid, areq, SHARED_LOCK);
+ tc = afs_Conn(&old_pdir_fid, areq, SHARED_LOCK, &rxconn);
if (tc) {
XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_RENAME);
RX_AFS_GUNLOCK();
- code = RXAFS_Rename(tc->id,
+ code = RXAFS_Rename(rxconn,
(struct AFSFid *)&old_pdir_fid.Fid,
old_name,
(struct AFSFid *)&new_pdir_fid.Fid,
code = -1;
} while (afs_Analyze(tc,
+ rxconn,
code,
&new_pdir_fid,
areq,
struct vcache *tdp = NULL, *tvc = NULL;
struct dcache *tdc = NULL;
struct afs_conn *tc;
+ struct rx_connection *rxconn;
afs_int32 hash, new_hash, index;
afs_size_t tlen;
int code, op = 0;
tname = afs_osi_Alloc(AFSNAMEMAX);
if (!tname)
return ENOMEM;
+ memset(&InStatus, 0, sizeof(InStatus));
code = afs_GetParentVCache(avc, 0, &pdir_fid, tname, &tdp);
- if (code)
+ if (code)
goto end;
/* This data may also be in linkData, but then we have to deal with
tdc = afs_GetDCache(avc, 0, areq, &offset, &tlen, 0);
if (!tdc) {
- code = ENOENT;
+ code = ENETDOWN;
goto end;
}
ttargetName = afs_osi_Alloc(tlen);
if (!ttargetName) {
afs_PutDCache(tdc);
- return ENOMEM;
+ code = ENOMEM;
+ goto end;
}
ObtainReadLock(&tdc->lock);
tfile = afs_CFileOpen(&tdc->f.inode);
+ if (!tfile) {
+ ReleaseReadLock(&tdc->lock);
+ afs_PutDCache(tdc);
+ code = EIO;
+ goto end;
+ }
code = afs_CFileRead(tfile, 0, ttargetName, tlen);
ttargetName[tlen-1] = '\0';
afs_CFileClose(tfile);
ReleaseReadLock(&tdc->lock);
afs_PutDCache(tdc);
}
-
+
/* Set status. */
InStatus.Mask = AFS_SETMODTIME | AFS_SETMODE | AFS_SETGROUP;
InStatus.ClientModTime = avc->f.m.Date;
InStatus.UnixModeBits = avc->f.m.Mode & 0xffff;
do {
- tc = afs_Conn(&tdp->f.fid, areq, SHARED_LOCK);
+ tc = afs_Conn(&tdp->f.fid, areq, SHARED_LOCK, &rxconn);
if (tc) {
switch (vType(avc)) {
case VREG:
op = AFS_STATS_FS_RPCIDX_CREATEFILE;
XSTATS_START_TIME(op);
RX_AFS_GUNLOCK();
- code = RXAFS_CreateFile(tc->id,
+ code = RXAFS_CreateFile(rxconn,
(struct AFSFid *)&tdp->f.fid.Fid,
tname, &InStatus,
(struct AFSFid *) &newFid.Fid,
op = AFS_STATS_FS_RPCIDX_MAKEDIR;
XSTATS_START_TIME(op);
RX_AFS_GUNLOCK();
- code = RXAFS_MakeDir(tc->id, (struct AFSFid *) &tdp->f.fid.Fid,
+ code = RXAFS_MakeDir(rxconn, (struct AFSFid *) &tdp->f.fid.Fid,
tname, &InStatus,
(struct AFSFid *) &newFid.Fid,
&OutFidStatus, &OutDirStatus,
op = AFS_STATS_FS_RPCIDX_SYMLINK;
XSTATS_START_TIME(op);
RX_AFS_GUNLOCK();
- code = RXAFS_Symlink(tc->id,
+ code = RXAFS_Symlink(rxconn,
(struct AFSFid *) &tdp->f.fid.Fid,
tname, ttargetName, &InStatus,
(struct AFSFid *) &newFid.Fid,
}
} else
code = -1;
- } while (afs_Analyze(tc, code, &tdp->f.fid, areq, op, SHARED_LOCK, NULL));
+ } while (afs_Analyze(tc, rxconn, code, &tdp->f.fid, areq, op, SHARED_LOCK, NULL));
/* TODO: Handle errors. */
if (code) {
*/
tdc = afs_FindDCacheByFid(&avc->f.fid);
if (tdc) {
- afs_dir_ChangeFid(tdc, ".", &avc->f.fid.Fid.Vnode,
+ afs_dir_ChangeFid(tdc, ".", &avc->f.fid.Fid.Vnode,
&newFid.Fid.Vnode);
if (avc->f.m.LinkCount >= 2)
- /* For non empty dirs, fix children's parentVnode and
+ /* For non empty dirs, fix children's parentVnode and
* parentUnique reference.
*/
afs_FixChildrenFids(&avc->f.fid, &newFid);
ObtainWriteLock(&afs_xdcache, 743);
for (index = afs_dvhashTbl[hash]; index != NULLIDX; index = hash) {
hash = afs_dvnextTbl[index];
- tdc = afs_GetDSlot(index, NULL);
+ tdc = afs_GetValidDSlot(index);
+ if (!tdc) {
+ ReleaseWriteLock(&afs_xdcache);
+ code = EIO;
+ goto end;
+ }
ReleaseReadLock(&tdc->tlock);
if (afs_indexUnique[index] == avc->f.fid.Fid.Unique) {
if (!FidCmp(&tdc->f.fid, &avc->f.fid)) {
memcpy(&tdc->f.fid, &newFid, sizeof(struct VenusFid));
} /* if fid match */
} /* if uniquifier match */
- if (tdc)
- afs_PutDCache(tdc);
+ afs_PutDCache(tdc);
} /* for all dcaches in this hash bucket */
ReleaseWriteLock(&afs_xdcache);
if (tdp)
afs_PutVCache(tdp);
afs_osi_Free(tname, AFSNAMEMAX);
- if (ttargetName)
+ if (ttargetName)
afs_osi_Free(ttargetName, tlen);
return code;
}
struct VenusFid pdir_fid;
struct AFSVolSync tsync;
struct afs_conn *tc;
+ struct rx_connection *rxconn;
struct vcache *tdp = NULL;
int code = 0;
XSTATS_DECLS;
if (vType(avc) == VREG || vType(avc) == VLNK) {
/* Remove file on server. */
do {
- tc = afs_Conn(&pdir_fid, areq, SHARED_LOCK);
+ tc = afs_Conn(&pdir_fid, areq, SHARED_LOCK, &rxconn);
if (tc) {
XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_REMOVEFILE);
RX_AFS_GUNLOCK();
- code = RXAFS_RemoveFile(tc->id,
+ code = RXAFS_RemoveFile(rxconn,
&pdir_fid.Fid,
tname,
&OutDirStatus,
} else
code = -1;
} while (afs_Analyze(tc,
+ rxconn,
code,
&pdir_fid,
areq,
} else if (vType(avc) == VDIR) {
/* Remove dir on server. */
do {
- tc = afs_Conn(&pdir_fid, areq, SHARED_LOCK);
+ tc = afs_Conn(&pdir_fid, areq, SHARED_LOCK, &rxconn);
if (tc) {
XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_REMOVEDIR);
RX_AFS_GUNLOCK();
- code = RXAFS_RemoveDir(tc->id,
+ code = RXAFS_RemoveDir(rxconn,
&pdir_fid.Fid,
tname,
&OutDirStatus,
} else
code = -1;
} while (afs_Analyze(tc,
+ rxconn,
code,
&pdir_fid,
areq,
afs_SendChanges(struct vcache *avc, struct vrequest *areq)
{
struct afs_conn *tc;
+ struct rx_connection *rxconn;
struct AFSStoreStatus sstat;
struct AFSFetchStatus fstat;
struct AFSVolSync tsync;
/* Turn dirty vc data into a new store status... */
if (afs_GenStoreStatus(avc, &sstat) > 0) {
do {
- tc = afs_Conn(&avc->f.fid, areq, SHARED_LOCK);
+ tc = afs_Conn(&avc->f.fid, areq, SHARED_LOCK, &rxconn);
if (tc) {
/* ... and send it. */
XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_STORESTATUS);
RX_AFS_GUNLOCK();
- code = RXAFS_StoreStatus(tc->id,
+ code = RXAFS_StoreStatus(rxconn,
(struct AFSFid *) &avc->f.fid.Fid,
&sstat,
&fstat,
code = -1;
} while (afs_Analyze(tc,
+ rxconn,
code,
&avc->f.fid,
areq,
/* Truncate OP: */
do {
- tc = afs_Conn(&avc->f.fid, areq, SHARED_LOCK);
+ tc = afs_Conn(&avc->f.fid, areq, SHARED_LOCK, &rxconn);
if (tc) {
/* Set storing flags. XXX: A tad inefficient ... */
if (avc->f.ddirty_flags & VDisconWriteClose)
code = -1;
} while (afs_Analyze(tc,
+ rxconn,
code,
&avc->f.fid,
areq,
afs_ResyncDisconFiles(struct vrequest *areq, afs_ucred_t *acred)
{
struct afs_conn *tc;
+ struct rx_connection *rxconn;
struct vcache *tvc;
struct AFSFetchStatus fstat;
struct AFSCallBack callback;
tvc->f.ddirty_flags &= ~VDisconCreate;
tvc->f.ddirty_flags |= VDisconCreated;
}
-#if 0
- /* Get server write lock. */
- do {
- tc = afs_Conn(&tvc->f.fid, areq, SHARED_LOCK);
- if (tc) {
- XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_SETLOCK);
- RX_AFS_GUNLOCK();
- code = RXAFS_SetLock(tc->id,
- (struct AFSFid *)&tvc->f.fid.Fid,
- LockWrite,
- &tsync);
- RX_AFS_GLOCK();
- XSTATS_END_TIME;
- } else
- code = -1;
-
- } while (afs_Analyze(tc,
- code,
- &tvc->f.fid,
- areq,
- AFS_STATS_FS_RPCIDX_SETLOCK,
- SHARED_LOCK,
- NULL));
-
- if (code)
- goto next_file;
-#endif
if (tvc->f.ddirty_flags & VDisconRename) {
/* If we're renaming the file, do so now */
code = afs_ProcessOpRename(tvc, areq);
/* Issue a FetchStatus to get info about DV and callbacks. */
do {
- tc = afs_Conn(&tvc->f.fid, areq, SHARED_LOCK);
+ tc = afs_Conn(&tvc->f.fid, areq, SHARED_LOCK, &rxconn);
if (tc) {
- tvc->callback = tc->srvr->server;
+ tvc->callback = tc->parent->srvr->server;
start = osi_Time();
XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_FETCHSTATUS);
RX_AFS_GUNLOCK();
- code = RXAFS_FetchStatus(tc->id,
+ code = RXAFS_FetchStatus(rxconn,
(struct AFSFid *)&tvc->f.fid.Fid,
&fstat,
&callback,
code = -1;
} while (afs_Analyze(tc,
+ rxconn,
code,
&tvc->f.fid,
areq,
} else if (afs_ConflictPolicy == SERVER_WINS) {
/* DV mismatch, apply collision resolution policy. */
/* Discard this files chunks and remove from current dir. */
- afs_ResetVCache(tvc, acred);
+ afs_ResetVCache(tvc, acred, 0);
tvc->f.truncPos = AFS_NOTRUNC;
} else {
/* printf("afs_ResyncDisconFiles: no resolution policy selected.\n"); */
} /* if DV match or client wins policy */
unlock_srv_file:
- /* Release server write lock. */
-#if 0
- do {
- tc = afs_Conn(&tvc->f.fid, areq, SHARED_LOCK);
- if (tc) {
- XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_RELEASELOCK);
- RX_AFS_GUNLOCK();
- ucode = RXAFS_ReleaseLock(tc->id,
- (struct AFSFid *) &tvc->f.fid.Fid,
- &tsync);
- RX_AFS_GLOCK();
- XSTATS_END_TIME;
- } else
- ucode = -1;
- } while (afs_Analyze(tc,
- ucode,
- &tvc->f.fid,
- areq,
- AFS_STATS_FS_RPCIDX_RELEASELOCK,
- SHARED_LOCK,
- NULL));
-#endif
+ /* If we ever lock files while replaying changes, we should unlock the
+ * file here. */
+
next_file:
ObtainWriteLock(&afs_disconDirtyLock, 710);
if (code == 0) {
- /* Replayed successfully - pull the vcache from the
+ /* Replayed successfully - pull the vcache from the
* disconnected list */
tvc->f.ddirty_flags = 0;
QRemove(&tvc->dirtyq);
afs_PutVCache(tvc);
} else {
if (code == EAGAIN) {
- /* Operation was deferred. Pull it from the current place in
+ /* Operation was deferred. Pull it from the current place in
* the list, and stick it at the end again */
QRemove(&tvc->dirtyq);
QAdd(&afs_disconDirty, &tvc->dirtyq);
* Discard all of our shadow directory copies. If squash is true, then
* we also invalidate the vcache holding the shadow directory, to ensure
* that any disconnected changes are deleted
- *
+ *
* \param squash
* \param acred
*
*/
static void
-afs_DisconDiscardAllShadows(int squash, afs_ucred_t *acred) {
+afs_DisconDiscardAllShadows(int squash, afs_ucred_t *acred)
+{
struct vcache *tvc;
while (!QEmpty(&afs_disconShadow)) {
ReleaseWriteLock(&afs_disconDirtyLock);
ObtainWriteLock(&tvc->lock, 706);
- afs_DeleteShadowDir(tvc);
- tvc->f.shadow.vnode = 0;
- tvc->f.shadow.unique = 0;
-
if (squash)
- afs_ResetVCache(tvc, acred);
+ afs_ResetVCache(tvc, acred, 0);
+
+ afs_DeleteShadowDir(tvc);
ReleaseWriteLock(&tvc->lock);
ObtainWriteLock(&afs_disconDirtyLock, 709);
* \param acred
*
*/
-void
-afs_DisconDiscardAll(afs_ucred_t *acred) {
+void
+afs_DisconDiscardAll(afs_ucred_t *acred)
+{
struct vcache *tvc;
ObtainWriteLock(&afs_disconDirtyLock, 717);
while (!QEmpty(&afs_disconDirty)) {
tvc = QEntry(QPrev(&afs_disconDirty), struct vcache, dirtyq);
+ QRemove(&tvc->dirtyq);
ReleaseWriteLock(&afs_disconDirtyLock);
ObtainWriteLock(&tvc->lock, 718);
- afs_ResetVCache(tvc, acred);
+ afs_ResetVCache(tvc, acred, 0);
tvc->f.truncPos = AFS_NOTRUNC;
ReleaseWriteLock(&tvc->lock);
- afs_PutVCache(tvc);
ObtainWriteLock(&afs_disconDirtyLock, 719);
+ afs_PutVCache(tvc);
}
afs_DisconDiscardAllShadows(1, acred);
struct VenusFid *afid, struct vattr *attrs,
struct vrequest *areq, int file_type)
{
+ afs_hyper_t zero;
memcpy(&avc->f.fid, afid, sizeof(struct VenusFid));
avc->f.m.Mode = attrs->va_mode;
/* Used to do this:
*/
avc->f.m.Group = adp->f.m.Group;
avc->f.m.Owner = adp->f.m.Owner;
- hset64(avc->f.m.DataVersion, 0, 0);
+ hzero(zero);
+ afs_SetDataVersion(avc, &zero);
avc->f.m.Length = attrs->va_size;
avc->f.m.Date = osi_Time();
switch(file_type) {
vSetType(avc, VLNK);
avc->f.m.Mode |= S_IFLNK;
if ((avc->f.m.Mode & 0111) == 0)
- avc->mvstat = 1;
+ avc->mvstat = AFS_MVSTAT_MTPT;
avc->f.parent.vnode = adp->f.fid.Fid.Vnode;
avc->f.parent.unique = adp->f.fid.Fid.Unique;
break;
avc->f.states |= CStatd;
avc->f.states &= ~CBulkFetching;
}
-#endif