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