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