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