c43d92c50dbbb32402921ff6a955d9ca998a1db5
[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         memcpy((char *)dataBuffP, (char *)&afs_cmstats, 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         memcpy((char *)dataBuffP, (char *)&afs_stats_cmperf, 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         memcpy((char *)(&(afs_stats_cmfullperf.perf)), (char *)(&afs_stats_cmperf), sizeof(struct afs_stats_CMPerf));
761         afs_stats_cmfullperf.numFullPerfCalls++;
762
763         dataBytes = sizeof(afs_stats_cmfullperf);
764         dataBuffP = (afs_int32 *)afs_osi_Alloc(dataBytes);
765         memcpy((char *)dataBuffP, (char *)(&afs_stats_cmfullperf), dataBytes);
766         a_dataP->AFSCB_CollData_len = dataBytes>>2;
767         a_dataP->AFSCB_CollData_val = dataBuffP;
768         break;
769
770       default:
771         /*
772          * Illegal collection number.
773          */
774         a_dataP->AFSCB_CollData_len = 0;
775         a_dataP->AFSCB_CollData_val = (afs_int32 *)0;
776         code = 1;
777     } /*Switch on collection number*/
778 #endif /* AFS_NOSTATS */
779
780     XSTATS_END_TIME;
781
782 #ifdef RX_ENABLE_LOCKS
783     AFS_GUNLOCK();
784 #endif /* RX_ENABLE_LOCKS */
785
786     return(code);
787
788 } /*SRXAFSCB_GetXStats*/
789
790
791 /*------------------------------------------------------------------------
792  * EXPORTED afs_RXCallBackServer
793  *
794  * Description:
795  *      Body of the thread supporting callback services.
796  *
797  * Arguments:
798  *      None.
799  *
800  * Returns:
801  *      0 (always).
802  *
803  * Environment:
804  *      Nothing interesting.
805  *
806  * Side Effects:
807  *      As advertised.
808  *------------------------------------------------------------------------*/
809
810 int afs_RXCallBackServer()
811
812 { /*afs_RXCallBackServer*/
813     AFS_STATCNT(afs_RXCallBackServer);
814
815     while (1) {
816         if (afs_server)
817             break;
818         afs_osi_Sleep(&afs_server);
819     }
820
821     /*
822      * Donate this process to Rx.
823      */
824     rx_ServerProc();
825     return(0);
826
827 } /*afs_RXCallBackServer*/
828
829
830 /*------------------------------------------------------------------------
831  * EXPORTED shutdown_CB
832  *
833  * Description:
834  *      Zero out important Cache Manager data structures.
835  *
836  * Arguments:
837  *      None.
838  *
839  * Returns:
840  *      0 (always).
841  *
842  * Environment:
843  *      Nothing interesting.
844  *
845  * Side Effects:
846  *      As advertised.
847  *------------------------------------------------------------------------*/
848
849 int shutdown_CB() 
850
851 { /*shutdown_CB*/
852
853   extern int afs_cold_shutdown;
854
855   AFS_STATCNT(shutdown_CB);
856
857   if (afs_cold_shutdown) {
858     afs_oddCBs = afs_evenCBs = afs_allCBs = afs_allZaps = afs_oddZaps = afs_evenZaps =
859         afs_connectBacks = 0;
860   }
861
862   return(0);
863
864 } /*shutdown_CB*/
865
866 /*------------------------------------------------------------------------
867  * EXPORTED SRXAFSCB_InitCallBackState2
868  *
869  * Description:
870  *      This routine was used in the AFS 3.5 beta release, but not anymore.
871  *      It has since been replaced by SRXAFSCB_InitCallBackState3.
872  *
873  * Arguments:
874  *      a_call : Ptr to Rx call on which this request came in.
875  *
876  * Returns:
877  *      RXGEN_OPCODE (always). 
878  *
879  * Environment:
880  *      Nothing interesting.
881  *
882  * Side Effects:
883  *      None
884  *------------------------------------------------------------------------*/
885
886 int SRXAFSCB_InitCallBackState2(a_call, addr)
887 struct rx_call *a_call;
888 struct interfaceAddr * addr;
889 {
890         return RXGEN_OPCODE;
891 }
892
893 /*------------------------------------------------------------------------
894  * EXPORTED SRXAFSCB_WhoAreYou
895  *
896  * Description:
897  *      Routine called by the server-side callback RPC interface to
898  *      obtain a unique identifier for the client. The server uses
899  *      this identifier to figure out whether or not two RX connections
900  *      are from the same client, and to find out which addresses go
901  *      with which clients.
902  *
903  * Arguments:
904  *      a_call : Ptr to Rx call on which this request came in.
905  *      addr: Ptr to return the list of interfaces for this client.
906  *
907  * Returns:
908  *      0 (Always)
909  *
910  * Environment:
911  *      Nothing interesting.
912  *
913  * Side Effects:
914  *      As advertised.
915  *------------------------------------------------------------------------*/
916
917 int SRXAFSCB_WhoAreYou(a_call, addr)
918 struct rx_call *a_call;
919 struct interfaceAddr *addr;
920 {
921     int i;
922     int code = 0;
923     XSTATS_DECLS;
924
925 #ifdef RX_ENABLE_LOCKS
926     AFS_GLOCK();
927 #endif /* RX_ENABLE_LOCKS */
928
929     AFS_STATCNT(SRXAFSCB_WhoAreYou);
930
931     ObtainReadLock(&afs_xinterface);
932
933     /* return all network interface addresses */
934     addr->numberOfInterfaces = afs_cb_interface.numberOfInterfaces;
935     addr->uuid = afs_cb_interface.uuid;
936     for ( i=0; i < afs_cb_interface.numberOfInterfaces; i++) {
937         addr->addr_in[i] = ntohl(afs_cb_interface.addr_in[i]);
938         addr->subnetmask[i] = ntohl(afs_cb_interface.subnetmask[i]);
939         addr->mtu[i] = ntohl(afs_cb_interface.mtu[i]);
940     }
941
942     ReleaseReadLock(&afs_xinterface);
943
944 #ifdef RX_ENABLE_LOCKS
945     AFS_GUNLOCK();
946 #endif /* RX_ENABLE_LOCKS */
947
948     return code;
949 }
950
951
952 /*------------------------------------------------------------------------
953  * EXPORTED SRXAFSCB_InitCallBackState3
954  *
955  * Description:
956  *      Routine called by the server-side callback RPC interface to
957  *      implement clearing all callbacks from this host.
958  *
959  * Arguments:
960  *      a_call : Ptr to Rx call on which this request came in.
961  *
962  * Returns:
963  *      0 (always).
964  *
965  * Environment:
966  *      Nothing interesting.
967  *
968  * Side Effects:
969  *      As advertised.
970  *------------------------------------------------------------------------*/
971
972 int SRXAFSCB_InitCallBackState3(a_call, a_uuid)
973 struct rx_call *a_call;
974 afsUUID *a_uuid;
975 {
976     int code;
977
978     /*
979      * TBD: Lookup the server by the UUID instead of its IP address.
980      */
981     code = SRXAFSCB_InitCallBackState(a_call);
982
983     return code;
984 }
985  
986
987 /*------------------------------------------------------------------------
988  * EXPORTED SRXAFSCB_ProbeUuid
989  *
990  * Description:
991  *      Routine called by the server-side callback RPC interface to
992  *      implement ``probing'' the Cache Manager, just making sure it's
993  *      still there is still the same client it used to be.
994  *
995  * Arguments:
996  *      a_call : Ptr to Rx call on which this request came in.
997  *      a_uuid : Ptr to UUID that must match the client's UUID.
998  *
999  * Returns:
1000  *      0 if a_uuid matches the UUID for this client
1001  *      Non-zero otherwize
1002  *
1003  * Environment:
1004  *      Nothing interesting.
1005  *
1006  * Side Effects:
1007  *      As advertised.
1008  *------------------------------------------------------------------------*/
1009
1010 int SRXAFSCB_ProbeUuid(a_call, a_uuid)
1011 struct rx_call *a_call;
1012 afsUUID *a_uuid;
1013 {
1014     int code = 0;
1015     XSTATS_DECLS;
1016
1017 #ifdef RX_ENABLE_LOCKS
1018     AFS_GLOCK();
1019 #endif /* RX_ENABLE_LOCKS */
1020     AFS_STATCNT(SRXAFSCB_Probe);
1021
1022     XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_PROBE);
1023     if (!afs_uuid_equal(a_uuid, &afs_cb_interface.uuid))
1024         code = 1; /* failure */
1025     XSTATS_END_TIME;
1026
1027 #ifdef RX_ENABLE_LOCKS
1028     AFS_GUNLOCK();
1029 #endif /* RX_ENABLE_LOCKS */
1030
1031     return code;
1032 }
1033  
1034
1035 /*------------------------------------------------------------------------
1036  * EXPORTED SRXAFSCB_GetServerPrefs
1037  *
1038  * Description:
1039  *      Routine to list server preferences used by this client.
1040  *
1041  * Arguments:
1042  *      a_call  : Ptr to Rx call on which this request came in.
1043  *      a_index : Input server index
1044  *      a_srvr_addr  : Output server address in host byte order
1045  *                     (0xffffffff on last server)
1046  *      a_srvr_rank  : Output server rank
1047  *
1048  * Returns:
1049  *      0 on success
1050  *
1051  * Environment:
1052  *      Nothing interesting.
1053  *
1054  * Side Effects:
1055  *      As advertised.
1056  *------------------------------------------------------------------------*/
1057
1058 int SRXAFSCB_GetServerPrefs(
1059     struct rx_call *a_call,
1060     afs_int32 a_index,
1061     afs_int32 *a_srvr_addr,
1062     afs_int32 *a_srvr_rank)
1063 {
1064     int i, j;
1065     struct srvAddr *sa;
1066
1067 #ifdef RX_ENABLE_LOCKS
1068     AFS_GLOCK();
1069 #endif /* RX_ENABLE_LOCKS */
1070     AFS_STATCNT(SRXAFSCB_GetServerPrefs);
1071
1072     ObtainReadLock(&afs_xserver);
1073
1074     /* Search the hash table for the server with this index */
1075     *a_srvr_addr = 0xffffffff;
1076     *a_srvr_rank = 0xffffffff;
1077     for (i=0, j=0; j < NSERVERS && i <= a_index; j++) {
1078         for (sa = afs_srvAddrs[j]; sa && i <= a_index; sa = sa->next_bkt, i++) {
1079             if (i == a_index) {
1080                 *a_srvr_addr = ntohl(sa->sa_ip);
1081                 *a_srvr_rank = sa->sa_iprank;
1082             }
1083         }
1084     }
1085
1086     ReleaseReadLock(&afs_xserver);
1087
1088 #ifdef RX_ENABLE_LOCKS
1089     AFS_GUNLOCK();
1090 #endif /* RX_ENABLE_LOCKS */
1091
1092     return 0;
1093 }
1094  
1095
1096 /*------------------------------------------------------------------------
1097  * EXPORTED SRXAFSCB_GetCellServDB
1098  *
1099  * Description:
1100  *      Routine to list cells configured for this client
1101  *
1102  * Arguments:
1103  *      a_call  : Ptr to Rx call on which this request came in.
1104  *      a_index : Input cell index
1105  *      a_name  : Output cell name ("" on last cell)
1106  *      a_hosts : Output cell database servers in host byte order.
1107  *
1108  * Returns:
1109  *      0 on success
1110  *
1111  * Environment:
1112  *      Nothing interesting.
1113  *
1114  * Side Effects:
1115  *      As advertised.
1116  *------------------------------------------------------------------------*/
1117
1118 int SRXAFSCB_GetCellServDB(
1119     struct rx_call *a_call,
1120     afs_int32 a_index,
1121     char **a_name,
1122     afs_int32 *a_hosts)
1123 {
1124     afs_int32 i, j;
1125     struct cell *tcell;
1126     struct afs_q *cq, *tq;
1127     char *t_name, *p_name = NULL;
1128
1129 #ifdef RX_ENABLE_LOCKS
1130     AFS_GLOCK();
1131 #endif /* RX_ENABLE_LOCKS */
1132     AFS_STATCNT(SRXAFSCB_GetCellServDB);
1133
1134     memset(a_hosts, 0, AFSMAXCELLHOSTS * sizeof(afs_int32));
1135
1136     /* search the list for the cell with this index */
1137     ObtainReadLock(&afs_xcell);
1138     for (i=0, cq = CellLRU.next; cq != &CellLRU && i<= a_index; cq = tq, i++) {
1139         tq = QNext(cq);
1140         if (i == a_index) {
1141             tcell = QTOC(cq);
1142             p_name = tcell->cellName;
1143             for (j = 0 ; j < AFSMAXCELLHOSTS && tcell->cellHosts[j] ; j++) {
1144                 a_hosts[j] = ntohl(tcell->cellHosts[j]->addr->sa_ip);
1145             }
1146         }
1147     }
1148
1149     if (p_name)
1150         i = strlen(p_name);
1151     else
1152         i = 0;
1153     t_name = (char *)rxi_Alloc(i+1);
1154     if (t_name == NULL) {
1155 #ifdef RX_ENABLE_LOCKS
1156         AFS_GUNLOCK();
1157 #endif /* RX_ENABLE_LOCKS */
1158         return ENOMEM;
1159     }
1160
1161     t_name[i] = '\0';
1162     if (p_name)
1163         memcpy(t_name, p_name, i);
1164
1165     ReleaseReadLock(&afs_xcell);
1166
1167 #ifdef RX_ENABLE_LOCKS
1168     AFS_GUNLOCK();
1169 #endif /* RX_ENABLE_LOCKS */
1170
1171     *a_name = t_name;
1172     return 0;
1173 }
1174  
1175
1176 /*------------------------------------------------------------------------
1177  * EXPORTED SRXAFSCB_GetLocalCell
1178  *
1179  * Description:
1180  *      Routine to return name of client's local cell
1181  *
1182  * Arguments:
1183  *      a_call  : Ptr to Rx call on which this request came in.
1184  *      a_name  : Output cell name
1185  *
1186  * Returns:
1187  *      0 on success
1188  *
1189  * Environment:
1190  *      Nothing interesting.
1191  *
1192  * Side Effects:
1193  *      As advertised.
1194  *------------------------------------------------------------------------*/
1195
1196 int SRXAFSCB_GetLocalCell(
1197     struct rx_call *a_call,
1198     char **a_name)
1199 {
1200     int plen;
1201     struct cell *tcell;
1202     struct afs_q *cq, *tq;
1203     char *t_name, *p_name = NULL;
1204
1205 #ifdef RX_ENABLE_LOCKS
1206     AFS_GLOCK();
1207 #endif /* RX_ENABLE_LOCKS */
1208     AFS_STATCNT(SRXAFSCB_GetLocalCell);
1209
1210     /* Search the list for the primary cell. Cell number 1 is only
1211      * the primary cell is when no other cell is explicitly marked as
1212      * the primary cell.  */
1213     ObtainReadLock(&afs_xcell);
1214     for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
1215         tq = QNext(cq);
1216         tcell = QTOC(cq);
1217         if (tcell->states & CPrimary) {
1218             p_name = tcell->cellName;
1219             break;
1220         }
1221         if (tcell->cell == 1) {
1222             p_name = tcell->cellName;
1223         }
1224     }
1225
1226     if (p_name)
1227         plen = strlen(p_name);
1228     else
1229         plen = 0;
1230     t_name = (char *)rxi_Alloc(plen+1);
1231     if (t_name == NULL) {
1232 #ifdef RX_ENABLE_LOCKS
1233         AFS_GUNLOCK();
1234 #endif /* RX_ENABLE_LOCKS */
1235         return ENOMEM;
1236     }
1237
1238     t_name[plen] = '\0';
1239     if (p_name)
1240         memcpy(t_name, p_name, plen);
1241
1242     ReleaseReadLock(&afs_xcell);
1243
1244 #ifdef RX_ENABLE_LOCKS
1245     AFS_GUNLOCK();
1246 #endif /* RX_ENABLE_LOCKS */
1247
1248     *a_name = t_name;
1249     return 0;
1250 }
1251
1252
1253 /*
1254  * afs_MarshallCacheConfig - marshall client cache configuration
1255  *
1256  * PARAMETERS
1257  *
1258  * IN callerVersion - the rpc stat version of the caller.
1259  *
1260  * IN config - client cache configuration.
1261  *
1262  * OUT ptr - buffer where configuration is marshalled.
1263  *
1264  * RETURN CODES
1265  *
1266  * Returns void.
1267  */
1268 static void afs_MarshallCacheConfig(
1269     afs_uint32 callerVersion,
1270     cm_initparams_v1 *config,
1271     afs_uint32 *ptr)
1272 {
1273     AFS_STATCNT(afs_MarshallCacheConfig);
1274     /*
1275      * We currently only support version 1.
1276      */
1277     *(ptr++) = config->nChunkFiles;
1278     *(ptr++) = config->nStatCaches;
1279     *(ptr++) = config->nDataCaches;
1280     *(ptr++) = config->nVolumeCaches;
1281     *(ptr++) = config->firstChunkSize;
1282     *(ptr++) = config->otherChunkSize;
1283     *(ptr++) = config->cacheSize;
1284     *(ptr++) = config->setTime;
1285     *(ptr++) = config->memCache;
1286
1287 }
1288  
1289
1290 /*------------------------------------------------------------------------
1291  * EXPORTED SRXAFSCB_GetCacheConfig
1292  *
1293  * Description:
1294  *      Routine to return parameters used to initialize client cache.
1295  *      Client may request any format version. Server may not return
1296  *      format version greater than version requested by client.
1297  *
1298  * Arguments:
1299  *      a_call:        Ptr to Rx call on which this request came in.
1300  *      callerVersion: Data format version desired by the client.
1301  *      serverVersion: Data format version of output data.
1302  *      configCount:   Number bytes allocated for output data.
1303  *      config:        Client cache configuration.
1304  *
1305  * Returns:
1306  *      0 on success
1307  *
1308  * Environment:
1309  *      Nothing interesting.
1310  *
1311  * Side Effects:
1312  *      As advertised.
1313  *------------------------------------------------------------------------*/
1314
1315 int SRXAFSCB_GetCacheConfig(
1316     struct rx_call *a_call,
1317     afs_uint32 callerVersion,
1318     afs_uint32 *serverVersion,
1319     afs_uint32 *configCount,
1320     cacheConfig *config)
1321 {
1322     afs_uint32 *t_config;
1323     size_t allocsize;
1324     cm_initparams_v1 cm_config;
1325
1326 #ifdef RX_ENABLE_LOCKS
1327     AFS_GLOCK();
1328 #endif /* RX_ENABLE_LOCKS */
1329     AFS_STATCNT(SRXAFSCB_GetCacheConfig);
1330
1331     /*
1332      * Currently only support version 1
1333      */
1334     allocsize = sizeof(cm_initparams_v1);
1335     t_config = (afs_uint32 *)rxi_Alloc(allocsize);
1336     if (t_config == NULL) {
1337 #ifdef RX_ENABLE_LOCKS
1338         AFS_GUNLOCK();
1339 #endif /* RX_ENABLE_LOCKS */
1340         return ENOMEM;
1341     }
1342
1343     cm_config.nChunkFiles = cm_initParams.cmi_nChunkFiles;
1344     cm_config.nStatCaches = cm_initParams.cmi_nStatCaches;
1345     cm_config.nDataCaches = cm_initParams.cmi_nDataCaches;
1346     cm_config.nVolumeCaches = cm_initParams.cmi_nVolumeCaches;
1347     cm_config.firstChunkSize = cm_initParams.cmi_firstChunkSize;
1348     cm_config.otherChunkSize = cm_initParams.cmi_otherChunkSize;
1349     cm_config.cacheSize = cm_initParams.cmi_cacheSize;
1350     cm_config.setTime = cm_initParams.cmi_setTime;
1351     cm_config.memCache = cm_initParams.cmi_memCache;
1352
1353     afs_MarshallCacheConfig(callerVersion, &cm_config, t_config);
1354
1355     *serverVersion = AFS_CLIENT_RETRIEVAL_FIRST_EDITION;
1356     *configCount = allocsize;
1357     config->cacheConfig_val = t_config;
1358     config->cacheConfig_len = allocsize/sizeof(afs_uint32);
1359
1360 #ifdef RX_ENABLE_LOCKS
1361     AFS_GUNLOCK();
1362 #endif /* RX_ENABLE_LOCKS */
1363
1364     return 0;
1365 }