2 * Copyright 2000, International Business Machines Corporation and others.
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
12 * Exported routines (and their private support) to implement
13 * the callback RPC interface.
16 #include <afsconfig.h>
17 #include "afs/param.h"
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"
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;
34 * Some debugging aids.
36 static struct ltable {
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},
57 "afs_xosi", (char *)&afs_xosi},
60 "afs_xsrvAddr", (char *)&afs_xsrvAddr},
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},
69 unsigned long lastCallBack_vnode;
70 unsigned int lastCallBack_dv;
71 osi_timeval_t lastCallBack_time;
73 /* these are for storing alternate interface addresses */
74 struct interfaceAddr afs_cb_interface;
76 /*------------------------------------------------------------------------
77 * EXPORTED SRXAFSCB_GetCE
80 * Routine called by the server-side callback RPC interface to
81 * implement pulling out the contents of the i'th cache entry.
84 * a_call : Ptr to Rx call on which this request came in.
85 * a_index : Index of desired cache entry.
86 * a_result : Ptr to a buffer for the given cache entry.
89 * 0 if everything went fine,
90 * 1 if we were given a bad index.
93 * Nothing interesting.
97 *------------------------------------------------------------------------*/
100 SRXAFSCB_GetCE(struct rx_call *a_call, afs_int32 a_index,
101 struct AFSDBCacheEntry *a_result)
104 int i; /*Loop variable */
105 struct vcache *tvc; /*Ptr to current cache entry */
106 int code; /*Return code */
111 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_GETCE);
113 AFS_STATCNT(SRXAFSCB_GetCE);
114 for (i = 0; i < VCSIZE; i++) {
115 for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
119 } /*Zip through current hash chain */
120 } /*Zip through hash chains */
130 * Copy out the located entry.
132 a_result->addr = afs_data_pointer_to_int32(tvc);
133 a_result->cell = tvc->f.fid.Cell;
134 a_result->netFid.Volume = tvc->f.fid.Fid.Volume;
135 a_result->netFid.Vnode = tvc->f.fid.Fid.Vnode;
136 a_result->netFid.Unique = tvc->f.fid.Fid.Unique;
137 a_result->lock.waitStates = tvc->lock.wait_states;
138 a_result->lock.exclLocked = tvc->lock.excl_locked;
139 a_result->lock.readersReading = tvc->lock.readers_reading;
140 a_result->lock.numWaiting = tvc->lock.num_waiting;
141 #if defined(INSTRUMENT_LOCKS)
142 a_result->lock.pid_last_reader = MyPidxx2Pid(tvc->lock.pid_last_reader);
143 a_result->lock.pid_writer = MyPidxx2Pid(tvc->lock.pid_writer);
144 a_result->lock.src_indicator = tvc->lock.src_indicator;
146 /* On osf20 , the vcache does not maintain these three fields */
147 a_result->lock.pid_last_reader = 0;
148 a_result->lock.pid_writer = 0;
149 a_result->lock.src_indicator = 0;
150 #endif /* INSTRUMENT_LOCKS */
151 #ifdef AFS_64BIT_CLIENT
152 a_result->Length = (afs_int32) tvc->f.m.Length & 0xffffffff;
153 #else /* AFS_64BIT_CLIENT */
154 a_result->Length = tvc->f.m.Length;
155 #endif /* AFS_64BIT_CLIENT */
156 a_result->DataVersion = hgetlo(tvc->f.m.DataVersion);
157 a_result->callback = afs_data_pointer_to_int32(tvc->callback); /* XXXX Now a pointer; change it XXXX */
158 a_result->cbExpires = tvc->cbExpires;
159 if (tvc->f.states & CVInit) {
160 a_result->refCount = 1;
162 #ifdef AFS_DARWIN80_ENV
163 a_result->refCount = vnode_isinuse(AFSTOV(tvc),0)?1:0; /* XXX fix */
165 a_result->refCount = VREFCOUNT(tvc);
168 a_result->opens = tvc->opens;
169 a_result->writers = tvc->execsOrWriters;
170 a_result->mvstat = tvc->mvstat;
171 a_result->states = tvc->f.states;
175 * Return our results.
184 } /*SRXAFSCB_GetCE */
187 SRXAFSCB_GetCE64(struct rx_call *a_call, afs_int32 a_index,
188 struct AFSDBCacheEntry64 *a_result)
190 int i; /*Loop variable */
191 struct vcache *tvc; /*Ptr to current cache entry */
192 int code; /*Return code */
197 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_GETCE);
199 AFS_STATCNT(SRXAFSCB_GetCE64);
200 for (i = 0; i < VCSIZE; i++) {
201 for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
205 } /*Zip through current hash chain */
206 } /*Zip through hash chains */
216 * Copy out the located entry.
218 a_result->addr = afs_data_pointer_to_int32(tvc);
219 a_result->cell = tvc->f.fid.Cell;
220 a_result->netFid.Volume = tvc->f.fid.Fid.Volume;
221 a_result->netFid.Vnode = tvc->f.fid.Fid.Vnode;
222 a_result->netFid.Unique = tvc->f.fid.Fid.Unique;
223 a_result->lock.waitStates = tvc->lock.wait_states;
224 a_result->lock.exclLocked = tvc->lock.excl_locked;
225 a_result->lock.readersReading = tvc->lock.readers_reading;
226 a_result->lock.numWaiting = tvc->lock.num_waiting;
227 #if defined(INSTRUMENT_LOCKS)
228 a_result->lock.pid_last_reader = MyPidxx2Pid(tvc->lock.pid_last_reader);
229 a_result->lock.pid_writer = MyPidxx2Pid(tvc->lock.pid_writer);
230 a_result->lock.src_indicator = tvc->lock.src_indicator;
232 /* On osf20 , the vcache does not maintain these three fields */
233 a_result->lock.pid_last_reader = 0;
234 a_result->lock.pid_writer = 0;
235 a_result->lock.src_indicator = 0;
236 #endif /* INSTRUMENT_LOCKS */
237 a_result->Length = tvc->f.m.Length;
238 a_result->DataVersion = hgetlo(tvc->f.m.DataVersion);
239 a_result->callback = afs_data_pointer_to_int32(tvc->callback); /* XXXX Now a pointer; change it XXXX */
240 a_result->cbExpires = tvc->cbExpires;
241 if (tvc->f.states & CVInit) {
242 a_result->refCount = 1;
244 #ifdef AFS_DARWIN80_ENV
245 a_result->refCount = vnode_isinuse(AFSTOV(tvc),0)?1:0; /* XXX fix */
247 a_result->refCount = VREFCOUNT(tvc);
250 a_result->opens = tvc->opens;
251 a_result->writers = tvc->execsOrWriters;
252 a_result->mvstat = tvc->mvstat;
253 a_result->states = tvc->f.states;
257 * Return our results.
266 } /*SRXAFSCB_GetCE64 */
269 /*------------------------------------------------------------------------
270 * EXPORTED SRXAFSCB_GetLock
273 * Routine called by the server-side callback RPC interface to
274 * implement pulling out the contents of a lock in the lock
278 * a_call : Ptr to Rx call on which this request came in.
279 * a_index : Index of desired lock.
280 * a_result : Ptr to a buffer for the given lock.
283 * 0 if everything went fine,
284 * 1 if we were given a bad index.
287 * Nothing interesting.
291 *------------------------------------------------------------------------*/
294 SRXAFSCB_GetLock(struct rx_call *a_call, afs_int32 a_index,
295 struct AFSDBLock *a_result)
297 struct ltable *tl; /*Ptr to lock table entry */
298 int nentries; /*Num entries in table */
299 int code; /*Return code */
304 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_GETLOCK);
306 AFS_STATCNT(SRXAFSCB_GetLock);
307 nentries = sizeof(ltable) / sizeof(struct ltable);
308 if (a_index < 0 || a_index >= nentries+afs_cellindex) {
313 } else if (a_index >= nentries) {
314 struct cell *tc = afs_GetCellByIndex(a_index-nentries, 0);
315 strcpy(a_result->name, tc->cellName);
316 a_result->lock.waitStates =
317 ((struct afs_lock *)&(tc->lock))->wait_states;
318 a_result->lock.exclLocked =
319 ((struct afs_lock *)&(tc->lock))->excl_locked;
320 a_result->lock.readersReading =
321 ((struct afs_lock *)&(tc->lock))->readers_reading;
322 a_result->lock.numWaiting =
323 ((struct afs_lock *)&(tc->lock))->num_waiting;
324 #ifdef INSTRUMENT_LOCKS
325 a_result->lock.pid_last_reader =
326 MyPidxx2Pid(((struct afs_lock *)&(tc->lock))->pid_last_reader);
327 a_result->lock.pid_writer =
328 MyPidxx2Pid(((struct afs_lock *)&(tc->lock))->pid_writer);
329 a_result->lock.src_indicator =
330 ((struct afs_lock *)&(tc->lock))->src_indicator;
332 a_result->lock.pid_last_reader = 0;
333 a_result->lock.pid_writer = 0;
334 a_result->lock.src_indicator = 0;
339 * Found it - copy out its contents.
341 tl = <able[a_index];
342 strcpy(a_result->name, tl->name);
343 a_result->lock.waitStates =
344 ((struct afs_lock *)(tl->addr))->wait_states;
345 a_result->lock.exclLocked =
346 ((struct afs_lock *)(tl->addr))->excl_locked;
347 a_result->lock.readersReading =
348 ((struct afs_lock *)(tl->addr))->readers_reading;
349 a_result->lock.numWaiting =
350 ((struct afs_lock *)(tl->addr))->num_waiting;
351 #ifdef INSTRUMENT_LOCKS
352 a_result->lock.pid_last_reader =
353 MyPidxx2Pid(((struct afs_lock *)(tl->addr))->pid_last_reader);
354 a_result->lock.pid_writer =
355 MyPidxx2Pid(((struct afs_lock *)(tl->addr))->pid_writer);
356 a_result->lock.src_indicator =
357 ((struct afs_lock *)(tl->addr))->src_indicator;
359 a_result->lock.pid_last_reader = 0;
360 a_result->lock.pid_writer = 0;
361 a_result->lock.src_indicator = 0;
372 } /*SRXAFSCB_GetLock */
375 /*------------------------------------------------------------------------
376 * static ClearCallBack
379 * Clear out callback information for the specified file, or
380 * even a whole volume. Used to worry about callback was from
381 * within the particular cell or not. Now we don't bother with
382 * that anymore; it's not worth the time.
385 * a_conn : Ptr to Rx connection involved.
386 * a_fid : Ptr to AFS fid being cleared.
392 * Nothing interesting.
397 Appears to need to be called with GLOCK held, as the icl_Event4 stuff asserts otherwise
399 *------------------------------------------------------------------------*/
402 ClearCallBack(struct rx_connection *a_conn,
403 struct AFSFid *a_fid)
407 struct VenusFid localFid;
409 #ifdef AFS_DARWIN80_ENV
413 AFS_STATCNT(ClearCallBack);
418 * XXXX Don't hold any server locks here because of callback protocol XXX
421 localFid.Fid.Volume = a_fid->Volume;
422 localFid.Fid.Vnode = a_fid->Vnode;
423 localFid.Fid.Unique = a_fid->Unique;
426 * Volume ID of zero means don't do anything.
428 if (a_fid->Volume != 0) {
429 if (a_fid->Vnode == 0) {
430 struct afs_q *tq, *uq;
432 * Clear callback for the whole volume. Zip through the
433 * hash chain, nullifying entries whose volume ID matches.
436 ObtainReadLock(&afs_xvcache);
437 i = VCHashV(&localFid);
438 for (tq = afs_vhashTV[i].prev; tq != &afs_vhashTV[i]; tq = uq) {
441 if (tvc->f.fid.Fid.Volume == a_fid->Volume) {
442 tvc->callback = NULL;
444 localFid.Cell = tvc->f.fid.Cell;
445 tvc->dchint = NULL; /* invalidate hints */
446 if (tvc->f.states & CVInit) {
447 ReleaseReadLock(&afs_xvcache);
448 afs_osi_Sleep(&tvc->f.states);
451 #if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_HPUX_ENV) || defined(AFS_LINUX20_ENV)
454 #ifdef AFS_DARWIN80_ENV
455 if (tvc->f.states & CDeadVnode) {
456 ReleaseReadLock(&afs_xvcache);
457 afs_osi_Sleep(&tvc->f.states);
473 ReleaseReadLock(&afs_xvcache);
474 ObtainWriteLock(&afs_xcbhash, 449);
475 afs_DequeueCallback(tvc);
476 tvc->f.states &= ~(CStatd | CUnique | CBulkFetching);
478 if (tvc->f.fid.Fid.Vnode & 1)
482 ReleaseWriteLock(&afs_xcbhash);
483 if ((tvc->f.fid.Fid.Vnode & 1 || (vType(tvc) == VDIR)))
484 osi_dnlc_purgedp(tvc);
485 afs_Trace3(afs_iclSetp, CM_TRACE_CALLBACK,
486 ICL_TYPE_POINTER, tvc, ICL_TYPE_INT32,
487 tvc->f.states, ICL_TYPE_INT32,
489 #ifdef AFS_DARWIN80_ENV
490 vnode_put(AFSTOV(tvc));
492 ObtainReadLock(&afs_xvcache);
495 } else if ((tvc->f.states & CMValid)
496 && (tvc->mvid->Fid.Volume == a_fid->Volume)) {
497 tvc->f.states &= ~CMValid;
499 localFid.Cell = tvc->mvid->Cell;
502 ReleaseReadLock(&afs_xvcache);
505 * XXXX Don't hold any locks here XXXX
507 tv = afs_FindVolume(&localFid, 0);
509 afs_ResetVolumeInfo(tv);
510 afs_PutVolume(tv, 0);
511 /* invalidate mtpoint? */
513 } /*Clear callbacks for whole volume */
516 * Clear callbacks just for the one file.
520 if (a_fid->Vnode & 1)
521 afs_oddCBs++; /*Could do this on volume basis, too */
523 afs_evenCBs++; /*A particular fid was specified */
525 ObtainReadLock(&afs_xvcache);
526 i = VCHash(&localFid);
527 for (tvc = afs_vhashT[i]; tvc; tvc = uvc) {
529 if (tvc->f.fid.Fid.Vnode == a_fid->Vnode
530 && tvc->f.fid.Fid.Volume == a_fid->Volume
531 && tvc->f.fid.Fid.Unique == a_fid->Unique) {
532 tvc->callback = NULL;
533 tvc->dchint = NULL; /* invalidate hints */
534 if (tvc->f.states & CVInit) {
535 ReleaseReadLock(&afs_xvcache);
536 afs_osi_Sleep(&tvc->f.states);
539 #if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_HPUX_ENV) || defined(AFS_LINUX20_ENV)
542 #ifdef AFS_DARWIN80_ENV
543 if (tvc->f.states & CDeadVnode) {
544 ReleaseReadLock(&afs_xvcache);
545 afs_osi_Sleep(&tvc->f.states);
561 ReleaseReadLock(&afs_xvcache);
562 ObtainWriteLock(&afs_xcbhash, 450);
563 afs_DequeueCallback(tvc);
564 tvc->f.states &= ~(CStatd | CUnique | CBulkFetching);
565 ReleaseWriteLock(&afs_xcbhash);
566 if ((tvc->f.fid.Fid.Vnode & 1 || (vType(tvc) == VDIR)))
567 osi_dnlc_purgedp(tvc);
568 afs_Trace3(afs_iclSetp, CM_TRACE_CALLBACK,
569 ICL_TYPE_POINTER, tvc, ICL_TYPE_INT32,
570 tvc->f.states, ICL_TYPE_LONG, 0);
572 lastCallBack_vnode = afid->Vnode;
573 lastCallBack_dv = tvc->mstat.DataVersion.low;
574 osi_GetuTime(&lastCallBack_time);
576 #ifdef AFS_DARWIN80_ENV
577 vnode_put(AFSTOV(tvc));
579 ObtainReadLock(&afs_xvcache);
583 } /*Walk through hash table */
584 ReleaseReadLock(&afs_xvcache);
585 } /*Clear callbacks for one file */
588 /*Fid has non-zero volume ID */
590 * Always return a predictable value.
597 /*------------------------------------------------------------------------
598 * EXPORTED SRXAFSCB_CallBack
601 * Routine called by the server-side callback RPC interface to
602 * implement passing in callback information.
606 * a_call : Ptr to Rx call on which this request came in.
607 * a_fids : Ptr to array of fids involved.
608 * a_callbacks : Ptr to matching callback info for the fids.
614 * Nothing interesting.
618 *------------------------------------------------------------------------*/
621 SRXAFSCB_CallBack(struct rx_call *a_call, struct AFSCBFids *a_fids,
622 struct AFSCBs *a_callbacks)
624 int i; /*Loop variable */
625 struct AFSFid *tfid; /*Ptr to current fid */
626 struct rx_connection *tconn; /*Call's connection */
632 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_CALLBACK);
634 AFS_STATCNT(SRXAFSCB_CallBack);
635 if (!(tconn = rx_ConnectionOf(a_call)))
637 tfid = (struct AFSFid *)a_fids->AFSCBFids_val;
640 * For now, we ignore callbacks, since the File Server only *breaks*
641 * callbacks at present.
643 for (i = 0; i < a_fids->AFSCBFids_len; i++)
644 ClearCallBack(tconn, &tfid[i]);
652 } /*SRXAFSCB_CallBack */
655 /*------------------------------------------------------------------------
656 * EXPORTED SRXAFSCB_Probe
659 * Routine called by the server-side callback RPC interface to
660 * implement ``probing'' the Cache Manager, just making sure it's
664 * a_call : Ptr to Rx call on which this request came in.
670 * Nothing interesting.
674 *------------------------------------------------------------------------*/
677 SRXAFSCB_Probe(struct rx_call *a_call)
683 AFS_STATCNT(SRXAFSCB_Probe);
685 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_PROBE);
692 } /*SRXAFSCB_Probe */
695 /*------------------------------------------------------------------------
696 * EXPORTED SRXAFSCB_InitCallBackState
699 * Routine called by the server-side callback RPC interface to
700 * implement clearing all callbacks from this host.
703 * a_call : Ptr to Rx call on which this request came in.
709 * Nothing interesting.
713 *------------------------------------------------------------------------*/
716 SRXAFSCB_InitCallBackState(struct rx_call *a_call)
720 struct rx_connection *tconn;
721 struct rx_peer *peer;
728 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_INITCALLBACKSTATE);
729 AFS_STATCNT(SRXAFSCB_InitCallBackState);
732 * Find the address of the host making this call
734 if ((tconn = rx_ConnectionOf(a_call)) && (peer = rx_PeerOf(tconn))) {
737 afs_oddCBs++; /*Including any missed via create race */
738 afs_evenCBs++; /*Including any missed via create race */
740 ts = afs_FindServer(rx_HostOf(peer), rx_PortOf(peer), (afsUUID *) 0,
743 for (i = 0; i < VCSIZE; i++)
744 for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
745 if (tvc->callback == ts) {
746 ObtainWriteLock(&afs_xcbhash, 451);
747 afs_DequeueCallback(tvc);
748 tvc->callback = NULL;
749 tvc->f.states &= ~(CStatd | CUnique | CBulkFetching);
750 ReleaseWriteLock(&afs_xcbhash);
754 /* capabilities need be requested again */
755 ts->flags &= ~SCAPS_KNOWN;
760 /* find any volumes residing on this server and flush their state */
765 for (i = 0; i < NVOLS; i++)
766 for (tv = afs_volumes[i]; tv; tv = tv->next) {
767 for (j = 0; j < AFS_MAXHOSTS; j++)
768 if (tv->serverHost[j] == ts)
769 afs_ResetVolumeInfo(tv);
772 osi_dnlc_purge(); /* may be a little bit extreme */
781 } /*SRXAFSCB_InitCallBackState */
784 /*------------------------------------------------------------------------
785 * EXPORTED SRXAFSCB_XStatsVersion
788 * Routine called by the server-side callback RPC interface to
789 * implement pulling out the xstat version number for the Cache
793 * a_versionP : Ptr to the version number variable to set.
799 * Nothing interesting.
803 *------------------------------------------------------------------------*/
806 SRXAFSCB_XStatsVersion(struct rx_call *a_call, afs_int32 * a_versionP)
813 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_XSTATSVERSION);
815 *a_versionP = AFSCB_XSTAT_VERSION;
822 } /*SRXAFSCB_XStatsVersion */
825 /*------------------------------------------------------------------------
826 * EXPORTED SRXAFSCB_GetXStats
829 * Routine called by the server-side callback RPC interface to
830 * implement getting the given data collection from the extended
831 * Cache Manager statistics.
834 * a_call : Ptr to Rx call on which this request came in.
835 * a_clientVersionNum : Client version number.
836 * a_opCode : Desired operation.
837 * a_serverVersionNumP : Ptr to version number to set.
838 * a_timeP : Ptr to time value (seconds) to set.
839 * a_dataArray : Ptr to variable array structure to return
846 * Nothing interesting.
850 *------------------------------------------------------------------------*/
853 SRXAFSCB_GetXStats(struct rx_call *a_call, afs_int32 a_clientVersionNum,
854 afs_int32 a_collectionNumber, afs_int32 * a_srvVersionNumP,
855 afs_int32 * a_timeP, AFSCB_CollData * a_dataP)
857 int code; /*Return value */
858 afs_int32 *dataBuffP; /*Ptr to data to be returned */
859 afs_int32 dataBytes; /*Bytes in data buffer */
864 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_GETXSTATS);
867 * Record the time of day and the server version number.
869 *a_srvVersionNumP = AFSCB_XSTAT_VERSION;
870 *a_timeP = osi_Time();
873 * Stuff the appropriate data in there (assume victory)
879 * We're not keeping stats, so just return successfully with
882 a_dataP->AFSCB_CollData_len = 0;
883 a_dataP->AFSCB_CollData_val = NULL;
885 switch (a_collectionNumber) {
886 case AFSCB_XSTATSCOLL_CALL_INFO:
888 * Pass back all the call-count-related data.
890 * >>> We are forced to allocate a separate area in which to
891 * >>> put this stuff in by the RPC stub generator, since it
892 * >>> will be freed at the tail end of the server stub code.
894 dataBytes = sizeof(struct afs_CMStats);
895 dataBuffP = (afs_int32 *) afs_osi_Alloc(dataBytes);
896 osi_Assert(dataBuffP != NULL);
897 memcpy((char *)dataBuffP, (char *)&afs_cmstats, dataBytes);
898 a_dataP->AFSCB_CollData_len = dataBytes >> 2;
899 a_dataP->AFSCB_CollData_val = dataBuffP;
902 case AFSCB_XSTATSCOLL_PERF_INFO:
904 * Update and then pass back all the performance-related data.
905 * Note: the only performance fields that need to be computed
906 * at this time are the number of accesses for this collection
907 * and the current server record info.
909 * >>> We are forced to allocate a separate area in which to
910 * >>> put this stuff in by the RPC stub generator, since it
911 * >>> will be freed at the tail end of the server stub code.
913 afs_stats_cmperf.numPerfCalls++;
915 dataBytes = sizeof(afs_stats_cmperf);
916 dataBuffP = (afs_int32 *) afs_osi_Alloc(dataBytes);
917 osi_Assert(dataBuffP != NULL);
918 memcpy((char *)dataBuffP, (char *)&afs_stats_cmperf, dataBytes);
919 a_dataP->AFSCB_CollData_len = dataBytes >> 2;
920 a_dataP->AFSCB_CollData_val = dataBuffP;
923 case AFSCB_XSTATSCOLL_FULL_PERF_INFO:
925 * Pass back the full range of performance and statistical
926 * data available. We have to bring the normal performance
927 * data collection up to date, then copy that data into
928 * the full collection.
930 * >>> We are forced to allocate a separate area in which to
931 * >>> put this stuff in by the RPC stub generator, since it
932 * >>> will be freed at the tail end of the server stub code.
934 afs_stats_cmperf.numPerfCalls++;
936 memcpy((char *)(&(afs_stats_cmfullperf.perf)),
937 (char *)(&afs_stats_cmperf), sizeof(struct afs_stats_CMPerf));
938 afs_stats_cmfullperf.numFullPerfCalls++;
940 dataBytes = sizeof(afs_stats_cmfullperf);
941 dataBuffP = (afs_int32 *) afs_osi_Alloc(dataBytes);
942 osi_Assert(dataBuffP != NULL);
943 memcpy((char *)dataBuffP, (char *)(&afs_stats_cmfullperf), dataBytes);
944 a_dataP->AFSCB_CollData_len = dataBytes >> 2;
945 a_dataP->AFSCB_CollData_val = dataBuffP;
950 * Illegal collection number.
952 a_dataP->AFSCB_CollData_len = 0;
953 a_dataP->AFSCB_CollData_val = NULL;
955 } /*Switch on collection number */
956 #endif /* AFS_NOSTATS */
964 } /*SRXAFSCB_GetXStats */
967 /*------------------------------------------------------------------------
968 * EXPORTED afs_RXCallBackServer
971 * Body of the thread supporting callback services.
980 * Nothing interesting.
984 *------------------------------------------------------------------------*/
987 afs_RXCallBackServer(void)
989 AFS_STATCNT(afs_RXCallBackServer);
994 afs_osi_Sleep(&afs_server);
998 * Donate this process to Rx.
1000 rx_ServerProc(NULL);
1003 } /*afs_RXCallBackServer */
1006 /*------------------------------------------------------------------------
1007 * EXPORTED shutdown_CB
1010 * Zero out important Cache Manager data structures.
1019 * Nothing interesting.
1023 *------------------------------------------------------------------------*/
1028 AFS_STATCNT(shutdown_CB);
1030 if (afs_cold_shutdown) {
1031 afs_oddCBs = afs_evenCBs = afs_allCBs = afs_allZaps = afs_oddZaps =
1032 afs_evenZaps = afs_connectBacks = 0;
1039 /*------------------------------------------------------------------------
1040 * EXPORTED SRXAFSCB_InitCallBackState2
1043 * This routine was used in the AFS 3.5 beta release, but not anymore.
1044 * It has since been replaced by SRXAFSCB_InitCallBackState3.
1047 * a_call : Ptr to Rx call on which this request came in.
1050 * RXGEN_OPCODE (always).
1053 * Nothing interesting.
1057 *------------------------------------------------------------------------*/
1060 SRXAFSCB_InitCallBackState2(struct rx_call *a_call,
1061 struct interfaceAddr *addr)
1063 return RXGEN_OPCODE;
1066 /*------------------------------------------------------------------------
1067 * EXPORTED SRXAFSCB_WhoAreYou
1070 * Routine called by the server-side callback RPC interface to
1071 * obtain a unique identifier for the client. The server uses
1072 * this identifier to figure out whether or not two RX connections
1073 * are from the same client, and to find out which addresses go
1074 * with which clients.
1077 * a_call : Ptr to Rx call on which this request came in.
1078 * addr: Ptr to return the list of interfaces for this client.
1084 * Nothing interesting.
1088 *------------------------------------------------------------------------*/
1091 SRXAFSCB_WhoAreYou(struct rx_call *a_call, struct interfaceAddr *addr)
1098 AFS_STATCNT(SRXAFSCB_WhoAreYou);
1100 memset(addr, 0, sizeof(*addr));
1102 ObtainReadLock(&afs_xinterface);
1104 /* return all network interface addresses */
1105 addr->numberOfInterfaces = afs_cb_interface.numberOfInterfaces;
1106 addr->uuid = afs_cb_interface.uuid;
1107 for (i = 0; i < afs_cb_interface.numberOfInterfaces; i++) {
1108 addr->addr_in[i] = ntohl(afs_cb_interface.addr_in[i]);
1109 addr->subnetmask[i] = ntohl(afs_cb_interface.subnetmask[i]);
1110 addr->mtu[i] = ntohl(afs_cb_interface.mtu[i]);
1113 ReleaseReadLock(&afs_xinterface);
1121 /*------------------------------------------------------------------------
1122 * EXPORTED SRXAFSCB_InitCallBackState3
1125 * Routine called by the server-side callback RPC interface to
1126 * implement clearing all callbacks from this host.
1129 * a_call : Ptr to Rx call on which this request came in.
1135 * Nothing interesting.
1139 *------------------------------------------------------------------------*/
1142 SRXAFSCB_InitCallBackState3(struct rx_call *a_call, afsUUID * a_uuid)
1147 * TBD: Lookup the server by the UUID instead of its IP address.
1149 code = SRXAFSCB_InitCallBackState(a_call);
1155 /*------------------------------------------------------------------------
1156 * EXPORTED SRXAFSCB_ProbeUuid
1159 * Routine called by the server-side callback RPC interface to
1160 * implement ``probing'' the Cache Manager, just making sure it's
1161 * still there is still the same client it used to be.
1164 * a_call : Ptr to Rx call on which this request came in.
1165 * a_uuid : Ptr to UUID that must match the client's UUID.
1168 * 0 if a_uuid matches the UUID for this client
1169 * Non-zero otherwize
1172 * Nothing interesting.
1176 *------------------------------------------------------------------------*/
1179 SRXAFSCB_ProbeUuid(struct rx_call *a_call, afsUUID * a_uuid)
1185 AFS_STATCNT(SRXAFSCB_Probe);
1187 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_PROBE);
1188 if (!afs_uuid_equal(a_uuid, &afs_cb_interface.uuid))
1189 code = 1; /* failure */
1198 /*------------------------------------------------------------------------
1199 * EXPORTED SRXAFSCB_GetServerPrefs
1202 * Routine to list server preferences used by this client.
1205 * a_call : Ptr to Rx call on which this request came in.
1206 * a_index : Input server index
1207 * a_srvr_addr : Output server address in host byte order
1208 * (0xffffffff on last server)
1209 * a_srvr_rank : Output server rank
1215 * Nothing interesting.
1219 *------------------------------------------------------------------------*/
1222 SRXAFSCB_GetServerPrefs(struct rx_call *a_call, afs_int32 a_index,
1223 afs_int32 * a_srvr_addr, afs_int32 * a_srvr_rank)
1229 AFS_STATCNT(SRXAFSCB_GetServerPrefs);
1231 ObtainReadLock(&afs_xserver);
1233 /* Search the hash table for the server with this index */
1234 *a_srvr_addr = 0xffffffff;
1235 *a_srvr_rank = 0xffffffff;
1236 for (i = 0, j = 0; j < NSERVERS && i <= a_index; j++) {
1237 for (sa = afs_srvAddrs[j]; sa && i <= a_index; sa = sa->next_bkt, i++) {
1239 *a_srvr_addr = ntohl(sa->sa_ip);
1240 *a_srvr_rank = sa->sa_iprank;
1245 ReleaseReadLock(&afs_xserver);
1253 /*------------------------------------------------------------------------
1254 * EXPORTED SRXAFSCB_GetCellServDB
1257 * Routine to list cells configured for this client
1260 * a_call : Ptr to Rx call on which this request came in.
1261 * a_index : Input cell index
1262 * a_name : Output cell name ("" on last cell)
1263 * a_hosts : Output cell database servers in host byte order.
1269 * Nothing interesting.
1273 *------------------------------------------------------------------------*/
1276 SRXAFSCB_GetCellServDB(struct rx_call *a_call, afs_int32 a_index,
1277 char **a_name, serverList * a_hosts)
1281 char *t_name, *p_name = NULL;
1284 AFS_STATCNT(SRXAFSCB_GetCellServDB);
1286 tcell = afs_GetCellByIndex(a_index, READ_LOCK);
1290 a_hosts->serverList_val = 0;
1291 a_hosts->serverList_len = 0;
1293 p_name = tcell->cellName;
1294 for (j = 0; j < AFSMAXCELLHOSTS && tcell->cellHosts[j]; j++);
1296 a_hosts->serverList_val = afs_osi_Alloc(j * sizeof(afs_int32));
1297 osi_Assert(a_hosts->serverList_val != NULL);
1298 a_hosts->serverList_len = j;
1299 for (j = 0; j < AFSMAXCELLHOSTS && tcell->cellHosts[j]; j++)
1300 a_hosts->serverList_val[j] =
1301 ntohl(tcell->cellHosts[j]->addr->sa_ip);
1302 afs_PutCell(tcell, READ_LOCK);
1305 t_name = afs_osi_Alloc(i + 1);
1306 if (t_name == NULL) {
1307 afs_osi_Free(a_hosts->serverList_val, (j * sizeof(afs_int32)));
1314 memcpy(t_name, p_name, i);
1323 /*------------------------------------------------------------------------
1324 * EXPORTED SRXAFSCB_GetLocalCell
1327 * Routine to return name of client's local cell
1330 * a_call : Ptr to Rx call on which this request came in.
1331 * a_name : Output cell name
1337 * Nothing interesting.
1341 *------------------------------------------------------------------------*/
1344 SRXAFSCB_GetLocalCell(struct rx_call *a_call, char **a_name)
1348 char *t_name, *p_name = NULL;
1351 AFS_STATCNT(SRXAFSCB_GetLocalCell);
1353 /* Search the list for the primary cell. Cell number 1 is only
1354 * the primary cell is when no other cell is explicitly marked as
1355 * the primary cell. */
1356 tcell = afs_GetPrimaryCell(READ_LOCK);
1358 p_name = tcell->cellName;
1360 plen = strlen(p_name);
1363 t_name = afs_osi_Alloc(plen + 1);
1364 if (t_name == NULL) {
1366 afs_PutCell(tcell, READ_LOCK);
1371 t_name[plen] = '\0';
1373 memcpy(t_name, p_name, plen);
1379 afs_PutCell(tcell, READ_LOCK);
1385 * afs_MarshallCacheConfig - marshall client cache configuration
1389 * IN callerVersion - the rpc stat version of the caller.
1391 * IN config - client cache configuration.
1393 * OUT ptr - buffer where configuration is marshalled.
1400 afs_MarshallCacheConfig(afs_uint32 callerVersion, cm_initparams_v1 * config,
1403 AFS_STATCNT(afs_MarshallCacheConfig);
1405 * We currently only support version 1.
1407 *(ptr++) = config->nChunkFiles;
1408 *(ptr++) = config->nStatCaches;
1409 *(ptr++) = config->nDataCaches;
1410 *(ptr++) = config->nVolumeCaches;
1411 *(ptr++) = config->firstChunkSize;
1412 *(ptr++) = config->otherChunkSize;
1413 *(ptr++) = config->cacheSize;
1414 *(ptr++) = config->setTime;
1415 *(ptr++) = config->memCache;
1419 /*------------------------------------------------------------------------
1420 * EXPORTED SRXAFSCB_GetCacheConfig
1423 * Routine to return parameters used to initialize client cache.
1424 * Client may request any format version. Server may not return
1425 * format version greater than version requested by client.
1428 * a_call: Ptr to Rx call on which this request came in.
1429 * callerVersion: Data format version desired by the client.
1430 * serverVersion: Data format version of output data.
1431 * configCount: Number bytes allocated for output data.
1432 * config: Client cache configuration.
1438 * Nothing interesting.
1442 *------------------------------------------------------------------------*/
1445 SRXAFSCB_GetCacheConfig(struct rx_call *a_call, afs_uint32 callerVersion,
1446 afs_uint32 * serverVersion, afs_uint32 * configCount,
1447 cacheConfig * config)
1449 afs_uint32 *t_config;
1451 cm_initparams_v1 cm_config;
1454 AFS_STATCNT(SRXAFSCB_GetCacheConfig);
1457 * Currently only support version 1
1459 allocsize = sizeof(cm_initparams_v1);
1460 t_config = afs_osi_Alloc(allocsize);
1461 if (t_config == NULL) {
1466 cm_config.nChunkFiles = cm_initParams.cmi_nChunkFiles;
1467 cm_config.nStatCaches = cm_initParams.cmi_nStatCaches;
1468 cm_config.nDataCaches = cm_initParams.cmi_nDataCaches;
1469 cm_config.nVolumeCaches = cm_initParams.cmi_nVolumeCaches;
1470 cm_config.firstChunkSize = cm_initParams.cmi_firstChunkSize;
1471 cm_config.otherChunkSize = cm_initParams.cmi_otherChunkSize;
1472 cm_config.cacheSize = cm_initParams.cmi_cacheSize;
1473 cm_config.setTime = cm_initParams.cmi_setTime;
1474 cm_config.memCache = cm_initParams.cmi_memCache;
1476 afs_MarshallCacheConfig(callerVersion, &cm_config, t_config);
1478 *serverVersion = AFS_CLIENT_RETRIEVAL_FIRST_EDITION;
1479 *configCount = allocsize;
1480 config->cacheConfig_val = t_config;
1481 config->cacheConfig_len = allocsize / sizeof(afs_uint32);
1488 /*------------------------------------------------------------------------
1489 * EXPORTED SRXAFSCB_FetchData
1492 * Routine to do third party move from a remioserver to the original
1493 * issuer of an ArchiveData request. Presently supported only by the
1494 * "fs" command, not by the AFS client.
1497 * rxcall: Ptr to Rx call on which this request came in.
1498 * Fid: pointer to AFSFid structure.
1499 * Fd: File descriptor inside fs command.
1500 * Position: Offset in the file.
1501 * Length: Data length to transfer.
1502 * TotalLength: Pointer to total file length field
1508 * Nothing interesting.
1511 *------------------------------------------------------------------------*/
1513 SRXAFSCB_FetchData(struct rx_call *rxcall, struct AFSFid *Fid, afs_int32 Fd,
1514 afs_int64 Position, afs_int64 Length,
1515 afs_int64 * TotalLength)
1520 /*------------------------------------------------------------------------
1521 * EXPORTED SRXAFSCB_StoreData
1524 * Routine to do third party move from a remioserver to the original
1525 * issuer of a RetrieveData request. Presently supported only by the
1526 * "fs" command, not by the AFS client.
1529 * rxcall: Ptr to Rx call on which this request came in.
1530 * Fid: pointer to AFSFid structure.
1531 * Fd: File descriptor inside fs command.
1532 * Position: Offset in the file.
1533 * Length: Data length to transfer.
1534 * TotalLength: Pointer to total file length field
1540 * Nothing interesting.
1544 *------------------------------------------------------------------------*/
1546 SRXAFSCB_StoreData(struct rx_call *rxcall, struct AFSFid *Fid, afs_int32 Fd,
1547 afs_int64 Position, afs_int64 Length,
1548 afs_int64 * TotalLength)
1553 /*------------------------------------------------------------------------
1554 * EXPORTED SRXAFSCB_GetCellByNum
1557 * Routine to get information about a cell specified by its
1558 * cell number (returned by GetCE/GetCE64).
1561 * a_call : Ptr to Rx call on which this request came in.
1562 * a_cellnum : Input cell number
1563 * a_name : Output cell name (one zero byte when no such cell).
1564 * a_hosts : Output cell database servers in host byte order.
1570 * Nothing interesting.
1574 *------------------------------------------------------------------------*/
1577 SRXAFSCB_GetCellByNum(struct rx_call *a_call, afs_int32 a_cellnum,
1578 char **a_name, serverList * a_hosts)
1584 AFS_STATCNT(SRXAFSCB_GetCellByNum);
1586 a_hosts->serverList_val = 0;
1587 a_hosts->serverList_len = 0;
1589 tcell = afs_GetCellStale(a_cellnum, READ_LOCK);
1591 *a_name = afs_strdup("");
1596 ObtainReadLock(&tcell->lock);
1597 *a_name = afs_strdup(tcell->cellName);
1599 for (sn = 0; sn < AFSMAXCELLHOSTS && tcell->cellHosts[sn]; sn++);
1600 a_hosts->serverList_len = sn;
1601 a_hosts->serverList_val = afs_osi_Alloc(sn * sizeof(afs_int32));
1602 osi_Assert(a_hosts->serverList_val != NULL);
1604 for (i = 0; i < sn; i++)
1605 a_hosts->serverList_val[i] = ntohl(tcell->cellHosts[i]->addr->sa_ip);
1606 ReleaseReadLock(&tcell->lock);
1607 afs_PutCell(tcell, READ_LOCK);
1614 SRXAFSCB_TellMeAboutYourself(struct rx_call *a_call,
1615 struct interfaceAddr *addr,
1616 Capabilities * capabilities)
1620 afs_uint32 *dataBuffP;
1621 afs_int32 dataBytes;
1625 AFS_STATCNT(SRXAFSCB_WhoAreYou);
1627 ObtainReadLock(&afs_xinterface);
1629 /* return all network interface addresses */
1630 addr->numberOfInterfaces = afs_cb_interface.numberOfInterfaces;
1631 addr->uuid = afs_cb_interface.uuid;
1632 for (i = 0; i < afs_cb_interface.numberOfInterfaces; i++) {
1633 addr->addr_in[i] = ntohl(afs_cb_interface.addr_in[i]);
1634 addr->subnetmask[i] = ntohl(afs_cb_interface.subnetmask[i]);
1635 addr->mtu[i] = ntohl(afs_cb_interface.mtu[i]);
1638 ReleaseReadLock(&afs_xinterface);
1642 dataBytes = 1 * sizeof(afs_uint32);
1643 dataBuffP = afs_osi_Alloc(dataBytes);
1644 osi_Assert(dataBuffP != NULL);
1645 dataBuffP[0] = CLIENT_CAPABILITY_ERRORTRANS;
1646 capabilities->Capabilities_len = dataBytes / sizeof(afs_uint32);
1647 capabilities->Capabilities_val = dataBuffP;
1653 #if 0 && defined(AFS_LINUX24_ENV)
1654 extern struct vcache *afs_globalVp;
1656 int recurse_dcache_parent(parent, a_index, addr, inode, flags, time, fileName)
1657 struct dentry * parent;
1665 struct dentry *this_parent = parent;
1666 struct list_head *next;
1668 struct dentry *dentry;
1671 next = this_parent->d_subdirs.next;
1673 while (next != &this_parent->d_subdirs) {
1674 struct list_head *tmp = next;
1675 dentry = list_entry(tmp, struct dentry, d_child);
1681 * Descend a level if the d_subdirs list is non-empty.
1683 if (!list_empty(&dentry->d_subdirs)) {
1684 this_parent = dentry;
1689 * All done at this level ... ascend and resume the search.
1691 if (this_parent != parent) {
1692 next = this_parent->d_child.next;
1693 this_parent = this_parent->d_parent;
1699 if (d_unhashed(dentry))
1704 *fileName = afs_strdup(dentry->d_name.name?dentry->d_name.name:"");
1705 *inode = ITOAFS(dentry->d_inode);
1706 *addr = atomic_read(&(dentry)->d_count);
1707 *time = dentry->d_time;
1716 SRXAFSCB_GetDE(struct rx_call *a_call, afs_int32 a_index, afs_int32 *addr,
1717 afs_int32 *inode, afs_int32 *flags, afs_int32 *time,
1719 { /*SRXAFSCB_GetDE*/
1720 int code = 0; /*Return code*/
1721 #if 0 && defined(AFS_LINUX24_ENV)
1722 int i; /*Loop variable*/
1723 struct vcache *tvc = afs_globalVp;
1724 struct dentry *dentry;
1725 struct list_head *cur, *head = &(AFSTOI(tvc))->i_dentry;
1727 #ifdef RX_ENABLE_LOCKS
1729 #endif /* RX_ENABLE_LOCKS */
1731 #if defined(AFS_LINUX24_ENV)
1732 spin_lock(&dcache_lock);
1736 while ((cur = cur->next) != head) {
1737 dentry = list_entry(cur, struct dentry, d_alias);
1739 dget_locked(dentry);
1741 #if defined(AFS_LINUX24_ENV)
1742 spin_unlock(&dcache_lock);
1748 if (recurse_dcache_parent(dentry, a_index, addr, inode, flags, time, fileName) == 0) {
1759 *fileName = afs_strdup("");
1763 if (d_unhashed(dentry))
1768 *fileName = afs_strdup(dentry->d_name.name?dentry->d_name.name:"");
1769 *inode = ITOAFS(dentry->d_inode);
1770 *addr = atomic_read(&(dentry)->d_count);
1771 *time = dentry->d_time;
1778 #ifdef RX_ENABLE_LOCKS
1780 #endif /* RX_ENABLE_LOCKS */
1784 } /*SRXAFSCB_GetDE*/