aix vnode hold simplification
[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
776
777
778         /* find any volumes residing on this server and flush their state */
779         {
780             register struct volume *tv;
781             register int j;
782
783             for (i = 0; i < NVOLS; i++)
784                 for (tv = afs_volumes[i]; tv; tv = tv->next) {
785                     for (j = 0; j < AFS_MAXHOSTS; j++)
786                         if (tv->serverHost[j] == ts)
787                             afs_ResetVolumeInfo(tv);
788                 }
789         }
790         osi_dnlc_purge();       /* may be a little bit extreme */
791     }
792
793     XSTATS_END_TIME;
794
795     RX_AFS_GUNLOCK();
796
797     return (0);
798
799 }                               /*SRXAFSCB_InitCallBackState */
800
801
802 /*------------------------------------------------------------------------
803  * EXPORTED SRXAFSCB_XStatsVersion
804  *
805  * Description:
806  *      Routine called by the server-side callback RPC interface to
807  *      implement pulling out the xstat version number for the Cache
808  *      Manager.
809  *
810  * Arguments:
811  *      a_versionP : Ptr to the version number variable to set.
812  *
813  * Returns:
814  *      0 (always)
815  *
816  * Environment:
817  *      Nothing interesting.
818  *
819  * Side Effects:
820  *      As advertised.
821  *------------------------------------------------------------------------*/
822
823 int
824 SRXAFSCB_XStatsVersion(struct rx_call *a_call, afs_int32 * a_versionP)
825 {
826     int code = 0;
827
828     XSTATS_DECLS;
829
830     RX_AFS_GLOCK();
831     XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_XSTATSVERSION);
832
833     *a_versionP = AFSCB_XSTAT_VERSION;
834
835     XSTATS_END_TIME;
836
837     RX_AFS_GUNLOCK();
838
839     return (0);
840 }                               /*SRXAFSCB_XStatsVersion */
841
842
843 /*------------------------------------------------------------------------
844  * EXPORTED SRXAFSCB_GetXStats
845  *
846  * Description:
847  *      Routine called by the server-side callback RPC interface to
848  *      implement getting the given data collection from the extended
849  *      Cache Manager statistics.
850  *
851  * Arguments:
852  *      a_call              : Ptr to Rx call on which this request came in.
853  *      a_clientVersionNum  : Client version number.
854  *      a_opCode            : Desired operation.
855  *      a_serverVersionNumP : Ptr to version number to set.
856  *      a_timeP             : Ptr to time value (seconds) to set.
857  *      a_dataArray         : Ptr to variable array structure to return
858  *                            stuff in.
859  *
860  * Returns:
861  *      0 (always).
862  *
863  * Environment:
864  *      Nothing interesting.
865  *
866  * Side Effects:
867  *      As advertised.
868  *------------------------------------------------------------------------*/
869
870 int
871 SRXAFSCB_GetXStats(struct rx_call *a_call, afs_int32 a_clientVersionNum,
872                    afs_int32 a_collectionNumber, afs_int32 * a_srvVersionNumP,
873                    afs_int32 * a_timeP, AFSCB_CollData * a_dataP)
874 {
875     register int code;          /*Return value */
876     afs_int32 *dataBuffP;       /*Ptr to data to be returned */
877     afs_int32 dataBytes;        /*Bytes in data buffer */
878     XSTATS_DECLS;
879
880     RX_AFS_GLOCK();
881
882     XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_GETXSTATS);
883
884     /*
885      * Record the time of day and the server version number.
886      */
887     *a_srvVersionNumP = AFSCB_XSTAT_VERSION;
888     *a_timeP = osi_Time();
889
890     /*
891      * Stuff the appropriate data in there (assume victory)
892      */
893     code = 0;
894
895 #ifdef AFS_NOSTATS
896     /*
897      * We're not keeping stats, so just return successfully with
898      * no data.
899      */
900     a_dataP->AFSCB_CollData_len = 0;
901     a_dataP->AFSCB_CollData_val = NULL;
902 #else
903     switch (a_collectionNumber) {
904     case AFSCB_XSTATSCOLL_CALL_INFO:
905         /*
906          * Pass back all the call-count-related data.
907          *
908          * >>> We are forced to allocate a separate area in which to
909          * >>> put this stuff in by the RPC stub generator, since it
910          * >>> will be freed at the tail end of the server stub code.
911          */
912         dataBytes = sizeof(struct afs_CMStats);
913         dataBuffP = (afs_int32 *) afs_osi_Alloc(dataBytes);
914         memcpy((char *)dataBuffP, (char *)&afs_cmstats, dataBytes);
915         a_dataP->AFSCB_CollData_len = dataBytes >> 2;
916         a_dataP->AFSCB_CollData_val = dataBuffP;
917         break;
918
919     case AFSCB_XSTATSCOLL_PERF_INFO:
920         /*
921          * Update and then pass back all the performance-related data.
922          * Note: the only performance fields that need to be computed
923          * at this time are the number of accesses for this collection
924          * and the current server record info.
925          *
926          * >>> We are forced to allocate a separate area in which to
927          * >>> put this stuff in by the RPC stub generator, since it
928          * >>> will be freed at the tail end of the server stub code.
929          */
930         afs_stats_cmperf.numPerfCalls++;
931         afs_CountServers();
932         dataBytes = sizeof(afs_stats_cmperf);
933         dataBuffP = (afs_int32 *) afs_osi_Alloc(dataBytes);
934         memcpy((char *)dataBuffP, (char *)&afs_stats_cmperf, dataBytes);
935         a_dataP->AFSCB_CollData_len = dataBytes >> 2;
936         a_dataP->AFSCB_CollData_val = dataBuffP;
937         break;
938
939     case AFSCB_XSTATSCOLL_FULL_PERF_INFO:
940         /*
941          * Pass back the full range of performance and statistical
942          * data available.  We have to bring the normal performance
943          * data collection up to date, then copy that data into
944          * the full collection.
945          *
946          * >>> We are forced to allocate a separate area in which to
947          * >>> put this stuff in by the RPC stub generator, since it
948          * >>> will be freed at the tail end of the server stub code.
949          */
950         afs_stats_cmperf.numPerfCalls++;
951         afs_CountServers();
952         memcpy((char *)(&(afs_stats_cmfullperf.perf)),
953                (char *)(&afs_stats_cmperf), sizeof(struct afs_stats_CMPerf));
954         afs_stats_cmfullperf.numFullPerfCalls++;
955
956         dataBytes = sizeof(afs_stats_cmfullperf);
957         dataBuffP = (afs_int32 *) afs_osi_Alloc(dataBytes);
958         memcpy((char *)dataBuffP, (char *)(&afs_stats_cmfullperf), dataBytes);
959         a_dataP->AFSCB_CollData_len = dataBytes >> 2;
960         a_dataP->AFSCB_CollData_val = dataBuffP;
961         break;
962
963     default:
964         /*
965          * Illegal collection number.
966          */
967         a_dataP->AFSCB_CollData_len = 0;
968         a_dataP->AFSCB_CollData_val = NULL;
969         code = 1;
970     }                           /*Switch on collection number */
971 #endif /* AFS_NOSTATS */
972
973     XSTATS_END_TIME;
974
975     RX_AFS_GUNLOCK();
976
977     return (code);
978
979 }                               /*SRXAFSCB_GetXStats */
980
981
982 /*------------------------------------------------------------------------
983  * EXPORTED afs_RXCallBackServer
984  *
985  * Description:
986  *      Body of the thread supporting callback services.
987  *
988  * Arguments:
989  *      None.
990  *
991  * Returns:
992  *      0 (always).
993  *
994  * Environment:
995  *      Nothing interesting.
996  *
997  * Side Effects:
998  *      As advertised.
999  *------------------------------------------------------------------------*/
1000
1001 int
1002 afs_RXCallBackServer(void)
1003 {
1004     AFS_STATCNT(afs_RXCallBackServer);
1005
1006     while (1) {
1007         if (afs_server)
1008             break;
1009         afs_osi_Sleep(&afs_server);
1010     }
1011
1012     /*
1013      * Donate this process to Rx.
1014      */
1015     rx_ServerProc(NULL);
1016     return (0);
1017
1018 }                               /*afs_RXCallBackServer */
1019
1020
1021 /*------------------------------------------------------------------------
1022  * EXPORTED shutdown_CB
1023  *
1024  * Description:
1025  *      Zero out important Cache Manager data structures.
1026  *
1027  * Arguments:
1028  *      None.
1029  *
1030  * Returns:
1031  *      0 (always).
1032  *
1033  * Environment:
1034  *      Nothing interesting.
1035  *
1036  * Side Effects:
1037  *      As advertised.
1038  *------------------------------------------------------------------------*/
1039
1040 int
1041 shutdown_CB(void)
1042 {
1043     AFS_STATCNT(shutdown_CB);
1044
1045     if (afs_cold_shutdown) {
1046         afs_oddCBs = afs_evenCBs = afs_allCBs = afs_allZaps = afs_oddZaps =
1047             afs_evenZaps = afs_connectBacks = 0;
1048     }
1049
1050     return (0);
1051
1052 }                               /*shutdown_CB */
1053
1054 /*------------------------------------------------------------------------
1055  * EXPORTED SRXAFSCB_InitCallBackState2
1056  *
1057  * Description:
1058  *      This routine was used in the AFS 3.5 beta release, but not anymore.
1059  *      It has since been replaced by SRXAFSCB_InitCallBackState3.
1060  *
1061  * Arguments:
1062  *      a_call : Ptr to Rx call on which this request came in.
1063  *
1064  * Returns:
1065  *      RXGEN_OPCODE (always). 
1066  *
1067  * Environment:
1068  *      Nothing interesting.
1069  *
1070  * Side Effects:
1071  *      None
1072  *------------------------------------------------------------------------*/
1073
1074 int
1075 SRXAFSCB_InitCallBackState2(struct rx_call *a_call,
1076                             struct interfaceAddr *addr)
1077 {
1078     return RXGEN_OPCODE;
1079 }
1080
1081 /*------------------------------------------------------------------------
1082  * EXPORTED SRXAFSCB_WhoAreYou
1083  *
1084  * Description:
1085  *      Routine called by the server-side callback RPC interface to
1086  *      obtain a unique identifier for the client. The server uses
1087  *      this identifier to figure out whether or not two RX connections
1088  *      are from the same client, and to find out which addresses go
1089  *      with which clients.
1090  *
1091  * Arguments:
1092  *      a_call : Ptr to Rx call on which this request came in.
1093  *      addr: Ptr to return the list of interfaces for this client.
1094  *
1095  * Returns:
1096  *      0 (Always)
1097  *
1098  * Environment:
1099  *      Nothing interesting.
1100  *
1101  * Side Effects:
1102  *      As advertised.
1103  *------------------------------------------------------------------------*/
1104
1105 int
1106 SRXAFSCB_WhoAreYou(struct rx_call *a_call, struct interfaceAddr *addr)
1107 {
1108     int i;
1109     int code = 0;
1110
1111     RX_AFS_GLOCK();
1112
1113     AFS_STATCNT(SRXAFSCB_WhoAreYou);
1114
1115     memset(addr, 0, sizeof(*addr));
1116
1117     ObtainReadLock(&afs_xinterface);
1118
1119     /* return all network interface addresses */
1120     addr->numberOfInterfaces = afs_cb_interface.numberOfInterfaces;
1121     addr->uuid = afs_cb_interface.uuid;
1122     for (i = 0; i < afs_cb_interface.numberOfInterfaces; i++) {
1123         addr->addr_in[i] = ntohl(afs_cb_interface.addr_in[i]);
1124         addr->subnetmask[i] = ntohl(afs_cb_interface.subnetmask[i]);
1125         addr->mtu[i] = ntohl(afs_cb_interface.mtu[i]);
1126     }
1127
1128     ReleaseReadLock(&afs_xinterface);
1129
1130     RX_AFS_GUNLOCK();
1131
1132     return code;
1133 }
1134
1135
1136 /*------------------------------------------------------------------------
1137  * EXPORTED SRXAFSCB_InitCallBackState3
1138  *
1139  * Description:
1140  *      Routine called by the server-side callback RPC interface to
1141  *      implement clearing all callbacks from this host.
1142  *
1143  * Arguments:
1144  *      a_call : Ptr to Rx call on which this request came in.
1145  *
1146  * Returns:
1147  *      0 (always).
1148  *
1149  * Environment:
1150  *      Nothing interesting.
1151  *
1152  * Side Effects:
1153  *      As advertised.
1154  *------------------------------------------------------------------------*/
1155
1156 int
1157 SRXAFSCB_InitCallBackState3(struct rx_call *a_call, afsUUID * a_uuid)
1158 {
1159     int code;
1160
1161     /*
1162      * TBD: Lookup the server by the UUID instead of its IP address.
1163      */
1164     code = SRXAFSCB_InitCallBackState(a_call);
1165
1166     return code;
1167 }
1168
1169
1170 /*------------------------------------------------------------------------
1171  * EXPORTED SRXAFSCB_ProbeUuid
1172  *
1173  * Description:
1174  *      Routine called by the server-side callback RPC interface to
1175  *      implement ``probing'' the Cache Manager, just making sure it's
1176  *      still there is still the same client it used to be.
1177  *
1178  * Arguments:
1179  *      a_call : Ptr to Rx call on which this request came in.
1180  *      a_uuid : Ptr to UUID that must match the client's UUID.
1181  *
1182  * Returns:
1183  *      0 if a_uuid matches the UUID for this client
1184  *      Non-zero otherwize
1185  *
1186  * Environment:
1187  *      Nothing interesting.
1188  *
1189  * Side Effects:
1190  *      As advertised.
1191  *------------------------------------------------------------------------*/
1192
1193 int
1194 SRXAFSCB_ProbeUuid(struct rx_call *a_call, afsUUID * a_uuid)
1195 {
1196     int code = 0;
1197     XSTATS_DECLS;
1198
1199     RX_AFS_GLOCK();
1200     AFS_STATCNT(SRXAFSCB_Probe);
1201
1202     XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_PROBE);
1203     if (!afs_uuid_equal(a_uuid, &afs_cb_interface.uuid))
1204         code = 1;               /* failure */
1205     XSTATS_END_TIME;
1206
1207     RX_AFS_GUNLOCK();
1208
1209     return code;
1210 }
1211
1212
1213 /*------------------------------------------------------------------------
1214  * EXPORTED SRXAFSCB_GetServerPrefs
1215  *
1216  * Description:
1217  *      Routine to list server preferences used by this client.
1218  *
1219  * Arguments:
1220  *      a_call  : Ptr to Rx call on which this request came in.
1221  *      a_index : Input server index
1222  *      a_srvr_addr  : Output server address in host byte order
1223  *                     (0xffffffff on last server)
1224  *      a_srvr_rank  : Output server rank
1225  *
1226  * Returns:
1227  *      0 on success
1228  *
1229  * Environment:
1230  *      Nothing interesting.
1231  *
1232  * Side Effects:
1233  *      As advertised.
1234  *------------------------------------------------------------------------*/
1235
1236 int
1237 SRXAFSCB_GetServerPrefs(struct rx_call *a_call, afs_int32 a_index,
1238                         afs_int32 * a_srvr_addr, afs_int32 * a_srvr_rank)
1239 {
1240     int i, j;
1241     struct srvAddr *sa;
1242
1243     RX_AFS_GLOCK();
1244     AFS_STATCNT(SRXAFSCB_GetServerPrefs);
1245
1246     ObtainReadLock(&afs_xserver);
1247
1248     /* Search the hash table for the server with this index */
1249     *a_srvr_addr = 0xffffffff;
1250     *a_srvr_rank = 0xffffffff;
1251     for (i = 0, j = 0; j < NSERVERS && i <= a_index; j++) {
1252         for (sa = afs_srvAddrs[j]; sa && i <= a_index; sa = sa->next_bkt, i++) {
1253             if (i == a_index) {
1254                 *a_srvr_addr = ntohl(sa->sa_ip);
1255                 *a_srvr_rank = sa->sa_iprank;
1256             }
1257         }
1258     }
1259
1260     ReleaseReadLock(&afs_xserver);
1261
1262     RX_AFS_GUNLOCK();
1263
1264     return 0;
1265 }
1266
1267
1268 /*------------------------------------------------------------------------
1269  * EXPORTED SRXAFSCB_GetCellServDB
1270  *
1271  * Description:
1272  *      Routine to list cells configured for this client
1273  *
1274  * Arguments:
1275  *      a_call  : Ptr to Rx call on which this request came in.
1276  *      a_index : Input cell index
1277  *      a_name  : Output cell name ("" on last cell)
1278  *      a_hosts : Output cell database servers in host byte order.
1279  *
1280  * Returns:
1281  *      0 on success
1282  *
1283  * Environment:
1284  *      Nothing interesting.
1285  *
1286  * Side Effects:
1287  *      As advertised.
1288  *------------------------------------------------------------------------*/
1289
1290 int
1291 SRXAFSCB_GetCellServDB(struct rx_call *a_call, afs_int32 a_index,
1292                        char **a_name, serverList * a_hosts)
1293 {
1294     afs_int32 i, j = 0;
1295     struct cell *tcell;
1296     char *t_name, *p_name = NULL;
1297
1298     RX_AFS_GLOCK();
1299     AFS_STATCNT(SRXAFSCB_GetCellServDB);
1300
1301     tcell = afs_GetCellByIndex(a_index, READ_LOCK);
1302
1303     if (!tcell) {
1304         i = 0;
1305         a_hosts->serverList_val = 0;
1306         a_hosts->serverList_len = 0;
1307     } else {
1308         p_name = tcell->cellName;
1309         for (j = 0; j < AFSMAXCELLHOSTS && tcell->cellHosts[j]; j++);
1310         i = strlen(p_name);
1311         a_hosts->serverList_val =
1312             (afs_int32 *) afs_osi_Alloc(j * sizeof(afs_int32));
1313         a_hosts->serverList_len = j;
1314         for (j = 0; j < AFSMAXCELLHOSTS && tcell->cellHosts[j]; j++)
1315             a_hosts->serverList_val[j] =
1316                 ntohl(tcell->cellHosts[j]->addr->sa_ip);
1317         afs_PutCell(tcell, READ_LOCK);
1318     }
1319
1320     t_name = (char *)afs_osi_Alloc(i + 1);
1321     if (t_name == NULL) {
1322         afs_osi_Free(a_hosts->serverList_val, (j * sizeof(afs_int32)));
1323         RX_AFS_GUNLOCK();
1324         return ENOMEM;
1325     }
1326
1327     t_name[i] = '\0';
1328     if (p_name)
1329         memcpy(t_name, p_name, i);
1330
1331     RX_AFS_GUNLOCK();
1332
1333     *a_name = t_name;
1334     return 0;
1335 }
1336
1337
1338 /*------------------------------------------------------------------------
1339  * EXPORTED SRXAFSCB_GetLocalCell
1340  *
1341  * Description:
1342  *      Routine to return name of client's local cell
1343  *
1344  * Arguments:
1345  *      a_call  : Ptr to Rx call on which this request came in.
1346  *      a_name  : Output cell name
1347  *
1348  * Returns:
1349  *      0 on success
1350  *
1351  * Environment:
1352  *      Nothing interesting.
1353  *
1354  * Side Effects:
1355  *      As advertised.
1356  *------------------------------------------------------------------------*/
1357
1358 int
1359 SRXAFSCB_GetLocalCell(struct rx_call *a_call, char **a_name)
1360 {
1361     int plen;
1362     struct cell *tcell;
1363     char *t_name, *p_name = NULL;
1364
1365     RX_AFS_GLOCK();
1366     AFS_STATCNT(SRXAFSCB_GetLocalCell);
1367
1368     /* Search the list for the primary cell. Cell number 1 is only
1369      * the primary cell is when no other cell is explicitly marked as
1370      * the primary cell.  */
1371     tcell = afs_GetPrimaryCell(READ_LOCK);
1372     if (tcell)
1373         p_name = tcell->cellName;
1374     if (p_name)
1375         plen = strlen(p_name);
1376     else
1377         plen = 0;
1378     t_name = (char *)afs_osi_Alloc(plen + 1);
1379     if (t_name == NULL) {
1380         if (tcell)
1381             afs_PutCell(tcell, READ_LOCK);
1382         RX_AFS_GUNLOCK();
1383         return ENOMEM;
1384     }
1385
1386     t_name[plen] = '\0';
1387     if (p_name)
1388         memcpy(t_name, p_name, plen);
1389
1390     RX_AFS_GUNLOCK();
1391
1392     *a_name = t_name;
1393     if (tcell)
1394         afs_PutCell(tcell, READ_LOCK);
1395     return 0;
1396 }
1397
1398
1399 /*
1400  * afs_MarshallCacheConfig - marshall client cache configuration
1401  *
1402  * PARAMETERS
1403  *
1404  * IN callerVersion - the rpc stat version of the caller.
1405  *
1406  * IN config - client cache configuration.
1407  *
1408  * OUT ptr - buffer where configuration is marshalled.
1409  *
1410  * RETURN CODES
1411  *
1412  * Returns void.
1413  */
1414 static void
1415 afs_MarshallCacheConfig(afs_uint32 callerVersion, cm_initparams_v1 * config,
1416                         afs_uint32 * ptr)
1417 {
1418     AFS_STATCNT(afs_MarshallCacheConfig);
1419     /*
1420      * We currently only support version 1.
1421      */
1422     *(ptr++) = config->nChunkFiles;
1423     *(ptr++) = config->nStatCaches;
1424     *(ptr++) = config->nDataCaches;
1425     *(ptr++) = config->nVolumeCaches;
1426     *(ptr++) = config->firstChunkSize;
1427     *(ptr++) = config->otherChunkSize;
1428     *(ptr++) = config->cacheSize;
1429     *(ptr++) = config->setTime;
1430     *(ptr++) = config->memCache;
1431 }
1432
1433
1434 /*------------------------------------------------------------------------
1435  * EXPORTED SRXAFSCB_GetCacheConfig
1436  *
1437  * Description:
1438  *      Routine to return parameters used to initialize client cache.
1439  *      Client may request any format version. Server may not return
1440  *      format version greater than version requested by client.
1441  *
1442  * Arguments:
1443  *      a_call:        Ptr to Rx call on which this request came in.
1444  *      callerVersion: Data format version desired by the client.
1445  *      serverVersion: Data format version of output data.
1446  *      configCount:   Number bytes allocated for output data.
1447  *      config:        Client cache configuration.
1448  *
1449  * Returns:
1450  *      0 on success
1451  *
1452  * Environment:
1453  *      Nothing interesting.
1454  *
1455  * Side Effects:
1456  *      As advertised.
1457  *------------------------------------------------------------------------*/
1458
1459 int
1460 SRXAFSCB_GetCacheConfig(struct rx_call *a_call, afs_uint32 callerVersion,
1461                         afs_uint32 * serverVersion, afs_uint32 * configCount,
1462                         cacheConfig * config)
1463 {
1464     afs_uint32 *t_config;
1465     size_t allocsize;
1466     cm_initparams_v1 cm_config;
1467
1468     RX_AFS_GLOCK();
1469     AFS_STATCNT(SRXAFSCB_GetCacheConfig);
1470
1471     /*
1472      * Currently only support version 1
1473      */
1474     allocsize = sizeof(cm_initparams_v1);
1475     t_config = (afs_uint32 *) afs_osi_Alloc(allocsize);
1476     if (t_config == NULL) {
1477         RX_AFS_GUNLOCK();
1478         return ENOMEM;
1479     }
1480
1481     cm_config.nChunkFiles = cm_initParams.cmi_nChunkFiles;
1482     cm_config.nStatCaches = cm_initParams.cmi_nStatCaches;
1483     cm_config.nDataCaches = cm_initParams.cmi_nDataCaches;
1484     cm_config.nVolumeCaches = cm_initParams.cmi_nVolumeCaches;
1485     cm_config.firstChunkSize = cm_initParams.cmi_firstChunkSize;
1486     cm_config.otherChunkSize = cm_initParams.cmi_otherChunkSize;
1487     cm_config.cacheSize = cm_initParams.cmi_cacheSize;
1488     cm_config.setTime = cm_initParams.cmi_setTime;
1489     cm_config.memCache = cm_initParams.cmi_memCache;
1490
1491     afs_MarshallCacheConfig(callerVersion, &cm_config, t_config);
1492
1493     *serverVersion = AFS_CLIENT_RETRIEVAL_FIRST_EDITION;
1494     *configCount = allocsize;
1495     config->cacheConfig_val = t_config;
1496     config->cacheConfig_len = allocsize / sizeof(afs_uint32);
1497
1498     RX_AFS_GUNLOCK();
1499
1500     return 0;
1501 }
1502
1503 /*------------------------------------------------------------------------
1504  * EXPORTED SRXAFSCB_FetchData
1505  *
1506  * Description:
1507  *      Routine to do third party move from a remioserver to the original
1508  *      issuer of an ArchiveData request. Presently supported only by the
1509  *      "fs" command, not by the AFS client.
1510  *
1511  * Arguments:
1512  *      rxcall:        Ptr to Rx call on which this request came in.
1513  *      Fid:           pointer to AFSFid structure.
1514  *      Fd:            File descriptor inside fs command.
1515  *      Position:      Offset in the file.
1516  *      Length:        Data length to transfer.
1517  *      TotalLength:   Pointer to total file length field
1518  *
1519  * Returns:
1520  *      0 on success
1521  *
1522  * Environment:
1523  *      Nothing interesting.
1524  *
1525  * Side Effects:
1526  *------------------------------------------------------------------------*/
1527 int
1528 SRXAFSCB_FetchData(struct rx_call *rxcall, struct AFSFid *Fid, afs_int32 Fd,
1529                    afs_int64 Position, afs_int64 Length,
1530                    afs_int64 * TotalLength)
1531 {
1532     return ENOSYS;
1533 }
1534
1535 /*------------------------------------------------------------------------
1536  * EXPORTED SRXAFSCB_StoreData
1537  *
1538  * Description:
1539  *      Routine to do third party move from a remioserver to the original
1540  *      issuer of a RetrieveData request. Presently supported only by the
1541  *      "fs" command, not by the AFS client.
1542  *
1543  * Arguments:
1544  *      rxcall:        Ptr to Rx call on which this request came in.
1545  *      Fid:           pointer to AFSFid structure.
1546  *      Fd:            File descriptor inside fs command.
1547  *      Position:      Offset in the file.
1548  *      Length:        Data length to transfer.
1549  *      TotalLength:   Pointer to total file length field
1550  *
1551  * Returns:
1552  *      0 on success
1553  *
1554  * Environment:
1555  *      Nothing interesting.
1556  *
1557  * Side Effects:
1558  *      As advertised.
1559  *------------------------------------------------------------------------*/
1560 int
1561 SRXAFSCB_StoreData(struct rx_call *rxcall, struct AFSFid *Fid, afs_int32 Fd,
1562                    afs_int64 Position, afs_int64 Length,
1563                    afs_int64 * TotalLength)
1564 {
1565     return ENOSYS;
1566 }
1567
1568 /*------------------------------------------------------------------------
1569  * EXPORTED SRXAFSCB_GetCellByNum
1570  *
1571  * Description:
1572  *      Routine to get information about a cell specified by its
1573  *      cell number (returned by GetCE/GetCE64).
1574  *
1575  * Arguments:
1576  *      a_call    : Ptr to Rx call on which this request came in.
1577  *      a_cellnum : Input cell number
1578  *      a_name    : Output cell name (one zero byte when no such cell).
1579  *      a_hosts   : Output cell database servers in host byte order.
1580  *
1581  * Returns:
1582  *      0 on success
1583  *
1584  * Environment:
1585  *      Nothing interesting.
1586  *
1587  * Side Effects:
1588  *      As advertised.
1589  *------------------------------------------------------------------------*/
1590
1591 int
1592 SRXAFSCB_GetCellByNum(struct rx_call *a_call, afs_int32 a_cellnum,
1593                       char **a_name, serverList * a_hosts)
1594 {
1595     afs_int32 i, sn;
1596     struct cell *tcell;
1597
1598     RX_AFS_GLOCK();
1599     AFS_STATCNT(SRXAFSCB_GetCellByNum);
1600
1601     a_hosts->serverList_val = 0;
1602     a_hosts->serverList_len = 0;
1603
1604     tcell = afs_GetCellStale(a_cellnum, READ_LOCK);
1605     if (!tcell) {
1606         *a_name = afs_strdup("");
1607         RX_AFS_GUNLOCK();
1608         return 0;
1609     }
1610
1611     ObtainReadLock(&tcell->lock);
1612     *a_name = afs_strdup(tcell->cellName);
1613
1614     for (sn = 0; sn < AFSMAXCELLHOSTS && tcell->cellHosts[sn]; sn++);
1615     a_hosts->serverList_len = sn;
1616     a_hosts->serverList_val =
1617         (afs_int32 *) afs_osi_Alloc(sn * sizeof(afs_int32));
1618
1619     for (i = 0; i < sn; i++)
1620         a_hosts->serverList_val[i] = ntohl(tcell->cellHosts[i]->addr->sa_ip);
1621     ReleaseReadLock(&tcell->lock);
1622     afs_PutCell(tcell, READ_LOCK);
1623
1624     RX_AFS_GUNLOCK();
1625     return 0;
1626 }
1627
1628 int
1629 SRXAFSCB_TellMeAboutYourself(struct rx_call *a_call,
1630                              struct interfaceAddr *addr,
1631                              Capabilities * capabilities)
1632 {
1633     int i;
1634     int code = 0;
1635     afs_uint32 *dataBuffP;
1636     afs_int32 dataBytes;
1637
1638     RX_AFS_GLOCK();
1639
1640     AFS_STATCNT(SRXAFSCB_WhoAreYou);
1641
1642     ObtainReadLock(&afs_xinterface);
1643
1644     /* return all network interface addresses */
1645     addr->numberOfInterfaces = afs_cb_interface.numberOfInterfaces;
1646     addr->uuid = afs_cb_interface.uuid;
1647     for (i = 0; i < afs_cb_interface.numberOfInterfaces; i++) {
1648         addr->addr_in[i] = ntohl(afs_cb_interface.addr_in[i]);
1649         addr->subnetmask[i] = ntohl(afs_cb_interface.subnetmask[i]);
1650         addr->mtu[i] = ntohl(afs_cb_interface.mtu[i]);
1651     }
1652
1653     ReleaseReadLock(&afs_xinterface);
1654
1655     RX_AFS_GUNLOCK();
1656
1657     dataBytes = 1 * sizeof(afs_uint32);
1658     dataBuffP = (afs_uint32 *) afs_osi_Alloc(dataBytes);
1659     dataBuffP[0] = CLIENT_CAPABILITY_ERRORTRANS;
1660     capabilities->Capabilities_len = dataBytes / sizeof(afs_uint32);
1661     capabilities->Capabilities_val = dataBuffP;
1662
1663     return code;
1664 }
1665
1666
1667 #if 0 && defined(AFS_LINUX24_ENV)
1668 extern struct vcache *afs_globalVp;
1669
1670 int recurse_dcache_parent(parent, a_index, addr, inode, flags, time, fileName)
1671      struct dentry * parent;
1672     afs_int32 a_index;
1673     afs_int32 *addr;
1674     afs_int32 *inode;
1675     afs_int32 *flags;
1676     afs_int32 *time;
1677     char ** fileName;
1678 {
1679         struct dentry *this_parent = parent;
1680         struct list_head *next;
1681         int found = 0;
1682         struct dentry *dentry;
1683
1684 repeat:
1685         next = this_parent->d_subdirs.next;
1686 resume:
1687         while (next != &this_parent->d_subdirs) {
1688                 struct list_head *tmp = next;
1689                 dentry = list_entry(tmp, struct dentry, d_child);
1690                 if (a_index == 0)
1691                   goto searchdone3;
1692                 a_index--;
1693                 next = tmp->next;
1694                 /*
1695                  * Descend a level if the d_subdirs list is non-empty.
1696                  */
1697                 if (!list_empty(&dentry->d_subdirs)) {
1698                         this_parent = dentry;
1699                         goto repeat;
1700                 }
1701         }
1702         /*
1703          * All done at this level ... ascend and resume the search.
1704          */
1705         if (this_parent != parent) {
1706                 next = this_parent->d_child.next; 
1707                 this_parent = this_parent->d_parent;
1708                 goto resume;
1709         }
1710         goto ret;
1711
1712  searchdone3:
1713     if (d_unhashed(dentry))
1714       *flags = 1;
1715     else 
1716       *flags = 0;
1717
1718     *fileName = afs_strdup(dentry->d_name.name?dentry->d_name.name:"");
1719     *inode = ITOAFS(dentry->d_inode);
1720     *addr = atomic_read(&(dentry)->d_count);
1721     *time = dentry->d_time;
1722
1723     return 0;
1724  ret:
1725     return 1;
1726 }
1727 #endif
1728
1729 int SRXAFSCB_GetDE(struct rx_call *a_call, afs_int32 a_index, afs_int32 *addr,
1730                    afs_int32 *inode, afs_int32 *flags, afs_int32 *time,
1731                    char ** fileName)
1732 { /*SRXAFSCB_GetDE*/
1733     int code = 0;                               /*Return code*/
1734 #if 0 && defined(AFS_LINUX24_ENV)
1735     register int i;                     /*Loop variable*/
1736     register struct vcache *tvc = afs_globalVp;
1737     struct dentry *dentry;
1738     struct list_head *cur, *head = &(AFSTOI(tvc))->i_dentry;
1739
1740 #ifdef RX_ENABLE_LOCKS
1741     AFS_GLOCK();
1742 #endif /* RX_ENABLE_LOCKS */
1743
1744 #if defined(AFS_LINUX24_ENV)
1745     spin_lock(&dcache_lock);
1746 #endif
1747
1748     cur = head;
1749     while ((cur = cur->next) != head) {
1750       dentry = list_entry(cur, struct dentry, d_alias);
1751       
1752       dget_locked(dentry);
1753       
1754 #if defined(AFS_LINUX24_ENV)
1755       spin_unlock(&dcache_lock);
1756 #endif
1757       if (a_index == 0)
1758         goto searchdone2;
1759       a_index--;
1760
1761       if (recurse_dcache_parent(dentry, a_index, addr, inode, flags, time, fileName) == 0) {
1762         dput(dentry);
1763         code = 0;
1764         goto fcnDone;
1765       }
1766       dput(dentry);
1767     }                   
1768  searchdone2:
1769     if (cur == head) {
1770         /*Past EOF*/
1771         code = 1;
1772         *fileName = afs_strdup("");
1773         goto fcnDone;
1774     }
1775
1776     if (d_unhashed(dentry))
1777       *flags = 1;
1778     else 
1779       *flags = 0;
1780
1781     *fileName = afs_strdup(dentry->d_name.name?dentry->d_name.name:"");
1782     *inode = ITOAFS(dentry->d_inode);
1783     *addr = atomic_read(&(dentry)->d_count);
1784     *time = dentry->d_time;
1785
1786     dput(dentry);
1787     code = 0;
1788
1789 fcnDone:
1790
1791 #ifdef RX_ENABLE_LOCKS
1792     AFS_GUNLOCK();
1793 #endif /* RX_ENABLE_LOCKS */
1794 #endif
1795     return(code);
1796
1797 } /*SRXAFSCB_GetDE*/