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