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