Windows: AFSVolSync creationDate based readonly volume versioning
authorJeffrey Altman <jaltman@your-file-system.com>
Wed, 14 Oct 2009 03:36:26 +0000 (23:36 -0400)
committerJeffrey Altman <jaltman|account-1000011@unknown>
Thu, 15 Oct 2009 11:41:52 +0000 (04:41 -0700)
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>

src/WINNT/afsd/cm_callback.c
src/WINNT/afsd/cm_callback.h
src/WINNT/afsd/cm_dcache.c
src/WINNT/afsd/cm_ioctl.c
src/WINNT/afsd/cm_scache.c
src/WINNT/afsd/cm_scache.h
src/WINNT/afsd/cm_server.c
src/WINNT/afsd/cm_vnodeops.c
src/WINNT/afsd/cm_volume.c
src/WINNT/afsd/cm_volume.h

index e919bf4..0b94d40 100644 (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 */
index 78633b9..6a066b7 100644 (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);
index d15ecde..340eb67 100644 (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.
index 0768079..b29c2ad 100644 (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;
index c86453f..9028d8c 100644 (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++)
index 79046f9..2da484b 100644 (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 */
 
index 16e6824..ed441cc 100644 (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);
index addbe23..4a13e40 100644 (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);
index 4e15051..538448c 100644 (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);
index a7aecff..a26b10f 100644 (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 */