Cleanup usage of LINUX_VERSION_CODE for older kernels
[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_timeval32_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 #ifdef AFS_DARWIN80_ENV
451                         if (tvc->f.states & CDeadVnode) {
452                             ReleaseReadLock(&afs_xvcache);
453                             afs_osi_Sleep(&tvc->f.states);
454                             goto loop1;
455                         }
456                         vp = AFSTOV(tvc);
457                         if (vnode_get(vp))
458                             continue;
459                         if (vnode_ref(vp)) {
460                             AFS_GUNLOCK();
461                             vnode_put(vp);
462                             AFS_GLOCK();
463                             continue;
464                         }
465 #else
466                         if (osi_vnhold(tvc) != 0) {
467                             continue;
468                         }
469 #endif
470                         ReleaseReadLock(&afs_xvcache);
471                         afs_StaleVCacheFlags(tvc, 0, CUnique | CBulkFetching);
472                         afs_allCBs++;
473                         if (tvc->f.fid.Fid.Vnode & 1)
474                             afs_oddCBs++;
475                         else
476                             afs_evenCBs++;
477                         afs_Trace3(afs_iclSetp, CM_TRACE_CALLBACK,
478                                    ICL_TYPE_POINTER, tvc, ICL_TYPE_INT32,
479                                    tvc->f.states, ICL_TYPE_INT32,
480                                    a_fid->Volume);
481 #ifdef AFS_DARWIN80_ENV
482                         vnode_put(AFSTOV(tvc));
483 #endif
484                         ObtainReadLock(&afs_xvcache);
485                         uq = QPrev(tq);
486                         AFS_FAST_RELE(tvc);
487                     } else if ((tvc->f.states & CMValid)
488                                && (tvc->mvid.target_root->Fid.Volume == a_fid->Volume)) {
489                         tvc->f.states &= ~CMValid;
490                         if (!localFid.Cell)
491                             localFid.Cell = tvc->mvid.target_root->Cell;
492                     }
493                 }
494                 ReleaseReadLock(&afs_xvcache);
495
496             /*
497              * XXXX Don't hold any locks here XXXX
498              */
499             tv = afs_FindVolume(&localFid, 0);
500             if (tv) {
501                 afs_ResetVolumeInfo(tv);
502                 afs_PutVolume(tv, 0);
503                 /* invalidate mtpoint? */
504             }
505         } /*Clear callbacks for whole volume */
506         else {
507             /*
508              * Clear callbacks just for the one file.
509              */
510             struct vcache *uvc;
511             afs_allCBs++;
512             if (a_fid->Vnode & 1)
513                 afs_oddCBs++;   /*Could do this on volume basis, too */
514             else
515                 afs_evenCBs++;  /*A particular fid was specified */
516 loop2:
517             ObtainReadLock(&afs_xvcache);
518             i = VCHash(&localFid);
519             for (tvc = afs_vhashT[i]; tvc; tvc = uvc) {
520                 uvc = tvc->hnext;
521                 if (tvc->f.fid.Fid.Vnode == a_fid->Vnode
522                     && tvc->f.fid.Fid.Volume == a_fid->Volume
523                     && tvc->f.fid.Fid.Unique == a_fid->Unique) {
524                     tvc->callback = NULL;
525                     tvc->dchint = NULL; /* invalidate hints */
526                     if (tvc->f.states & CVInit) {
527                         ReleaseReadLock(&afs_xvcache);
528                         afs_osi_Sleep(&tvc->f.states);
529                         goto loop2;
530                     }
531 #ifdef AFS_DARWIN80_ENV
532                     if (tvc->f.states & CDeadVnode) {
533                         ReleaseReadLock(&afs_xvcache);
534                         afs_osi_Sleep(&tvc->f.states);
535                         goto loop2;
536                     }
537                     vp = AFSTOV(tvc);
538                     if (vnode_get(vp))
539                         continue;
540                     if (vnode_ref(vp)) {
541                         AFS_GUNLOCK();
542                         vnode_put(vp);
543                         AFS_GLOCK();
544                         continue;
545                     }
546 #else
547                     if (osi_vnhold(tvc) != 0) {
548                         continue;
549                     }
550 #endif
551                     ReleaseReadLock(&afs_xvcache);
552                     afs_StaleVCacheFlags(tvc, 0, CUnique | CBulkFetching);
553                     afs_Trace3(afs_iclSetp, CM_TRACE_CALLBACK,
554                                ICL_TYPE_POINTER, tvc, ICL_TYPE_INT32,
555                                tvc->f.states, ICL_TYPE_LONG, 0);
556 #ifdef CBDEBUG
557                     lastCallBack_vnode = afid->Vnode;
558                     lastCallBack_dv = tvc->mstat.DataVersion.low;
559                     osi_GetTime(&lastCallBack_time);
560 #endif /* CBDEBUG */
561 #ifdef AFS_DARWIN80_ENV
562                     vnode_put(AFSTOV(tvc));
563 #endif
564                     ObtainReadLock(&afs_xvcache);
565                     uvc = tvc->hnext;
566                     AFS_FAST_RELE(tvc);
567                 }
568             }                   /*Walk through hash table */
569             ReleaseReadLock(&afs_xvcache);
570         }                       /*Clear callbacks for one file */
571     }
572
573     /*Fid has non-zero volume ID */
574     /*
575      * Always return a predictable value.
576      */
577     return (0);
578
579 }                               /*ClearCallBack */
580
581
582 /*------------------------------------------------------------------------
583  * EXPORTED SRXAFSCB_CallBack
584  *
585  * Description:
586  *      Routine called by the server-side callback RPC interface to
587  *      implement passing in callback information.
588  *      table.
589  *
590  * Arguments:
591  *      a_call      : Ptr to Rx call on which this request came in.
592  *      a_fids      : Ptr to array of fids involved.
593  *      a_callbacks : Ptr to matching callback info for the fids.
594  *
595  * Returns:
596  *      0 (always).
597  *
598  * Environment:
599  *      Nothing interesting.
600  *
601  * Side Effects:
602  *      As advertised.
603  *------------------------------------------------------------------------*/
604
605 int
606 SRXAFSCB_CallBack(struct rx_call *a_call, struct AFSCBFids *a_fids,
607                   struct AFSCBs *a_callbacks)
608 {
609     int i;              /*Loop variable */
610     struct AFSFid *tfid;        /*Ptr to current fid */
611     struct rx_connection *tconn;        /*Call's connection */
612     int code = 0;
613     XSTATS_DECLS;
614
615     RX_AFS_GLOCK();
616
617     XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_CALLBACK);
618
619     AFS_STATCNT(SRXAFSCB_CallBack);
620     if (!(tconn = rx_ConnectionOf(a_call)))
621         return (0);
622     tfid = (struct AFSFid *)a_fids->AFSCBFids_val;
623
624     /*
625      * For now, we ignore callbacks, since the File Server only *breaks*
626      * callbacks at present.
627      */
628     for (i = 0; i < a_fids->AFSCBFids_len; i++)
629         ClearCallBack(tconn, &tfid[i]);
630
631     XSTATS_END_TIME;
632
633     RX_AFS_GUNLOCK();
634
635     return (0);
636
637 }                               /*SRXAFSCB_CallBack */
638
639
640 /*------------------------------------------------------------------------
641  * EXPORTED SRXAFSCB_Probe
642  *
643  * Description:
644  *      Routine called by the server-side callback RPC interface to
645  *      implement ``probing'' the Cache Manager, just making sure it's
646  *      still there.
647  *
648  * Arguments:
649  *      a_call : Ptr to Rx call on which this request came in.
650  *
651  * Returns:
652  *      0 (always).
653  *
654  * Environment:
655  *      Nothing interesting.
656  *
657  * Side Effects:
658  *      As advertised.
659  *------------------------------------------------------------------------*/
660
661 int
662 SRXAFSCB_Probe(struct rx_call *a_call)
663 {
664     int code = 0;
665     XSTATS_DECLS;
666
667     RX_AFS_GLOCK();
668     AFS_STATCNT(SRXAFSCB_Probe);
669
670     XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_PROBE);
671     XSTATS_END_TIME;
672
673     RX_AFS_GUNLOCK();
674
675     return (0);
676
677 }                               /*SRXAFSCB_Probe */
678
679
680 /*------------------------------------------------------------------------
681  * EXPORTED SRXAFSCB_InitCallBackState
682  *
683  * Description:
684  *      Routine called by the server-side callback RPC interface to
685  *      implement clearing all callbacks from this host.
686  *
687  * Arguments:
688  *      a_call : Ptr to Rx call on which this request came in.
689  *
690  * Returns:
691  *      0 (always).
692  *
693  * Environment:
694  *      Nothing interesting.
695  *
696  * Side Effects:
697  *      As advertised.
698  *------------------------------------------------------------------------*/
699
700 int
701 SRXAFSCB_InitCallBackState(struct rx_call *a_call)
702 {
703     int i;
704     struct vcache *tvc;
705     struct rx_connection *tconn;
706     struct rx_peer *peer;
707     struct server *ts;
708     int code = 0;
709     XSTATS_DECLS;
710
711     RX_AFS_GLOCK();
712
713     XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_INITCALLBACKSTATE);
714     AFS_STATCNT(SRXAFSCB_InitCallBackState);
715
716     /*
717      * Find the address of the host making this call
718      */
719     if ((tconn = rx_ConnectionOf(a_call)) && (peer = rx_PeerOf(tconn))) {
720
721         afs_allCBs++;
722         afs_oddCBs++;           /*Including any missed via create race */
723         afs_evenCBs++;          /*Including any missed via create race */
724
725         ts = afs_FindServer(rx_HostOf(peer), rx_PortOf(peer), (afsUUID *) 0,
726                             0);
727         if (ts) {
728             for (i = 0; i < VCSIZE; i++)
729                 for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
730                     if (tvc->callback == ts) {
731                         afs_StaleVCacheFlags(tvc, AFS_STALEVC_NODNLC |
732                                                   AFS_STALEVC_CLEARCB,
733                                              CUnique | CBulkFetching);
734                     }
735                 }
736
737             /* capabilities need be requested again */
738             ts->flags &= ~SCAPS_KNOWN;
739         }
740
741
742
743         /* find any volumes residing on this server and flush their state */
744         {
745             struct volume *tv;
746             int j;
747
748             for (i = 0; i < NVOLS; i++)
749                 for (tv = afs_volumes[i]; tv; tv = tv->next) {
750                     for (j = 0; j < AFS_MAXHOSTS; j++)
751                         if (tv->serverHost[j] == ts)
752                             afs_ResetVolumeInfo(tv);
753                 }
754         }
755         osi_dnlc_purge();       /* may be a little bit extreme */
756     }
757
758     XSTATS_END_TIME;
759
760     RX_AFS_GUNLOCK();
761
762     return (0);
763
764 }                               /*SRXAFSCB_InitCallBackState */
765
766
767 /*------------------------------------------------------------------------
768  * EXPORTED SRXAFSCB_XStatsVersion
769  *
770  * Description:
771  *      Routine called by the server-side callback RPC interface to
772  *      implement pulling out the xstat version number for the Cache
773  *      Manager.
774  *
775  * Arguments:
776  *      a_versionP : Ptr to the version number variable to set.
777  *
778  * Returns:
779  *      0 (always)
780  *
781  * Environment:
782  *      Nothing interesting.
783  *
784  * Side Effects:
785  *      As advertised.
786  *------------------------------------------------------------------------*/
787
788 int
789 SRXAFSCB_XStatsVersion(struct rx_call *a_call, afs_int32 * a_versionP)
790 {
791     int code = 0;
792
793     XSTATS_DECLS;
794
795     RX_AFS_GLOCK();
796     XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_XSTATSVERSION);
797
798     *a_versionP = AFSCB_XSTAT_VERSION;
799
800     XSTATS_END_TIME;
801
802     RX_AFS_GUNLOCK();
803
804     return (0);
805 }                               /*SRXAFSCB_XStatsVersion */
806
807
808 /*------------------------------------------------------------------------
809  * EXPORTED SRXAFSCB_GetXStats
810  *
811  * Description:
812  *      Routine called by the server-side callback RPC interface to
813  *      implement getting the given data collection from the extended
814  *      Cache Manager statistics.
815  *
816  * Arguments:
817  *      a_call              : Ptr to Rx call on which this request came in.
818  *      a_clientVersionNum  : Client version number.
819  *      a_opCode            : Desired operation.
820  *      a_serverVersionNumP : Ptr to version number to set.
821  *      a_timeP             : Ptr to time value (seconds) to set.
822  *      a_dataArray         : Ptr to variable array structure to return
823  *                            stuff in.
824  *
825  * Returns:
826  *      0 (always).
827  *
828  * Environment:
829  *      Nothing interesting.
830  *
831  * Side Effects:
832  *      As advertised.
833  *------------------------------------------------------------------------*/
834
835 int
836 SRXAFSCB_GetXStats(struct rx_call *a_call, afs_int32 a_clientVersionNum,
837                    afs_int32 a_collectionNumber, afs_int32 * a_srvVersionNumP,
838                    afs_int32 * a_timeP, AFSCB_CollData * a_dataP)
839 {
840     int code;           /*Return value */
841     afs_int32 *dataBuffP;       /*Ptr to data to be returned */
842     afs_int32 dataBytes;        /*Bytes in data buffer */
843     XSTATS_DECLS;
844
845     RX_AFS_GLOCK();
846
847     XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_GETXSTATS);
848
849     /*
850      * Record the time of day and the server version number.
851      */
852     *a_srvVersionNumP = AFSCB_XSTAT_VERSION;
853     *a_timeP = osi_Time();
854
855     /*
856      * Stuff the appropriate data in there (assume victory)
857      */
858     code = 0;
859
860 #ifdef AFS_NOSTATS
861     /*
862      * We're not keeping stats, so just return successfully with
863      * no data.
864      */
865     a_dataP->AFSCB_CollData_len = 0;
866     a_dataP->AFSCB_CollData_val = NULL;
867 #else
868     switch (a_collectionNumber) {
869     case AFSCB_XSTATSCOLL_CALL_INFO:
870         /*
871          * Pass back all the call-count-related data.
872          *
873          * >>> We are forced to allocate a separate area in which to
874          * >>> put this stuff in by the RPC stub generator, since it
875          * >>> will be freed at the tail end of the server stub code.
876          */
877         dataBytes = sizeof(struct afs_CMStats);
878         dataBuffP = (afs_int32 *) afs_osi_Alloc(dataBytes);
879         osi_Assert(dataBuffP != NULL);
880         memcpy((char *)dataBuffP, (char *)&afs_cmstats, dataBytes);
881         a_dataP->AFSCB_CollData_len = dataBytes >> 2;
882         a_dataP->AFSCB_CollData_val = dataBuffP;
883         break;
884
885     case AFSCB_XSTATSCOLL_PERF_INFO:
886         /*
887          * Update and then pass back all the performance-related data.
888          * Note: the only performance fields that need to be computed
889          * at this time are the number of accesses for this collection
890          * and the current server record info.
891          *
892          * >>> We are forced to allocate a separate area in which to
893          * >>> put this stuff in by the RPC stub generator, since it
894          * >>> will be freed at the tail end of the server stub code.
895          */
896         afs_stats_cmperf.numPerfCalls++;
897         afs_CountServers();
898         dataBytes = sizeof(afs_stats_cmperf);
899         dataBuffP = (afs_int32 *) afs_osi_Alloc(dataBytes);
900         osi_Assert(dataBuffP != NULL);
901         memcpy((char *)dataBuffP, (char *)&afs_stats_cmperf, dataBytes);
902         a_dataP->AFSCB_CollData_len = dataBytes >> 2;
903         a_dataP->AFSCB_CollData_val = dataBuffP;
904         break;
905
906     case AFSCB_XSTATSCOLL_FULL_PERF_INFO:
907         /*
908          * Pass back the full range of performance and statistical
909          * data available.  We have to bring the normal performance
910          * data collection up to date, then copy that data into
911          * the full collection.
912          *
913          * >>> We are forced to allocate a separate area in which to
914          * >>> put this stuff in by the RPC stub generator, since it
915          * >>> will be freed at the tail end of the server stub code.
916          */
917         afs_stats_cmperf.numPerfCalls++;
918         afs_CountServers();
919         memcpy((char *)(&(afs_stats_cmfullperf.perf)),
920                (char *)(&afs_stats_cmperf), sizeof(struct afs_stats_CMPerf));
921         afs_stats_cmfullperf.numFullPerfCalls++;
922
923         dataBytes = sizeof(afs_stats_cmfullperf);
924         dataBuffP = (afs_int32 *) afs_osi_Alloc(dataBytes);
925         osi_Assert(dataBuffP != NULL);
926         memcpy((char *)dataBuffP, (char *)(&afs_stats_cmfullperf), dataBytes);
927         a_dataP->AFSCB_CollData_len = dataBytes >> 2;
928         a_dataP->AFSCB_CollData_val = dataBuffP;
929         break;
930
931     default:
932         /*
933          * Illegal collection number.
934          */
935         a_dataP->AFSCB_CollData_len = 0;
936         a_dataP->AFSCB_CollData_val = NULL;
937         code = 1;
938     }                           /*Switch on collection number */
939 #endif /* AFS_NOSTATS */
940
941     XSTATS_END_TIME;
942
943     RX_AFS_GUNLOCK();
944
945     return (code);
946
947 }                               /*SRXAFSCB_GetXStats */
948
949
950 /*------------------------------------------------------------------------
951  * EXPORTED afs_RXCallBackServer
952  *
953  * Description:
954  *      Body of the thread supporting callback services.
955  *
956  * Arguments:
957  *      None.
958  *
959  * Returns:
960  *      0 (always).
961  *
962  * Environment:
963  *      Nothing interesting.
964  *
965  * Side Effects:
966  *      As advertised.
967  *------------------------------------------------------------------------*/
968
969 int
970 afs_RXCallBackServer(void)
971 {
972     AFS_STATCNT(afs_RXCallBackServer);
973
974     while (1) {
975         if (afs_server)
976             break;
977         afs_osi_Sleep(&afs_server);
978     }
979
980     /*
981      * Donate this process to Rx.
982      */
983     rx_ServerProc(NULL);
984     return (0);
985
986 }                               /*afs_RXCallBackServer */
987
988
989 /*------------------------------------------------------------------------
990  * EXPORTED shutdown_CB
991  *
992  * Description:
993  *      Zero out important Cache Manager data structures.
994  *
995  * Arguments:
996  *      None.
997  *
998  * Returns:
999  *      0 (always).
1000  *
1001  * Environment:
1002  *      Nothing interesting.
1003  *
1004  * Side Effects:
1005  *      As advertised.
1006  *------------------------------------------------------------------------*/
1007
1008 int
1009 shutdown_CB(void)
1010 {
1011     AFS_STATCNT(shutdown_CB);
1012
1013     if (afs_cold_shutdown) {
1014         afs_oddCBs = afs_evenCBs = afs_allCBs = afs_allZaps = afs_oddZaps =
1015             afs_evenZaps = afs_connectBacks = 0;
1016     }
1017
1018     return (0);
1019
1020 }                               /*shutdown_CB */
1021
1022 /*------------------------------------------------------------------------
1023  * EXPORTED SRXAFSCB_InitCallBackState2
1024  *
1025  * Description:
1026  *      This routine was used in the AFS 3.5 beta release, but not anymore.
1027  *      It has since been replaced by SRXAFSCB_InitCallBackState3.
1028  *
1029  * Arguments:
1030  *      a_call : Ptr to Rx call on which this request came in.
1031  *
1032  * Returns:
1033  *      RXGEN_OPCODE (always).
1034  *
1035  * Environment:
1036  *      Nothing interesting.
1037  *
1038  * Side Effects:
1039  *      None
1040  *------------------------------------------------------------------------*/
1041
1042 int
1043 SRXAFSCB_InitCallBackState2(struct rx_call *a_call,
1044                             struct interfaceAddr *addr)
1045 {
1046     return RXGEN_OPCODE;
1047 }
1048
1049 /*------------------------------------------------------------------------
1050  * EXPORTED SRXAFSCB_WhoAreYou
1051  *
1052  * Description:
1053  *      Routine called by the server-side callback RPC interface to
1054  *      obtain a unique identifier for the client. The server uses
1055  *      this identifier to figure out whether or not two RX connections
1056  *      are from the same client, and to find out which addresses go
1057  *      with which clients.
1058  *
1059  * Arguments:
1060  *      a_call : Ptr to Rx call on which this request came in.
1061  *      addr: Ptr to return the list of interfaces for this client.
1062  *
1063  * Returns:
1064  *      0 (Always)
1065  *
1066  * Environment:
1067  *      Nothing interesting.
1068  *
1069  * Side Effects:
1070  *      As advertised.
1071  *------------------------------------------------------------------------*/
1072
1073 int
1074 SRXAFSCB_WhoAreYou(struct rx_call *a_call, struct interfaceAddr *addr)
1075 {
1076     int i;
1077     int code = 0;
1078
1079     RX_AFS_GLOCK();
1080
1081     AFS_STATCNT(SRXAFSCB_WhoAreYou);
1082
1083     memset(addr, 0, sizeof(*addr));
1084
1085     ObtainReadLock(&afs_xinterface);
1086
1087     /* return all network interface addresses */
1088     addr->numberOfInterfaces = afs_cb_interface.numberOfInterfaces;
1089     addr->uuid = afs_cb_interface.uuid;
1090     for (i = 0; i < afs_cb_interface.numberOfInterfaces; i++) {
1091         addr->addr_in[i] = ntohl(afs_cb_interface.addr_in[i]);
1092         addr->subnetmask[i] = ntohl(afs_cb_interface.subnetmask[i]);
1093         addr->mtu[i] = ntohl(afs_cb_interface.mtu[i]);
1094     }
1095
1096     ReleaseReadLock(&afs_xinterface);
1097
1098     RX_AFS_GUNLOCK();
1099
1100     return code;
1101 }
1102
1103
1104 /*------------------------------------------------------------------------
1105  * EXPORTED SRXAFSCB_InitCallBackState3
1106  *
1107  * Description:
1108  *      Routine called by the server-side callback RPC interface to
1109  *      implement clearing all callbacks from this host.
1110  *
1111  * Arguments:
1112  *      a_call : Ptr to Rx call on which this request came in.
1113  *
1114  * Returns:
1115  *      0 (always).
1116  *
1117  * Environment:
1118  *      Nothing interesting.
1119  *
1120  * Side Effects:
1121  *      As advertised.
1122  *------------------------------------------------------------------------*/
1123
1124 int
1125 SRXAFSCB_InitCallBackState3(struct rx_call *a_call, afsUUID * a_uuid)
1126 {
1127     int code;
1128
1129     /*
1130      * TBD: Lookup the server by the UUID instead of its IP address.
1131      */
1132     code = SRXAFSCB_InitCallBackState(a_call);
1133
1134     return code;
1135 }
1136
1137
1138 /*------------------------------------------------------------------------
1139  * EXPORTED SRXAFSCB_ProbeUuid
1140  *
1141  * Description:
1142  *      Routine called by the server-side callback RPC interface to
1143  *      implement ``probing'' the Cache Manager, just making sure it's
1144  *      still there is still the same client it used to be.
1145  *
1146  * Arguments:
1147  *      a_call : Ptr to Rx call on which this request came in.
1148  *      a_uuid : Ptr to UUID that must match the client's UUID.
1149  *
1150  * Returns:
1151  *      0 if a_uuid matches the UUID for this client
1152  *      Non-zero otherwize
1153  *
1154  * Environment:
1155  *      Nothing interesting.
1156  *
1157  * Side Effects:
1158  *      As advertised.
1159  *------------------------------------------------------------------------*/
1160
1161 int
1162 SRXAFSCB_ProbeUuid(struct rx_call *a_call, afsUUID * a_uuid)
1163 {
1164     int code = 0;
1165     XSTATS_DECLS;
1166
1167     RX_AFS_GLOCK();
1168     AFS_STATCNT(SRXAFSCB_Probe);
1169
1170     XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_PROBE);
1171     if (!afs_uuid_equal(a_uuid, &afs_cb_interface.uuid))
1172         code = 1;               /* failure */
1173     XSTATS_END_TIME;
1174
1175     RX_AFS_GUNLOCK();
1176
1177     return code;
1178 }
1179
1180
1181 /*------------------------------------------------------------------------
1182  * EXPORTED SRXAFSCB_GetServerPrefs
1183  *
1184  * Description:
1185  *      Routine to list server preferences used by this client.
1186  *
1187  * Arguments:
1188  *      a_call  : Ptr to Rx call on which this request came in.
1189  *      a_index : Input server index
1190  *      a_srvr_addr  : Output server address in host byte order
1191  *                     (0xffffffff on last server)
1192  *      a_srvr_rank  : Output server rank
1193  *
1194  * Returns:
1195  *      0 on success
1196  *
1197  * Environment:
1198  *      Nothing interesting.
1199  *
1200  * Side Effects:
1201  *      As advertised.
1202  *------------------------------------------------------------------------*/
1203
1204 int
1205 SRXAFSCB_GetServerPrefs(struct rx_call *a_call, afs_int32 a_index,
1206                         afs_int32 * a_srvr_addr, afs_int32 * a_srvr_rank)
1207 {
1208     int i, j;
1209     struct srvAddr *sa;
1210
1211     RX_AFS_GLOCK();
1212     AFS_STATCNT(SRXAFSCB_GetServerPrefs);
1213
1214     ObtainReadLock(&afs_xserver);
1215
1216     /* Search the hash table for the server with this index */
1217     *a_srvr_addr = 0xffffffff;
1218     *a_srvr_rank = 0xffffffff;
1219     for (i = 0, j = 0; j < NSERVERS && i <= a_index; j++) {
1220         for (sa = afs_srvAddrs[j]; sa && i <= a_index; sa = sa->next_bkt, i++) {
1221             if (i == a_index) {
1222                 *a_srvr_addr = ntohl(sa->sa_ip);
1223                 *a_srvr_rank = sa->sa_iprank;
1224             }
1225         }
1226     }
1227
1228     ReleaseReadLock(&afs_xserver);
1229
1230     RX_AFS_GUNLOCK();
1231
1232     return 0;
1233 }
1234
1235
1236 /*------------------------------------------------------------------------
1237  * EXPORTED SRXAFSCB_GetCellServDB
1238  *
1239  * Description:
1240  *      Routine to list cells configured for this client
1241  *
1242  * Arguments:
1243  *      a_call  : Ptr to Rx call on which this request came in.
1244  *      a_index : Input cell index
1245  *      a_name  : Output cell name ("" on last cell)
1246  *      a_hosts : Output cell database servers in host byte order.
1247  *
1248  * Returns:
1249  *      0 on success
1250  *
1251  * Environment:
1252  *      Nothing interesting.
1253  *
1254  * Side Effects:
1255  *      As advertised.
1256  *------------------------------------------------------------------------*/
1257
1258 int
1259 SRXAFSCB_GetCellServDB(struct rx_call *a_call, afs_int32 a_index,
1260                        char **a_name, serverList * a_hosts)
1261 {
1262     afs_int32 i, j = 0;
1263     struct cell *tcell;
1264     char *t_name, *p_name = NULL;
1265
1266     RX_AFS_GLOCK();
1267     AFS_STATCNT(SRXAFSCB_GetCellServDB);
1268
1269     tcell = afs_GetCellByIndex(a_index, READ_LOCK);
1270
1271     if (!tcell) {
1272         i = 0;
1273         a_hosts->serverList_val = 0;
1274         a_hosts->serverList_len = 0;
1275     } else {
1276         p_name = tcell->cellName;
1277         for (j = 0; j < AFSMAXCELLHOSTS && tcell->cellHosts[j]; j++);
1278         i = strlen(p_name);
1279         a_hosts->serverList_val = afs_osi_Alloc(j * sizeof(afs_int32));
1280         osi_Assert(a_hosts->serverList_val != NULL);
1281         a_hosts->serverList_len = j;
1282         for (j = 0; j < AFSMAXCELLHOSTS && tcell->cellHosts[j]; j++)
1283             a_hosts->serverList_val[j] =
1284                 ntohl(tcell->cellHosts[j]->addr->sa_ip);
1285         afs_PutCell(tcell, READ_LOCK);
1286     }
1287
1288     t_name = afs_osi_Alloc(i + 1);
1289     if (t_name == NULL) {
1290         if (tcell != 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 = 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_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 = afs_osi_Alloc(sn * sizeof(afs_int32));
1586     osi_Assert(a_hosts->serverList_val != NULL);
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_uint32 *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     memset(addr, 0, sizeof(*addr));
1615     addr->numberOfInterfaces = afs_cb_interface.numberOfInterfaces;
1616     addr->uuid = afs_cb_interface.uuid;
1617     for (i = 0; i < afs_cb_interface.numberOfInterfaces; i++) {
1618         addr->addr_in[i] = ntohl(afs_cb_interface.addr_in[i]);
1619         addr->subnetmask[i] = ntohl(afs_cb_interface.subnetmask[i]);
1620         addr->mtu[i] = ntohl(afs_cb_interface.mtu[i]);
1621     }
1622
1623     ReleaseReadLock(&afs_xinterface);
1624
1625     RX_AFS_GUNLOCK();
1626
1627     dataBytes = 1 * sizeof(afs_uint32);
1628     dataBuffP = afs_osi_Alloc(dataBytes);
1629     osi_Assert(dataBuffP != NULL);
1630     dataBuffP[0] = CLIENT_CAPABILITY_ERRORTRANS;
1631     capabilities->Capabilities_len = dataBytes / sizeof(afs_uint32);
1632     capabilities->Capabilities_val = dataBuffP;
1633
1634     return code;
1635 }