Standardize License information
[openafs.git] / src / afs / afs_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 /*
11  * afs_callback.c:
12  *      Exported routines (and their private support) to implement
13  *      the callback RPC interface.
14  */
15
16 #include "../afs/param.h"       /*Should be always first*/
17 #include "../afs/sysincludes.h" /*Standard vendor system headers*/
18 #include "../afs/afsincludes.h" /*AFS-based standard headers*/
19 #include "../afs/afs_stats.h"   /*Cache Manager stats*/
20 #include "../afs/afs_args.h"
21
22 extern struct volume *afs_volumes[NVOLS];   /* volume hash table */
23 extern void afs_DequeueCallback();
24 extern void afs_ComputePAGStats();
25 afs_int32 afs_allCBs    = 0;            /*Break callbacks on all objects */
26 afs_int32 afs_oddCBs    = 0;            /*Break callbacks on dirs*/
27 afs_int32 afs_evenCBs = 0;              /*Break callbacks received on files*/
28 afs_int32 afs_allZaps = 0;              /*Objects entries deleted */
29 afs_int32 afs_oddZaps = 0;              /*Dir cache entries deleted*/
30 afs_int32 afs_evenZaps = 0;             /*File cache entries deleted*/
31 afs_int32 afs_connectBacks = 0;
32 extern struct rx_service *afs_server;
33
34 extern afs_lock_t afs_xvcb, afs_xbrs, afs_xdcache;
35 extern afs_rwlock_t afs_xvcache, afs_xserver,  afs_xcell,  afs_xuser;
36 extern afs_rwlock_t afs_xvolume, afs_puttofileLock, afs_ftf, afs_xinterface;
37 extern afs_rwlock_t afs_xconn;
38 extern struct afs_lock afs_xaxs;
39 extern afs_lock_t afs_xcbhash;
40 extern struct srvAddr *afs_srvAddrs[NSERVERS];
41 extern struct afs_q CellLRU;
42 extern struct cm_initparams cm_initParams;
43
44 /*
45  * Some debugging aids.
46  */
47 static struct ltable {
48     char *name;
49     char *addr;
50 } ltable []= {
51     "afs_xvcache", (char *)&afs_xvcache,
52     "afs_xdcache", (char *)&afs_xdcache,
53     "afs_xserver", (char *)&afs_xserver,
54     "afs_xvcb",    (char *)&afs_xvcb,
55     "afs_xbrs",    (char *)&afs_xbrs,
56     "afs_xcell",   (char *)&afs_xcell,
57     "afs_xconn",   (char *)&afs_xconn,
58     "afs_xuser",   (char *)&afs_xuser,
59     "afs_xvolume", (char *)&afs_xvolume,
60     "puttofile",   (char *)&afs_puttofileLock,
61     "afs_ftf",     (char *)&afs_ftf,
62     "afs_xcbhash", (char *)&afs_xcbhash,
63     "afs_xaxs",    (char *)&afs_xaxs,
64     "afs_xinterface", (char *)&afs_xinterface,
65 };
66 unsigned long  lastCallBack_vnode;
67 unsigned int   lastCallBack_dv;
68 osi_timeval_t  lastCallBack_time;
69
70 /* these are for storing alternate interface addresses */
71 struct interfaceAddr afs_cb_interface;
72
73 /*------------------------------------------------------------------------
74  * EXPORTED SRXAFSCB_GetCE
75  *
76  * Description:
77  *      Routine called by the server-side callback RPC interface to
78  *      implement pulling out the contents of the i'th cache entry.
79  *
80  * Arguments:
81  *      a_call   : Ptr to Rx call on which this request came in.
82  *      a_index  : Index of desired cache entry.
83  *      a_result : Ptr to a buffer for the given cache entry.
84  *
85  * Returns:
86  *      0 if everything went fine,
87  *      1 if we were given a bad index.
88  *
89  * Environment:
90  *      Nothing interesting.
91  *
92  * Side Effects:
93  *      As advertised.
94  *------------------------------------------------------------------------*/
95
96 int SRXAFSCB_GetCE(a_call, a_index, a_result)
97     struct rx_call *a_call;
98     afs_int32 a_index;
99     struct AFSDBCacheEntry *a_result;
100
101 { /*SRXAFSCB_GetCE*/
102
103     register int i;                     /*Loop variable*/
104     register struct vcache *tvc;        /*Ptr to current cache entry*/
105     int code;                           /*Return code*/
106     XSTATS_DECLS;
107
108 #ifdef RX_ENABLE_LOCKS
109     AFS_GLOCK();
110 #endif /* RX_ENABLE_LOCKS */
111
112     XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_GETCE);
113
114     AFS_STATCNT(SRXAFSCB_GetCE);
115     for (i = 0; i < VCSIZE; i++) {
116         for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
117             if (a_index == 0)
118                 goto searchDone;
119             a_index--;
120         } /*Zip through current hash chain*/
121     } /*Zip through hash chains*/
122
123   searchDone:
124     if (tvc == (struct vcache *) 0) {
125         /*Past EOF*/
126         code = 1;
127         goto fcnDone;
128     }
129
130     /*
131      * Copy out the located entry.
132      */
133     a_result->addr = afs_data_pointer_to_int32(tvc);
134     a_result->cell = tvc->fid.Cell;
135     a_result->netFid.Volume = tvc->fid.Fid.Volume;
136     a_result->netFid.Vnode = tvc->fid.Fid.Vnode;
137     a_result->netFid.Unique = tvc->fid.Fid.Unique;
138     a_result->lock.waitStates = tvc->lock.wait_states;
139     a_result->lock.exclLocked = tvc->lock.excl_locked;
140     a_result->lock.readersReading = tvc->lock.readers_reading;
141     a_result->lock.numWaiting = tvc->lock.num_waiting;
142 #if defined(INSTRUMENT_LOCKS)
143     a_result->lock.pid_last_reader = tvc->lock.pid_last_reader;
144     a_result->lock.pid_writer = tvc->lock.pid_writer;
145     a_result->lock.src_indicator = tvc->lock.src_indicator;
146 #else
147     /* On osf20 , the vcache does not maintain these three fields */
148     a_result->lock.pid_last_reader = 0;
149     a_result->lock.pid_writer = 0;
150     a_result->lock.src_indicator = 0;
151 #endif /* AFS_OSF20_ENV */
152     a_result->Length = tvc->m.Length;
153     a_result->DataVersion = hgetlo(tvc->m.DataVersion);
154     a_result->callback = afs_data_pointer_to_int32(tvc->callback);              /* XXXX Now a pointer; change it XXXX */
155     a_result->cbExpires = tvc->cbExpires;
156     a_result->refCount = tvc->vrefCount;
157     a_result->opens = tvc->opens;
158     a_result->writers = tvc->execsOrWriters;
159     a_result->mvstat = tvc->mvstat;
160     a_result->states = tvc->states;
161     code = 0;
162
163     /*
164      * Return our results.
165      */
166 fcnDone:
167     XSTATS_END_TIME;
168
169 #ifdef RX_ENABLE_LOCKS
170     AFS_GUNLOCK();
171 #endif /* RX_ENABLE_LOCKS */
172
173     return(code);
174
175 } /*SRXAFSCB_GetCE*/
176
177
178 /*------------------------------------------------------------------------
179  * EXPORTED SRXAFSCB_GetLock
180  *
181  * Description:
182  *      Routine called by the server-side callback RPC interface to
183  *      implement pulling out the contents of a lock in the lock
184  *      table.
185  *
186  * Arguments:
187  *      a_call   : Ptr to Rx call on which this request came in.
188  *      a_index  : Index of desired lock.
189  *      a_result : Ptr to a buffer for the given lock.
190  *
191  * Returns:
192  *      0 if everything went fine,
193  *      1 if we were given a bad index.
194  *
195  * Environment:
196  *      Nothing interesting.
197  *
198  * Side Effects:
199  *      As advertised.
200  *------------------------------------------------------------------------*/
201
202 int SRXAFSCB_GetLock (a_call, a_index, a_result)
203     struct rx_call *a_call;
204     afs_int32 a_index;
205     struct AFSDBLock *a_result;
206
207 { /*SRXAFSCB_GetLock*/
208
209     struct ltable *tl;          /*Ptr to lock table entry*/
210     int nentries;               /*Num entries in table*/
211     int code;                   /*Return code*/
212     XSTATS_DECLS;
213
214 #ifdef RX_ENABLE_LOCKS
215     AFS_GLOCK();
216 #endif /* RX_ENABLE_LOCKS */
217
218     XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_GETLOCK);
219     
220     AFS_STATCNT(SRXAFSCB_GetLock);
221     nentries = sizeof(ltable)/sizeof(struct ltable);
222     if (a_index < 0 || a_index >= nentries) {
223         /*
224           * Past EOF
225           */
226         code = 1;
227     }
228     else {
229         /*
230          * Found it - copy out its contents.
231          */
232         tl = &ltable[a_index];
233         strcpy(a_result->name, tl->name);
234         a_result->lock.waitStates = ((struct afs_lock *)(tl->addr))->wait_states;
235         a_result->lock.exclLocked = ((struct afs_lock *)(tl->addr))->excl_locked;
236         a_result->lock.readersReading = ((struct afs_lock *)(tl->addr))->readers_reading;
237         a_result->lock.numWaiting = ((struct afs_lock *)(tl->addr))->num_waiting;
238         a_result->lock.pid_last_reader = ((struct afs_lock *)(tl->addr))->pid_last_reader;
239         a_result->lock.pid_writer = ((struct afs_lock *)(tl->addr))->pid_writer;
240         a_result->lock.src_indicator = ((struct afs_lock *)(tl->addr))->src_indicator;
241         code = 0;
242     }
243
244     XSTATS_END_TIME;
245
246 #ifdef RX_ENABLE_LOCKS
247     AFS_GUNLOCK();
248 #endif /* RX_ENABLE_LOCKS */
249
250     return(code);
251
252 }  /*SRXAFSCB_GetLock*/
253
254
255 /*------------------------------------------------------------------------
256  * static ClearCallBack
257  *
258  * Description:
259  *      Clear out callback information for the specified file, or
260  *      even a whole volume.  Used to worry about callback was from 
261  *      within the particular cell or not.  Now we don't bother with
262  *      that anymore; it's not worth the time.
263  *
264  * Arguments:
265  *      a_conn : Ptr to Rx connection involved.
266  *      a_fid  : Ptr to AFS fid being cleared.
267  *
268  * Returns:
269  *      0 (always)
270  *
271  * Environment:
272  *      Nothing interesting.
273  *
274  * Side Effects:
275  *      As advertised.
276  *------------------------------------------------------------------------*/
277
278 static ClearCallBack(a_conn, a_fid)
279     register struct rx_connection *a_conn;
280     register struct AFSFid *a_fid;
281
282 { /*ClearCallBack*/
283
284     register struct vcache *tvc;
285     register int i;
286     struct VenusFid localFid;
287     struct volume * tv;
288
289     AFS_STATCNT(ClearCallBack);
290
291     /*
292      * XXXX Don't hold any server locks here because of callback protocol XXX
293      */
294     localFid.Cell = 0;
295     localFid.Fid.Volume = a_fid->Volume;
296     localFid.Fid.Vnode = a_fid->Vnode;
297     localFid.Fid.Unique = a_fid->Unique;
298
299     /*
300       * Volume ID of zero means don't do anything.
301       */
302     if (a_fid->Volume != 0) {
303         if (a_fid->Vnode == 0) {
304             /*
305              * Clear callback for the whole volume.  Zip through the
306              * hash chain, nullifying entries whose volume ID matches.
307              */
308             for (i = 0; i < VCSIZE; i++)
309                 for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
310                     if (tvc->fid.Fid.Volume == a_fid->Volume) {
311                         tvc->callback = (struct server *)0;
312                         tvc->quick.stamp = 0; 
313                         if (!localFid.Cell)
314                             localFid.Cell = tvc->fid.Cell;
315                         tvc->h1.dchint = NULL; /* invalidate hints */
316                         ObtainWriteLock(&afs_xcbhash, 449);
317                         afs_DequeueCallback(tvc);
318                         tvc->states &= ~(CStatd | CUnique | CBulkFetching);
319                         afs_allCBs++;
320                         if (tvc->fid.Fid.Vnode & 1)
321                           afs_oddCBs++; 
322                         else
323                           afs_evenCBs++; 
324                         ReleaseWriteLock(&afs_xcbhash);
325                         if (tvc->fid.Fid.Vnode & 1 || (vType(tvc) == VDIR))
326                             osi_dnlc_purgedp(tvc);
327                         afs_Trace3(afs_iclSetp, CM_TRACE_CALLBACK,
328                                    ICL_TYPE_POINTER, tvc, 
329                                    ICL_TYPE_INT32, tvc->states,
330                                    ICL_TYPE_INT32, a_fid->Volume);
331                     } else if ((tvc->states & CMValid) && (tvc->mvid->Fid.Volume == a_fid->Volume)) {
332                         tvc->states &= ~CMValid;
333                         if (!localFid.Cell)
334                             localFid.Cell = tvc->mvid->Cell;
335                     }
336                 }
337
338             /*
339              * XXXX Don't hold any locks here XXXX
340              */
341             tv = afs_FindVolume(&localFid, 0);
342             if (tv) {
343               afs_ResetVolumeInfo(tv);
344               afs_PutVolume(tv, 0);
345               /* invalidate mtpoint? */
346             }
347         } /*Clear callbacks for whole volume*/
348         else {
349             /*
350              * Clear callbacks just for the one file.
351              */
352             afs_allCBs++;
353             if (a_fid->Vnode & 1)
354                 afs_oddCBs++;   /*Could do this on volume basis, too*/
355             else
356                 afs_evenCBs++; /*A particular fid was specified*/
357             i = VCHash(&localFid);
358             for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
359                 if (tvc->fid.Fid.Vnode == a_fid->Vnode
360                     && tvc->fid.Fid.Volume == a_fid->Volume
361                     && tvc->fid.Fid.Unique == a_fid->Unique ) {
362                     tvc->callback = (struct server *)0;
363                     tvc->quick.stamp = 0; 
364                     tvc->h1.dchint = NULL; /* invalidate hints */
365                     ObtainWriteLock(&afs_xcbhash, 450);
366                     afs_DequeueCallback(tvc);
367                     tvc->states &= ~(CStatd | CUnique | CBulkFetching);
368                     ReleaseWriteLock(&afs_xcbhash);
369                     if (a_fid->Vnode & 1 || (vType(tvc) == VDIR))
370                         osi_dnlc_purgedp(tvc);
371                     afs_Trace3(afs_iclSetp, CM_TRACE_CALLBACK,
372                                ICL_TYPE_POINTER, tvc, 
373                                ICL_TYPE_INT32, tvc->states, ICL_TYPE_LONG, 0);
374 #ifdef CBDEBUG
375                     lastCallBack_vnode = afid->Vnode;
376                     lastCallBack_dv = tvc->mstat.DataVersion.low;
377                     osi_GetuTime(&lastCallBack_time);
378 #endif /* CBDEBUG */
379                 }
380             } /*Walk through hash table*/
381         } /*Clear callbacks for one file*/
382     } /*Fid has non-zero volume ID*/
383
384     /*
385      * Always return a predictable value.
386      */
387     return(0);
388
389 } /*ClearCallBack*/
390
391
392 /*------------------------------------------------------------------------
393  * EXPORTED SRXAFSCB_CallBack
394  *
395  * Description:
396  *      Routine called by the server-side callback RPC interface to
397  *      implement passing in callback information.
398  *      table.
399  *
400  * Arguments:
401  *      a_call      : Ptr to Rx call on which this request came in.
402  *      a_fids      : Ptr to array of fids involved.
403  *      a_callbacks : Ptr to matching callback info for the fids.
404  *
405  * Returns:
406  *      0 (always).
407  *
408  * Environment:
409  *      Nothing interesting.
410  *
411  * Side Effects:
412  *      As advertised.
413  *------------------------------------------------------------------------*/
414
415 int SRXAFSCB_CallBack(a_call, a_fids, a_callbacks)
416     struct rx_call *a_call;
417     register struct AFSCBFids *a_fids;
418     struct AFSCBs *a_callbacks;
419     
420 { /*SRXAFSCB_CallBack*/
421
422     register int i;                         /*Loop variable*/
423     struct AFSFid *tfid;                    /*Ptr to current fid*/
424     register struct rx_connection *tconn;   /*Call's connection*/
425     int code=0;
426     XSTATS_DECLS;
427
428 #ifdef RX_ENABLE_LOCKS
429     AFS_GLOCK();
430 #endif /* RX_ENABLE_LOCKS */
431
432     XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_CALLBACK);
433
434     AFS_STATCNT(SRXAFSCB_CallBack);
435     if (!(tconn = rx_ConnectionOf(a_call))) return;
436     tfid = (struct AFSFid *) a_fids->AFSCBFids_val;
437     
438     /*
439      * For now, we ignore callbacks, since the File Server only *breaks*
440      * callbacks at present.
441      */
442     for (i = 0; i < a_fids->AFSCBFids_len; i++) 
443         ClearCallBack(tconn, &tfid[i]);
444
445     XSTATS_END_TIME;
446
447 #ifdef RX_ENABLE_LOCKS
448     AFS_GUNLOCK();
449 #endif /* RX_ENABLE_LOCKS */
450     
451     return(0);
452
453 } /*SRXAFSCB_CallBack*/
454
455
456 /*------------------------------------------------------------------------
457  * EXPORTED SRXAFSCB_Probe
458  *
459  * Description:
460  *      Routine called by the server-side callback RPC interface to
461  *      implement ``probing'' the Cache Manager, just making sure it's
462  *      still there.
463  *
464  * Arguments:
465  *      a_call : Ptr to Rx call on which this request came in.
466  *
467  * Returns:
468  *      0 (always).
469  *
470  * Environment:
471  *      Nothing interesting.
472  *
473  * Side Effects:
474  *      As advertised.
475  *------------------------------------------------------------------------*/
476
477 int SRXAFSCB_Probe(a_call)
478     struct rx_call *a_call;
479
480 { /*SRXAFSCB_Probe*/
481     int code = 0;
482     XSTATS_DECLS;
483
484 #ifdef RX_ENABLE_LOCKS
485     AFS_GLOCK();
486 #endif /* RX_ENABLE_LOCKS */
487     AFS_STATCNT(SRXAFSCB_Probe);
488
489     XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_PROBE);
490     XSTATS_END_TIME;
491
492 #ifdef RX_ENABLE_LOCKS
493     AFS_GUNLOCK();
494 #endif /* RX_ENABLE_LOCKS */
495
496     return(0);
497
498 } /*SRXAFSCB_Probe*/
499
500
501 /*------------------------------------------------------------------------
502  * EXPORTED SRXAFSCB_InitCallBackState
503  *
504  * Description:
505  *      Routine called by the server-side callback RPC interface to
506  *      implement clearing all callbacks from this host.
507  *
508  * Arguments:
509  *      a_call : Ptr to Rx call on which this request came in.
510  *
511  * Returns:
512  *      0 (always).
513  *
514  * Environment:
515  *      Nothing interesting.
516  *
517  * Side Effects:
518  *      As advertised.
519  *------------------------------------------------------------------------*/
520
521 int SRXAFSCB_InitCallBackState(a_call)
522     struct rx_call *a_call;
523
524 { /*SRXAFSCB_InitCallBackState*/
525
526     register int i;
527     register struct vcache *tvc;
528     register struct rx_connection *tconn;
529     register struct rx_peer *peer;
530     struct server *ts;
531     int code = 0;
532     extern int osi_dnlc_purge();
533     XSTATS_DECLS;
534
535 #ifdef RX_ENABLE_LOCKS
536     AFS_GLOCK();
537 #endif /* RX_ENABLE_LOCKS */
538
539     XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_INITCALLBACKSTATE);
540     AFS_STATCNT(SRXAFSCB_InitCallBackState);
541
542     /*
543      * Find the address of the host making this call
544      */
545     if ((tconn = rx_ConnectionOf(a_call)) && (peer = rx_PeerOf(tconn))) {
546
547         afs_allCBs++;
548         afs_oddCBs++;   /*Including any missed via create race*/
549         afs_evenCBs++;  /*Including any missed via create race*/
550
551         ts = afs_FindServer(rx_HostOf(peer), rx_PortOf(peer), (afsUUID *)0, 0);
552         if (ts) {
553             for (i = 0; i < VCSIZE; i++)
554                 for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
555                     if (tvc->callback == ts) {
556                         ObtainWriteLock(&afs_xcbhash, 451);
557                         afs_DequeueCallback(tvc);
558                         tvc->callback = (struct server *)0;
559                         tvc->states &= ~(CStatd | CUnique | CBulkFetching);
560                         ReleaseWriteLock(&afs_xcbhash);
561                     }
562                 }
563         }
564
565       
566  
567         /* find any volumes residing on this server and flush their state */
568         {
569             register struct volume *tv;
570             register int j;
571         
572             for (i=0;i<NVOLS;i++) 
573                 for (tv = afs_volumes[i]; tv; tv=tv->next) {
574                     for (j=0; j<MAXHOSTS; j++)
575                         if (tv->serverHost[j] == ts)
576                             afs_ResetVolumeInfo(tv);
577                 }
578         }
579         osi_dnlc_purge(); /* may be a little bit extreme */
580     }
581
582     XSTATS_END_TIME;
583
584 #ifdef RX_ENABLE_LOCKS
585     AFS_GUNLOCK();
586 #endif /* RX_ENABLE_LOCKS */
587
588     return(0);
589
590 } /*SRXAFSCB_InitCallBackState*/
591
592
593 /*------------------------------------------------------------------------
594  * EXPORTED SRXAFSCB_XStatsVersion
595  *
596  * Description:
597  *      Routine called by the server-side callback RPC interface to
598  *      implement pulling out the xstat version number for the Cache
599  *      Manager.
600  *
601  * Arguments:
602  *      a_versionP : Ptr to the version number variable to set.
603  *
604  * Returns:
605  *      0 (always)
606  *
607  * Environment:
608  *      Nothing interesting.
609  *
610  * Side Effects:
611  *      As advertised.
612  *------------------------------------------------------------------------*/
613
614 int SRXAFSCB_XStatsVersion(a_call, a_versionP)
615     struct rx_call *a_call;
616     afs_int32 *a_versionP;
617
618 { /*SRXAFSCB_XStatsVersion*/
619    int code=0;
620
621     XSTATS_DECLS;
622
623 #ifdef RX_ENABLE_LOCKS
624     AFS_GLOCK();
625 #endif /* RX_ENABLE_LOCKS */
626     XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_XSTATSVERSION);
627
628     *a_versionP = AFSCB_XSTAT_VERSION;
629
630     XSTATS_END_TIME;
631
632 #ifdef RX_ENABLE_LOCKS
633     AFS_GUNLOCK();
634 #endif /* RX_ENABLE_LOCKS */
635
636     return(0);
637 }  /*SRXAFSCB_XStatsVersion*/
638
639
640 /*------------------------------------------------------------------------
641  * EXPORTED SRXAFSCB_GetXStats
642  *
643  * Description:
644  *      Routine called by the server-side callback RPC interface to
645  *      implement getting the given data collection from the extended
646  *      Cache Manager statistics.
647  *
648  * Arguments:
649  *      a_call              : Ptr to Rx call on which this request came in.
650  *      a_clientVersionNum  : Client version number.
651  *      a_opCode            : Desired operation.
652  *      a_serverVersionNumP : Ptr to version number to set.
653  *      a_timeP             : Ptr to time value (seconds) to set.
654  *      a_dataArray         : Ptr to variable array structure to return
655  *                            stuff in.
656  *
657  * Returns:
658  *      0 (always).
659  *
660  * Environment:
661  *      Nothing interesting.
662  *
663  * Side Effects:
664  *      As advertised.
665  *------------------------------------------------------------------------*/
666
667 int SRXAFSCB_GetXStats(a_call, a_clientVersionNum, a_collectionNumber, a_srvVersionNumP, a_timeP, a_dataP)
668     struct rx_call *a_call;
669     afs_int32 a_clientVersionNum;
670     afs_int32 a_collectionNumber;
671     afs_int32 *a_srvVersionNumP;
672     afs_int32 *a_timeP;
673     AFSCB_CollData *a_dataP;
674
675 { /*SRXAFSCB_GetXStats*/
676
677     register int code;          /*Return value*/
678     afs_int32 *dataBuffP;               /*Ptr to data to be returned*/
679     afs_int32 dataBytes;                /*Bytes in data buffer*/
680     XSTATS_DECLS;
681
682 #ifdef RX_ENABLE_LOCKS
683     AFS_GLOCK();
684 #endif /* RX_ENABLE_LOCKS */
685
686     XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_GETXSTATS);
687
688     /*
689      * Record the time of day and the server version number.
690      */
691     *a_srvVersionNumP = AFSCB_XSTAT_VERSION;
692     *a_timeP = osi_Time();
693
694     /*
695      * Stuff the appropriate data in there (assume victory)
696      */
697     code = 0;
698
699 #ifdef AFS_NOSTATS
700     /*
701      * We're not keeping stats, so just return successfully with
702      * no data.
703      */
704     a_dataP->AFSCB_CollData_len = 0;
705     a_dataP->AFSCB_CollData_val = (afs_int32 *)0;
706 #else
707     switch(a_collectionNumber) {
708       case AFSCB_XSTATSCOLL_CALL_INFO:
709         /*
710          * Pass back all the call-count-related data.
711          *
712          * >>> We are forced to allocate a separate area in which to
713          * >>> put this stuff in by the RPC stub generator, since it
714          * >>> will be freed at the tail end of the server stub code.
715          */
716         dataBytes = sizeof(struct afs_CMStats);
717         dataBuffP = (afs_int32 *)afs_osi_Alloc(dataBytes);
718         bcopy((char *)&afs_cmstats, (char *)dataBuffP, dataBytes);
719         a_dataP->AFSCB_CollData_len = dataBytes>>2;
720         a_dataP->AFSCB_CollData_val = dataBuffP;
721         break;
722
723       case AFSCB_XSTATSCOLL_PERF_INFO:
724         /*
725          * Update and then pass back all the performance-related data.
726          * Note: the only performance fields that need to be computed
727          * at this time are the number of accesses for this collection
728          * and the current server record info.
729          *
730          * >>> We are forced to allocate a separate area in which to
731          * >>> put this stuff in by the RPC stub generator, since it
732          * >>> will be freed at the tail end of the server stub code.
733          */
734         afs_stats_cmperf.numPerfCalls++;
735         afs_CountServers();
736         dataBytes = sizeof(afs_stats_cmperf);
737         dataBuffP = (afs_int32 *)afs_osi_Alloc(dataBytes);
738         bcopy((char *)&afs_stats_cmperf, (char *)dataBuffP, dataBytes);
739         a_dataP->AFSCB_CollData_len = dataBytes>>2;
740         a_dataP->AFSCB_CollData_val = dataBuffP;
741         break;
742
743       case AFSCB_XSTATSCOLL_FULL_PERF_INFO:
744         /*
745          * Pass back the full range of performance and statistical
746          * data available.  We have to bring the normal performance
747          * data collection up to date, then copy that data into
748          * the full collection.
749          *
750          * >>> We are forced to allocate a separate area in which to
751          * >>> put this stuff in by the RPC stub generator, since it
752          * >>> will be freed at the tail end of the server stub code.
753          */
754         afs_stats_cmperf.numPerfCalls++;
755         afs_CountServers();
756         bcopy((char *)(&afs_stats_cmperf),
757               (char *)(&(afs_stats_cmfullperf.perf)),
758               sizeof(struct afs_stats_CMPerf));
759         afs_stats_cmfullperf.numFullPerfCalls++;
760
761         dataBytes = sizeof(afs_stats_cmfullperf);
762         dataBuffP = (afs_int32 *)afs_osi_Alloc(dataBytes);
763         bcopy((char *)(&afs_stats_cmfullperf), (char *)dataBuffP, dataBytes);
764         a_dataP->AFSCB_CollData_len = dataBytes>>2;
765         a_dataP->AFSCB_CollData_val = dataBuffP;
766         break;
767
768       default:
769         /*
770          * Illegal collection number.
771          */
772         a_dataP->AFSCB_CollData_len = 0;
773         a_dataP->AFSCB_CollData_val = (afs_int32 *)0;
774         code = 1;
775     } /*Switch on collection number*/
776 #endif /* AFS_NOSTATS */
777
778     XSTATS_END_TIME;
779
780 #ifdef RX_ENABLE_LOCKS
781     AFS_GUNLOCK();
782 #endif /* RX_ENABLE_LOCKS */
783
784     return(code);
785
786 } /*SRXAFSCB_GetXStats*/
787
788
789 /*------------------------------------------------------------------------
790  * EXPORTED afs_RXCallBackServer
791  *
792  * Description:
793  *      Body of the thread supporting callback services.
794  *
795  * Arguments:
796  *      None.
797  *
798  * Returns:
799  *      0 (always).
800  *
801  * Environment:
802  *      Nothing interesting.
803  *
804  * Side Effects:
805  *      As advertised.
806  *------------------------------------------------------------------------*/
807
808 int afs_RXCallBackServer()
809
810 { /*afs_RXCallBackServer*/
811     AFS_STATCNT(afs_RXCallBackServer);
812
813     while (1) {
814         if (afs_server)
815             break;
816         afs_osi_Sleep(&afs_server);
817     }
818
819     /*
820      * Donate this process to Rx.
821      */
822     rx_ServerProc();
823     return(0);
824
825 } /*afs_RXCallBackServer*/
826
827
828 /*------------------------------------------------------------------------
829  * EXPORTED shutdown_CB
830  *
831  * Description:
832  *      Zero out important Cache Manager data structures.
833  *
834  * Arguments:
835  *      None.
836  *
837  * Returns:
838  *      0 (always).
839  *
840  * Environment:
841  *      Nothing interesting.
842  *
843  * Side Effects:
844  *      As advertised.
845  *------------------------------------------------------------------------*/
846
847 int shutdown_CB() 
848
849 { /*shutdown_CB*/
850
851   extern int afs_cold_shutdown;
852
853   AFS_STATCNT(shutdown_CB);
854
855   if (afs_cold_shutdown) {
856     afs_oddCBs = afs_evenCBs = afs_allCBs = afs_allZaps = afs_oddZaps = afs_evenZaps =
857         afs_connectBacks = 0;
858   }
859
860   return(0);
861
862 } /*shutdown_CB*/
863
864 /*------------------------------------------------------------------------
865  * EXPORTED SRXAFSCB_InitCallBackState2
866  *
867  * Description:
868  *      This routine was used in the AFS 3.5 beta release, but not anymore.
869  *      It has since been replaced by SRXAFSCB_InitCallBackState3.
870  *
871  * Arguments:
872  *      a_call : Ptr to Rx call on which this request came in.
873  *
874  * Returns:
875  *      RXGEN_OPCODE (always). 
876  *
877  * Environment:
878  *      Nothing interesting.
879  *
880  * Side Effects:
881  *      None
882  *------------------------------------------------------------------------*/
883
884 int SRXAFSCB_InitCallBackState2(a_call, addr)
885 struct rx_call *a_call;
886 struct interfaceAddr * addr;
887 {
888         return RXGEN_OPCODE;
889 }
890
891 /*------------------------------------------------------------------------
892  * EXPORTED SRXAFSCB_WhoAreYou
893  *
894  * Description:
895  *      Routine called by the server-side callback RPC interface to
896  *      obtain a unique identifier for the client. The server uses
897  *      this identifier to figure out whether or not two RX connections
898  *      are from the same client, and to find out which addresses go
899  *      with which clients.
900  *
901  * Arguments:
902  *      a_call : Ptr to Rx call on which this request came in.
903  *      addr: Ptr to return the list of interfaces for this client.
904  *
905  * Returns:
906  *      0 (Always)
907  *
908  * Environment:
909  *      Nothing interesting.
910  *
911  * Side Effects:
912  *      As advertised.
913  *------------------------------------------------------------------------*/
914
915 int SRXAFSCB_WhoAreYou(a_call, addr)
916 struct rx_call *a_call;
917 struct interfaceAddr *addr;
918 {
919     int i;
920     int code = 0;
921     XSTATS_DECLS;
922
923 #ifdef RX_ENABLE_LOCKS
924     AFS_GLOCK();
925 #endif /* RX_ENABLE_LOCKS */
926
927     AFS_STATCNT(SRXAFSCB_WhoAreYou);
928
929     ObtainReadLock(&afs_xinterface);
930
931     /* return all network interface addresses */
932     addr->numberOfInterfaces = afs_cb_interface.numberOfInterfaces;
933     addr->uuid = afs_cb_interface.uuid;
934     for ( i=0; i < afs_cb_interface.numberOfInterfaces; i++) {
935         addr->addr_in[i] = ntohl(afs_cb_interface.addr_in[i]);
936         addr->subnetmask[i] = ntohl(afs_cb_interface.subnetmask[i]);
937         addr->mtu[i] = ntohl(afs_cb_interface.mtu[i]);
938     }
939
940     ReleaseReadLock(&afs_xinterface);
941
942 #ifdef RX_ENABLE_LOCKS
943     AFS_GUNLOCK();
944 #endif /* RX_ENABLE_LOCKS */
945
946     return code;
947 }
948
949
950 /*------------------------------------------------------------------------
951  * EXPORTED SRXAFSCB_InitCallBackState3
952  *
953  * Description:
954  *      Routine called by the server-side callback RPC interface to
955  *      implement clearing all callbacks from this host.
956  *
957  * Arguments:
958  *      a_call : Ptr to Rx call on which this request came in.
959  *
960  * Returns:
961  *      0 (always).
962  *
963  * Environment:
964  *      Nothing interesting.
965  *
966  * Side Effects:
967  *      As advertised.
968  *------------------------------------------------------------------------*/
969
970 int SRXAFSCB_InitCallBackState3(a_call, a_uuid)
971 struct rx_call *a_call;
972 afsUUID *a_uuid;
973 {
974     int code;
975
976     /*
977      * TBD: Lookup the server by the UUID instead of its IP address.
978      */
979     code = SRXAFSCB_InitCallBackState(a_call);
980
981     return code;
982 }
983  
984
985 /*------------------------------------------------------------------------
986  * EXPORTED SRXAFSCB_ProbeUuid
987  *
988  * Description:
989  *      Routine called by the server-side callback RPC interface to
990  *      implement ``probing'' the Cache Manager, just making sure it's
991  *      still there is still the same client it used to be.
992  *
993  * Arguments:
994  *      a_call : Ptr to Rx call on which this request came in.
995  *      a_uuid : Ptr to UUID that must match the client's UUID.
996  *
997  * Returns:
998  *      0 if a_uuid matches the UUID for this client
999  *      Non-zero otherwize
1000  *
1001  * Environment:
1002  *      Nothing interesting.
1003  *
1004  * Side Effects:
1005  *      As advertised.
1006  *------------------------------------------------------------------------*/
1007
1008 int SRXAFSCB_ProbeUuid(a_call, a_uuid)
1009 struct rx_call *a_call;
1010 afsUUID *a_uuid;
1011 {
1012     int code = 0;
1013     XSTATS_DECLS;
1014
1015 #ifdef RX_ENABLE_LOCKS
1016     AFS_GLOCK();
1017 #endif /* RX_ENABLE_LOCKS */
1018     AFS_STATCNT(SRXAFSCB_Probe);
1019
1020     XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_PROBE);
1021     if (!afs_uuid_equal(a_uuid, &afs_cb_interface.uuid))
1022         code = 1; /* failure */
1023     XSTATS_END_TIME;
1024
1025 #ifdef RX_ENABLE_LOCKS
1026     AFS_GUNLOCK();
1027 #endif /* RX_ENABLE_LOCKS */
1028
1029     return code;
1030 }
1031  
1032
1033 /*------------------------------------------------------------------------
1034  * EXPORTED SRXAFSCB_GetServerPrefs
1035  *
1036  * Description:
1037  *      Routine to list server preferences used by this client.
1038  *
1039  * Arguments:
1040  *      a_call  : Ptr to Rx call on which this request came in.
1041  *      a_index : Input server index
1042  *      a_srvr_addr  : Output server address in host byte order
1043  *                     (0xffffffff on last server)
1044  *      a_srvr_rank  : Output server rank
1045  *
1046  * Returns:
1047  *      0 on success
1048  *
1049  * Environment:
1050  *      Nothing interesting.
1051  *
1052  * Side Effects:
1053  *      As advertised.
1054  *------------------------------------------------------------------------*/
1055
1056 int SRXAFSCB_GetServerPrefs(
1057     struct rx_call *a_call,
1058     afs_int32 a_index,
1059     afs_int32 *a_srvr_addr,
1060     afs_int32 *a_srvr_rank)
1061 {
1062     int i, j;
1063     struct srvAddr *sa;
1064
1065 #ifdef RX_ENABLE_LOCKS
1066     AFS_GLOCK();
1067 #endif /* RX_ENABLE_LOCKS */
1068     AFS_STATCNT(SRXAFSCB_GetServerPrefs);
1069
1070     ObtainReadLock(&afs_xserver);
1071
1072     /* Search the hash table for the server with this index */
1073     *a_srvr_addr = 0xffffffff;
1074     *a_srvr_rank = 0xffffffff;
1075     for (i=0, j=0; j < NSERVERS && i <= a_index; j++) {
1076         for (sa = afs_srvAddrs[j]; sa && i <= a_index; sa = sa->next_bkt, i++) {
1077             if (i == a_index) {
1078                 *a_srvr_addr = ntohl(sa->sa_ip);
1079                 *a_srvr_rank = sa->sa_iprank;
1080             }
1081         }
1082     }
1083
1084     ReleaseReadLock(&afs_xserver);
1085
1086 #ifdef RX_ENABLE_LOCKS
1087     AFS_GUNLOCK();
1088 #endif /* RX_ENABLE_LOCKS */
1089
1090     return 0;
1091 }
1092  
1093
1094 /*------------------------------------------------------------------------
1095  * EXPORTED SRXAFSCB_GetCellServDB
1096  *
1097  * Description:
1098  *      Routine to list cells configured for this client
1099  *
1100  * Arguments:
1101  *      a_call  : Ptr to Rx call on which this request came in.
1102  *      a_index : Input cell index
1103  *      a_name  : Output cell name ("" on last cell)
1104  *      a_hosts : Output cell database servers in host byte order.
1105  *
1106  * Returns:
1107  *      0 on success
1108  *
1109  * Environment:
1110  *      Nothing interesting.
1111  *
1112  * Side Effects:
1113  *      As advertised.
1114  *------------------------------------------------------------------------*/
1115
1116 int SRXAFSCB_GetCellServDB(
1117     struct rx_call *a_call,
1118     afs_int32 a_index,
1119     char **a_name,
1120     afs_int32 *a_hosts)
1121 {
1122     afs_int32 i, j;
1123     struct cell *tcell;
1124     struct afs_q *cq, *tq;
1125     char *t_name;
1126
1127 #ifdef RX_ENABLE_LOCKS
1128     AFS_GLOCK();
1129 #endif /* RX_ENABLE_LOCKS */
1130     AFS_STATCNT(SRXAFSCB_GetCellServDB);
1131
1132     t_name = (char *)rxi_Alloc(AFSNAMEMAX);
1133     if (t_name == NULL) {
1134 #ifdef RX_ENABLE_LOCKS
1135         AFS_GUNLOCK();
1136 #endif /* RX_ENABLE_LOCKS */
1137         return ENOMEM;
1138     }
1139
1140     t_name[0] = '\0';
1141     bzero(a_hosts, AFSMAXCELLHOSTS * sizeof(afs_int32));
1142
1143     /* search the list for the cell with this index */
1144     ObtainReadLock(&afs_xcell);
1145     for (i=0, cq = CellLRU.next; cq != &CellLRU && i<= a_index; cq = tq, i++) {
1146         tq = QNext(cq);
1147         if (i == a_index) {
1148             tcell = QTOC(cq);
1149             strcpy(t_name, tcell->cellName);
1150             for (j = 0 ; j < AFSMAXCELLHOSTS && tcell->cellHosts[j] ; j++) {
1151                 a_hosts[j] = ntohl(tcell->cellHosts[j]->addr->sa_ip);
1152             }
1153         }
1154     }
1155     ReleaseReadLock(&afs_xcell);
1156
1157 #ifdef RX_ENABLE_LOCKS
1158     AFS_GUNLOCK();
1159 #endif /* RX_ENABLE_LOCKS */
1160
1161     *a_name = t_name;
1162     return 0;
1163 }
1164  
1165
1166 /*------------------------------------------------------------------------
1167  * EXPORTED SRXAFSCB_GetLocalCell
1168  *
1169  * Description:
1170  *      Routine to return name of client's local cell
1171  *
1172  * Arguments:
1173  *      a_call  : Ptr to Rx call on which this request came in.
1174  *      a_name  : Output cell name
1175  *
1176  * Returns:
1177  *      0 on success
1178  *
1179  * Environment:
1180  *      Nothing interesting.
1181  *
1182  * Side Effects:
1183  *      As advertised.
1184  *------------------------------------------------------------------------*/
1185
1186 int SRXAFSCB_GetLocalCell(
1187     struct rx_call *a_call,
1188     char **a_name)
1189 {
1190     struct cell *tcell;
1191     struct afs_q *cq, *tq;
1192     char *t_name;
1193
1194 #ifdef RX_ENABLE_LOCKS
1195     AFS_GLOCK();
1196 #endif /* RX_ENABLE_LOCKS */
1197     AFS_STATCNT(SRXAFSCB_GetLocalCell);
1198
1199     t_name = (char *)rxi_Alloc(AFSNAMEMAX);
1200     if (t_name == NULL) {
1201 #ifdef RX_ENABLE_LOCKS
1202         AFS_GUNLOCK();
1203 #endif /* RX_ENABLE_LOCKS */
1204         return ENOMEM;
1205     }
1206
1207     t_name[0] = '\0';
1208
1209     /* Search the list for the primary cell. Cell number 1 is only
1210      * the primary cell is when no other cell is explicitly marked as
1211      * the primary cell.  */
1212     ObtainReadLock(&afs_xcell);
1213     for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
1214         tq = QNext(cq);
1215         tcell = QTOC(cq);
1216         if (tcell->states & CPrimary) {
1217             strcpy(t_name, tcell->cellName);
1218             break;
1219         }
1220         if (tcell->cell == 1) {
1221             strcpy(t_name, tcell->cellName);
1222         }
1223     }
1224     ReleaseReadLock(&afs_xcell);
1225
1226 #ifdef RX_ENABLE_LOCKS
1227     AFS_GUNLOCK();
1228 #endif /* RX_ENABLE_LOCKS */
1229
1230     *a_name = t_name;
1231     return 0;
1232 }
1233
1234
1235 /*
1236  * afs_MarshallCacheConfig - marshall client cache configuration
1237  *
1238  * PARAMETERS
1239  *
1240  * IN callerVersion - the rpc stat version of the caller.
1241  *
1242  * IN config - client cache configuration.
1243  *
1244  * OUT ptr - buffer where configuration is marshalled.
1245  *
1246  * RETURN CODES
1247  *
1248  * Returns void.
1249  */
1250 static void afs_MarshallCacheConfig(
1251     afs_uint32 callerVersion,
1252     cm_initparams_v1 *config,
1253     afs_uint32 *ptr)
1254 {
1255     AFS_STATCNT(afs_MarshallCacheConfig);
1256     /*
1257      * We currently only support version 1.
1258      */
1259     *(ptr++) = config->nChunkFiles;
1260     *(ptr++) = config->nStatCaches;
1261     *(ptr++) = config->nDataCaches;
1262     *(ptr++) = config->nVolumeCaches;
1263     *(ptr++) = config->firstChunkSize;
1264     *(ptr++) = config->otherChunkSize;
1265     *(ptr++) = config->cacheSize;
1266     *(ptr++) = config->setTime;
1267     *(ptr++) = config->memCache;
1268
1269 }
1270  
1271
1272 /*------------------------------------------------------------------------
1273  * EXPORTED SRXAFSCB_GetCacheConfig
1274  *
1275  * Description:
1276  *      Routine to return parameters used to initialize client cache.
1277  *      Client may request any format version. Server may not return
1278  *      format version greater than version requested by client.
1279  *
1280  * Arguments:
1281  *      a_call:        Ptr to Rx call on which this request came in.
1282  *      callerVersion: Data format version desired by the client.
1283  *      serverVersion: Data format version of output data.
1284  *      configCount:   Number bytes allocated for output data.
1285  *      config:        Client cache configuration.
1286  *
1287  * Returns:
1288  *      0 on success
1289  *
1290  * Environment:
1291  *      Nothing interesting.
1292  *
1293  * Side Effects:
1294  *      As advertised.
1295  *------------------------------------------------------------------------*/
1296
1297 int SRXAFSCB_GetCacheConfig(
1298     struct rx_call *a_call,
1299     afs_uint32 callerVersion,
1300     afs_uint32 *serverVersion,
1301     afs_uint32 *configCount,
1302     cacheConfig *config)
1303 {
1304     afs_uint32 *t_config;
1305     size_t allocsize;
1306     cm_initparams_v1 cm_config;
1307
1308 #ifdef RX_ENABLE_LOCKS
1309     AFS_GLOCK();
1310 #endif /* RX_ENABLE_LOCKS */
1311     AFS_STATCNT(SRXAFSCB_GetCacheConfig);
1312
1313     /*
1314      * Currently only support version 1
1315      */
1316     allocsize = sizeof(cm_initparams_v1);
1317     t_config = (afs_uint32 *)rxi_Alloc(allocsize);
1318     if (t_config == NULL) {
1319 #ifdef RX_ENABLE_LOCKS
1320         AFS_GUNLOCK();
1321 #endif /* RX_ENABLE_LOCKS */
1322         return ENOMEM;
1323     }
1324
1325     cm_config.nChunkFiles = cm_initParams.cmi_nChunkFiles;
1326     cm_config.nStatCaches = cm_initParams.cmi_nStatCaches;
1327     cm_config.nDataCaches = cm_initParams.cmi_nDataCaches;
1328     cm_config.nVolumeCaches = cm_initParams.cmi_nVolumeCaches;
1329     cm_config.firstChunkSize = cm_initParams.cmi_firstChunkSize;
1330     cm_config.otherChunkSize = cm_initParams.cmi_otherChunkSize;
1331     cm_config.cacheSize = cm_initParams.cmi_cacheSize;
1332     cm_config.setTime = cm_initParams.cmi_setTime;
1333     cm_config.memCache = cm_initParams.cmi_memCache;
1334
1335     afs_MarshallCacheConfig(callerVersion, &cm_config, t_config);
1336
1337     *serverVersion = AFS_CLIENT_RETRIEVAL_FIRST_EDITION;
1338     *configCount = allocsize;
1339     config->cacheConfig_val = t_config;
1340     config->cacheConfig_len = allocsize/sizeof(afs_uint32);
1341
1342 #ifdef RX_ENABLE_LOCKS
1343     AFS_GUNLOCK();
1344 #endif /* RX_ENABLE_LOCKS */
1345
1346     return 0;
1347 }