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