61b2a75b7a20b3af63e2152cf58849872eaac41d
[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                         afs_StaleVCacheFlags(tvc, 0, CUnique | CBulkFetching);
477                         afs_allCBs++;
478                         if (tvc->f.fid.Fid.Vnode & 1)
479                             afs_oddCBs++;
480                         else
481                             afs_evenCBs++;
482                         afs_Trace3(afs_iclSetp, CM_TRACE_CALLBACK,
483                                    ICL_TYPE_POINTER, tvc, ICL_TYPE_INT32,
484                                    tvc->f.states, ICL_TYPE_INT32,
485                                    a_fid->Volume);
486 #ifdef AFS_DARWIN80_ENV
487                         vnode_put(AFSTOV(tvc));
488 #endif
489                         ObtainReadLock(&afs_xvcache);
490                         uq = QPrev(tq);
491                         AFS_FAST_RELE(tvc);
492                     } else if ((tvc->f.states & CMValid)
493                                && (tvc->mvid.target_root->Fid.Volume == a_fid->Volume)) {
494                         tvc->f.states &= ~CMValid;
495                         if (!localFid.Cell)
496                             localFid.Cell = tvc->mvid.target_root->Cell;
497                     }
498                 }
499                 ReleaseReadLock(&afs_xvcache);
500
501             /*
502              * XXXX Don't hold any locks here XXXX
503              */
504             tv = afs_FindVolume(&localFid, 0);
505             if (tv) {
506                 afs_ResetVolumeInfo(tv);
507                 afs_PutVolume(tv, 0);
508                 /* invalidate mtpoint? */
509             }
510         } /*Clear callbacks for whole volume */
511         else {
512             /*
513              * Clear callbacks just for the one file.
514              */
515             struct vcache *uvc;
516             afs_allCBs++;
517             if (a_fid->Vnode & 1)
518                 afs_oddCBs++;   /*Could do this on volume basis, too */
519             else
520                 afs_evenCBs++;  /*A particular fid was specified */
521 loop2:
522             ObtainReadLock(&afs_xvcache);
523             i = VCHash(&localFid);
524             for (tvc = afs_vhashT[i]; tvc; tvc = uvc) {
525                 uvc = tvc->hnext;
526                 if (tvc->f.fid.Fid.Vnode == a_fid->Vnode
527                     && tvc->f.fid.Fid.Volume == a_fid->Volume
528                     && tvc->f.fid.Fid.Unique == a_fid->Unique) {
529                     tvc->callback = NULL;
530                     tvc->dchint = NULL; /* invalidate hints */
531                     if (tvc->f.states & CVInit) {
532                         ReleaseReadLock(&afs_xvcache);
533                         afs_osi_Sleep(&tvc->f.states);
534                         goto loop2;
535                     }
536 #if     defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)  || defined(AFS_HPUX_ENV) || defined(AFS_LINUX20_ENV)
537                     AFS_FAST_HOLD(tvc);
538 #else
539 #ifdef AFS_DARWIN80_ENV
540                     if (tvc->f.states & CDeadVnode) {
541                         ReleaseReadLock(&afs_xvcache);
542                         afs_osi_Sleep(&tvc->f.states);
543                         goto loop2;
544                     }
545                     vp = AFSTOV(tvc);
546                     if (vnode_get(vp))
547                         continue;
548                     if (vnode_ref(vp)) {
549                         AFS_GUNLOCK();
550                         vnode_put(vp);
551                         AFS_GLOCK();
552                         continue;
553                     }
554 #else
555                     AFS_FAST_HOLD(tvc);
556 #endif
557 #endif
558                     ReleaseReadLock(&afs_xvcache);
559                     afs_StaleVCacheFlags(tvc, 0, CUnique | CBulkFetching);
560                     afs_Trace3(afs_iclSetp, CM_TRACE_CALLBACK,
561                                ICL_TYPE_POINTER, tvc, ICL_TYPE_INT32,
562                                tvc->f.states, ICL_TYPE_LONG, 0);
563 #ifdef CBDEBUG
564                     lastCallBack_vnode = afid->Vnode;
565                     lastCallBack_dv = tvc->mstat.DataVersion.low;
566                     osi_GetuTime(&lastCallBack_time);
567 #endif /* CBDEBUG */
568 #ifdef AFS_DARWIN80_ENV
569                     vnode_put(AFSTOV(tvc));
570 #endif
571                     ObtainReadLock(&afs_xvcache);
572                     uvc = tvc->hnext;
573                     AFS_FAST_RELE(tvc);
574                 }
575             }                   /*Walk through hash table */
576             ReleaseReadLock(&afs_xvcache);
577         }                       /*Clear callbacks for one file */
578     }
579
580     /*Fid has non-zero volume ID */
581     /*
582      * Always return a predictable value.
583      */
584     return (0);
585
586 }                               /*ClearCallBack */
587
588
589 /*------------------------------------------------------------------------
590  * EXPORTED SRXAFSCB_CallBack
591  *
592  * Description:
593  *      Routine called by the server-side callback RPC interface to
594  *      implement passing in callback information.
595  *      table.
596  *
597  * Arguments:
598  *      a_call      : Ptr to Rx call on which this request came in.
599  *      a_fids      : Ptr to array of fids involved.
600  *      a_callbacks : Ptr to matching callback info for the fids.
601  *
602  * Returns:
603  *      0 (always).
604  *
605  * Environment:
606  *      Nothing interesting.
607  *
608  * Side Effects:
609  *      As advertised.
610  *------------------------------------------------------------------------*/
611
612 int
613 SRXAFSCB_CallBack(struct rx_call *a_call, struct AFSCBFids *a_fids,
614                   struct AFSCBs *a_callbacks)
615 {
616     int i;              /*Loop variable */
617     struct AFSFid *tfid;        /*Ptr to current fid */
618     struct rx_connection *tconn;        /*Call's connection */
619     int code = 0;
620     XSTATS_DECLS;
621
622     RX_AFS_GLOCK();
623
624     XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_CALLBACK);
625
626     AFS_STATCNT(SRXAFSCB_CallBack);
627     if (!(tconn = rx_ConnectionOf(a_call)))
628         return (0);
629     tfid = (struct AFSFid *)a_fids->AFSCBFids_val;
630
631     /*
632      * For now, we ignore callbacks, since the File Server only *breaks*
633      * callbacks at present.
634      */
635     for (i = 0; i < a_fids->AFSCBFids_len; i++)
636         ClearCallBack(tconn, &tfid[i]);
637
638     XSTATS_END_TIME;
639
640     RX_AFS_GUNLOCK();
641
642     return (0);
643
644 }                               /*SRXAFSCB_CallBack */
645
646
647 /*------------------------------------------------------------------------
648  * EXPORTED SRXAFSCB_Probe
649  *
650  * Description:
651  *      Routine called by the server-side callback RPC interface to
652  *      implement ``probing'' the Cache Manager, just making sure it's
653  *      still there.
654  *
655  * Arguments:
656  *      a_call : Ptr to Rx call on which this request came in.
657  *
658  * Returns:
659  *      0 (always).
660  *
661  * Environment:
662  *      Nothing interesting.
663  *
664  * Side Effects:
665  *      As advertised.
666  *------------------------------------------------------------------------*/
667
668 int
669 SRXAFSCB_Probe(struct rx_call *a_call)
670 {
671     int code = 0;
672     XSTATS_DECLS;
673
674     RX_AFS_GLOCK();
675     AFS_STATCNT(SRXAFSCB_Probe);
676
677     XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_PROBE);
678     XSTATS_END_TIME;
679
680     RX_AFS_GUNLOCK();
681
682     return (0);
683
684 }                               /*SRXAFSCB_Probe */
685
686
687 /*------------------------------------------------------------------------
688  * EXPORTED SRXAFSCB_InitCallBackState
689  *
690  * Description:
691  *      Routine called by the server-side callback RPC interface to
692  *      implement clearing all callbacks from this host.
693  *
694  * Arguments:
695  *      a_call : Ptr to Rx call on which this request came in.
696  *
697  * Returns:
698  *      0 (always).
699  *
700  * Environment:
701  *      Nothing interesting.
702  *
703  * Side Effects:
704  *      As advertised.
705  *------------------------------------------------------------------------*/
706
707 int
708 SRXAFSCB_InitCallBackState(struct rx_call *a_call)
709 {
710     int i;
711     struct vcache *tvc;
712     struct rx_connection *tconn;
713     struct rx_peer *peer;
714     struct server *ts;
715     int code = 0;
716     XSTATS_DECLS;
717
718     RX_AFS_GLOCK();
719
720     XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_INITCALLBACKSTATE);
721     AFS_STATCNT(SRXAFSCB_InitCallBackState);
722
723     /*
724      * Find the address of the host making this call
725      */
726     if ((tconn = rx_ConnectionOf(a_call)) && (peer = rx_PeerOf(tconn))) {
727
728         afs_allCBs++;
729         afs_oddCBs++;           /*Including any missed via create race */
730         afs_evenCBs++;          /*Including any missed via create race */
731
732         ts = afs_FindServer(rx_HostOf(peer), rx_PortOf(peer), (afsUUID *) 0,
733                             0);
734         if (ts) {
735             for (i = 0; i < VCSIZE; i++)
736                 for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
737                     if (tvc->callback == ts) {
738                         afs_StaleVCacheFlags(tvc, AFS_STALEVC_NODNLC |
739                                                   AFS_STALEVC_CLEARCB,
740                                              CUnique | CBulkFetching);
741                     }
742                 }
743
744             /* capabilities need be requested again */
745             ts->flags &= ~SCAPS_KNOWN;
746         }
747
748
749
750         /* find any volumes residing on this server and flush their state */
751         {
752             struct volume *tv;
753             int j;
754
755             for (i = 0; i < NVOLS; i++)
756                 for (tv = afs_volumes[i]; tv; tv = tv->next) {
757                     for (j = 0; j < AFS_MAXHOSTS; j++)
758                         if (tv->serverHost[j] == ts)
759                             afs_ResetVolumeInfo(tv);
760                 }
761         }
762         osi_dnlc_purge();       /* may be a little bit extreme */
763     }
764
765     XSTATS_END_TIME;
766
767     RX_AFS_GUNLOCK();
768
769     return (0);
770
771 }                               /*SRXAFSCB_InitCallBackState */
772
773
774 /*------------------------------------------------------------------------
775  * EXPORTED SRXAFSCB_XStatsVersion
776  *
777  * Description:
778  *      Routine called by the server-side callback RPC interface to
779  *      implement pulling out the xstat version number for the Cache
780  *      Manager.
781  *
782  * Arguments:
783  *      a_versionP : Ptr to the version number variable to set.
784  *
785  * Returns:
786  *      0 (always)
787  *
788  * Environment:
789  *      Nothing interesting.
790  *
791  * Side Effects:
792  *      As advertised.
793  *------------------------------------------------------------------------*/
794
795 int
796 SRXAFSCB_XStatsVersion(struct rx_call *a_call, afs_int32 * a_versionP)
797 {
798     int code = 0;
799
800     XSTATS_DECLS;
801
802     RX_AFS_GLOCK();
803     XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_XSTATSVERSION);
804
805     *a_versionP = AFSCB_XSTAT_VERSION;
806
807     XSTATS_END_TIME;
808
809     RX_AFS_GUNLOCK();
810
811     return (0);
812 }                               /*SRXAFSCB_XStatsVersion */
813
814
815 /*------------------------------------------------------------------------
816  * EXPORTED SRXAFSCB_GetXStats
817  *
818  * Description:
819  *      Routine called by the server-side callback RPC interface to
820  *      implement getting the given data collection from the extended
821  *      Cache Manager statistics.
822  *
823  * Arguments:
824  *      a_call              : Ptr to Rx call on which this request came in.
825  *      a_clientVersionNum  : Client version number.
826  *      a_opCode            : Desired operation.
827  *      a_serverVersionNumP : Ptr to version number to set.
828  *      a_timeP             : Ptr to time value (seconds) to set.
829  *      a_dataArray         : Ptr to variable array structure to return
830  *                            stuff in.
831  *
832  * Returns:
833  *      0 (always).
834  *
835  * Environment:
836  *      Nothing interesting.
837  *
838  * Side Effects:
839  *      As advertised.
840  *------------------------------------------------------------------------*/
841
842 int
843 SRXAFSCB_GetXStats(struct rx_call *a_call, afs_int32 a_clientVersionNum,
844                    afs_int32 a_collectionNumber, afs_int32 * a_srvVersionNumP,
845                    afs_int32 * a_timeP, AFSCB_CollData * a_dataP)
846 {
847     int code;           /*Return value */
848     afs_int32 *dataBuffP;       /*Ptr to data to be returned */
849     afs_int32 dataBytes;        /*Bytes in data buffer */
850     XSTATS_DECLS;
851
852     RX_AFS_GLOCK();
853
854     XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_GETXSTATS);
855
856     /*
857      * Record the time of day and the server version number.
858      */
859     *a_srvVersionNumP = AFSCB_XSTAT_VERSION;
860     *a_timeP = osi_Time();
861
862     /*
863      * Stuff the appropriate data in there (assume victory)
864      */
865     code = 0;
866
867 #ifdef AFS_NOSTATS
868     /*
869      * We're not keeping stats, so just return successfully with
870      * no data.
871      */
872     a_dataP->AFSCB_CollData_len = 0;
873     a_dataP->AFSCB_CollData_val = NULL;
874 #else
875     switch (a_collectionNumber) {
876     case AFSCB_XSTATSCOLL_CALL_INFO:
877         /*
878          * Pass back all the call-count-related data.
879          *
880          * >>> We are forced to allocate a separate area in which to
881          * >>> put this stuff in by the RPC stub generator, since it
882          * >>> will be freed at the tail end of the server stub code.
883          */
884         dataBytes = sizeof(struct afs_CMStats);
885         dataBuffP = (afs_int32 *) afs_osi_Alloc(dataBytes);
886         osi_Assert(dataBuffP != NULL);
887         memcpy((char *)dataBuffP, (char *)&afs_cmstats, dataBytes);
888         a_dataP->AFSCB_CollData_len = dataBytes >> 2;
889         a_dataP->AFSCB_CollData_val = dataBuffP;
890         break;
891
892     case AFSCB_XSTATSCOLL_PERF_INFO:
893         /*
894          * Update and then pass back all the performance-related data.
895          * Note: the only performance fields that need to be computed
896          * at this time are the number of accesses for this collection
897          * and the current server record info.
898          *
899          * >>> We are forced to allocate a separate area in which to
900          * >>> put this stuff in by the RPC stub generator, since it
901          * >>> will be freed at the tail end of the server stub code.
902          */
903         afs_stats_cmperf.numPerfCalls++;
904         afs_CountServers();
905         dataBytes = sizeof(afs_stats_cmperf);
906         dataBuffP = (afs_int32 *) afs_osi_Alloc(dataBytes);
907         osi_Assert(dataBuffP != NULL);
908         memcpy((char *)dataBuffP, (char *)&afs_stats_cmperf, dataBytes);
909         a_dataP->AFSCB_CollData_len = dataBytes >> 2;
910         a_dataP->AFSCB_CollData_val = dataBuffP;
911         break;
912
913     case AFSCB_XSTATSCOLL_FULL_PERF_INFO:
914         /*
915          * Pass back the full range of performance and statistical
916          * data available.  We have to bring the normal performance
917          * data collection up to date, then copy that data into
918          * the full collection.
919          *
920          * >>> We are forced to allocate a separate area in which to
921          * >>> put this stuff in by the RPC stub generator, since it
922          * >>> will be freed at the tail end of the server stub code.
923          */
924         afs_stats_cmperf.numPerfCalls++;
925         afs_CountServers();
926         memcpy((char *)(&(afs_stats_cmfullperf.perf)),
927                (char *)(&afs_stats_cmperf), sizeof(struct afs_stats_CMPerf));
928         afs_stats_cmfullperf.numFullPerfCalls++;
929
930         dataBytes = sizeof(afs_stats_cmfullperf);
931         dataBuffP = (afs_int32 *) afs_osi_Alloc(dataBytes);
932         osi_Assert(dataBuffP != NULL);
933         memcpy((char *)dataBuffP, (char *)(&afs_stats_cmfullperf), dataBytes);
934         a_dataP->AFSCB_CollData_len = dataBytes >> 2;
935         a_dataP->AFSCB_CollData_val = dataBuffP;
936         break;
937
938     default:
939         /*
940          * Illegal collection number.
941          */
942         a_dataP->AFSCB_CollData_len = 0;
943         a_dataP->AFSCB_CollData_val = NULL;
944         code = 1;
945     }                           /*Switch on collection number */
946 #endif /* AFS_NOSTATS */
947
948     XSTATS_END_TIME;
949
950     RX_AFS_GUNLOCK();
951
952     return (code);
953
954 }                               /*SRXAFSCB_GetXStats */
955
956
957 /*------------------------------------------------------------------------
958  * EXPORTED afs_RXCallBackServer
959  *
960  * Description:
961  *      Body of the thread supporting callback services.
962  *
963  * Arguments:
964  *      None.
965  *
966  * Returns:
967  *      0 (always).
968  *
969  * Environment:
970  *      Nothing interesting.
971  *
972  * Side Effects:
973  *      As advertised.
974  *------------------------------------------------------------------------*/
975
976 int
977 afs_RXCallBackServer(void)
978 {
979     AFS_STATCNT(afs_RXCallBackServer);
980
981     while (1) {
982         if (afs_server)
983             break;
984         afs_osi_Sleep(&afs_server);
985     }
986
987     /*
988      * Donate this process to Rx.
989      */
990     rx_ServerProc(NULL);
991     return (0);
992
993 }                               /*afs_RXCallBackServer */
994
995
996 /*------------------------------------------------------------------------
997  * EXPORTED shutdown_CB
998  *
999  * Description:
1000  *      Zero out important Cache Manager data structures.
1001  *
1002  * Arguments:
1003  *      None.
1004  *
1005  * Returns:
1006  *      0 (always).
1007  *
1008  * Environment:
1009  *      Nothing interesting.
1010  *
1011  * Side Effects:
1012  *      As advertised.
1013  *------------------------------------------------------------------------*/
1014
1015 int
1016 shutdown_CB(void)
1017 {
1018     AFS_STATCNT(shutdown_CB);
1019
1020     if (afs_cold_shutdown) {
1021         afs_oddCBs = afs_evenCBs = afs_allCBs = afs_allZaps = afs_oddZaps =
1022             afs_evenZaps = afs_connectBacks = 0;
1023     }
1024
1025     return (0);
1026
1027 }                               /*shutdown_CB */
1028
1029 /*------------------------------------------------------------------------
1030  * EXPORTED SRXAFSCB_InitCallBackState2
1031  *
1032  * Description:
1033  *      This routine was used in the AFS 3.5 beta release, but not anymore.
1034  *      It has since been replaced by SRXAFSCB_InitCallBackState3.
1035  *
1036  * Arguments:
1037  *      a_call : Ptr to Rx call on which this request came in.
1038  *
1039  * Returns:
1040  *      RXGEN_OPCODE (always).
1041  *
1042  * Environment:
1043  *      Nothing interesting.
1044  *
1045  * Side Effects:
1046  *      None
1047  *------------------------------------------------------------------------*/
1048
1049 int
1050 SRXAFSCB_InitCallBackState2(struct rx_call *a_call,
1051                             struct interfaceAddr *addr)
1052 {
1053     return RXGEN_OPCODE;
1054 }
1055
1056 /*------------------------------------------------------------------------
1057  * EXPORTED SRXAFSCB_WhoAreYou
1058  *
1059  * Description:
1060  *      Routine called by the server-side callback RPC interface to
1061  *      obtain a unique identifier for the client. The server uses
1062  *      this identifier to figure out whether or not two RX connections
1063  *      are from the same client, and to find out which addresses go
1064  *      with which clients.
1065  *
1066  * Arguments:
1067  *      a_call : Ptr to Rx call on which this request came in.
1068  *      addr: Ptr to return the list of interfaces for this client.
1069  *
1070  * Returns:
1071  *      0 (Always)
1072  *
1073  * Environment:
1074  *      Nothing interesting.
1075  *
1076  * Side Effects:
1077  *      As advertised.
1078  *------------------------------------------------------------------------*/
1079
1080 int
1081 SRXAFSCB_WhoAreYou(struct rx_call *a_call, struct interfaceAddr *addr)
1082 {
1083     int i;
1084     int code = 0;
1085
1086     RX_AFS_GLOCK();
1087
1088     AFS_STATCNT(SRXAFSCB_WhoAreYou);
1089
1090     memset(addr, 0, sizeof(*addr));
1091
1092     ObtainReadLock(&afs_xinterface);
1093
1094     /* return all network interface addresses */
1095     addr->numberOfInterfaces = afs_cb_interface.numberOfInterfaces;
1096     addr->uuid = afs_cb_interface.uuid;
1097     for (i = 0; i < afs_cb_interface.numberOfInterfaces; i++) {
1098         addr->addr_in[i] = ntohl(afs_cb_interface.addr_in[i]);
1099         addr->subnetmask[i] = ntohl(afs_cb_interface.subnetmask[i]);
1100         addr->mtu[i] = ntohl(afs_cb_interface.mtu[i]);
1101     }
1102
1103     ReleaseReadLock(&afs_xinterface);
1104
1105     RX_AFS_GUNLOCK();
1106
1107     return code;
1108 }
1109
1110
1111 /*------------------------------------------------------------------------
1112  * EXPORTED SRXAFSCB_InitCallBackState3
1113  *
1114  * Description:
1115  *      Routine called by the server-side callback RPC interface to
1116  *      implement clearing all callbacks from this host.
1117  *
1118  * Arguments:
1119  *      a_call : Ptr to Rx call on which this request came in.
1120  *
1121  * Returns:
1122  *      0 (always).
1123  *
1124  * Environment:
1125  *      Nothing interesting.
1126  *
1127  * Side Effects:
1128  *      As advertised.
1129  *------------------------------------------------------------------------*/
1130
1131 int
1132 SRXAFSCB_InitCallBackState3(struct rx_call *a_call, afsUUID * a_uuid)
1133 {
1134     int code;
1135
1136     /*
1137      * TBD: Lookup the server by the UUID instead of its IP address.
1138      */
1139     code = SRXAFSCB_InitCallBackState(a_call);
1140
1141     return code;
1142 }
1143
1144
1145 /*------------------------------------------------------------------------
1146  * EXPORTED SRXAFSCB_ProbeUuid
1147  *
1148  * Description:
1149  *      Routine called by the server-side callback RPC interface to
1150  *      implement ``probing'' the Cache Manager, just making sure it's
1151  *      still there is still the same client it used to be.
1152  *
1153  * Arguments:
1154  *      a_call : Ptr to Rx call on which this request came in.
1155  *      a_uuid : Ptr to UUID that must match the client's UUID.
1156  *
1157  * Returns:
1158  *      0 if a_uuid matches the UUID for this client
1159  *      Non-zero otherwize
1160  *
1161  * Environment:
1162  *      Nothing interesting.
1163  *
1164  * Side Effects:
1165  *      As advertised.
1166  *------------------------------------------------------------------------*/
1167
1168 int
1169 SRXAFSCB_ProbeUuid(struct rx_call *a_call, afsUUID * a_uuid)
1170 {
1171     int code = 0;
1172     XSTATS_DECLS;
1173
1174     RX_AFS_GLOCK();
1175     AFS_STATCNT(SRXAFSCB_Probe);
1176
1177     XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_PROBE);
1178     if (!afs_uuid_equal(a_uuid, &afs_cb_interface.uuid))
1179         code = 1;               /* failure */
1180     XSTATS_END_TIME;
1181
1182     RX_AFS_GUNLOCK();
1183
1184     return code;
1185 }
1186
1187
1188 /*------------------------------------------------------------------------
1189  * EXPORTED SRXAFSCB_GetServerPrefs
1190  *
1191  * Description:
1192  *      Routine to list server preferences used by this client.
1193  *
1194  * Arguments:
1195  *      a_call  : Ptr to Rx call on which this request came in.
1196  *      a_index : Input server index
1197  *      a_srvr_addr  : Output server address in host byte order
1198  *                     (0xffffffff on last server)
1199  *      a_srvr_rank  : Output server rank
1200  *
1201  * Returns:
1202  *      0 on success
1203  *
1204  * Environment:
1205  *      Nothing interesting.
1206  *
1207  * Side Effects:
1208  *      As advertised.
1209  *------------------------------------------------------------------------*/
1210
1211 int
1212 SRXAFSCB_GetServerPrefs(struct rx_call *a_call, afs_int32 a_index,
1213                         afs_int32 * a_srvr_addr, afs_int32 * a_srvr_rank)
1214 {
1215     int i, j;
1216     struct srvAddr *sa;
1217
1218     RX_AFS_GLOCK();
1219     AFS_STATCNT(SRXAFSCB_GetServerPrefs);
1220
1221     ObtainReadLock(&afs_xserver);
1222
1223     /* Search the hash table for the server with this index */
1224     *a_srvr_addr = 0xffffffff;
1225     *a_srvr_rank = 0xffffffff;
1226     for (i = 0, j = 0; j < NSERVERS && i <= a_index; j++) {
1227         for (sa = afs_srvAddrs[j]; sa && i <= a_index; sa = sa->next_bkt, i++) {
1228             if (i == a_index) {
1229                 *a_srvr_addr = ntohl(sa->sa_ip);
1230                 *a_srvr_rank = sa->sa_iprank;
1231             }
1232         }
1233     }
1234
1235     ReleaseReadLock(&afs_xserver);
1236
1237     RX_AFS_GUNLOCK();
1238
1239     return 0;
1240 }
1241
1242
1243 /*------------------------------------------------------------------------
1244  * EXPORTED SRXAFSCB_GetCellServDB
1245  *
1246  * Description:
1247  *      Routine to list cells configured for this client
1248  *
1249  * Arguments:
1250  *      a_call  : Ptr to Rx call on which this request came in.
1251  *      a_index : Input cell index
1252  *      a_name  : Output cell name ("" on last cell)
1253  *      a_hosts : Output cell database servers in host byte order.
1254  *
1255  * Returns:
1256  *      0 on success
1257  *
1258  * Environment:
1259  *      Nothing interesting.
1260  *
1261  * Side Effects:
1262  *      As advertised.
1263  *------------------------------------------------------------------------*/
1264
1265 int
1266 SRXAFSCB_GetCellServDB(struct rx_call *a_call, afs_int32 a_index,
1267                        char **a_name, serverList * a_hosts)
1268 {
1269     afs_int32 i, j = 0;
1270     struct cell *tcell;
1271     char *t_name, *p_name = NULL;
1272
1273     RX_AFS_GLOCK();
1274     AFS_STATCNT(SRXAFSCB_GetCellServDB);
1275
1276     tcell = afs_GetCellByIndex(a_index, READ_LOCK);
1277
1278     if (!tcell) {
1279         i = 0;
1280         a_hosts->serverList_val = 0;
1281         a_hosts->serverList_len = 0;
1282     } else {
1283         p_name = tcell->cellName;
1284         for (j = 0; j < AFSMAXCELLHOSTS && tcell->cellHosts[j]; j++);
1285         i = strlen(p_name);
1286         a_hosts->serverList_val = afs_osi_Alloc(j * sizeof(afs_int32));
1287         osi_Assert(a_hosts->serverList_val != NULL);
1288         a_hosts->serverList_len = j;
1289         for (j = 0; j < AFSMAXCELLHOSTS && tcell->cellHosts[j]; j++)
1290             a_hosts->serverList_val[j] =
1291                 ntohl(tcell->cellHosts[j]->addr->sa_ip);
1292         afs_PutCell(tcell, READ_LOCK);
1293     }
1294
1295     t_name = afs_osi_Alloc(i + 1);
1296     if (t_name == NULL) {
1297         if (tcell != NULL)
1298             afs_osi_Free(a_hosts->serverList_val, (j * sizeof(afs_int32)));
1299         RX_AFS_GUNLOCK();
1300         return ENOMEM;
1301     }
1302
1303     t_name[i] = '\0';
1304     if (p_name)
1305         memcpy(t_name, p_name, i);
1306
1307     RX_AFS_GUNLOCK();
1308
1309     *a_name = t_name;
1310     return 0;
1311 }
1312
1313
1314 /*------------------------------------------------------------------------
1315  * EXPORTED SRXAFSCB_GetLocalCell
1316  *
1317  * Description:
1318  *      Routine to return name of client's local cell
1319  *
1320  * Arguments:
1321  *      a_call  : Ptr to Rx call on which this request came in.
1322  *      a_name  : Output cell name
1323  *
1324  * Returns:
1325  *      0 on success
1326  *
1327  * Environment:
1328  *      Nothing interesting.
1329  *
1330  * Side Effects:
1331  *      As advertised.
1332  *------------------------------------------------------------------------*/
1333
1334 int
1335 SRXAFSCB_GetLocalCell(struct rx_call *a_call, char **a_name)
1336 {
1337     int plen;
1338     struct cell *tcell;
1339     char *t_name, *p_name = NULL;
1340
1341     RX_AFS_GLOCK();
1342     AFS_STATCNT(SRXAFSCB_GetLocalCell);
1343
1344     /* Search the list for the primary cell. Cell number 1 is only
1345      * the primary cell is when no other cell is explicitly marked as
1346      * the primary cell.  */
1347     tcell = afs_GetPrimaryCell(READ_LOCK);
1348     if (tcell)
1349         p_name = tcell->cellName;
1350     if (p_name)
1351         plen = strlen(p_name);
1352     else
1353         plen = 0;
1354     t_name = afs_osi_Alloc(plen + 1);
1355     if (t_name == NULL) {
1356         if (tcell)
1357             afs_PutCell(tcell, READ_LOCK);
1358         RX_AFS_GUNLOCK();
1359         return ENOMEM;
1360     }
1361
1362     t_name[plen] = '\0';
1363     if (p_name)
1364         memcpy(t_name, p_name, plen);
1365
1366     RX_AFS_GUNLOCK();
1367
1368     *a_name = t_name;
1369     if (tcell)
1370         afs_PutCell(tcell, READ_LOCK);
1371     return 0;
1372 }
1373
1374
1375 /*
1376  * afs_MarshallCacheConfig - marshall client cache configuration
1377  *
1378  * PARAMETERS
1379  *
1380  * IN callerVersion - the rpc stat version of the caller.
1381  *
1382  * IN config - client cache configuration.
1383  *
1384  * OUT ptr - buffer where configuration is marshalled.
1385  *
1386  * RETURN CODES
1387  *
1388  * Returns void.
1389  */
1390 static void
1391 afs_MarshallCacheConfig(afs_uint32 callerVersion, cm_initparams_v1 * config,
1392                         afs_uint32 * ptr)
1393 {
1394     AFS_STATCNT(afs_MarshallCacheConfig);
1395     /*
1396      * We currently only support version 1.
1397      */
1398     *(ptr++) = config->nChunkFiles;
1399     *(ptr++) = config->nStatCaches;
1400     *(ptr++) = config->nDataCaches;
1401     *(ptr++) = config->nVolumeCaches;
1402     *(ptr++) = config->firstChunkSize;
1403     *(ptr++) = config->otherChunkSize;
1404     *(ptr++) = config->cacheSize;
1405     *(ptr++) = config->setTime;
1406     *(ptr++) = config->memCache;
1407 }
1408
1409
1410 /*------------------------------------------------------------------------
1411  * EXPORTED SRXAFSCB_GetCacheConfig
1412  *
1413  * Description:
1414  *      Routine to return parameters used to initialize client cache.
1415  *      Client may request any format version. Server may not return
1416  *      format version greater than version requested by client.
1417  *
1418  * Arguments:
1419  *      a_call:        Ptr to Rx call on which this request came in.
1420  *      callerVersion: Data format version desired by the client.
1421  *      serverVersion: Data format version of output data.
1422  *      configCount:   Number bytes allocated for output data.
1423  *      config:        Client cache configuration.
1424  *
1425  * Returns:
1426  *      0 on success
1427  *
1428  * Environment:
1429  *      Nothing interesting.
1430  *
1431  * Side Effects:
1432  *      As advertised.
1433  *------------------------------------------------------------------------*/
1434
1435 int
1436 SRXAFSCB_GetCacheConfig(struct rx_call *a_call, afs_uint32 callerVersion,
1437                         afs_uint32 * serverVersion, afs_uint32 * configCount,
1438                         cacheConfig * config)
1439 {
1440     afs_uint32 *t_config;
1441     size_t allocsize;
1442     cm_initparams_v1 cm_config;
1443
1444     RX_AFS_GLOCK();
1445     AFS_STATCNT(SRXAFSCB_GetCacheConfig);
1446
1447     /*
1448      * Currently only support version 1
1449      */
1450     allocsize = sizeof(cm_initparams_v1);
1451     t_config = afs_osi_Alloc(allocsize);
1452     if (t_config == NULL) {
1453         RX_AFS_GUNLOCK();
1454         return ENOMEM;
1455     }
1456
1457     cm_config.nChunkFiles = cm_initParams.cmi_nChunkFiles;
1458     cm_config.nStatCaches = cm_initParams.cmi_nStatCaches;
1459     cm_config.nDataCaches = cm_initParams.cmi_nDataCaches;
1460     cm_config.nVolumeCaches = cm_initParams.cmi_nVolumeCaches;
1461     cm_config.firstChunkSize = cm_initParams.cmi_firstChunkSize;
1462     cm_config.otherChunkSize = cm_initParams.cmi_otherChunkSize;
1463     cm_config.cacheSize = cm_initParams.cmi_cacheSize;
1464     cm_config.setTime = cm_initParams.cmi_setTime;
1465     cm_config.memCache = cm_initParams.cmi_memCache;
1466
1467     afs_MarshallCacheConfig(callerVersion, &cm_config, t_config);
1468
1469     *serverVersion = AFS_CLIENT_RETRIEVAL_FIRST_EDITION;
1470     *configCount = allocsize;
1471     config->cacheConfig_val = t_config;
1472     config->cacheConfig_len = allocsize / sizeof(afs_uint32);
1473
1474     RX_AFS_GUNLOCK();
1475
1476     return 0;
1477 }
1478
1479 /*------------------------------------------------------------------------
1480  * EXPORTED SRXAFSCB_FetchData
1481  *
1482  * Description:
1483  *      Routine to do third party move from a remioserver to the original
1484  *      issuer of an ArchiveData request. Presently supported only by the
1485  *      "fs" command, not by the AFS client.
1486  *
1487  * Arguments:
1488  *      rxcall:        Ptr to Rx call on which this request came in.
1489  *      Fid:           pointer to AFSFid structure.
1490  *      Fd:            File descriptor inside fs command.
1491  *      Position:      Offset in the file.
1492  *      Length:        Data length to transfer.
1493  *      TotalLength:   Pointer to total file length field
1494  *
1495  * Returns:
1496  *      0 on success
1497  *
1498  * Environment:
1499  *      Nothing interesting.
1500  *
1501  * Side Effects:
1502  *------------------------------------------------------------------------*/
1503 int
1504 SRXAFSCB_FetchData(struct rx_call *rxcall, struct AFSFid *Fid, afs_int32 Fd,
1505                    afs_int64 Position, afs_int64 Length,
1506                    afs_int64 * TotalLength)
1507 {
1508     return ENOSYS;
1509 }
1510
1511 /*------------------------------------------------------------------------
1512  * EXPORTED SRXAFSCB_StoreData
1513  *
1514  * Description:
1515  *      Routine to do third party move from a remioserver to the original
1516  *      issuer of a RetrieveData request. Presently supported only by the
1517  *      "fs" command, not by the AFS client.
1518  *
1519  * Arguments:
1520  *      rxcall:        Ptr to Rx call on which this request came in.
1521  *      Fid:           pointer to AFSFid structure.
1522  *      Fd:            File descriptor inside fs command.
1523  *      Position:      Offset in the file.
1524  *      Length:        Data length to transfer.
1525  *      TotalLength:   Pointer to total file length field
1526  *
1527  * Returns:
1528  *      0 on success
1529  *
1530  * Environment:
1531  *      Nothing interesting.
1532  *
1533  * Side Effects:
1534  *      As advertised.
1535  *------------------------------------------------------------------------*/
1536 int
1537 SRXAFSCB_StoreData(struct rx_call *rxcall, struct AFSFid *Fid, afs_int32 Fd,
1538                    afs_int64 Position, afs_int64 Length,
1539                    afs_int64 * TotalLength)
1540 {
1541     return ENOSYS;
1542 }
1543
1544 /*------------------------------------------------------------------------
1545  * EXPORTED SRXAFSCB_GetCellByNum
1546  *
1547  * Description:
1548  *      Routine to get information about a cell specified by its
1549  *      cell number (returned by GetCE/GetCE64).
1550  *
1551  * Arguments:
1552  *      a_call    : Ptr to Rx call on which this request came in.
1553  *      a_cellnum : Input cell number
1554  *      a_name    : Output cell name (one zero byte when no such cell).
1555  *      a_hosts   : Output cell database servers in host byte order.
1556  *
1557  * Returns:
1558  *      0 on success
1559  *
1560  * Environment:
1561  *      Nothing interesting.
1562  *
1563  * Side Effects:
1564  *      As advertised.
1565  *------------------------------------------------------------------------*/
1566
1567 int
1568 SRXAFSCB_GetCellByNum(struct rx_call *a_call, afs_int32 a_cellnum,
1569                       char **a_name, serverList * a_hosts)
1570 {
1571     afs_int32 i, sn;
1572     struct cell *tcell;
1573
1574     RX_AFS_GLOCK();
1575     AFS_STATCNT(SRXAFSCB_GetCellByNum);
1576
1577     a_hosts->serverList_val = 0;
1578     a_hosts->serverList_len = 0;
1579
1580     tcell = afs_GetCellStale(a_cellnum, READ_LOCK);
1581     if (!tcell) {
1582         *a_name = afs_strdup("");
1583         RX_AFS_GUNLOCK();
1584         return 0;
1585     }
1586
1587     ObtainReadLock(&tcell->lock);
1588     *a_name = afs_strdup(tcell->cellName);
1589
1590     for (sn = 0; sn < AFSMAXCELLHOSTS && tcell->cellHosts[sn]; sn++);
1591     a_hosts->serverList_len = sn;
1592     a_hosts->serverList_val = afs_osi_Alloc(sn * sizeof(afs_int32));
1593     osi_Assert(a_hosts->serverList_val != NULL);
1594
1595     for (i = 0; i < sn; i++)
1596         a_hosts->serverList_val[i] = ntohl(tcell->cellHosts[i]->addr->sa_ip);
1597     ReleaseReadLock(&tcell->lock);
1598     afs_PutCell(tcell, READ_LOCK);
1599
1600     RX_AFS_GUNLOCK();
1601     return 0;
1602 }
1603
1604 int
1605 SRXAFSCB_TellMeAboutYourself(struct rx_call *a_call,
1606                              struct interfaceAddr *addr,
1607                              Capabilities * capabilities)
1608 {
1609     int i;
1610     int code = 0;
1611     afs_uint32 *dataBuffP;
1612     afs_int32 dataBytes;
1613
1614     RX_AFS_GLOCK();
1615
1616     AFS_STATCNT(SRXAFSCB_WhoAreYou);
1617
1618     ObtainReadLock(&afs_xinterface);
1619
1620     /* return all network interface addresses */
1621     addr->numberOfInterfaces = afs_cb_interface.numberOfInterfaces;
1622     addr->uuid = afs_cb_interface.uuid;
1623     for (i = 0; i < afs_cb_interface.numberOfInterfaces; i++) {
1624         addr->addr_in[i] = ntohl(afs_cb_interface.addr_in[i]);
1625         addr->subnetmask[i] = ntohl(afs_cb_interface.subnetmask[i]);
1626         addr->mtu[i] = ntohl(afs_cb_interface.mtu[i]);
1627     }
1628
1629     ReleaseReadLock(&afs_xinterface);
1630
1631     RX_AFS_GUNLOCK();
1632
1633     dataBytes = 1 * sizeof(afs_uint32);
1634     dataBuffP = afs_osi_Alloc(dataBytes);
1635     osi_Assert(dataBuffP != NULL);
1636     dataBuffP[0] = CLIENT_CAPABILITY_ERRORTRANS;
1637     capabilities->Capabilities_len = dataBytes / sizeof(afs_uint32);
1638     capabilities->Capabilities_val = dataBuffP;
1639
1640     return code;
1641 }
1642
1643
1644 #if 0 && defined(AFS_LINUX24_ENV)
1645 extern struct vcache *afs_globalVp;
1646
1647 int recurse_dcache_parent(parent, a_index, addr, inode, flags, time, fileName)
1648      struct dentry * parent;
1649     afs_int32 a_index;
1650     afs_int32 *addr;
1651     afs_int32 *inode;
1652     afs_int32 *flags;
1653     afs_int32 *time;
1654     char ** fileName;
1655 {
1656         struct dentry *this_parent = parent;
1657         struct list_head *next;
1658         int found = 0;
1659         struct dentry *dentry;
1660
1661 repeat:
1662         next = this_parent->d_subdirs.next;
1663 resume:
1664         while (next != &this_parent->d_subdirs) {
1665                 struct list_head *tmp = next;
1666                 dentry = list_entry(tmp, struct dentry, d_child);
1667                 if (a_index == 0)
1668                   goto searchdone3;
1669                 a_index--;
1670                 next = tmp->next;
1671                 /*
1672                  * Descend a level if the d_subdirs list is non-empty.
1673                  */
1674                 if (!list_empty(&dentry->d_subdirs)) {
1675                         this_parent = dentry;
1676                         goto repeat;
1677                 }
1678         }
1679         /*
1680          * All done at this level ... ascend and resume the search.
1681          */
1682         if (this_parent != parent) {
1683                 next = this_parent->d_child.next;
1684                 this_parent = this_parent->d_parent;
1685                 goto resume;
1686         }
1687         goto ret;
1688
1689  searchdone3:
1690     if (d_unhashed(dentry))
1691       *flags = 1;
1692     else
1693       *flags = 0;
1694
1695     *fileName = afs_strdup(dentry->d_name.name?dentry->d_name.name:"");
1696     *inode = ITOAFS(dentry->d_inode);
1697     *addr = atomic_read(&(dentry)->d_count);
1698     *time = dentry->d_time;
1699
1700     return 0;
1701  ret:
1702     return 1;
1703 }
1704 #endif
1705
1706 int
1707 SRXAFSCB_GetDE(struct rx_call *a_call, afs_int32 a_index, afs_int32 *addr,
1708                afs_int32 *inode, afs_int32 *flags, afs_int32 *time,
1709                char ** fileName)
1710 { /*SRXAFSCB_GetDE*/
1711     int code = 0;                               /*Return code*/
1712 #if 0 && defined(AFS_LINUX24_ENV)
1713     int i;                      /*Loop variable*/
1714     struct vcache *tvc = afs_globalVp;
1715     struct dentry *dentry;
1716     struct list_head *cur, *head = &(AFSTOI(tvc))->i_dentry;
1717
1718 #ifdef RX_ENABLE_LOCKS
1719     AFS_GLOCK();
1720 #endif /* RX_ENABLE_LOCKS */
1721
1722 #if defined(AFS_LINUX24_ENV)
1723     spin_lock(&dcache_lock);
1724 #endif
1725
1726     cur = head;
1727     while ((cur = cur->next) != head) {
1728       dentry = list_entry(cur, struct dentry, d_alias);
1729
1730       dget_locked(dentry);
1731
1732 #if defined(AFS_LINUX24_ENV)
1733       spin_unlock(&dcache_lock);
1734 #endif
1735       if (a_index == 0)
1736         goto searchdone2;
1737       a_index--;
1738
1739       if (recurse_dcache_parent(dentry, a_index, addr, inode, flags, time, fileName) == 0) {
1740         dput(dentry);
1741         code = 0;
1742         goto fcnDone;
1743       }
1744       dput(dentry);
1745     }
1746  searchdone2:
1747     if (cur == head) {
1748         /*Past EOF*/
1749         code = 1;
1750         *fileName = afs_strdup("");
1751         goto fcnDone;
1752     }
1753
1754     if (d_unhashed(dentry))
1755       *flags = 1;
1756     else
1757       *flags = 0;
1758
1759     *fileName = afs_strdup(dentry->d_name.name?dentry->d_name.name:"");
1760     *inode = ITOAFS(dentry->d_inode);
1761     *addr = atomic_read(&(dentry)->d_count);
1762     *time = dentry->d_time;
1763
1764     dput(dentry);
1765     code = 0;
1766
1767 fcnDone:
1768
1769 #ifdef RX_ENABLE_LOCKS
1770     AFS_GUNLOCK();
1771 #endif /* RX_ENABLE_LOCKS */
1772 #endif
1773     return(code);
1774
1775 } /*SRXAFSCB_GetDE*/