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