a9deefa0d4b5511e14171f6463191844a33ba918
[openafs.git] / src / WINNT / afsd / cm_callback.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  *
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 #include <afsconfig.h>
11 #include <afs/param.h>
12 #include <roken.h>
13
14 #include <afs/afs_args.h>
15 #include <afs/stds.h>
16
17 #include <windows.h>
18 #include <winsock2.h>
19 #include <malloc.h>
20 #include <string.h>
21 #include <stdlib.h>
22
23 #include "afsd.h"
24 #include "smb.h"
25 #include <osi.h>
26 #include <rx_pthread.h>
27
28 #include <WINNT/syscfg.h>
29 #include <WINNT/afsreg.h>
30
31 int
32 SRXAFSCB_InitCallBackState3(struct rx_call *callp, afsUUID* serverUuid);
33
34 /* read/write lock for all global storage in this module */
35 osi_rwlock_t cm_callbackLock;
36
37 afs_int32 cm_OfflineROIsValid = 0;
38
39 afs_int32 cm_giveUpAllCBs = 1;
40
41 afs_int32 cm_shutdown = 0;
42
43 #ifdef AFS_FREELANCE_CLIENT
44 extern osi_mutex_t cm_Freelance_Lock;
45 #endif
46
47 /* count of # of callback breaking messages received by this CM so far.  We use
48  * this count in determining whether there have been any callback breaks that
49  * apply to a call that returned a new callback.  If the counter doesn't
50  * increase during a call, then we know that no callbacks were broken during
51  * that call, and thus that the callback that was just returned is still valid.
52  */
53 long cm_callbackCount;
54
55 /* count of number of RPCs potentially returning a callback executing now.
56  * When this counter hits zero, we can clear out the racing revokes list, since
57  * at that time, we know that none of the just-executed callback revokes will
58  * apply to any future call that returns a callback (since the latter hasn't
59  * even started execution yet).
60  */
61 long cm_activeCallbackGrantingCalls;
62
63 /* list of callbacks that have been broken recently.  If a call returning a
64  * callback is executing and a callback revoke runs immediately after it at the
65  * server, the revoke may end up being processed before the response to the
66  * original callback granting call.  We detect this by keeping a list of
67  * callback revokes that have been received since we *started* the callback
68  * granting call, and discarding any callbacks received for the same file ID,
69  * even if the callback revoke was received before the callback grant.
70  */
71 cm_racingRevokes_t *cm_racingRevokesp;
72
73 /* record a (potentially) racing revoke for this file ID; null means for all
74  * file IDs, and is used by InitCallBackState.
75  *
76  * The cancelFlags describe whether we're just discarding callbacks for the same
77  * file ID, the same volume, or all from the same server.
78  *
79  * Called with no locks held.
80  */
81 void cm_RecordRacingRevoke(cm_fid_t *fidp, long cancelFlags)
82 {
83     cm_racingRevokes_t *rp;
84
85     lock_ObtainWrite(&cm_callbackLock);
86
87     osi_Log3(afsd_logp, "RecordRacingRevoke Volume %d Flags %lX activeCalls %d",
88                 fidp ? fidp->volume : 0, cancelFlags, cm_activeCallbackGrantingCalls);
89
90     if (cm_activeCallbackGrantingCalls > 0) {
91         rp = malloc(sizeof(*rp));
92         memset(rp, 0, sizeof(*rp));
93         osi_QAdd((osi_queue_t **) &cm_racingRevokesp, &rp->q);
94         rp->flags |= (cancelFlags & CM_RACINGFLAG_ALL);
95         if (fidp) rp->fid = *fidp;
96         rp->callbackCount = ++cm_callbackCount;
97     }
98     lock_ReleaseWrite(&cm_callbackLock);
99 }
100
101 /*
102  * When we lose a callback, may have to send change notification replies.
103  * Do not call with a lock on the scp.
104  */
105 void cm_CallbackNotifyChange(cm_scache_t *scp)
106 {
107     DWORD dwDelay = 0;
108     HKEY  hKey;
109     DWORD dummyLen;
110
111     /* why does this have to query the registry each time? */
112         if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
113                       AFSREG_CLT_OPENAFS_SUBKEY,
114                       0,
115                       KEY_READ|KEY_QUERY_VALUE,
116                       &hKey) == ERROR_SUCCESS) {
117
118         dummyLen = sizeof(DWORD);
119         RegQueryValueEx(hKey, "CallBack Notify Change Delay", NULL, NULL,
120                         (BYTE *) &dwDelay, &dummyLen);
121         RegCloseKey(hKey);
122     }
123
124     if (dwDelay > 5000)    /* do not allow a delay of more then 5 seconds */
125         dwDelay = 5000;
126
127     osi_Log3(afsd_logp, "CallbackNotifyChange FileType %d Flags %lX Delay %dms",
128               scp->fileType, scp->flags, dwDelay);
129
130     if (dwDelay)
131         Sleep(dwDelay);
132
133     /* for directories, this sends a change notification on the dir itself */
134     if (scp->fileType == CM_SCACHETYPE_DIRECTORY) {
135         if (scp->flags & CM_SCACHEFLAG_ANYWATCH)
136             smb_NotifyChange(0,
137                              FILE_NOTIFY_GENERIC_DIRECTORY_FILTER,
138                              scp, NULL, NULL, TRUE);
139     } else {
140         /* and for files, this sends a change notification on the file's parent dir */
141         cm_fid_t tfid;
142         cm_scache_t *dscp;
143
144         cm_SetFid(&tfid, scp->fid.cell, scp->fid.volume, scp->parentVnode, scp->parentUnique);
145         dscp = cm_FindSCache(&tfid);
146         if ( dscp &&
147              dscp->flags & CM_SCACHEFLAG_ANYWATCH )
148             smb_NotifyChange( 0,
149                               FILE_NOTIFY_GENERIC_FILE_FILTER,
150                               dscp, NULL, NULL, TRUE);
151         if (dscp)
152             cm_ReleaseSCache(dscp);
153     }
154 }
155
156 /* called with no locks held for every file ID that is revoked directly by
157  * a callback revoke call.  Does not have to handle volume callback breaks,
158  * since those have already been split out.
159  *
160  * The callp parameter is currently unused.
161  */
162 void cm_RevokeCallback(struct rx_call *callp, cm_cell_t * cellp, AFSFid *fidp)
163 {
164     cm_fid_t tfid;
165     cm_scache_t *scp;
166     long hash;
167
168     tfid.cell = cellp ? cellp->cellID : 0;
169     tfid.volume = fidp->Volume;
170     tfid.vnode = fidp->Vnode;
171     tfid.unique = fidp->Unique;
172     CM_FID_GEN_HASH(&tfid);
173     hash = CM_SCACHE_HASH(&tfid);
174
175     osi_Log3(afsd_logp, "RevokeCallback vol %u vn %u uniq %u",
176              fidp->Volume, fidp->Vnode, fidp->Unique);
177
178     /* do this first, so that if we're executing a callback granting call
179      * at this moment, we kill it before it can be merged in.  Otherwise,
180      * it could complete while we're doing the scan below, and get missed
181      * by both the scan and by this code.
182      */
183     cm_RecordRacingRevoke(&tfid, 0);
184
185     lock_ObtainWrite(&cm_scacheLock);
186     /* do all in the hash bucket, since we don't know how many we'll find with
187      * varying cells.
188      */
189     for (scp = cm_data.scacheHashTablep[hash]; scp; scp=scp->nextp) {
190         if (scp->fid.volume == tfid.volume &&
191              scp->fid.vnode == tfid.vnode &&
192              scp->fid.unique == tfid.unique &&
193              (cellp == NULL || scp->fid.cell == cellp->cellID) &&
194              cm_HaveCallback(scp))
195         {
196             cm_HoldSCacheNoLock(scp);
197             lock_ReleaseWrite(&cm_scacheLock);
198             osi_Log4(afsd_logp, "RevokeCallback Discarding SCache scp 0x%p vol %u vn %u uniq %u",
199                      scp, scp->fid.volume, scp->fid.vnode, scp->fid.unique);
200
201             lock_ObtainWrite(&scp->rw);
202             cm_DiscardSCache(scp);
203             lock_ReleaseWrite(&scp->rw);
204
205             if (RDR_Initialized)
206                 RDR_InvalidateObject(scp->fid.cell, scp->fid.volume, scp->fid.vnode, scp->fid.unique,
207                                      scp->fid.hash, scp->fileType, AFS_INVALIDATE_CALLBACK);
208
209             cm_CallbackNotifyChange(scp);
210
211             lock_ObtainWrite(&cm_scacheLock);
212             cm_ReleaseSCacheNoLock(scp);
213         }
214     }
215     lock_ReleaseWrite(&cm_scacheLock);
216
217     osi_Log3(afsd_logp, "RevokeCallback Complete vol %u vn %u uniq %u",
218              fidp->Volume, fidp->Vnode, fidp->Unique);
219 }
220
221 static __inline void
222 cm_callbackDiscardROVolumeByFID(cm_fid_t *fidp)
223 {
224     cm_volume_t *volp = cm_GetVolumeByFID(fidp);
225     if (volp) {
226         cm_PutVolume(volp);
227         if (volp->cbExpiresRO) {
228             volp->cbExpiresRO = 0;
229             volp->cbIssuedRO = 0;
230             volp->volumeSizeRO = 0;
231             _InterlockedAnd(&volp->volumeSizeRO, ~CM_VOLUMEFLAG_RO_SIZE_VALID);
232             if (volp->cbServerpRO) {
233                 cm_PutServer(volp->cbServerpRO);
234                 volp->cbServerpRO = NULL;
235             }
236             volp->creationDateRO = 0;
237         }
238     }
239 }
240
241 /* called to revoke a volume callback, which is typically issued when a volume
242  * is moved from one server to another.
243  *
244  * Called with no locks held.
245  */
246 void cm_RevokeVolumeCallback(struct rx_call *callp, cm_cell_t *cellp, AFSFid *fidp)
247 {
248     unsigned long hash;
249     cm_scache_t *scp;
250     cm_fid_t tfid;
251
252     osi_Log1(afsd_logp, "RevokeVolumeCallback vol %u", fidp->Volume);
253
254     /* do this first, so that if we're executing a callback granting call
255      * at this moment, we kill it before it can be merged in.  Otherwise,
256      * it could complete while we're doing the scan below, and get missed
257      * by both the scan and by this code.
258      */
259     tfid.cell = cellp ? cellp->cellID : 0;
260     tfid.volume = fidp->Volume;
261     tfid.vnode = tfid.unique = 0;
262     cm_RecordRacingRevoke(&tfid, CM_RACINGFLAG_CANCELVOL);
263
264     lock_ObtainWrite(&cm_scacheLock);
265     for (hash = 0; hash < cm_data.scacheHashTableSize; hash++) {
266         for(scp=cm_data.scacheHashTablep[hash]; scp; scp=scp->nextp) {
267             if (scp->fid.volume == fidp->Volume &&
268                 (cellp == NULL || scp->fid.cell == cellp->cellID) &&
269                  scp->cbExpires > 0 &&
270                  scp->cbServerp != NULL) {
271                 cm_HoldSCacheNoLock(scp);
272                 lock_ReleaseWrite(&cm_scacheLock);
273
274                 lock_ObtainWrite(&scp->rw);
275                 osi_Log5(afsd_logp, "RevokeVolumeCallback Discarding SCache scp 0x%p vol %u vn %u uniq %u",
276                           scp, scp->fid.cell, scp->fid.volume, scp->fid.vnode, scp->fid.unique);
277                 osi_Log2(afsd_logp, ".... dv 0x%x:%x",
278                           (afs_uint32)((scp->dataVersion >> 32) & 0xFFFFFFFF),
279                           (afs_uint32)(scp->dataVersion & 0xFFFFFFFF));
280
281                 cm_DiscardSCache(scp);
282                 lock_ReleaseWrite(&scp->rw);
283
284                 if (RDR_Initialized)
285                     RDR_InvalidateObject(scp->fid.cell, scp->fid.volume, scp->fid.vnode, scp->fid.unique,
286                                          scp->fid.hash, scp->fileType, AFS_INVALIDATE_CALLBACK);
287
288                 cm_CallbackNotifyChange(scp);
289                 lock_ObtainWrite(&cm_scacheLock);
290                 cm_ReleaseSCacheNoLock(scp);
291                 if (scp->flags & CM_SCACHEFLAG_PURERO)
292                     cm_callbackDiscardROVolumeByFID(&scp->fid);
293             }
294         }       /* search one hash bucket */
295     }   /* search all hash buckets */
296
297     lock_ReleaseWrite(&cm_scacheLock);
298
299     if (cellp && RDR_Initialized)
300         RDR_InvalidateVolume(cellp->cellID, fidp->Volume, AFS_INVALIDATE_CALLBACK);
301
302     osi_Log1(afsd_logp, "RevokeVolumeCallback Complete vol %d", fidp->Volume);
303 }
304
305 /*
306  * afs_data_pointer_to_int32() - returns least significant afs_int32 of the
307  * given data pointer, without triggering "cast truncates pointer"
308  * warnings.  We use this where we explicitly don't care whether a
309  * pointer is truncated -- it loses information where a pointer is
310  * larger than an afs_int32.
311  */
312
313 static afs_int32
314 afs_data_pointer_to_int32(const void *p)
315 {
316     union {
317         afs_int32 i32[sizeof(void *) / sizeof(afs_int32)];
318         const void *p;
319     } ip;
320
321     int i32_sub;                /* subscript of least significant afs_int32 in ip.i32[] */
322
323     /* set i32_sub */
324
325     {
326         /* used to determine the byte order of the system */
327
328         union {
329             char c[sizeof(int) / sizeof(char)];
330             int i;
331         } ci;
332
333         ci.i = 1;
334         if (ci.c[0] == 1) {
335             /* little-endian system */
336             i32_sub = 0;
337         } else {
338             /* big-endian system */
339             i32_sub = (sizeof ip.i32 / sizeof ip.i32[0]) - 1;
340         }
341     }
342
343     ip.p = p;
344     return ip.i32[i32_sub];
345 }
346 /*------------------------------------------------------------------------
347  * EXPORTED SRXAFSCB_CallBack
348  *
349  * Description:
350  *      Routine called by the server-side callback RPC interface to
351  *      implement passing in callback information.
352  *      table.
353  *
354  * Arguments:
355  *      rx_call    : Ptr to Rx call on which this request came in.
356  *      fidsArrayp : Ptr to array of fids involved.
357  *      cbsArrayp  : Ptr to matching callback info for the fids.
358  *
359  * Returns:
360  *      0 (always).
361  *
362  * Environment:
363  *      Nothing interesting.
364  *
365  * Side Effects:
366  *      As advertised.
367  *------------------------------------------------------------------------*/
368 /* handle incoming RPC callback breaking message.
369  * Called with no locks held.
370  */
371 int
372 SRXAFSCB_CallBack(struct rx_call *callp, AFSCBFids *fidsArrayp, AFSCBs *cbsArrayp)
373 {
374     int i;
375     AFSFid *tfidp;
376     struct rx_connection *connp;
377     struct rx_peer *peerp;
378     unsigned long host = 0;
379     unsigned short port = 0;
380     cm_server_t *tsp = NULL;
381     cm_cell_t* cellp = NULL;
382
383     if (cm_shutdown)
384         return 1;
385
386     if ((connp = rx_ConnectionOf(callp)) && (peerp = rx_PeerOf(connp))) {
387         host = rx_HostOf(peerp);
388         port = rx_PortOf(peerp);
389
390         tsp = cm_FindServerByIP(host, port, CM_SERVER_FILE, FALSE);
391         if (tsp) {
392             cellp = tsp->cellp;
393             cm_PutServer(tsp);
394         }
395
396         if (!cellp)
397             osi_Log2(afsd_logp, "SRXAFSCB_CallBack from host 0x%x port %d",
398                      ntohl(host),
399                      ntohs(port));
400         else
401             osi_Log3(afsd_logp, "SRXAFSCB_CallBack from host 0x%x port %d for cell %s",
402                      ntohl(host),
403                      ntohs(port),
404                      cellp->name /* does not need to be saved, doesn't change */);
405     } else {
406         osi_Log0(afsd_logp, "SRXAFSCB_CallBack from unknown host");
407     }
408
409
410     for (i=0; i < (long) fidsArrayp->AFSCBFids_len; i++) {
411         tfidp = &fidsArrayp->AFSCBFids_val[i];
412
413         if (tfidp->Volume == 0)
414             continue;   /* means don't do anything */
415         else if (tfidp->Vnode == 0)
416             cm_RevokeVolumeCallback(callp, cellp, tfidp);
417         else
418             cm_RevokeCallback(callp, cellp, tfidp);
419     }
420     return 0;
421 }
422
423 /*------------------------------------------------------------------------
424  * EXPORTED SRXAFSCB_InitCallBackState
425  *
426  * Description:
427  *      Routine called by the server-side callback RPC interface to
428  *      implement clearing all callbacks from this host.
429  *
430  * Arguments:
431  *      rx_call : Ptr to Rx call on which this request came in.
432  *
433  * Returns:
434  *      0 (always).
435  *
436  * Environment:
437  *      Nothing interesting.
438  *
439  * Side Effects:
440  *      As advertised.
441  *------------------------------------------------------------------------*/
442 /* called with no locks by RPC system when a server indicates that it has never
443  * heard from us, or for other reasons has had to discard callbacks from us
444  * without telling us, e.g. a network partition.
445  */
446 int
447 SRXAFSCB_InitCallBackState(struct rx_call *callp)
448 {
449     if (cm_shutdown)
450         return 1;
451
452     osi_Log0(afsd_logp, "SRXAFSCB_InitCallBackState ->");
453
454     return SRXAFSCB_InitCallBackState3(callp, NULL);
455 }
456
457 /*------------------------------------------------------------------------
458  * EXPORTED SRXAFSCB_Probe
459  *
460  * Description:
461  *      Routine called by the server-side callback RPC interface to
462  *      implement ``probing'' the Cache Manager, just making sure it's
463  *      still there.
464  *
465  * Arguments:
466  *      rx_call : Ptr to Rx call on which this request came in.
467  *
468  * Returns:
469  *      0 (always).
470  *
471  * Environment:
472  *      Nothing interesting.
473  *
474  * Side Effects:
475  *      As advertised.
476  *------------------------------------------------------------------------*/
477 int
478 SRXAFSCB_Probe(struct rx_call *callp)
479 {
480     struct rx_connection *connp;
481     struct rx_peer *peerp;
482     unsigned long host = 0;
483     unsigned short port = 0;
484
485     if (cm_shutdown)
486         return 1;
487
488     if ((connp = rx_ConnectionOf(callp)) && (peerp = rx_PeerOf(connp))) {
489         host = rx_HostOf(peerp);
490         port = rx_PortOf(peerp);
491     }
492
493     osi_Log2(afsd_logp, "SRXAFSCB_Probe from host 0x%x port %d",
494               ntohl(host),
495               ntohs(port));
496
497     return 0;
498 }
499
500 /*------------------------------------------------------------------------
501  * EXPORTED SRXAFSCB_GetLock
502  *
503  * Description:
504  *      Routine called by the server-side callback RPC interface to
505  *      implement pulling out the contents of a lock in the lock
506  *      table.
507  *
508  * Arguments:
509  *      a_call   : Ptr to Rx call on which this request came in.
510  *      a_index  : Index of desired lock.
511  *      a_result : Ptr to a buffer for the given lock.
512  *
513  * Returns:
514  *      0 if everything went fine,
515  *      1 if we were given a bad index.
516  *
517  * Environment:
518  *      Nothing interesting.
519  *
520  * Side Effects:
521  *      As advertised.
522  *------------------------------------------------------------------------*/
523 /* debug interface */
524
525 extern osi_rwlock_t cm_aclLock;
526 extern osi_rwlock_t buf_globalLock;
527 extern osi_rwlock_t cm_cellLock;
528 extern osi_rwlock_t cm_connLock;
529 extern osi_rwlock_t cm_dnlcLock;
530 extern osi_rwlock_t cm_scacheLock;
531 extern osi_rwlock_t cm_serverLock;
532 extern osi_rwlock_t cm_syscfgLock;
533 extern osi_rwlock_t cm_userLock;
534 extern osi_rwlock_t cm_utilsLock;
535 extern osi_rwlock_t cm_volumeLock;
536 extern osi_rwlock_t smb_globalLock;
537 extern osi_rwlock_t smb_rctLock;
538
539 extern osi_mutex_t cm_Freelance_Lock;
540 extern osi_mutex_t cm_Afsdsbmt_Lock;
541 extern osi_mutex_t tokenEventLock;
542 extern osi_mutex_t  smb_ListenerLock;
543 extern osi_mutex_t smb_RawBufLock;
544 extern osi_mutex_t smb_Dir_Watch_Lock;
545
546 #define LOCKTYPE_RW     1
547 #define LOCKTYPE_MUTEX  2
548 static struct _ltable {
549     char *name;
550     char *addr;
551     int  type;
552 } ltable[] = {
553     {"cm_scacheLock",    (char*)&cm_scacheLock,         LOCKTYPE_RW},
554     {"buf_globalLock",   (char*)&buf_globalLock,        LOCKTYPE_RW},
555     {"cm_serverLock",    (char*)&cm_serverLock,         LOCKTYPE_RW},
556     {"cm_callbackLock",  (char*)&cm_callbackLock,       LOCKTYPE_RW},
557     {"cm_syscfgLock",    (char*)&cm_syscfgLock,         LOCKTYPE_RW},
558     {"cm_aclLock",       (char*)&cm_aclLock,            LOCKTYPE_RW},
559     {"cm_cellLock",      (char*)&cm_cellLock,           LOCKTYPE_RW},
560     {"cm_connLock",      (char*)&cm_connLock,           LOCKTYPE_RW},
561     {"cm_userLock",      (char*)&cm_userLock,           LOCKTYPE_RW},
562     {"cm_volumeLock",    (char*)&cm_volumeLock,         LOCKTYPE_RW},
563     {"cm_dnlcLock",      (char*)&cm_dnlcLock,           LOCKTYPE_RW},
564     {"cm_utilsLock",     (char*)&cm_utilsLock,          LOCKTYPE_RW},
565     {"smb_globalLock",   (char*)&smb_globalLock,        LOCKTYPE_RW},
566     {"smb_rctLock",      (char*)&smb_rctLock,           LOCKTYPE_RW},
567     {"cm_Freelance_Lock",(char*)&cm_Freelance_Lock,     LOCKTYPE_MUTEX},
568     {"cm_Afsdsbmt_Lock", (char*)&cm_Afsdsbmt_Lock,      LOCKTYPE_MUTEX},
569     {"tokenEventLock",   (char*)&tokenEventLock,        LOCKTYPE_MUTEX},
570     {"smb_ListenerLock", (char*)&smb_ListenerLock,      LOCKTYPE_MUTEX},
571     {"smb_RawBufLock",   (char*)&smb_RawBufLock,        LOCKTYPE_MUTEX},
572     {"smb_Dir_Watch_Lock",(char*)&smb_Dir_Watch_Lock,   LOCKTYPE_MUTEX}
573 };
574
575 int
576 SRXAFSCB_GetLock(struct rx_call *callp, long index, AFSDBLock *lockp)
577 {
578     struct _ltable *tl;          /*Ptr to lock table entry */
579     osi_rwlock_t  *rwp;
580     osi_mutex_t   *mtxp;
581     int nentries;               /*Num entries in table */
582     int code;                   /*Return code */
583     struct rx_connection *connp;
584     struct rx_peer *peerp;
585     unsigned long host = 0;
586     unsigned short port = 0;
587
588     if (cm_shutdown)
589         return 1;
590
591     if ((connp = rx_ConnectionOf(callp)) && (peerp = rx_PeerOf(connp))) {
592         host = rx_HostOf(peerp);
593         port = rx_PortOf(peerp);
594     }
595
596     osi_Log3(afsd_logp, "SRXAFSCB_GetLock(%d) from host 0x%x port %d",
597              index, ntohl(host), ntohs(port));
598
599     nentries = sizeof(ltable) / sizeof(struct _ltable);
600     if (index < 0 || index >= nentries) {
601         /*
602          * Past EOF
603          */
604         code = 1;
605     } else {
606         /*
607          * Found it - copy out its contents.
608          */
609         tl = &ltable[index];
610         strncpy(lockp->name, tl->name, sizeof(lockp->name));
611         lockp->name[sizeof(lockp->name)-1] = '\0';
612         lockp->lock.waitStates = 0;
613         switch ( tl->type ) {
614         case LOCKTYPE_RW:
615             rwp = (osi_rwlock_t *)tl->addr;
616             lockp->lock.exclLocked = rwp->flags;
617             lockp->lock.readersReading = rwp->readers;
618             lockp->lock.numWaiting = rwp->waiters;
619             break;
620         case LOCKTYPE_MUTEX:
621             mtxp = (osi_mutex_t *)tl->addr;
622             lockp->lock.exclLocked = mtxp->flags;
623             lockp->lock.readersReading = 0;
624             lockp->lock.numWaiting = mtxp->waiters;
625             break;
626         }
627         lockp->lock.pid_last_reader = 0;
628         lockp->lock.pid_writer = 0;
629         lockp->lock.src_indicator = 0;
630         code = 0;
631     }
632
633     return code;
634 }
635
636 /* debug interface */
637 int
638 SRXAFSCB_GetCE(struct rx_call *callp, long index, AFSDBCacheEntry *cep)
639 {
640     afs_uint32 i;
641     cm_scache_t * scp;
642     int code;
643     struct rx_connection *connp;
644     struct rx_peer *peerp;
645     unsigned long host = 0;
646     unsigned short port = 0;
647
648     if (cm_shutdown)
649         return 1;
650
651     if ((connp = rx_ConnectionOf(callp)) && (peerp = rx_PeerOf(connp))) {
652         host = rx_HostOf(peerp);
653         port = rx_PortOf(peerp);
654     }
655
656     osi_Log2(afsd_logp, "SRXAFSCB_GetCE from host 0x%x port %d",
657              ntohl(host), ntohs(port));
658
659     lock_ObtainRead(&cm_scacheLock);
660     for (i = 0; i < cm_data.scacheHashTableSize; i++) {
661         for (scp = cm_data.scacheHashTablep[i]; scp; scp = scp->nextp) {
662             if (index == 0)
663                 goto searchDone;
664             index--;
665         }                       /*Zip through current hash chain */
666     }                           /*Zip through hash chains */
667
668   searchDone:
669     if (scp == NULL) {
670         /*Past EOF */
671         code = 1;
672         goto fcnDone;
673     }
674
675     /*
676      * Copy out the located entry.
677      */
678     memset(cep, 0, sizeof(AFSDBCacheEntry));
679     cep->addr = afs_data_pointer_to_int32(scp);
680     cep->cell = scp->fid.cell;
681     cep->netFid.Volume = scp->fid.volume;
682     cep->netFid.Vnode = scp->fid.vnode;
683     cep->netFid.Unique = scp->fid.unique;
684     cep->lock.waitStates = 0;
685     cep->lock.exclLocked = scp->rw.flags;
686     cep->lock.readersReading = 0;
687     cep->lock.numWaiting = scp->rw.waiters;
688     cep->lock.pid_last_reader = 0;
689     cep->lock.pid_writer = 0;
690     cep->lock.src_indicator = 0;
691     cep->Length = scp->length.LowPart;
692     cep->DataVersion = (afs_uint32)(scp->dataVersion & 0xFFFFFFFF);
693     cep->callback = afs_data_pointer_to_int32(scp->cbServerp);
694     if (scp->flags & CM_SCACHEFLAG_PURERO) {
695         cm_volume_t *volp = cm_GetVolumeByFID(&scp->fid);
696         if (volp) {
697             cep->cbExpires = volp->cbExpiresRO;
698             cm_PutVolume(volp);
699         }
700     } else {
701         /* TODO: deal with time_t below */
702         cep->cbExpires = (afs_int32) scp->cbExpires;
703     }
704     cep->refCount = scp->refCount;
705     cep->opens = scp->openReads;
706     cep->writers = scp->openWrites;
707     switch (scp->fileType) {
708     case CM_SCACHETYPE_FILE:
709         cep->mvstat = 0;
710         break;
711     case CM_SCACHETYPE_MOUNTPOINT:
712         cep->mvstat = 1;
713         break;
714     case CM_SCACHETYPE_DIRECTORY:
715         if (scp->fid.vnode == 1 && scp->fid.unique == 1)
716             cep->mvstat = 2;
717         else
718             cep->mvstat = 3;
719         break;
720     case CM_SCACHETYPE_SYMLINK:
721         cep->mvstat = 4;
722         break;
723     case CM_SCACHETYPE_DFSLINK:
724         cep->mvstat = 5;
725         break;
726     case CM_SCACHETYPE_INVALID:
727         cep->mvstat = 6;
728         break;
729     }
730     cep->states = 0;
731     if (cm_HaveCallback(scp))
732         cep->states |= 1;
733     if (scp->flags & CM_SCACHEFLAG_RO || scp->flags & CM_SCACHEFLAG_PURERO)
734         cep->states |= 4;
735     if (scp->fileType == CM_SCACHETYPE_MOUNTPOINT &&
736         scp->mpDataVersion == scp->dataVersion)
737         cep->states |= 8;
738     if (!osi_QIsEmpty(&scp->waitQueueH))
739         cep->states |= 0x40;
740     code = 0;
741
742     /*
743      * Return our results.
744      */
745   fcnDone:
746     lock_ReleaseRead(&cm_scacheLock);
747
748     return (code);
749 }
750
751 /* debug interface */
752 int
753 SRXAFSCB_GetCE64(struct rx_call *callp, long index, AFSDBCacheEntry64 *cep)
754 {
755     afs_uint32 i;
756     cm_scache_t * scp;
757     int code;
758     struct rx_connection *connp;
759     struct rx_peer *peerp;
760     unsigned long host = 0;
761     unsigned short port = 0;
762
763     if (cm_shutdown)
764         return 1;
765
766     if ((connp = rx_ConnectionOf(callp)) && (peerp = rx_PeerOf(connp))) {
767         host = rx_HostOf(peerp);
768         port = rx_PortOf(peerp);
769     }
770
771     osi_Log2(afsd_logp, "SRXAFSCB_GetCE64 from host 0x%x port %d",
772              ntohl(host), ntohs(port));
773
774     lock_ObtainRead(&cm_scacheLock);
775     for (i = 0; i < cm_data.scacheHashTableSize; i++) {
776         for (scp = cm_data.scacheHashTablep[i]; scp; scp = scp->nextp) {
777             if (index == 0)
778                 goto searchDone;
779             index--;
780         }                       /*Zip through current hash chain */
781     }                           /*Zip through hash chains */
782
783   searchDone:
784     if (scp == NULL) {
785         /*Past EOF */
786         code = 1;
787         goto fcnDone;
788     }
789
790     /*
791      * Copy out the located entry.
792      */
793     memset(cep, 0, sizeof(AFSDBCacheEntry64));
794     cep->addr = afs_data_pointer_to_int32(scp);
795     cep->cell = scp->fid.cell;
796     cep->netFid.Volume = scp->fid.volume;
797     cep->netFid.Vnode = scp->fid.vnode;
798     cep->netFid.Unique = scp->fid.unique;
799     cep->lock.waitStates = 0;
800     cep->lock.exclLocked = scp->rw.flags;
801     cep->lock.readersReading = 0;
802     cep->lock.numWaiting = scp->rw.waiters;
803     cep->lock.pid_last_reader = 0;
804     cep->lock.pid_writer = 0;
805     cep->lock.src_indicator = 0;
806     cep->Length = (afs_int64) scp->length.QuadPart;
807     cep->DataVersion = (afs_uint32)(scp->dataVersion & 0xFFFFFFFF);
808     cep->callback = afs_data_pointer_to_int32(scp->cbServerp);
809     if (scp->flags & CM_SCACHEFLAG_PURERO) {
810         cm_volume_t *volp = cm_GetVolumeByFID(&scp->fid);
811         if (volp) {
812             cep->cbExpires = volp->cbExpiresRO;
813             cm_PutVolume(volp);
814         }
815     } else {
816         /* TODO: handle time_t */
817         cep->cbExpires = (afs_int32) scp->cbExpires;
818     }
819     cep->refCount = scp->refCount;
820     cep->opens = scp->openReads;
821     cep->writers = scp->openWrites;
822     switch (scp->fileType) {
823     case CM_SCACHETYPE_FILE:
824         cep->mvstat = 0;
825         break;
826     case CM_SCACHETYPE_MOUNTPOINT:
827         cep->mvstat = 1;
828         break;
829     case CM_SCACHETYPE_DIRECTORY:
830         if (scp->fid.vnode == 1 && scp->fid.unique == 1)
831             cep->mvstat = 2;
832         else
833             cep->mvstat = 3;
834         break;
835     case CM_SCACHETYPE_SYMLINK:
836         cep->mvstat = 4;
837         break;
838     case CM_SCACHETYPE_DFSLINK:
839         cep->mvstat = 5;
840         break;
841     case CM_SCACHETYPE_INVALID:
842         cep->mvstat = 6;
843         break;
844     }
845     cep->states = 0;
846     if (cm_HaveCallback(scp))
847         cep->states |= 1;
848     if (scp->flags & CM_SCACHEFLAG_RO || scp->flags & CM_SCACHEFLAG_PURERO)
849         cep->states |= 4;
850     if (scp->fileType == CM_SCACHETYPE_MOUNTPOINT &&
851         scp->mpDataVersion == scp->dataVersion)
852         cep->states |= 8;
853     if (!osi_QIsEmpty(&scp->waitQueueH))
854         cep->states |= 0x40;
855     code = 0;
856
857     /*
858      * Return our results.
859      */
860   fcnDone:
861     lock_ReleaseRead(&cm_scacheLock);
862
863     return (code);
864 }
865
866 /* debug interface: not implemented */
867 int
868 SRXAFSCB_XStatsVersion(struct rx_call *callp, long *vp)
869 {
870     struct rx_connection *connp;
871     struct rx_peer *peerp;
872     unsigned long host = 0;
873     unsigned short port = 0;
874
875     if (cm_shutdown)
876         return 1;
877
878     if ((connp = rx_ConnectionOf(callp)) && (peerp = rx_PeerOf(connp))) {
879         host = rx_HostOf(peerp);
880         port = rx_PortOf(peerp);
881     }
882
883     osi_Log2(afsd_logp, "SRXAFSCB_XStatsVersion from host 0x%x port %d - not implemented",
884              ntohl(host), ntohs(port));
885     *vp = -1;
886
887     return RXGEN_OPCODE;
888 }
889
890 /* debug interface: not implemented */
891 int
892 SRXAFSCB_GetXStats(struct rx_call *callp, long cvn, long coln, long *srvp, long *timep,
893                    AFSCB_CollData *datap)
894 {
895     struct rx_connection *connp;
896     struct rx_peer *peerp;
897     unsigned long host = 0;
898     unsigned short port = 0;
899
900     if (cm_shutdown)
901         return 1;
902
903     if ((connp = rx_ConnectionOf(callp)) && (peerp = rx_PeerOf(connp))) {
904         host = rx_HostOf(peerp);
905         port = rx_PortOf(peerp);
906     }
907
908     osi_Log2(afsd_logp, "SRXAFSCB_GetXStats from host 0x%x port %d - not implemented",
909              ntohl(host), ntohs(port));
910
911     return RXGEN_OPCODE;
912 }
913
914 int
915 SRXAFSCB_InitCallBackState2(struct rx_call *callp, struct interfaceAddr* addr)
916 {
917     if (cm_shutdown)
918         return 1;
919
920     osi_Log0(afsd_logp, "SRXAFSCB_InitCallBackState2 ->");
921
922     return SRXAFSCB_InitCallBackState3(callp, NULL);
923 }
924
925 /* debug interface */
926 int
927 SRXAFSCB_WhoAreYou(struct rx_call *callp, struct interfaceAddr* addr)
928 {
929     int i;
930     long code;
931     struct rx_connection *connp;
932     struct rx_peer *peerp;
933     unsigned long host = 0;
934     unsigned short port = 0;
935
936     if (cm_shutdown)
937         return 1;
938
939     if ((connp = rx_ConnectionOf(callp)) && (peerp = rx_PeerOf(connp))) {
940         host = rx_HostOf(peerp);
941         port = rx_PortOf(peerp);
942     }
943
944     osi_Log2(afsd_logp, "SRXAFSCB_WhoAreYou from host 0x%x port %d",
945               ntohl(host),
946               ntohs(port));
947
948     lock_ObtainRead(&cm_syscfgLock);
949     if (cm_LanAdapterChangeDetected) {
950         lock_ConvertRToW(&cm_syscfgLock);
951         if (cm_LanAdapterChangeDetected) {
952             /* get network related info */
953             cm_noIPAddr = CM_MAXINTERFACE_ADDR;
954             code = syscfg_GetIFInfo(&cm_noIPAddr,
955                                      cm_IPAddr, cm_SubnetMask,
956                                      cm_NetMtu, cm_NetFlags);
957             cm_LanAdapterChangeDetected = 0;
958         }
959         lock_ConvertWToR(&cm_syscfgLock);
960     }
961
962     /* return all network interface addresses */
963     addr->numberOfInterfaces = cm_noIPAddr;
964     addr->uuid = cm_data.Uuid;
965     for ( i=0; i < cm_noIPAddr; i++ ) {
966         addr->addr_in[i] = cm_IPAddr[i];
967         addr->subnetmask[i] = cm_SubnetMask[i];
968         addr->mtu[i] = (rx_mtu == -1 || (rx_mtu != -1 && cm_NetMtu[i] < rx_mtu)) ?
969             cm_NetMtu[i] : rx_mtu;
970     }
971
972     lock_ReleaseRead(&cm_syscfgLock);
973
974     return 0;
975 }
976
977 int
978 SRXAFSCB_InitCallBackState3(struct rx_call *callp, afsUUID* serverUuid)
979 {
980     char *p = NULL;
981
982     cm_server_t *tsp = NULL;
983     cm_scache_t *scp = NULL;
984     cm_cell_t* cellp = NULL;
985     afs_uint32 hash;
986     int discarded;
987     cm_fid_t discardFid;
988     afs_uint32 discardType;
989     struct rx_connection *connp;
990     struct rx_peer *peerp;
991     unsigned long host = 0;
992     unsigned short port = 0;
993
994     if (cm_shutdown)
995         return 1;
996
997     if ((connp = rx_ConnectionOf(callp)) && (peerp = rx_PeerOf(connp))) {
998         host = rx_HostOf(peerp);
999         port = rx_PortOf(peerp);
1000
1001         if (serverUuid) {
1002             if (UuidToString((UUID *)serverUuid, &p) == RPC_S_OK) {
1003                 osi_Log1(afsd_logp, "SRXAFSCB_InitCallBackState3 Uuid%s ->",osi_LogSaveString(afsd_logp,p));
1004                 RpcStringFree(&p);
1005             }
1006
1007             tsp = cm_FindServerByUuid(serverUuid, CM_SERVER_FILE, FALSE);
1008         }
1009         if (!tsp)
1010             tsp = cm_FindServerByIP(host, port, CM_SERVER_FILE, FALSE);
1011         if (tsp) {
1012             cellp = tsp->cellp;
1013             cm_PutServer(tsp);
1014         }
1015
1016         if (!cellp)
1017             osi_Log2(afsd_logp, "SRXAFSCB_InitCallBackState3 from host 0x%x port %d",
1018                      ntohl(host),
1019                      ntohs(port));
1020         else
1021             osi_Log3(afsd_logp, "SRXAFSCB_InitCallBackState3 from host 0x%x port %d for cell %s",
1022                      ntohl(host),
1023                      ntohs(port),
1024                      cellp->name /* does not need to be saved, doesn't change */);
1025     } else {
1026         osi_Log0(afsd_logp, "SRXAFSCB_InitCallBackState3 from unknown host");
1027     }
1028
1029     if (connp && peerp) {
1030         tsp = cm_FindServerByIP(host, port, CM_SERVER_FILE, FALSE);
1031
1032         osi_Log1(afsd_logp, "InitCallbackState3 server %x", tsp);
1033
1034         /* record the callback in the racing revokes structure.  This
1035          * shouldn't be necessary, since we shouldn't be making callback
1036          * granting calls while we're going to get an initstate call,
1037          * but there probably are some obscure races, so better safe
1038          * than sorry.
1039          *
1040          * We do this first since we don't hold the cm_scacheLock and vnode
1041          * locks over the entire callback scan operation below.  The
1042          * big loop below is guaranteed to hit any callback already
1043          * processed.  The call to RecordRacingRevoke is guaranteed
1044          * to kill any callback that is currently being returned.
1045          * Anything that sneaks past both must start
1046          * after the call to RecordRacingRevoke.
1047          */
1048         if (cellp) {
1049             cm_fid_t fid;
1050
1051             fid.cell = cellp->cellID;
1052             fid.volume = fid.vnode = fid.unique = 0;
1053
1054             cm_RecordRacingRevoke(&fid, CM_RACINGFLAG_CANCELALL);
1055         } else {
1056             cm_RecordRacingRevoke(NULL, CM_RACINGFLAG_CANCELALL);
1057         }
1058
1059         /* now search all vnodes looking for guys with this callback, if we
1060          * found it, or guys with any callbacks, if we didn't find the server
1061          * (that's how multihomed machines will appear and how we'll handle
1062          * them, albeit a little inefficiently).  That is, we're discarding all
1063          * callbacks from all hosts if we get an initstate call from an unknown
1064          * host.  Since these calls are rare, and multihomed servers
1065          * are "rare," hopefully this won't be a problem.
1066          */
1067         lock_ObtainWrite(&cm_scacheLock);
1068         for (hash = 0; hash < cm_data.scacheHashTableSize; hash++) {
1069             for (scp=cm_data.scacheHashTablep[hash]; scp; scp=scp->nextp) {
1070                 if (scp->cbExpires > 0 && scp->cbServerp != NULL) {
1071                     cm_HoldSCacheNoLock(scp);
1072                     lock_ReleaseWrite(&cm_scacheLock);
1073                     discarded = 0;
1074                     lock_ObtainWrite(&scp->rw);
1075                     if (scp->cbExpires > 0 && scp->cbServerp != NULL) {
1076                         /* we have a callback, now decide if we should clear it */
1077                         if (cm_ServerEqual(scp->cbServerp, tsp)) {
1078                             osi_Log4(afsd_logp, "InitCallbackState3 Discarding SCache scp 0x%p vol %u vn %u uniq %u",
1079                                      scp, scp->fid.volume, scp->fid.vnode, scp->fid.unique);
1080                             discardFid = scp->fid;
1081                             discardType = scp->fileType;
1082                             cm_DiscardSCache(scp);
1083                             discarded = 1;
1084                         }
1085                     }
1086                     lock_ReleaseWrite(&scp->rw);
1087                     if (discarded) {
1088                         cm_CallbackNotifyChange(scp);
1089                         if (RDR_Initialized)
1090                             RDR_InvalidateObject(discardFid.cell, discardFid.volume, discardFid.vnode, discardFid.unique,
1091                                                  discardFid.hash, discardType, AFS_INVALIDATE_EXPIRED);
1092                     }
1093                     lock_ObtainWrite(&cm_scacheLock);
1094                     cm_ReleaseSCacheNoLock(scp);
1095
1096                     if (discarded && (scp->flags & CM_SCACHEFLAG_PURERO))
1097                         cm_callbackDiscardROVolumeByFID(&scp->fid);
1098                 }
1099             }   /* search one hash bucket */
1100         }       /* search all hash buckets */
1101
1102         lock_ReleaseWrite(&cm_scacheLock);
1103
1104         if (tsp) {
1105             /* reset the No flags on the server */
1106             cm_SetServerNo64Bit(tsp, 0);
1107             cm_SetServerNoInlineBulk(tsp, 0);
1108
1109             /* we're done with the server structure */
1110             cm_PutServer(tsp);
1111         }
1112     }
1113     return 0;
1114 }
1115
1116 /* debug interface */
1117 int
1118 SRXAFSCB_ProbeUuid(struct rx_call *callp, afsUUID* clientUuid)
1119 {
1120     struct rx_connection *connp;
1121     struct rx_peer *peerp;
1122     unsigned long host = 0;
1123     unsigned short port = 0;
1124     char *p,*q;
1125     int code = 0;
1126
1127     if (cm_shutdown)
1128         return 1;
1129
1130     if ((connp = rx_ConnectionOf(callp)) && (peerp = rx_PeerOf(connp))) {
1131         host = rx_HostOf(peerp);
1132         port = rx_PortOf(peerp);
1133     }
1134
1135     if ( !afs_uuid_equal(&cm_data.Uuid, clientUuid) ) {
1136         UuidToString((UUID *)&cm_data.Uuid, &p);
1137         UuidToString((UUID *)clientUuid, &q);
1138         osi_Log4(afsd_logp, "SRXAFSCB_ProbeUuid %s != %s from host 0x%x port %d",
1139                   osi_LogSaveString(afsd_logp,p),
1140                   osi_LogSaveString(afsd_logp,q),
1141                   ntohl(host),
1142                   ntohs(port));
1143         RpcStringFree(&p);
1144         RpcStringFree(&q);
1145
1146         code = 1;       /* failure */
1147     } else
1148         osi_Log2(afsd_logp, "SRXAFSCB_ProbeUuid (success) from host 0x%x port %d",
1149                   ntohl(host),
1150                   ntohs(port));
1151
1152     return code;
1153 }
1154
1155 /* debug interface */
1156 static int
1157 GetCellCommon(afs_int32 a_cellnum, char **a_name, serverList *a_hosts)
1158 {
1159     afs_int32 sn;
1160     cm_cell_t * cellp;
1161     cm_serverRef_t * serverRefp;
1162     size_t len;
1163
1164     cellp = cm_FindCellByID(a_cellnum, CM_FLAG_NOPROBE);
1165     if (!cellp) {
1166         *a_name = (char *)xdr_alloc(sizeof(char));
1167         if (*a_name)
1168             *a_name[0] = '\0';
1169         return 0;
1170     }
1171
1172     lock_ObtainRead(&cm_serverLock);
1173     len = strlen(cellp->name)+1;
1174     *a_name = (char *)xdr_alloc(len);
1175     if (*a_name)
1176         memcpy(*a_name, cellp->name, len);
1177
1178     for ( sn = 0, serverRefp = cellp->vlServersp;
1179           sn < AFSMAXCELLHOSTS && serverRefp;
1180           sn++, serverRefp = serverRefp->next);
1181
1182     a_hosts->serverList_len = sn;
1183     a_hosts->serverList_val = (afs_int32 *)xdr_alloc(sn * sizeof(afs_int32));
1184
1185     for ( sn = 0, serverRefp = cellp->vlServersp;
1186           sn < AFSMAXCELLHOSTS && serverRefp;
1187           sn++, serverRefp = serverRefp->next)
1188     {
1189         a_hosts->serverList_val[sn] = ntohl(serverRefp->server->addr.sin_addr.s_addr);
1190     }
1191
1192     lock_ReleaseRead(&cm_serverLock);
1193     return 0;
1194 }
1195
1196 /* debug interface */
1197 int
1198 SRXAFSCB_GetCellByNum(struct rx_call *callp, afs_int32 a_cellnum,
1199                       char **a_name, serverList *a_hosts)
1200 {
1201     struct rx_connection *connp;
1202     struct rx_peer *peerp;
1203     unsigned long host = 0;
1204     unsigned short port = 0;
1205     int rc;
1206
1207     if (cm_shutdown)
1208         return 1;
1209
1210     if ((connp = rx_ConnectionOf(callp)) && (peerp = rx_PeerOf(connp))) {
1211         host = rx_HostOf(peerp);
1212         port = rx_PortOf(peerp);
1213     }
1214
1215     osi_Log3(afsd_logp, "SRXAFSCB_GetCellByNum(%d) from host 0x%x port %d",
1216              a_cellnum, ntohl(host), ntohs(port));
1217
1218     a_hosts->serverList_val = 0;
1219     a_hosts->serverList_len = 0;
1220
1221
1222     rc = GetCellCommon(a_cellnum, a_name, a_hosts);
1223
1224     return rc;
1225 }
1226
1227 /* debug interface */
1228 int
1229 SRXAFSCB_TellMeAboutYourself( struct rx_call *callp,
1230                               struct interfaceAddr *addr,
1231                               Capabilities * capabilities)
1232 {
1233     int i;
1234     afs_uint32 *dataBuffP;
1235     afs_int32 dataBytes;
1236     long code;
1237     struct rx_connection *connp;
1238     struct rx_peer *peerp;
1239     unsigned long host = 0;
1240     unsigned short port = 0;
1241
1242     if (cm_shutdown)
1243         return 1;
1244
1245     if ((connp = rx_ConnectionOf(callp)) && (peerp = rx_PeerOf(connp))) {
1246         host = rx_HostOf(peerp);
1247         port = rx_PortOf(peerp);
1248     }
1249
1250     osi_Log2(afsd_logp, "SRXAFSCB_TellMeAboutYourself from host 0x%x port %d",
1251               ntohl(host),
1252               ntohs(port));
1253
1254     lock_ObtainRead(&cm_syscfgLock);
1255     if (cm_LanAdapterChangeDetected) {
1256         lock_ConvertRToW(&cm_syscfgLock);
1257         if (cm_LanAdapterChangeDetected) {
1258             /* get network related info */
1259             cm_noIPAddr = CM_MAXINTERFACE_ADDR;
1260             code = syscfg_GetIFInfo(&cm_noIPAddr,
1261                                      cm_IPAddr, cm_SubnetMask,
1262                                      cm_NetMtu, cm_NetFlags);
1263             cm_LanAdapterChangeDetected = 0;
1264         }
1265         lock_ConvertWToR(&cm_syscfgLock);
1266     }
1267
1268     /* return all network interface addresses */
1269     addr->numberOfInterfaces = cm_noIPAddr;
1270     addr->uuid = cm_data.Uuid;
1271     for ( i=0; i < cm_noIPAddr; i++ ) {
1272         addr->addr_in[i] = cm_IPAddr[i];
1273         addr->subnetmask[i] = cm_SubnetMask[i];
1274         addr->mtu[i] = (rx_mtu == -1 || (rx_mtu != -1 && cm_NetMtu[i] < rx_mtu)) ?
1275             cm_NetMtu[i] : rx_mtu;
1276     }
1277     lock_ReleaseRead(&cm_syscfgLock);
1278
1279     dataBytes = 1 * sizeof(afs_uint32);
1280     dataBuffP = (afs_uint32 *) xdr_alloc(dataBytes);
1281     dataBuffP[0] = CLIENT_CAPABILITY_ERRORTRANS;
1282     capabilities->Capabilities_len = dataBytes / sizeof(afs_uint32);
1283     capabilities->Capabilities_val = dataBuffP;
1284
1285     return 0;
1286 }
1287
1288 /*------------------------------------------------------------------------
1289  * EXPORTED SRXAFSCB_GetServerPrefs
1290  *
1291  * Description:
1292  *      Routine to list server preferences used by this client.
1293  *
1294  * Arguments:
1295  *      a_call  : Ptr to Rx call on which this request came in.
1296  *      a_index : Input server index
1297  *      a_srvr_addr  : Output server address (0xffffffff on last server)
1298  *      a_srvr_rank  : Output server rank
1299  *
1300  * Returns:
1301  *      0 on success
1302  *
1303  * Environment:
1304  *      Nothing interesting.
1305  *
1306  * Side Effects:
1307  *      As advertised.
1308  *------------------------------------------------------------------------*/
1309
1310 int SRXAFSCB_GetServerPrefs(
1311     struct rx_call *callp,
1312     afs_int32 a_index,
1313     afs_int32 *a_srvr_addr,
1314     afs_int32 *a_srvr_rank)
1315 {
1316     struct rx_connection *connp;
1317     struct rx_peer *peerp;
1318     unsigned long host = 0;
1319     unsigned short port = 0;
1320
1321     if (cm_shutdown)
1322         return 1;
1323
1324     if ((connp = rx_ConnectionOf(callp)) && (peerp = rx_PeerOf(connp))) {
1325         host = rx_HostOf(peerp);
1326         port = rx_PortOf(peerp);
1327     }
1328
1329     osi_Log2(afsd_logp, "SRXAFSCB_GetServerPrefs from host 0x%x port %d - not implemented",
1330               ntohl(host),
1331               ntohs(port));
1332
1333     *a_srvr_addr = 0xffffffff;
1334     *a_srvr_rank = 0xffffffff;
1335
1336     return 0;
1337 }
1338
1339 /*------------------------------------------------------------------------
1340  * EXPORTED SRXAFSCB_GetCellServDB
1341  *
1342  * Description:
1343  *      Routine to list cells configured for this client
1344  *
1345  * Arguments:
1346  *      a_call  : Ptr to Rx call on which this request came in.
1347  *      a_index : Input cell index
1348  *      a_name  : Output cell name ("" on last cell)
1349  *      a_hosts : Output cell database servers
1350  *
1351  * Returns:
1352  *      0 on success
1353  *
1354  * Environment:
1355  *      Nothing interesting.
1356  *
1357  * Side Effects:
1358  *      As advertised.
1359  *------------------------------------------------------------------------*/
1360
1361 int SRXAFSCB_GetCellServDB(struct rx_call *callp, afs_int32 index, char **a_name,
1362                            serverList *a_hosts)
1363 {
1364     struct rx_connection *connp;
1365     struct rx_peer *peerp;
1366     unsigned long host = 0;
1367     unsigned short port = 0;
1368     int rc;
1369
1370     if (cm_shutdown)
1371         return 1;
1372
1373     if ((connp = rx_ConnectionOf(callp)) && (peerp = rx_PeerOf(connp))) {
1374         host = rx_HostOf(peerp);
1375         port = rx_PortOf(peerp);
1376     }
1377
1378     osi_Log2(afsd_logp, "SRXAFSCB_GetCellServDB from host 0x%x port %d - not implemented",
1379              ntohl(host), ntohs(port));
1380
1381 #ifdef AFS_FREELANCE_CLIENT
1382     if (cm_freelanceEnabled && index == 0) {
1383         rc = GetCellCommon(AFS_FAKE_ROOT_CELL_ID, a_name, a_hosts);
1384     } else
1385 #endif
1386     {
1387         rc = GetCellCommon(index+1, a_name, a_hosts);
1388     }
1389     return 0;
1390 }
1391
1392 /*------------------------------------------------------------------------
1393  * EXPORTED SRXAFSCB_GetLocalCell
1394  *
1395  * Description:
1396  *      Routine to return name of client's local cell
1397  *
1398  * Arguments:
1399  *      a_call  : Ptr to Rx call on which this request came in.
1400  *      a_name  : Output cell name
1401  *
1402  * Returns:
1403  *      0 on success
1404  *
1405  * Environment:
1406  *      Nothing interesting.
1407  *
1408  * Side Effects:
1409  *      As advertised.
1410  *------------------------------------------------------------------------*/
1411
1412 int SRXAFSCB_GetLocalCell(struct rx_call *callp, char **a_name)
1413 {
1414     char *t_name;
1415     struct rx_connection *connp;
1416     struct rx_peer *peerp;
1417     unsigned long host = 0;
1418     unsigned short port = 0;
1419     size_t len;
1420
1421     if (cm_shutdown)
1422         return 1;
1423
1424     if ((connp = rx_ConnectionOf(callp)) && (peerp = rx_PeerOf(connp))) {
1425         host = rx_HostOf(peerp);
1426         port = rx_PortOf(peerp);
1427     }
1428
1429     osi_Log2(afsd_logp, "SRXAFSCB_GetLocalCell from host 0x%x port %d",
1430              ntohl(host), ntohs(port));
1431
1432     if (cm_data.rootCellp) {
1433         len = strlen(cm_data.rootCellp->name) + 1;
1434         t_name = (char *)xdr_alloc(len);
1435         if (t_name)
1436             memcpy(t_name, cm_data.rootCellp->name, len);
1437     } else {
1438         t_name = (char *)xdr_alloc(1);
1439         t_name[0] = '\0';
1440     }
1441     *a_name = t_name;
1442
1443     return 0;
1444 }
1445
1446
1447 /*
1448  * afs_MarshallCacheConfig - marshall client cache configuration
1449  *
1450  * PARAMETERS
1451  *
1452  * IN callerVersion - the rpc stat version of the caller.
1453  *
1454  * IN config - client cache configuration.
1455  *
1456  * OUT ptr - buffer where configuration is marshalled.
1457  *
1458  * RETURN CODES
1459  *
1460  * Returns void.
1461  */
1462 static void afs_MarshallCacheConfig(
1463     afs_uint32 callerVersion,
1464     cm_initparams_v1 *config,
1465     afs_uint32 *ptr)
1466 {
1467     /*
1468      * We currently only support version 1.
1469      */
1470     *(ptr++) = config->nChunkFiles;
1471     *(ptr++) = config->nStatCaches;
1472     *(ptr++) = config->nDataCaches;
1473     *(ptr++) = config->nVolumeCaches;
1474     *(ptr++) = config->firstChunkSize;
1475     *(ptr++) = config->otherChunkSize;
1476     *(ptr++) = config->cacheSize;
1477     *(ptr++) = config->setTime;
1478     *(ptr++) = config->memCache;
1479
1480 }
1481
1482
1483 /*------------------------------------------------------------------------
1484  * EXPORTED SRXAFSCB_GetCacheConfig
1485  *
1486  * Description:
1487  *      Routine to return parameters used to initialize client cache.
1488  *      Client may request any format version. Server may not return
1489  *      format version greater than version requested by client.
1490  *
1491  * Arguments:
1492  *      a_call:        Ptr to Rx call on which this request came in.
1493  *      callerVersion: Data format version desired by the client.
1494  *      serverVersion: Data format version of output data.
1495  *      configCount:   Number bytes allocated for output data.
1496  *      config:        Client cache configuration.
1497  *
1498  * Returns:
1499  *      0 on success
1500  *
1501  * Environment:
1502  *      Nothing interesting.
1503  *
1504  * Side Effects:
1505  *      As advertised.
1506  *------------------------------------------------------------------------*/
1507
1508 int SRXAFSCB_GetCacheConfig(struct rx_call *callp,
1509                             afs_uint32 callerVersion,
1510                             afs_uint32 *serverVersion,
1511                             afs_uint32 *configCount,
1512                             cacheConfig *config)
1513 {
1514     afs_uint32 *t_config;
1515     size_t allocsize;
1516     extern cm_initparams_v1 cm_initParams;
1517     struct rx_connection *connp;
1518     struct rx_peer *peerp;
1519     unsigned long host = 0;
1520     unsigned short port = 0;
1521
1522     if (cm_shutdown)
1523         return 1;
1524
1525     if ((connp = rx_ConnectionOf(callp)) && (peerp = rx_PeerOf(connp))) {
1526         host = rx_HostOf(peerp);
1527         port = rx_PortOf(peerp);
1528     }
1529
1530     osi_Log2(afsd_logp, "SRXAFSCB_GetCacheConfig from host 0x%x port %d - version 1 only",
1531              ntohl(host), ntohs(port));
1532
1533     /*
1534      * Currently only support version 1
1535      */
1536     allocsize = sizeof(cm_initparams_v1);
1537     t_config = (afs_uint32 *)xdr_alloc(allocsize);
1538
1539     afs_MarshallCacheConfig(callerVersion, &cm_initParams, t_config);
1540
1541     *serverVersion = AFS_CLIENT_RETRIEVAL_FIRST_EDITION;
1542 #ifdef DEBUG
1543 #ifndef SIZE_MAX
1544 #define SIZE_MAX UINT_MAX
1545 #endif
1546     osi_assertx(allocsize < SIZE_MAX, "allocsize >= SIZE_MAX");
1547 #endif
1548     *configCount = (afs_uint32)allocsize;
1549     config->cacheConfig_val = t_config;
1550     config->cacheConfig_len = (*configCount)/sizeof(afs_uint32);
1551
1552     return 0;
1553 }
1554
1555 /* called by afsd without any locks to initialize this module */
1556 void cm_InitCallback(void)
1557 {
1558     lock_InitializeRWLock(&cm_callbackLock, "cm_callbackLock", LOCK_HIERARCHY_CALLBACK_GLOBAL);
1559     cm_activeCallbackGrantingCalls = 0;
1560 }
1561
1562 /* called with locked scp; tells us whether we've got a callback.
1563  * Expirations are checked by a background daemon so as to make
1564  * this function as inexpensive as possible
1565  */
1566 int cm_HaveCallback(cm_scache_t *scp)
1567 {
1568 #ifdef AFS_FREELANCE_CLIENT
1569     if (cm_freelanceEnabled &&
1570         scp->fid.cell==AFS_FAKE_ROOT_CELL_ID &&
1571         scp->fid.volume==AFS_FAKE_ROOT_VOL_ID) {
1572         if (cm_getLocalMountPointChange()) {
1573             cm_clearLocalMountPointChange();
1574             lock_ReleaseWrite(&scp->rw);
1575             cm_reInitLocalMountPoints();
1576             lock_ObtainWrite(&scp->rw);
1577         }
1578         return (cm_data.fakeDirVersion == scp->dataVersion);
1579     }
1580 #endif
1581     if (scp->cbServerp != NULL)
1582         return 1;
1583
1584     if (scp->flags & CM_SCACHEFLAG_PURERO) {
1585         cm_volume_t *volp = cm_GetVolumeByFID(&scp->fid);
1586         if (volp) {
1587             int haveCB = 0;
1588             if (cm_OfflineROIsValid) {
1589                 switch (cm_GetVolumeStatus(volp, scp->fid.volume)) {
1590                 case vl_offline:
1591                 case vl_alldown:
1592                 case vl_unknown:
1593                     haveCB = 1;
1594                     break;
1595                 }
1596             }
1597             if (cm_readonlyVolumeVersioning &&
1598                 !haveCB &&
1599                 scp->volumeCreationDate != 0 &&
1600                 volp->creationDateRO == scp->volumeCreationDate &&
1601                 volp->cbServerpRO != NULL) {
1602                 haveCB = 1;
1603             }
1604             cm_PutVolume(volp);
1605             return haveCB;
1606         }
1607     }
1608     return 0;
1609 }
1610
1611 /* need to detect a broken callback that races with our obtaining a callback.
1612  * Need to be able to do this even if we don't know the file ID of the file
1613  * we're breaking the callback on at the time we start the acquisition of the
1614  * callback (as in the case where we are creating a file).
1615  *
1616  * So, we start by writing down the count of the # of callbacks we've received
1617  * so far, and bumping a global counter of the # of callback granting calls
1618  * outstanding (all done under cm_callbackLock).
1619  *
1620  * When we're back from the call, we look at all of the callback revokes with
1621  * counter numbers greater than the one we recorded in our caller's structure,
1622  * and replay those that are higher than when we started the call.
1623  *
1624  * We free all the structures in the queue when the count of the # of outstanding
1625  * callback-granting calls drops to zero.
1626  *
1627  * We call this function with the scp locked, too, but in its current implementation,
1628  * this knowledge is not used.
1629  */
1630 void cm_StartCallbackGrantingCall(cm_scache_t *scp, cm_callbackRequest_t *cbrp)
1631 {
1632     lock_ObtainWrite(&cm_callbackLock);
1633     cbrp->callbackCount = cm_callbackCount;
1634     cm_activeCallbackGrantingCalls++;
1635     cbrp->startTime = time(NULL);
1636     cbrp->serverp = NULL;
1637     lock_ReleaseWrite(&cm_callbackLock);
1638 }
1639
1640 /* Called at the end of a callback-granting call, to remove the callback
1641  * info from the scache entry, if necessary.
1642  *
1643  * Called with scp write locked, so we can discard the callbacks easily with
1644  * this locking hierarchy.
1645  *
1646  * Performs cleanup of the stack allocated cm_callbackRequest_t object.
1647  *
1648  * Returns 0 on success and non-zero if the callback lost a race.
1649  */
1650 int
1651 cm_EndCallbackGrantingCall(cm_scache_t *scp, cm_callbackRequest_t *cbrp,
1652                            AFSCallBack *cbp, AFSVolSync *volSyncp, long flags)
1653 {
1654     cm_racingRevokes_t *revp;           /* where we are */
1655     cm_racingRevokes_t *nrevp;          /* where we'll be next */
1656     int freeRacingRevokes;
1657     int freeServer;
1658     cm_server_t * serverp = NULL;
1659     int lostRace = 0;
1660
1661     lock_ObtainWrite(&cm_callbackLock);
1662     if (flags & CM_CALLBACK_MAINTAINCOUNT) {
1663         osi_assertx(cm_activeCallbackGrantingCalls > 0,
1664                     "CM_CALLBACK_MAINTAINCOUNT && cm_activeCallbackGrantingCalls == 0");
1665         freeServer = 0;
1666     }
1667     else {
1668         osi_assertx(cm_activeCallbackGrantingCalls-- > 0,
1669                     "!CM_CALLBACK_MAINTAINCOUNT && cm_activeCallbackGrantingCalls == 0");
1670         freeServer = 1;
1671     }
1672     if (cm_activeCallbackGrantingCalls == 0)
1673         freeRacingRevokes = 1;
1674     else
1675         freeRacingRevokes = 0;
1676
1677     /*
1678      * a callback was revoked during our granting call, so
1679      * run down the list of revoked fids, looking for ours.
1680      * If activeCallbackGrantingCalls is zero, free the elements, too.
1681      *
1682      * May need to go through entire list just to do the freeing.
1683      */
1684     for (revp = cm_racingRevokesp; revp; revp = nrevp) {
1685         nrevp = (cm_racingRevokes_t *) osi_QNext(&revp->q);
1686         /* if this callback came in later than when we started the
1687          * callback-granting call, and if this fid is the right fid,
1688          * then clear the callback.
1689          */
1690         if (scp && cbrp && cbrp->callbackCount != cm_callbackCount
1691              && revp->callbackCount > cbrp->callbackCount
1692              && (( scp->fid.volume == revp->fid.volume &&
1693                    scp->fid.vnode == revp->fid.vnode &&
1694                    scp->fid.unique == revp->fid.unique)
1695                   ||
1696                   ((revp->flags & CM_RACINGFLAG_CANCELVOL) &&
1697                     scp->fid.volume == revp->fid.volume)
1698                   ||
1699                   ((revp->flags & CM_RACINGFLAG_CANCELALL) &&
1700                    (revp->fid.cell == 0 || scp->fid.cell == revp->fid.cell)))) {
1701             /* this one matches */
1702             osi_Log4(afsd_logp,
1703                       "Racing revoke scp 0x%p old cbc %d rev cbc %d cur cbc %d",
1704                       scp,
1705                       cbrp->callbackCount, revp->callbackCount,
1706                       cm_callbackCount);
1707             lostRace = 1;
1708             if ((scp->flags & CM_SCACHEFLAG_PURERO) &&
1709                  (revp->flags & CM_RACINGFLAG_ALL))
1710                 cm_callbackDiscardROVolumeByFID(&scp->fid);
1711         }
1712         if (freeRacingRevokes)
1713             free(revp);
1714     }
1715
1716     /* if we freed the list, zap the pointer to it */
1717     if (freeRacingRevokes)
1718         cm_racingRevokesp = NULL;
1719     lock_ReleaseWrite(&cm_callbackLock);
1720
1721     /* record the callback if we didn't lose it */
1722     if (!lostRace && scp) {
1723         if (cbrp) {
1724             if (!cm_ServerEqual(scp->cbServerp, cbrp->serverp)) {
1725                 serverp = scp->cbServerp;
1726                 scp->cbServerp = cbrp->serverp;
1727                 if (freeServer) {
1728                     cbrp->serverp = NULL;
1729                 } else {
1730                     cm_GetServer(scp->cbServerp);
1731                 }
1732             } else if (freeServer) {
1733                 serverp = cbrp->serverp;
1734                 cbrp->serverp = NULL;
1735             }
1736             scp->cbExpires = cbrp->startTime + cbp->ExpirationTime;
1737             scp->cbIssued = time(NULL);
1738         }
1739
1740         if (scp->flags & CM_SCACHEFLAG_PURERO) {
1741             cm_volume_t * volp = cm_GetVolumeByFID(&scp->fid);
1742             if (volp) {
1743                 if (volSyncp) {
1744                     lock_ObtainWrite(&cm_scacheLock);
1745                     volp->cbExpiresRO = scp->cbExpires;
1746                     volp->cbIssuedRO = scp->cbIssued;
1747                     if (cm_readonlyVolumeVersioning || !(flags & CM_CALLBACK_BULKSTAT))
1748                         volp->creationDateRO = volSyncp->spare1;
1749                     else
1750                         volp->creationDateRO = 0;
1751                     if (volp->cbServerpRO != scp->cbServerp) {
1752                         if (volp->cbServerpRO)
1753                             cm_PutServer(volp->cbServerpRO);
1754                         cm_GetServer(scp->cbServerp);
1755                         volp->cbServerpRO = scp->cbServerp;
1756                     }
1757                     lock_ReleaseWrite(&cm_scacheLock);
1758                 }
1759                 cm_PutVolume(volp);
1760             }
1761         }
1762     }
1763     else
1764     {
1765         /*
1766          * No need to discard the cm_scache object or notify the
1767          * afs redirector or smb client about a change if we did lose
1768          * the race.  That was done when the callback was processed in
1769          * cm_RevokeCallback().
1770          */
1771         if (cbrp && freeServer) {
1772             serverp = cbrp->serverp;
1773             cbrp->serverp = NULL;
1774         }
1775     }
1776
1777     if ( serverp ) {
1778         lock_ObtainWrite(&cm_serverLock);
1779         cm_FreeServer(serverp);
1780         lock_ReleaseWrite(&cm_serverLock);
1781     }
1782
1783     return lostRace;
1784 }
1785
1786 /* if flags is 1, we want to force the code to make one call, anyway.
1787  * called with locked scp; returns with same.
1788  */
1789 long cm_GetCallback(cm_scache_t *scp, struct cm_user *userp,
1790                     struct cm_req *reqp, long flags)
1791 {
1792     long code = 0;
1793     cm_conn_t *connp = NULL;
1794     AFSFetchStatus afsStatus;
1795     AFSVolSync volSync;
1796     AFSCallBack callback;
1797     AFSFid tfid;
1798     cm_callbackRequest_t cbr;
1799     int mustCall;
1800     cm_fid_t sfid;
1801     struct rx_connection * rxconnp = NULL;
1802     int syncop_done = 0;
1803
1804     memset(&volSync, 0, sizeof(volSync));
1805
1806     osi_Log4(afsd_logp, "GetCallback scp 0x%p cell %d vol %d flags %lX",
1807              scp, scp->fid.cell, scp->fid.volume, flags);
1808
1809 #ifdef AFS_FREELANCE_CLIENT
1810     // The case where a callback is needed on /afs is handled
1811     // specially. We need to fetch the status by calling
1812     // cm_MergeStatus
1813     if (cm_freelanceEnabled &&
1814         (scp->fid.cell==AFS_FAKE_ROOT_CELL_ID &&
1815          scp->fid.volume==AFS_FAKE_ROOT_VOL_ID)) {
1816
1817         code = cm_SyncOp(scp, NULL, userp, reqp, 0,
1818                           CM_SCACHESYNC_FETCHSTATUS | CM_SCACHESYNC_GETCALLBACK);
1819         if (code)
1820             goto done;
1821         syncop_done = 1;
1822
1823         if (scp->dataVersion != cm_data.fakeDirVersion) {
1824             memset(&afsStatus, 0, sizeof(afsStatus));
1825             memset(&volSync, 0, sizeof(volSync));
1826             InterlockedIncrement(&scp->activeRPCs);
1827
1828             // Fetch the status info
1829             code = cm_MergeStatus(NULL, scp, &afsStatus, &volSync, userp, reqp, 0);
1830         }
1831         goto done;
1832     }
1833 #endif /* AFS_FREELANCE_CLIENT */
1834
1835     mustCall = (flags & 1);
1836     cm_AFSFidFromFid(&tfid, &scp->fid);
1837     while (1) {
1838         if (!mustCall && cm_HaveCallback(scp))
1839             break;
1840
1841         /* turn off mustCall, since it has now forced us past the check above */
1842         mustCall = 0;
1843
1844         /* otherwise, we have to make an RPC to get the status */
1845         if (!syncop_done) {
1846             code = cm_SyncOp(scp, NULL, userp, reqp, 0,
1847                              CM_SCACHESYNC_FETCHSTATUS | CM_SCACHESYNC_GETCALLBACK);
1848             if (code)
1849                 break;
1850             syncop_done = 1;
1851         }
1852         cm_StartCallbackGrantingCall(scp, &cbr);
1853         sfid = scp->fid;
1854         lock_ReleaseWrite(&scp->rw);
1855
1856         /* now make the RPC */
1857         InterlockedIncrement(&scp->activeRPCs);
1858         osi_Log4(afsd_logp, "CALL FetchStatus scp 0x%p vol %u vn %u uniq %u",
1859                  scp, sfid.volume, sfid.vnode, sfid.unique);
1860         do {
1861             code = cm_ConnFromFID(&sfid, userp, reqp, &connp);
1862             if (code)
1863                 continue;
1864
1865             rxconnp = cm_GetRxConn(connp);
1866             code = RXAFS_FetchStatus(rxconnp, &tfid,
1867                                      &afsStatus, &callback, &volSync);
1868             rx_PutConnection(rxconnp);
1869
1870         } while (cm_Analyze(connp, userp, reqp, &sfid, NULL, 0, &afsStatus, &volSync, NULL,
1871                             &cbr, code));
1872         code = cm_MapRPCError(code, reqp);
1873         if (code)
1874             osi_Log4(afsd_logp, "CALL FetchStatus FAILURE code 0x%x scp 0x%p vol %u vn %u",
1875                      code, scp, scp->fid.volume, scp->fid.vnode);
1876         else
1877             osi_Log4(afsd_logp, "CALL FetchStatus SUCCESS scp 0x%p vol %u vn %u uniq %u",
1878                      scp, scp->fid.volume, scp->fid.vnode, scp->fid.unique);
1879
1880         lock_ObtainWrite(&scp->rw);
1881         if (code == 0) {
1882             int lostRace = cm_EndCallbackGrantingCall(scp, &cbr, &callback, &volSync, 0);
1883             if (!lostRace)
1884                 code = cm_MergeStatus(NULL, scp, &afsStatus, &volSync, userp, reqp, 0);
1885         } else {
1886             cm_EndCallbackGrantingCall(NULL, &cbr, NULL, NULL, 0);
1887             InterlockedDecrement(&scp->activeRPCs);
1888         }
1889
1890         /* if we got an error, return to caller */
1891         if (code)
1892             break;
1893     }
1894
1895   done:
1896     if (syncop_done)
1897         cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_FETCHSTATUS | CM_SCACHESYNC_GETCALLBACK);
1898
1899     if (code) {
1900         osi_Log2(afsd_logp, "GetCallback Failed code 0x%x scp 0x%p -->",code, scp);
1901         osi_Log4(afsd_logp, "            cell %u vol %u vn %u uniq %u",
1902                  scp->fid.cell, scp->fid.volume, scp->fid.vnode, scp->fid.unique);
1903     } else {
1904         osi_Log3(afsd_logp, "GetCallback Complete scp 0x%p cell %d vol %d",
1905                   scp, scp->fid.cell, scp->fid.volume);
1906     }
1907
1908     return code;
1909 }
1910
1911
1912 /*
1913  * cm_CBServersDownTime() returns 1 if the downTime parameter is valid.
1914  *
1915  * Servers with multiple interfaces have multiple cm_server_t objects
1916  * which share the same UUID.  If one interface is down but others are up,
1917  * the server should not be considered down.  The returned downTime should
1918  * be the largest non-zero value if down or zero if up.  If the cbServerp
1919  * is down, it is updated to refer to an interface that is up (if one exists).
1920  *
1921  * called with cm_scacheLock held
1922  */
1923 static long
1924 cm_CBServersDownTime(cm_scache_t *scp, cm_volume_t *volp, time_t * pdownTime)
1925 {
1926     cm_vol_state_t *statep;
1927     cm_serverRef_t *tsrp;
1928     int alldown = 1;
1929     time_t downTime = 0;
1930     cm_server_t * upserver = NULL;
1931     cm_server_t * downserver;
1932
1933     *pdownTime = 0;
1934
1935     if (scp->cbServerp == NULL)
1936         return 1;
1937
1938     if (!(scp->cbServerp->flags & CM_SERVERFLAG_DOWN))
1939         return 1;
1940
1941     statep = cm_VolumeStateByID(volp, scp->fid.volume);
1942     if (statep) {
1943         for (tsrp = statep->serversp; tsrp; tsrp=tsrp->next) {
1944             if (tsrp->status == srv_deleted)
1945                 continue;
1946
1947             if (!cm_ServerEqual(tsrp->server, scp->cbServerp))
1948                 continue;
1949
1950             if (!(tsrp->server->flags & CM_SERVERFLAG_DOWN)) {
1951                 alldown = 0;
1952                 if (!upserver) {
1953                     upserver = tsrp->server;
1954                     cm_GetServer(upserver);
1955                 }
1956             }
1957
1958             if (tsrp->server->downTime > downTime)
1959                 downTime = tsrp->server->downTime;
1960         }
1961     } else {
1962         downTime = scp->cbServerp->downTime;
1963     }
1964
1965     /* if the cbServerp does not match the current volume server list
1966      * we report the callback server as up so the callback can be
1967      * expired.
1968      */
1969
1970     if (alldown) {
1971         *pdownTime = downTime;
1972     } else {
1973         lock_ObtainWrite(&scp->rw);
1974         downserver = scp->cbServerp;
1975         scp->cbServerp = upserver;
1976         lock_ReleaseWrite(&scp->rw);
1977         cm_PutServer(downserver);
1978     }
1979     return 1;
1980 }
1981
1982 /* called periodically by cm_daemon to shut down use of expired callbacks */
1983 void cm_CheckCBExpiration(void)
1984 {
1985     afs_uint32 i;
1986     cm_scache_t *scp;
1987     cm_volume_t *volp;
1988     enum volstatus volstate;
1989     time_t now, downTime;
1990
1991     osi_Log0(afsd_logp, "CheckCBExpiration");
1992
1993     now = time(NULL);
1994     lock_ObtainWrite(&cm_scacheLock);
1995     for (i=0; i<cm_data.scacheHashTableSize; i++) {
1996         for (scp = cm_data.scacheHashTablep[i]; scp; scp=scp->nextp) {
1997             volp = NULL;
1998             cm_HoldSCacheNoLock(scp);
1999             lock_ReleaseWrite(&cm_scacheLock);
2000
2001             /*
2002              * If this is not a PURERO object and there is no callback
2003              * or it hasn't expired, there is nothing to do
2004              */
2005             if (!(scp->flags & CM_SCACHEFLAG_PURERO) &&
2006                 (scp->cbServerp == NULL || scp->cbExpires == 0 || now < scp->cbExpires))
2007                 goto scp_complete;
2008
2009             /*
2010              * Determine the volume state and update the callback info
2011              * to the latest if it is a PURERO object.
2012              */
2013             volp = cm_GetVolumeByFID(&scp->fid);
2014             volstate = vl_unknown;
2015             downTime = 0;
2016             if (volp) {
2017                 if ((scp->flags & CM_SCACHEFLAG_PURERO) &&
2018                     volp->cbExpiresRO > scp->cbExpires && scp->cbExpires > 0)
2019                 {
2020                     lock_ObtainWrite(&scp->rw);
2021                     scp->cbExpires = volp->cbExpiresRO;
2022                     scp->cbIssued = volp->cbIssuedRO;
2023                     if (volp->cbServerpRO != scp->cbServerp) {
2024                         if (scp->cbServerp)
2025                             cm_PutServer(scp->cbServerp);
2026                         cm_GetServer(volp->cbServerpRO);
2027                         scp->cbServerp = volp->cbServerpRO;
2028                     }
2029                     lock_ReleaseWrite(&scp->rw);
2030                 }
2031                 volstate = cm_GetVolumeStatus(volp, scp->fid.volume);
2032             }
2033
2034             /* If there is no callback or it hasn't expired, there is nothing to do */
2035             if (scp->cbServerp == NULL || scp->cbExpires == 0 || now < scp->cbExpires)
2036                 goto scp_complete;
2037
2038             /* If the volume is known not to be online, do not expire the callback */
2039             if (volstate != vl_online)
2040                 goto scp_complete;
2041
2042             /*
2043              * If all the servers are down and the callback expired after the
2044              * issuing server went down, do not expire the callback
2045              */
2046             if (cm_CBServersDownTime(scp, volp, &downTime) && downTime && downTime < scp->cbExpires)
2047                 goto scp_complete;
2048
2049             /* The callback has expired, discard the status info */
2050             osi_Log4(afsd_logp, "Callback Expiration Discarding SCache scp 0x%p vol %u vn %u uniq %u",
2051                      scp, scp->fid.volume, scp->fid.vnode, scp->fid.unique);
2052             lock_ObtainWrite(&scp->rw);
2053             cm_DiscardSCache(scp);
2054             lock_ReleaseWrite(&scp->rw);
2055
2056             if (RDR_Initialized)
2057                 RDR_InvalidateObject(scp->fid.cell, scp->fid.volume, scp->fid.vnode, scp->fid.unique,
2058                                      scp->fid.hash, scp->fileType, AFS_INVALIDATE_EXPIRED);
2059
2060             cm_CallbackNotifyChange(scp);
2061
2062             if (scp->fileType == CM_SCACHETYPE_DIRECTORY &&
2063                 !(volp && (volp->flags & CM_VOLUMEFLAG_DFS_VOLUME)) &&
2064                 !cm_accessPerFileCheck)
2065                 cm_EAccesClearParentEntries(&scp->fid);
2066
2067           scp_complete:
2068             if (volp)
2069                 cm_PutVolume(volp);
2070
2071             lock_ObtainWrite(&cm_scacheLock);
2072             cm_ReleaseSCacheNoLock(scp);
2073         }
2074     }
2075     lock_ReleaseWrite(&cm_scacheLock);
2076
2077     osi_Log0(afsd_logp, "CheckCBExpiration Complete");
2078 }
2079
2080
2081 void
2082 cm_GiveUpAllCallbacks(cm_server_t *tsp, afs_int32 markDown)
2083 {
2084     long code;
2085     cm_conn_t *connp;
2086     struct rx_connection * rxconnp;
2087
2088     if ((tsp->type == CM_SERVER_FILE) && !(tsp->flags & CM_SERVERFLAG_DOWN))
2089     {
2090         code = cm_ConnByServer(tsp, cm_rootUserp, FALSE, &connp);
2091         if (code == 0) {
2092             rxconnp = cm_GetRxConn(connp);
2093             rx_SetConnDeadTime(rxconnp, 10);
2094             code = RXAFS_GiveUpAllCallBacks(rxconnp);
2095             rx_SetConnDeadTime(rxconnp, ConnDeadtimeout);
2096             rx_PutConnection(rxconnp);
2097         }
2098
2099         if (markDown) {
2100             cm_server_vols_t * tsrvp;
2101             cm_volume_t * volp;
2102             int i;
2103
2104             cm_ForceNewConnections(tsp);
2105
2106             lock_ObtainMutex(&tsp->mx);
2107             if (!(tsp->flags & CM_SERVERFLAG_DOWN)) {
2108                 _InterlockedOr(&tsp->flags, CM_SERVERFLAG_DOWN);
2109                 tsp->downTime = time(NULL);
2110             }
2111             /* Now update the volume status */
2112             for (tsrvp = tsp->vols; tsrvp; tsrvp = tsrvp->nextp) {
2113                 for (i=0; i<NUM_SERVER_VOLS; i++) {
2114                     if (tsrvp->ids[i] != 0) {
2115                         cm_req_t req;
2116
2117                         cm_InitReq(&req);
2118                         lock_ReleaseMutex(&tsp->mx);
2119                         code = cm_FindVolumeByID(tsp->cellp, tsrvp->ids[i], cm_rootUserp,
2120                                                  &req, CM_GETVOL_FLAG_NO_LRU_UPDATE | CM_GETVOL_FLAG_NO_RESET, &volp);
2121                         lock_ObtainMutex(&tsp->mx);
2122                         if (code == 0) {
2123                             cm_UpdateVolumeStatus(volp, tsrvp->ids[i]);
2124                             cm_PutVolume(volp);
2125                         }
2126                     }
2127                 }
2128             }
2129             lock_ReleaseMutex(&tsp->mx);
2130         }
2131     }
2132 }
2133
2134 void
2135 cm_GiveUpAllCallbacksAllServers(afs_int32 markDown)
2136 {
2137     cm_server_t *tsp;
2138
2139     if (!cm_giveUpAllCBs)
2140         return;
2141
2142     lock_ObtainRead(&cm_serverLock);
2143     for (tsp = cm_allServersp; tsp; tsp = tsp->allNextp) {
2144         cm_GetServerNoLock(tsp);
2145         lock_ReleaseRead(&cm_serverLock);
2146         cm_GiveUpAllCallbacks(tsp, markDown);
2147         lock_ObtainRead(&cm_serverLock);
2148         cm_PutServerNoLock(tsp);
2149     }
2150     lock_ReleaseRead(&cm_serverLock);
2151 }
2152
2153 void
2154 cm_GiveUpAllCallbacksAllServersMulti(afs_int32 markDown)
2155 {
2156     long code;
2157     cm_conn_t **conns = NULL;
2158     struct rx_connection **rxconns = NULL;
2159     afs_int32 i, nconns = 0, maxconns;
2160     cm_server_t ** serversp, *tsp;
2161     afs_int32 *results;
2162     time_t start, *deltas;
2163
2164     maxconns = cm_numFileServers;
2165     if (maxconns == 0)
2166         return;
2167
2168     conns = (cm_conn_t **)malloc(maxconns * sizeof(cm_conn_t *));
2169     rxconns = (struct rx_connection **)malloc(maxconns * sizeof(struct rx_connection *));
2170     deltas = (time_t *)malloc(maxconns * sizeof (time_t));
2171     results = (afs_int32 *)malloc(maxconns * sizeof (afs_int32));
2172     serversp = (cm_server_t **)malloc(maxconns * sizeof(cm_server_t *));
2173
2174     lock_ObtainRead(&cm_serverLock);
2175     for (nconns=0, tsp = cm_allServersp; tsp && nconns < maxconns; tsp = tsp->allNextp) {
2176         if (tsp->type != CM_SERVER_FILE ||
2177             (tsp->flags & CM_SERVERFLAG_DOWN) ||
2178             tsp->cellp == NULL          /* SetPrefs only */)
2179             continue;
2180
2181         cm_GetServerNoLock(tsp);
2182         lock_ReleaseRead(&cm_serverLock);
2183
2184         serversp[nconns] = tsp;
2185         code = cm_ConnByServer(tsp, cm_rootUserp, FALSE, &conns[nconns]);
2186         if (code) {
2187             lock_ObtainRead(&cm_serverLock);
2188             cm_PutServerNoLock(tsp);
2189             continue;
2190         }
2191         lock_ObtainRead(&cm_serverLock);
2192         rxconns[nconns] = cm_GetRxConn(conns[nconns]);
2193         rx_SetConnDeadTime(rxconns[nconns], 10);
2194
2195         nconns++;
2196     }
2197     lock_ReleaseRead(&cm_serverLock);
2198
2199     if (nconns) {
2200         /* Perform the multi call */
2201         start = time(NULL);
2202         multi_Rx(rxconns,nconns)
2203         {
2204             multi_RXAFS_GiveUpAllCallBacks();
2205             results[multi_i]=multi_error;
2206         } multi_End;
2207     }
2208
2209     /* Process results of servers that support RXAFS_GetCapabilities */
2210     for (i=0; i<nconns; i++) {
2211         rx_SetConnDeadTime(rxconns[i], ConnDeadtimeout);
2212         rx_PutConnection(rxconns[i]);
2213         cm_PutConn(conns[i]);
2214
2215         tsp = serversp[i];
2216         cm_GCConnections(tsp);
2217
2218         if (markDown) {
2219             cm_server_vols_t * tsrvp;
2220             cm_volume_t * volp;
2221             int i;
2222
2223             cm_ForceNewConnections(tsp);
2224
2225             lock_ObtainMutex(&tsp->mx);
2226             if (!(tsp->flags & CM_SERVERFLAG_DOWN)) {
2227                 _InterlockedOr(&tsp->flags, CM_SERVERFLAG_DOWN);
2228                 tsp->downTime = time(NULL);
2229             }
2230             /* Now update the volume status */
2231             for (tsrvp = tsp->vols; tsrvp; tsrvp = tsrvp->nextp) {
2232                 for (i=0; i<NUM_SERVER_VOLS; i++) {
2233                     if (tsrvp->ids[i] != 0) {
2234                         cm_req_t req;
2235
2236                         cm_InitReq(&req);
2237                         lock_ReleaseMutex(&tsp->mx);
2238                         code = cm_FindVolumeByID(tsp->cellp, tsrvp->ids[i], cm_rootUserp,
2239                                                  &req, CM_GETVOL_FLAG_NO_LRU_UPDATE | CM_GETVOL_FLAG_NO_RESET, &volp);
2240                         lock_ObtainMutex(&tsp->mx);
2241                         if (code == 0) {
2242                             cm_UpdateVolumeStatus(volp, tsrvp->ids[i]);
2243                             cm_PutVolume(volp);
2244                         }
2245                     }
2246                 }
2247             }
2248             lock_ReleaseMutex(&tsp->mx);
2249         }
2250     }
2251
2252     free(conns);
2253     free(rxconns);
2254     free(deltas);
2255     free(results);
2256     free(serversp);
2257 }
2258
2259