Windows: AFSVolSync creationDate based readonly volume versioning

Implement readonly volume versioning based upon the .readonly
volume creation date as reported in the AFSVolSync output
parameter of every RXAFS RPC.

Whenever a new callback is obtained for an object stored within
a .readonly volume, the volume creation date is recorded in the
cm_volume object along with the callback expiration time and
a reference to the server that issued it.  These values are
used to determine if a callback is present when the cm_scache
object's volume creation date matches the cm_volume object's
volume creation date.  If there is no match, the cm_scache
object's individual callback information is used to determine
whether a callback has been registered.

This mechansism ensures that the whole-volume callback issued
in response to a RXAFS_FetchStatus request against a .readonly
volume can be applied to all objects that are cached from the
same version of the .readonly volume instance.

LICENSE MIT

Reviewed-on: http://gerrit.openafs.org/654
Tested-by: Jeffrey Altman <jaltman@openafs.org>
Reviewed-by: Asanka Herath <asanka@secure-endpoints.com>
Tested-by: Asanka Herath <asanka@secure-endpoints.com>
Reviewed-by: Alistair Ferguson <alistair.ferguson@mac.com>
Reviewed-by: Jeffrey Altman <jaltman@openafs.org>
This commit is contained in:
Jeffrey Altman 2009-10-13 23:36:26 -04:00 committed by Jeffrey Altman
parent 0468b18058
commit 862390a987
10 changed files with 233 additions and 77 deletions

View File

@ -210,6 +210,23 @@ void cm_RevokeCallback(struct rx_call *callp, cm_cell_t * cellp, AFSFid *fidp)
fidp->Volume, fidp->Vnode, fidp->Unique);
}
static __inline void
cm_callbackDiscardROVolumeByFID(cm_fid_t *fidp)
{
cm_volume_t *volp = cm_GetVolumeByFID(fidp);
if (volp) {
cm_PutVolume(volp);
if (volp->cbExpiresRO) {
volp->cbExpiresRO = 0;
if (volp->cbServerpRO) {
cm_PutServer(volp->cbServerpRO);
volp->cbServerpRO = NULL;
}
volp->creationDateRO = 0;
}
}
}
/* called to revoke a volume callback, which is typically issued when a volume
* is moved from one server to another.
*
@ -253,13 +270,8 @@ void cm_RevokeVolumeCallback(struct rx_call *callp, cm_cell_t *cellp, AFSFid *fi
cm_CallbackNotifyChange(scp);
lock_ObtainWrite(&cm_scacheLock);
cm_ReleaseSCacheNoLock(scp);
if (scp->flags & CM_SCACHEFLAG_PURERO) {
cm_volume_t *volp = cm_GetVolumeByFID(&scp->fid);
if (volp) {
volp->cbExpiresRO = 0;
cm_PutVolume(volp);
}
}
if (scp->flags & CM_SCACHEFLAG_PURERO)
cm_callbackDiscardROVolumeByFID(&scp->fid);
}
} /* search one hash bucket */
} /* search all hash buckets */
@ -1063,14 +1075,8 @@ SRXAFSCB_InitCallBackState3(struct rx_call *callp, afsUUID* serverUuid)
lock_ObtainWrite(&cm_scacheLock);
cm_ReleaseSCacheNoLock(scp);
if (discarded && (scp->flags & CM_SCACHEFLAG_PURERO)) {
cm_volume_t *volp = cm_GetVolumeByFID(&scp->fid);
if (volp) {
if (volp->cbExpiresRO != 0)
volp->cbExpiresRO = 0;
cm_PutVolume(volp);
}
}
if (discarded && (scp->flags & CM_SCACHEFLAG_PURERO))
cm_callbackDiscardROVolumeByFID(&scp->fid);
} /* search one hash bucket */
} /* search all hash buckets */
@ -1570,26 +1576,32 @@ int cm_HaveCallback(cm_scache_t *scp)
return 0;
}
#endif
if (scp->cbServerp != NULL) {
return 1;
} else if (cm_OfflineROIsValid) {
if (scp->flags & CM_SCACHEFLAG_PURERO) {
cm_volume_t *volp = cm_GetVolumeByFID(&scp->fid);
if (volp) {
switch (cm_GetVolumeStatus(volp, scp->fid.volume)) {
case vl_offline:
case vl_alldown:
case vl_unknown:
cm_PutVolume(volp);
return 1;
default:
cm_PutVolume(volp);
return 0;
int haveCB = 0;
if (cm_OfflineROIsValid) {
switch (cm_GetVolumeStatus(volp, scp->fid.volume)) {
case vl_offline:
case vl_alldown:
case vl_unknown:
haveCB = 1;
break;
}
}
if (!haveCB &&
volp->creationDateRO == scp->volumeCreationDate &&
volp->cbServerpRO != NULL) {
haveCB = 1;
}
cm_PutVolume(volp);
return haveCB;
}
return 1;
}
return 0;
if (scp->cbServerp != NULL)
return 1;
else
return 0;
}
/* need to detect a broken callback that races with our obtaining a callback.
@ -1628,7 +1640,7 @@ void cm_StartCallbackGrantingCall(cm_scache_t *scp, cm_callbackRequest_t *cbrp)
* this locking hierarchy.
*/
void cm_EndCallbackGrantingCall(cm_scache_t *scp, cm_callbackRequest_t *cbrp,
AFSCallBack *cbp, long flags)
AFSCallBack *cbp, AFSVolSync *volSyncp, long flags)
{
cm_racingRevokes_t *revp; /* where we are */
cm_racingRevokes_t *nrevp; /* where we'll be next */
@ -1701,14 +1713,9 @@ void cm_EndCallbackGrantingCall(cm_scache_t *scp, cm_callbackRequest_t *cbrp,
cbrp->callbackCount, revp->callbackCount,
cm_callbackCount);
discardScp = 1;
if ((scp->flags & CM_SCACHEFLAG_PURERO) &&
(revp->flags & CM_RACINGFLAG_ALL)) {
cm_volume_t *volp = cm_GetVolumeByFID(&scp->fid);
if (volp) {
volp->cbExpiresRO = 0;
cm_PutVolume(volp);
}
}
if ((scp->flags & CM_SCACHEFLAG_PURERO) &&
(revp->flags & CM_RACINGFLAG_ALL))
cm_callbackDiscardROVolumeByFID(&scp->fid);
}
if (freeFlag)
free(revp);
@ -1729,12 +1736,17 @@ void cm_EndCallbackGrantingCall(cm_scache_t *scp, cm_callbackRequest_t *cbrp,
if (scp && scp->flags & CM_SCACHEFLAG_PURERO) {
cm_volume_t * volp = cm_GetVolumeByFID(&scp->fid);
if (volp) {
volp->cbExpiresRO = scp->cbExpires;
if (volp->cbServerpRO != scp->cbServerp) {
if (volp->cbServerpRO)
cm_PutServer(volp->cbServerpRO);
cm_GetServer(scp->cbServerp);
volp->cbServerpRO = scp->cbServerp;
if (volSyncp) {
lock_ObtainWrite(&cm_scacheLock);
volp->cbExpiresRO = scp->cbExpires;
volp->creationDateRO = volSyncp->spare1;
if (volp->cbServerpRO != scp->cbServerp) {
if (volp->cbServerpRO)
cm_PutServer(volp->cbServerpRO);
cm_GetServer(scp->cbServerp);
volp->cbServerpRO = scp->cbServerp;
}
lock_ReleaseWrite(&cm_scacheLock);
}
cm_PutVolume(volp);
}
@ -1766,6 +1778,8 @@ long cm_GetCallback(cm_scache_t *scp, struct cm_user *userp,
struct rx_connection * rxconnp = NULL;
int syncop_done = 0;
memset(&volSync, 0, sizeof(volSync));
osi_Log4(afsd_logp, "GetCallback scp 0x%p cell %d vol %d flags %lX",
scp, scp->fid.cell, scp->fid.volume, flags);
@ -1792,7 +1806,6 @@ long cm_GetCallback(cm_scache_t *scp, struct cm_user *userp,
lock_ReleaseMutex(&cm_Freelance_Lock);
memset(&afsStatus, 0, sizeof(afsStatus));
memset(&volSync, 0, sizeof(volSync));
// Fetch the status info
cm_MergeStatus(NULL, scp, &afsStatus, &volSync, userp, reqp, 0);
@ -1857,10 +1870,10 @@ long cm_GetCallback(cm_scache_t *scp, struct cm_user *userp,
lock_ObtainWrite(&scp->rw);
if (code == 0) {
cm_EndCallbackGrantingCall(scp, &cbr, &callback, 0);
cm_EndCallbackGrantingCall(scp, &cbr, &callback, &volSync, 0);
cm_MergeStatus(NULL, scp, &afsStatus, &volSync, userp, reqp, 0);
} else {
cm_EndCallbackGrantingCall(NULL, &cbr, NULL, 0);
cm_EndCallbackGrantingCall(NULL, &cbr, NULL, NULL, 0);
}
/* if we got an error, return to caller */

View File

@ -57,7 +57,7 @@ extern int cm_HaveCallback(struct cm_scache *);
extern void cm_StartCallbackGrantingCall(struct cm_scache *, cm_callbackRequest_t *);
extern void cm_EndCallbackGrantingCall(struct cm_scache *, cm_callbackRequest_t *,
struct AFSCallBack *, long);
struct AFSCallBack *, struct AFSVolSync *, long);
extern long cm_GetCallback(struct cm_scache *, struct cm_user *,
struct cm_req * reqp, long flags);

View File

@ -79,6 +79,8 @@ long cm_BufWrite(void *vscp, osi_hyper_t *offsetp, long length, long flags,
osi_assertx(userp != NULL, "null cm_user_t");
osi_assertx(scp != NULL, "null cm_scache_t");
memset(&volSync, 0, sizeof(volSync));
/* now, the buffer may or may not be filled with good data (buf_GetNew
* drops lots of locks, and may indeed return a properly initialized
* buffer, although more likely it will just return a new, empty, buffer.
@ -347,6 +349,8 @@ long cm_StoreMini(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp)
int require_64bit_ops = 0;
int call_was_64bit = 0;
memset(&volSync, 0, sizeof(volSync));
/* Serialize StoreData RPC's; for rationale see cm_scache.c */
(void) cm_SyncOp(scp, NULL, userp, reqp, 0,
CM_SCACHESYNC_STOREDATA_EXCL);
@ -1431,8 +1435,7 @@ cm_CloneStatus(cm_scache_t *scp, cm_user_t *userp, int scp_locked,
afsStatusp->Length_hi = scp->length.HighPart;
afsStatusp->errorCode = 0;
memset(volSyncp, 0, sizeof(AFSVolSync));
volSyncp->spare1 = scp->lastUpdateRO;
volSyncp->spare1 = scp->volumeCreationDate;
return scp_locked;
}
@ -1468,6 +1471,8 @@ long cm_GetBuffer(cm_scache_t *scp, cm_buf_t *bufp, int *cpffp, cm_user_t *userp
int first_read = 1;
int scp_locked = 1;
memset(&volSync, 0, sizeof(volSync));
/* now, the buffer may or may not be filled with good data (buf_GetNew
* drops lots of locks, and may indeed return a properly initialized
* buffer, although more likely it will just return a new, empty, buffer.

View File

@ -396,6 +396,8 @@ cm_IoctlGetACL(cm_ioctl_t *ioctlp, cm_user_t *userp, cm_scache_t *scp, cm_req_t
int tlen;
struct rx_connection * rxconnp;
memset(&volSync, 0, sizeof(volSync));
/* now make the get acl call */
#ifdef AFS_FREELANCE_CLIENT
if ( scp->fid.cell == AFS_FAKE_ROOT_CELL_ID && scp->fid.volume == AFS_FAKE_ROOT_VOL_ID ) {
@ -493,6 +495,8 @@ cm_IoctlSetACL(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *scp,
AFSFid fid;
struct rx_connection * rxconnp;
memset(&volSync, 0, sizeof(volSync));
#ifdef AFS_FREELANCE_CLIENT
if ( scp->fid.cell == AFS_FAKE_ROOT_CELL_ID && scp->fid.volume == AFS_FAKE_ROOT_VOL_ID ) {
code = CM_ERROR_NOACCESS;

View File

@ -208,6 +208,7 @@ long cm_RecycleSCache(cm_scache_t *scp, afs_int32 flags)
scp->cbServerp = NULL;
}
scp->cbExpires = 0;
scp->volumeCreationDate = 0;
scp->fid.vnode = 0;
scp->fid.volume = 0;
@ -619,6 +620,7 @@ void cm_InitSCache(int newFile, long maxSCaches)
#endif
scp->cbServerp = NULL;
scp->cbExpires = 0;
scp->volumeCreationDate = 0;
scp->fileLocksH = NULL;
scp->fileLocksT = NULL;
scp->serverLock = (-1);
@ -1635,6 +1637,8 @@ void cm_MergeStatus(cm_scache_t *dscp,
return;
}
scp->volumeCreationDate = volsyncp->spare1; /* volume creation date */
scp->serverModTime = statusp->ServerModTime;
if (!(scp->mask & CM_SCACHEMASK_CLIENTMODTIME)) {
@ -1963,11 +1967,44 @@ int cm_DumpSCache(FILE *outputFile, char *cookie, int lock)
for (scp = cm_data.allSCachesp; scp; scp = scp->allNextp)
{
sprintf(output, "%s scp=0x%p, fid (cell=%d, volume=%d, vnode=%d, unique=%d) type=%d dv=%I64d len=0x%I64x mp='%s' Locks (server=0x%x shared=%u excl=%u clnt=%u) lockCount=%d flags=0x%x cb=0x%x refCount=%u\r\n",
cookie, scp, scp->fid.cell, scp->fid.volume, scp->fid.vnode, scp->fid.unique,
scp->fileType, scp->dataVersion, scp->length.QuadPart, scp->mountPointStringp,
time_t t;
char *srvStr = NULL;
afs_uint32 srvStrRpc = TRUE;
char *cbt = NULL;
char *cdrot = NULL;
if (scp->cbServerp) {
if (!((scp->cbServerp->flags & CM_SERVERFLAG_UUID) &&
UuidToString((UUID *)&scp->cbServerp->uuid, &srvStr) == RPC_S_OK)) {
afs_asprintf(&srvStr, "%.0I", scp->cbServerp->addr.sin_addr.s_addr);
srvStrRpc = FALSE;
}
}
if (scp->cbExpires) {
t = scp->cbExpires;
cbt = ctime(&t);
if (cbt) {
cbt = strdup(cbt);
cbt[strlen(cbt)-1] = '\0';
}
}
if (scp->volumeCreationDate) {
t = scp->volumeCreationDate;
cdrot = ctime(&t);
if (cdrot) {
cdrot = strdup(cdrot);
cdrot[strlen(cdrot)-1] = '\0';
}
}
sprintf(output,
"%s scp=0x%p, fid (cell=%d, volume=%d, vnode=%d, unique=%d) type=%d dv=%I64d len=0x%I64x "
"mp='%s' Locks (server=0x%x shared=%d excl=%d clnt=%d) fsLockCount=%d linkCount=%d anyAccess=0x%x "
"flags=0x%x cbServer='%s' cbExpires='%s' volumeCreationDate='%s' refCount=%u\r\n",
cookie, scp, scp->fid.cell, scp->fid.volume, scp->fid.vnode, scp->fid.unique,
scp->fileType, scp->dataVersion, scp->length.QuadPart, scp->mountPointStringp,
scp->serverLock, scp->sharedLocks, scp->exclusiveLocks, scp->clientLocks, scp->fsLockCount,
scp->flags, (unsigned long)scp->cbExpires, scp->refCount);
scp->linkCount, scp->anyAccess, scp->flags, srvStr ? srvStr : "<none>", cbt ? cbt : "<none>",
cdrot ? cdrot : "<none>", scp->refCount);
WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
if (scp->fileLocksH) {
@ -1976,20 +2013,33 @@ int cm_DumpSCache(FILE *outputFile, char *cookie, int lock)
for (q = scp->fileLocksH; q; q = osi_QNext(q)) {
cm_file_lock_t * lockp = (cm_file_lock_t *)((char *) q - offsetof(cm_file_lock_t, fileq));
sprintf(output, " %s lockp=0x%p scp=0x%p, cm_userp=0x%p offset=0x%I64x len=0x%08I64x type=0x%x key=0x%I64x flags=0x%x update=0x%I64u\r\n",
cookie, lockp, lockp->scp, lockp->userp, lockp->range.offset, lockp->range.length,
lockp->lockType, lockp->key, lockp->flags, (afs_uint64)lockp->lastUpdate);
sprintf(output, " %s lockp=0x%p scp=0x%p, cm_userp=0x%p offset=0x%I64x len=0x%08I64x type=0x%x "
"key=0x%I64x flags=0x%x update=0x%I64u\r\n",
cookie, lockp, lockp->scp, lockp->userp, lockp->range.offset, lockp->range.length,
lockp->lockType, lockp->key, lockp->flags, (afs_uint64)lockp->lastUpdate);
WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
}
sprintf(output, " %s - done dumping scp locks\r\n", cookie);
WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
}
if (srvStr) {
if (srvStrRpc)
RpcStringFree(&srvStr);
else
free(srvStr);
}
if (cbt)
free(cbt);
if (cdrot)
free(cdrot);
}
sprintf(output, "%s - Done dumping all scache.\r\n", cookie);
WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
sprintf(output, "%s - dumping cm_data.scacheHashTable - cm_data.scacheHashTableSize=%d\r\n", cookie, cm_data.scacheHashTableSize);
sprintf(output, "%s - dumping cm_data.scacheHashTable - cm_data.scacheHashTableSize=%d\r\n",
cookie, cm_data.scacheHashTableSize);
WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
for (i = 0; i < cm_data.scacheHashTableSize; i++)

View File

@ -128,6 +128,9 @@ typedef struct cm_scache {
afs_uint32 group; /* file owning group */
cm_user_t *creator; /* user, if new file */
/* volume status */
time_t volumeCreationDate; /* volume creation date from AFSVolSync */
/* pseudo file status */
osi_hyper_t serverLength; /* length known to server */

View File

@ -210,6 +210,7 @@ static void cm_CheckServersSingular(afs_uint32 flags, cm_cell_t *cellp)
int doPing;
int isDown;
int isFS;
int isVLDB;
lock_ObtainRead(&cm_serverLock);
for (tsp = cm_allServersp; tsp; tsp = tsp->allNextp) {
@ -222,6 +223,7 @@ static void cm_CheckServersSingular(afs_uint32 flags, cm_cell_t *cellp)
doPing = 0;
isDown = tsp->flags & CM_SERVERFLAG_DOWN;
isFS = tsp->type == CM_SERVER_FILE;
isVLDB = tsp->type == CM_SERVER_VLDB;
/* only do the ping if the cell matches the requested cell, or we're
* matching all cells (cellp == NULL), and if we've requested to ping
@ -231,7 +233,7 @@ static void cm_CheckServersSingular(afs_uint32 flags, cm_cell_t *cellp)
((isDown && (flags & CM_FLAG_CHECKDOWNSERVERS)) ||
(!isDown && (flags & CM_FLAG_CHECKUPSERVERS))) &&
((!(flags & CM_FLAG_CHECKVLDBSERVERS) ||
!isFS && (flags & CM_FLAG_CHECKVLDBSERVERS)) &&
isVLDB && (flags & CM_FLAG_CHECKVLDBSERVERS)) &&
(!(flags & CM_FLAG_CHECKFILESERVERS) ||
isFS && (flags & CM_FLAG_CHECKFILESERVERS)))) {
doPing = 1;
@ -837,7 +839,7 @@ void cm_SetServerPrefs(cm_server_t * serverp)
}
serverAddr = ntohl(serverp->addr.sin_addr.s_addr);
serverp->ipRank = CM_IPRANK_LOW; /* default setings */
serverp->ipRank = CM_IPRANK_LOW; /* default settings */
for ( i=0; i < cm_noIPAddr; i++)
{
@ -1337,7 +1339,8 @@ int cm_DumpServers(FILE *outputFile, char *cookie, int lock)
if (lock)
lock_ObtainRead(&cm_serverLock);
sprintf(output, "%s - dumping servers - cm_numFileServers=%d, cm_numVldbServers=%d\r\n",
sprintf(output,
"%s - dumping servers - cm_numFileServers=%d, cm_numVldbServers=%d\r\n",
cookie, cm_numFileServers, cm_numVldbServers);
WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
@ -1362,8 +1365,11 @@ int cm_DumpServers(FILE *outputFile, char *cookie, int lock)
down = ctime(&tsp->downTime);
down[strlen(down)-1] = '\0';
sprintf(output, "%s - tsp=0x%p cell=%s addr=%-15s port=%u uuid=%s type=%s caps=0x%x flags=0x%x waitCount=%u rank=%u downTime=\"%s\" refCount=%u\r\n",
cookie, tsp, tsp->cellp ? tsp->cellp->name : "", tsp->addr.sin_port, hoststr, uuidstr, type,
sprintf(output,
"%s - tsp=0x%p cell=%s addr=%-15s port=%u uuid=%s type=%s caps=0x%x "
"flags=0x%x waitCount=%u rank=%u downTime=\"%s\" refCount=%u\r\n",
cookie, tsp, tsp->cellp ? tsp->cellp->name : "", hoststr,
ntohs(tsp->addr.sin_port), uuidstr, type,
tsp->capabilities, tsp->flags, tsp->waitCount, tsp->ipRank,
(tsp->flags & CM_SERVERFLAG_DOWN) ? down : "up",
tsp->refCount);

View File

@ -1538,6 +1538,8 @@ long cm_Unlink(cm_scache_t *dscp, fschar_t *fnamep, clientchar_t * cnamep,
cm_scache_t *scp = NULL;
int free_fnamep = FALSE;
memset(&volSync, 0, sizeof(volSync));
if (fnamep == NULL) {
code = -1;
#ifdef USE_BPLUS
@ -2297,6 +2299,8 @@ cm_TryBulkStatRPC(cm_scache_t *dscp, cm_bulkStat_t *bbp, cm_user_t *userp, cm_re
struct rx_connection * rxconnp;
int inlinebulk = 0; /* Did we use InlineBulkStatus RPC or not? */
memset(&volSync, 0, sizeof(volSync));
/* otherwise, we may have one or more bulk stat's worth of stuff in bb;
* make the calls to create the entries. Handle AFSCBMAX files at a
* time.
@ -2348,7 +2352,7 @@ cm_TryBulkStatRPC(cm_scache_t *dscp, cm_bulkStat_t *bbp, cm_user_t *userp, cm_re
* much better on the next immediate call, either.
*/
if (code) {
cm_EndCallbackGrantingCall(NULL, &cbReq, NULL, 0);
cm_EndCallbackGrantingCall(NULL, &cbReq, NULL, NULL, 0);
break;
}
@ -2381,6 +2385,7 @@ cm_TryBulkStatRPC(cm_scache_t *dscp, cm_bulkStat_t *bbp, cm_user_t *userp, cm_re
| CM_SCACHEFLAG_SIZESTORING))) {
cm_EndCallbackGrantingCall(scp, &cbReq,
&bbp->callbacks[j],
&volSync,
CM_CALLBACK_MAINTAINCOUNT);
cm_MergeStatus(dscp, scp, &bbp->stats[j], &volSync, userp, reqp, 0);
}
@ -2389,7 +2394,7 @@ cm_TryBulkStatRPC(cm_scache_t *dscp, cm_bulkStat_t *bbp, cm_user_t *userp, cm_re
} /* all files in the response */
/* now tell it to drop the count,
* after doing the vnode processing above */
cm_EndCallbackGrantingCall(NULL, &cbReq, NULL, 0);
cm_EndCallbackGrantingCall(NULL, &cbReq, NULL, NULL, 0);
} /* while there are still more files to process */
/* If we did the InlineBulk RPC pull out the return code and log it */
@ -2592,6 +2597,8 @@ long cm_SetAttr(cm_scache_t *scp, cm_attr_t *attrp, cm_user_t *userp,
AFSStoreStatus afsInStatus;
struct rx_connection * rxconnp;
memset(&volSync, 0, sizeof(volSync));
/* handle file length setting */
if (attrp->mask & CM_ATTRMASK_LENGTH)
return cm_SetLength(scp, &attrp->length, userp, reqp);
@ -2669,6 +2676,8 @@ long cm_Create(cm_scache_t *dscp, clientchar_t *cnamep, long flags, cm_attr_t *a
cm_dirOp_t dirop;
fschar_t * fnamep = NULL;
memset(&volSync, 0, sizeof(volSync));
/* can't create names with @sys in them; must expand it manually first.
* return "invalid request" if they try.
*/
@ -2758,10 +2767,10 @@ long cm_Create(cm_scache_t *dscp, clientchar_t *cnamep, long flags, cm_attr_t *a
lock_ObtainWrite(&scp->rw);
scp->creator = userp; /* remember who created it */
if (!cm_HaveCallback(scp)) {
cm_EndCallbackGrantingCall(scp, &cbReq,
&newFileCallback, &volSync, 0);
cm_MergeStatus(dscp, scp, &newFileStatus, &volSync,
userp, reqp, 0);
cm_EndCallbackGrantingCall(scp, &cbReq,
&newFileCallback, 0);
didEnd = 1;
}
lock_ReleaseWrite(&scp->rw);
@ -2770,7 +2779,7 @@ long cm_Create(cm_scache_t *dscp, clientchar_t *cnamep, long flags, cm_attr_t *a
/* make sure we end things properly */
if (!didEnd)
cm_EndCallbackGrantingCall(NULL, &cbReq, NULL, 0);
cm_EndCallbackGrantingCall(NULL, &cbReq, NULL, NULL, 0);
if (scp && cm_CheckDirOpForSingleChange(&dirop)) {
cm_DirCreateEntry(&dirop, fnamep, &newFid);
@ -2835,6 +2844,8 @@ long cm_MakeDir(cm_scache_t *dscp, clientchar_t *cnamep, long flags, cm_attr_t *
cm_dirOp_t dirop;
fschar_t * fnamep = NULL;
memset(&volSync, 0, sizeof(volSync));
/* can't create names with @sys in them; must expand it manually first.
* return "invalid request" if they try.
*/
@ -2922,10 +2933,10 @@ long cm_MakeDir(cm_scache_t *dscp, clientchar_t *cnamep, long flags, cm_attr_t *
if (code == 0) {
lock_ObtainWrite(&scp->rw);
if (!cm_HaveCallback(scp)) {
cm_EndCallbackGrantingCall(scp, &cbReq,
&newDirCallback, &volSync, 0);
cm_MergeStatus(dscp, scp, &newDirStatus, &volSync,
userp, reqp, 0);
cm_EndCallbackGrantingCall(scp, &cbReq,
&newDirCallback, 0);
didEnd = 1;
}
lock_ReleaseWrite(&scp->rw);
@ -2934,7 +2945,7 @@ long cm_MakeDir(cm_scache_t *dscp, clientchar_t *cnamep, long flags, cm_attr_t *
/* make sure we end things properly */
if (!didEnd)
cm_EndCallbackGrantingCall(NULL, &cbReq, NULL, 0);
cm_EndCallbackGrantingCall(NULL, &cbReq, NULL, NULL, 0);
if (scp && cm_CheckDirOpForSingleChange(&dirop)) {
cm_DirCreateEntry(&dirop, fnamep, &newFid);
@ -2971,6 +2982,8 @@ long cm_Link(cm_scache_t *dscp, clientchar_t *cnamep, cm_scache_t *sscp, long fl
cm_dirOp_t dirop;
fschar_t * fnamep = NULL;
memset(&volSync, 0, sizeof(volSync));
if (dscp->fid.cell != sscp->fid.cell ||
dscp->fid.volume != sscp->fid.volume) {
return CM_ERROR_CROSSDEVLINK;
@ -3068,6 +3081,8 @@ long cm_SymLink(cm_scache_t *dscp, clientchar_t *cnamep, fschar_t *contentsp, lo
cm_dirOp_t dirop;
fschar_t *fnamep = NULL;
memset(&volSync, 0, sizeof(volSync));
/* before starting the RPC, mark that we're changing the directory data,
* so that someone who does a chmod on the dir will wait until our
* call completes.
@ -3192,6 +3207,8 @@ long cm_RemoveDir(cm_scache_t *dscp, fschar_t *fnamep, clientchar_t *cnamep, cm_
cm_scache_t *scp = NULL;
int free_fnamep = FALSE;
memset(&volSync, 0, sizeof(volSync));
if (fnamep == NULL) {
code = -1;
#ifdef USE_BPLUS
@ -3353,6 +3370,8 @@ long cm_Rename(cm_scache_t *oldDscp, fschar_t *oldNamep, clientchar_t *cOldNamep
int free_oldNamep = FALSE;
cm_scache_t *oldScp = NULL, *newScp = NULL;
memset(&volSync, 0, sizeof(volSync));
if (cOldNamep == NULL || cNewNamep == NULL ||
cm_ClientStrLen(cOldNamep) == 0 ||
cm_ClientStrLen(cNewNamep) == 0)
@ -4175,6 +4194,8 @@ long cm_IntSetLock(cm_scache_t * scp, cm_user_t * userp, int lockType,
AFSVolSync volSync;
afs_uint32 reqflags = reqp->flags;
memset(&volSync, 0, sizeof(volSync));
tfid.Volume = scp->fid.volume;
tfid.Vnode = scp->fid.vnode;
tfid.Unique = scp->fid.unique;
@ -4220,6 +4241,8 @@ long cm_IntReleaseLock(cm_scache_t * scp, cm_user_t * userp,
struct rx_connection * rxconnp;
AFSVolSync volSync;
memset(&volSync, 0, sizeof(volSync));
tfid.Volume = scp->fid.volume;
tfid.Vnode = scp->fid.vnode;
tfid.Unique = scp->fid.unique;
@ -5159,6 +5182,8 @@ void cm_CheckLocks()
struct rx_connection * rxconnp;
cm_scache_t * scp;
memset(&volSync, 0, sizeof(volSync));
cm_InitReq(&req);
lock_ObtainWrite(&cm_scacheLock);

View File

@ -526,8 +526,10 @@ long cm_UpdateVolumeLocation(struct cm_cell *cellp, cm_user_t *userp, cm_req_t *
}
}
if (!tsp) {
/* cm_NewServer will probe the server which in turn will
* update the state on the volume group object */
/*
* cm_NewServer will probe the file server which in turn will
* update the state on the volume group object
*/
lock_ReleaseWrite(&volp->rw);
tsp = cm_NewServer(&tsockAddr, CM_SERVER_FILE, cellp, &serverUUID[i], 0);
lock_ObtainWrite(&volp->rw);
@ -937,6 +939,7 @@ long cm_FindVolumeByName(struct cm_cell *cellp, char *volumeNamep,
}
volp->cbExpiresRO = 0;
volp->cbServerpRO = NULL;
volp->creationDateRO = 0;
cm_AddVolumeToNameHashTable(volp);
lock_ReleaseWrite(&cm_volumeLock);
}
@ -1479,15 +1482,61 @@ int cm_DumpVolumes(FILE *outputFile, char *cookie, int lock)
lock_ObtainRead(&cm_volumeLock);
}
sprintf(output, "%s - dumping volumes - cm_data.currentVolumes=%d, cm_data.maxVolumes=%d\r\n", cookie, cm_data.currentVolumes, cm_data.maxVolumes);
sprintf(output, "%s - dumping volumes - cm_data.currentVolumes=%d, cm_data.maxVolumes=%d\r\n",
cookie, cm_data.currentVolumes, cm_data.maxVolumes);
WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
for (volp = cm_data.allVolumesp; volp; volp=volp->allNextp)
{
sprintf(output, "%s - volp=0x%p cell=%s name=%s rwID=%u roID=%u bkID=%u flags=0x%x refCount=%u\r\n",
cookie, volp, volp->cellp->name, volp->namep, volp->vol[RWVOL].ID, volp->vol[ROVOL].ID, volp->vol[BACKVOL].ID, volp->flags,
time_t t;
char *srvStr = NULL;
afs_uint32 srvStrRpc = TRUE;
char *cbt = NULL;
char *cdrot = NULL;
if (volp->cbServerpRO) {
if (!((volp->cbServerpRO->flags & CM_SERVERFLAG_UUID) &&
UuidToString((UUID *)&volp->cbServerpRO->uuid, &srvStr) == RPC_S_OK)) {
afs_asprintf(&srvStr, "%.0I", volp->cbServerpRO->addr.sin_addr.s_addr);
srvStrRpc = FALSE;
}
}
if (volp->cbExpiresRO) {
t = volp->cbExpiresRO;
cbt = ctime(&t);
if (cbt) {
cbt = strdup(cbt);
cbt[strlen(cbt)-1] = '\0';
}
}
if (volp->creationDateRO) {
t = volp->creationDateRO;
cdrot = ctime(&t);
if (cdrot) {
cdrot = strdup(cdrot);
cdrot[strlen(cdrot)-1] = '\0';
}
}
sprintf(output,
"%s - volp=0x%p cell=%s name=%s rwID=%u roID=%u bkID=%u flags=0x%x "
"cbServerpRO='%s' cbExpiresRO='%s' creationDateRO='%s' refCount=%u\r\n",
cookie, volp, volp->cellp->name, volp->namep, volp->vol[RWVOL].ID,
volp->vol[ROVOL].ID, volp->vol[BACKVOL].ID, volp->flags,
srvStr ? srvStr : "<none>", cbt ? cbt : "<none>", cdrot ? cdrot : "<none>",
volp->refCount);
WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
if (srvStr) {
if (srvStrRpc)
RpcStringFree(&srvStr);
else
free(srvStr);
}
if (cbt)
free(cbt);
if (cdrot)
free(cdrot);
}
sprintf(output, "%s - Done dumping volumes.\r\n", cookie);
WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);

View File

@ -44,6 +44,7 @@ typedef struct cm_volume {
afs_int32 refCount; /* by Interlocked operations */
struct cm_server *cbServerpRO; /* server granting RO callback; by cm_scacheLock */
time_t cbExpiresRO; /* latest RO expiration time; by cm_scacheLock */
time_t creationDateRO; /* latest volume creation date; 0 if unknown; by cm_scacheLock */
} cm_volume_t;
#define CM_VOLUMEFLAG_RESET 1 /* reload this info on next use */