windows-misc-20040803
[openafs.git] / src / WINNT / afsd / cm_callback.c
index f00938a..ddc9af0 100644 (file)
 
 #include "afsd.h"
 
+/*extern void afsi_log(char *pattern, ...);*/
+
 /* read/write lock for all global storage in this module */
 osi_rwlock_t cm_callbackLock;
 
+#ifdef AFS_FREELANCE_CLIENT
+extern osi_mutex_t cm_Freelance_Lock;
+#endif
+
 /* count of # of callback breaking messages received by this CM so far.  We use
  * this count in determining whether there have been any callback breaks that
  * apply to a call that returned a new callback.  If the counter doesn't
@@ -67,6 +73,10 @@ void cm_RecordRacingRevoke(cm_fid_t *fidp, long cancelFlags)
        cm_racingRevokes_t *rp;
 
        lock_ObtainWrite(&cm_callbackLock);
+
+    osi_Log3(afsd_logp, "RecordRacingRevoke Volume %d Flags %lX activeCalls %d",
+             fidp->volume, cancelFlags, cm_activeCallbackGrantingCalls);
+
        if (cm_activeCallbackGrantingCalls > 0) {
                rp = malloc(sizeof(*rp));
                memset(rp, 0, sizeof(*rp));
@@ -83,6 +93,9 @@ void cm_RecordRacingRevoke(cm_fid_t *fidp, long cancelFlags)
  */
 void cm_CallbackNotifyChange(cm_scache_t *scp)
 {
+    osi_Log2(afsd_logp, "CallbackNotifyChange FileType %d Flags %lX",
+              scp->fileType, scp->flags);
+
        if (scp->fileType == CM_SCACHETYPE_DIRECTORY) {
                if (scp->flags & CM_SCACHEFLAG_ANYWATCH)
                        smb_NotifyChange(0,
@@ -102,6 +115,7 @@ void cm_CallbackNotifyChange(cm_scache_t *scp)
                        smb_NotifyChange(0,
                         FILE_NOTIFY_GENERIC_FILE_FILTER,
                         dscp, NULL, NULL, TRUE);
+               if (dscp) cm_ReleaseSCache(dscp);
        }
 }
 
@@ -127,7 +141,7 @@ void cm_RevokeCallback(struct rx_call *callp, AFSFid *fidp)
         tfid.unique = fidp->Unique;
         hash = CM_SCACHE_HASH(&tfid);
 
-       osi_Log3(afsd_logp, "Revoke callback vol %d vn %d un %d",
+    osi_Log3(afsd_logp, "RevokeCallback vol %d vn %d un %d",
                 fidp->Volume, fidp->Vnode, fidp->Unique);
         
        /* do this first, so that if we're executing a callback granting call
@@ -147,7 +161,7 @@ void cm_RevokeCallback(struct rx_call *callp, AFSFid *fidp)
                         scp->fid.unique == tfid.unique) {
                        scp->refCount++;
                        lock_ReleaseWrite(&cm_scacheLock);
-                       osi_Log1(afsd_logp, "Revoke scp %x", scp);
+            osi_Log1(afsd_logp, "Discarding SCache scp %x", scp);
                         lock_ObtainMutex(&scp->mx);
                        cm_DiscardSCache(scp);
                         lock_ReleaseMutex(&scp->mx);
@@ -170,6 +184,8 @@ void cm_RevokeVolumeCallback(struct rx_call *callp, AFSFid *fidp)
         cm_scache_t *scp;
         cm_fid_t tfid;
 
+    osi_Log1(afsd_logp, "RevokeVolumeCallback %d", fidp->Volume);
+
        /* do this first, so that if we're executing a callback granting call
          * at this moment, we kill it before it can be merged in.  Otherwise,
          * it could complete while we're doing the scan below, and get missed
@@ -179,7 +195,6 @@ void cm_RevokeVolumeCallback(struct rx_call *callp, AFSFid *fidp)
         tfid.volume = fidp->Volume;
         cm_RecordRacingRevoke(&tfid, CM_RACINGFLAG_CANCELVOL);
 
-       osi_Log1(afsd_logp, "Revoke Volume %d", fidp->Volume);
 
         lock_ObtainWrite(&cm_scacheLock);
        for(hash = 0; hash < cm_hashTableSize; hash++) {
@@ -188,6 +203,7 @@ void cm_RevokeVolumeCallback(struct rx_call *callp, AFSFid *fidp)
                                scp->refCount++;
                                lock_ReleaseWrite(&cm_scacheLock);
                                lock_ObtainMutex(&scp->mx);
+                osi_Log1(afsd_logp, "Discarding SCache scp %x", scp);
                                cm_DiscardSCache(scp);
                                lock_ReleaseMutex(&scp->mx);
                                cm_CallbackNotifyChange(scp);
@@ -208,13 +224,17 @@ SRXAFSCB_CallBack(struct rx_call *callp, AFSCBFids *fidsArrayp, AFSCBs *cbsArray
         int i;
         AFSFid *tfidp;
         
+    osi_Log0(afsd_logp, "SRXAFSCB_CallBack");
+
         for(i=0; i < (long) fidsArrayp->AFSCBFids_len; i++) {
                tfidp = &fidsArrayp->AFSCBFids_val[i];
                 
-                if (tfidp->Volume == 0) continue;      /* means don't do anything */
+        if (tfidp->Volume == 0)
+            continue;   /* means don't do anything */
                 else if (tfidp->Vnode == 0)
                        cm_RevokeVolumeCallback(callp, tfidp);
-               else cm_RevokeCallback(callp, tfidp);
+        else
+            cm_RevokeCallback(callp, tfidp);
         }
 
        return 0;
@@ -232,6 +252,8 @@ SRXAFSCB_InitCallBackState(struct rx_call *callp)
     int hash;
     int discarded;
 
+    osi_Log0(afsd_logp, "SRXAFSCB_InitCallBackState");
+
     if ((rx_ConnectionOf(callp)) && (rx_PeerOf(rx_ConnectionOf(callp)))) {
        taddr.sin_family = AF_INET;
        taddr.sin_addr.s_addr = rx_HostOf(rx_PeerOf(rx_ConnectionOf(callp)));
@@ -274,6 +296,7 @@ SRXAFSCB_InitCallBackState(struct rx_call *callp)
                        if (scp->cbServerp != NULL) {
                                /* we have a callback, now decide if we should clear it */
                                if (scp->cbServerp == tsp || tsp == NULL) {
+                        osi_Log1(afsd_logp, "Discarding SCache scp %x", scp);
                                        cm_DiscardSCache(scp);
                                        discarded = 1;
                                }
@@ -298,13 +321,23 @@ SRXAFSCB_InitCallBackState(struct rx_call *callp)
 /* just returns if we're up */
 SRXAFSCB_Probe(struct rx_call *callp)
 {
+    osi_Log0(afsd_logp, "SRXAFSCB_Probe - not implemented");
        return 0;
 }
 
 /* debug interface: not implemented */
+SRXAFSCB_GetCE64(struct rx_call *callp, long index, AFSDBCacheEntry *cep)
+{
+    /* XXXX */
+    osi_Log0(afsd_logp, "SRXAFSCB_GetCE64 - not implemented");
+    return RXGEN_OPCODE;
+}
+
+/* debug interface: not implemented */
 SRXAFSCB_GetLock(struct rx_call *callp, long index, AFSDBLock *lockp)
 {
        /* XXXX */
+    osi_Log0(afsd_logp, "SRXAFSCB_GetLock - not implemented");
        return RXGEN_OPCODE;
 }
 
@@ -312,6 +345,7 @@ SRXAFSCB_GetLock(struct rx_call *callp, long index, AFSDBLock *lockp)
 SRXAFSCB_GetCE(struct rx_call *callp, long index, AFSDBCacheEntry *cep)
 {
        /* XXXX */
+    osi_Log0(afsd_logp, "SRXAFSCB_GetCE - not implemented");
        return RXGEN_OPCODE;
 }
 
@@ -319,6 +353,7 @@ SRXAFSCB_GetCE(struct rx_call *callp, long index, AFSDBCacheEntry *cep)
 SRXAFSCB_XStatsVersion(struct rx_call *callp, long *vp)
 {
        /* XXXX */
+    osi_Log0(afsd_logp, "SRXAFSCB_XStatsVersion - not implemented");
        *vp = -1;
        return RXGEN_OPCODE;
 }
@@ -328,6 +363,7 @@ SRXAFSCB_GetXStats(struct rx_call *callp, long cvn, long coln, long *srvp, long
        AFSCB_CollData *datap)
 {
        /* XXXX */
+    osi_Log0(afsd_logp, "SRXAFSCB_GetXStats - not implemented");
        return RXGEN_OPCODE;
 }
 
@@ -335,6 +371,7 @@ SRXAFSCB_GetXStats(struct rx_call *callp, long cvn, long coln, long *srvp, long
 SRXAFSCB_InitCallBackState2(struct rx_call *callp, struct interfaceAddr* addr)
 {
        /* XXXX */
+    osi_Log0(afsd_logp, "SRXAFSCB_InitCallBackState2 - not implemented");
        return RXGEN_OPCODE;
 }
 
@@ -342,6 +379,7 @@ SRXAFSCB_InitCallBackState2(struct rx_call *callp, struct interfaceAddr* addr)
 SRXAFSCB_WhoAreYou(struct rx_call *callp, struct interfaceAddr* addr)
 {
        /* XXXX */
+    osi_Log0(afsd_logp, "SRXAFSCB_WhoAreYou - not implemented");
        return RXGEN_OPCODE;
 }
 
@@ -349,6 +387,7 @@ SRXAFSCB_WhoAreYou(struct rx_call *callp, struct interfaceAddr* addr)
 SRXAFSCB_InitCallBackState3(struct rx_call *callp, afsUUID* serverUuid)
 {
        /* XXXX */
+    osi_Log0(afsd_logp, "SRXAFSCB_InitCallBackState3 - not implemented");
        return RXGEN_OPCODE;
 }
 
@@ -356,6 +395,7 @@ SRXAFSCB_InitCallBackState3(struct rx_call *callp, afsUUID* serverUuid)
 SRXAFSCB_ProbeUuid(struct rx_call *callp, afsUUID* clientUuid)
 {
        /* XXXX */
+    osi_Log0(afsd_logp, "SRXAFSCB_ProbeUuid - not implemented");
        return RXGEN_OPCODE;
 }
 
@@ -387,6 +427,8 @@ int SRXAFSCB_GetServerPrefs(
     afs_int32 *a_srvr_addr,
     afs_int32 *a_srvr_rank)
 {
+    osi_Log0(afsd_logp, "SRXAFSCB_GetServerPrefs - not implemented");
+
     *a_srvr_addr = 0xffffffff;
     *a_srvr_rank = 0xffffffff;
     return 0;
@@ -418,14 +460,16 @@ int SRXAFSCB_GetCellServDB(
     struct rx_call *a_call,
     afs_int32 a_index,
     char **a_name,
-    afs_int32 *a_hosts)
+    serverList *a_hosts)
 {
     char *t_name;
 
+    osi_Log0(afsd_logp, "SRXAFSCB_GetCellServDB - not implemented");
+
     t_name = (char *)malloc(AFSNAMEMAX);
     t_name[0] = '\0';
     *a_name = t_name;
-    memset(a_hosts, 0, AFSMAXCELLHOSTS * sizeof(afs_int32));
+    a_hosts->serverList_len = 0;
     return 0;
 }
 
@@ -455,10 +499,13 @@ int SRXAFSCB_GetLocalCell(
 {
     char *t_name;
 
-    t_name = (char *)malloc(AFSNAMEMAX);
+    osi_Log0(afsd_logp, "SRXAFSCB_GetLocalCell");
+
     if (cm_rootCellp) {
+       t_name = (char *)malloc(strlen(cm_rootCellp->namep)+1);
         strcpy(t_name, cm_rootCellp->namep);
     } else {
+       t_name = (char *)malloc(1);
        t_name[0] = '\0';
     }
     *a_name = t_name;
@@ -539,6 +586,8 @@ cacheConfig *config;
     size_t allocsize;
     extern cm_initparams_v1 cm_initParams;
 
+    osi_Log0(afsd_logp, "SRXAFSCB_GetCacheConfig - version 1 only");
+
     /*
      * Currently only support version 1
      */
@@ -568,9 +617,52 @@ void cm_InitCallback(void)
  */
 int cm_HaveCallback(cm_scache_t *scp)
 {
-       if (scp->cbServerp != NULL)
-               return 1;
-       else return 0;
+#ifdef AFS_FREELANCE_CLIENT
+    // yj: we handle callbacks specially for callbacks on the root directory
+    // Since it's local, we almost always say that we have callback on it
+    // The only time we send back a 0 is if we're need to initialize or
+    // reinitialize the fake directory
+
+    // There are 2 state variables cm_fakeGettingCallback and cm_fakeDirCallback
+    // cm_fakeGettingCallback is 1 if we're in the process of initialization and
+    // hence should return false. it's 0 otherwise
+    // cm_fakeDirCallback is 0 if we haven't loaded the fake directory, it's 1
+    // if the fake directory is loaded and this is the first time cm_HaveCallback
+    // is called since then. We return false in this case to allow cm_GetCallback
+    // to be called because cm_GetCallback has some initialization work to do.
+    // If cm_fakeDirCallback is 2, then it means that the fake directory is in
+    // good shape and we simply return true, provided no change is detected.
+  int fdc, fgc;
+
+    if (cm_freelanceEnabled && 
+        scp->fid.cell==AFS_FAKE_ROOT_CELL_ID &&
+        scp->fid.volume==AFS_FAKE_ROOT_VOL_ID) {       // if it's something on /afs
+       if (!(scp->fid.vnode==0x1 && scp->fid.unique==0x1))     // if it's not root.afs
+           return 1;
+       else {
+           lock_ObtainMutex(&cm_Freelance_Lock);
+           fdc = cm_fakeDirCallback;
+           fgc = cm_fakeGettingCallback;
+           lock_ReleaseMutex(&cm_Freelance_Lock);
+           
+           if (fdc==1) {       // first call since init
+               return 0;
+           } else if (fdc==2 && !fgc) {        // we're in good shape
+               if (cm_getLocalMountPointChange()) {    // check for changes
+                   cm_clearLocalMountPointChange(); // clear the changefile
+                   cm_reInitLocalMountPoints();        // start reinit
+                   return 0;
+               }
+               return 1;                       // no change
+           }
+           return 0;
+       }
+    }
+#endif
+
+    if (scp->cbServerp != NULL)
+       return 1;
+    else return 0;
 }
 
 /* need to detect a broken callback that races with our obtaining a callback.
@@ -645,8 +737,7 @@ void cm_EndCallbackGrantingCall(cm_scache_t *scp, cm_callbackRequest_t *cbrp,
                  */
                 if (scp && cbrp->callbackCount != cm_callbackCount
                                && revp->callbackCount > cbrp->callbackCount
-                               && (
-                               (scp->fid.volume == revp->fid.volume &&
+             && (( scp->fid.volume == revp->fid.volume &&
                                  scp->fid.vnode == revp->fid.vnode &&
                                  scp->fid.unique == revp->fid.unique)
                             ||
@@ -685,55 +776,94 @@ long cm_GetCallback(cm_scache_t *scp, struct cm_user *userp,
        struct cm_req *reqp, long flags)
 {
        long code;
-        cm_conn_t *connp;
-        AFSFetchStatus afsStatus;
-        AFSVolSync volSync;
-        AFSCallBack callback;
-        AFSFid tfid;
-        cm_callbackRequest_t cbr;
-        int mustCall;
-        long sflags;
+    cm_conn_t *connp;
+    AFSFetchStatus afsStatus;
+    AFSVolSync volSync;
+    AFSCallBack callback;
+    AFSFid tfid;
+    cm_callbackRequest_t cbr;
+    int mustCall;
+    long sflags;
+    cm_fid_t sfid;
+
+    osi_Log2(afsd_logp, "GetCallback scp %x flags %lX", scp, flags);
+
+#ifdef AFS_FREELANCE_CLIENT
+       // The case where a callback is needed on /afs is handled
+       // specially. We need to fetch the status by calling
+       // cm_MergeStatus and mark that cm_fakeDirCallback is 2
+       if (cm_freelanceEnabled) {
+        if (scp->fid.cell==AFS_FAKE_ROOT_CELL_ID &&
+             scp->fid.volume==AFS_FAKE_ROOT_VOL_ID &&
+             scp->fid.unique==0x1 &&
+             scp->fid.vnode==0x1) {
+            // Start by indicating that we're in the process
+            // of fetching the callback
+
+            lock_ObtainMutex(&cm_Freelance_Lock);
+            cm_fakeGettingCallback = 1;
+            lock_ReleaseMutex(&cm_Freelance_Lock);
+
+            // Fetch the status info 
+            cm_MergeStatus(scp, &afsStatus, &volSync, userp, 0);
+
+            // Indicate that the callback is not done
+            lock_ObtainMutex(&cm_Freelance_Lock);
+            cm_fakeDirCallback = 2;
+            // Indicate that we're no longer fetching the callback
+            cm_fakeGettingCallback = 0;
+            lock_ReleaseMutex(&cm_Freelance_Lock);
+
+            return 0;
+        }
 
+        if (scp->fid.cell==AFS_FAKE_ROOT_CELL_ID && scp->fid.volume==AFS_FAKE_ROOT_VOL_ID) {
+            osi_Log0(afsd_logp,"cm_getcallback should NEVER EVER get here... ");
+        }
+    }
+#endif /* AFS_FREELANCE_CLIENT */
+       
        mustCall = (flags & 1);
        cm_AFSFidFromFid(&tfid, &scp->fid);
        while (1) {
                if (!mustCall && cm_HaveCallback(scp)) return 0;
 
-                /* turn off mustCall, since it has now forced us past the check above */
-                mustCall = 0;
+        /* turn off mustCall, since it has now forced us past the check above */
+        mustCall = 0;
 
-                /* otherwise, we have to make an RPC to get the status */
+        /* otherwise, we have to make an RPC to get the status */
                sflags = CM_SCACHESYNC_FETCHSTATUS | CM_SCACHESYNC_GETCALLBACK;
-                cm_SyncOp(scp, NULL, NULL, NULL, 0, sflags);
-                cm_StartCallbackGrantingCall(scp, &cbr);
+        cm_SyncOp(scp, NULL, NULL, NULL, 0, sflags);
+        cm_StartCallbackGrantingCall(scp, &cbr);
+        sfid = scp->fid;
                lock_ReleaseMutex(&scp->mx);
                
                /* now make the RPC */
                osi_Log1(afsd_logp, "CALL FetchStatus vp %x", (long) scp);
-               do {
-                       code = cm_Conn(&scp->fid, userp, reqp, &connp);
-                       if (code) continue;
+        do {
+                       code = cm_Conn(&sfid, userp, reqp, &connp);
+            if (code) continue;
                
-                       code = RXAFS_FetchStatus(connp->callp, &tfid,
-                               &afsStatus, &callback, &volSync);
+            code = RXAFS_FetchStatus(connp->callp, &tfid,
+                                     &afsStatus, &callback, &volSync);
 
-               } while (cm_Analyze(connp, userp, reqp, &scp->fid, &volSync,
-                                   &cbr, code));
-                code = cm_MapRPCError(code, reqp);
+               } while (cm_Analyze(connp, userp, reqp, &sfid, &volSync, NULL,
+                            &cbr, code));
+        code = cm_MapRPCError(code, reqp);
                osi_Log0(afsd_logp, "CALL FetchStatus DONE");
 
                lock_ObtainMutex(&scp->mx);
-                cm_SyncOpDone(scp, NULL, sflags);
+        cm_SyncOpDone(scp, NULL, sflags);
                if (code == 0) {
-                       cm_EndCallbackGrantingCall(scp, &cbr, &callback, 0);
-                       cm_MergeStatus(scp, &afsStatus, &volSync, userp, 0);
-               }
-                else
-                       cm_EndCallbackGrantingCall(NULL, NULL, NULL, 0);
-
-                /* now check to see if we got an error */
-                if (code) return code;
-        }
+            cm_EndCallbackGrantingCall(scp, &cbr, &callback, 0);
+            cm_MergeStatus(scp, &afsStatus, &volSync, userp, 0);
+               }   
+        else
+            cm_EndCallbackGrantingCall(NULL, NULL, NULL, 0);
+
+        /* now check to see if we got an error */
+        if (code) return code;
+    }
 }
 
 /* called periodically by cm_daemon to shut down use of expired callbacks */
@@ -743,6 +873,8 @@ void cm_CheckCBExpiration(void)
         cm_scache_t *scp;
         long now;
         
+    osi_Log0(afsd_logp, "CheckCBExpiration");
+
        now = osi_Time();
        lock_ObtainWrite(&cm_scacheLock);
         for(i=0; i<cm_hashTableSize; i++) {
@@ -751,6 +883,7 @@ void cm_CheckCBExpiration(void)
                        lock_ReleaseWrite(&cm_scacheLock);
                        lock_ObtainMutex(&scp->mx);
                        if (scp->cbServerp && now > scp->cbExpires) {
+                osi_Log1(afsd_logp, "Discarding SCache scp %x", scp);
                                cm_DiscardSCache(scp);
                         }
                        lock_ReleaseMutex(&scp->mx);
@@ -760,3 +893,21 @@ void cm_CheckCBExpiration(void)
         }
         lock_ReleaseWrite(&cm_scacheLock);
 }
+
+/* debug interface: not implemented */
+int SRXAFSCB_GetCellByNum(struct rx_call *a_call, afs_int32 a_cellnum,
+                         char **a_name, serverList *a_hosts)
+{
+    /* XXXX */
+    osi_Log0(afsd_logp, "SRXAFSCB_GetCellByNum - not implemented");
+    return RXGEN_OPCODE;
+}
+
+/* debug interface: not implemented */
+int SRXAFSCB_TellMeAboutYourself(struct rx_call *a_call, afs_int32 a_cellnum,
+                          char **a_name, serverList *a_hosts)
+{
+    /* XXXX */
+    osi_Log0(afsd_logp, "SRXAFSCB_TellMeAboutYourself - not implemented");
+    return RXGEN_OPCODE;
+}