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