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