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