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