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