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