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