From 862390a987f5ef4438079e7d1e961c7ddafb94ac Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Tue, 13 Oct 2009 23:36:26 -0400 Subject: [PATCH] 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 Reviewed-by: Asanka Herath Tested-by: Asanka Herath Reviewed-by: Alistair Ferguson Reviewed-by: Jeffrey Altman --- src/WINNT/afsd/cm_callback.c | 109 ++++++++++++++++++++--------------- src/WINNT/afsd/cm_callback.h | 2 +- src/WINNT/afsd/cm_dcache.c | 9 ++- src/WINNT/afsd/cm_ioctl.c | 4 ++ src/WINNT/afsd/cm_scache.c | 66 ++++++++++++++++++--- src/WINNT/afsd/cm_scache.h | 3 + src/WINNT/afsd/cm_server.c | 16 +++-- src/WINNT/afsd/cm_vnodeops.c | 41 ++++++++++--- src/WINNT/afsd/cm_volume.c | 59 +++++++++++++++++-- src/WINNT/afsd/cm_volume.h | 1 + 10 files changed, 233 insertions(+), 77 deletions(-) diff --git a/src/WINNT/afsd/cm_callback.c b/src/WINNT/afsd/cm_callback.c index e919bf443a..0b94d40f1d 100644 --- a/src/WINNT/afsd/cm_callback.c +++ b/src/WINNT/afsd/cm_callback.c @@ -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 */ diff --git a/src/WINNT/afsd/cm_callback.h b/src/WINNT/afsd/cm_callback.h index 78633b940c..6a066b7085 100644 --- a/src/WINNT/afsd/cm_callback.h +++ b/src/WINNT/afsd/cm_callback.h @@ -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); diff --git a/src/WINNT/afsd/cm_dcache.c b/src/WINNT/afsd/cm_dcache.c index d15ecde0ad..340eb67e4a 100644 --- a/src/WINNT/afsd/cm_dcache.c +++ b/src/WINNT/afsd/cm_dcache.c @@ -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. diff --git a/src/WINNT/afsd/cm_ioctl.c b/src/WINNT/afsd/cm_ioctl.c index 0768079380..b29c2ada01 100644 --- a/src/WINNT/afsd/cm_ioctl.c +++ b/src/WINNT/afsd/cm_ioctl.c @@ -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; diff --git a/src/WINNT/afsd/cm_scache.c b/src/WINNT/afsd/cm_scache.c index c86453f67b..9028d8c5df 100644 --- a/src/WINNT/afsd/cm_scache.c +++ b/src/WINNT/afsd/cm_scache.c @@ -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 : "", cbt ? cbt : "", + cdrot ? cdrot : "", 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++) diff --git a/src/WINNT/afsd/cm_scache.h b/src/WINNT/afsd/cm_scache.h index 79046f9e37..2da484b3b0 100644 --- a/src/WINNT/afsd/cm_scache.h +++ b/src/WINNT/afsd/cm_scache.h @@ -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 */ diff --git a/src/WINNT/afsd/cm_server.c b/src/WINNT/afsd/cm_server.c index 16e6824282..ed441cc20d 100644 --- a/src/WINNT/afsd/cm_server.c +++ b/src/WINNT/afsd/cm_server.c @@ -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); diff --git a/src/WINNT/afsd/cm_vnodeops.c b/src/WINNT/afsd/cm_vnodeops.c index addbe23dce..4a13e40f02 100644 --- a/src/WINNT/afsd/cm_vnodeops.c +++ b/src/WINNT/afsd/cm_vnodeops.c @@ -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); diff --git a/src/WINNT/afsd/cm_volume.c b/src/WINNT/afsd/cm_volume.c index 4e150519ed..538448c6de 100644 --- a/src/WINNT/afsd/cm_volume.c +++ b/src/WINNT/afsd/cm_volume.c @@ -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 : "", cbt ? cbt : "", cdrot ? cdrot : "", 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); diff --git a/src/WINNT/afsd/cm_volume.h b/src/WINNT/afsd/cm_volume.h index a7aecff46d..a26b10f3f0 100644 --- a/src/WINNT/afsd/cm_volume.h +++ b/src/WINNT/afsd/cm_volume.h @@ -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 */