2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
12 * Exported routines (and their private support) to implement
13 * the callback RPC interface.
16 #include <afsconfig.h>
17 #include "afs/param.h"
20 #include "afs/sysincludes.h" /*Standard vendor system headers */
21 #include "afsincludes.h" /*AFS-based standard headers */
22 #include "afs/afs_stats.h" /*Cache Manager stats */
23 #include "afs/afs_args.h"
25 afs_int32 afs_allCBs = 0; /*Break callbacks on all objects */
26 afs_int32 afs_oddCBs = 0; /*Break callbacks on dirs */
27 afs_int32 afs_evenCBs = 0; /*Break callbacks received on files */
28 afs_int32 afs_allZaps = 0; /*Objects entries deleted */
29 afs_int32 afs_oddZaps = 0; /*Dir cache entries deleted */
30 afs_int32 afs_evenZaps = 0; /*File cache entries deleted */
31 afs_int32 afs_connectBacks = 0;
34 * Some debugging aids.
36 static struct ltable {
41 "afs_xvcache", (char *)&afs_xvcache}, {
42 "afs_xdcache", (char *)&afs_xdcache}, {
43 "afs_xserver", (char *)&afs_xserver}, {
44 "afs_xvcb", (char *)&afs_xvcb}, {
45 "afs_xbrs", (char *)&afs_xbrs}, {
46 "afs_xcell", (char *)&afs_xcell}, {
47 "afs_xconn", (char *)&afs_xconn}, {
48 "afs_xuser", (char *)&afs_xuser}, {
49 "afs_xvolume", (char *)&afs_xvolume}, {
50 "puttofile", (char *)&afs_puttofileLock}, {
51 "afs_ftf", (char *)&afs_ftf}, {
52 "afs_xcbhash", (char *)&afs_xcbhash}, {
53 "afs_xaxs", (char *)&afs_xaxs}, {
54 "afs_xinterface", (char *)&afs_xinterface},
57 "afs_xosi", (char *)&afs_xosi},
60 "afs_xsrvAddr", (char *)&afs_xsrvAddr},
62 "afs_xvreclaim", (char *)&afs_xvreclaim},
64 { "afsdb_client_lock", (char *)&afsdb_client_lock},
65 { "afsdb_req_lock", (char *)&afsdb_req_lock},
68 { "afs_discon_lock", (char *)&afs_discon_lock},
69 { "afs_disconDirtyLock", (char *)&afs_disconDirtyLock},
70 { "afs_discon_vc_dirty", (char *)&afs_xvcdirty},
73 unsigned long lastCallBack_vnode;
74 unsigned int lastCallBack_dv;
75 osi_timeval_t lastCallBack_time;
77 /* these are for storing alternate interface addresses */
78 struct interfaceAddr afs_cb_interface;
80 /*------------------------------------------------------------------------
81 * EXPORTED SRXAFSCB_GetCE
84 * Routine called by the server-side callback RPC interface to
85 * implement pulling out the contents of the i'th cache entry.
88 * a_call : Ptr to Rx call on which this request came in.
89 * a_index : Index of desired cache entry.
90 * a_result : Ptr to a buffer for the given cache entry.
93 * 0 if everything went fine,
94 * 1 if we were given a bad index.
97 * Nothing interesting.
101 *------------------------------------------------------------------------*/
104 SRXAFSCB_GetCE(struct rx_call *a_call, afs_int32 a_index,
105 struct AFSDBCacheEntry *a_result)
108 register int i; /*Loop variable */
109 register struct vcache *tvc; /*Ptr to current cache entry */
110 int code; /*Return code */
115 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_GETCE);
117 AFS_STATCNT(SRXAFSCB_GetCE);
118 for (i = 0; i < VCSIZE; i++) {
119 for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
123 } /*Zip through current hash chain */
124 } /*Zip through hash chains */
134 * Copy out the located entry.
136 a_result->addr = afs_data_pointer_to_int32(tvc);
137 a_result->cell = tvc->f.fid.Cell;
138 a_result->netFid.Volume = tvc->f.fid.Fid.Volume;
139 a_result->netFid.Vnode = tvc->f.fid.Fid.Vnode;
140 a_result->netFid.Unique = tvc->f.fid.Fid.Unique;
141 a_result->lock.waitStates = tvc->lock.wait_states;
142 a_result->lock.exclLocked = tvc->lock.excl_locked;
143 a_result->lock.readersReading = tvc->lock.readers_reading;
144 a_result->lock.numWaiting = tvc->lock.num_waiting;
145 #if defined(INSTRUMENT_LOCKS)
146 a_result->lock.pid_last_reader = MyPidxx2Pid(tvc->lock.pid_last_reader);
147 a_result->lock.pid_writer = MyPidxx2Pid(tvc->lock.pid_writer);
148 a_result->lock.src_indicator = tvc->lock.src_indicator;
150 /* On osf20 , the vcache does not maintain these three fields */
151 a_result->lock.pid_last_reader = 0;
152 a_result->lock.pid_writer = 0;
153 a_result->lock.src_indicator = 0;
154 #endif /* AFS_OSF20_ENV */
155 #ifdef AFS_64BIT_CLIENT
156 a_result->Length = (afs_int32) tvc->f.m.Length & 0xffffffff;
157 #else /* AFS_64BIT_CLIENT */
158 a_result->Length = tvc->f.m.Length;
159 #endif /* AFS_64BIT_CLIENT */
160 a_result->DataVersion = hgetlo(tvc->f.m.DataVersion);
161 a_result->callback = afs_data_pointer_to_int32(tvc->callback); /* XXXX Now a pointer; change it XXXX */
162 a_result->cbExpires = tvc->cbExpires;
163 if (tvc->f.states & CVInit) {
164 a_result->refCount = 1;
166 #ifdef AFS_DARWIN80_ENV
167 a_result->refCount = vnode_isinuse(AFSTOV(tvc),0)?1:0; /* XXX fix */
169 a_result->refCount = VREFCOUNT(tvc);
172 a_result->opens = tvc->opens;
173 a_result->writers = tvc->execsOrWriters;
174 a_result->mvstat = tvc->mvstat;
175 a_result->states = tvc->f.states;
179 * Return our results.
188 } /*SRXAFSCB_GetCE */
191 SRXAFSCB_GetCE64(struct rx_call *a_call, afs_int32 a_index,
192 struct AFSDBCacheEntry64 *a_result)
194 register int i; /*Loop variable */
195 register struct vcache *tvc; /*Ptr to current cache entry */
196 int code; /*Return code */
201 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_GETCE);
203 AFS_STATCNT(SRXAFSCB_GetCE64);
204 for (i = 0; i < VCSIZE; i++) {
205 for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
209 } /*Zip through current hash chain */
210 } /*Zip through hash chains */
220 * Copy out the located entry.
222 a_result->addr = afs_data_pointer_to_int32(tvc);
223 a_result->cell = tvc->f.fid.Cell;
224 a_result->netFid.Volume = tvc->f.fid.Fid.Volume;
225 a_result->netFid.Vnode = tvc->f.fid.Fid.Vnode;
226 a_result->netFid.Unique = tvc->f.fid.Fid.Unique;
227 a_result->lock.waitStates = tvc->lock.wait_states;
228 a_result->lock.exclLocked = tvc->lock.excl_locked;
229 a_result->lock.readersReading = tvc->lock.readers_reading;
230 a_result->lock.numWaiting = tvc->lock.num_waiting;
231 #if defined(INSTRUMENT_LOCKS)
232 a_result->lock.pid_last_reader = MyPidxx2Pid(tvc->lock.pid_last_reader);
233 a_result->lock.pid_writer = MyPidxx2Pid(tvc->lock.pid_writer);
234 a_result->lock.src_indicator = tvc->lock.src_indicator;
236 /* On osf20 , the vcache does not maintain these three fields */
237 a_result->lock.pid_last_reader = 0;
238 a_result->lock.pid_writer = 0;
239 a_result->lock.src_indicator = 0;
240 #endif /* AFS_OSF20_ENV */
241 #if !defined(AFS_64BIT_ENV)
242 a_result->Length.high = 0;
243 a_result->Length.low = tvc->f.m.Length;
245 a_result->Length = tvc->f.m.Length;
247 a_result->DataVersion = hgetlo(tvc->f.m.DataVersion);
248 a_result->callback = afs_data_pointer_to_int32(tvc->callback); /* XXXX Now a pointer; change it XXXX */
249 a_result->cbExpires = tvc->cbExpires;
250 if (tvc->f.states & CVInit) {
251 a_result->refCount = 1;
253 #ifdef AFS_DARWIN80_ENV
254 a_result->refCount = vnode_isinuse(AFSTOV(tvc),0)?1:0; /* XXX fix */
256 a_result->refCount = VREFCOUNT(tvc);
259 a_result->opens = tvc->opens;
260 a_result->writers = tvc->execsOrWriters;
261 a_result->mvstat = tvc->mvstat;
262 a_result->states = tvc->f.states;
266 * Return our results.
275 } /*SRXAFSCB_GetCE64 */
278 /*------------------------------------------------------------------------
279 * EXPORTED SRXAFSCB_GetLock
282 * Routine called by the server-side callback RPC interface to
283 * implement pulling out the contents of a lock in the lock
287 * a_call : Ptr to Rx call on which this request came in.
288 * a_index : Index of desired lock.
289 * a_result : Ptr to a buffer for the given lock.
292 * 0 if everything went fine,
293 * 1 if we were given a bad index.
296 * Nothing interesting.
300 *------------------------------------------------------------------------*/
303 SRXAFSCB_GetLock(struct rx_call *a_call, afs_int32 a_index,
304 struct AFSDBLock *a_result)
306 struct ltable *tl; /*Ptr to lock table entry */
307 int nentries; /*Num entries in table */
308 int code; /*Return code */
313 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_GETLOCK);
315 AFS_STATCNT(SRXAFSCB_GetLock);
316 nentries = sizeof(ltable) / sizeof(struct ltable);
317 if (a_index < 0 || a_index >= nentries+afs_cellindex) {
322 } else if (a_index >= nentries) {
323 struct cell *tc = afs_GetCellByIndex(a_index-nentries, 0);
324 strcpy(a_result->name, tc->cellName);
325 a_result->lock.waitStates =
326 ((struct afs_lock *)&(tc->lock))->wait_states;
327 a_result->lock.exclLocked =
328 ((struct afs_lock *)&(tc->lock))->excl_locked;
329 a_result->lock.readersReading =
330 ((struct afs_lock *)&(tc->lock))->readers_reading;
331 a_result->lock.numWaiting =
332 ((struct afs_lock *)&(tc->lock))->num_waiting;
333 #ifdef INSTRUMENT_LOCKS
334 a_result->lock.pid_last_reader =
335 MyPidxx2Pid(((struct afs_lock *)&(tc->lock))->pid_last_reader);
336 a_result->lock.pid_writer =
337 MyPidxx2Pid(((struct afs_lock *)&(tc->lock))->pid_writer);
338 a_result->lock.src_indicator =
339 ((struct afs_lock *)&(tc->lock))->src_indicator;
341 a_result->lock.pid_last_reader = 0;
342 a_result->lock.pid_writer = 0;
343 a_result->lock.src_indicator = 0;
348 * Found it - copy out its contents.
350 tl = <able[a_index];
351 strcpy(a_result->name, tl->name);
352 a_result->lock.waitStates =
353 ((struct afs_lock *)(tl->addr))->wait_states;
354 a_result->lock.exclLocked =
355 ((struct afs_lock *)(tl->addr))->excl_locked;
356 a_result->lock.readersReading =
357 ((struct afs_lock *)(tl->addr))->readers_reading;
358 a_result->lock.numWaiting =
359 ((struct afs_lock *)(tl->addr))->num_waiting;
360 #ifdef INSTRUMENT_LOCKS
361 a_result->lock.pid_last_reader =
362 MyPidxx2Pid(((struct afs_lock *)(tl->addr))->pid_last_reader);
363 a_result->lock.pid_writer =
364 MyPidxx2Pid(((struct afs_lock *)(tl->addr))->pid_writer);
365 a_result->lock.src_indicator =
366 ((struct afs_lock *)(tl->addr))->src_indicator;
368 a_result->lock.pid_last_reader = 0;
369 a_result->lock.pid_writer = 0;
370 a_result->lock.src_indicator = 0;
381 } /*SRXAFSCB_GetLock */
384 /*------------------------------------------------------------------------
385 * static ClearCallBack
388 * Clear out callback information for the specified file, or
389 * even a whole volume. Used to worry about callback was from
390 * within the particular cell or not. Now we don't bother with
391 * that anymore; it's not worth the time.
394 * a_conn : Ptr to Rx connection involved.
395 * a_fid : Ptr to AFS fid being cleared.
401 * Nothing interesting.
406 Appears to need to be called with GLOCK held, as the icl_Event4 stuff asserts otherwise
408 *------------------------------------------------------------------------*/
411 ClearCallBack(register struct rx_connection *a_conn,
412 register struct AFSFid *a_fid)
414 register struct vcache *tvc;
416 struct VenusFid localFid;
418 #ifdef AFS_DARWIN80_ENV
422 AFS_STATCNT(ClearCallBack);
427 * XXXX Don't hold any server locks here because of callback protocol XXX
430 localFid.Fid.Volume = a_fid->Volume;
431 localFid.Fid.Vnode = a_fid->Vnode;
432 localFid.Fid.Unique = a_fid->Unique;
435 * Volume ID of zero means don't do anything.
437 if (a_fid->Volume != 0) {
438 if (a_fid->Vnode == 0) {
439 struct afs_q *tq, *uq;
441 * Clear callback for the whole volume. Zip through the
442 * hash chain, nullifying entries whose volume ID matches.
445 ObtainReadLock(&afs_xvcache);
446 i = VCHashV(&localFid);
447 for (tq = afs_vhashTV[i].prev; tq != &afs_vhashTV[i]; tq = uq) {
450 if (tvc->f.fid.Fid.Volume == a_fid->Volume) {
451 tvc->callback = NULL;
453 localFid.Cell = tvc->f.fid.Cell;
454 tvc->dchint = NULL; /* invalidate hints */
455 if (tvc->f.states & CVInit) {
456 ReleaseReadLock(&afs_xvcache);
457 afs_osi_Sleep(&tvc->f.states);
460 #ifdef AFS_DARWIN80_ENV
461 if (tvc->f.states & CDeadVnode) {
462 ReleaseReadLock(&afs_xvcache);
463 afs_osi_Sleep(&tvc->f.states);
467 #if defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_HPUX_ENV) || defined(AFS_LINUX20_ENV)
468 VN_HOLD(AFSTOV(tvc));
470 #ifdef AFS_DARWIN80_ENV
481 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
484 VREFCOUNT_INC(tvc); /* AIX, apparently */
488 ReleaseReadLock(&afs_xvcache);
489 ObtainWriteLock(&afs_xcbhash, 449);
490 afs_DequeueCallback(tvc);
491 tvc->f.states &= ~(CStatd | CUnique | CBulkFetching);
493 if (tvc->f.fid.Fid.Vnode & 1)
497 ReleaseWriteLock(&afs_xcbhash);
498 if ((tvc->f.fid.Fid.Vnode & 1 || (vType(tvc) == VDIR)))
499 osi_dnlc_purgedp(tvc);
500 afs_Trace3(afs_iclSetp, CM_TRACE_CALLBACK,
501 ICL_TYPE_POINTER, tvc, ICL_TYPE_INT32,
502 tvc->f.states, ICL_TYPE_INT32,
504 #ifdef AFS_DARWIN80_ENV
505 vnode_put(AFSTOV(tvc));
507 ObtainReadLock(&afs_xvcache);
510 } else if ((tvc->f.states & CMValid)
511 && (tvc->mvid->Fid.Volume == a_fid->Volume)) {
512 tvc->f.states &= ~CMValid;
514 localFid.Cell = tvc->mvid->Cell;
517 ReleaseReadLock(&afs_xvcache);
520 * XXXX Don't hold any locks here XXXX
522 tv = afs_FindVolume(&localFid, 0);
524 afs_ResetVolumeInfo(tv);
525 afs_PutVolume(tv, 0);
526 /* invalidate mtpoint? */
528 } /*Clear callbacks for whole volume */
531 * Clear callbacks just for the one file.
535 if (a_fid->Vnode & 1)
536 afs_oddCBs++; /*Could do this on volume basis, too */
538 afs_evenCBs++; /*A particular fid was specified */
540 ObtainReadLock(&afs_xvcache);
541 i = VCHash(&localFid);
542 for (tvc = afs_vhashT[i]; tvc; tvc = uvc) {
544 if (tvc->f.fid.Fid.Vnode == a_fid->Vnode
545 && tvc->f.fid.Fid.Volume == a_fid->Volume
546 && tvc->f.fid.Fid.Unique == a_fid->Unique) {
547 tvc->callback = NULL;
548 tvc->dchint = NULL; /* invalidate hints */
549 if (tvc->f.states & CVInit) {
550 ReleaseReadLock(&afs_xvcache);
551 afs_osi_Sleep(&tvc->f.states);
554 #ifdef AFS_DARWIN80_ENV
555 if (tvc->f.states & CDeadVnode) {
556 ReleaseReadLock(&afs_xvcache);
557 afs_osi_Sleep(&tvc->f.states);
561 #if defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_HPUX_ENV) || defined(AFS_LINUX20_ENV)
562 VN_HOLD(AFSTOV(tvc));
564 #ifdef AFS_DARWIN80_ENV
575 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
578 VREFCOUNT_INC(tvc); /* AIX, apparently */
582 ReleaseReadLock(&afs_xvcache);
583 ObtainWriteLock(&afs_xcbhash, 450);
584 afs_DequeueCallback(tvc);
585 tvc->f.states &= ~(CStatd | CUnique | CBulkFetching);
586 ReleaseWriteLock(&afs_xcbhash);
587 if ((tvc->f.fid.Fid.Vnode & 1 || (vType(tvc) == VDIR)))
588 osi_dnlc_purgedp(tvc);
589 afs_Trace3(afs_iclSetp, CM_TRACE_CALLBACK,
590 ICL_TYPE_POINTER, tvc, ICL_TYPE_INT32,
591 tvc->f.states, ICL_TYPE_LONG, 0);
593 lastCallBack_vnode = afid->Vnode;
594 lastCallBack_dv = tvc->mstat.DataVersion.low;
595 osi_GetuTime(&lastCallBack_time);
597 #ifdef AFS_DARWIN80_ENV
598 vnode_put(AFSTOV(tvc));
600 ObtainReadLock(&afs_xvcache);
604 } /*Walk through hash table */
605 ReleaseReadLock(&afs_xvcache);
606 } /*Clear callbacks for one file */
609 /*Fid has non-zero volume ID */
611 * Always return a predictable value.
618 /*------------------------------------------------------------------------
619 * EXPORTED SRXAFSCB_CallBack
622 * Routine called by the server-side callback RPC interface to
623 * implement passing in callback information.
627 * a_call : Ptr to Rx call on which this request came in.
628 * a_fids : Ptr to array of fids involved.
629 * a_callbacks : Ptr to matching callback info for the fids.
635 * Nothing interesting.
639 *------------------------------------------------------------------------*/
642 SRXAFSCB_CallBack(struct rx_call *a_call, register struct AFSCBFids *a_fids,
643 struct AFSCBs *a_callbacks)
645 register int i; /*Loop variable */
646 struct AFSFid *tfid; /*Ptr to current fid */
647 register struct rx_connection *tconn; /*Call's connection */
653 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_CALLBACK);
655 AFS_STATCNT(SRXAFSCB_CallBack);
656 if (!(tconn = rx_ConnectionOf(a_call)))
658 tfid = (struct AFSFid *)a_fids->AFSCBFids_val;
661 * For now, we ignore callbacks, since the File Server only *breaks*
662 * callbacks at present.
664 for (i = 0; i < a_fids->AFSCBFids_len; i++)
665 ClearCallBack(tconn, &tfid[i]);
673 } /*SRXAFSCB_CallBack */
676 /*------------------------------------------------------------------------
677 * EXPORTED SRXAFSCB_Probe
680 * Routine called by the server-side callback RPC interface to
681 * implement ``probing'' the Cache Manager, just making sure it's
685 * a_call : Ptr to Rx call on which this request came in.
691 * Nothing interesting.
695 *------------------------------------------------------------------------*/
698 SRXAFSCB_Probe(struct rx_call *a_call)
704 AFS_STATCNT(SRXAFSCB_Probe);
706 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_PROBE);
713 } /*SRXAFSCB_Probe */
716 /*------------------------------------------------------------------------
717 * EXPORTED SRXAFSCB_InitCallBackState
720 * Routine called by the server-side callback RPC interface to
721 * implement clearing all callbacks from this host.
724 * a_call : Ptr to Rx call on which this request came in.
730 * Nothing interesting.
734 *------------------------------------------------------------------------*/
737 SRXAFSCB_InitCallBackState(struct rx_call *a_call)
740 register struct vcache *tvc;
741 register struct rx_connection *tconn;
742 register struct rx_peer *peer;
749 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_INITCALLBACKSTATE);
750 AFS_STATCNT(SRXAFSCB_InitCallBackState);
753 * Find the address of the host making this call
755 if ((tconn = rx_ConnectionOf(a_call)) && (peer = rx_PeerOf(tconn))) {
758 afs_oddCBs++; /*Including any missed via create race */
759 afs_evenCBs++; /*Including any missed via create race */
761 ts = afs_FindServer(rx_HostOf(peer), rx_PortOf(peer), (afsUUID *) 0,
764 for (i = 0; i < VCSIZE; i++)
765 for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) {
766 if (tvc->callback == ts) {
767 ObtainWriteLock(&afs_xcbhash, 451);
768 afs_DequeueCallback(tvc);
769 tvc->callback = NULL;
770 tvc->f.states &= ~(CStatd | CUnique | CBulkFetching);
771 ReleaseWriteLock(&afs_xcbhash);
778 /* find any volumes residing on this server and flush their state */
780 register struct volume *tv;
783 for (i = 0; i < NVOLS; i++)
784 for (tv = afs_volumes[i]; tv; tv = tv->next) {
785 for (j = 0; j < MAXHOSTS; j++)
786 if (tv->serverHost[j] == ts)
787 afs_ResetVolumeInfo(tv);
790 osi_dnlc_purge(); /* may be a little bit extreme */
799 } /*SRXAFSCB_InitCallBackState */
802 /*------------------------------------------------------------------------
803 * EXPORTED SRXAFSCB_XStatsVersion
806 * Routine called by the server-side callback RPC interface to
807 * implement pulling out the xstat version number for the Cache
811 * a_versionP : Ptr to the version number variable to set.
817 * Nothing interesting.
821 *------------------------------------------------------------------------*/
824 SRXAFSCB_XStatsVersion(struct rx_call *a_call, afs_int32 * a_versionP)
831 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_XSTATSVERSION);
833 *a_versionP = AFSCB_XSTAT_VERSION;
840 } /*SRXAFSCB_XStatsVersion */
843 /*------------------------------------------------------------------------
844 * EXPORTED SRXAFSCB_GetXStats
847 * Routine called by the server-side callback RPC interface to
848 * implement getting the given data collection from the extended
849 * Cache Manager statistics.
852 * a_call : Ptr to Rx call on which this request came in.
853 * a_clientVersionNum : Client version number.
854 * a_opCode : Desired operation.
855 * a_serverVersionNumP : Ptr to version number to set.
856 * a_timeP : Ptr to time value (seconds) to set.
857 * a_dataArray : Ptr to variable array structure to return
864 * Nothing interesting.
868 *------------------------------------------------------------------------*/
871 SRXAFSCB_GetXStats(struct rx_call *a_call, afs_int32 a_clientVersionNum,
872 afs_int32 a_collectionNumber, afs_int32 * a_srvVersionNumP,
873 afs_int32 * a_timeP, AFSCB_CollData * a_dataP)
875 register int code; /*Return value */
876 afs_int32 *dataBuffP; /*Ptr to data to be returned */
877 afs_int32 dataBytes; /*Bytes in data buffer */
882 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_GETXSTATS);
885 * Record the time of day and the server version number.
887 *a_srvVersionNumP = AFSCB_XSTAT_VERSION;
888 *a_timeP = osi_Time();
891 * Stuff the appropriate data in there (assume victory)
897 * We're not keeping stats, so just return successfully with
900 a_dataP->AFSCB_CollData_len = 0;
901 a_dataP->AFSCB_CollData_val = NULL;
903 switch (a_collectionNumber) {
904 case AFSCB_XSTATSCOLL_CALL_INFO:
906 * Pass back all the call-count-related data.
908 * >>> We are forced to allocate a separate area in which to
909 * >>> put this stuff in by the RPC stub generator, since it
910 * >>> will be freed at the tail end of the server stub code.
912 dataBytes = sizeof(struct afs_CMStats);
913 dataBuffP = (afs_int32 *) afs_osi_Alloc(dataBytes);
914 memcpy((char *)dataBuffP, (char *)&afs_cmstats, dataBytes);
915 a_dataP->AFSCB_CollData_len = dataBytes >> 2;
916 a_dataP->AFSCB_CollData_val = dataBuffP;
919 case AFSCB_XSTATSCOLL_PERF_INFO:
921 * Update and then pass back all the performance-related data.
922 * Note: the only performance fields that need to be computed
923 * at this time are the number of accesses for this collection
924 * and the current server record info.
926 * >>> We are forced to allocate a separate area in which to
927 * >>> put this stuff in by the RPC stub generator, since it
928 * >>> will be freed at the tail end of the server stub code.
930 afs_stats_cmperf.numPerfCalls++;
932 dataBytes = sizeof(afs_stats_cmperf);
933 dataBuffP = (afs_int32 *) afs_osi_Alloc(dataBytes);
934 memcpy((char *)dataBuffP, (char *)&afs_stats_cmperf, dataBytes);
935 a_dataP->AFSCB_CollData_len = dataBytes >> 2;
936 a_dataP->AFSCB_CollData_val = dataBuffP;
939 case AFSCB_XSTATSCOLL_FULL_PERF_INFO:
941 * Pass back the full range of performance and statistical
942 * data available. We have to bring the normal performance
943 * data collection up to date, then copy that data into
944 * the full collection.
946 * >>> We are forced to allocate a separate area in which to
947 * >>> put this stuff in by the RPC stub generator, since it
948 * >>> will be freed at the tail end of the server stub code.
950 afs_stats_cmperf.numPerfCalls++;
952 memcpy((char *)(&(afs_stats_cmfullperf.perf)),
953 (char *)(&afs_stats_cmperf), sizeof(struct afs_stats_CMPerf));
954 afs_stats_cmfullperf.numFullPerfCalls++;
956 dataBytes = sizeof(afs_stats_cmfullperf);
957 dataBuffP = (afs_int32 *) afs_osi_Alloc(dataBytes);
958 memcpy((char *)dataBuffP, (char *)(&afs_stats_cmfullperf), dataBytes);
959 a_dataP->AFSCB_CollData_len = dataBytes >> 2;
960 a_dataP->AFSCB_CollData_val = dataBuffP;
965 * Illegal collection number.
967 a_dataP->AFSCB_CollData_len = 0;
968 a_dataP->AFSCB_CollData_val = NULL;
970 } /*Switch on collection number */
971 #endif /* AFS_NOSTATS */
979 } /*SRXAFSCB_GetXStats */
982 /*------------------------------------------------------------------------
983 * EXPORTED afs_RXCallBackServer
986 * Body of the thread supporting callback services.
995 * Nothing interesting.
999 *------------------------------------------------------------------------*/
1002 afs_RXCallBackServer(void)
1004 AFS_STATCNT(afs_RXCallBackServer);
1009 afs_osi_Sleep(&afs_server);
1013 * Donate this process to Rx.
1015 rx_ServerProc(NULL);
1018 } /*afs_RXCallBackServer */
1021 /*------------------------------------------------------------------------
1022 * EXPORTED shutdown_CB
1025 * Zero out important Cache Manager data structures.
1034 * Nothing interesting.
1038 *------------------------------------------------------------------------*/
1043 AFS_STATCNT(shutdown_CB);
1045 if (afs_cold_shutdown) {
1046 afs_oddCBs = afs_evenCBs = afs_allCBs = afs_allZaps = afs_oddZaps =
1047 afs_evenZaps = afs_connectBacks = 0;
1054 /*------------------------------------------------------------------------
1055 * EXPORTED SRXAFSCB_InitCallBackState2
1058 * This routine was used in the AFS 3.5 beta release, but not anymore.
1059 * It has since been replaced by SRXAFSCB_InitCallBackState3.
1062 * a_call : Ptr to Rx call on which this request came in.
1065 * RXGEN_OPCODE (always).
1068 * Nothing interesting.
1072 *------------------------------------------------------------------------*/
1075 SRXAFSCB_InitCallBackState2(struct rx_call *a_call,
1076 struct interfaceAddr *addr)
1078 return RXGEN_OPCODE;
1081 /*------------------------------------------------------------------------
1082 * EXPORTED SRXAFSCB_WhoAreYou
1085 * Routine called by the server-side callback RPC interface to
1086 * obtain a unique identifier for the client. The server uses
1087 * this identifier to figure out whether or not two RX connections
1088 * are from the same client, and to find out which addresses go
1089 * with which clients.
1092 * a_call : Ptr to Rx call on which this request came in.
1093 * addr: Ptr to return the list of interfaces for this client.
1099 * Nothing interesting.
1103 *------------------------------------------------------------------------*/
1106 SRXAFSCB_WhoAreYou(struct rx_call *a_call, struct interfaceAddr *addr)
1113 AFS_STATCNT(SRXAFSCB_WhoAreYou);
1115 memset(addr, 0, sizeof(*addr));
1117 ObtainReadLock(&afs_xinterface);
1119 /* return all network interface addresses */
1120 addr->numberOfInterfaces = afs_cb_interface.numberOfInterfaces;
1121 addr->uuid = afs_cb_interface.uuid;
1122 for (i = 0; i < afs_cb_interface.numberOfInterfaces; i++) {
1123 addr->addr_in[i] = ntohl(afs_cb_interface.addr_in[i]);
1124 addr->subnetmask[i] = ntohl(afs_cb_interface.subnetmask[i]);
1125 addr->mtu[i] = ntohl(afs_cb_interface.mtu[i]);
1128 ReleaseReadLock(&afs_xinterface);
1136 /*------------------------------------------------------------------------
1137 * EXPORTED SRXAFSCB_InitCallBackState3
1140 * Routine called by the server-side callback RPC interface to
1141 * implement clearing all callbacks from this host.
1144 * a_call : Ptr to Rx call on which this request came in.
1150 * Nothing interesting.
1154 *------------------------------------------------------------------------*/
1157 SRXAFSCB_InitCallBackState3(struct rx_call *a_call, afsUUID * a_uuid)
1162 * TBD: Lookup the server by the UUID instead of its IP address.
1164 code = SRXAFSCB_InitCallBackState(a_call);
1170 /*------------------------------------------------------------------------
1171 * EXPORTED SRXAFSCB_ProbeUuid
1174 * Routine called by the server-side callback RPC interface to
1175 * implement ``probing'' the Cache Manager, just making sure it's
1176 * still there is still the same client it used to be.
1179 * a_call : Ptr to Rx call on which this request came in.
1180 * a_uuid : Ptr to UUID that must match the client's UUID.
1183 * 0 if a_uuid matches the UUID for this client
1184 * Non-zero otherwize
1187 * Nothing interesting.
1191 *------------------------------------------------------------------------*/
1194 SRXAFSCB_ProbeUuid(struct rx_call *a_call, afsUUID * a_uuid)
1200 AFS_STATCNT(SRXAFSCB_Probe);
1202 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_PROBE);
1203 if (!afs_uuid_equal(a_uuid, &afs_cb_interface.uuid))
1204 code = 1; /* failure */
1213 /*------------------------------------------------------------------------
1214 * EXPORTED SRXAFSCB_GetServerPrefs
1217 * Routine to list server preferences used by this client.
1220 * a_call : Ptr to Rx call on which this request came in.
1221 * a_index : Input server index
1222 * a_srvr_addr : Output server address in host byte order
1223 * (0xffffffff on last server)
1224 * a_srvr_rank : Output server rank
1230 * Nothing interesting.
1234 *------------------------------------------------------------------------*/
1237 SRXAFSCB_GetServerPrefs(struct rx_call *a_call, afs_int32 a_index,
1238 afs_int32 * a_srvr_addr, afs_int32 * a_srvr_rank)
1244 AFS_STATCNT(SRXAFSCB_GetServerPrefs);
1246 ObtainReadLock(&afs_xserver);
1248 /* Search the hash table for the server with this index */
1249 *a_srvr_addr = 0xffffffff;
1250 *a_srvr_rank = 0xffffffff;
1251 for (i = 0, j = 0; j < NSERVERS && i <= a_index; j++) {
1252 for (sa = afs_srvAddrs[j]; sa && i <= a_index; sa = sa->next_bkt, i++) {
1254 *a_srvr_addr = ntohl(sa->sa_ip);
1255 *a_srvr_rank = sa->sa_iprank;
1260 ReleaseReadLock(&afs_xserver);
1268 /*------------------------------------------------------------------------
1269 * EXPORTED SRXAFSCB_GetCellServDB
1272 * Routine to list cells configured for this client
1275 * a_call : Ptr to Rx call on which this request came in.
1276 * a_index : Input cell index
1277 * a_name : Output cell name ("" on last cell)
1278 * a_hosts : Output cell database servers in host byte order.
1284 * Nothing interesting.
1288 *------------------------------------------------------------------------*/
1291 SRXAFSCB_GetCellServDB(struct rx_call *a_call, afs_int32 a_index,
1292 char **a_name, serverList * a_hosts)
1296 char *t_name, *p_name = NULL;
1299 AFS_STATCNT(SRXAFSCB_GetCellServDB);
1301 tcell = afs_GetCellByIndex(a_index, READ_LOCK);
1305 a_hosts->serverList_val = 0;
1306 a_hosts->serverList_len = 0;
1308 p_name = tcell->cellName;
1309 for (j = 0; j < AFSMAXCELLHOSTS && tcell->cellHosts[j]; j++);
1311 a_hosts->serverList_val =
1312 (afs_int32 *) afs_osi_Alloc(j * sizeof(afs_int32));
1313 a_hosts->serverList_len = j;
1314 for (j = 0; j < AFSMAXCELLHOSTS && tcell->cellHosts[j]; j++)
1315 a_hosts->serverList_val[j] =
1316 ntohl(tcell->cellHosts[j]->addr->sa_ip);
1317 afs_PutCell(tcell, READ_LOCK);
1320 t_name = (char *)afs_osi_Alloc(i + 1);
1321 if (t_name == NULL) {
1322 afs_osi_Free(a_hosts->serverList_val, (j * sizeof(afs_int32)));
1329 memcpy(t_name, p_name, i);
1338 /*------------------------------------------------------------------------
1339 * EXPORTED SRXAFSCB_GetLocalCell
1342 * Routine to return name of client's local cell
1345 * a_call : Ptr to Rx call on which this request came in.
1346 * a_name : Output cell name
1352 * Nothing interesting.
1356 *------------------------------------------------------------------------*/
1359 SRXAFSCB_GetLocalCell(struct rx_call *a_call, char **a_name)
1363 char *t_name, *p_name = NULL;
1366 AFS_STATCNT(SRXAFSCB_GetLocalCell);
1368 /* Search the list for the primary cell. Cell number 1 is only
1369 * the primary cell is when no other cell is explicitly marked as
1370 * the primary cell. */
1371 tcell = afs_GetPrimaryCell(READ_LOCK);
1373 p_name = tcell->cellName;
1375 plen = strlen(p_name);
1378 t_name = (char *)afs_osi_Alloc(plen + 1);
1379 if (t_name == NULL) {
1381 afs_PutCell(tcell, READ_LOCK);
1386 t_name[plen] = '\0';
1388 memcpy(t_name, p_name, plen);
1394 afs_PutCell(tcell, READ_LOCK);
1400 * afs_MarshallCacheConfig - marshall client cache configuration
1404 * IN callerVersion - the rpc stat version of the caller.
1406 * IN config - client cache configuration.
1408 * OUT ptr - buffer where configuration is marshalled.
1415 afs_MarshallCacheConfig(afs_uint32 callerVersion, cm_initparams_v1 * config,
1418 AFS_STATCNT(afs_MarshallCacheConfig);
1420 * We currently only support version 1.
1422 *(ptr++) = config->nChunkFiles;
1423 *(ptr++) = config->nStatCaches;
1424 *(ptr++) = config->nDataCaches;
1425 *(ptr++) = config->nVolumeCaches;
1426 *(ptr++) = config->firstChunkSize;
1427 *(ptr++) = config->otherChunkSize;
1428 *(ptr++) = config->cacheSize;
1429 *(ptr++) = config->setTime;
1430 *(ptr++) = config->memCache;
1434 /*------------------------------------------------------------------------
1435 * EXPORTED SRXAFSCB_GetCacheConfig
1438 * Routine to return parameters used to initialize client cache.
1439 * Client may request any format version. Server may not return
1440 * format version greater than version requested by client.
1443 * a_call: Ptr to Rx call on which this request came in.
1444 * callerVersion: Data format version desired by the client.
1445 * serverVersion: Data format version of output data.
1446 * configCount: Number bytes allocated for output data.
1447 * config: Client cache configuration.
1453 * Nothing interesting.
1457 *------------------------------------------------------------------------*/
1460 SRXAFSCB_GetCacheConfig(struct rx_call *a_call, afs_uint32 callerVersion,
1461 afs_uint32 * serverVersion, afs_uint32 * configCount,
1462 cacheConfig * config)
1464 afs_uint32 *t_config;
1466 cm_initparams_v1 cm_config;
1469 AFS_STATCNT(SRXAFSCB_GetCacheConfig);
1472 * Currently only support version 1
1474 allocsize = sizeof(cm_initparams_v1);
1475 t_config = (afs_uint32 *) afs_osi_Alloc(allocsize);
1476 if (t_config == NULL) {
1481 cm_config.nChunkFiles = cm_initParams.cmi_nChunkFiles;
1482 cm_config.nStatCaches = cm_initParams.cmi_nStatCaches;
1483 cm_config.nDataCaches = cm_initParams.cmi_nDataCaches;
1484 cm_config.nVolumeCaches = cm_initParams.cmi_nVolumeCaches;
1485 cm_config.firstChunkSize = cm_initParams.cmi_firstChunkSize;
1486 cm_config.otherChunkSize = cm_initParams.cmi_otherChunkSize;
1487 cm_config.cacheSize = cm_initParams.cmi_cacheSize;
1488 cm_config.setTime = cm_initParams.cmi_setTime;
1489 cm_config.memCache = cm_initParams.cmi_memCache;
1491 afs_MarshallCacheConfig(callerVersion, &cm_config, t_config);
1493 *serverVersion = AFS_CLIENT_RETRIEVAL_FIRST_EDITION;
1494 *configCount = allocsize;
1495 config->cacheConfig_val = t_config;
1496 config->cacheConfig_len = allocsize / sizeof(afs_uint32);
1503 /*------------------------------------------------------------------------
1504 * EXPORTED SRXAFSCB_FetchData
1507 * Routine to do third party move from a remioserver to the original
1508 * issuer of an ArchiveData request. Presently supported only by the
1509 * "fs" command, not by the AFS client.
1512 * rxcall: Ptr to Rx call on which this request came in.
1513 * Fid: pointer to AFSFid structure.
1514 * Fd: File descriptor inside fs command.
1515 * Position: Offset in the file.
1516 * Length: Data length to transfer.
1517 * TotalLength: Pointer to total file length field
1523 * Nothing interesting.
1526 *------------------------------------------------------------------------*/
1528 SRXAFSCB_FetchData(struct rx_call *rxcall, struct AFSFid *Fid, afs_int32 Fd,
1529 afs_int64 Position, afs_int64 Length,
1530 afs_int64 * TotalLength)
1535 /*------------------------------------------------------------------------
1536 * EXPORTED SRXAFSCB_StoreData
1539 * Routine to do third party move from a remioserver to the original
1540 * issuer of a RetrieveData request. Presently supported only by the
1541 * "fs" command, not by the AFS client.
1544 * rxcall: Ptr to Rx call on which this request came in.
1545 * Fid: pointer to AFSFid structure.
1546 * Fd: File descriptor inside fs command.
1547 * Position: Offset in the file.
1548 * Length: Data length to transfer.
1549 * TotalLength: Pointer to total file length field
1555 * Nothing interesting.
1559 *------------------------------------------------------------------------*/
1561 SRXAFSCB_StoreData(struct rx_call *rxcall, struct AFSFid *Fid, afs_int32 Fd,
1562 afs_int64 Position, afs_int64 Length,
1563 afs_int64 * TotalLength)
1568 /*------------------------------------------------------------------------
1569 * EXPORTED SRXAFSCB_GetCellByNum
1572 * Routine to get information about a cell specified by its
1573 * cell number (returned by GetCE/GetCE64).
1576 * a_call : Ptr to Rx call on which this request came in.
1577 * a_cellnum : Input cell number
1578 * a_name : Output cell name (one zero byte when no such cell).
1579 * a_hosts : Output cell database servers in host byte order.
1585 * Nothing interesting.
1589 *------------------------------------------------------------------------*/
1592 SRXAFSCB_GetCellByNum(struct rx_call *a_call, afs_int32 a_cellnum,
1593 char **a_name, serverList * a_hosts)
1599 AFS_STATCNT(SRXAFSCB_GetCellByNum);
1601 a_hosts->serverList_val = 0;
1602 a_hosts->serverList_len = 0;
1604 tcell = afs_GetCellStale(a_cellnum, READ_LOCK);
1606 *a_name = afs_strdup("");
1611 ObtainReadLock(&tcell->lock);
1612 *a_name = afs_strdup(tcell->cellName);
1614 for (sn = 0; sn < AFSMAXCELLHOSTS && tcell->cellHosts[sn]; sn++);
1615 a_hosts->serverList_len = sn;
1616 a_hosts->serverList_val =
1617 (afs_int32 *) afs_osi_Alloc(sn * sizeof(afs_int32));
1619 for (i = 0; i < sn; i++)
1620 a_hosts->serverList_val[i] = ntohl(tcell->cellHosts[i]->addr->sa_ip);
1621 ReleaseReadLock(&tcell->lock);
1622 afs_PutCell(tcell, READ_LOCK);
1629 SRXAFSCB_TellMeAboutYourself(struct rx_call *a_call,
1630 struct interfaceAddr *addr,
1631 Capabilities * capabilities)
1635 afs_int32 *dataBuffP;
1636 afs_int32 dataBytes;
1640 AFS_STATCNT(SRXAFSCB_WhoAreYou);
1642 ObtainReadLock(&afs_xinterface);
1644 /* return all network interface addresses */
1645 addr->numberOfInterfaces = afs_cb_interface.numberOfInterfaces;
1646 addr->uuid = afs_cb_interface.uuid;
1647 for (i = 0; i < afs_cb_interface.numberOfInterfaces; i++) {
1648 addr->addr_in[i] = ntohl(afs_cb_interface.addr_in[i]);
1649 addr->subnetmask[i] = ntohl(afs_cb_interface.subnetmask[i]);
1650 addr->mtu[i] = ntohl(afs_cb_interface.mtu[i]);
1653 ReleaseReadLock(&afs_xinterface);
1657 dataBytes = 1 * sizeof(afs_int32);
1658 dataBuffP = (afs_int32 *) afs_osi_Alloc(dataBytes);
1659 dataBuffP[0] = CLIENT_CAPABILITY_ERRORTRANS;
1660 capabilities->Capabilities_len = dataBytes / sizeof(afs_int32);
1661 capabilities->Capabilities_val = dataBuffP;
1667 #if 0 && defined(AFS_LINUX24_ENV)
1668 extern struct vcache *afs_globalVp;
1670 int recurse_dcache_parent(parent, a_index, addr, inode, flags, time, fileName)
1671 struct dentry * parent;
1679 struct dentry *this_parent = parent;
1680 struct list_head *next;
1682 struct dentry *dentry;
1685 next = this_parent->d_subdirs.next;
1687 while (next != &this_parent->d_subdirs) {
1688 struct list_head *tmp = next;
1689 dentry = list_entry(tmp, struct dentry, d_child);
1695 * Descend a level if the d_subdirs list is non-empty.
1697 if (!list_empty(&dentry->d_subdirs)) {
1698 this_parent = dentry;
1703 * All done at this level ... ascend and resume the search.
1705 if (this_parent != parent) {
1706 next = this_parent->d_child.next;
1707 this_parent = this_parent->d_parent;
1713 if (d_unhashed(dentry))
1718 *fileName = afs_strdup(dentry->d_name.name?dentry->d_name.name:"");
1719 *inode = ITOAFS(dentry->d_inode);
1720 *addr = atomic_read(&(dentry)->d_count);
1721 *time = dentry->d_time;
1729 int SRXAFSCB_GetDE(a_call, a_index, addr, inode, flags, time, fileName)
1730 struct rx_call *a_call;
1737 { /*SRXAFSCB_GetDE*/
1738 int code = 0; /*Return code*/
1739 #if 0 && defined(AFS_LINUX24_ENV)
1740 register int i; /*Loop variable*/
1741 register struct vcache *tvc = afs_globalVp;
1742 struct dentry *dentry;
1743 struct list_head *cur, *head = &(AFSTOI(tvc))->i_dentry;
1745 #ifdef RX_ENABLE_LOCKS
1747 #endif /* RX_ENABLE_LOCKS */
1749 #if defined(AFS_LINUX24_ENV)
1750 spin_lock(&dcache_lock);
1754 while ((cur = cur->next) != head) {
1755 dentry = list_entry(cur, struct dentry, d_alias);
1757 dget_locked(dentry);
1759 #if defined(AFS_LINUX24_ENV)
1760 spin_unlock(&dcache_lock);
1766 if (recurse_dcache_parent(dentry, a_index, addr, inode, flags, time, fileName) == 0) {
1777 *fileName = afs_strdup("");
1781 if (d_unhashed(dentry))
1786 *fileName = afs_strdup(dentry->d_name.name?dentry->d_name.name:"");
1787 *inode = ITOAFS(dentry->d_inode);
1788 *addr = atomic_read(&(dentry)->d_count);
1789 *time = dentry->d_time;
1796 #ifdef RX_ENABLE_LOCKS
1798 #endif /* RX_ENABLE_LOCKS */
1802 } /*SRXAFSCB_GetDE*/