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