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