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