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