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