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