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