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