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 { "afs_discon_lock", (char *)&afs_discon_lock},
71 { "afs_disconDirtyLock", (char *)&afs_disconDirtyLock},
72 { "afs_discon_vc_dirty", (char *)&afs_xvcdirty},
75 unsigned long lastCallBack_vnode;
76 unsigned int lastCallBack_dv;
77 osi_timeval_t lastCallBack_time;
79 /* these are for storing alternate interface addresses */
80 struct interfaceAddr afs_cb_interface;
82 /*------------------------------------------------------------------------
83 * EXPORTED SRXAFSCB_GetCE
86 * Routine called by the server-side callback RPC interface to
87 * implement pulling out the contents of the i'th cache entry.
90 * a_call : Ptr to Rx call on which this request came in.
91 * a_index : Index of desired cache entry.
92 * a_result : Ptr to a buffer for the given cache entry.
95 * 0 if everything went fine,
96 * 1 if we were given a bad index.
99 * Nothing interesting.
103 *------------------------------------------------------------------------*/
106 SRXAFSCB_GetCE(struct rx_call *a_call, afs_int32 a_index,
107 struct AFSDBCacheEntry *a_result)
110 register int i; /*Loop variable */
111 register struct vcache *tvc; /*Ptr to current cache entry */
112 int code; /*Return code */
117 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_GETCE);
119 AFS_STATCNT(SRXAFSCB_GetCE);
120 for (i = 0; i < VCSIZE; i++) {
121 for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
125 } /*Zip through current hash chain */
126 } /*Zip through hash chains */
136 * Copy out the located entry.
138 a_result->addr = afs_data_pointer_to_int32(tvc);
139 a_result->cell = tvc->f.fid.Cell;
140 a_result->netFid.Volume = tvc->f.fid.Fid.Volume;
141 a_result->netFid.Vnode = tvc->f.fid.Fid.Vnode;
142 a_result->netFid.Unique = tvc->f.fid.Fid.Unique;
143 a_result->lock.waitStates = tvc->lock.wait_states;
144 a_result->lock.exclLocked = tvc->lock.excl_locked;
145 a_result->lock.readersReading = tvc->lock.readers_reading;
146 a_result->lock.numWaiting = tvc->lock.num_waiting;
147 #if defined(INSTRUMENT_LOCKS)
148 a_result->lock.pid_last_reader = MyPidxx2Pid(tvc->lock.pid_last_reader);
149 a_result->lock.pid_writer = MyPidxx2Pid(tvc->lock.pid_writer);
150 a_result->lock.src_indicator = tvc->lock.src_indicator;
152 /* On osf20 , the vcache does not maintain these three fields */
153 a_result->lock.pid_last_reader = 0;
154 a_result->lock.pid_writer = 0;
155 a_result->lock.src_indicator = 0;
156 #endif /* AFS_OSF20_ENV */
157 #ifdef AFS_64BIT_CLIENT
158 a_result->Length = (afs_int32) tvc->f.m.Length & 0xffffffff;
159 #else /* AFS_64BIT_CLIENT */
160 a_result->Length = tvc->f.m.Length;
161 #endif /* AFS_64BIT_CLIENT */
162 a_result->DataVersion = hgetlo(tvc->f.m.DataVersion);
163 a_result->callback = afs_data_pointer_to_int32(tvc->callback); /* XXXX Now a pointer; change it XXXX */
164 a_result->cbExpires = tvc->cbExpires;
165 if (tvc->f.states & CVInit) {
166 a_result->refCount = 1;
168 #ifdef AFS_DARWIN80_ENV
169 a_result->refCount = vnode_isinuse(AFSTOV(tvc),0)?1:0; /* XXX fix */
171 a_result->refCount = VREFCOUNT(tvc);
174 a_result->opens = tvc->opens;
175 a_result->writers = tvc->execsOrWriters;
176 a_result->mvstat = tvc->mvstat;
177 a_result->states = tvc->f.states;
181 * Return our results.
190 } /*SRXAFSCB_GetCE */
193 SRXAFSCB_GetCE64(struct rx_call *a_call, afs_int32 a_index,
194 struct AFSDBCacheEntry64 *a_result)
196 register int i; /*Loop variable */
197 register struct vcache *tvc; /*Ptr to current cache entry */
198 int code; /*Return code */
203 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_GETCE);
205 AFS_STATCNT(SRXAFSCB_GetCE64);
206 for (i = 0; i < VCSIZE; i++) {
207 for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
211 } /*Zip through current hash chain */
212 } /*Zip through hash chains */
222 * Copy out the located entry.
224 a_result->addr = afs_data_pointer_to_int32(tvc);
225 a_result->cell = tvc->f.fid.Cell;
226 a_result->netFid.Volume = tvc->f.fid.Fid.Volume;
227 a_result->netFid.Vnode = tvc->f.fid.Fid.Vnode;
228 a_result->netFid.Unique = tvc->f.fid.Fid.Unique;
229 a_result->lock.waitStates = tvc->lock.wait_states;
230 a_result->lock.exclLocked = tvc->lock.excl_locked;
231 a_result->lock.readersReading = tvc->lock.readers_reading;
232 a_result->lock.numWaiting = tvc->lock.num_waiting;
233 #if defined(INSTRUMENT_LOCKS)
234 a_result->lock.pid_last_reader = MyPidxx2Pid(tvc->lock.pid_last_reader);
235 a_result->lock.pid_writer = MyPidxx2Pid(tvc->lock.pid_writer);
236 a_result->lock.src_indicator = tvc->lock.src_indicator;
238 /* On osf20 , the vcache does not maintain these three fields */
239 a_result->lock.pid_last_reader = 0;
240 a_result->lock.pid_writer = 0;
241 a_result->lock.src_indicator = 0;
242 #endif /* AFS_OSF20_ENV */
243 #if !defined(AFS_64BIT_ENV)
244 a_result->Length.high = 0;
245 a_result->Length.low = tvc->f.m.Length;
247 a_result->Length = tvc->f.m.Length;
249 a_result->DataVersion = hgetlo(tvc->f.m.DataVersion);
250 a_result->callback = afs_data_pointer_to_int32(tvc->callback); /* XXXX Now a pointer; change it XXXX */
251 a_result->cbExpires = tvc->cbExpires;
252 if (tvc->f.states & CVInit) {
253 a_result->refCount = 1;
255 #ifdef AFS_DARWIN80_ENV
256 a_result->refCount = vnode_isinuse(AFSTOV(tvc),0)?1:0; /* XXX fix */
258 a_result->refCount = VREFCOUNT(tvc);
261 a_result->opens = tvc->opens;
262 a_result->writers = tvc->execsOrWriters;
263 a_result->mvstat = tvc->mvstat;
264 a_result->states = tvc->f.states;
268 * Return our results.
277 } /*SRXAFSCB_GetCE64 */
280 /*------------------------------------------------------------------------
281 * EXPORTED SRXAFSCB_GetLock
284 * Routine called by the server-side callback RPC interface to
285 * implement pulling out the contents of a lock in the lock
289 * a_call : Ptr to Rx call on which this request came in.
290 * a_index : Index of desired lock.
291 * a_result : Ptr to a buffer for the given lock.
294 * 0 if everything went fine,
295 * 1 if we were given a bad index.
298 * Nothing interesting.
302 *------------------------------------------------------------------------*/
305 SRXAFSCB_GetLock(struct rx_call *a_call, afs_int32 a_index,
306 struct AFSDBLock *a_result)
308 struct ltable *tl; /*Ptr to lock table entry */
309 int nentries; /*Num entries in table */
310 int code; /*Return code */
315 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_GETLOCK);
317 AFS_STATCNT(SRXAFSCB_GetLock);
318 nentries = sizeof(ltable) / sizeof(struct ltable);
319 if (a_index < 0 || a_index >= nentries+afs_cellindex) {
324 } else if (a_index >= nentries) {
325 struct cell *tc = afs_GetCellByIndex(a_index-nentries, 0);
326 strcpy(a_result->name, tc->cellName);
327 a_result->lock.waitStates =
328 ((struct afs_lock *)&(tc->lock))->wait_states;
329 a_result->lock.exclLocked =
330 ((struct afs_lock *)&(tc->lock))->excl_locked;
331 a_result->lock.readersReading =
332 ((struct afs_lock *)&(tc->lock))->readers_reading;
333 a_result->lock.numWaiting =
334 ((struct afs_lock *)&(tc->lock))->num_waiting;
335 #ifdef INSTRUMENT_LOCKS
336 a_result->lock.pid_last_reader =
337 MyPidxx2Pid(((struct afs_lock *)&(tc->lock))->pid_last_reader);
338 a_result->lock.pid_writer =
339 MyPidxx2Pid(((struct afs_lock *)&(tc->lock))->pid_writer);
340 a_result->lock.src_indicator =
341 ((struct afs_lock *)&(tc->lock))->src_indicator;
343 a_result->lock.pid_last_reader = 0;
344 a_result->lock.pid_writer = 0;
345 a_result->lock.src_indicator = 0;
350 * Found it - copy out its contents.
352 tl = <able[a_index];
353 strcpy(a_result->name, tl->name);
354 a_result->lock.waitStates =
355 ((struct afs_lock *)(tl->addr))->wait_states;
356 a_result->lock.exclLocked =
357 ((struct afs_lock *)(tl->addr))->excl_locked;
358 a_result->lock.readersReading =
359 ((struct afs_lock *)(tl->addr))->readers_reading;
360 a_result->lock.numWaiting =
361 ((struct afs_lock *)(tl->addr))->num_waiting;
362 #ifdef INSTRUMENT_LOCKS
363 a_result->lock.pid_last_reader =
364 MyPidxx2Pid(((struct afs_lock *)(tl->addr))->pid_last_reader);
365 a_result->lock.pid_writer =
366 MyPidxx2Pid(((struct afs_lock *)(tl->addr))->pid_writer);
367 a_result->lock.src_indicator =
368 ((struct afs_lock *)(tl->addr))->src_indicator;
370 a_result->lock.pid_last_reader = 0;
371 a_result->lock.pid_writer = 0;
372 a_result->lock.src_indicator = 0;
383 } /*SRXAFSCB_GetLock */
386 /*------------------------------------------------------------------------
387 * static ClearCallBack
390 * Clear out callback information for the specified file, or
391 * even a whole volume. Used to worry about callback was from
392 * within the particular cell or not. Now we don't bother with
393 * that anymore; it's not worth the time.
396 * a_conn : Ptr to Rx connection involved.
397 * a_fid : Ptr to AFS fid being cleared.
403 * Nothing interesting.
408 Appears to need to be called with GLOCK held, as the icl_Event4 stuff asserts otherwise
410 *------------------------------------------------------------------------*/
413 ClearCallBack(register struct rx_connection *a_conn,
414 register struct AFSFid *a_fid)
416 register struct vcache *tvc;
418 struct VenusFid localFid;
420 #ifdef AFS_DARWIN80_ENV
424 AFS_STATCNT(ClearCallBack);
429 * XXXX Don't hold any server locks here because of callback protocol XXX
432 localFid.Fid.Volume = a_fid->Volume;
433 localFid.Fid.Vnode = a_fid->Vnode;
434 localFid.Fid.Unique = a_fid->Unique;
437 * Volume ID of zero means don't do anything.
439 if (a_fid->Volume != 0) {
440 if (a_fid->Vnode == 0) {
441 struct afs_q *tq, *uq;
443 * Clear callback for the whole volume. Zip through the
444 * hash chain, nullifying entries whose volume ID matches.
447 ObtainReadLock(&afs_xvcache);
448 i = VCHashV(&localFid);
449 for (tq = afs_vhashTV[i].prev; tq != &afs_vhashTV[i]; tq = uq) {
452 if (tvc->f.fid.Fid.Volume == a_fid->Volume) {
453 tvc->callback = NULL;
455 localFid.Cell = tvc->f.fid.Cell;
456 tvc->dchint = NULL; /* invalidate hints */
457 if (tvc->f.states & CVInit) {
458 ReleaseReadLock(&afs_xvcache);
459 afs_osi_Sleep(&tvc->f.states);
462 #ifdef AFS_DARWIN80_ENV
463 if (tvc->f.states & CDeadVnode) {
464 ReleaseReadLock(&afs_xvcache);
465 afs_osi_Sleep(&tvc->f.states);
469 #if defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_HPUX_ENV) || defined(AFS_LINUX20_ENV)
470 VN_HOLD(AFSTOV(tvc));
472 #ifdef AFS_DARWIN80_ENV
483 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
486 VREFCOUNT_INC(tvc); /* AIX, apparently */
490 ReleaseReadLock(&afs_xvcache);
491 ObtainWriteLock(&afs_xcbhash, 449);
492 afs_DequeueCallback(tvc);
493 tvc->f.states &= ~(CStatd | CUnique | CBulkFetching);
495 if (tvc->f.fid.Fid.Vnode & 1)
499 ReleaseWriteLock(&afs_xcbhash);
500 if ((tvc->f.fid.Fid.Vnode & 1 || (vType(tvc) == VDIR)))
501 osi_dnlc_purgedp(tvc);
502 afs_Trace3(afs_iclSetp, CM_TRACE_CALLBACK,
503 ICL_TYPE_POINTER, tvc, ICL_TYPE_INT32,
504 tvc->f.states, ICL_TYPE_INT32,
506 #ifdef AFS_DARWIN80_ENV
507 vnode_put(AFSTOV(tvc));
509 ObtainReadLock(&afs_xvcache);
512 } else if ((tvc->f.states & CMValid)
513 && (tvc->mvid->Fid.Volume == a_fid->Volume)) {
514 tvc->f.states &= ~CMValid;
516 localFid.Cell = tvc->mvid->Cell;
519 ReleaseReadLock(&afs_xvcache);
522 * XXXX Don't hold any locks here XXXX
524 tv = afs_FindVolume(&localFid, 0);
526 afs_ResetVolumeInfo(tv);
527 afs_PutVolume(tv, 0);
528 /* invalidate mtpoint? */
530 } /*Clear callbacks for whole volume */
533 * Clear callbacks just for the one file.
537 if (a_fid->Vnode & 1)
538 afs_oddCBs++; /*Could do this on volume basis, too */
540 afs_evenCBs++; /*A particular fid was specified */
542 ObtainReadLock(&afs_xvcache);
543 i = VCHash(&localFid);
544 for (tvc = afs_vhashT[i]; tvc; tvc = uvc) {
546 if (tvc->f.fid.Fid.Vnode == a_fid->Vnode
547 && tvc->f.fid.Fid.Volume == a_fid->Volume
548 && tvc->f.fid.Fid.Unique == a_fid->Unique) {
549 tvc->callback = NULL;
550 tvc->dchint = NULL; /* invalidate hints */
551 if (tvc->f.states & CVInit) {
552 ReleaseReadLock(&afs_xvcache);
553 afs_osi_Sleep(&tvc->f.states);
556 #ifdef AFS_DARWIN80_ENV
557 if (tvc->f.states & CDeadVnode) {
558 ReleaseReadLock(&afs_xvcache);
559 afs_osi_Sleep(&tvc->f.states);
563 #if defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_HPUX_ENV) || defined(AFS_LINUX20_ENV)
564 VN_HOLD(AFSTOV(tvc));
566 #ifdef AFS_DARWIN80_ENV
577 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
580 VREFCOUNT_INC(tvc); /* AIX, apparently */
584 ReleaseReadLock(&afs_xvcache);
585 ObtainWriteLock(&afs_xcbhash, 450);
586 afs_DequeueCallback(tvc);
587 tvc->f.states &= ~(CStatd | CUnique | CBulkFetching);
588 ReleaseWriteLock(&afs_xcbhash);
589 if ((tvc->f.fid.Fid.Vnode & 1 || (vType(tvc) == VDIR)))
590 osi_dnlc_purgedp(tvc);
591 afs_Trace3(afs_iclSetp, CM_TRACE_CALLBACK,
592 ICL_TYPE_POINTER, tvc, ICL_TYPE_INT32,
593 tvc->f.states, ICL_TYPE_LONG, 0);
595 lastCallBack_vnode = afid->Vnode;
596 lastCallBack_dv = tvc->mstat.DataVersion.low;
597 osi_GetuTime(&lastCallBack_time);
599 #ifdef AFS_DARWIN80_ENV
600 vnode_put(AFSTOV(tvc));
602 ObtainReadLock(&afs_xvcache);
606 } /*Walk through hash table */
607 ReleaseReadLock(&afs_xvcache);
608 } /*Clear callbacks for one file */
611 /*Fid has non-zero volume ID */
613 * Always return a predictable value.
620 /*------------------------------------------------------------------------
621 * EXPORTED SRXAFSCB_CallBack
624 * Routine called by the server-side callback RPC interface to
625 * implement passing in callback information.
629 * a_call : Ptr to Rx call on which this request came in.
630 * a_fids : Ptr to array of fids involved.
631 * a_callbacks : Ptr to matching callback info for the fids.
637 * Nothing interesting.
641 *------------------------------------------------------------------------*/
644 SRXAFSCB_CallBack(struct rx_call *a_call, register struct AFSCBFids *a_fids,
645 struct AFSCBs *a_callbacks)
647 register int i; /*Loop variable */
648 struct AFSFid *tfid; /*Ptr to current fid */
649 register struct rx_connection *tconn; /*Call's connection */
655 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_CALLBACK);
657 AFS_STATCNT(SRXAFSCB_CallBack);
658 if (!(tconn = rx_ConnectionOf(a_call)))
660 tfid = (struct AFSFid *)a_fids->AFSCBFids_val;
663 * For now, we ignore callbacks, since the File Server only *breaks*
664 * callbacks at present.
666 for (i = 0; i < a_fids->AFSCBFids_len; i++)
667 ClearCallBack(tconn, &tfid[i]);
675 } /*SRXAFSCB_CallBack */
678 /*------------------------------------------------------------------------
679 * EXPORTED SRXAFSCB_Probe
682 * Routine called by the server-side callback RPC interface to
683 * implement ``probing'' the Cache Manager, just making sure it's
687 * a_call : Ptr to Rx call on which this request came in.
693 * Nothing interesting.
697 *------------------------------------------------------------------------*/
700 SRXAFSCB_Probe(struct rx_call *a_call)
706 AFS_STATCNT(SRXAFSCB_Probe);
708 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_PROBE);
715 } /*SRXAFSCB_Probe */
718 /*------------------------------------------------------------------------
719 * EXPORTED SRXAFSCB_InitCallBackState
722 * Routine called by the server-side callback RPC interface to
723 * implement clearing all callbacks from this host.
726 * a_call : Ptr to Rx call on which this request came in.
732 * Nothing interesting.
736 *------------------------------------------------------------------------*/
739 SRXAFSCB_InitCallBackState(struct rx_call *a_call)
742 register struct vcache *tvc;
743 register struct rx_connection *tconn;
744 register struct rx_peer *peer;
751 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_INITCALLBACKSTATE);
752 AFS_STATCNT(SRXAFSCB_InitCallBackState);
755 * Find the address of the host making this call
757 if ((tconn = rx_ConnectionOf(a_call)) && (peer = rx_PeerOf(tconn))) {
760 afs_oddCBs++; /*Including any missed via create race */
761 afs_evenCBs++; /*Including any missed via create race */
763 ts = afs_FindServer(rx_HostOf(peer), rx_PortOf(peer), (afsUUID *) 0,
766 for (i = 0; i < VCSIZE; i++)
767 for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
768 if (tvc->callback == ts) {
769 ObtainWriteLock(&afs_xcbhash, 451);
770 afs_DequeueCallback(tvc);
771 tvc->callback = NULL;
772 tvc->f.states &= ~(CStatd | CUnique | CBulkFetching);
773 ReleaseWriteLock(&afs_xcbhash);
780 /* find any volumes residing on this server and flush their state */
782 register struct volume *tv;
785 for (i = 0; i < NVOLS; i++)
786 for (tv = afs_volumes[i]; tv; tv = tv->next) {
787 for (j = 0; j < MAXHOSTS; j++)
788 if (tv->serverHost[j] == ts)
789 afs_ResetVolumeInfo(tv);
792 osi_dnlc_purge(); /* may be a little bit extreme */
801 } /*SRXAFSCB_InitCallBackState */
804 /*------------------------------------------------------------------------
805 * EXPORTED SRXAFSCB_XStatsVersion
808 * Routine called by the server-side callback RPC interface to
809 * implement pulling out the xstat version number for the Cache
813 * a_versionP : Ptr to the version number variable to set.
819 * Nothing interesting.
823 *------------------------------------------------------------------------*/
826 SRXAFSCB_XStatsVersion(struct rx_call *a_call, afs_int32 * a_versionP)
833 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_XSTATSVERSION);
835 *a_versionP = AFSCB_XSTAT_VERSION;
842 } /*SRXAFSCB_XStatsVersion */
845 /*------------------------------------------------------------------------
846 * EXPORTED SRXAFSCB_GetXStats
849 * Routine called by the server-side callback RPC interface to
850 * implement getting the given data collection from the extended
851 * Cache Manager statistics.
854 * a_call : Ptr to Rx call on which this request came in.
855 * a_clientVersionNum : Client version number.
856 * a_opCode : Desired operation.
857 * a_serverVersionNumP : Ptr to version number to set.
858 * a_timeP : Ptr to time value (seconds) to set.
859 * a_dataArray : Ptr to variable array structure to return
866 * Nothing interesting.
870 *------------------------------------------------------------------------*/
873 SRXAFSCB_GetXStats(struct rx_call *a_call, afs_int32 a_clientVersionNum,
874 afs_int32 a_collectionNumber, afs_int32 * a_srvVersionNumP,
875 afs_int32 * a_timeP, AFSCB_CollData * a_dataP)
877 register int code; /*Return value */
878 afs_int32 *dataBuffP; /*Ptr to data to be returned */
879 afs_int32 dataBytes; /*Bytes in data buffer */
884 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_GETXSTATS);
887 * Record the time of day and the server version number.
889 *a_srvVersionNumP = AFSCB_XSTAT_VERSION;
890 *a_timeP = osi_Time();
893 * Stuff the appropriate data in there (assume victory)
899 * We're not keeping stats, so just return successfully with
902 a_dataP->AFSCB_CollData_len = 0;
903 a_dataP->AFSCB_CollData_val = NULL;
905 switch (a_collectionNumber) {
906 case AFSCB_XSTATSCOLL_CALL_INFO:
908 * Pass back all the call-count-related data.
910 * >>> We are forced to allocate a separate area in which to
911 * >>> put this stuff in by the RPC stub generator, since it
912 * >>> will be freed at the tail end of the server stub code.
914 dataBytes = sizeof(struct afs_CMStats);
915 dataBuffP = (afs_int32 *) afs_osi_Alloc(dataBytes);
916 memcpy((char *)dataBuffP, (char *)&afs_cmstats, dataBytes);
917 a_dataP->AFSCB_CollData_len = dataBytes >> 2;
918 a_dataP->AFSCB_CollData_val = dataBuffP;
921 case AFSCB_XSTATSCOLL_PERF_INFO:
923 * Update and then pass back all the performance-related data.
924 * Note: the only performance fields that need to be computed
925 * at this time are the number of accesses for this collection
926 * and the current server record info.
928 * >>> We are forced to allocate a separate area in which to
929 * >>> put this stuff in by the RPC stub generator, since it
930 * >>> will be freed at the tail end of the server stub code.
932 afs_stats_cmperf.numPerfCalls++;
934 dataBytes = sizeof(afs_stats_cmperf);
935 dataBuffP = (afs_int32 *) afs_osi_Alloc(dataBytes);
936 memcpy((char *)dataBuffP, (char *)&afs_stats_cmperf, dataBytes);
937 a_dataP->AFSCB_CollData_len = dataBytes >> 2;
938 a_dataP->AFSCB_CollData_val = dataBuffP;
941 case AFSCB_XSTATSCOLL_FULL_PERF_INFO:
943 * Pass back the full range of performance and statistical
944 * data available. We have to bring the normal performance
945 * data collection up to date, then copy that data into
946 * the full collection.
948 * >>> We are forced to allocate a separate area in which to
949 * >>> put this stuff in by the RPC stub generator, since it
950 * >>> will be freed at the tail end of the server stub code.
952 afs_stats_cmperf.numPerfCalls++;
954 memcpy((char *)(&(afs_stats_cmfullperf.perf)),
955 (char *)(&afs_stats_cmperf), sizeof(struct afs_stats_CMPerf));
956 afs_stats_cmfullperf.numFullPerfCalls++;
958 dataBytes = sizeof(afs_stats_cmfullperf);
959 dataBuffP = (afs_int32 *) afs_osi_Alloc(dataBytes);
960 memcpy((char *)dataBuffP, (char *)(&afs_stats_cmfullperf), dataBytes);
961 a_dataP->AFSCB_CollData_len = dataBytes >> 2;
962 a_dataP->AFSCB_CollData_val = dataBuffP;
967 * Illegal collection number.
969 a_dataP->AFSCB_CollData_len = 0;
970 a_dataP->AFSCB_CollData_val = NULL;
972 } /*Switch on collection number */
973 #endif /* AFS_NOSTATS */
981 } /*SRXAFSCB_GetXStats */
984 /*------------------------------------------------------------------------
985 * EXPORTED afs_RXCallBackServer
988 * Body of the thread supporting callback services.
997 * Nothing interesting.
1001 *------------------------------------------------------------------------*/
1004 afs_RXCallBackServer(void)
1006 AFS_STATCNT(afs_RXCallBackServer);
1011 afs_osi_Sleep(&afs_server);
1015 * Donate this process to Rx.
1017 rx_ServerProc(NULL);
1020 } /*afs_RXCallBackServer */
1023 /*------------------------------------------------------------------------
1024 * EXPORTED shutdown_CB
1027 * Zero out important Cache Manager data structures.
1036 * Nothing interesting.
1040 *------------------------------------------------------------------------*/
1045 AFS_STATCNT(shutdown_CB);
1047 if (afs_cold_shutdown) {
1048 afs_oddCBs = afs_evenCBs = afs_allCBs = afs_allZaps = afs_oddZaps =
1049 afs_evenZaps = afs_connectBacks = 0;
1056 /*------------------------------------------------------------------------
1057 * EXPORTED SRXAFSCB_InitCallBackState2
1060 * This routine was used in the AFS 3.5 beta release, but not anymore.
1061 * It has since been replaced by SRXAFSCB_InitCallBackState3.
1064 * a_call : Ptr to Rx call on which this request came in.
1067 * RXGEN_OPCODE (always).
1070 * Nothing interesting.
1074 *------------------------------------------------------------------------*/
1077 SRXAFSCB_InitCallBackState2(struct rx_call *a_call,
1078 struct interfaceAddr *addr)
1080 return RXGEN_OPCODE;
1083 /*------------------------------------------------------------------------
1084 * EXPORTED SRXAFSCB_WhoAreYou
1087 * Routine called by the server-side callback RPC interface to
1088 * obtain a unique identifier for the client. The server uses
1089 * this identifier to figure out whether or not two RX connections
1090 * are from the same client, and to find out which addresses go
1091 * with which clients.
1094 * a_call : Ptr to Rx call on which this request came in.
1095 * addr: Ptr to return the list of interfaces for this client.
1101 * Nothing interesting.
1105 *------------------------------------------------------------------------*/
1108 SRXAFSCB_WhoAreYou(struct rx_call *a_call, struct interfaceAddr *addr)
1115 AFS_STATCNT(SRXAFSCB_WhoAreYou);
1117 memset(addr, 0, sizeof(*addr));
1119 ObtainReadLock(&afs_xinterface);
1121 /* return all network interface addresses */
1122 addr->numberOfInterfaces = afs_cb_interface.numberOfInterfaces;
1123 addr->uuid = afs_cb_interface.uuid;
1124 for (i = 0; i < afs_cb_interface.numberOfInterfaces; i++) {
1125 addr->addr_in[i] = ntohl(afs_cb_interface.addr_in[i]);
1126 addr->subnetmask[i] = ntohl(afs_cb_interface.subnetmask[i]);
1127 addr->mtu[i] = ntohl(afs_cb_interface.mtu[i]);
1130 ReleaseReadLock(&afs_xinterface);
1138 /*------------------------------------------------------------------------
1139 * EXPORTED SRXAFSCB_InitCallBackState3
1142 * Routine called by the server-side callback RPC interface to
1143 * implement clearing all callbacks from this host.
1146 * a_call : Ptr to Rx call on which this request came in.
1152 * Nothing interesting.
1156 *------------------------------------------------------------------------*/
1159 SRXAFSCB_InitCallBackState3(struct rx_call *a_call, afsUUID * a_uuid)
1164 * TBD: Lookup the server by the UUID instead of its IP address.
1166 code = SRXAFSCB_InitCallBackState(a_call);
1172 /*------------------------------------------------------------------------
1173 * EXPORTED SRXAFSCB_ProbeUuid
1176 * Routine called by the server-side callback RPC interface to
1177 * implement ``probing'' the Cache Manager, just making sure it's
1178 * still there is still the same client it used to be.
1181 * a_call : Ptr to Rx call on which this request came in.
1182 * a_uuid : Ptr to UUID that must match the client's UUID.
1185 * 0 if a_uuid matches the UUID for this client
1186 * Non-zero otherwize
1189 * Nothing interesting.
1193 *------------------------------------------------------------------------*/
1196 SRXAFSCB_ProbeUuid(struct rx_call *a_call, afsUUID * a_uuid)
1202 AFS_STATCNT(SRXAFSCB_Probe);
1204 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_PROBE);
1205 if (!afs_uuid_equal(a_uuid, &afs_cb_interface.uuid))
1206 code = 1; /* failure */
1215 /*------------------------------------------------------------------------
1216 * EXPORTED SRXAFSCB_GetServerPrefs
1219 * Routine to list server preferences used by this client.
1222 * a_call : Ptr to Rx call on which this request came in.
1223 * a_index : Input server index
1224 * a_srvr_addr : Output server address in host byte order
1225 * (0xffffffff on last server)
1226 * a_srvr_rank : Output server rank
1232 * Nothing interesting.
1236 *------------------------------------------------------------------------*/
1239 SRXAFSCB_GetServerPrefs(struct rx_call *a_call, afs_int32 a_index,
1240 afs_int32 * a_srvr_addr, afs_int32 * a_srvr_rank)
1246 AFS_STATCNT(SRXAFSCB_GetServerPrefs);
1248 ObtainReadLock(&afs_xserver);
1250 /* Search the hash table for the server with this index */
1251 *a_srvr_addr = 0xffffffff;
1252 *a_srvr_rank = 0xffffffff;
1253 for (i = 0, j = 0; j < NSERVERS && i <= a_index; j++) {
1254 for (sa = afs_srvAddrs[j]; sa && i <= a_index; sa = sa->next_bkt, i++) {
1256 *a_srvr_addr = ntohl(sa->sa_ip);
1257 *a_srvr_rank = sa->sa_iprank;
1262 ReleaseReadLock(&afs_xserver);
1270 /*------------------------------------------------------------------------
1271 * EXPORTED SRXAFSCB_GetCellServDB
1274 * Routine to list cells configured for this client
1277 * a_call : Ptr to Rx call on which this request came in.
1278 * a_index : Input cell index
1279 * a_name : Output cell name ("" on last cell)
1280 * a_hosts : Output cell database servers in host byte order.
1286 * Nothing interesting.
1290 *------------------------------------------------------------------------*/
1293 SRXAFSCB_GetCellServDB(struct rx_call *a_call, afs_int32 a_index,
1294 char **a_name, serverList * a_hosts)
1298 char *t_name, *p_name = NULL;
1301 AFS_STATCNT(SRXAFSCB_GetCellServDB);
1303 tcell = afs_GetCellByIndex(a_index, READ_LOCK);
1307 a_hosts->serverList_val = 0;
1308 a_hosts->serverList_len = 0;
1310 p_name = tcell->cellName;
1311 for (j = 0; j < AFSMAXCELLHOSTS && tcell->cellHosts[j]; j++);
1313 a_hosts->serverList_val =
1314 (afs_int32 *) afs_osi_Alloc(j * sizeof(afs_int32));
1315 a_hosts->serverList_len = j;
1316 for (j = 0; j < AFSMAXCELLHOSTS && tcell->cellHosts[j]; j++)
1317 a_hosts->serverList_val[j] =
1318 ntohl(tcell->cellHosts[j]->addr->sa_ip);
1319 afs_PutCell(tcell, READ_LOCK);
1322 t_name = (char *)afs_osi_Alloc(i + 1);
1323 if (t_name == NULL) {
1324 afs_osi_Free(a_hosts->serverList_val, (j * sizeof(afs_int32)));
1331 memcpy(t_name, p_name, i);
1340 /*------------------------------------------------------------------------
1341 * EXPORTED SRXAFSCB_GetLocalCell
1344 * Routine to return name of client's local cell
1347 * a_call : Ptr to Rx call on which this request came in.
1348 * a_name : Output cell name
1354 * Nothing interesting.
1358 *------------------------------------------------------------------------*/
1361 SRXAFSCB_GetLocalCell(struct rx_call *a_call, char **a_name)
1365 char *t_name, *p_name = NULL;
1368 AFS_STATCNT(SRXAFSCB_GetLocalCell);
1370 /* Search the list for the primary cell. Cell number 1 is only
1371 * the primary cell is when no other cell is explicitly marked as
1372 * the primary cell. */
1373 tcell = afs_GetPrimaryCell(READ_LOCK);
1375 p_name = tcell->cellName;
1377 plen = strlen(p_name);
1380 t_name = (char *)afs_osi_Alloc(plen + 1);
1381 if (t_name == NULL) {
1383 afs_PutCell(tcell, READ_LOCK);
1388 t_name[plen] = '\0';
1390 memcpy(t_name, p_name, plen);
1396 afs_PutCell(tcell, READ_LOCK);
1402 * afs_MarshallCacheConfig - marshall client cache configuration
1406 * IN callerVersion - the rpc stat version of the caller.
1408 * IN config - client cache configuration.
1410 * OUT ptr - buffer where configuration is marshalled.
1417 afs_MarshallCacheConfig(afs_uint32 callerVersion, cm_initparams_v1 * config,
1420 AFS_STATCNT(afs_MarshallCacheConfig);
1422 * We currently only support version 1.
1424 *(ptr++) = config->nChunkFiles;
1425 *(ptr++) = config->nStatCaches;
1426 *(ptr++) = config->nDataCaches;
1427 *(ptr++) = config->nVolumeCaches;
1428 *(ptr++) = config->firstChunkSize;
1429 *(ptr++) = config->otherChunkSize;
1430 *(ptr++) = config->cacheSize;
1431 *(ptr++) = config->setTime;
1432 *(ptr++) = config->memCache;
1436 /*------------------------------------------------------------------------
1437 * EXPORTED SRXAFSCB_GetCacheConfig
1440 * Routine to return parameters used to initialize client cache.
1441 * Client may request any format version. Server may not return
1442 * format version greater than version requested by client.
1445 * a_call: Ptr to Rx call on which this request came in.
1446 * callerVersion: Data format version desired by the client.
1447 * serverVersion: Data format version of output data.
1448 * configCount: Number bytes allocated for output data.
1449 * config: Client cache configuration.
1455 * Nothing interesting.
1459 *------------------------------------------------------------------------*/
1462 SRXAFSCB_GetCacheConfig(struct rx_call *a_call, afs_uint32 callerVersion,
1463 afs_uint32 * serverVersion, afs_uint32 * configCount,
1464 cacheConfig * config)
1466 afs_uint32 *t_config;
1468 cm_initparams_v1 cm_config;
1471 AFS_STATCNT(SRXAFSCB_GetCacheConfig);
1474 * Currently only support version 1
1476 allocsize = sizeof(cm_initparams_v1);
1477 t_config = (afs_uint32 *) afs_osi_Alloc(allocsize);
1478 if (t_config == NULL) {
1483 cm_config.nChunkFiles = cm_initParams.cmi_nChunkFiles;
1484 cm_config.nStatCaches = cm_initParams.cmi_nStatCaches;
1485 cm_config.nDataCaches = cm_initParams.cmi_nDataCaches;
1486 cm_config.nVolumeCaches = cm_initParams.cmi_nVolumeCaches;
1487 cm_config.firstChunkSize = cm_initParams.cmi_firstChunkSize;
1488 cm_config.otherChunkSize = cm_initParams.cmi_otherChunkSize;
1489 cm_config.cacheSize = cm_initParams.cmi_cacheSize;
1490 cm_config.setTime = cm_initParams.cmi_setTime;
1491 cm_config.memCache = cm_initParams.cmi_memCache;
1493 afs_MarshallCacheConfig(callerVersion, &cm_config, t_config);
1495 *serverVersion = AFS_CLIENT_RETRIEVAL_FIRST_EDITION;
1496 *configCount = allocsize;
1497 config->cacheConfig_val = t_config;
1498 config->cacheConfig_len = allocsize / sizeof(afs_uint32);
1505 /*------------------------------------------------------------------------
1506 * EXPORTED SRXAFSCB_FetchData
1509 * Routine to do third party move from a remioserver to the original
1510 * issuer of an ArchiveData request. Presently supported only by the
1511 * "fs" command, not by the AFS client.
1514 * rxcall: Ptr to Rx call on which this request came in.
1515 * Fid: pointer to AFSFid structure.
1516 * Fd: File descriptor inside fs command.
1517 * Position: Offset in the file.
1518 * Length: Data length to transfer.
1519 * TotalLength: Pointer to total file length field
1525 * Nothing interesting.
1528 *------------------------------------------------------------------------*/
1530 SRXAFSCB_FetchData(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_StoreData
1541 * Routine to do third party move from a remioserver to the original
1542 * issuer of a RetrieveData request. Presently supported only by the
1543 * "fs" command, not by the AFS client.
1546 * rxcall: Ptr to Rx call on which this request came in.
1547 * Fid: pointer to AFSFid structure.
1548 * Fd: File descriptor inside fs command.
1549 * Position: Offset in the file.
1550 * Length: Data length to transfer.
1551 * TotalLength: Pointer to total file length field
1557 * Nothing interesting.
1561 *------------------------------------------------------------------------*/
1563 SRXAFSCB_StoreData(struct rx_call *rxcall, struct AFSFid *Fid, afs_int32 Fd,
1564 afs_int64 Position, afs_int64 Length,
1565 afs_int64 * TotalLength)
1570 /*------------------------------------------------------------------------
1571 * EXPORTED SRXAFSCB_GetCellByNum
1574 * Routine to get information about a cell specified by its
1575 * cell number (returned by GetCE/GetCE64).
1578 * a_call : Ptr to Rx call on which this request came in.
1579 * a_cellnum : Input cell number
1580 * a_name : Output cell name (one zero byte when no such cell).
1581 * a_hosts : Output cell database servers in host byte order.
1587 * Nothing interesting.
1591 *------------------------------------------------------------------------*/
1594 SRXAFSCB_GetCellByNum(struct rx_call *a_call, afs_int32 a_cellnum,
1595 char **a_name, serverList * a_hosts)
1601 AFS_STATCNT(SRXAFSCB_GetCellByNum);
1603 a_hosts->serverList_val = 0;
1604 a_hosts->serverList_len = 0;
1606 tcell = afs_GetCellStale(a_cellnum, READ_LOCK);
1608 *a_name = afs_strdup("");
1613 ObtainReadLock(&tcell->lock);
1614 *a_name = afs_strdup(tcell->cellName);
1616 for (sn = 0; sn < AFSMAXCELLHOSTS && tcell->cellHosts[sn]; sn++);
1617 a_hosts->serverList_len = sn;
1618 a_hosts->serverList_val =
1619 (afs_int32 *) afs_osi_Alloc(sn * sizeof(afs_int32));
1621 for (i = 0; i < sn; i++)
1622 a_hosts->serverList_val[i] = ntohl(tcell->cellHosts[i]->addr->sa_ip);
1623 ReleaseReadLock(&tcell->lock);
1624 afs_PutCell(tcell, READ_LOCK);
1631 SRXAFSCB_TellMeAboutYourself(struct rx_call *a_call,
1632 struct interfaceAddr *addr,
1633 Capabilities * capabilities)
1637 afs_int32 *dataBuffP;
1638 afs_int32 dataBytes;
1642 AFS_STATCNT(SRXAFSCB_WhoAreYou);
1644 ObtainReadLock(&afs_xinterface);
1646 /* return all network interface addresses */
1647 addr->numberOfInterfaces = afs_cb_interface.numberOfInterfaces;
1648 addr->uuid = afs_cb_interface.uuid;
1649 for (i = 0; i < afs_cb_interface.numberOfInterfaces; i++) {
1650 addr->addr_in[i] = ntohl(afs_cb_interface.addr_in[i]);
1651 addr->subnetmask[i] = ntohl(afs_cb_interface.subnetmask[i]);
1652 addr->mtu[i] = ntohl(afs_cb_interface.mtu[i]);
1655 ReleaseReadLock(&afs_xinterface);
1659 dataBytes = 1 * sizeof(afs_int32);
1660 dataBuffP = (afs_int32 *) afs_osi_Alloc(dataBytes);
1661 dataBuffP[0] = CLIENT_CAPABILITY_ERRORTRANS;
1662 capabilities->Capabilities_len = dataBytes / sizeof(afs_int32);
1663 capabilities->Capabilities_val = dataBuffP;
1669 #if 0 && defined(AFS_LINUX24_ENV)
1670 extern struct vcache *afs_globalVp;
1672 int recurse_dcache_parent(parent, a_index, addr, inode, flags, time, fileName)
1673 struct dentry * parent;
1681 struct dentry *this_parent = parent;
1682 struct list_head *next;
1684 struct dentry *dentry;
1687 next = this_parent->d_subdirs.next;
1689 while (next != &this_parent->d_subdirs) {
1690 struct list_head *tmp = next;
1691 dentry = list_entry(tmp, struct dentry, d_child);
1697 * Descend a level if the d_subdirs list is non-empty.
1699 if (!list_empty(&dentry->d_subdirs)) {
1700 this_parent = dentry;
1705 * All done at this level ... ascend and resume the search.
1707 if (this_parent != parent) {
1708 next = this_parent->d_child.next;
1709 this_parent = this_parent->d_parent;
1715 if (d_unhashed(dentry))
1720 *fileName = afs_strdup(dentry->d_name.name?dentry->d_name.name:"");
1721 *inode = ITOAFS(dentry->d_inode);
1722 *addr = atomic_read(&(dentry)->d_count);
1723 *time = dentry->d_time;
1731 int SRXAFSCB_GetDE(a_call, a_index, addr, inode, flags, time, fileName)
1732 struct rx_call *a_call;
1739 { /*SRXAFSCB_GetDE*/
1740 int code = 0; /*Return code*/
1741 #if 0 && defined(AFS_LINUX24_ENV)
1742 register int i; /*Loop variable*/
1743 register struct vcache *tvc = afs_globalVp;
1744 struct dentry *dentry;
1745 struct list_head *cur, *head = &(AFSTOI(tvc))->i_dentry;
1747 #ifdef RX_ENABLE_LOCKS
1749 #endif /* RX_ENABLE_LOCKS */
1751 #if defined(AFS_LINUX24_ENV)
1752 spin_lock(&dcache_lock);
1756 while ((cur = cur->next) != head) {
1757 dentry = list_entry(cur, struct dentry, d_alias);
1759 dget_locked(dentry);
1761 #if defined(AFS_LINUX24_ENV)
1762 spin_unlock(&dcache_lock);
1768 if (recurse_dcache_parent(dentry, a_index, addr, inode, flags, time, fileName) == 0) {
1779 *fileName = afs_strdup("");
1783 if (d_unhashed(dentry))
1788 *fileName = afs_strdup(dentry->d_name.name?dentry->d_name.name:"");
1789 *inode = ITOAFS(dentry->d_inode);
1790 *addr = atomic_read(&(dentry)->d_count);
1791 *time = dentry->d_time;
1798 #ifdef RX_ENABLE_LOCKS
1800 #endif /* RX_ENABLE_LOCKS */
1804 } /*SRXAFSCB_GetDE*/