OPENAFS-SA-2018-002 afs: prevent RXAFSCB_TellMeAboutYourself information leak
[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->flags, ~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             code = cm_UpdateIFInfo();
953         }
954         lock_ConvertWToR(&cm_syscfgLock);
955     }
956
957     /* return all network interface addresses */
958     addr->numberOfInterfaces = cm_noIPAddr;
959     addr->uuid = cm_data.Uuid;
960     for ( i=0; i < cm_noIPAddr; i++ ) {
961         addr->addr_in[i] = cm_IPAddr[i];
962         addr->subnetmask[i] = cm_SubnetMask[i];
963         addr->mtu[i] = (rx_mtu == -1 || (rx_mtu != -1 && cm_NetMtu[i] < rx_mtu)) ?
964             cm_NetMtu[i] : rx_mtu;
965     }
966
967     lock_ReleaseRead(&cm_syscfgLock);
968
969     return 0;
970 }
971
972 int
973 SRXAFSCB_InitCallBackState3(struct rx_call *callp, afsUUID* serverUuid)
974 {
975     char *p = NULL;
976
977     cm_server_t *tsp = NULL;
978     cm_scache_t *scp = NULL;
979     cm_cell_t* cellp = NULL;
980     afs_uint32 hash;
981     int discarded;
982     cm_fid_t discardFid;
983     afs_uint32 discardType;
984     struct rx_connection *connp;
985     struct rx_peer *peerp;
986     unsigned long host = 0;
987     unsigned short port = 0;
988
989     if (cm_shutdown)
990         return 1;
991
992     if ((connp = rx_ConnectionOf(callp)) && (peerp = rx_PeerOf(connp))) {
993         host = rx_HostOf(peerp);
994         port = rx_PortOf(peerp);
995
996         if (serverUuid) {
997             if (UuidToString((UUID *)serverUuid, &p) == RPC_S_OK) {
998                 osi_Log1(afsd_logp, "SRXAFSCB_InitCallBackState3 Uuid%s ->",osi_LogSaveString(afsd_logp,p));
999                 RpcStringFree(&p);
1000             }
1001
1002             tsp = cm_FindServerByUuid(serverUuid, CM_SERVER_FILE, FALSE);
1003         }
1004         if (!tsp)
1005             tsp = cm_FindServerByIP(host, port, CM_SERVER_FILE, FALSE);
1006         if (tsp) {
1007             cellp = tsp->cellp;
1008             cm_PutServer(tsp);
1009         }
1010
1011         if (!cellp)
1012             osi_Log2(afsd_logp, "SRXAFSCB_InitCallBackState3 from host 0x%x port %d",
1013                      ntohl(host),
1014                      ntohs(port));
1015         else
1016             osi_Log3(afsd_logp, "SRXAFSCB_InitCallBackState3 from host 0x%x port %d for cell %s",
1017                      ntohl(host),
1018                      ntohs(port),
1019                      cellp->name /* does not need to be saved, doesn't change */);
1020     } else {
1021         osi_Log0(afsd_logp, "SRXAFSCB_InitCallBackState3 from unknown host");
1022     }
1023
1024     if (connp && peerp) {
1025         tsp = cm_FindServerByIP(host, port, CM_SERVER_FILE, FALSE);
1026
1027         osi_Log1(afsd_logp, "InitCallbackState3 server %x", tsp);
1028
1029         /* record the callback in the racing revokes structure.  This
1030          * shouldn't be necessary, since we shouldn't be making callback
1031          * granting calls while we're going to get an initstate call,
1032          * but there probably are some obscure races, so better safe
1033          * than sorry.
1034          *
1035          * We do this first since we don't hold the cm_scacheLock and vnode
1036          * locks over the entire callback scan operation below.  The
1037          * big loop below is guaranteed to hit any callback already
1038          * processed.  The call to RecordRacingRevoke is guaranteed
1039          * to kill any callback that is currently being returned.
1040          * Anything that sneaks past both must start
1041          * after the call to RecordRacingRevoke.
1042          */
1043         if (cellp) {
1044             cm_fid_t fid;
1045
1046             fid.cell = cellp->cellID;
1047             fid.volume = fid.vnode = fid.unique = 0;
1048
1049             cm_RecordRacingRevoke(&fid, CM_RACINGFLAG_CANCELALL);
1050         } else {
1051             cm_RecordRacingRevoke(NULL, CM_RACINGFLAG_CANCELALL);
1052         }
1053
1054         /* now search all vnodes looking for guys with this callback, if we
1055          * found it, or guys with any callbacks, if we didn't find the server
1056          * (that's how multihomed machines will appear and how we'll handle
1057          * them, albeit a little inefficiently).  That is, we're discarding all
1058          * callbacks from all hosts if we get an initstate call from an unknown
1059          * host.  Since these calls are rare, and multihomed servers
1060          * are "rare," hopefully this won't be a problem.
1061          */
1062         lock_ObtainWrite(&cm_scacheLock);
1063         for (hash = 0; hash < cm_data.scacheHashTableSize; hash++) {
1064             for (scp=cm_data.scacheHashTablep[hash]; scp; scp=scp->nextp) {
1065                 if (scp->cbExpires > 0 && scp->cbServerp != NULL) {
1066                     cm_HoldSCacheNoLock(scp);
1067                     lock_ReleaseWrite(&cm_scacheLock);
1068                     discarded = 0;
1069                     lock_ObtainWrite(&scp->rw);
1070                     if (scp->cbExpires > 0 && scp->cbServerp != NULL) {
1071                         /* we have a callback, now decide if we should clear it */
1072                         if (cm_ServerEqual(scp->cbServerp, tsp)) {
1073                             osi_Log4(afsd_logp, "InitCallbackState3 Discarding SCache scp 0x%p vol %u vn %u uniq %u",
1074                                      scp, scp->fid.volume, scp->fid.vnode, scp->fid.unique);
1075                             discardFid = scp->fid;
1076                             discardType = scp->fileType;
1077                             cm_DiscardSCache(scp);
1078                             discarded = 1;
1079                         }
1080                     }
1081                     lock_ReleaseWrite(&scp->rw);
1082                     if (discarded) {
1083                         cm_CallbackNotifyChange(scp);
1084                         if (RDR_Initialized)
1085                             RDR_InvalidateObject(discardFid.cell, discardFid.volume, discardFid.vnode, discardFid.unique,
1086                                                  discardFid.hash, discardType, AFS_INVALIDATE_EXPIRED);
1087                     }
1088                     lock_ObtainWrite(&cm_scacheLock);
1089                     cm_ReleaseSCacheNoLock(scp);
1090
1091                     if (discarded && (scp->flags & CM_SCACHEFLAG_PURERO))
1092                         cm_callbackDiscardROVolumeByFID(&scp->fid);
1093                 }
1094             }   /* search one hash bucket */
1095         }       /* search all hash buckets */
1096
1097         lock_ReleaseWrite(&cm_scacheLock);
1098
1099         if (tsp) {
1100             /* reset the No flags on the server */
1101             cm_SetServerNo64Bit(tsp, 0);
1102             cm_SetServerNoInlineBulk(tsp, 0);
1103
1104             /* we're done with the server structure */
1105             cm_PutServer(tsp);
1106         }
1107     }
1108     return 0;
1109 }
1110
1111 /* debug interface */
1112 int
1113 SRXAFSCB_ProbeUuid(struct rx_call *callp, afsUUID* clientUuid)
1114 {
1115     struct rx_connection *connp;
1116     struct rx_peer *peerp;
1117     unsigned long host = 0;
1118     unsigned short port = 0;
1119     char *p,*q;
1120     int code = 0;
1121
1122     if (cm_shutdown)
1123         return 1;
1124
1125     if ((connp = rx_ConnectionOf(callp)) && (peerp = rx_PeerOf(connp))) {
1126         host = rx_HostOf(peerp);
1127         port = rx_PortOf(peerp);
1128     }
1129
1130     if ( !afs_uuid_equal(&cm_data.Uuid, clientUuid) ) {
1131         UuidToString((UUID *)&cm_data.Uuid, &p);
1132         UuidToString((UUID *)clientUuid, &q);
1133         osi_Log4(afsd_logp, "SRXAFSCB_ProbeUuid %s != %s from host 0x%x port %d",
1134                   osi_LogSaveString(afsd_logp,p),
1135                   osi_LogSaveString(afsd_logp,q),
1136                   ntohl(host),
1137                   ntohs(port));
1138         RpcStringFree(&p);
1139         RpcStringFree(&q);
1140
1141         code = 1;       /* failure */
1142     } else
1143         osi_Log2(afsd_logp, "SRXAFSCB_ProbeUuid (success) from host 0x%x port %d",
1144                   ntohl(host),
1145                   ntohs(port));
1146
1147     return code;
1148 }
1149
1150 /* debug interface */
1151 static int
1152 GetCellCommon(afs_int32 a_cellnum, char **a_name, serverList *a_hosts)
1153 {
1154     afs_int32 sn;
1155     cm_cell_t * cellp;
1156     cm_serverRef_t * serverRefp;
1157     size_t len;
1158
1159     cellp = cm_FindCellByID(a_cellnum, CM_FLAG_NOPROBE);
1160     if (!cellp) {
1161         *a_name = (char *)xdr_alloc(sizeof(char));
1162         if (*a_name)
1163             *a_name[0] = '\0';
1164         return 0;
1165     }
1166
1167     lock_ObtainRead(&cm_serverLock);
1168     len = strlen(cellp->name)+1;
1169     *a_name = (char *)xdr_alloc(len);
1170     if (*a_name)
1171         memcpy(*a_name, cellp->name, len);
1172
1173     for ( sn = 0, serverRefp = cellp->vlServersp;
1174           sn < AFSMAXCELLHOSTS && serverRefp;
1175           sn++, serverRefp = serverRefp->next);
1176
1177     a_hosts->serverList_len = sn;
1178     a_hosts->serverList_val = (afs_int32 *)xdr_alloc(sn * sizeof(afs_int32));
1179
1180     for ( sn = 0, serverRefp = cellp->vlServersp;
1181           sn < AFSMAXCELLHOSTS && serverRefp;
1182           sn++, serverRefp = serverRefp->next)
1183     {
1184         a_hosts->serverList_val[sn] = ntohl(serverRefp->server->addr.sin_addr.s_addr);
1185     }
1186
1187     lock_ReleaseRead(&cm_serverLock);
1188     return 0;
1189 }
1190
1191 /* debug interface */
1192 int
1193 SRXAFSCB_GetCellByNum(struct rx_call *callp, afs_int32 a_cellnum,
1194                       char **a_name, serverList *a_hosts)
1195 {
1196     struct rx_connection *connp;
1197     struct rx_peer *peerp;
1198     unsigned long host = 0;
1199     unsigned short port = 0;
1200     int rc;
1201
1202     if (cm_shutdown)
1203         return 1;
1204
1205     if ((connp = rx_ConnectionOf(callp)) && (peerp = rx_PeerOf(connp))) {
1206         host = rx_HostOf(peerp);
1207         port = rx_PortOf(peerp);
1208     }
1209
1210     osi_Log3(afsd_logp, "SRXAFSCB_GetCellByNum(%d) from host 0x%x port %d",
1211              a_cellnum, ntohl(host), ntohs(port));
1212
1213     a_hosts->serverList_val = 0;
1214     a_hosts->serverList_len = 0;
1215
1216
1217     rc = GetCellCommon(a_cellnum, a_name, a_hosts);
1218
1219     return rc;
1220 }
1221
1222 /* debug interface */
1223 int
1224 SRXAFSCB_TellMeAboutYourself( struct rx_call *callp,
1225                               struct interfaceAddr *addr,
1226                               Capabilities * capabilities)
1227 {
1228     int i;
1229     afs_uint32 *dataBuffP;
1230     afs_int32 dataBytes;
1231     long code;
1232     struct rx_connection *connp;
1233     struct rx_peer *peerp;
1234     unsigned long host = 0;
1235     unsigned short port = 0;
1236
1237     if (cm_shutdown)
1238         return 1;
1239
1240     if ((connp = rx_ConnectionOf(callp)) && (peerp = rx_PeerOf(connp))) {
1241         host = rx_HostOf(peerp);
1242         port = rx_PortOf(peerp);
1243     }
1244
1245     osi_Log2(afsd_logp, "SRXAFSCB_TellMeAboutYourself from host 0x%x port %d",
1246               ntohl(host),
1247               ntohs(port));
1248
1249     lock_ObtainRead(&cm_syscfgLock);
1250     if (cm_LanAdapterChangeDetected) {
1251         lock_ConvertRToW(&cm_syscfgLock);
1252         if (cm_LanAdapterChangeDetected) {
1253             code = cm_UpdateIFInfo();
1254         }
1255         lock_ConvertWToR(&cm_syscfgLock);
1256     }
1257
1258     /* return all network interface addresses */
1259     memset(addr, 0, sizeof(*addr));
1260     addr->numberOfInterfaces = cm_noIPAddr;
1261     addr->uuid = cm_data.Uuid;
1262     for ( i=0; i < cm_noIPAddr; i++ ) {
1263         addr->addr_in[i] = cm_IPAddr[i];
1264         addr->subnetmask[i] = cm_SubnetMask[i];
1265         addr->mtu[i] = (rx_mtu == -1 || (rx_mtu != -1 && cm_NetMtu[i] < rx_mtu)) ?
1266             cm_NetMtu[i] : rx_mtu;
1267     }
1268     lock_ReleaseRead(&cm_syscfgLock);
1269
1270     dataBytes = 1 * sizeof(afs_uint32);
1271     dataBuffP = (afs_uint32 *) xdr_alloc(dataBytes);
1272     dataBuffP[0] = CLIENT_CAPABILITY_ERRORTRANS;
1273     capabilities->Capabilities_len = dataBytes / sizeof(afs_uint32);
1274     capabilities->Capabilities_val = dataBuffP;
1275
1276     return 0;
1277 }
1278
1279 /*------------------------------------------------------------------------
1280  * EXPORTED SRXAFSCB_GetServerPrefs
1281  *
1282  * Description:
1283  *      Routine to list server preferences used by this client.
1284  *
1285  * Arguments:
1286  *      a_call  : Ptr to Rx call on which this request came in.
1287  *      a_index : Input server index
1288  *      a_srvr_addr  : Output server address (0xffffffff on last server)
1289  *      a_srvr_rank  : Output server rank
1290  *
1291  * Returns:
1292  *      0 on success
1293  *
1294  * Environment:
1295  *      Nothing interesting.
1296  *
1297  * Side Effects:
1298  *      As advertised.
1299  *------------------------------------------------------------------------*/
1300
1301 int SRXAFSCB_GetServerPrefs(
1302     struct rx_call *callp,
1303     afs_int32 a_index,
1304     afs_int32 *a_srvr_addr,
1305     afs_int32 *a_srvr_rank)
1306 {
1307     struct rx_connection *connp;
1308     struct rx_peer *peerp;
1309     unsigned long host = 0;
1310     unsigned short port = 0;
1311
1312     if (cm_shutdown)
1313         return 1;
1314
1315     if ((connp = rx_ConnectionOf(callp)) && (peerp = rx_PeerOf(connp))) {
1316         host = rx_HostOf(peerp);
1317         port = rx_PortOf(peerp);
1318     }
1319
1320     osi_Log2(afsd_logp, "SRXAFSCB_GetServerPrefs from host 0x%x port %d - not implemented",
1321               ntohl(host),
1322               ntohs(port));
1323
1324     *a_srvr_addr = 0xffffffff;
1325     *a_srvr_rank = 0xffffffff;
1326
1327     return 0;
1328 }
1329
1330 /*------------------------------------------------------------------------
1331  * EXPORTED SRXAFSCB_GetCellServDB
1332  *
1333  * Description:
1334  *      Routine to list cells configured for this client
1335  *
1336  * Arguments:
1337  *      a_call  : Ptr to Rx call on which this request came in.
1338  *      a_index : Input cell index
1339  *      a_name  : Output cell name ("" on last cell)
1340  *      a_hosts : Output cell database servers
1341  *
1342  * Returns:
1343  *      0 on success
1344  *
1345  * Environment:
1346  *      Nothing interesting.
1347  *
1348  * Side Effects:
1349  *      As advertised.
1350  *------------------------------------------------------------------------*/
1351
1352 int SRXAFSCB_GetCellServDB(struct rx_call *callp, afs_int32 index, char **a_name,
1353                            serverList *a_hosts)
1354 {
1355     struct rx_connection *connp;
1356     struct rx_peer *peerp;
1357     unsigned long host = 0;
1358     unsigned short port = 0;
1359     int rc;
1360
1361     if (cm_shutdown)
1362         return 1;
1363
1364     if ((connp = rx_ConnectionOf(callp)) && (peerp = rx_PeerOf(connp))) {
1365         host = rx_HostOf(peerp);
1366         port = rx_PortOf(peerp);
1367     }
1368
1369     osi_Log2(afsd_logp, "SRXAFSCB_GetCellServDB from host 0x%x port %d - not implemented",
1370              ntohl(host), ntohs(port));
1371
1372 #ifdef AFS_FREELANCE_CLIENT
1373     if (cm_freelanceEnabled && index == 0) {
1374         rc = GetCellCommon(AFS_FAKE_ROOT_CELL_ID, a_name, a_hosts);
1375     } else
1376 #endif
1377     {
1378         rc = GetCellCommon(index+1, a_name, a_hosts);
1379     }
1380     return 0;
1381 }
1382
1383 /*------------------------------------------------------------------------
1384  * EXPORTED SRXAFSCB_GetLocalCell
1385  *
1386  * Description:
1387  *      Routine to return name of client's local cell
1388  *
1389  * Arguments:
1390  *      a_call  : Ptr to Rx call on which this request came in.
1391  *      a_name  : Output cell name
1392  *
1393  * Returns:
1394  *      0 on success
1395  *
1396  * Environment:
1397  *      Nothing interesting.
1398  *
1399  * Side Effects:
1400  *      As advertised.
1401  *------------------------------------------------------------------------*/
1402
1403 int SRXAFSCB_GetLocalCell(struct rx_call *callp, char **a_name)
1404 {
1405     char *t_name;
1406     struct rx_connection *connp;
1407     struct rx_peer *peerp;
1408     unsigned long host = 0;
1409     unsigned short port = 0;
1410     size_t len;
1411
1412     if (cm_shutdown)
1413         return 1;
1414
1415     if ((connp = rx_ConnectionOf(callp)) && (peerp = rx_PeerOf(connp))) {
1416         host = rx_HostOf(peerp);
1417         port = rx_PortOf(peerp);
1418     }
1419
1420     osi_Log2(afsd_logp, "SRXAFSCB_GetLocalCell from host 0x%x port %d",
1421              ntohl(host), ntohs(port));
1422
1423     if (cm_data.rootCellp) {
1424         len = strlen(cm_data.rootCellp->name) + 1;
1425         t_name = (char *)xdr_alloc(len);
1426         if (t_name)
1427             memcpy(t_name, cm_data.rootCellp->name, len);
1428     } else {
1429         t_name = (char *)xdr_alloc(1);
1430         t_name[0] = '\0';
1431     }
1432     *a_name = t_name;
1433
1434     return 0;
1435 }
1436
1437
1438 /*
1439  * afs_MarshallCacheConfig - marshall client cache configuration
1440  *
1441  * PARAMETERS
1442  *
1443  * IN callerVersion - the rpc stat version of the caller.
1444  *
1445  * IN config - client cache configuration.
1446  *
1447  * OUT ptr - buffer where configuration is marshalled.
1448  *
1449  * RETURN CODES
1450  *
1451  * Returns void.
1452  */
1453 static void afs_MarshallCacheConfig(
1454     afs_uint32 callerVersion,
1455     cm_initparams_v1 *config,
1456     afs_uint32 *ptr)
1457 {
1458     /*
1459      * We currently only support version 1.
1460      */
1461     *(ptr++) = config->nChunkFiles;
1462     *(ptr++) = config->nStatCaches;
1463     *(ptr++) = config->nDataCaches;
1464     *(ptr++) = config->nVolumeCaches;
1465     *(ptr++) = config->firstChunkSize;
1466     *(ptr++) = config->otherChunkSize;
1467     *(ptr++) = config->cacheSize;
1468     *(ptr++) = config->setTime;
1469     *(ptr++) = config->memCache;
1470
1471 }
1472
1473
1474 /*------------------------------------------------------------------------
1475  * EXPORTED SRXAFSCB_GetCacheConfig
1476  *
1477  * Description:
1478  *      Routine to return parameters used to initialize client cache.
1479  *      Client may request any format version. Server may not return
1480  *      format version greater than version requested by client.
1481  *
1482  * Arguments:
1483  *      a_call:        Ptr to Rx call on which this request came in.
1484  *      callerVersion: Data format version desired by the client.
1485  *      serverVersion: Data format version of output data.
1486  *      configCount:   Number bytes allocated for output data.
1487  *      config:        Client cache configuration.
1488  *
1489  * Returns:
1490  *      0 on success
1491  *
1492  * Environment:
1493  *      Nothing interesting.
1494  *
1495  * Side Effects:
1496  *      As advertised.
1497  *------------------------------------------------------------------------*/
1498
1499 int SRXAFSCB_GetCacheConfig(struct rx_call *callp,
1500                             afs_uint32 callerVersion,
1501                             afs_uint32 *serverVersion,
1502                             afs_uint32 *configCount,
1503                             cacheConfig *config)
1504 {
1505     afs_uint32 *t_config;
1506     size_t allocsize;
1507     extern cm_initparams_v1 cm_initParams;
1508     struct rx_connection *connp;
1509     struct rx_peer *peerp;
1510     unsigned long host = 0;
1511     unsigned short port = 0;
1512
1513     if (cm_shutdown)
1514         return 1;
1515
1516     if ((connp = rx_ConnectionOf(callp)) && (peerp = rx_PeerOf(connp))) {
1517         host = rx_HostOf(peerp);
1518         port = rx_PortOf(peerp);
1519     }
1520
1521     osi_Log2(afsd_logp, "SRXAFSCB_GetCacheConfig from host 0x%x port %d - version 1 only",
1522              ntohl(host), ntohs(port));
1523
1524     /*
1525      * Currently only support version 1
1526      */
1527     allocsize = sizeof(cm_initparams_v1);
1528     t_config = (afs_uint32 *)xdr_alloc(allocsize);
1529
1530     afs_MarshallCacheConfig(callerVersion, &cm_initParams, t_config);
1531
1532     *serverVersion = AFS_CLIENT_RETRIEVAL_FIRST_EDITION;
1533 #ifdef DEBUG
1534 #ifndef SIZE_MAX
1535 #define SIZE_MAX UINT_MAX
1536 #endif
1537     osi_assertx(allocsize < SIZE_MAX, "allocsize >= SIZE_MAX");
1538 #endif
1539     *configCount = (afs_uint32)allocsize;
1540     config->cacheConfig_val = t_config;
1541     config->cacheConfig_len = (*configCount)/sizeof(afs_uint32);
1542
1543     return 0;
1544 }
1545
1546 /* called by afsd without any locks to initialize this module */
1547 void cm_InitCallback(void)
1548 {
1549     lock_InitializeRWLock(&cm_callbackLock, "cm_callbackLock", LOCK_HIERARCHY_CALLBACK_GLOBAL);
1550     cm_activeCallbackGrantingCalls = 0;
1551 }
1552
1553 /* called with locked scp; tells us whether we've got a callback.
1554  * Expirations are checked by a background daemon so as to make
1555  * this function as inexpensive as possible
1556  */
1557 int cm_HaveCallback(cm_scache_t *scp)
1558 {
1559 #ifdef AFS_FREELANCE_CLIENT
1560     if (cm_freelanceEnabled &&
1561         scp->fid.cell==AFS_FAKE_ROOT_CELL_ID &&
1562         scp->fid.volume==AFS_FAKE_ROOT_VOL_ID) {
1563         if (cm_getLocalMountPointChange()) {
1564             cm_clearLocalMountPointChange();
1565             lock_ReleaseWrite(&scp->rw);
1566             cm_reInitLocalMountPoints();
1567             lock_ObtainWrite(&scp->rw);
1568         }
1569         return (cm_data.fakeDirVersion == scp->dataVersion);
1570     }
1571 #endif
1572     if (scp->cbServerp != NULL)
1573         return 1;
1574
1575     if (scp->flags & CM_SCACHEFLAG_PURERO) {
1576         cm_volume_t *volp = cm_GetVolumeByFID(&scp->fid);
1577         if (volp) {
1578             int haveCB = 0;
1579             if (cm_OfflineROIsValid) {
1580                 switch (cm_GetVolumeStatus(volp, scp->fid.volume)) {
1581                 case vl_offline:
1582                 case vl_alldown:
1583                 case vl_unknown:
1584                     haveCB = 1;
1585                     break;
1586                 }
1587             }
1588             if (cm_readonlyVolumeVersioning &&
1589                 !haveCB &&
1590                 scp->volumeCreationDate != 0 &&
1591                 volp->creationDateRO == scp->volumeCreationDate &&
1592                 volp->cbServerpRO != NULL) {
1593                 haveCB = 1;
1594             }
1595             cm_PutVolume(volp);
1596             return haveCB;
1597         }
1598     }
1599     return 0;
1600 }
1601
1602 /* need to detect a broken callback that races with our obtaining a callback.
1603  * Need to be able to do this even if we don't know the file ID of the file
1604  * we're breaking the callback on at the time we start the acquisition of the
1605  * callback (as in the case where we are creating a file).
1606  *
1607  * So, we start by writing down the count of the # of callbacks we've received
1608  * so far, and bumping a global counter of the # of callback granting calls
1609  * outstanding (all done under cm_callbackLock).
1610  *
1611  * When we're back from the call, we look at all of the callback revokes with
1612  * counter numbers greater than the one we recorded in our caller's structure,
1613  * and replay those that are higher than when we started the call.
1614  *
1615  * We free all the structures in the queue when the count of the # of outstanding
1616  * callback-granting calls drops to zero.
1617  *
1618  * We call this function with the scp locked, too, but in its current implementation,
1619  * this knowledge is not used.
1620  */
1621 void cm_StartCallbackGrantingCall(cm_scache_t *scp, cm_callbackRequest_t *cbrp)
1622 {
1623     lock_ObtainWrite(&cm_callbackLock);
1624     cbrp->callbackCount = cm_callbackCount;
1625     cm_activeCallbackGrantingCalls++;
1626     cbrp->startTime = time(NULL);
1627     cbrp->serverp = NULL;
1628     lock_ReleaseWrite(&cm_callbackLock);
1629 }
1630
1631 /* Called at the end of a callback-granting call, to remove the callback
1632  * info from the scache entry, if necessary.
1633  *
1634  * Called with scp write locked, so we can discard the callbacks easily with
1635  * this locking hierarchy.
1636  *
1637  * Performs cleanup of the stack allocated cm_callbackRequest_t object.
1638  *
1639  * Returns 0 on success and non-zero if the callback lost a race.
1640  */
1641 int
1642 cm_EndCallbackGrantingCall(cm_scache_t *scp, cm_callbackRequest_t *cbrp,
1643                            AFSCallBack *cbp, AFSVolSync *volSyncp, long flags)
1644 {
1645     cm_racingRevokes_t *revp;           /* where we are */
1646     cm_racingRevokes_t *nrevp;          /* where we'll be next */
1647     int freeRacingRevokes;
1648     int freeServer;
1649     cm_server_t * serverp = NULL;
1650     int lostRace = 0;
1651
1652     lock_ObtainWrite(&cm_callbackLock);
1653     if (flags & CM_CALLBACK_MAINTAINCOUNT) {
1654         osi_assertx(cm_activeCallbackGrantingCalls > 0,
1655                     "CM_CALLBACK_MAINTAINCOUNT && cm_activeCallbackGrantingCalls == 0");
1656         freeServer = 0;
1657     }
1658     else {
1659         osi_assertx(cm_activeCallbackGrantingCalls-- > 0,
1660                     "!CM_CALLBACK_MAINTAINCOUNT && cm_activeCallbackGrantingCalls == 0");
1661         freeServer = 1;
1662     }
1663     if (cm_activeCallbackGrantingCalls == 0)
1664         freeRacingRevokes = 1;
1665     else
1666         freeRacingRevokes = 0;
1667
1668     /*
1669      * a callback was revoked during our granting call, so
1670      * run down the list of revoked fids, looking for ours.
1671      * If activeCallbackGrantingCalls is zero, free the elements, too.
1672      *
1673      * May need to go through entire list just to do the freeing.
1674      */
1675     for (revp = cm_racingRevokesp; revp; revp = nrevp) {
1676         nrevp = (cm_racingRevokes_t *) osi_QNext(&revp->q);
1677         /* if this callback came in later than when we started the
1678          * callback-granting call, and if this fid is the right fid,
1679          * then clear the callback.
1680          */
1681         if (scp && cbrp && cbrp->callbackCount != cm_callbackCount
1682              && revp->callbackCount > cbrp->callbackCount
1683              && (( scp->fid.volume == revp->fid.volume &&
1684                    scp->fid.vnode == revp->fid.vnode &&
1685                    scp->fid.unique == revp->fid.unique)
1686                   ||
1687                   ((revp->flags & CM_RACINGFLAG_CANCELVOL) &&
1688                     scp->fid.volume == revp->fid.volume)
1689                   ||
1690                   ((revp->flags & CM_RACINGFLAG_CANCELALL) &&
1691                    (revp->fid.cell == 0 || scp->fid.cell == revp->fid.cell)))) {
1692             /* this one matches */
1693             osi_Log4(afsd_logp,
1694                       "Racing revoke scp 0x%p old cbc %d rev cbc %d cur cbc %d",
1695                       scp,
1696                       cbrp->callbackCount, revp->callbackCount,
1697                       cm_callbackCount);
1698             lostRace = 1;
1699             if ((scp->flags & CM_SCACHEFLAG_PURERO) &&
1700                  (revp->flags & CM_RACINGFLAG_ALL))
1701                 cm_callbackDiscardROVolumeByFID(&scp->fid);
1702         }
1703         if (freeRacingRevokes)
1704             free(revp);
1705     }
1706
1707     /* if we freed the list, zap the pointer to it */
1708     if (freeRacingRevokes)
1709         cm_racingRevokesp = NULL;
1710     lock_ReleaseWrite(&cm_callbackLock);
1711
1712     /* record the callback if we didn't lose it */
1713     if (!lostRace && scp) {
1714         if (cbrp) {
1715             if (!cm_ServerEqual(scp->cbServerp, cbrp->serverp)) {
1716                 serverp = scp->cbServerp;
1717                 scp->cbServerp = cbrp->serverp;
1718                 if (freeServer) {
1719                     cbrp->serverp = NULL;
1720                 } else {
1721                     cm_GetServer(scp->cbServerp);
1722                 }
1723             } else if (freeServer) {
1724                 serverp = cbrp->serverp;
1725                 cbrp->serverp = NULL;
1726             }
1727             scp->cbExpires = cbrp->startTime + cbp->ExpirationTime;
1728             scp->cbIssued = time(NULL);
1729         }
1730
1731         if (scp->flags & CM_SCACHEFLAG_PURERO) {
1732             cm_volume_t * volp = cm_GetVolumeByFID(&scp->fid);
1733             if (volp) {
1734                 if (volSyncp) {
1735                     lock_ObtainWrite(&cm_scacheLock);
1736                     volp->cbExpiresRO = scp->cbExpires;
1737                     volp->cbIssuedRO = scp->cbIssued;
1738                     if (cm_readonlyVolumeVersioning || !(flags & CM_CALLBACK_BULKSTAT))
1739                         volp->creationDateRO = volSyncp->spare1;
1740                     else
1741                         volp->creationDateRO = 0;
1742                     if (volp->cbServerpRO != scp->cbServerp) {
1743                         if (volp->cbServerpRO)
1744                             cm_PutServer(volp->cbServerpRO);
1745                         cm_GetServer(scp->cbServerp);
1746                         volp->cbServerpRO = scp->cbServerp;
1747                     }
1748                     lock_ReleaseWrite(&cm_scacheLock);
1749                 }
1750                 cm_PutVolume(volp);
1751             }
1752         }
1753     }
1754     else
1755     {
1756         /*
1757          * No need to discard the cm_scache object or notify the
1758          * afs redirector or smb client about a change if we did lose
1759          * the race.  That was done when the callback was processed in
1760          * cm_RevokeCallback().
1761          */
1762         if (cbrp && freeServer) {
1763             serverp = cbrp->serverp;
1764             cbrp->serverp = NULL;
1765         }
1766     }
1767
1768     if ( serverp ) {
1769         lock_ObtainWrite(&cm_serverLock);
1770         cm_FreeServer(serverp);
1771         lock_ReleaseWrite(&cm_serverLock);
1772     }
1773
1774     return lostRace;
1775 }
1776
1777 /* if flags is 1, we want to force the code to make one call, anyway.
1778  * called with locked scp; returns with same.
1779  */
1780 long cm_GetCallback(cm_scache_t *scp, struct cm_user *userp,
1781                     struct cm_req *reqp, long flags)
1782 {
1783     long code = 0;
1784     cm_conn_t *connp = NULL;
1785     AFSFetchStatus afsStatus;
1786     AFSVolSync volSync;
1787     AFSCallBack callback;
1788     AFSFid tfid;
1789     cm_callbackRequest_t cbr;
1790     int mustCall;
1791     cm_fid_t sfid;
1792     struct rx_connection * rxconnp = NULL;
1793     int syncop_done = 0;
1794
1795     memset(&volSync, 0, sizeof(volSync));
1796
1797     osi_Log4(afsd_logp, "GetCallback scp 0x%p cell %d vol %d flags %lX",
1798              scp, scp->fid.cell, scp->fid.volume, flags);
1799
1800 #ifdef AFS_FREELANCE_CLIENT
1801     // The case where a callback is needed on /afs is handled
1802     // specially. We need to fetch the status by calling
1803     // cm_MergeStatus
1804     if (cm_freelanceEnabled &&
1805         (scp->fid.cell==AFS_FAKE_ROOT_CELL_ID &&
1806          scp->fid.volume==AFS_FAKE_ROOT_VOL_ID)) {
1807
1808         code = cm_SyncOp(scp, NULL, userp, reqp, 0,
1809                           CM_SCACHESYNC_FETCHSTATUS | CM_SCACHESYNC_GETCALLBACK);
1810         if (code)
1811             goto done;
1812         syncop_done = 1;
1813
1814         if (scp->dataVersion != cm_data.fakeDirVersion) {
1815             memset(&afsStatus, 0, sizeof(afsStatus));
1816             memset(&volSync, 0, sizeof(volSync));
1817             InterlockedIncrement(&scp->activeRPCs);
1818
1819             // Fetch the status info
1820             code = cm_MergeStatus(NULL, scp, &afsStatus, &volSync, userp, reqp, 0);
1821         }
1822         goto done;
1823     }
1824 #endif /* AFS_FREELANCE_CLIENT */
1825
1826     mustCall = (flags & 1);
1827     cm_AFSFidFromFid(&tfid, &scp->fid);
1828     while (1) {
1829         if (!mustCall && cm_HaveCallback(scp))
1830             break;
1831
1832         /* turn off mustCall, since it has now forced us past the check above */
1833         mustCall = 0;
1834
1835         /* otherwise, we have to make an RPC to get the status */
1836         if (!syncop_done) {
1837             code = cm_SyncOp(scp, NULL, userp, reqp, 0,
1838                              CM_SCACHESYNC_FETCHSTATUS | CM_SCACHESYNC_GETCALLBACK);
1839             if (code)
1840                 break;
1841             syncop_done = 1;
1842         }
1843         cm_StartCallbackGrantingCall(scp, &cbr);
1844         sfid = scp->fid;
1845         lock_ReleaseWrite(&scp->rw);
1846
1847         /* now make the RPC */
1848         InterlockedIncrement(&scp->activeRPCs);
1849         osi_Log4(afsd_logp, "CALL FetchStatus scp 0x%p vol %u vn %u uniq %u",
1850                  scp, sfid.volume, sfid.vnode, sfid.unique);
1851         do {
1852             code = cm_ConnFromFID(&sfid, userp, reqp, &connp);
1853             if (code)
1854                 continue;
1855
1856             rxconnp = cm_GetRxConn(connp);
1857             code = RXAFS_FetchStatus(rxconnp, &tfid,
1858                                      &afsStatus, &callback, &volSync);
1859             rx_PutConnection(rxconnp);
1860
1861         } while (cm_Analyze(connp, userp, reqp, &sfid, NULL, 0, &afsStatus, &volSync, NULL,
1862                             &cbr, code));
1863         code = cm_MapRPCError(code, reqp);
1864         if (code)
1865             osi_Log4(afsd_logp, "CALL FetchStatus FAILURE code 0x%x scp 0x%p vol %u vn %u",
1866                      code, scp, scp->fid.volume, scp->fid.vnode);
1867         else
1868             osi_Log4(afsd_logp, "CALL FetchStatus SUCCESS scp 0x%p vol %u vn %u uniq %u",
1869                      scp, scp->fid.volume, scp->fid.vnode, scp->fid.unique);
1870
1871         lock_ObtainWrite(&scp->rw);
1872         if (code == 0) {
1873             int lostRace = cm_EndCallbackGrantingCall(scp, &cbr, &callback, &volSync, 0);
1874             if (lostRace) {
1875                 InterlockedDecrement(&scp->activeRPCs);
1876             } else {
1877                 code = cm_MergeStatus(NULL, scp, &afsStatus, &volSync, userp, reqp, 0);
1878             }
1879         } else {
1880             cm_EndCallbackGrantingCall(NULL, &cbr, NULL, NULL, 0);
1881             InterlockedDecrement(&scp->activeRPCs);
1882         }
1883
1884         /* if we got an error, return to caller */
1885         if (code)
1886             break;
1887     }
1888
1889   done:
1890     if (syncop_done)
1891         cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_FETCHSTATUS | CM_SCACHESYNC_GETCALLBACK);
1892
1893     if (code) {
1894         osi_Log2(afsd_logp, "GetCallback Failed code 0x%x scp 0x%p -->",code, scp);
1895         osi_Log4(afsd_logp, "            cell %u vol %u vn %u uniq %u",
1896                  scp->fid.cell, scp->fid.volume, scp->fid.vnode, scp->fid.unique);
1897     } else {
1898         osi_Log3(afsd_logp, "GetCallback Complete scp 0x%p cell %d vol %d",
1899                   scp, scp->fid.cell, scp->fid.volume);
1900     }
1901
1902     return code;
1903 }
1904
1905
1906 /*
1907  * cm_CBServersDownTime() returns 1 if the downTime parameter is valid.
1908  *
1909  * Servers with multiple interfaces have multiple cm_server_t objects
1910  * which share the same UUID.  If one interface is down but others are up,
1911  * the server should not be considered down.  The returned downTime should
1912  * be the largest non-zero value if down or zero if up.  If the cbServerp
1913  * is down, it is updated to refer to an interface that is up (if one exists).
1914  *
1915  * called with cm_scacheLock held
1916  */
1917 static long
1918 cm_CBServersDownTime(cm_scache_t *scp, cm_volume_t *volp, time_t * pdownTime)
1919 {
1920     cm_vol_state_t *statep;
1921     cm_serverRef_t *tsrp;
1922     int alldown = 1;
1923     time_t downTime = 0;
1924     cm_server_t * upserver = NULL;
1925     cm_server_t * downserver;
1926
1927     *pdownTime = 0;
1928
1929     if (scp->cbServerp == NULL)
1930         return 1;
1931
1932     if (!(scp->cbServerp->flags & CM_SERVERFLAG_DOWN))
1933         return 1;
1934
1935     statep = cm_VolumeStateByID(volp, scp->fid.volume);
1936     if (statep) {
1937         for (tsrp = statep->serversp; tsrp; tsrp=tsrp->next) {
1938             if (tsrp->status == srv_deleted)
1939                 continue;
1940
1941             if (!cm_ServerEqual(tsrp->server, scp->cbServerp))
1942                 continue;
1943
1944             if (!(tsrp->server->flags & CM_SERVERFLAG_DOWN)) {
1945                 alldown = 0;
1946                 if (!upserver) {
1947                     upserver = tsrp->server;
1948                     cm_GetServer(upserver);
1949                 }
1950             }
1951
1952             if (tsrp->server->downTime > downTime)
1953                 downTime = tsrp->server->downTime;
1954         }
1955     } else {
1956         downTime = scp->cbServerp->downTime;
1957     }
1958
1959     /* if the cbServerp does not match the current volume server list
1960      * we report the callback server as up so the callback can be
1961      * expired.
1962      */
1963
1964     if (alldown) {
1965         *pdownTime = downTime;
1966     } else {
1967         lock_ObtainWrite(&scp->rw);
1968         downserver = scp->cbServerp;
1969         scp->cbServerp = upserver;
1970         lock_ReleaseWrite(&scp->rw);
1971         cm_PutServer(downserver);
1972     }
1973     return 1;
1974 }
1975
1976 /* called periodically by cm_daemon to shut down use of expired callbacks */
1977 void cm_CheckCBExpiration(void)
1978 {
1979     afs_uint32 i;
1980     cm_scache_t *scp;
1981     cm_volume_t *volp;
1982     enum volstatus volstate;
1983     time_t now, downTime;
1984
1985     osi_Log0(afsd_logp, "CheckCBExpiration");
1986
1987     now = time(NULL);
1988     lock_ObtainWrite(&cm_scacheLock);
1989     for (i=0; i<cm_data.scacheHashTableSize; i++) {
1990         for (scp = cm_data.scacheHashTablep[i]; scp; scp=scp->nextp) {
1991             volp = NULL;
1992             cm_HoldSCacheNoLock(scp);
1993             lock_ReleaseWrite(&cm_scacheLock);
1994
1995             /*
1996              * If this is not a PURERO object and there is no callback
1997              * or it hasn't expired, there is nothing to do
1998              */
1999             if (!(scp->flags & CM_SCACHEFLAG_PURERO) &&
2000                 (scp->cbServerp == NULL || scp->cbExpires == 0 || now < scp->cbExpires))
2001                 goto scp_complete;
2002
2003             /*
2004              * Determine the volume state and update the callback info
2005              * to the latest if it is a PURERO object.
2006              */
2007             volp = cm_GetVolumeByFID(&scp->fid);
2008             volstate = vl_unknown;
2009             downTime = 0;
2010             if (volp) {
2011                 if ((scp->flags & CM_SCACHEFLAG_PURERO) &&
2012                     volp->cbExpiresRO > scp->cbExpires && scp->cbExpires > 0)
2013                 {
2014                     lock_ObtainWrite(&scp->rw);
2015                     scp->cbExpires = volp->cbExpiresRO;
2016                     scp->cbIssued = volp->cbIssuedRO;
2017                     if (volp->cbServerpRO != scp->cbServerp) {
2018                         if (scp->cbServerp)
2019                             cm_PutServer(scp->cbServerp);
2020                         cm_GetServer(volp->cbServerpRO);
2021                         scp->cbServerp = volp->cbServerpRO;
2022                     }
2023                     lock_ReleaseWrite(&scp->rw);
2024                 }
2025                 volstate = cm_GetVolumeStatus(volp, scp->fid.volume);
2026             }
2027
2028             /* If there is no callback or it hasn't expired, there is nothing to do */
2029             if (scp->cbServerp == NULL || scp->cbExpires == 0 || now < scp->cbExpires)
2030                 goto scp_complete;
2031
2032             /* If the volume is known not to be online, do not expire the callback */
2033             if (volstate != vl_online)
2034                 goto scp_complete;
2035
2036             /*
2037              * If all the servers are down and the callback expired after the
2038              * issuing server went down, do not expire the callback
2039              */
2040             if (cm_CBServersDownTime(scp, volp, &downTime) && downTime && downTime < scp->cbExpires)
2041                 goto scp_complete;
2042
2043             /* The callback has expired, discard the status info */
2044             osi_Log4(afsd_logp, "Callback Expiration Discarding SCache scp 0x%p vol %u vn %u uniq %u",
2045                      scp, scp->fid.volume, scp->fid.vnode, scp->fid.unique);
2046             lock_ObtainWrite(&scp->rw);
2047             cm_DiscardSCache(scp);
2048             lock_ReleaseWrite(&scp->rw);
2049
2050             if (RDR_Initialized)
2051                 RDR_InvalidateObject(scp->fid.cell, scp->fid.volume, scp->fid.vnode, scp->fid.unique,
2052                                      scp->fid.hash, scp->fileType, AFS_INVALIDATE_EXPIRED);
2053
2054             cm_CallbackNotifyChange(scp);
2055
2056             if (scp->fileType == CM_SCACHETYPE_DIRECTORY &&
2057                 !(volp && (volp->flags & CM_VOLUMEFLAG_DFS_VOLUME)) &&
2058                 !cm_accessPerFileCheck)
2059                 cm_EAccesClearParentEntries(&scp->fid);
2060
2061           scp_complete:
2062             if (volp)
2063                 cm_PutVolume(volp);
2064
2065             lock_ObtainWrite(&cm_scacheLock);
2066             cm_ReleaseSCacheNoLock(scp);
2067         }
2068     }
2069     lock_ReleaseWrite(&cm_scacheLock);
2070
2071     osi_Log0(afsd_logp, "CheckCBExpiration Complete");
2072 }
2073
2074
2075 void
2076 cm_GiveUpAllCallbacks(cm_server_t *tsp, afs_int32 markDown)
2077 {
2078     long code;
2079     cm_conn_t *connp;
2080     struct rx_connection * rxconnp;
2081
2082     if ((tsp->type == CM_SERVER_FILE) && !(tsp->flags & CM_SERVERFLAG_DOWN))
2083     {
2084         code = cm_ConnByServer(tsp, cm_rootUserp, FALSE, &connp);
2085         if (code == 0) {
2086             rxconnp = cm_GetRxConn(connp);
2087             rx_SetConnDeadTime(rxconnp, 10);
2088             code = RXAFS_GiveUpAllCallBacks(rxconnp);
2089             rx_SetConnDeadTime(rxconnp, ConnDeadtimeout);
2090             rx_PutConnection(rxconnp);
2091         }
2092
2093         if (markDown) {
2094             cm_server_vols_t * tsrvp;
2095             cm_volume_t * volp;
2096             int i;
2097
2098             cm_ForceNewConnections(tsp);
2099
2100             lock_ObtainMutex(&tsp->mx);
2101             if (!(tsp->flags & CM_SERVERFLAG_DOWN)) {
2102                 _InterlockedOr(&tsp->flags, CM_SERVERFLAG_DOWN);
2103                 tsp->downTime = time(NULL);
2104             }
2105             /* Now update the volume status */
2106             for (tsrvp = tsp->vols; tsrvp; tsrvp = tsrvp->nextp) {
2107                 for (i=0; i<NUM_SERVER_VOLS; i++) {
2108                     if (tsrvp->ids[i] != 0) {
2109                         cm_req_t req;
2110
2111                         cm_InitReq(&req);
2112                         lock_ReleaseMutex(&tsp->mx);
2113                         code = cm_FindVolumeByID(tsp->cellp, tsrvp->ids[i], cm_rootUserp,
2114                                                  &req, CM_GETVOL_FLAG_NO_LRU_UPDATE | CM_GETVOL_FLAG_NO_RESET, &volp);
2115                         lock_ObtainMutex(&tsp->mx);
2116                         if (code == 0) {
2117                             cm_UpdateVolumeStatus(volp, tsrvp->ids[i]);
2118                             cm_PutVolume(volp);
2119                         }
2120                     }
2121                 }
2122             }
2123             lock_ReleaseMutex(&tsp->mx);
2124         }
2125     }
2126 }
2127
2128 void
2129 cm_GiveUpAllCallbacksAllServers(afs_int32 markDown)
2130 {
2131     cm_server_t *tsp;
2132
2133     if (!cm_giveUpAllCBs)
2134         return;
2135
2136     lock_ObtainRead(&cm_serverLock);
2137     for (tsp = cm_serversAllFirstp;
2138          tsp;
2139          tsp = (cm_server_t *)osi_QNext(&tsp->allq)) {
2140         cm_GetServerNoLock(tsp);
2141         lock_ReleaseRead(&cm_serverLock);
2142         cm_GiveUpAllCallbacks(tsp, markDown);
2143         lock_ObtainRead(&cm_serverLock);
2144         cm_PutServerNoLock(tsp);
2145     }
2146     lock_ReleaseRead(&cm_serverLock);
2147 }
2148
2149 void
2150 cm_GiveUpAllCallbacksAllServersMulti(afs_int32 markDown)
2151 {
2152     long code;
2153     cm_conn_t **conns = NULL;
2154     struct rx_connection **rxconns = NULL;
2155     afs_int32 i, nconns = 0, maxconns;
2156     cm_server_t ** serversp, *tsp;
2157     afs_int32 *results;
2158     time_t start, *deltas;
2159
2160     maxconns = cm_numFileServers;
2161     if (maxconns == 0)
2162         return;
2163
2164     conns = (cm_conn_t **)malloc(maxconns * sizeof(cm_conn_t *));
2165     rxconns = (struct rx_connection **)malloc(maxconns * sizeof(struct rx_connection *));
2166     deltas = (time_t *)malloc(maxconns * sizeof (time_t));
2167     results = (afs_int32 *)malloc(maxconns * sizeof (afs_int32));
2168     serversp = (cm_server_t **)malloc(maxconns * sizeof(cm_server_t *));
2169
2170     lock_ObtainRead(&cm_serverLock);
2171     for (nconns=0, tsp = cm_serversAllFirstp;
2172          tsp && nconns < maxconns;
2173          tsp = (cm_server_t *)osi_QNext(&tsp->allq)) {
2174         if (tsp->type != CM_SERVER_FILE ||
2175             (tsp->flags & CM_SERVERFLAG_DOWN) ||
2176             tsp->cellp == NULL          /* SetPrefs only */)
2177             continue;
2178
2179         cm_GetServerNoLock(tsp);
2180         lock_ReleaseRead(&cm_serverLock);
2181
2182         serversp[nconns] = tsp;
2183         code = cm_ConnByServer(tsp, cm_rootUserp, FALSE, &conns[nconns]);
2184         if (code) {
2185             lock_ObtainRead(&cm_serverLock);
2186             cm_PutServerNoLock(tsp);
2187             continue;
2188         }
2189         lock_ObtainRead(&cm_serverLock);
2190         rxconns[nconns] = cm_GetRxConn(conns[nconns]);
2191         rx_SetConnDeadTime(rxconns[nconns], 10);
2192
2193         nconns++;
2194     }
2195     lock_ReleaseRead(&cm_serverLock);
2196
2197     if (nconns) {
2198         /* Perform the multi call */
2199         start = time(NULL);
2200         multi_Rx(rxconns,nconns)
2201         {
2202             multi_RXAFS_GiveUpAllCallBacks();
2203             results[multi_i]=multi_error;
2204         } multi_End;
2205     }
2206
2207     /* Process results of servers that support RXAFS_GetCapabilities */
2208     for (i=0; i<nconns; i++) {
2209         rx_SetConnDeadTime(rxconns[i], ConnDeadtimeout);
2210         rx_PutConnection(rxconns[i]);
2211         cm_PutConn(conns[i]);
2212
2213         tsp = serversp[i];
2214         cm_GCConnections(tsp);
2215
2216         if (markDown) {
2217             cm_server_vols_t * tsrvp;
2218             cm_volume_t * volp;
2219             int i;
2220
2221             cm_ForceNewConnections(tsp);
2222
2223             lock_ObtainMutex(&tsp->mx);
2224             if (!(tsp->flags & CM_SERVERFLAG_DOWN)) {
2225                 _InterlockedOr(&tsp->flags, CM_SERVERFLAG_DOWN);
2226                 tsp->downTime = time(NULL);
2227             }
2228             /* Now update the volume status */
2229             for (tsrvp = tsp->vols; tsrvp; tsrvp = tsrvp->nextp) {
2230                 for (i=0; i<NUM_SERVER_VOLS; i++) {
2231                     if (tsrvp->ids[i] != 0) {
2232                         cm_req_t req;
2233
2234                         cm_InitReq(&req);
2235                         lock_ReleaseMutex(&tsp->mx);
2236                         code = cm_FindVolumeByID(tsp->cellp, tsrvp->ids[i], cm_rootUserp,
2237                                                  &req, CM_GETVOL_FLAG_NO_LRU_UPDATE | CM_GETVOL_FLAG_NO_RESET, &volp);
2238                         lock_ObtainMutex(&tsp->mx);
2239                         if (code == 0) {
2240                             cm_UpdateVolumeStatus(volp, tsrvp->ids[i]);
2241                             cm_PutVolume(volp);
2242                         }
2243                     }
2244                 }
2245             }
2246             lock_ReleaseMutex(&tsp->mx);
2247         }
2248     }
2249
2250     free(conns);
2251     free(rxconns);
2252     free(deltas);
2253     free(results);
2254     free(serversp);
2255 }
2256
2257