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
10 #include <afs/param.h>
11 #include <afs/afs_args.h>
23 #include <rx_pthread.h>
25 #include <WINNT/syscfg.h>
26 #include <WINNT/afsreg.h>
29 SRXAFSCB_InitCallBackState3(struct rx_call *callp, afsUUID* serverUuid);
31 /* read/write lock for all global storage in this module */
32 osi_rwlock_t cm_callbackLock;
34 afs_int32 cm_OfflineROIsValid = 0;
36 afs_int32 cm_giveUpAllCBs = 0;
38 afs_int32 cm_shutdown = 0;
40 #ifdef AFS_FREELANCE_CLIENT
41 extern osi_mutex_t cm_Freelance_Lock;
44 /* count of # of callback breaking messages received by this CM so far. We use
45 * this count in determining whether there have been any callback breaks that
46 * apply to a call that returned a new callback. If the counter doesn't
47 * increase during a call, then we know that no callbacks were broken during
48 * that call, and thus that the callback that was just returned is still valid.
50 long cm_callbackCount;
52 /* count of number of RPCs potentially returning a callback executing now.
53 * When this counter hits zero, we can clear out the racing revokes list, since
54 * at that time, we know that none of the just-executed callback revokes will
55 * apply to any future call that returns a callback (since the latter hasn't
56 * even started execution yet).
58 long cm_activeCallbackGrantingCalls;
60 /* list of callbacks that have been broken recently. If a call returning a
61 * callback is executing and a callback revoke runs immediately after it at the
62 * server, the revoke may end up being processed before the response to the
63 * original callback granting call. We detect this by keeping a list of
64 * callback revokes that have been received since we *started* the callback
65 * granting call, and discarding any callbacks received for the same file ID,
66 * even if the callback revoke was received before the callback grant.
68 cm_racingRevokes_t *cm_racingRevokesp;
70 /* record a (potentially) racing revoke for this file ID; null means for all
71 * file IDs, and is used by InitCallBackState.
73 * The cancelFlags describe whether we're just discarding callbacks for the same
74 * file ID, the same volume, or all from the same server.
76 * Called with no locks held.
78 void cm_RecordRacingRevoke(cm_fid_t *fidp, long cancelFlags)
80 cm_racingRevokes_t *rp;
82 lock_ObtainWrite(&cm_callbackLock);
84 osi_Log3(afsd_logp, "RecordRacingRevoke Volume %d Flags %lX activeCalls %d",
85 fidp ? fidp->volume : 0, cancelFlags, cm_activeCallbackGrantingCalls);
87 if (cm_activeCallbackGrantingCalls > 0) {
88 rp = malloc(sizeof(*rp));
89 memset(rp, 0, sizeof(*rp));
90 osi_QAdd((osi_queue_t **) &cm_racingRevokesp, &rp->q);
91 rp->flags |= (cancelFlags & CM_RACINGFLAG_ALL);
92 if (fidp) rp->fid = *fidp;
93 rp->callbackCount = ++cm_callbackCount;
95 lock_ReleaseWrite(&cm_callbackLock);
99 * When we lose a callback, may have to send change notification replies.
100 * Do not call with a lock on the scp.
102 void cm_CallbackNotifyChange(cm_scache_t *scp)
108 /* why does this have to query the registry each time? */
109 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
110 AFSREG_CLT_OPENAFS_SUBKEY,
112 KEY_READ|KEY_QUERY_VALUE,
113 &hKey) == ERROR_SUCCESS) {
115 dummyLen = sizeof(DWORD);
116 RegQueryValueEx(hKey, "CallBack Notify Change Delay", NULL, NULL,
117 (BYTE *) &dwDelay, &dummyLen);
121 if (dwDelay > 5000) /* do not allow a delay of more then 5 seconds */
124 osi_Log3(afsd_logp, "CallbackNotifyChange FileType %d Flags %lX Delay %dms",
125 scp->fileType, scp->flags, dwDelay);
130 /* for directories, this sends a change notification on the dir itself */
131 if (scp->fileType == CM_SCACHETYPE_DIRECTORY) {
132 if (scp->flags & CM_SCACHEFLAG_ANYWATCH)
134 FILE_NOTIFY_GENERIC_DIRECTORY_FILTER,
135 scp, NULL, NULL, TRUE);
137 /* and for files, this sends a change notification on the file's parent dir */
141 cm_SetFid(&tfid, scp->fid.cell, scp->fid.volume, scp->parentVnode, scp->parentUnique);
142 dscp = cm_FindSCache(&tfid);
144 dscp->flags & CM_SCACHEFLAG_ANYWATCH )
146 FILE_NOTIFY_GENERIC_FILE_FILTER,
147 dscp, NULL, NULL, TRUE);
149 cm_ReleaseSCache(dscp);
153 /* called with no locks held for every file ID that is revoked directly by
154 * a callback revoke call. Does not have to handle volume callback breaks,
155 * since those have already been split out.
157 * The callp parameter is currently unused.
159 void cm_RevokeCallback(struct rx_call *callp, cm_cell_t * cellp, AFSFid *fidp)
165 tfid.cell = cellp ? cellp->cellID : 0;
166 tfid.volume = fidp->Volume;
167 tfid.vnode = fidp->Vnode;
168 tfid.unique = fidp->Unique;
169 hash = CM_SCACHE_HASH(&tfid);
171 osi_Log3(afsd_logp, "RevokeCallback vol %u vn %u uniq %u",
172 fidp->Volume, fidp->Vnode, fidp->Unique);
174 /* do this first, so that if we're executing a callback granting call
175 * at this moment, we kill it before it can be merged in. Otherwise,
176 * it could complete while we're doing the scan below, and get missed
177 * by both the scan and by this code.
179 cm_RecordRacingRevoke(&tfid, 0);
181 lock_ObtainWrite(&cm_scacheLock);
182 /* do all in the hash bucket, since we don't know how many we'll find with
185 for (scp = cm_data.scacheHashTablep[hash]; scp; scp=scp->nextp) {
186 if (scp->fid.volume == tfid.volume &&
187 scp->fid.vnode == tfid.vnode &&
188 scp->fid.unique == tfid.unique &&
189 (cellp == NULL || scp->fid.cell == cellp->cellID) &&
190 cm_HaveCallback(scp))
192 cm_HoldSCacheNoLock(scp);
193 lock_ReleaseWrite(&cm_scacheLock);
194 osi_Log4(afsd_logp, "RevokeCallback Discarding SCache scp 0x%p vol %u vn %u uniq %u",
195 scp, scp->fid.volume, scp->fid.vnode, scp->fid.unique);
197 lock_ObtainWrite(&scp->rw);
198 cm_DiscardSCache(scp);
199 lock_ReleaseWrite(&scp->rw);
201 cm_CallbackNotifyChange(scp);
203 lock_ObtainWrite(&cm_scacheLock);
204 cm_ReleaseSCacheNoLock(scp);
207 lock_ReleaseWrite(&cm_scacheLock);
209 osi_Log3(afsd_logp, "RevokeCallback Complete vol %u vn %u uniq %u",
210 fidp->Volume, fidp->Vnode, fidp->Unique);
214 cm_callbackDiscardROVolumeByFID(cm_fid_t *fidp)
216 cm_volume_t *volp = cm_GetVolumeByFID(fidp);
219 if (volp->cbExpiresRO) {
220 volp->cbExpiresRO = 0;
221 if (volp->cbServerpRO) {
222 cm_PutServer(volp->cbServerpRO);
223 volp->cbServerpRO = NULL;
225 volp->creationDateRO = 0;
230 /* called to revoke a volume callback, which is typically issued when a volume
231 * is moved from one server to another.
233 * Called with no locks held.
235 void cm_RevokeVolumeCallback(struct rx_call *callp, cm_cell_t *cellp, AFSFid *fidp)
241 osi_Log1(afsd_logp, "RevokeVolumeCallback vol %d", fidp->Volume);
243 /* do this first, so that if we're executing a callback granting call
244 * at this moment, we kill it before it can be merged in. Otherwise,
245 * it could complete while we're doing the scan below, and get missed
246 * by both the scan and by this code.
248 tfid.cell = cellp ? cellp->cellID : 0;
249 tfid.volume = fidp->Volume;
250 tfid.vnode = tfid.unique = 0;
252 cm_RecordRacingRevoke(&tfid, CM_RACINGFLAG_CANCELVOL);
254 lock_ObtainWrite(&cm_scacheLock);
255 for (hash = 0; hash < cm_data.scacheHashTableSize; hash++) {
256 for(scp=cm_data.scacheHashTablep[hash]; scp; scp=scp->nextp) {
257 if (scp->fid.volume == fidp->Volume &&
258 (cellp == NULL || scp->fid.cell == cellp->cellID) &&
259 scp->cbExpires > 0 &&
260 scp->cbServerp != NULL) {
261 cm_HoldSCacheNoLock(scp);
262 lock_ReleaseWrite(&cm_scacheLock);
264 lock_ObtainWrite(&scp->rw);
265 osi_Log4(afsd_logp, "RevokeVolumeCallback Discarding SCache scp 0x%p vol %u vn %u uniq %u",
266 scp, scp->fid.volume, scp->fid.vnode, scp->fid.unique);
267 cm_DiscardSCache(scp);
268 lock_ReleaseWrite(&scp->rw);
270 cm_CallbackNotifyChange(scp);
271 lock_ObtainWrite(&cm_scacheLock);
272 cm_ReleaseSCacheNoLock(scp);
273 if (scp->flags & CM_SCACHEFLAG_PURERO)
274 cm_callbackDiscardROVolumeByFID(&scp->fid);
276 } /* search one hash bucket */
277 } /* search all hash buckets */
279 lock_ReleaseWrite(&cm_scacheLock);
281 osi_Log1(afsd_logp, "RevokeVolumeCallback Complete vol %d", fidp->Volume);
285 * afs_data_pointer_to_int32() - returns least significant afs_int32 of the
286 * given data pointer, without triggering "cast truncates pointer"
287 * warnings. We use this where we explicitly don't care whether a
288 * pointer is truncated -- it loses information where a pointer is
289 * larger than an afs_int32.
293 afs_data_pointer_to_int32(const void *p)
296 afs_int32 i32[sizeof(void *) / sizeof(afs_int32)];
300 int i32_sub; /* subscript of least significant afs_int32 in ip.i32[] */
305 /* used to determine the byte order of the system */
308 char c[sizeof(int) / sizeof(char)];
314 /* little-endian system */
317 /* big-endian system */
318 i32_sub = (sizeof ip.i32 / sizeof ip.i32[0]) - 1;
323 return ip.i32[i32_sub];
325 /*------------------------------------------------------------------------
326 * EXPORTED SRXAFSCB_CallBack
329 * Routine called by the server-side callback RPC interface to
330 * implement passing in callback information.
334 * rx_call : Ptr to Rx call on which this request came in.
335 * fidsArrayp : Ptr to array of fids involved.
336 * cbsArrayp : Ptr to matching callback info for the fids.
342 * Nothing interesting.
346 *------------------------------------------------------------------------*/
347 /* handle incoming RPC callback breaking message.
348 * Called with no locks held.
351 SRXAFSCB_CallBack(struct rx_call *callp, AFSCBFids *fidsArrayp, AFSCBs *cbsArrayp)
355 struct rx_connection *connp;
356 struct rx_peer *peerp;
357 unsigned long host = 0;
358 unsigned short port = 0;
359 cm_server_t *tsp = NULL;
360 cm_cell_t* cellp = NULL;
365 if ((connp = rx_ConnectionOf(callp)) && (peerp = rx_PeerOf(connp))) {
366 host = rx_HostOf(peerp);
367 port = rx_PortOf(peerp);
369 tsp = cm_FindServerByIP(host, port, CM_SERVER_FILE);
376 osi_Log2(afsd_logp, "SRXAFSCB_CallBack from host 0x%x port %d",
380 osi_Log3(afsd_logp, "SRXAFSCB_CallBack from host 0x%x port %d for cell %s",
383 cellp->name /* does not need to be saved, doesn't change */);
385 osi_Log0(afsd_logp, "SRXAFSCB_CallBack from unknown host");
389 for (i=0; i < (long) fidsArrayp->AFSCBFids_len; i++) {
390 tfidp = &fidsArrayp->AFSCBFids_val[i];
392 if (tfidp->Volume == 0)
393 continue; /* means don't do anything */
394 else if (tfidp->Vnode == 0)
395 cm_RevokeVolumeCallback(callp, cellp, tfidp);
397 cm_RevokeCallback(callp, cellp, tfidp);
402 /*------------------------------------------------------------------------
403 * EXPORTED SRXAFSCB_InitCallBackState
406 * Routine called by the server-side callback RPC interface to
407 * implement clearing all callbacks from this host.
410 * rx_call : Ptr to Rx call on which this request came in.
416 * Nothing interesting.
420 *------------------------------------------------------------------------*/
421 /* called with no locks by RPC system when a server indicates that it has never
422 * heard from us, or for other reasons has had to discard callbacks from us
423 * without telling us, e.g. a network partition.
426 SRXAFSCB_InitCallBackState(struct rx_call *callp)
431 osi_Log0(afsd_logp, "SRXAFSCB_InitCallBackState ->");
433 return SRXAFSCB_InitCallBackState3(callp, NULL);
436 /*------------------------------------------------------------------------
437 * EXPORTED SRXAFSCB_Probe
440 * Routine called by the server-side callback RPC interface to
441 * implement ``probing'' the Cache Manager, just making sure it's
445 * rx_call : Ptr to Rx call on which this request came in.
451 * Nothing interesting.
455 *------------------------------------------------------------------------*/
457 SRXAFSCB_Probe(struct rx_call *callp)
459 struct rx_connection *connp;
460 struct rx_peer *peerp;
461 unsigned long host = 0;
462 unsigned short port = 0;
467 if ((connp = rx_ConnectionOf(callp)) && (peerp = rx_PeerOf(connp))) {
468 host = rx_HostOf(peerp);
469 port = rx_PortOf(peerp);
472 osi_Log2(afsd_logp, "SRXAFSCB_Probe from host 0x%x port %d",
479 /*------------------------------------------------------------------------
480 * EXPORTED SRXAFSCB_GetLock
483 * Routine called by the server-side callback RPC interface to
484 * implement pulling out the contents of a lock in the lock
488 * a_call : Ptr to Rx call on which this request came in.
489 * a_index : Index of desired lock.
490 * a_result : Ptr to a buffer for the given lock.
493 * 0 if everything went fine,
494 * 1 if we were given a bad index.
497 * Nothing interesting.
501 *------------------------------------------------------------------------*/
502 /* debug interface */
504 extern osi_rwlock_t cm_aclLock;
505 extern osi_rwlock_t buf_globalLock;
506 extern osi_rwlock_t cm_cellLock;
507 extern osi_rwlock_t cm_connLock;
508 extern osi_rwlock_t cm_daemonLock;
509 extern osi_rwlock_t cm_dnlcLock;
510 extern osi_rwlock_t cm_scacheLock;
511 extern osi_rwlock_t cm_serverLock;
512 extern osi_rwlock_t cm_syscfgLock;
513 extern osi_rwlock_t cm_userLock;
514 extern osi_rwlock_t cm_utilsLock;
515 extern osi_rwlock_t cm_volumeLock;
516 extern osi_rwlock_t smb_globalLock;
517 extern osi_rwlock_t smb_rctLock;
519 extern osi_mutex_t cm_Freelance_Lock;
520 extern osi_mutex_t cm_Afsdsbmt_Lock;
521 extern osi_mutex_t tokenEventLock;
522 extern osi_mutex_t smb_ListenerLock;
523 extern osi_mutex_t smb_RawBufLock;
524 extern osi_mutex_t smb_Dir_Watch_Lock;
526 #define LOCKTYPE_RW 1
527 #define LOCKTYPE_MUTEX 2
528 static struct _ltable {
533 {"cm_scacheLock", (char*)&cm_scacheLock, LOCKTYPE_RW},
534 {"buf_globalLock", (char*)&buf_globalLock, LOCKTYPE_RW},
535 {"cm_serverLock", (char*)&cm_serverLock, LOCKTYPE_RW},
536 {"cm_callbackLock", (char*)&cm_callbackLock, LOCKTYPE_RW},
537 {"cm_syscfgLock", (char*)&cm_syscfgLock, LOCKTYPE_RW},
538 {"cm_aclLock", (char*)&cm_aclLock, LOCKTYPE_RW},
539 {"cm_cellLock", (char*)&cm_cellLock, LOCKTYPE_RW},
540 {"cm_connLock", (char*)&cm_connLock, LOCKTYPE_RW},
541 {"cm_userLock", (char*)&cm_userLock, LOCKTYPE_RW},
542 {"cm_volumeLock", (char*)&cm_volumeLock, LOCKTYPE_RW},
543 {"cm_daemonLock", (char*)&cm_daemonLock, LOCKTYPE_RW},
544 {"cm_dnlcLock", (char*)&cm_dnlcLock, LOCKTYPE_RW},
545 {"cm_utilsLock", (char*)&cm_utilsLock, LOCKTYPE_RW},
546 {"smb_globalLock", (char*)&smb_globalLock, LOCKTYPE_RW},
547 {"smb_rctLock", (char*)&smb_rctLock, LOCKTYPE_RW},
548 {"cm_Freelance_Lock",(char*)&cm_Freelance_Lock, LOCKTYPE_MUTEX},
549 {"cm_Afsdsbmt_Lock", (char*)&cm_Afsdsbmt_Lock, LOCKTYPE_MUTEX},
550 {"tokenEventLock", (char*)&tokenEventLock, LOCKTYPE_MUTEX},
551 {"smb_ListenerLock", (char*)&smb_ListenerLock, LOCKTYPE_MUTEX},
552 {"smb_RawBufLock", (char*)&smb_RawBufLock, LOCKTYPE_MUTEX},
553 {"smb_Dir_Watch_Lock",(char*)&smb_Dir_Watch_Lock, LOCKTYPE_MUTEX}
557 SRXAFSCB_GetLock(struct rx_call *callp, long index, AFSDBLock *lockp)
559 struct _ltable *tl; /*Ptr to lock table entry */
562 int nentries; /*Num entries in table */
563 int code; /*Return code */
564 struct rx_connection *connp;
565 struct rx_peer *peerp;
566 unsigned long host = 0;
567 unsigned short port = 0;
572 if ((connp = rx_ConnectionOf(callp)) && (peerp = rx_PeerOf(connp))) {
573 host = rx_HostOf(peerp);
574 port = rx_PortOf(peerp);
577 osi_Log3(afsd_logp, "SRXAFSCB_GetLock(%d) from host 0x%x port %d",
578 index, ntohl(host), ntohs(port));
580 nentries = sizeof(ltable) / sizeof(struct _ltable);
581 if (index < 0 || index >= nentries) {
588 * Found it - copy out its contents.
591 strncpy(lockp->name, tl->name, sizeof(lockp->name));
592 lockp->name[sizeof(lockp->name)-1] = '\0';
593 lockp->lock.waitStates = 0;
594 switch ( tl->type ) {
596 rwp = (osi_rwlock_t *)tl->addr;
597 lockp->lock.exclLocked = rwp->flags;
598 lockp->lock.readersReading = rwp->readers;
599 lockp->lock.numWaiting = rwp->waiters;
602 mtxp = (osi_mutex_t *)tl->addr;
603 lockp->lock.exclLocked = mtxp->flags;
604 lockp->lock.readersReading = 0;
605 lockp->lock.numWaiting = mtxp->waiters;
608 lockp->lock.pid_last_reader = 0;
609 lockp->lock.pid_writer = 0;
610 lockp->lock.src_indicator = 0;
617 /* debug interface */
619 SRXAFSCB_GetCE(struct rx_call *callp, long index, AFSDBCacheEntry *cep)
624 struct rx_connection *connp;
625 struct rx_peer *peerp;
626 unsigned long host = 0;
627 unsigned short port = 0;
632 if ((connp = rx_ConnectionOf(callp)) && (peerp = rx_PeerOf(connp))) {
633 host = rx_HostOf(peerp);
634 port = rx_PortOf(peerp);
637 osi_Log2(afsd_logp, "SRXAFSCB_GetCE from host 0x%x port %d",
638 ntohl(host), ntohs(port));
640 lock_ObtainRead(&cm_scacheLock);
641 for (i = 0; i < cm_data.scacheHashTableSize; i++) {
642 for (scp = cm_data.scacheHashTablep[i]; scp; scp = scp->nextp) {
646 } /*Zip through current hash chain */
647 } /*Zip through hash chains */
657 * Copy out the located entry.
659 memset(cep, 0, sizeof(AFSDBCacheEntry));
660 cep->addr = afs_data_pointer_to_int32(scp);
661 cep->cell = scp->fid.cell;
662 cep->netFid.Volume = scp->fid.volume;
663 cep->netFid.Vnode = scp->fid.vnode;
664 cep->netFid.Unique = scp->fid.unique;
665 cep->lock.waitStates = 0;
666 cep->lock.exclLocked = scp->rw.flags;
667 cep->lock.readersReading = 0;
668 cep->lock.numWaiting = scp->rw.waiters;
669 cep->lock.pid_last_reader = 0;
670 cep->lock.pid_writer = 0;
671 cep->lock.src_indicator = 0;
672 cep->Length = scp->length.LowPart;
673 cep->DataVersion = (afs_uint32)(scp->dataVersion & 0xFFFFFFFF);
674 cep->callback = afs_data_pointer_to_int32(scp->cbServerp);
675 if (scp->flags & CM_SCACHEFLAG_PURERO) {
676 cm_volume_t *volp = cm_GetVolumeByFID(&scp->fid);
678 cep->cbExpires = volp->cbExpiresRO;
682 /* TODO: deal with time_t below */
683 cep->cbExpires = (afs_int32) scp->cbExpires;
685 cep->refCount = scp->refCount;
686 cep->opens = scp->openReads;
687 cep->writers = scp->openWrites;
688 switch (scp->fileType) {
689 case CM_SCACHETYPE_FILE:
692 case CM_SCACHETYPE_MOUNTPOINT:
695 case CM_SCACHETYPE_DIRECTORY:
696 if (scp->fid.vnode == 1 && scp->fid.unique == 1)
701 case CM_SCACHETYPE_SYMLINK:
704 case CM_SCACHETYPE_DFSLINK:
707 case CM_SCACHETYPE_INVALID:
712 if (scp->flags & CM_SCACHEFLAG_STATD)
714 if (scp->flags & CM_SCACHEFLAG_RO || scp->flags & CM_SCACHEFLAG_PURERO)
716 if (scp->fileType == CM_SCACHETYPE_MOUNTPOINT &&
717 scp->mountPointStringp[0])
719 if (scp->flags & CM_SCACHEFLAG_WAITING)
724 * Return our results.
727 lock_ReleaseRead(&cm_scacheLock);
732 /* debug interface */
734 SRXAFSCB_GetCE64(struct rx_call *callp, long index, AFSDBCacheEntry64 *cep)
739 struct rx_connection *connp;
740 struct rx_peer *peerp;
741 unsigned long host = 0;
742 unsigned short port = 0;
747 if ((connp = rx_ConnectionOf(callp)) && (peerp = rx_PeerOf(connp))) {
748 host = rx_HostOf(peerp);
749 port = rx_PortOf(peerp);
752 osi_Log2(afsd_logp, "SRXAFSCB_GetCE64 from host 0x%x port %d",
753 ntohl(host), ntohs(port));
755 lock_ObtainRead(&cm_scacheLock);
756 for (i = 0; i < cm_data.scacheHashTableSize; i++) {
757 for (scp = cm_data.scacheHashTablep[i]; scp; scp = scp->nextp) {
761 } /*Zip through current hash chain */
762 } /*Zip through hash chains */
772 * Copy out the located entry.
774 memset(cep, 0, sizeof(AFSDBCacheEntry64));
775 cep->addr = afs_data_pointer_to_int32(scp);
776 cep->cell = scp->fid.cell;
777 cep->netFid.Volume = scp->fid.volume;
778 cep->netFid.Vnode = scp->fid.vnode;
779 cep->netFid.Unique = scp->fid.unique;
780 cep->lock.waitStates = 0;
781 cep->lock.exclLocked = scp->rw.flags;
782 cep->lock.readersReading = 0;
783 cep->lock.numWaiting = scp->rw.waiters;
784 cep->lock.pid_last_reader = 0;
785 cep->lock.pid_writer = 0;
786 cep->lock.src_indicator = 0;
787 #if !defined(AFS_64BIT_ENV)
788 cep->Length.high = scp->length.HighPart;
789 cep->Length.low = scp->length.LowPart;
791 cep->Length = (afs_int64) scp->length.QuadPart;
793 cep->DataVersion = (afs_uint32)(scp->dataVersion & 0xFFFFFFFF);
794 cep->callback = afs_data_pointer_to_int32(scp->cbServerp);
795 if (scp->flags & CM_SCACHEFLAG_PURERO) {
796 cm_volume_t *volp = cm_GetVolumeByFID(&scp->fid);
798 cep->cbExpires = volp->cbExpiresRO;
802 /* TODO: handle time_t */
803 cep->cbExpires = (afs_int32) scp->cbExpires;
805 cep->refCount = scp->refCount;
806 cep->opens = scp->openReads;
807 cep->writers = scp->openWrites;
808 switch (scp->fileType) {
809 case CM_SCACHETYPE_FILE:
812 case CM_SCACHETYPE_MOUNTPOINT:
815 case CM_SCACHETYPE_DIRECTORY:
816 if (scp->fid.vnode == 1 && scp->fid.unique == 1)
821 case CM_SCACHETYPE_SYMLINK:
824 case CM_SCACHETYPE_DFSLINK:
827 case CM_SCACHETYPE_INVALID:
832 if (scp->flags & CM_SCACHEFLAG_STATD)
834 if (scp->flags & CM_SCACHEFLAG_RO || scp->flags & CM_SCACHEFLAG_PURERO)
836 if (scp->fileType == CM_SCACHETYPE_MOUNTPOINT &&
837 scp->mountPointStringp[0])
839 if (scp->flags & CM_SCACHEFLAG_WAITING)
844 * Return our results.
847 lock_ReleaseRead(&cm_scacheLock);
852 /* debug interface: not implemented */
854 SRXAFSCB_XStatsVersion(struct rx_call *callp, long *vp)
856 struct rx_connection *connp;
857 struct rx_peer *peerp;
858 unsigned long host = 0;
859 unsigned short port = 0;
864 if ((connp = rx_ConnectionOf(callp)) && (peerp = rx_PeerOf(connp))) {
865 host = rx_HostOf(peerp);
866 port = rx_PortOf(peerp);
869 osi_Log2(afsd_logp, "SRXAFSCB_XStatsVersion from host 0x%x port %d - not implemented",
870 ntohl(host), ntohs(port));
876 /* debug interface: not implemented */
878 SRXAFSCB_GetXStats(struct rx_call *callp, long cvn, long coln, long *srvp, long *timep,
879 AFSCB_CollData *datap)
881 struct rx_connection *connp;
882 struct rx_peer *peerp;
883 unsigned long host = 0;
884 unsigned short port = 0;
889 if ((connp = rx_ConnectionOf(callp)) && (peerp = rx_PeerOf(connp))) {
890 host = rx_HostOf(peerp);
891 port = rx_PortOf(peerp);
894 osi_Log2(afsd_logp, "SRXAFSCB_GetXStats from host 0x%x port %d - not implemented",
895 ntohl(host), ntohs(port));
901 SRXAFSCB_InitCallBackState2(struct rx_call *callp, struct interfaceAddr* addr)
906 osi_Log0(afsd_logp, "SRXAFSCB_InitCallBackState2 ->");
908 return SRXAFSCB_InitCallBackState3(callp, NULL);
911 /* debug interface */
913 SRXAFSCB_WhoAreYou(struct rx_call *callp, struct interfaceAddr* addr)
917 struct rx_connection *connp;
918 struct rx_peer *peerp;
919 unsigned long host = 0;
920 unsigned short port = 0;
925 if ((connp = rx_ConnectionOf(callp)) && (peerp = rx_PeerOf(connp))) {
926 host = rx_HostOf(peerp);
927 port = rx_PortOf(peerp);
930 osi_Log2(afsd_logp, "SRXAFSCB_WhoAreYou from host 0x%x port %d",
934 lock_ObtainRead(&cm_syscfgLock);
935 if (cm_LanAdapterChangeDetected) {
936 lock_ConvertRToW(&cm_syscfgLock);
937 if (cm_LanAdapterChangeDetected) {
938 /* get network related info */
939 cm_noIPAddr = CM_MAXINTERFACE_ADDR;
940 code = syscfg_GetIFInfo(&cm_noIPAddr,
941 cm_IPAddr, cm_SubnetMask,
942 cm_NetMtu, cm_NetFlags);
943 cm_LanAdapterChangeDetected = 0;
945 lock_ConvertWToR(&cm_syscfgLock);
948 /* return all network interface addresses */
949 addr->numberOfInterfaces = cm_noIPAddr;
950 addr->uuid = cm_data.Uuid;
951 for ( i=0; i < cm_noIPAddr; i++ ) {
952 addr->addr_in[i] = cm_IPAddr[i];
953 addr->subnetmask[i] = cm_SubnetMask[i];
954 addr->mtu[i] = (rx_mtu == -1 || (rx_mtu != -1 && cm_NetMtu[i] < rx_mtu)) ?
955 cm_NetMtu[i] : rx_mtu;
958 lock_ReleaseRead(&cm_syscfgLock);
964 SRXAFSCB_InitCallBackState3(struct rx_call *callp, afsUUID* serverUuid)
968 struct sockaddr_in taddr;
969 cm_server_t *tsp = NULL;
970 cm_scache_t *scp = NULL;
971 cm_cell_t* cellp = NULL;
974 struct rx_connection *connp;
975 struct rx_peer *peerp;
976 unsigned long host = 0;
977 unsigned short port = 0;
982 if ((connp = rx_ConnectionOf(callp)) && (peerp = rx_PeerOf(connp))) {
983 host = rx_HostOf(peerp);
984 port = rx_PortOf(peerp);
987 if (UuidToString((UUID *)serverUuid, &p) == RPC_S_OK) {
988 osi_Log1(afsd_logp, "SRXAFSCB_InitCallBackState3 Uuid%s ->",osi_LogSaveString(afsd_logp,p));
992 tsp = cm_FindServerByUuid(serverUuid, CM_SERVER_FILE);
995 tsp = cm_FindServerByIP(host, port, CM_SERVER_FILE);
1002 osi_Log2(afsd_logp, "SRXAFSCB_InitCallBackState3 from host 0x%x port %d",
1006 osi_Log3(afsd_logp, "SRXAFSCB_InitCallBackState3 from host 0x%x port %d for cell %s",
1009 cellp->name /* does not need to be saved, doesn't change */);
1011 osi_Log0(afsd_logp, "SRXAFSCB_InitCallBackState3 from unknown host");
1014 if (connp && peerp) {
1015 taddr.sin_family = AF_INET;
1016 taddr.sin_addr.s_addr = rx_HostOf(rx_PeerOf(rx_ConnectionOf(callp)));
1017 taddr.sin_port = rx_PortOf(rx_PeerOf(rx_ConnectionOf(callp)));
1019 tsp = cm_FindServer(&taddr, CM_SERVER_FILE);
1021 osi_Log1(afsd_logp, "InitCallbackState3 server %x", tsp);
1023 /* record the callback in the racing revokes structure. This
1024 * shouldn't be necessary, since we shouldn't be making callback
1025 * granting calls while we're going to get an initstate call,
1026 * but there probably are some obscure races, so better safe
1029 * We do this first since we don't hold the cm_scacheLock and vnode
1030 * locks over the entire callback scan operation below. The
1031 * big loop below is guaranteed to hit any callback already
1032 * processed. The call to RecordRacingRevoke is guaranteed
1033 * to kill any callback that is currently being returned.
1034 * Anything that sneaks past both must start
1035 * after the call to RecordRacingRevoke.
1040 fid.cell = cellp->cellID;
1041 fid.volume = fid.vnode = fid.unique = 0;
1043 cm_RecordRacingRevoke(&fid, CM_RACINGFLAG_CANCELALL);
1045 cm_RecordRacingRevoke(NULL, CM_RACINGFLAG_CANCELALL);
1048 /* now search all vnodes looking for guys with this callback, if we
1049 * found it, or guys with any callbacks, if we didn't find the server
1050 * (that's how multihomed machines will appear and how we'll handle
1051 * them, albeit a little inefficiently). That is, we're discarding all
1052 * callbacks from all hosts if we get an initstate call from an unknown
1053 * host. Since these calls are rare, and multihomed servers
1054 * are "rare," hopefully this won't be a problem.
1056 lock_ObtainWrite(&cm_scacheLock);
1057 for (hash = 0; hash < cm_data.scacheHashTableSize; hash++) {
1058 for (scp=cm_data.scacheHashTablep[hash]; scp; scp=scp->nextp) {
1059 cm_HoldSCacheNoLock(scp);
1060 lock_ReleaseWrite(&cm_scacheLock);
1061 lock_ObtainWrite(&scp->rw);
1063 if (scp->cbExpires > 0 && scp->cbServerp != NULL) {
1064 /* we have a callback, now decide if we should clear it */
1065 if (cm_ServerEqual(scp->cbServerp, tsp)) {
1066 osi_Log4(afsd_logp, "InitCallbackState3 Discarding SCache scp 0x%p vol %u vn %u uniq %u",
1067 scp, scp->fid.volume, scp->fid.vnode, scp->fid.unique);
1068 cm_DiscardSCache(scp);
1072 lock_ReleaseWrite(&scp->rw);
1074 cm_CallbackNotifyChange(scp);
1075 lock_ObtainWrite(&cm_scacheLock);
1076 cm_ReleaseSCacheNoLock(scp);
1078 if (discarded && (scp->flags & CM_SCACHEFLAG_PURERO))
1079 cm_callbackDiscardROVolumeByFID(&scp->fid);
1081 } /* search one hash bucket */
1082 } /* search all hash buckets */
1084 lock_ReleaseWrite(&cm_scacheLock);
1087 /* reset the No flags on the server */
1088 cm_SetServerNo64Bit(tsp, 0);
1089 cm_SetServerNoInlineBulk(tsp, 0);
1091 /* we're done with the server structure */
1098 /* debug interface */
1100 SRXAFSCB_ProbeUuid(struct rx_call *callp, afsUUID* clientUuid)
1102 struct rx_connection *connp;
1103 struct rx_peer *peerp;
1104 unsigned long host = 0;
1105 unsigned short port = 0;
1112 if ((connp = rx_ConnectionOf(callp)) && (peerp = rx_PeerOf(connp))) {
1113 host = rx_HostOf(peerp);
1114 port = rx_PortOf(peerp);
1117 if ( !afs_uuid_equal(&cm_data.Uuid, clientUuid) ) {
1118 UuidToString((UUID *)&cm_data.Uuid, &p);
1119 UuidToString((UUID *)clientUuid, &q);
1120 osi_Log4(afsd_logp, "SRXAFSCB_ProbeUuid %s != %s from host 0x%x port %d",
1121 osi_LogSaveString(afsd_logp,p),
1122 osi_LogSaveString(afsd_logp,q),
1128 code = 1; /* failure */
1130 osi_Log2(afsd_logp, "SRXAFSCB_ProbeUuid (success) from host 0x%x port %d",
1137 /* debug interface */
1139 GetCellCommon(afs_int32 a_cellnum, char **a_name, serverList *a_hosts)
1143 cm_serverRef_t * serverRefp;
1145 cellp = cm_FindCellByID(a_cellnum, CM_FLAG_NOPROBE);
1147 *a_name = strdup("");
1151 lock_ObtainRead(&cm_serverLock);
1152 *a_name = strdup(cellp->name);
1154 for ( sn = 0, serverRefp = cellp->vlServersp;
1155 sn < AFSMAXCELLHOSTS && serverRefp;
1156 sn++, serverRefp = serverRefp->next);
1158 a_hosts->serverList_len = sn;
1159 a_hosts->serverList_val = (afs_int32 *)xdr_alloc(sn * sizeof(afs_int32));
1161 for ( sn = 0, serverRefp = cellp->vlServersp;
1162 sn < AFSMAXCELLHOSTS && serverRefp;
1163 sn++, serverRefp = serverRefp->next)
1165 a_hosts->serverList_val[sn] = ntohl(serverRefp->server->addr.sin_addr.s_addr);
1168 lock_ReleaseRead(&cm_serverLock);
1172 /* debug interface */
1174 SRXAFSCB_GetCellByNum(struct rx_call *callp, afs_int32 a_cellnum,
1175 char **a_name, serverList *a_hosts)
1177 struct rx_connection *connp;
1178 struct rx_peer *peerp;
1179 unsigned long host = 0;
1180 unsigned short port = 0;
1186 if ((connp = rx_ConnectionOf(callp)) && (peerp = rx_PeerOf(connp))) {
1187 host = rx_HostOf(peerp);
1188 port = rx_PortOf(peerp);
1191 osi_Log3(afsd_logp, "SRXAFSCB_GetCellByNum(%d) from host 0x%x port %d",
1192 a_cellnum, ntohl(host), ntohs(port));
1194 a_hosts->serverList_val = 0;
1195 a_hosts->serverList_len = 0;
1198 rc = GetCellCommon(a_cellnum, a_name, a_hosts);
1203 /* debug interface */
1205 SRXAFSCB_TellMeAboutYourself( struct rx_call *callp,
1206 struct interfaceAddr *addr,
1207 Capabilities * capabilities)
1210 afs_uint32 *dataBuffP;
1211 afs_int32 dataBytes;
1213 struct rx_connection *connp;
1214 struct rx_peer *peerp;
1215 unsigned long host = 0;
1216 unsigned short port = 0;
1221 if ((connp = rx_ConnectionOf(callp)) && (peerp = rx_PeerOf(connp))) {
1222 host = rx_HostOf(peerp);
1223 port = rx_PortOf(peerp);
1226 osi_Log2(afsd_logp, "SRXAFSCB_TellMeAboutYourself from host 0x%x port %d",
1230 lock_ObtainRead(&cm_syscfgLock);
1231 if (cm_LanAdapterChangeDetected) {
1232 lock_ConvertRToW(&cm_syscfgLock);
1233 if (cm_LanAdapterChangeDetected) {
1234 /* get network related info */
1235 cm_noIPAddr = CM_MAXINTERFACE_ADDR;
1236 code = syscfg_GetIFInfo(&cm_noIPAddr,
1237 cm_IPAddr, cm_SubnetMask,
1238 cm_NetMtu, cm_NetFlags);
1239 cm_LanAdapterChangeDetected = 0;
1241 lock_ConvertWToR(&cm_syscfgLock);
1244 /* return all network interface addresses */
1245 addr->numberOfInterfaces = cm_noIPAddr;
1246 addr->uuid = cm_data.Uuid;
1247 for ( i=0; i < cm_noIPAddr; i++ ) {
1248 addr->addr_in[i] = cm_IPAddr[i];
1249 addr->subnetmask[i] = cm_SubnetMask[i];
1250 addr->mtu[i] = (rx_mtu == -1 || (rx_mtu != -1 && cm_NetMtu[i] < rx_mtu)) ?
1251 cm_NetMtu[i] : rx_mtu;
1253 lock_ReleaseRead(&cm_syscfgLock);
1255 dataBytes = 1 * sizeof(afs_uint32);
1256 dataBuffP = (afs_uint32 *) xdr_alloc(dataBytes);
1257 dataBuffP[0] = CLIENT_CAPABILITY_ERRORTRANS;
1258 capabilities->Capabilities_len = dataBytes / sizeof(afs_uint32);
1259 capabilities->Capabilities_val = dataBuffP;
1264 /*------------------------------------------------------------------------
1265 * EXPORTED SRXAFSCB_GetServerPrefs
1268 * Routine to list server preferences used by this client.
1271 * a_call : Ptr to Rx call on which this request came in.
1272 * a_index : Input server index
1273 * a_srvr_addr : Output server address (0xffffffff on last server)
1274 * a_srvr_rank : Output server rank
1280 * Nothing interesting.
1284 *------------------------------------------------------------------------*/
1286 int SRXAFSCB_GetServerPrefs(
1287 struct rx_call *callp,
1289 afs_int32 *a_srvr_addr,
1290 afs_int32 *a_srvr_rank)
1292 struct rx_connection *connp;
1293 struct rx_peer *peerp;
1294 unsigned long host = 0;
1295 unsigned short port = 0;
1300 if ((connp = rx_ConnectionOf(callp)) && (peerp = rx_PeerOf(connp))) {
1301 host = rx_HostOf(peerp);
1302 port = rx_PortOf(peerp);
1305 osi_Log2(afsd_logp, "SRXAFSCB_GetServerPrefs from host 0x%x port %d - not implemented",
1309 *a_srvr_addr = 0xffffffff;
1310 *a_srvr_rank = 0xffffffff;
1315 /*------------------------------------------------------------------------
1316 * EXPORTED SRXAFSCB_GetCellServDB
1319 * Routine to list cells configured for this client
1322 * a_call : Ptr to Rx call on which this request came in.
1323 * a_index : Input cell index
1324 * a_name : Output cell name ("" on last cell)
1325 * a_hosts : Output cell database servers
1331 * Nothing interesting.
1335 *------------------------------------------------------------------------*/
1337 int SRXAFSCB_GetCellServDB(struct rx_call *callp, afs_int32 index, char **a_name,
1338 serverList *a_hosts)
1340 struct rx_connection *connp;
1341 struct rx_peer *peerp;
1342 unsigned long host = 0;
1343 unsigned short port = 0;
1349 if ((connp = rx_ConnectionOf(callp)) && (peerp = rx_PeerOf(connp))) {
1350 host = rx_HostOf(peerp);
1351 port = rx_PortOf(peerp);
1354 osi_Log2(afsd_logp, "SRXAFSCB_GetCellServDB from host 0x%x port %d - not implemented",
1355 ntohl(host), ntohs(port));
1357 #ifdef AFS_FREELANCE_CLIENT
1358 if (cm_freelanceEnabled && index == 0) {
1359 rc = GetCellCommon(AFS_FAKE_ROOT_CELL_ID, a_name, a_hosts);
1363 rc = GetCellCommon(index+1, a_name, a_hosts);
1368 /*------------------------------------------------------------------------
1369 * EXPORTED SRXAFSCB_GetLocalCell
1372 * Routine to return name of client's local cell
1375 * a_call : Ptr to Rx call on which this request came in.
1376 * a_name : Output cell name
1382 * Nothing interesting.
1386 *------------------------------------------------------------------------*/
1388 int SRXAFSCB_GetLocalCell(struct rx_call *callp, char **a_name)
1391 struct rx_connection *connp;
1392 struct rx_peer *peerp;
1393 unsigned long host = 0;
1394 unsigned short port = 0;
1399 if ((connp = rx_ConnectionOf(callp)) && (peerp = rx_PeerOf(connp))) {
1400 host = rx_HostOf(peerp);
1401 port = rx_PortOf(peerp);
1404 osi_Log2(afsd_logp, "SRXAFSCB_GetLocalCell from host 0x%x port %d",
1405 ntohl(host), ntohs(port));
1407 if (cm_data.rootCellp) {
1408 t_name = strdup(cm_data.rootCellp->name);
1410 t_name = (char *)xdr_alloc(1);
1420 * afs_MarshallCacheConfig - marshall client cache configuration
1424 * IN callerVersion - the rpc stat version of the caller.
1426 * IN config - client cache configuration.
1428 * OUT ptr - buffer where configuration is marshalled.
1434 static void afs_MarshallCacheConfig(
1435 afs_uint32 callerVersion,
1436 cm_initparams_v1 *config,
1440 * We currently only support version 1.
1442 *(ptr++) = config->nChunkFiles;
1443 *(ptr++) = config->nStatCaches;
1444 *(ptr++) = config->nDataCaches;
1445 *(ptr++) = config->nVolumeCaches;
1446 *(ptr++) = config->firstChunkSize;
1447 *(ptr++) = config->otherChunkSize;
1448 *(ptr++) = config->cacheSize;
1449 *(ptr++) = config->setTime;
1450 *(ptr++) = config->memCache;
1455 /*------------------------------------------------------------------------
1456 * EXPORTED SRXAFSCB_GetCacheConfig
1459 * Routine to return parameters used to initialize client cache.
1460 * Client may request any format version. Server may not return
1461 * format version greater than version requested by client.
1464 * a_call: Ptr to Rx call on which this request came in.
1465 * callerVersion: Data format version desired by the client.
1466 * serverVersion: Data format version of output data.
1467 * configCount: Number bytes allocated for output data.
1468 * config: Client cache configuration.
1474 * Nothing interesting.
1478 *------------------------------------------------------------------------*/
1480 int SRXAFSCB_GetCacheConfig(struct rx_call *callp,
1481 afs_uint32 callerVersion,
1482 afs_uint32 *serverVersion,
1483 afs_uint32 *configCount,
1484 cacheConfig *config)
1486 afs_uint32 *t_config;
1488 extern cm_initparams_v1 cm_initParams;
1489 struct rx_connection *connp;
1490 struct rx_peer *peerp;
1491 unsigned long host = 0;
1492 unsigned short port = 0;
1497 if ((connp = rx_ConnectionOf(callp)) && (peerp = rx_PeerOf(connp))) {
1498 host = rx_HostOf(peerp);
1499 port = rx_PortOf(peerp);
1502 osi_Log2(afsd_logp, "SRXAFSCB_GetCacheConfig from host 0x%x port %d - version 1 only",
1503 ntohl(host), ntohs(port));
1506 * Currently only support version 1
1508 allocsize = sizeof(cm_initparams_v1);
1509 t_config = (afs_uint32 *)xdr_alloc(allocsize);
1511 afs_MarshallCacheConfig(callerVersion, &cm_initParams, t_config);
1513 *serverVersion = AFS_CLIENT_RETRIEVAL_FIRST_EDITION;
1516 #define SIZE_MAX UINT_MAX
1518 osi_assertx(allocsize < SIZE_MAX, "allocsize >= SIZE_MAX");
1520 *configCount = (afs_uint32)allocsize;
1521 config->cacheConfig_val = t_config;
1522 config->cacheConfig_len = (*configCount)/sizeof(afs_uint32);
1527 /* called by afsd without any locks to initialize this module */
1528 void cm_InitCallback(void)
1530 lock_InitializeRWLock(&cm_callbackLock, "cm_callbackLock", LOCK_HIERARCHY_CALLBACK_GLOBAL);
1531 cm_activeCallbackGrantingCalls = 0;
1534 /* called with locked scp; tells us whether we've got a callback.
1535 * Expirations are checked by a background daemon so as to make
1536 * this function as inexpensive as possible
1538 int cm_HaveCallback(cm_scache_t *scp)
1540 #ifdef AFS_FREELANCE_CLIENT
1541 // yj: we handle callbacks specially for callbacks on the root directory
1542 // Since it's local, we almost always say that we have callback on it
1543 // The only time we send back a 0 is if we're need to initialize or
1544 // reinitialize the fake directory
1546 // There are 2 state variables cm_fakeGettingCallback and cm_fakeDirCallback
1547 // cm_fakeGettingCallback is 1 if we're in the process of initialization and
1548 // hence should return false. it's 0 otherwise
1549 // cm_fakeDirCallback is 0 if we haven't loaded the fake directory, it's 1
1550 // if the fake directory is loaded and this is the first time cm_HaveCallback
1551 // is called since then. We return false in this case to allow cm_GetCallback
1552 // to be called because cm_GetCallback has some initialization work to do.
1553 // If cm_fakeDirCallback is 2, then it means that the fake directory is in
1554 // good shape and we simply return true, provided no change is detected.
1557 if (cm_freelanceEnabled &&
1558 scp->fid.cell==AFS_FAKE_ROOT_CELL_ID && scp->fid.volume==AFS_FAKE_ROOT_VOL_ID) {
1559 lock_ObtainMutex(&cm_Freelance_Lock);
1560 fdc = cm_fakeDirCallback;
1561 fgc = cm_fakeGettingCallback;
1562 lock_ReleaseMutex(&cm_Freelance_Lock);
1564 if (fdc==1) { // first call since init
1566 } else if (fdc==2 && !fgc) { // we're in good shape
1567 if (cm_getLocalMountPointChange()) { // check for changes
1568 cm_clearLocalMountPointChange(); // clear the changefile
1569 lock_ReleaseWrite(&scp->rw); // this is re-locked in reInitLocalMountPoints
1570 cm_reInitLocalMountPoints(); // start reinit
1571 lock_ObtainWrite(&scp->rw); // now get the lock back
1574 return (cm_data.fakeDirVersion == scp->dataVersion);
1579 if (cm_readonlyVolumeVersioning &&
1580 (scp->flags & CM_SCACHEFLAG_PURERO)) {
1581 cm_volume_t *volp = cm_GetVolumeByFID(&scp->fid);
1584 if (cm_OfflineROIsValid) {
1585 switch (cm_GetVolumeStatus(volp, scp->fid.volume)) {
1594 volp->creationDateRO == scp->volumeCreationDate &&
1595 volp->cbServerpRO != NULL) {
1602 if (scp->cbServerp != NULL)
1608 /* need to detect a broken callback that races with our obtaining a callback.
1609 * Need to be able to do this even if we don't know the file ID of the file
1610 * we're breaking the callback on at the time we start the acquisition of the
1611 * callback (as in the case where we are creating a file).
1613 * So, we start by writing down the count of the # of callbacks we've received
1614 * so far, and bumping a global counter of the # of callback granting calls
1615 * outstanding (all done under cm_callbackLock).
1617 * When we're back from the call, we look at all of the callback revokes with
1618 * counter numbers greater than the one we recorded in our caller's structure,
1619 * and replay those that are higher than when we started the call.
1621 * We free all the structures in the queue when the count of the # of outstanding
1622 * callback-granting calls drops to zero.
1624 * We call this function with the scp locked, too, but in its current implementation,
1625 * this knowledge is not used.
1627 void cm_StartCallbackGrantingCall(cm_scache_t *scp, cm_callbackRequest_t *cbrp)
1629 lock_ObtainWrite(&cm_callbackLock);
1630 cbrp->callbackCount = cm_callbackCount;
1631 cm_activeCallbackGrantingCalls++;
1632 cbrp->startTime = time(NULL);
1633 cbrp->serverp = NULL;
1634 lock_ReleaseWrite(&cm_callbackLock);
1637 /* Called at the end of a callback-granting call, to remove the callback
1638 * info from the scache entry, if necessary.
1640 * Called with scp write locked, so we can discard the callbacks easily with
1641 * this locking hierarchy.
1643 void cm_EndCallbackGrantingCall(cm_scache_t *scp, cm_callbackRequest_t *cbrp,
1644 AFSCallBack *cbp, AFSVolSync *volSyncp, long flags)
1646 cm_racingRevokes_t *revp; /* where we are */
1647 cm_racingRevokes_t *nrevp; /* where we'll be next */
1649 cm_server_t * serverp = NULL;
1650 int discardScp = 0, discardVolCB = 0;
1652 lock_ObtainWrite(&cm_callbackLock);
1653 if (flags & CM_CALLBACK_MAINTAINCOUNT) {
1654 osi_assertx(cm_activeCallbackGrantingCalls > 0,
1655 "CM_CALLBACK_MAINTAINCOUNT && cm_activeCallbackGrantingCalls == 0");
1658 osi_assertx(cm_activeCallbackGrantingCalls-- > 0,
1659 "!CM_CALLBACK_MAINTAINCOUNT && cm_activeCallbackGrantingCalls == 0");
1661 if (cm_activeCallbackGrantingCalls == 0)
1666 /* record the callback; we'll clear it below if we really lose it */
1669 if (!cm_ServerEqual(scp->cbServerp, cbrp->serverp)) {
1670 serverp = scp->cbServerp;
1672 cm_GetServer(cbrp->serverp);
1673 scp->cbServerp = cbrp->serverp;
1676 serverp = cbrp->serverp;
1678 scp->cbExpires = cbrp->startTime + cbp->ExpirationTime;
1681 serverp = cbrp->serverp;
1684 cbrp->serverp = NULL;
1687 /* a callback was actually revoked during our granting call, so
1688 * run down the list of revoked fids, looking for ours.
1689 * If activeCallbackGrantingCalls is zero, free the elements, too.
1691 * May need to go through entire list just to do the freeing.
1693 for (revp = cm_racingRevokesp; revp; revp = nrevp) {
1694 nrevp = (cm_racingRevokes_t *) osi_QNext(&revp->q);
1695 /* if this callback came in later than when we started the
1696 * callback-granting call, and if this fid is the right fid,
1697 * then clear the callback.
1699 if (scp && cbrp && cbrp->callbackCount != cm_callbackCount
1700 && revp->callbackCount > cbrp->callbackCount
1701 && (( scp->fid.volume == revp->fid.volume &&
1702 scp->fid.vnode == revp->fid.vnode &&
1703 scp->fid.unique == revp->fid.unique)
1705 ((revp->flags & CM_RACINGFLAG_CANCELVOL) &&
1706 scp->fid.volume == revp->fid.volume)
1708 ((revp->flags & CM_RACINGFLAG_CANCELALL) &&
1709 (revp->fid.cell == 0 || scp->fid.cell == revp->fid.cell)))) {
1710 /* this one matches */
1712 "Racing revoke scp 0x%p old cbc %d rev cbc %d cur cbc %d",
1714 cbrp->callbackCount, revp->callbackCount,
1717 if ((scp->flags & CM_SCACHEFLAG_PURERO) &&
1718 (revp->flags & CM_RACINGFLAG_ALL))
1719 cm_callbackDiscardROVolumeByFID(&scp->fid);
1725 /* if we freed the list, zap the pointer to it */
1727 cm_racingRevokesp = NULL;
1729 lock_ReleaseWrite(&cm_callbackLock);
1732 cm_DiscardSCache(scp);
1733 lock_ReleaseWrite(&scp->rw);
1734 cm_CallbackNotifyChange(scp);
1735 lock_ObtainWrite(&scp->rw);
1737 if (scp && scp->flags & CM_SCACHEFLAG_PURERO) {
1738 cm_volume_t * volp = cm_GetVolumeByFID(&scp->fid);
1741 lock_ObtainWrite(&cm_scacheLock);
1742 volp->cbExpiresRO = scp->cbExpires;
1743 volp->creationDateRO = volSyncp->spare1;
1744 if (volp->cbServerpRO != scp->cbServerp) {
1745 if (volp->cbServerpRO)
1746 cm_PutServer(volp->cbServerpRO);
1747 cm_GetServer(scp->cbServerp);
1748 volp->cbServerpRO = scp->cbServerp;
1750 lock_ReleaseWrite(&cm_scacheLock);
1758 lock_ObtainWrite(&cm_serverLock);
1759 cm_FreeServer(serverp);
1760 lock_ReleaseWrite(&cm_serverLock);
1764 /* if flags is 1, we want to force the code to make one call, anyway.
1765 * called with locked scp; returns with same.
1767 long cm_GetCallback(cm_scache_t *scp, struct cm_user *userp,
1768 struct cm_req *reqp, long flags)
1771 cm_conn_t *connp = NULL;
1772 AFSFetchStatus afsStatus;
1774 AFSCallBack callback;
1776 cm_callbackRequest_t cbr;
1779 struct rx_connection * rxconnp = NULL;
1780 int syncop_done = 0;
1782 memset(&volSync, 0, sizeof(volSync));
1784 osi_Log4(afsd_logp, "GetCallback scp 0x%p cell %d vol %d flags %lX",
1785 scp, scp->fid.cell, scp->fid.volume, flags);
1787 #ifdef AFS_FREELANCE_CLIENT
1788 // The case where a callback is needed on /afs is handled
1789 // specially. We need to fetch the status by calling
1790 // cm_MergeStatus and mark that cm_fakeDirCallback is 2
1791 if (cm_freelanceEnabled &&
1792 (scp->fid.cell==AFS_FAKE_ROOT_CELL_ID &&
1793 scp->fid.volume==AFS_FAKE_ROOT_VOL_ID)) {
1795 code = cm_SyncOp(scp, NULL, userp, reqp, 0,
1796 CM_SCACHESYNC_FETCHSTATUS | CM_SCACHESYNC_GETCALLBACK);
1801 if (cm_fakeDirCallback != 2) {
1802 // Start by indicating that we're in the process
1803 // of fetching the callback
1804 lock_ObtainMutex(&cm_Freelance_Lock);
1805 osi_Log0(afsd_logp,"GetCallback Freelance fakeGettingCallback=1");
1806 cm_fakeGettingCallback = 1;
1807 lock_ReleaseMutex(&cm_Freelance_Lock);
1809 memset(&afsStatus, 0, sizeof(afsStatus));
1811 // Fetch the status info
1812 cm_MergeStatus(NULL, scp, &afsStatus, &volSync, userp, reqp, 0);
1814 // Indicate that the callback is not done
1815 lock_ObtainMutex(&cm_Freelance_Lock);
1816 osi_Log0(afsd_logp,"GetCallback Freelance fakeDirCallback=2");
1817 cm_fakeDirCallback = 2;
1819 // Indicate that we're no longer fetching the callback
1820 osi_Log0(afsd_logp,"GetCallback Freelance fakeGettingCallback=0");
1821 cm_fakeGettingCallback = 0;
1822 lock_ReleaseMutex(&cm_Freelance_Lock);
1826 #endif /* AFS_FREELANCE_CLIENT */
1828 mustCall = (flags & 1);
1829 cm_AFSFidFromFid(&tfid, &scp->fid);
1831 if (!mustCall && cm_HaveCallback(scp))
1834 /* turn off mustCall, since it has now forced us past the check above */
1837 /* otherwise, we have to make an RPC to get the status */
1839 code = cm_SyncOp(scp, NULL, userp, reqp, 0,
1840 CM_SCACHESYNC_FETCHSTATUS | CM_SCACHESYNC_GETCALLBACK);
1845 cm_StartCallbackGrantingCall(scp, &cbr);
1847 lock_ReleaseWrite(&scp->rw);
1849 /* now make the RPC */
1850 osi_Log4(afsd_logp, "CALL FetchStatus scp 0x%p vol %u vn %u uniq %u",
1851 scp, sfid.volume, sfid.vnode, sfid.unique);
1853 code = cm_ConnFromFID(&sfid, userp, reqp, &connp);
1857 rxconnp = cm_GetRxConn(connp);
1858 code = RXAFS_FetchStatus(rxconnp, &tfid,
1859 &afsStatus, &callback, &volSync);
1860 rx_PutConnection(rxconnp);
1862 } while (cm_Analyze(connp, userp, reqp, &sfid, &volSync, NULL,
1864 code = cm_MapRPCError(code, reqp);
1866 osi_Log4(afsd_logp, "CALL FetchStatus FAILURE code 0x%x scp 0x%p vol %u vn %u",
1867 code, scp, scp->fid.volume, scp->fid.vnode);
1869 osi_Log4(afsd_logp, "CALL FetchStatus SUCCESS scp 0x%p vol %u vn %u uniq %u",
1870 scp, scp->fid.volume, scp->fid.vnode, scp->fid.unique);
1872 lock_ObtainWrite(&scp->rw);
1874 cm_EndCallbackGrantingCall(scp, &cbr, &callback, &volSync, 0);
1875 cm_MergeStatus(NULL, scp, &afsStatus, &volSync, userp, reqp, 0);
1877 cm_EndCallbackGrantingCall(NULL, &cbr, NULL, NULL, 0);
1880 /* if we got an error, return to caller */
1887 cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_FETCHSTATUS | CM_SCACHESYNC_GETCALLBACK);
1890 osi_Log2(afsd_logp, "GetCallback Failed code 0x%x scp 0x%p -->",code, scp);
1891 osi_Log4(afsd_logp, " cell %u vol %u vn %u uniq %u",
1892 scp->fid.cell, scp->fid.volume, scp->fid.vnode, scp->fid.unique);
1894 osi_Log3(afsd_logp, "GetCallback Complete scp 0x%p cell %d vol %d",
1895 scp, scp->fid.cell, scp->fid.volume);
1902 /* called with cm_scacheLock held */
1903 long cm_CBServersUp(cm_scache_t *scp, time_t * downTime)
1905 cm_vol_state_t *statep;
1907 afs_uint32 volID = scp->fid.volume;
1908 cm_serverRef_t *tsrp;
1913 if (scp->cbServerp == NULL)
1916 volp = cm_GetVolumeByFID(&scp->fid);
1920 statep = cm_VolumeStateByID(volp, volID);
1922 if (statep->state == vl_online)
1925 for (found = 0,tsrp = statep->serversp; tsrp; tsrp=tsrp->next) {
1926 if (tsrp->status == srv_deleted)
1928 if (cm_ServerEqual(tsrp->server, scp->cbServerp))
1930 if (tsrp->server->downTime > *downTime)
1931 *downTime = tsrp->server->downTime;
1934 /* if the cbServerp does not match the current volume server list
1935 * we report the callback server as up so the callback can be
1938 return(found ? 0 : 1);
1941 /* called periodically by cm_daemon to shut down use of expired callbacks */
1942 void cm_CheckCBExpiration(void)
1946 time_t now, downTime;
1948 osi_Log0(afsd_logp, "CheckCBExpiration");
1951 lock_ObtainWrite(&cm_scacheLock);
1952 for (i=0; i<cm_data.scacheHashTableSize; i++) {
1953 for (scp = cm_data.scacheHashTablep[i]; scp; scp=scp->nextp) {
1955 if (scp->flags & CM_SCACHEFLAG_PURERO) {
1956 cm_volume_t *volp = cm_GetVolumeByFID(&scp->fid);
1958 if (volp->cbExpiresRO > scp->cbExpires &&
1961 scp->cbExpires = volp->cbExpiresRO;
1962 if (volp->cbServerpRO != scp->cbServerp) {
1964 cm_PutServer(scp->cbServerp);
1965 cm_GetServer(volp->cbServerpRO);
1966 scp->cbServerp = volp->cbServerpRO;
1972 if (scp->cbServerp && scp->cbExpires > 0 && now > scp->cbExpires &&
1973 (cm_CBServersUp(scp, &downTime) || downTime == 0 || downTime >= scp->cbExpires))
1975 cm_HoldSCacheNoLock(scp);
1976 lock_ReleaseWrite(&cm_scacheLock);
1978 osi_Log4(afsd_logp, "Callback Expiration Discarding SCache scp 0x%p vol %u vn %u uniq %u",
1979 scp, scp->fid.volume, scp->fid.vnode, scp->fid.unique);
1980 lock_ObtainWrite(&scp->rw);
1981 cm_DiscardSCache(scp);
1982 lock_ReleaseWrite(&scp->rw);
1983 cm_CallbackNotifyChange(scp);
1985 lock_ObtainWrite(&cm_scacheLock);
1986 cm_ReleaseSCacheNoLock(scp);
1990 lock_ReleaseWrite(&cm_scacheLock);
1992 osi_Log0(afsd_logp, "CheckCBExpiration Complete");
1997 cm_GiveUpAllCallbacks(cm_server_t *tsp, afs_int32 markDown)
2001 struct rx_connection * rxconnp;
2003 if ((tsp->type == CM_SERVER_FILE) && !(tsp->flags & CM_SERVERFLAG_DOWN))
2005 code = cm_ConnByServer(tsp, cm_rootUserp, &connp);
2007 rxconnp = cm_GetRxConn(connp);
2008 rx_SetConnDeadTime(rxconnp, 10);
2009 code = RXAFS_GiveUpAllCallBacks(rxconnp);
2010 rx_SetConnDeadTime(rxconnp, ConnDeadtimeout);
2011 rx_PutConnection(rxconnp);
2015 cm_server_vols_t * tsrvp;
2019 cm_ForceNewConnections(tsp);
2021 lock_ObtainMutex(&tsp->mx);
2022 if (!(tsp->flags & CM_SERVERFLAG_DOWN)) {
2023 tsp->flags |= CM_SERVERFLAG_DOWN;
2024 tsp->downTime = time(NULL);
2026 /* Now update the volume status */
2027 for (tsrvp = tsp->vols; tsrvp; tsrvp = tsrvp->nextp) {
2028 for (i=0; i<NUM_SERVER_VOLS; i++) {
2029 if (tsrvp->ids[i] != 0) {
2033 lock_ReleaseMutex(&tsp->mx);
2034 code = cm_FindVolumeByID(tsp->cellp, tsrvp->ids[i], cm_rootUserp,
2035 &req, CM_GETVOL_FLAG_NO_LRU_UPDATE | CM_GETVOL_FLAG_NO_RESET, &volp);
2036 lock_ObtainMutex(&tsp->mx);
2038 cm_UpdateVolumeStatus(volp, tsrvp->ids[i]);
2044 lock_ReleaseMutex(&tsp->mx);
2050 cm_GiveUpAllCallbacksAllServers(afs_int32 markDown)
2054 if (!cm_giveUpAllCBs)
2057 lock_ObtainWrite(&cm_serverLock);
2058 for (tsp = cm_allServersp; tsp; tsp = tsp->allNextp) {
2059 cm_GetServerNoLock(tsp);
2060 lock_ReleaseWrite(&cm_serverLock);
2061 cm_GiveUpAllCallbacks(tsp, markDown);
2062 lock_ObtainWrite(&cm_serverLock);
2063 cm_PutServerNoLock(tsp);
2065 lock_ReleaseWrite(&cm_serverLock);