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