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