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"
22 #include "afs/sysincludes.h" /*Standard vendor system headers */
23 #include "afsincludes.h" /*AFS-based standard headers */
24 #include "afs/afs_stats.h" /*Cache Manager stats */
25 #include "afs/afs_args.h"
27 afs_int32 afs_allCBs = 0; /*Break callbacks on all objects */
28 afs_int32 afs_oddCBs = 0; /*Break callbacks on dirs */
29 afs_int32 afs_evenCBs = 0; /*Break callbacks received on files */
30 afs_int32 afs_allZaps = 0; /*Objects entries deleted */
31 afs_int32 afs_oddZaps = 0; /*Dir cache entries deleted */
32 afs_int32 afs_evenZaps = 0; /*File cache entries deleted */
33 afs_int32 afs_connectBacks = 0;
36 * Some debugging aids.
38 static struct ltable {
43 "afs_xvcache", (char *)&afs_xvcache}, {
44 "afs_xdcache", (char *)&afs_xdcache}, {
45 "afs_xserver", (char *)&afs_xserver}, {
46 "afs_xvcb", (char *)&afs_xvcb}, {
47 "afs_xbrs", (char *)&afs_xbrs}, {
48 "afs_xcell", (char *)&afs_xcell}, {
49 "afs_xconn", (char *)&afs_xconn}, {
50 "afs_xuser", (char *)&afs_xuser}, {
51 "afs_xvolume", (char *)&afs_xvolume}, {
52 "puttofile", (char *)&afs_puttofileLock}, {
53 "afs_ftf", (char *)&afs_ftf}, {
54 "afs_xcbhash", (char *)&afs_xcbhash}, {
55 "afs_xaxs", (char *)&afs_xaxs}, {
56 "afs_xinterface", (char *)&afs_xinterface},
59 "afs_xosi", (char *)&afs_xosi},
62 "afs_xsrvAddr", (char *)&afs_xsrvAddr},
64 "afs_xvreclaim", (char *)&afs_xvreclaim},
66 { "afsdb_client_lock", (char *)&afsdb_client_lock},
67 { "afsdb_req_lock", (char *)&afsdb_req_lock},
70 unsigned long lastCallBack_vnode;
71 unsigned int lastCallBack_dv;
72 osi_timeval_t lastCallBack_time;
74 /* these are for storing alternate interface addresses */
75 struct interfaceAddr afs_cb_interface;
77 /*------------------------------------------------------------------------
78 * EXPORTED SRXAFSCB_GetCE
81 * Routine called by the server-side callback RPC interface to
82 * implement pulling out the contents of the i'th cache entry.
85 * a_call : Ptr to Rx call on which this request came in.
86 * a_index : Index of desired cache entry.
87 * a_result : Ptr to a buffer for the given cache entry.
90 * 0 if everything went fine,
91 * 1 if we were given a bad index.
94 * Nothing interesting.
98 *------------------------------------------------------------------------*/
101 SRXAFSCB_GetCE(struct rx_call *a_call, afs_int32 a_index,
102 struct AFSDBCacheEntry *a_result)
105 register int i; /*Loop variable */
106 register struct vcache *tvc; /*Ptr to current cache entry */
107 int code; /*Return code */
112 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_GETCE);
114 AFS_STATCNT(SRXAFSCB_GetCE);
115 for (i = 0; i < VCSIZE; i++) {
116 for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
120 } /*Zip through current hash chain */
121 } /*Zip through hash chains */
131 * Copy out the located entry.
133 a_result->addr = afs_data_pointer_to_int32(tvc);
134 a_result->cell = tvc->fid.Cell;
135 a_result->netFid.Volume = tvc->fid.Fid.Volume;
136 a_result->netFid.Vnode = tvc->fid.Fid.Vnode;
137 a_result->netFid.Unique = tvc->fid.Fid.Unique;
138 a_result->lock.waitStates = tvc->lock.wait_states;
139 a_result->lock.exclLocked = tvc->lock.excl_locked;
140 a_result->lock.readersReading = tvc->lock.readers_reading;
141 a_result->lock.numWaiting = tvc->lock.num_waiting;
142 #if defined(INSTRUMENT_LOCKS)
143 a_result->lock.pid_last_reader = MyPidxx2Pid(tvc->lock.pid_last_reader);
144 a_result->lock.pid_writer = MyPidxx2Pid(tvc->lock.pid_writer);
145 a_result->lock.src_indicator = tvc->lock.src_indicator;
147 /* On osf20 , the vcache does not maintain these three fields */
148 a_result->lock.pid_last_reader = 0;
149 a_result->lock.pid_writer = 0;
150 a_result->lock.src_indicator = 0;
151 #endif /* AFS_OSF20_ENV */
152 #ifdef AFS_64BIT_CLIENT
153 a_result->Length = (afs_int32) tvc->m.Length & 0xffffffff;
154 #else /* AFS_64BIT_CLIENT */
155 a_result->Length = tvc->m.Length;
156 #endif /* AFS_64BIT_CLIENT */
157 a_result->DataVersion = hgetlo(tvc->m.DataVersion);
158 a_result->callback = afs_data_pointer_to_int32(tvc->callback); /* XXXX Now a pointer; change it XXXX */
159 a_result->cbExpires = tvc->cbExpires;
160 if (tvc->states & CVInit) {
161 a_result->refCount = 1;
163 #ifdef AFS_DARWIN80_ENV
164 a_result->refCount = vnode_isinuse(AFSTOV(tvc),0)?1:0; /* XXX fix */
166 a_result->refCount = VREFCOUNT(tvc);
169 a_result->opens = tvc->opens;
170 a_result->writers = tvc->execsOrWriters;
171 a_result->mvstat = tvc->mvstat;
172 a_result->states = tvc->states;
176 * Return our results.
185 } /*SRXAFSCB_GetCE */
188 SRXAFSCB_GetCE64(struct rx_call *a_call, afs_int32 a_index,
189 struct AFSDBCacheEntry64 *a_result)
191 register int i; /*Loop variable */
192 register struct vcache *tvc; /*Ptr to current cache entry */
193 int code; /*Return code */
198 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_GETCE);
200 AFS_STATCNT(SRXAFSCB_GetCE64);
201 for (i = 0; i < VCSIZE; i++) {
202 for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
206 } /*Zip through current hash chain */
207 } /*Zip through hash chains */
217 * Copy out the located entry.
219 a_result->addr = afs_data_pointer_to_int32(tvc);
220 a_result->cell = tvc->fid.Cell;
221 a_result->netFid.Volume = tvc->fid.Fid.Volume;
222 a_result->netFid.Vnode = tvc->fid.Fid.Vnode;
223 a_result->netFid.Unique = tvc->fid.Fid.Unique;
224 a_result->lock.waitStates = tvc->lock.wait_states;
225 a_result->lock.exclLocked = tvc->lock.excl_locked;
226 a_result->lock.readersReading = tvc->lock.readers_reading;
227 a_result->lock.numWaiting = tvc->lock.num_waiting;
228 #if defined(INSTRUMENT_LOCKS)
229 a_result->lock.pid_last_reader = MyPidxx2Pid(tvc->lock.pid_last_reader);
230 a_result->lock.pid_writer = MyPidxx2Pid(tvc->lock.pid_writer);
231 a_result->lock.src_indicator = tvc->lock.src_indicator;
233 /* On osf20 , the vcache does not maintain these three fields */
234 a_result->lock.pid_last_reader = 0;
235 a_result->lock.pid_writer = 0;
236 a_result->lock.src_indicator = 0;
237 #endif /* AFS_OSF20_ENV */
238 #if !defined(AFS_64BIT_ENV)
239 a_result->Length.high = 0;
240 a_result->Length.low = tvc->m.Length;
242 a_result->Length = tvc->m.Length;
244 a_result->DataVersion = hgetlo(tvc->m.DataVersion);
245 a_result->callback = afs_data_pointer_to_int32(tvc->callback); /* XXXX Now a pointer; change it XXXX */
246 a_result->cbExpires = tvc->cbExpires;
247 if (tvc->states & CVInit) {
248 a_result->refCount = 1;
250 #ifdef AFS_DARWIN80_ENV
251 a_result->refCount = vnode_isinuse(AFSTOV(tvc),0)?1:0; /* XXX fix */
253 a_result->refCount = VREFCOUNT(tvc);
256 a_result->opens = tvc->opens;
257 a_result->writers = tvc->execsOrWriters;
258 a_result->mvstat = tvc->mvstat;
259 a_result->states = tvc->states;
263 * Return our results.
272 } /*SRXAFSCB_GetCE64 */
275 /*------------------------------------------------------------------------
276 * EXPORTED SRXAFSCB_GetLock
279 * Routine called by the server-side callback RPC interface to
280 * implement pulling out the contents of a lock in the lock
284 * a_call : Ptr to Rx call on which this request came in.
285 * a_index : Index of desired lock.
286 * a_result : Ptr to a buffer for the given lock.
289 * 0 if everything went fine,
290 * 1 if we were given a bad index.
293 * Nothing interesting.
297 *------------------------------------------------------------------------*/
300 SRXAFSCB_GetLock(struct rx_call *a_call, afs_int32 a_index,
301 struct AFSDBLock *a_result)
303 struct ltable *tl; /*Ptr to lock table entry */
304 int nentries; /*Num entries in table */
305 int code; /*Return code */
310 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_GETLOCK);
312 AFS_STATCNT(SRXAFSCB_GetLock);
313 nentries = sizeof(ltable) / sizeof(struct ltable);
314 if (a_index < 0 || a_index >= nentries+afs_cellindex) {
319 } else if (a_index >= nentries) {
320 struct cell *tc = afs_GetCellByIndex(a_index-nentries, 0);
321 strcpy(a_result->name, tc->cellName);
322 a_result->lock.waitStates =
323 ((struct afs_lock *)&(tc->lock))->wait_states;
324 a_result->lock.exclLocked =
325 ((struct afs_lock *)&(tc->lock))->excl_locked;
326 a_result->lock.readersReading =
327 ((struct afs_lock *)&(tc->lock))->readers_reading;
328 a_result->lock.numWaiting =
329 ((struct afs_lock *)&(tc->lock))->num_waiting;
330 #ifdef INSTRUMENT_LOCKS
331 a_result->lock.pid_last_reader =
332 MyPidxx2Pid(((struct afs_lock *)&(tc->lock))->pid_last_reader);
333 a_result->lock.pid_writer =
334 MyPidxx2Pid(((struct afs_lock *)&(tc->lock))->pid_writer);
335 a_result->lock.src_indicator =
336 ((struct afs_lock *)&(tc->lock))->src_indicator;
338 a_result->lock.pid_last_reader = 0;
339 a_result->lock.pid_writer = 0;
340 a_result->lock.src_indicator = 0;
345 * Found it - copy out its contents.
347 tl = <able[a_index];
348 strcpy(a_result->name, tl->name);
349 a_result->lock.waitStates =
350 ((struct afs_lock *)(tl->addr))->wait_states;
351 a_result->lock.exclLocked =
352 ((struct afs_lock *)(tl->addr))->excl_locked;
353 a_result->lock.readersReading =
354 ((struct afs_lock *)(tl->addr))->readers_reading;
355 a_result->lock.numWaiting =
356 ((struct afs_lock *)(tl->addr))->num_waiting;
357 #ifdef INSTRUMENT_LOCKS
358 a_result->lock.pid_last_reader =
359 MyPidxx2Pid(((struct afs_lock *)(tl->addr))->pid_last_reader);
360 a_result->lock.pid_writer =
361 MyPidxx2Pid(((struct afs_lock *)(tl->addr))->pid_writer);
362 a_result->lock.src_indicator =
363 ((struct afs_lock *)(tl->addr))->src_indicator;
365 a_result->lock.pid_last_reader = 0;
366 a_result->lock.pid_writer = 0;
367 a_result->lock.src_indicator = 0;
378 } /*SRXAFSCB_GetLock */
381 /*------------------------------------------------------------------------
382 * static ClearCallBack
385 * Clear out callback information for the specified file, or
386 * even a whole volume. Used to worry about callback was from
387 * within the particular cell or not. Now we don't bother with
388 * that anymore; it's not worth the time.
391 * a_conn : Ptr to Rx connection involved.
392 * a_fid : Ptr to AFS fid being cleared.
398 * Nothing interesting.
403 Appears to need to be called with GLOCK held, as the icl_Event4 stuff asserts otherwise
405 *------------------------------------------------------------------------*/
408 ClearCallBack(register struct rx_connection *a_conn,
409 register struct AFSFid *a_fid)
411 register struct vcache *tvc;
413 struct VenusFid localFid;
415 #ifdef AFS_DARWIN80_ENV
419 AFS_STATCNT(ClearCallBack);
424 * XXXX Don't hold any server locks here because of callback protocol XXX
427 localFid.Fid.Volume = a_fid->Volume;
428 localFid.Fid.Vnode = a_fid->Vnode;
429 localFid.Fid.Unique = a_fid->Unique;
432 * Volume ID of zero means don't do anything.
434 if (a_fid->Volume != 0) {
435 if (a_fid->Vnode == 0) {
436 struct afs_q *tq, *uq;
438 * Clear callback for the whole volume. Zip through the
439 * hash chain, nullifying entries whose volume ID matches.
442 ObtainReadLock(&afs_xvcache);
443 i = VCHashV(&localFid);
444 for (tq = afs_vhashTV[i].prev; tq != &afs_vhashTV[i]; tq = uq) {
447 if (tvc->fid.Fid.Volume == a_fid->Volume) {
448 tvc->callback = NULL;
450 localFid.Cell = tvc->fid.Cell;
451 tvc->dchint = NULL; /* invalidate hints */
452 if (tvc->states & CVInit) {
453 ReleaseReadLock(&afs_xvcache);
454 afs_osi_Sleep(&tvc->states);
457 #ifdef AFS_DARWIN80_ENV
458 if (tvc->states & CDeadVnode) {
459 ReleaseReadLock(&afs_xvcache);
460 afs_osi_Sleep(&tvc->states);
464 #if defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_HPUX_ENV) || defined(AFS_LINUX20_ENV)
465 VN_HOLD(AFSTOV(tvc));
467 #ifdef AFS_DARWIN80_ENV
478 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
481 VREFCOUNT_INC(tvc); /* AIX, apparently */
485 ReleaseReadLock(&afs_xvcache);
486 ObtainWriteLock(&afs_xcbhash, 449);
487 afs_DequeueCallback(tvc);
488 tvc->states &= ~(CStatd | CUnique | CBulkFetching);
490 if (tvc->fid.Fid.Vnode & 1)
494 ReleaseWriteLock(&afs_xcbhash);
495 if ((tvc->fid.Fid.Vnode & 1 || (vType(tvc) == VDIR)))
496 osi_dnlc_purgedp(tvc);
497 afs_Trace3(afs_iclSetp, CM_TRACE_CALLBACK,
498 ICL_TYPE_POINTER, tvc, ICL_TYPE_INT32,
499 tvc->states, ICL_TYPE_INT32,
501 #ifdef AFS_DARWIN80_ENV
502 vnode_put(AFSTOV(tvc));
504 ObtainReadLock(&afs_xvcache);
507 } else if ((tvc->states & CMValid)
508 && (tvc->mvid->Fid.Volume == a_fid->Volume)) {
509 tvc->states &= ~CMValid;
511 localFid.Cell = tvc->mvid->Cell;
514 ReleaseReadLock(&afs_xvcache);
517 * XXXX Don't hold any locks here XXXX
519 tv = afs_FindVolume(&localFid, 0);
521 afs_ResetVolumeInfo(tv);
522 afs_PutVolume(tv, 0);
523 /* invalidate mtpoint? */
525 } /*Clear callbacks for whole volume */
528 * Clear callbacks just for the one file.
532 if (a_fid->Vnode & 1)
533 afs_oddCBs++; /*Could do this on volume basis, too */
535 afs_evenCBs++; /*A particular fid was specified */
537 ObtainReadLock(&afs_xvcache);
538 i = VCHash(&localFid);
539 for (tvc = afs_vhashT[i]; tvc; tvc = uvc) {
541 if (tvc->fid.Fid.Vnode == a_fid->Vnode
542 && tvc->fid.Fid.Volume == a_fid->Volume
543 && tvc->fid.Fid.Unique == a_fid->Unique) {
544 tvc->callback = NULL;
545 tvc->dchint = NULL; /* invalidate hints */
546 if (tvc->states & CVInit) {
547 ReleaseReadLock(&afs_xvcache);
548 afs_osi_Sleep(&tvc->states);
551 #ifdef AFS_DARWIN80_ENV
552 if (tvc->states & CDeadVnode) {
553 ReleaseReadLock(&afs_xvcache);
554 afs_osi_Sleep(&tvc->states);
558 #if defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_HPUX_ENV) || defined(AFS_LINUX20_ENV)
559 VN_HOLD(AFSTOV(tvc));
561 #ifdef AFS_DARWIN80_ENV
572 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
575 VREFCOUNT_INC(tvc); /* AIX, apparently */
579 ReleaseReadLock(&afs_xvcache);
580 ObtainWriteLock(&afs_xcbhash, 450);
581 afs_DequeueCallback(tvc);
582 tvc->states &= ~(CStatd | CUnique | CBulkFetching);
583 ReleaseWriteLock(&afs_xcbhash);
584 if ((tvc->fid.Fid.Vnode & 1 || (vType(tvc) == VDIR)))
585 osi_dnlc_purgedp(tvc);
586 afs_Trace3(afs_iclSetp, CM_TRACE_CALLBACK,
587 ICL_TYPE_POINTER, tvc, ICL_TYPE_INT32,
588 tvc->states, ICL_TYPE_LONG, 0);
590 lastCallBack_vnode = afid->Vnode;
591 lastCallBack_dv = tvc->mstat.DataVersion.low;
592 osi_GetuTime(&lastCallBack_time);
594 #ifdef AFS_DARWIN80_ENV
595 vnode_put(AFSTOV(tvc));
597 ObtainReadLock(&afs_xvcache);
601 } /*Walk through hash table */
602 ReleaseReadLock(&afs_xvcache);
603 } /*Clear callbacks for one file */
606 /*Fid has non-zero volume ID */
608 * Always return a predictable value.
615 /*------------------------------------------------------------------------
616 * EXPORTED SRXAFSCB_CallBack
619 * Routine called by the server-side callback RPC interface to
620 * implement passing in callback information.
624 * a_call : Ptr to Rx call on which this request came in.
625 * a_fids : Ptr to array of fids involved.
626 * a_callbacks : Ptr to matching callback info for the fids.
632 * Nothing interesting.
636 *------------------------------------------------------------------------*/
639 SRXAFSCB_CallBack(struct rx_call *a_call, register struct AFSCBFids *a_fids,
640 struct AFSCBs *a_callbacks)
642 register int i; /*Loop variable */
643 struct AFSFid *tfid; /*Ptr to current fid */
644 register struct rx_connection *tconn; /*Call's connection */
650 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_CALLBACK);
652 AFS_STATCNT(SRXAFSCB_CallBack);
653 if (!(tconn = rx_ConnectionOf(a_call)))
655 tfid = (struct AFSFid *)a_fids->AFSCBFids_val;
658 * For now, we ignore callbacks, since the File Server only *breaks*
659 * callbacks at present.
661 for (i = 0; i < a_fids->AFSCBFids_len; i++)
662 ClearCallBack(tconn, &tfid[i]);
670 } /*SRXAFSCB_CallBack */
673 /*------------------------------------------------------------------------
674 * EXPORTED SRXAFSCB_Probe
677 * Routine called by the server-side callback RPC interface to
678 * implement ``probing'' the Cache Manager, just making sure it's
682 * a_call : Ptr to Rx call on which this request came in.
688 * Nothing interesting.
692 *------------------------------------------------------------------------*/
695 SRXAFSCB_Probe(struct rx_call *a_call)
701 AFS_STATCNT(SRXAFSCB_Probe);
703 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_PROBE);
710 } /*SRXAFSCB_Probe */
713 /*------------------------------------------------------------------------
714 * EXPORTED SRXAFSCB_InitCallBackState
717 * Routine called by the server-side callback RPC interface to
718 * implement clearing all callbacks from this host.
721 * a_call : Ptr to Rx call on which this request came in.
727 * Nothing interesting.
731 *------------------------------------------------------------------------*/
734 SRXAFSCB_InitCallBackState(struct rx_call *a_call)
737 register struct vcache *tvc;
738 register struct rx_connection *tconn;
739 register struct rx_peer *peer;
746 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_INITCALLBACKSTATE);
747 AFS_STATCNT(SRXAFSCB_InitCallBackState);
750 * Find the address of the host making this call
752 if ((tconn = rx_ConnectionOf(a_call)) && (peer = rx_PeerOf(tconn))) {
755 afs_oddCBs++; /*Including any missed via create race */
756 afs_evenCBs++; /*Including any missed via create race */
758 ts = afs_FindServer(rx_HostOf(peer), rx_PortOf(peer), (afsUUID *) 0,
761 for (i = 0; i < VCSIZE; i++)
762 for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
763 if (tvc->callback == ts) {
764 ObtainWriteLock(&afs_xcbhash, 451);
765 afs_DequeueCallback(tvc);
766 tvc->callback = NULL;
767 tvc->states &= ~(CStatd | CUnique | CBulkFetching);
768 ReleaseWriteLock(&afs_xcbhash);
775 /* find any volumes residing on this server and flush their state */
777 register struct volume *tv;
780 for (i = 0; i < NVOLS; i++)
781 for (tv = afs_volumes[i]; tv; tv = tv->next) {
782 for (j = 0; j < MAXHOSTS; j++)
783 if (tv->serverHost[j] == ts)
784 afs_ResetVolumeInfo(tv);
787 osi_dnlc_purge(); /* may be a little bit extreme */
796 } /*SRXAFSCB_InitCallBackState */
799 /*------------------------------------------------------------------------
800 * EXPORTED SRXAFSCB_XStatsVersion
803 * Routine called by the server-side callback RPC interface to
804 * implement pulling out the xstat version number for the Cache
808 * a_versionP : Ptr to the version number variable to set.
814 * Nothing interesting.
818 *------------------------------------------------------------------------*/
821 SRXAFSCB_XStatsVersion(struct rx_call *a_call, afs_int32 * a_versionP)
828 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_XSTATSVERSION);
830 *a_versionP = AFSCB_XSTAT_VERSION;
837 } /*SRXAFSCB_XStatsVersion */
840 /*------------------------------------------------------------------------
841 * EXPORTED SRXAFSCB_GetXStats
844 * Routine called by the server-side callback RPC interface to
845 * implement getting the given data collection from the extended
846 * Cache Manager statistics.
849 * a_call : Ptr to Rx call on which this request came in.
850 * a_clientVersionNum : Client version number.
851 * a_opCode : Desired operation.
852 * a_serverVersionNumP : Ptr to version number to set.
853 * a_timeP : Ptr to time value (seconds) to set.
854 * a_dataArray : Ptr to variable array structure to return
861 * Nothing interesting.
865 *------------------------------------------------------------------------*/
868 SRXAFSCB_GetXStats(struct rx_call *a_call, afs_int32 a_clientVersionNum,
869 afs_int32 a_collectionNumber, afs_int32 * a_srvVersionNumP,
870 afs_int32 * a_timeP, AFSCB_CollData * a_dataP)
872 register int code; /*Return value */
873 afs_int32 *dataBuffP; /*Ptr to data to be returned */
874 afs_int32 dataBytes; /*Bytes in data buffer */
879 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_GETXSTATS);
882 * Record the time of day and the server version number.
884 *a_srvVersionNumP = AFSCB_XSTAT_VERSION;
885 *a_timeP = osi_Time();
888 * Stuff the appropriate data in there (assume victory)
894 * We're not keeping stats, so just return successfully with
897 a_dataP->AFSCB_CollData_len = 0;
898 a_dataP->AFSCB_CollData_val = NULL;
900 switch (a_collectionNumber) {
901 case AFSCB_XSTATSCOLL_CALL_INFO:
903 * Pass back all the call-count-related data.
905 * >>> We are forced to allocate a separate area in which to
906 * >>> put this stuff in by the RPC stub generator, since it
907 * >>> will be freed at the tail end of the server stub code.
909 dataBytes = sizeof(struct afs_CMStats);
910 dataBuffP = (afs_int32 *) afs_osi_Alloc(dataBytes);
911 memcpy((char *)dataBuffP, (char *)&afs_cmstats, dataBytes);
912 a_dataP->AFSCB_CollData_len = dataBytes >> 2;
913 a_dataP->AFSCB_CollData_val = dataBuffP;
916 case AFSCB_XSTATSCOLL_PERF_INFO:
918 * Update and then pass back all the performance-related data.
919 * Note: the only performance fields that need to be computed
920 * at this time are the number of accesses for this collection
921 * and the current server record info.
923 * >>> We are forced to allocate a separate area in which to
924 * >>> put this stuff in by the RPC stub generator, since it
925 * >>> will be freed at the tail end of the server stub code.
927 afs_stats_cmperf.numPerfCalls++;
929 dataBytes = sizeof(afs_stats_cmperf);
930 dataBuffP = (afs_int32 *) afs_osi_Alloc(dataBytes);
931 memcpy((char *)dataBuffP, (char *)&afs_stats_cmperf, dataBytes);
932 a_dataP->AFSCB_CollData_len = dataBytes >> 2;
933 a_dataP->AFSCB_CollData_val = dataBuffP;
936 case AFSCB_XSTATSCOLL_FULL_PERF_INFO:
938 * Pass back the full range of performance and statistical
939 * data available. We have to bring the normal performance
940 * data collection up to date, then copy that data into
941 * the full collection.
943 * >>> We are forced to allocate a separate area in which to
944 * >>> put this stuff in by the RPC stub generator, since it
945 * >>> will be freed at the tail end of the server stub code.
947 afs_stats_cmperf.numPerfCalls++;
949 memcpy((char *)(&(afs_stats_cmfullperf.perf)),
950 (char *)(&afs_stats_cmperf), sizeof(struct afs_stats_CMPerf));
951 afs_stats_cmfullperf.numFullPerfCalls++;
953 dataBytes = sizeof(afs_stats_cmfullperf);
954 dataBuffP = (afs_int32 *) afs_osi_Alloc(dataBytes);
955 memcpy((char *)dataBuffP, (char *)(&afs_stats_cmfullperf), dataBytes);
956 a_dataP->AFSCB_CollData_len = dataBytes >> 2;
957 a_dataP->AFSCB_CollData_val = dataBuffP;
962 * Illegal collection number.
964 a_dataP->AFSCB_CollData_len = 0;
965 a_dataP->AFSCB_CollData_val = NULL;
967 } /*Switch on collection number */
968 #endif /* AFS_NOSTATS */
976 } /*SRXAFSCB_GetXStats */
979 /*------------------------------------------------------------------------
980 * EXPORTED afs_RXCallBackServer
983 * Body of the thread supporting callback services.
992 * Nothing interesting.
996 *------------------------------------------------------------------------*/
999 afs_RXCallBackServer(void)
1001 AFS_STATCNT(afs_RXCallBackServer);
1006 afs_osi_Sleep(&afs_server);
1010 * Donate this process to Rx.
1012 rx_ServerProc(NULL);
1015 } /*afs_RXCallBackServer */
1018 /*------------------------------------------------------------------------
1019 * EXPORTED shutdown_CB
1022 * Zero out important Cache Manager data structures.
1031 * Nothing interesting.
1035 *------------------------------------------------------------------------*/
1040 AFS_STATCNT(shutdown_CB);
1042 if (afs_cold_shutdown) {
1043 afs_oddCBs = afs_evenCBs = afs_allCBs = afs_allZaps = afs_oddZaps =
1044 afs_evenZaps = afs_connectBacks = 0;
1051 /*------------------------------------------------------------------------
1052 * EXPORTED SRXAFSCB_InitCallBackState2
1055 * This routine was used in the AFS 3.5 beta release, but not anymore.
1056 * It has since been replaced by SRXAFSCB_InitCallBackState3.
1059 * a_call : Ptr to Rx call on which this request came in.
1062 * RXGEN_OPCODE (always).
1065 * Nothing interesting.
1069 *------------------------------------------------------------------------*/
1072 SRXAFSCB_InitCallBackState2(struct rx_call *a_call,
1073 struct interfaceAddr *addr)
1075 return RXGEN_OPCODE;
1078 /*------------------------------------------------------------------------
1079 * EXPORTED SRXAFSCB_WhoAreYou
1082 * Routine called by the server-side callback RPC interface to
1083 * obtain a unique identifier for the client. The server uses
1084 * this identifier to figure out whether or not two RX connections
1085 * are from the same client, and to find out which addresses go
1086 * with which clients.
1089 * a_call : Ptr to Rx call on which this request came in.
1090 * addr: Ptr to return the list of interfaces for this client.
1096 * Nothing interesting.
1100 *------------------------------------------------------------------------*/
1103 SRXAFSCB_WhoAreYou(struct rx_call *a_call, struct interfaceAddr *addr)
1110 AFS_STATCNT(SRXAFSCB_WhoAreYou);
1112 memset(addr, 0, sizeof(*addr));
1114 ObtainReadLock(&afs_xinterface);
1116 /* return all network interface addresses */
1117 addr->numberOfInterfaces = afs_cb_interface.numberOfInterfaces;
1118 addr->uuid = afs_cb_interface.uuid;
1119 for (i = 0; i < afs_cb_interface.numberOfInterfaces; i++) {
1120 addr->addr_in[i] = ntohl(afs_cb_interface.addr_in[i]);
1121 addr->subnetmask[i] = ntohl(afs_cb_interface.subnetmask[i]);
1122 addr->mtu[i] = ntohl(afs_cb_interface.mtu[i]);
1125 ReleaseReadLock(&afs_xinterface);
1133 /*------------------------------------------------------------------------
1134 * EXPORTED SRXAFSCB_InitCallBackState3
1137 * Routine called by the server-side callback RPC interface to
1138 * implement clearing all callbacks from this host.
1141 * a_call : Ptr to Rx call on which this request came in.
1147 * Nothing interesting.
1151 *------------------------------------------------------------------------*/
1154 SRXAFSCB_InitCallBackState3(struct rx_call *a_call, afsUUID * a_uuid)
1159 * TBD: Lookup the server by the UUID instead of its IP address.
1161 code = SRXAFSCB_InitCallBackState(a_call);
1167 /*------------------------------------------------------------------------
1168 * EXPORTED SRXAFSCB_ProbeUuid
1171 * Routine called by the server-side callback RPC interface to
1172 * implement ``probing'' the Cache Manager, just making sure it's
1173 * still there is still the same client it used to be.
1176 * a_call : Ptr to Rx call on which this request came in.
1177 * a_uuid : Ptr to UUID that must match the client's UUID.
1180 * 0 if a_uuid matches the UUID for this client
1181 * Non-zero otherwize
1184 * Nothing interesting.
1188 *------------------------------------------------------------------------*/
1191 SRXAFSCB_ProbeUuid(struct rx_call *a_call, afsUUID * a_uuid)
1197 AFS_STATCNT(SRXAFSCB_Probe);
1199 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_PROBE);
1200 if (!afs_uuid_equal(a_uuid, &afs_cb_interface.uuid))
1201 code = 1; /* failure */
1210 /*------------------------------------------------------------------------
1211 * EXPORTED SRXAFSCB_GetServerPrefs
1214 * Routine to list server preferences used by this client.
1217 * a_call : Ptr to Rx call on which this request came in.
1218 * a_index : Input server index
1219 * a_srvr_addr : Output server address in host byte order
1220 * (0xffffffff on last server)
1221 * a_srvr_rank : Output server rank
1227 * Nothing interesting.
1231 *------------------------------------------------------------------------*/
1234 SRXAFSCB_GetServerPrefs(struct rx_call *a_call, afs_int32 a_index,
1235 afs_int32 * a_srvr_addr, afs_int32 * a_srvr_rank)
1241 AFS_STATCNT(SRXAFSCB_GetServerPrefs);
1243 ObtainReadLock(&afs_xserver);
1245 /* Search the hash table for the server with this index */
1246 *a_srvr_addr = 0xffffffff;
1247 *a_srvr_rank = 0xffffffff;
1248 for (i = 0, j = 0; j < NSERVERS && i <= a_index; j++) {
1249 for (sa = afs_srvAddrs[j]; sa && i <= a_index; sa = sa->next_bkt, i++) {
1251 *a_srvr_addr = ntohl(sa->sa_ip);
1252 *a_srvr_rank = sa->sa_iprank;
1257 ReleaseReadLock(&afs_xserver);
1265 /*------------------------------------------------------------------------
1266 * EXPORTED SRXAFSCB_GetCellServDB
1269 * Routine to list cells configured for this client
1272 * a_call : Ptr to Rx call on which this request came in.
1273 * a_index : Input cell index
1274 * a_name : Output cell name ("" on last cell)
1275 * a_hosts : Output cell database servers in host byte order.
1281 * Nothing interesting.
1285 *------------------------------------------------------------------------*/
1288 SRXAFSCB_GetCellServDB(struct rx_call *a_call, afs_int32 a_index,
1289 char **a_name, serverList * a_hosts)
1293 char *t_name, *p_name = NULL;
1296 AFS_STATCNT(SRXAFSCB_GetCellServDB);
1298 tcell = afs_GetCellByIndex(a_index, READ_LOCK);
1302 a_hosts->serverList_val = 0;
1303 a_hosts->serverList_len = 0;
1305 p_name = tcell->cellName;
1306 for (j = 0; j < AFSMAXCELLHOSTS && tcell->cellHosts[j]; j++);
1308 a_hosts->serverList_val =
1309 (afs_int32 *) afs_osi_Alloc(j * sizeof(afs_int32));
1310 a_hosts->serverList_len = j;
1311 for (j = 0; j < AFSMAXCELLHOSTS && tcell->cellHosts[j]; j++)
1312 a_hosts->serverList_val[j] =
1313 ntohl(tcell->cellHosts[j]->addr->sa_ip);
1314 afs_PutCell(tcell, READ_LOCK);
1317 t_name = (char *)afs_osi_Alloc(i + 1);
1318 if (t_name == NULL) {
1319 afs_osi_Free(a_hosts->serverList_val, (j * sizeof(afs_int32)));
1326 memcpy(t_name, p_name, i);
1335 /*------------------------------------------------------------------------
1336 * EXPORTED SRXAFSCB_GetLocalCell
1339 * Routine to return name of client's local cell
1342 * a_call : Ptr to Rx call on which this request came in.
1343 * a_name : Output cell name
1349 * Nothing interesting.
1353 *------------------------------------------------------------------------*/
1356 SRXAFSCB_GetLocalCell(struct rx_call *a_call, char **a_name)
1360 char *t_name, *p_name = NULL;
1363 AFS_STATCNT(SRXAFSCB_GetLocalCell);
1365 /* Search the list for the primary cell. Cell number 1 is only
1366 * the primary cell is when no other cell is explicitly marked as
1367 * the primary cell. */
1368 tcell = afs_GetPrimaryCell(READ_LOCK);
1370 p_name = tcell->cellName;
1372 plen = strlen(p_name);
1375 t_name = (char *)afs_osi_Alloc(plen + 1);
1376 if (t_name == NULL) {
1378 afs_PutCell(tcell, READ_LOCK);
1383 t_name[plen] = '\0';
1385 memcpy(t_name, p_name, plen);
1391 afs_PutCell(tcell, READ_LOCK);
1397 * afs_MarshallCacheConfig - marshall client cache configuration
1401 * IN callerVersion - the rpc stat version of the caller.
1403 * IN config - client cache configuration.
1405 * OUT ptr - buffer where configuration is marshalled.
1412 afs_MarshallCacheConfig(afs_uint32 callerVersion, cm_initparams_v1 * config,
1415 AFS_STATCNT(afs_MarshallCacheConfig);
1417 * We currently only support version 1.
1419 *(ptr++) = config->nChunkFiles;
1420 *(ptr++) = config->nStatCaches;
1421 *(ptr++) = config->nDataCaches;
1422 *(ptr++) = config->nVolumeCaches;
1423 *(ptr++) = config->firstChunkSize;
1424 *(ptr++) = config->otherChunkSize;
1425 *(ptr++) = config->cacheSize;
1426 *(ptr++) = config->setTime;
1427 *(ptr++) = config->memCache;
1431 /*------------------------------------------------------------------------
1432 * EXPORTED SRXAFSCB_GetCacheConfig
1435 * Routine to return parameters used to initialize client cache.
1436 * Client may request any format version. Server may not return
1437 * format version greater than version requested by client.
1440 * a_call: Ptr to Rx call on which this request came in.
1441 * callerVersion: Data format version desired by the client.
1442 * serverVersion: Data format version of output data.
1443 * configCount: Number bytes allocated for output data.
1444 * config: Client cache configuration.
1450 * Nothing interesting.
1454 *------------------------------------------------------------------------*/
1457 SRXAFSCB_GetCacheConfig(struct rx_call *a_call, afs_uint32 callerVersion,
1458 afs_uint32 * serverVersion, afs_uint32 * configCount,
1459 cacheConfig * config)
1461 afs_uint32 *t_config;
1463 cm_initparams_v1 cm_config;
1466 AFS_STATCNT(SRXAFSCB_GetCacheConfig);
1469 * Currently only support version 1
1471 allocsize = sizeof(cm_initparams_v1);
1472 t_config = (afs_uint32 *) afs_osi_Alloc(allocsize);
1473 if (t_config == NULL) {
1478 cm_config.nChunkFiles = cm_initParams.cmi_nChunkFiles;
1479 cm_config.nStatCaches = cm_initParams.cmi_nStatCaches;
1480 cm_config.nDataCaches = cm_initParams.cmi_nDataCaches;
1481 cm_config.nVolumeCaches = cm_initParams.cmi_nVolumeCaches;
1482 cm_config.firstChunkSize = cm_initParams.cmi_firstChunkSize;
1483 cm_config.otherChunkSize = cm_initParams.cmi_otherChunkSize;
1484 cm_config.cacheSize = cm_initParams.cmi_cacheSize;
1485 cm_config.setTime = cm_initParams.cmi_setTime;
1486 cm_config.memCache = cm_initParams.cmi_memCache;
1488 afs_MarshallCacheConfig(callerVersion, &cm_config, t_config);
1490 *serverVersion = AFS_CLIENT_RETRIEVAL_FIRST_EDITION;
1491 *configCount = allocsize;
1492 config->cacheConfig_val = t_config;
1493 config->cacheConfig_len = allocsize / sizeof(afs_uint32);
1500 /*------------------------------------------------------------------------
1501 * EXPORTED SRXAFSCB_FetchData
1504 * Routine to do third party move from a remioserver to the original
1505 * issuer of an ArchiveData request. Presently supported only by the
1506 * "fs" command, not by the AFS client.
1509 * rxcall: Ptr to Rx call on which this request came in.
1510 * Fid: pointer to AFSFid structure.
1511 * Fd: File descriptor inside fs command.
1512 * Position: Offset in the file.
1513 * Length: Data length to transfer.
1514 * TotalLength: Pointer to total file length field
1520 * Nothing interesting.
1523 *------------------------------------------------------------------------*/
1525 SRXAFSCB_FetchData(struct rx_call *rxcall, struct AFSFid *Fid, afs_int32 Fd,
1526 afs_int64 Position, afs_int64 Length,
1527 afs_int64 * TotalLength)
1532 /*------------------------------------------------------------------------
1533 * EXPORTED SRXAFSCB_StoreData
1536 * Routine to do third party move from a remioserver to the original
1537 * issuer of a RetrieveData request. Presently supported only by the
1538 * "fs" command, not by the AFS client.
1541 * rxcall: Ptr to Rx call on which this request came in.
1542 * Fid: pointer to AFSFid structure.
1543 * Fd: File descriptor inside fs command.
1544 * Position: Offset in the file.
1545 * Length: Data length to transfer.
1546 * TotalLength: Pointer to total file length field
1552 * Nothing interesting.
1556 *------------------------------------------------------------------------*/
1558 SRXAFSCB_StoreData(struct rx_call *rxcall, struct AFSFid *Fid, afs_int32 Fd,
1559 afs_int64 Position, afs_int64 Length,
1560 afs_int64 * TotalLength)
1565 /*------------------------------------------------------------------------
1566 * EXPORTED SRXAFSCB_GetCellByNum
1569 * Routine to get information about a cell specified by its
1570 * cell number (returned by GetCE/GetCE64).
1573 * a_call : Ptr to Rx call on which this request came in.
1574 * a_cellnum : Input cell number
1575 * a_name : Output cell name (one zero byte when no such cell).
1576 * a_hosts : Output cell database servers in host byte order.
1582 * Nothing interesting.
1586 *------------------------------------------------------------------------*/
1589 SRXAFSCB_GetCellByNum(struct rx_call *a_call, afs_int32 a_cellnum,
1590 char **a_name, serverList * a_hosts)
1596 AFS_STATCNT(SRXAFSCB_GetCellByNum);
1598 a_hosts->serverList_val = 0;
1599 a_hosts->serverList_len = 0;
1601 tcell = afs_GetCellStale(a_cellnum, READ_LOCK);
1603 *a_name = afs_strdup("");
1608 ObtainReadLock(&tcell->lock);
1609 *a_name = afs_strdup(tcell->cellName);
1611 for (sn = 0; sn < AFSMAXCELLHOSTS && tcell->cellHosts[sn]; sn++);
1612 a_hosts->serverList_len = sn;
1613 a_hosts->serverList_val =
1614 (afs_int32 *) afs_osi_Alloc(sn * sizeof(afs_int32));
1616 for (i = 0; i < sn; i++)
1617 a_hosts->serverList_val[i] = ntohl(tcell->cellHosts[i]->addr->sa_ip);
1618 ReleaseReadLock(&tcell->lock);
1619 afs_PutCell(tcell, READ_LOCK);
1626 SRXAFSCB_TellMeAboutYourself(struct rx_call *a_call,
1627 struct interfaceAddr *addr,
1628 Capabilities * capabilities)
1632 afs_int32 *dataBuffP;
1633 afs_int32 dataBytes;
1637 AFS_STATCNT(SRXAFSCB_WhoAreYou);
1639 ObtainReadLock(&afs_xinterface);
1641 /* return all network interface addresses */
1642 addr->numberOfInterfaces = afs_cb_interface.numberOfInterfaces;
1643 addr->uuid = afs_cb_interface.uuid;
1644 for (i = 0; i < afs_cb_interface.numberOfInterfaces; i++) {
1645 addr->addr_in[i] = ntohl(afs_cb_interface.addr_in[i]);
1646 addr->subnetmask[i] = ntohl(afs_cb_interface.subnetmask[i]);
1647 addr->mtu[i] = ntohl(afs_cb_interface.mtu[i]);
1650 ReleaseReadLock(&afs_xinterface);
1654 dataBytes = 1 * sizeof(afs_int32);
1655 dataBuffP = (afs_int32 *) afs_osi_Alloc(dataBytes);
1656 dataBuffP[0] = CLIENT_CAPABILITY_ERRORTRANS;
1657 capabilities->Capabilities_len = dataBytes / sizeof(afs_int32);
1658 capabilities->Capabilities_val = dataBuffP;
1664 #if 0 && defined(AFS_LINUX24_ENV)
1665 extern struct vcache *afs_globalVp;
1667 int recurse_dcache_parent(parent, a_index, addr, inode, flags, time, fileName)
1668 struct dentry * parent;
1676 struct dentry *this_parent = parent;
1677 struct list_head *next;
1679 struct dentry *dentry;
1682 next = this_parent->d_subdirs.next;
1684 while (next != &this_parent->d_subdirs) {
1685 struct list_head *tmp = next;
1686 dentry = list_entry(tmp, struct dentry, d_child);
1692 * Descend a level if the d_subdirs list is non-empty.
1694 if (!list_empty(&dentry->d_subdirs)) {
1695 this_parent = dentry;
1700 * All done at this level ... ascend and resume the search.
1702 if (this_parent != parent) {
1703 next = this_parent->d_child.next;
1704 this_parent = this_parent->d_parent;
1710 if (d_unhashed(dentry))
1715 *fileName = afs_strdup(dentry->d_name.name?dentry->d_name.name:"");
1716 *inode = ITOAFS(dentry->d_inode);
1717 *addr = atomic_read(&(dentry)->d_count);
1718 *time = dentry->d_time;
1726 int SRXAFSCB_GetDE(a_call, a_index, addr, inode, flags, time, fileName)
1727 struct rx_call *a_call;
1734 { /*SRXAFSCB_GetDE*/
1735 int code = 0; /*Return code*/
1736 #if 0 && defined(AFS_LINUX24_ENV)
1737 register int i; /*Loop variable*/
1738 register struct vcache *tvc = afs_globalVp;
1739 struct dentry *dentry;
1740 struct list_head *cur, *head = &(AFSTOI(tvc))->i_dentry;
1742 #ifdef RX_ENABLE_LOCKS
1744 #endif /* RX_ENABLE_LOCKS */
1746 #if defined(AFS_LINUX24_ENV)
1747 spin_lock(&dcache_lock);
1751 while ((cur = cur->next) != head) {
1752 dentry = list_entry(cur, struct dentry, d_alias);
1754 dget_locked(dentry);
1756 #if defined(AFS_LINUX24_ENV)
1757 spin_unlock(&dcache_lock);
1763 if (recurse_dcache_parent(dentry, a_index, addr, inode, flags, time, fileName) == 0) {
1774 *fileName = afs_strdup("");
1778 if (d_unhashed(dentry))
1783 *fileName = afs_strdup(dentry->d_name.name?dentry->d_name.name:"");
1784 *inode = ITOAFS(dentry->d_inode);
1785 *addr = atomic_read(&(dentry)->d_count);
1786 *time = dentry->d_time;
1793 #ifdef RX_ENABLE_LOCKS
1795 #endif /* RX_ENABLE_LOCKS */
1799 } /*SRXAFSCB_GetDE*/