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