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