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 unsigned long lastCallBack_vnode;
67 unsigned int lastCallBack_dv;
68 osi_timeval_t lastCallBack_time;
70 /* these are for storing alternate interface addresses */
71 struct interfaceAddr afs_cb_interface;
73 /*------------------------------------------------------------------------
74 * EXPORTED SRXAFSCB_GetCE
77 * Routine called by the server-side callback RPC interface to
78 * implement pulling out the contents of the i'th cache entry.
81 * a_call : Ptr to Rx call on which this request came in.
82 * a_index : Index of desired cache entry.
83 * a_result : Ptr to a buffer for the given cache entry.
86 * 0 if everything went fine,
87 * 1 if we were given a bad index.
90 * Nothing interesting.
94 *------------------------------------------------------------------------*/
97 SRXAFSCB_GetCE(struct rx_call *a_call, afs_int32 a_index,
98 struct AFSDBCacheEntry *a_result)
101 register int i; /*Loop variable */
102 register struct vcache *tvc; /*Ptr to current cache entry */
103 int code; /*Return code */
108 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_GETCE);
110 AFS_STATCNT(SRXAFSCB_GetCE);
111 for (i = 0; i < VCSIZE; i++) {
112 for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
116 } /*Zip through current hash chain */
117 } /*Zip through hash chains */
127 * Copy out the located entry.
129 a_result->addr = afs_data_pointer_to_int32(tvc);
130 a_result->cell = tvc->fid.Cell;
131 a_result->netFid.Volume = tvc->fid.Fid.Volume;
132 a_result->netFid.Vnode = tvc->fid.Fid.Vnode;
133 a_result->netFid.Unique = tvc->fid.Fid.Unique;
134 a_result->lock.waitStates = tvc->lock.wait_states;
135 a_result->lock.exclLocked = tvc->lock.excl_locked;
136 a_result->lock.readersReading = tvc->lock.readers_reading;
137 a_result->lock.numWaiting = tvc->lock.num_waiting;
138 #if defined(INSTRUMENT_LOCKS)
139 a_result->lock.pid_last_reader = tvc->lock.pid_last_reader;
140 a_result->lock.pid_writer = tvc->lock.pid_writer;
141 a_result->lock.src_indicator = tvc->lock.src_indicator;
143 /* On osf20 , the vcache does not maintain these three fields */
144 a_result->lock.pid_last_reader = 0;
145 a_result->lock.pid_writer = 0;
146 a_result->lock.src_indicator = 0;
147 #endif /* AFS_OSF20_ENV */
148 #ifdef AFS_64BIT_CLIENT
149 a_result->Length = (afs_int32) tvc->m.Length & 0xffffffff;
150 #else /* AFS_64BIT_CLIENT */
151 a_result->Length = tvc->m.Length;
152 #endif /* AFS_64BIT_CLIENT */
153 a_result->DataVersion = hgetlo(tvc->m.DataVersion);
154 a_result->callback = afs_data_pointer_to_int32(tvc->callback); /* XXXX Now a pointer; change it XXXX */
155 a_result->cbExpires = tvc->cbExpires;
156 if (tvc->states & CVInit) {
157 a_result->refCount = 1;
159 #ifdef AFS_DARWIN80_ENV
160 a_result->refCount = vnode_isinuse(AFSTOV(tvc),0)?1:0; /* XXX fix */
162 a_result->refCount = VREFCOUNT(tvc);
165 a_result->opens = tvc->opens;
166 a_result->writers = tvc->execsOrWriters;
167 a_result->mvstat = tvc->mvstat;
168 a_result->states = tvc->states;
172 * Return our results.
181 } /*SRXAFSCB_GetCE */
184 SRXAFSCB_GetCE64(struct rx_call *a_call, afs_int32 a_index,
185 struct AFSDBCacheEntry64 *a_result)
187 register int i; /*Loop variable */
188 register struct vcache *tvc; /*Ptr to current cache entry */
189 int code; /*Return code */
194 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_GETCE);
196 AFS_STATCNT(SRXAFSCB_GetCE64);
197 for (i = 0; i < VCSIZE; i++) {
198 for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
202 } /*Zip through current hash chain */
203 } /*Zip through hash chains */
213 * Copy out the located entry.
215 a_result->addr = afs_data_pointer_to_int32(tvc);
216 a_result->cell = tvc->fid.Cell;
217 a_result->netFid.Volume = tvc->fid.Fid.Volume;
218 a_result->netFid.Vnode = tvc->fid.Fid.Vnode;
219 a_result->netFid.Unique = tvc->fid.Fid.Unique;
220 a_result->lock.waitStates = tvc->lock.wait_states;
221 a_result->lock.exclLocked = tvc->lock.excl_locked;
222 a_result->lock.readersReading = tvc->lock.readers_reading;
223 a_result->lock.numWaiting = tvc->lock.num_waiting;
224 #if defined(INSTRUMENT_LOCKS)
225 a_result->lock.pid_last_reader = tvc->lock.pid_last_reader;
226 a_result->lock.pid_writer = tvc->lock.pid_writer;
227 a_result->lock.src_indicator = tvc->lock.src_indicator;
229 /* On osf20 , the vcache does not maintain these three fields */
230 a_result->lock.pid_last_reader = 0;
231 a_result->lock.pid_writer = 0;
232 a_result->lock.src_indicator = 0;
233 #endif /* AFS_OSF20_ENV */
234 #if !defined(AFS_64BIT_ENV)
235 a_result->Length.high = 0;
236 a_result->Length.low = tvc->m.Length;
238 a_result->Length = tvc->m.Length;
240 a_result->DataVersion = hgetlo(tvc->m.DataVersion);
241 a_result->callback = afs_data_pointer_to_int32(tvc->callback); /* XXXX Now a pointer; change it XXXX */
242 a_result->cbExpires = tvc->cbExpires;
243 if (tvc->states & CVInit) {
244 a_result->refCount = 1;
246 #ifdef AFS_DARWIN80_ENV
247 a_result->refCount = vnode_isinuse(AFSTOV(tvc),0)?1:0; /* XXX fix */
249 a_result->refCount = VREFCOUNT(tvc);
252 a_result->opens = tvc->opens;
253 a_result->writers = tvc->execsOrWriters;
254 a_result->mvstat = tvc->mvstat;
255 a_result->states = tvc->states;
259 * Return our results.
268 } /*SRXAFSCB_GetCE64 */
271 /*------------------------------------------------------------------------
272 * EXPORTED SRXAFSCB_GetLock
275 * Routine called by the server-side callback RPC interface to
276 * implement pulling out the contents of a lock in the lock
280 * a_call : Ptr to Rx call on which this request came in.
281 * a_index : Index of desired lock.
282 * a_result : Ptr to a buffer for the given lock.
285 * 0 if everything went fine,
286 * 1 if we were given a bad index.
289 * Nothing interesting.
293 *------------------------------------------------------------------------*/
296 SRXAFSCB_GetLock(struct rx_call *a_call, afs_int32 a_index,
297 struct AFSDBLock *a_result)
299 struct ltable *tl; /*Ptr to lock table entry */
300 int nentries; /*Num entries in table */
301 int code; /*Return code */
306 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_GETLOCK);
308 AFS_STATCNT(SRXAFSCB_GetLock);
309 nentries = sizeof(ltable) / sizeof(struct ltable);
310 if (a_index < 0 || a_index >= nentries) {
317 * Found it - copy out its contents.
319 tl = <able[a_index];
320 strcpy(a_result->name, tl->name);
321 a_result->lock.waitStates =
322 ((struct afs_lock *)(tl->addr))->wait_states;
323 a_result->lock.exclLocked =
324 ((struct afs_lock *)(tl->addr))->excl_locked;
325 a_result->lock.readersReading =
326 ((struct afs_lock *)(tl->addr))->readers_reading;
327 a_result->lock.numWaiting =
328 ((struct afs_lock *)(tl->addr))->num_waiting;
329 #ifdef INSTRUMENT_LOCKS
330 a_result->lock.pid_last_reader =
331 ((struct afs_lock *)(tl->addr))->pid_last_reader;
332 a_result->lock.pid_writer =
333 ((struct afs_lock *)(tl->addr))->pid_writer;
334 a_result->lock.src_indicator =
335 ((struct afs_lock *)(tl->addr))->src_indicator;
337 a_result->lock.pid_last_reader = 0;
338 a_result->lock.pid_writer = 0;
339 a_result->lock.src_indicator = 0;
350 } /*SRXAFSCB_GetLock */
353 /*------------------------------------------------------------------------
354 * static ClearCallBack
357 * Clear out callback information for the specified file, or
358 * even a whole volume. Used to worry about callback was from
359 * within the particular cell or not. Now we don't bother with
360 * that anymore; it's not worth the time.
363 * a_conn : Ptr to Rx connection involved.
364 * a_fid : Ptr to AFS fid being cleared.
370 * Nothing interesting.
375 Appears to need to be called with GLOCK held, as the icl_Event4 stuff asserts otherwise
377 *------------------------------------------------------------------------*/
380 ClearCallBack(register struct rx_connection *a_conn,
381 register struct AFSFid *a_fid)
383 register struct vcache *tvc;
385 struct VenusFid localFid;
387 #ifdef AFS_DARWIN80_ENV
391 AFS_STATCNT(ClearCallBack);
396 * XXXX Don't hold any server locks here because of callback protocol XXX
399 localFid.Fid.Volume = a_fid->Volume;
400 localFid.Fid.Vnode = a_fid->Vnode;
401 localFid.Fid.Unique = a_fid->Unique;
404 * Volume ID of zero means don't do anything.
406 if (a_fid->Volume != 0) {
407 if (a_fid->Vnode == 0) {
408 struct afs_q *tq, *uq;
410 * Clear callback for the whole volume. Zip through the
411 * hash chain, nullifying entries whose volume ID matches.
414 ObtainReadLock(&afs_xvcache);
415 i = VCHashV(&localFid);
416 for (tq = afs_vhashTV[i].prev; tq != &afs_vhashTV[i]; tq = uq) {
419 if (tvc->fid.Fid.Volume == a_fid->Volume) {
420 tvc->callback = NULL;
422 localFid.Cell = tvc->fid.Cell;
423 tvc->dchint = NULL; /* invalidate hints */
424 if (tvc->states & CVInit) {
425 ReleaseReadLock(&afs_xvcache);
426 afs_osi_Sleep(&tvc->states);
429 #ifdef AFS_DARWIN80_ENV
430 if (tvc->states & CDeadVnode) {
431 ReleaseReadLock(&afs_xvcache);
432 afs_osi_Sleep(&tvc->states);
436 #if defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_HPUX_ENV) || defined(AFS_LINUX20_ENV)
437 VN_HOLD(AFSTOV(tvc));
439 #ifdef AFS_DARWIN80_ENV
450 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
453 VREFCOUNT_INC(tvc); /* AIX, apparently */
457 ReleaseReadLock(&afs_xvcache);
458 ObtainWriteLock(&afs_xcbhash, 449);
459 afs_DequeueCallback(tvc);
460 tvc->states &= ~(CStatd | CUnique | CBulkFetching);
462 if (tvc->fid.Fid.Vnode & 1)
466 ReleaseWriteLock(&afs_xcbhash);
467 if ((tvc->fid.Fid.Vnode & 1 || (vType(tvc) == VDIR)))
468 osi_dnlc_purgedp(tvc);
469 afs_Trace3(afs_iclSetp, CM_TRACE_CALLBACK,
470 ICL_TYPE_POINTER, tvc, ICL_TYPE_INT32,
471 tvc->states, ICL_TYPE_INT32,
473 #ifdef AFS_DARWIN80_ENV
474 vnode_put(AFSTOV(tvc));
476 ObtainReadLock(&afs_xvcache);
479 } else if ((tvc->states & CMValid)
480 && (tvc->mvid->Fid.Volume == a_fid->Volume)) {
481 tvc->states &= ~CMValid;
483 localFid.Cell = tvc->mvid->Cell;
486 ReleaseReadLock(&afs_xvcache);
489 * XXXX Don't hold any locks here XXXX
491 tv = afs_FindVolume(&localFid, 0);
493 afs_ResetVolumeInfo(tv);
494 afs_PutVolume(tv, 0);
495 /* invalidate mtpoint? */
497 } /*Clear callbacks for whole volume */
500 * Clear callbacks just for the one file.
504 if (a_fid->Vnode & 1)
505 afs_oddCBs++; /*Could do this on volume basis, too */
507 afs_evenCBs++; /*A particular fid was specified */
509 ObtainReadLock(&afs_xvcache);
510 i = VCHash(&localFid);
511 for (tvc = afs_vhashT[i]; tvc; tvc = uvc) {
513 if (tvc->fid.Fid.Vnode == a_fid->Vnode
514 && tvc->fid.Fid.Volume == a_fid->Volume
515 && tvc->fid.Fid.Unique == a_fid->Unique) {
516 tvc->callback = NULL;
517 tvc->dchint = NULL; /* invalidate hints */
518 if (tvc->states & CVInit) {
519 ReleaseReadLock(&afs_xvcache);
520 afs_osi_Sleep(&tvc->states);
523 #ifdef AFS_DARWIN80_ENV
524 if (tvc->states & CDeadVnode) {
525 ReleaseReadLock(&afs_xvcache);
526 afs_osi_Sleep(&tvc->states);
530 #if defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_HPUX_ENV) || defined(AFS_LINUX20_ENV)
531 VN_HOLD(AFSTOV(tvc));
533 #ifdef AFS_DARWIN80_ENV
544 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
547 VREFCOUNT_INC(tvc); /* AIX, apparently */
551 ReleaseReadLock(&afs_xvcache);
552 ObtainWriteLock(&afs_xcbhash, 450);
553 afs_DequeueCallback(tvc);
554 tvc->states &= ~(CStatd | CUnique | CBulkFetching);
555 ReleaseWriteLock(&afs_xcbhash);
556 if ((tvc->fid.Fid.Vnode & 1 || (vType(tvc) == VDIR)))
557 osi_dnlc_purgedp(tvc);
558 afs_Trace3(afs_iclSetp, CM_TRACE_CALLBACK,
559 ICL_TYPE_POINTER, tvc, ICL_TYPE_INT32,
560 tvc->states, ICL_TYPE_LONG, 0);
562 lastCallBack_vnode = afid->Vnode;
563 lastCallBack_dv = tvc->mstat.DataVersion.low;
564 osi_GetuTime(&lastCallBack_time);
566 #ifdef AFS_DARWIN80_ENV
567 vnode_put(AFSTOV(tvc));
569 ObtainReadLock(&afs_xvcache);
573 } /*Walk through hash table */
574 ReleaseReadLock(&afs_xvcache);
575 } /*Clear callbacks for one file */
578 /*Fid has non-zero volume ID */
580 * Always return a predictable value.
587 /*------------------------------------------------------------------------
588 * EXPORTED SRXAFSCB_CallBack
591 * Routine called by the server-side callback RPC interface to
592 * implement passing in callback information.
596 * a_call : Ptr to Rx call on which this request came in.
597 * a_fids : Ptr to array of fids involved.
598 * a_callbacks : Ptr to matching callback info for the fids.
604 * Nothing interesting.
608 *------------------------------------------------------------------------*/
611 SRXAFSCB_CallBack(struct rx_call *a_call, register struct AFSCBFids *a_fids,
612 struct AFSCBs *a_callbacks)
614 register int i; /*Loop variable */
615 struct AFSFid *tfid; /*Ptr to current fid */
616 register struct rx_connection *tconn; /*Call's connection */
622 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_CALLBACK);
624 AFS_STATCNT(SRXAFSCB_CallBack);
625 if (!(tconn = rx_ConnectionOf(a_call)))
627 tfid = (struct AFSFid *)a_fids->AFSCBFids_val;
630 * For now, we ignore callbacks, since the File Server only *breaks*
631 * callbacks at present.
633 for (i = 0; i < a_fids->AFSCBFids_len; i++)
634 ClearCallBack(tconn, &tfid[i]);
642 } /*SRXAFSCB_CallBack */
645 /*------------------------------------------------------------------------
646 * EXPORTED SRXAFSCB_Probe
649 * Routine called by the server-side callback RPC interface to
650 * implement ``probing'' the Cache Manager, just making sure it's
654 * a_call : Ptr to Rx call on which this request came in.
660 * Nothing interesting.
664 *------------------------------------------------------------------------*/
667 SRXAFSCB_Probe(struct rx_call *a_call)
673 AFS_STATCNT(SRXAFSCB_Probe);
675 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_PROBE);
682 } /*SRXAFSCB_Probe */
685 /*------------------------------------------------------------------------
686 * EXPORTED SRXAFSCB_InitCallBackState
689 * Routine called by the server-side callback RPC interface to
690 * implement clearing all callbacks from this host.
693 * a_call : Ptr to Rx call on which this request came in.
699 * Nothing interesting.
703 *------------------------------------------------------------------------*/
706 SRXAFSCB_InitCallBackState(struct rx_call *a_call)
709 register struct vcache *tvc;
710 register struct rx_connection *tconn;
711 register struct rx_peer *peer;
718 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_INITCALLBACKSTATE);
719 AFS_STATCNT(SRXAFSCB_InitCallBackState);
722 * Find the address of the host making this call
724 if ((tconn = rx_ConnectionOf(a_call)) && (peer = rx_PeerOf(tconn))) {
727 afs_oddCBs++; /*Including any missed via create race */
728 afs_evenCBs++; /*Including any missed via create race */
730 ts = afs_FindServer(rx_HostOf(peer), rx_PortOf(peer), (afsUUID *) 0,
733 for (i = 0; i < VCSIZE; i++)
734 for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
735 if (tvc->callback == ts) {
736 ObtainWriteLock(&afs_xcbhash, 451);
737 afs_DequeueCallback(tvc);
738 tvc->callback = NULL;
739 tvc->states &= ~(CStatd | CUnique | CBulkFetching);
740 ReleaseWriteLock(&afs_xcbhash);
747 /* find any volumes residing on this server and flush their state */
749 register struct volume *tv;
752 for (i = 0; i < NVOLS; i++)
753 for (tv = afs_volumes[i]; tv; tv = tv->next) {
754 for (j = 0; j < MAXHOSTS; j++)
755 if (tv->serverHost[j] == ts)
756 afs_ResetVolumeInfo(tv);
759 osi_dnlc_purge(); /* may be a little bit extreme */
768 } /*SRXAFSCB_InitCallBackState */
771 /*------------------------------------------------------------------------
772 * EXPORTED SRXAFSCB_XStatsVersion
775 * Routine called by the server-side callback RPC interface to
776 * implement pulling out the xstat version number for the Cache
780 * a_versionP : Ptr to the version number variable to set.
786 * Nothing interesting.
790 *------------------------------------------------------------------------*/
793 SRXAFSCB_XStatsVersion(struct rx_call *a_call, afs_int32 * a_versionP)
800 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_XSTATSVERSION);
802 *a_versionP = AFSCB_XSTAT_VERSION;
809 } /*SRXAFSCB_XStatsVersion */
812 /*------------------------------------------------------------------------
813 * EXPORTED SRXAFSCB_GetXStats
816 * Routine called by the server-side callback RPC interface to
817 * implement getting the given data collection from the extended
818 * Cache Manager statistics.
821 * a_call : Ptr to Rx call on which this request came in.
822 * a_clientVersionNum : Client version number.
823 * a_opCode : Desired operation.
824 * a_serverVersionNumP : Ptr to version number to set.
825 * a_timeP : Ptr to time value (seconds) to set.
826 * a_dataArray : Ptr to variable array structure to return
833 * Nothing interesting.
837 *------------------------------------------------------------------------*/
840 SRXAFSCB_GetXStats(struct rx_call *a_call, afs_int32 a_clientVersionNum,
841 afs_int32 a_collectionNumber, afs_int32 * a_srvVersionNumP,
842 afs_int32 * a_timeP, AFSCB_CollData * a_dataP)
844 register int code; /*Return value */
845 afs_int32 *dataBuffP; /*Ptr to data to be returned */
846 afs_int32 dataBytes; /*Bytes in data buffer */
851 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_GETXSTATS);
854 * Record the time of day and the server version number.
856 *a_srvVersionNumP = AFSCB_XSTAT_VERSION;
857 *a_timeP = osi_Time();
860 * Stuff the appropriate data in there (assume victory)
866 * We're not keeping stats, so just return successfully with
869 a_dataP->AFSCB_CollData_len = 0;
870 a_dataP->AFSCB_CollData_val = NULL;
872 switch (a_collectionNumber) {
873 case AFSCB_XSTATSCOLL_CALL_INFO:
875 * Pass back all the call-count-related data.
877 * >>> We are forced to allocate a separate area in which to
878 * >>> put this stuff in by the RPC stub generator, since it
879 * >>> will be freed at the tail end of the server stub code.
881 dataBytes = sizeof(struct afs_CMStats);
882 dataBuffP = (afs_int32 *) afs_osi_Alloc(dataBytes);
883 memcpy((char *)dataBuffP, (char *)&afs_cmstats, dataBytes);
884 a_dataP->AFSCB_CollData_len = dataBytes >> 2;
885 a_dataP->AFSCB_CollData_val = dataBuffP;
888 case AFSCB_XSTATSCOLL_PERF_INFO:
890 * Update and then pass back all the performance-related data.
891 * Note: the only performance fields that need to be computed
892 * at this time are the number of accesses for this collection
893 * and the current server record info.
895 * >>> We are forced to allocate a separate area in which to
896 * >>> put this stuff in by the RPC stub generator, since it
897 * >>> will be freed at the tail end of the server stub code.
899 afs_stats_cmperf.numPerfCalls++;
901 dataBytes = sizeof(afs_stats_cmperf);
902 dataBuffP = (afs_int32 *) afs_osi_Alloc(dataBytes);
903 memcpy((char *)dataBuffP, (char *)&afs_stats_cmperf, dataBytes);
904 a_dataP->AFSCB_CollData_len = dataBytes >> 2;
905 a_dataP->AFSCB_CollData_val = dataBuffP;
908 case AFSCB_XSTATSCOLL_FULL_PERF_INFO:
910 * Pass back the full range of performance and statistical
911 * data available. We have to bring the normal performance
912 * data collection up to date, then copy that data into
913 * the full collection.
915 * >>> We are forced to allocate a separate area in which to
916 * >>> put this stuff in by the RPC stub generator, since it
917 * >>> will be freed at the tail end of the server stub code.
919 afs_stats_cmperf.numPerfCalls++;
921 memcpy((char *)(&(afs_stats_cmfullperf.perf)),
922 (char *)(&afs_stats_cmperf), sizeof(struct afs_stats_CMPerf));
923 afs_stats_cmfullperf.numFullPerfCalls++;
925 dataBytes = sizeof(afs_stats_cmfullperf);
926 dataBuffP = (afs_int32 *) afs_osi_Alloc(dataBytes);
927 memcpy((char *)dataBuffP, (char *)(&afs_stats_cmfullperf), dataBytes);
928 a_dataP->AFSCB_CollData_len = dataBytes >> 2;
929 a_dataP->AFSCB_CollData_val = dataBuffP;
934 * Illegal collection number.
936 a_dataP->AFSCB_CollData_len = 0;
937 a_dataP->AFSCB_CollData_val = NULL;
939 } /*Switch on collection number */
940 #endif /* AFS_NOSTATS */
948 } /*SRXAFSCB_GetXStats */
951 /*------------------------------------------------------------------------
952 * EXPORTED afs_RXCallBackServer
955 * Body of the thread supporting callback services.
964 * Nothing interesting.
968 *------------------------------------------------------------------------*/
971 afs_RXCallBackServer(void)
973 AFS_STATCNT(afs_RXCallBackServer);
978 afs_osi_Sleep(&afs_server);
982 * Donate this process to Rx.
987 } /*afs_RXCallBackServer */
990 /*------------------------------------------------------------------------
991 * EXPORTED shutdown_CB
994 * Zero out important Cache Manager data structures.
1003 * Nothing interesting.
1007 *------------------------------------------------------------------------*/
1012 AFS_STATCNT(shutdown_CB);
1014 if (afs_cold_shutdown) {
1015 afs_oddCBs = afs_evenCBs = afs_allCBs = afs_allZaps = afs_oddZaps =
1016 afs_evenZaps = afs_connectBacks = 0;
1023 /*------------------------------------------------------------------------
1024 * EXPORTED SRXAFSCB_InitCallBackState2
1027 * This routine was used in the AFS 3.5 beta release, but not anymore.
1028 * It has since been replaced by SRXAFSCB_InitCallBackState3.
1031 * a_call : Ptr to Rx call on which this request came in.
1034 * RXGEN_OPCODE (always).
1037 * Nothing interesting.
1041 *------------------------------------------------------------------------*/
1044 SRXAFSCB_InitCallBackState2(struct rx_call *a_call,
1045 struct interfaceAddr *addr)
1047 return RXGEN_OPCODE;
1050 /*------------------------------------------------------------------------
1051 * EXPORTED SRXAFSCB_WhoAreYou
1054 * Routine called by the server-side callback RPC interface to
1055 * obtain a unique identifier for the client. The server uses
1056 * this identifier to figure out whether or not two RX connections
1057 * are from the same client, and to find out which addresses go
1058 * with which clients.
1061 * a_call : Ptr to Rx call on which this request came in.
1062 * addr: Ptr to return the list of interfaces for this client.
1068 * Nothing interesting.
1072 *------------------------------------------------------------------------*/
1075 SRXAFSCB_WhoAreYou(struct rx_call *a_call, struct interfaceAddr *addr)
1082 AFS_STATCNT(SRXAFSCB_WhoAreYou);
1084 memset(addr, 0, sizeof(*addr));
1086 ObtainReadLock(&afs_xinterface);
1088 /* return all network interface addresses */
1089 addr->numberOfInterfaces = afs_cb_interface.numberOfInterfaces;
1090 addr->uuid = afs_cb_interface.uuid;
1091 for (i = 0; i < afs_cb_interface.numberOfInterfaces; i++) {
1092 addr->addr_in[i] = ntohl(afs_cb_interface.addr_in[i]);
1093 addr->subnetmask[i] = ntohl(afs_cb_interface.subnetmask[i]);
1094 addr->mtu[i] = ntohl(afs_cb_interface.mtu[i]);
1097 ReleaseReadLock(&afs_xinterface);
1105 /*------------------------------------------------------------------------
1106 * EXPORTED SRXAFSCB_InitCallBackState3
1109 * Routine called by the server-side callback RPC interface to
1110 * implement clearing all callbacks from this host.
1113 * a_call : Ptr to Rx call on which this request came in.
1119 * Nothing interesting.
1123 *------------------------------------------------------------------------*/
1126 SRXAFSCB_InitCallBackState3(struct rx_call *a_call, afsUUID * a_uuid)
1131 * TBD: Lookup the server by the UUID instead of its IP address.
1133 code = SRXAFSCB_InitCallBackState(a_call);
1139 /*------------------------------------------------------------------------
1140 * EXPORTED SRXAFSCB_ProbeUuid
1143 * Routine called by the server-side callback RPC interface to
1144 * implement ``probing'' the Cache Manager, just making sure it's
1145 * still there is still the same client it used to be.
1148 * a_call : Ptr to Rx call on which this request came in.
1149 * a_uuid : Ptr to UUID that must match the client's UUID.
1152 * 0 if a_uuid matches the UUID for this client
1153 * Non-zero otherwize
1156 * Nothing interesting.
1160 *------------------------------------------------------------------------*/
1163 SRXAFSCB_ProbeUuid(struct rx_call *a_call, afsUUID * a_uuid)
1169 AFS_STATCNT(SRXAFSCB_Probe);
1171 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_PROBE);
1172 if (!afs_uuid_equal(a_uuid, &afs_cb_interface.uuid))
1173 code = 1; /* failure */
1182 /*------------------------------------------------------------------------
1183 * EXPORTED SRXAFSCB_GetServerPrefs
1186 * Routine to list server preferences used by this client.
1189 * a_call : Ptr to Rx call on which this request came in.
1190 * a_index : Input server index
1191 * a_srvr_addr : Output server address in host byte order
1192 * (0xffffffff on last server)
1193 * a_srvr_rank : Output server rank
1199 * Nothing interesting.
1203 *------------------------------------------------------------------------*/
1206 SRXAFSCB_GetServerPrefs(struct rx_call *a_call, afs_int32 a_index,
1207 afs_int32 * a_srvr_addr, afs_int32 * a_srvr_rank)
1213 AFS_STATCNT(SRXAFSCB_GetServerPrefs);
1215 ObtainReadLock(&afs_xserver);
1217 /* Search the hash table for the server with this index */
1218 *a_srvr_addr = 0xffffffff;
1219 *a_srvr_rank = 0xffffffff;
1220 for (i = 0, j = 0; j < NSERVERS && i <= a_index; j++) {
1221 for (sa = afs_srvAddrs[j]; sa && i <= a_index; sa = sa->next_bkt, i++) {
1223 *a_srvr_addr = ntohl(sa->sa_ip);
1224 *a_srvr_rank = sa->sa_iprank;
1229 ReleaseReadLock(&afs_xserver);
1237 /*------------------------------------------------------------------------
1238 * EXPORTED SRXAFSCB_GetCellServDB
1241 * Routine to list cells configured for this client
1244 * a_call : Ptr to Rx call on which this request came in.
1245 * a_index : Input cell index
1246 * a_name : Output cell name ("" on last cell)
1247 * a_hosts : Output cell database servers in host byte order.
1253 * Nothing interesting.
1257 *------------------------------------------------------------------------*/
1260 SRXAFSCB_GetCellServDB(struct rx_call *a_call, afs_int32 a_index,
1261 char **a_name, serverList * a_hosts)
1265 char *t_name, *p_name = NULL;
1268 AFS_STATCNT(SRXAFSCB_GetCellServDB);
1270 tcell = afs_GetCellByIndex(a_index, READ_LOCK);
1274 a_hosts->serverList_val = 0;
1275 a_hosts->serverList_len = 0;
1277 p_name = tcell->cellName;
1278 for (j = 0; j < AFSMAXCELLHOSTS && tcell->cellHosts[j]; j++);
1280 a_hosts->serverList_val =
1281 (afs_int32 *) afs_osi_Alloc(j * sizeof(afs_int32));
1282 a_hosts->serverList_len = j;
1283 for (j = 0; j < AFSMAXCELLHOSTS && tcell->cellHosts[j]; j++)
1284 a_hosts->serverList_val[j] =
1285 ntohl(tcell->cellHosts[j]->addr->sa_ip);
1286 afs_PutCell(tcell, READ_LOCK);
1289 t_name = (char *)afs_osi_Alloc(i + 1);
1290 if (t_name == NULL) {
1291 afs_osi_Free(a_hosts->serverList_val, (j * sizeof(afs_int32)));
1298 memcpy(t_name, p_name, i);
1307 /*------------------------------------------------------------------------
1308 * EXPORTED SRXAFSCB_GetLocalCell
1311 * Routine to return name of client's local cell
1314 * a_call : Ptr to Rx call on which this request came in.
1315 * a_name : Output cell name
1321 * Nothing interesting.
1325 *------------------------------------------------------------------------*/
1328 SRXAFSCB_GetLocalCell(struct rx_call *a_call, char **a_name)
1332 char *t_name, *p_name = NULL;
1335 AFS_STATCNT(SRXAFSCB_GetLocalCell);
1337 /* Search the list for the primary cell. Cell number 1 is only
1338 * the primary cell is when no other cell is explicitly marked as
1339 * the primary cell. */
1340 tcell = afs_GetPrimaryCell(READ_LOCK);
1342 p_name = tcell->cellName;
1344 plen = strlen(p_name);
1347 t_name = (char *)afs_osi_Alloc(plen + 1);
1348 if (t_name == NULL) {
1350 afs_PutCell(tcell, READ_LOCK);
1355 t_name[plen] = '\0';
1357 memcpy(t_name, p_name, plen);
1363 afs_PutCell(tcell, READ_LOCK);
1369 * afs_MarshallCacheConfig - marshall client cache configuration
1373 * IN callerVersion - the rpc stat version of the caller.
1375 * IN config - client cache configuration.
1377 * OUT ptr - buffer where configuration is marshalled.
1384 afs_MarshallCacheConfig(afs_uint32 callerVersion, cm_initparams_v1 * config,
1387 AFS_STATCNT(afs_MarshallCacheConfig);
1389 * We currently only support version 1.
1391 *(ptr++) = config->nChunkFiles;
1392 *(ptr++) = config->nStatCaches;
1393 *(ptr++) = config->nDataCaches;
1394 *(ptr++) = config->nVolumeCaches;
1395 *(ptr++) = config->firstChunkSize;
1396 *(ptr++) = config->otherChunkSize;
1397 *(ptr++) = config->cacheSize;
1398 *(ptr++) = config->setTime;
1399 *(ptr++) = config->memCache;
1403 /*------------------------------------------------------------------------
1404 * EXPORTED SRXAFSCB_GetCacheConfig
1407 * Routine to return parameters used to initialize client cache.
1408 * Client may request any format version. Server may not return
1409 * format version greater than version requested by client.
1412 * a_call: Ptr to Rx call on which this request came in.
1413 * callerVersion: Data format version desired by the client.
1414 * serverVersion: Data format version of output data.
1415 * configCount: Number bytes allocated for output data.
1416 * config: Client cache configuration.
1422 * Nothing interesting.
1426 *------------------------------------------------------------------------*/
1429 SRXAFSCB_GetCacheConfig(struct rx_call *a_call, afs_uint32 callerVersion,
1430 afs_uint32 * serverVersion, afs_uint32 * configCount,
1431 cacheConfig * config)
1433 afs_uint32 *t_config;
1435 cm_initparams_v1 cm_config;
1438 AFS_STATCNT(SRXAFSCB_GetCacheConfig);
1441 * Currently only support version 1
1443 allocsize = sizeof(cm_initparams_v1);
1444 t_config = (afs_uint32 *) afs_osi_Alloc(allocsize);
1445 if (t_config == NULL) {
1450 cm_config.nChunkFiles = cm_initParams.cmi_nChunkFiles;
1451 cm_config.nStatCaches = cm_initParams.cmi_nStatCaches;
1452 cm_config.nDataCaches = cm_initParams.cmi_nDataCaches;
1453 cm_config.nVolumeCaches = cm_initParams.cmi_nVolumeCaches;
1454 cm_config.firstChunkSize = cm_initParams.cmi_firstChunkSize;
1455 cm_config.otherChunkSize = cm_initParams.cmi_otherChunkSize;
1456 cm_config.cacheSize = cm_initParams.cmi_cacheSize;
1457 cm_config.setTime = cm_initParams.cmi_setTime;
1458 cm_config.memCache = cm_initParams.cmi_memCache;
1460 afs_MarshallCacheConfig(callerVersion, &cm_config, t_config);
1462 *serverVersion = AFS_CLIENT_RETRIEVAL_FIRST_EDITION;
1463 *configCount = allocsize;
1464 config->cacheConfig_val = t_config;
1465 config->cacheConfig_len = allocsize / sizeof(afs_uint32);
1472 /*------------------------------------------------------------------------
1473 * EXPORTED SRXAFSCB_FetchData
1476 * Routine to do third party move from a remioserver to the original
1477 * issuer of an ArchiveData request. Presently supported only by the
1478 * "fs" command, not by the AFS client.
1481 * rxcall: Ptr to Rx call on which this request came in.
1482 * Fid: pointer to AFSFid structure.
1483 * Fd: File descriptor inside fs command.
1484 * Position: Offset in the file.
1485 * Length: Data length to transfer.
1486 * TotalLength: Pointer to total file length field
1492 * Nothing interesting.
1495 *------------------------------------------------------------------------*/
1497 SRXAFSCB_FetchData(struct rx_call *rxcall, struct AFSFid *Fid, afs_int32 Fd,
1498 afs_int64 Position, afs_int64 Length,
1499 afs_int64 * TotalLength)
1504 /*------------------------------------------------------------------------
1505 * EXPORTED SRXAFSCB_StoreData
1508 * Routine to do third party move from a remioserver to the original
1509 * issuer of a RetrieveData request. Presently supported only by the
1510 * "fs" command, not by the AFS client.
1513 * rxcall: Ptr to Rx call on which this request came in.
1514 * Fid: pointer to AFSFid structure.
1515 * Fd: File descriptor inside fs command.
1516 * Position: Offset in the file.
1517 * Length: Data length to transfer.
1518 * TotalLength: Pointer to total file length field
1524 * Nothing interesting.
1528 *------------------------------------------------------------------------*/
1530 SRXAFSCB_StoreData(struct rx_call *rxcall, struct AFSFid *Fid, afs_int32 Fd,
1531 afs_int64 Position, afs_int64 Length,
1532 afs_int64 * TotalLength)
1537 /*------------------------------------------------------------------------
1538 * EXPORTED SRXAFSCB_GetCellByNum
1541 * Routine to get information about a cell specified by its
1542 * cell number (returned by GetCE/GetCE64).
1545 * a_call : Ptr to Rx call on which this request came in.
1546 * a_cellnum : Input cell number
1547 * a_name : Output cell name (one zero byte when no such cell).
1548 * a_hosts : Output cell database servers in host byte order.
1554 * Nothing interesting.
1558 *------------------------------------------------------------------------*/
1561 SRXAFSCB_GetCellByNum(struct rx_call *a_call, afs_int32 a_cellnum,
1562 char **a_name, serverList * a_hosts)
1568 AFS_STATCNT(SRXAFSCB_GetCellByNum);
1570 a_hosts->serverList_val = 0;
1571 a_hosts->serverList_len = 0;
1573 tcell = afs_GetCellStale(a_cellnum, READ_LOCK);
1575 *a_name = afs_strdup("");
1580 ObtainReadLock(&tcell->lock);
1581 *a_name = afs_strdup(tcell->cellName);
1583 for (sn = 0; sn < AFSMAXCELLHOSTS && tcell->cellHosts[sn]; sn++);
1584 a_hosts->serverList_len = sn;
1585 a_hosts->serverList_val =
1586 (afs_int32 *) afs_osi_Alloc(sn * sizeof(afs_int32));
1588 for (i = 0; i < sn; i++)
1589 a_hosts->serverList_val[i] = ntohl(tcell->cellHosts[i]->addr->sa_ip);
1590 ReleaseReadLock(&tcell->lock);
1591 afs_PutCell(tcell, READ_LOCK);
1598 SRXAFSCB_TellMeAboutYourself(struct rx_call *a_call,
1599 struct interfaceAddr *addr,
1600 Capabilities * capabilities)
1604 afs_int32 *dataBuffP;
1605 afs_int32 dataBytes;
1609 AFS_STATCNT(SRXAFSCB_WhoAreYou);
1611 ObtainReadLock(&afs_xinterface);
1613 /* return all network interface addresses */
1614 addr->numberOfInterfaces = afs_cb_interface.numberOfInterfaces;
1615 addr->uuid = afs_cb_interface.uuid;
1616 for (i = 0; i < afs_cb_interface.numberOfInterfaces; i++) {
1617 addr->addr_in[i] = ntohl(afs_cb_interface.addr_in[i]);
1618 addr->subnetmask[i] = ntohl(afs_cb_interface.subnetmask[i]);
1619 addr->mtu[i] = ntohl(afs_cb_interface.mtu[i]);
1622 ReleaseReadLock(&afs_xinterface);
1626 dataBytes = 1 * sizeof(afs_int32);
1627 dataBuffP = (afs_int32 *) afs_osi_Alloc(dataBytes);
1628 dataBuffP[0] = CLIENT_CAPABILITY_ERRORTRANS;
1629 capabilities->Capabilities_len = dataBytes / sizeof(afs_int32);
1630 capabilities->Capabilities_val = dataBuffP;
1636 #ifdef AFS_LINUX24_ENV
1637 extern struct vcache *afs_globalVp;
1639 int recurse_dcache_parent(parent, a_index, addr, inode, flags, time, fileName)
1640 struct dentry * parent;
1648 struct dentry *this_parent = parent;
1649 struct list_head *next;
1651 struct dentry *dentry;
1654 next = this_parent->d_subdirs.next;
1656 while (next != &this_parent->d_subdirs) {
1657 struct list_head *tmp = next;
1658 dentry = list_entry(tmp, struct dentry, d_child);
1664 * Descend a level if the d_subdirs list is non-empty.
1666 if (!list_empty(&dentry->d_subdirs)) {
1667 this_parent = dentry;
1672 * All done at this level ... ascend and resume the search.
1674 if (this_parent != parent) {
1675 next = this_parent->d_child.next;
1676 this_parent = this_parent->d_parent;
1682 if (d_unhashed(dentry))
1687 *fileName = afs_strdup(dentry->d_name.name?dentry->d_name.name:"");
1688 *inode = ITOAFS(dentry->d_inode);
1689 *addr = atomic_read(&(dentry)->d_count);
1690 *time = dentry->d_time;
1698 int SRXAFSCB_GetDE(a_call, a_index, addr, inode, flags, time, fileName)
1699 struct rx_call *a_call;
1706 { /*SRXAFSCB_GetDE*/
1707 int code = 0; /*Return code*/
1708 #ifdef AFS_LINUX24_ENV
1709 register int i; /*Loop variable*/
1710 register struct vcache *tvc = afs_globalVp;
1711 struct dentry *dentry;
1712 struct list_head *cur, *head = &(AFSTOI(tvc))->i_dentry;
1714 #ifdef RX_ENABLE_LOCKS
1716 #endif /* RX_ENABLE_LOCKS */
1718 #if defined(AFS_LINUX24_ENV)
1719 spin_lock(&dcache_lock);
1723 while ((cur = cur->next) != head) {
1724 dentry = list_entry(cur, struct dentry, d_alias);
1726 dget_locked(dentry);
1728 #if defined(AFS_LINUX24_ENV)
1729 spin_unlock(&dcache_lock);
1735 if (recurse_dcache_parent(dentry, a_index, addr, inode, flags, time, fileName) == 0) {
1746 *fileName = afs_strdup("");
1750 if (d_unhashed(dentry))
1755 *fileName = afs_strdup(dentry->d_name.name?dentry->d_name.name:"");
1756 *inode = ITOAFS(dentry->d_inode);
1757 *addr = atomic_read(&(dentry)->d_count);
1758 *time = dentry->d_time;
1765 #ifdef RX_ENABLE_LOCKS
1767 #endif /* RX_ENABLE_LOCKS */
1771 } /*SRXAFSCB_GetDE*/