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