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
},
56 "afs_xsrvAddr", (char *)&afs_xsrvAddr
},
58 "afs_xvreclaim", (char *)&afs_xvreclaim
},
59 { "afsdb_client_lock", (char *)&afsdb_client_lock
},
60 { "afsdb_req_lock", (char *)&afsdb_req_lock
},
61 { "afs_discon_lock", (char *)&afs_discon_lock
},
62 { "afs_disconDirtyLock", (char *)&afs_disconDirtyLock
},
63 { "afs_discon_vc_dirty", (char *)&afs_xvcdirty
},
64 { "afs_dynrootDirLock", (char *)&afs_dynrootDirLock
},
65 { "afs_dynSymlinkLock", (char *)&afs_dynSymlinkLock
},
67 unsigned long lastCallBack_vnode
;
68 unsigned int lastCallBack_dv
;
69 osi_timeval_t lastCallBack_time
;
71 /* these are for storing alternate interface addresses */
72 struct interfaceAddr afs_cb_interface
;
74 /*------------------------------------------------------------------------
75 * EXPORTED SRXAFSCB_GetCE
78 * Routine called by the server-side callback RPC interface to
79 * implement pulling out the contents of the i'th cache entry.
82 * a_call : Ptr to Rx call on which this request came in.
83 * a_index : Index of desired cache entry.
84 * a_result : Ptr to a buffer for the given cache entry.
87 * 0 if everything went fine,
88 * 1 if we were given a bad index.
91 * Nothing interesting.
95 *------------------------------------------------------------------------*/
98 SRXAFSCB_GetCE(struct rx_call
*a_call
, afs_int32 a_index
,
99 struct AFSDBCacheEntry
*a_result
)
102 int i
; /*Loop variable */
103 struct vcache
*tvc
; /*Ptr to current cache entry */
104 int code
; /*Return code */
109 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_GETCE
);
111 AFS_STATCNT(SRXAFSCB_GetCE
);
112 for (i
= 0; i
< VCSIZE
; i
++) {
113 for (tvc
= afs_vhashT
[i
]; tvc
; tvc
= tvc
->hnext
) {
117 } /*Zip through current hash chain */
118 } /*Zip through hash chains */
128 * Copy out the located entry.
130 a_result
->addr
= afs_data_pointer_to_int32(tvc
);
131 a_result
->cell
= tvc
->f
.fid
.Cell
;
132 a_result
->netFid
.Volume
= tvc
->f
.fid
.Fid
.Volume
;
133 a_result
->netFid
.Vnode
= tvc
->f
.fid
.Fid
.Vnode
;
134 a_result
->netFid
.Unique
= tvc
->f
.fid
.Fid
.Unique
;
135 a_result
->lock
.waitStates
= tvc
->lock
.wait_states
;
136 a_result
->lock
.exclLocked
= tvc
->lock
.excl_locked
;
137 a_result
->lock
.readersReading
= tvc
->lock
.readers_reading
;
138 a_result
->lock
.numWaiting
= tvc
->lock
.num_waiting
;
139 #if defined(INSTRUMENT_LOCKS)
140 a_result
->lock
.pid_last_reader
= MyPidxx2Pid(tvc
->lock
.pid_last_reader
);
141 a_result
->lock
.pid_writer
= MyPidxx2Pid(tvc
->lock
.pid_writer
);
142 a_result
->lock
.src_indicator
= tvc
->lock
.src_indicator
;
144 /* On osf20 , the vcache does not maintain these three fields */
145 a_result
->lock
.pid_last_reader
= 0;
146 a_result
->lock
.pid_writer
= 0;
147 a_result
->lock
.src_indicator
= 0;
148 #endif /* INSTRUMENT_LOCKS */
149 #ifdef AFS_64BIT_CLIENT
150 a_result
->Length
= (afs_int32
) tvc
->f
.m
.Length
& 0xffffffff;
151 #else /* AFS_64BIT_CLIENT */
152 a_result
->Length
= tvc
->f
.m
.Length
;
153 #endif /* AFS_64BIT_CLIENT */
154 a_result
->DataVersion
= hgetlo(tvc
->f
.m
.DataVersion
);
155 a_result
->callback
= afs_data_pointer_to_int32(tvc
->callback
); /* XXXX Now a pointer; change it XXXX */
156 a_result
->cbExpires
= tvc
->cbExpires
;
157 if (tvc
->f
.states
& CVInit
) {
158 a_result
->refCount
= 1;
160 #ifdef AFS_DARWIN80_ENV
161 a_result
->refCount
= vnode_isinuse(AFSTOV(tvc
),0)?1:0; /* XXX fix */
163 a_result
->refCount
= VREFCOUNT(tvc
);
166 a_result
->opens
= tvc
->opens
;
167 a_result
->writers
= tvc
->execsOrWriters
;
168 a_result
->mvstat
= tvc
->mvstat
;
169 a_result
->states
= tvc
->f
.states
;
173 * Return our results.
182 } /*SRXAFSCB_GetCE */
185 SRXAFSCB_GetCE64(struct rx_call
*a_call
, afs_int32 a_index
,
186 struct AFSDBCacheEntry64
*a_result
)
188 int i
; /*Loop variable */
189 struct vcache
*tvc
; /*Ptr to current cache entry */
190 int code
; /*Return code */
195 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_GETCE
);
197 AFS_STATCNT(SRXAFSCB_GetCE64
);
198 for (i
= 0; i
< VCSIZE
; i
++) {
199 for (tvc
= afs_vhashT
[i
]; tvc
; tvc
= tvc
->hnext
) {
203 } /*Zip through current hash chain */
204 } /*Zip through hash chains */
214 * Copy out the located entry.
216 a_result
->addr
= afs_data_pointer_to_int32(tvc
);
217 a_result
->cell
= tvc
->f
.fid
.Cell
;
218 a_result
->netFid
.Volume
= tvc
->f
.fid
.Fid
.Volume
;
219 a_result
->netFid
.Vnode
= tvc
->f
.fid
.Fid
.Vnode
;
220 a_result
->netFid
.Unique
= tvc
->f
.fid
.Fid
.Unique
;
221 a_result
->lock
.waitStates
= tvc
->lock
.wait_states
;
222 a_result
->lock
.exclLocked
= tvc
->lock
.excl_locked
;
223 a_result
->lock
.readersReading
= tvc
->lock
.readers_reading
;
224 a_result
->lock
.numWaiting
= tvc
->lock
.num_waiting
;
225 #if defined(INSTRUMENT_LOCKS)
226 a_result
->lock
.pid_last_reader
= MyPidxx2Pid(tvc
->lock
.pid_last_reader
);
227 a_result
->lock
.pid_writer
= MyPidxx2Pid(tvc
->lock
.pid_writer
);
228 a_result
->lock
.src_indicator
= tvc
->lock
.src_indicator
;
230 /* On osf20 , the vcache does not maintain these three fields */
231 a_result
->lock
.pid_last_reader
= 0;
232 a_result
->lock
.pid_writer
= 0;
233 a_result
->lock
.src_indicator
= 0;
234 #endif /* INSTRUMENT_LOCKS */
235 a_result
->Length
= tvc
->f
.m
.Length
;
236 a_result
->DataVersion
= hgetlo(tvc
->f
.m
.DataVersion
);
237 a_result
->callback
= afs_data_pointer_to_int32(tvc
->callback
); /* XXXX Now a pointer; change it XXXX */
238 a_result
->cbExpires
= tvc
->cbExpires
;
239 if (tvc
->f
.states
& CVInit
) {
240 a_result
->refCount
= 1;
242 #ifdef AFS_DARWIN80_ENV
243 a_result
->refCount
= vnode_isinuse(AFSTOV(tvc
),0)?1:0; /* XXX fix */
245 a_result
->refCount
= VREFCOUNT(tvc
);
248 a_result
->opens
= tvc
->opens
;
249 a_result
->writers
= tvc
->execsOrWriters
;
250 a_result
->mvstat
= tvc
->mvstat
;
251 a_result
->states
= tvc
->f
.states
;
255 * Return our results.
264 } /*SRXAFSCB_GetCE64 */
267 /*------------------------------------------------------------------------
268 * EXPORTED SRXAFSCB_GetLock
271 * Routine called by the server-side callback RPC interface to
272 * implement pulling out the contents of a lock in the lock
276 * a_call : Ptr to Rx call on which this request came in.
277 * a_index : Index of desired lock.
278 * a_result : Ptr to a buffer for the given lock.
281 * 0 if everything went fine,
282 * 1 if we were given a bad index.
285 * Nothing interesting.
289 *------------------------------------------------------------------------*/
292 SRXAFSCB_GetLock(struct rx_call
*a_call
, afs_int32 a_index
,
293 struct AFSDBLock
*a_result
)
295 struct ltable
*tl
; /*Ptr to lock table entry */
296 int nentries
; /*Num entries in table */
297 int code
; /*Return code */
302 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_GETLOCK
);
304 AFS_STATCNT(SRXAFSCB_GetLock
);
305 memset(a_result
, 0, sizeof(*a_result
));
306 nentries
= sizeof(ltable
) / sizeof(struct ltable
);
307 if (a_index
< 0 || a_index
>= nentries
+afs_cellindex
) {
312 } else if (a_index
>= nentries
) {
313 struct cell
*tc
= afs_GetCellByIndex(a_index
-nentries
, 0);
314 strcpy(a_result
->name
, tc
->cellName
);
315 a_result
->lock
.waitStates
=
316 ((struct afs_lock
*)&(tc
->lock
))->wait_states
;
317 a_result
->lock
.exclLocked
=
318 ((struct afs_lock
*)&(tc
->lock
))->excl_locked
;
319 a_result
->lock
.readersReading
=
320 ((struct afs_lock
*)&(tc
->lock
))->readers_reading
;
321 a_result
->lock
.numWaiting
=
322 ((struct afs_lock
*)&(tc
->lock
))->num_waiting
;
323 #ifdef INSTRUMENT_LOCKS
324 a_result
->lock
.pid_last_reader
=
325 MyPidxx2Pid(((struct afs_lock
*)&(tc
->lock
))->pid_last_reader
);
326 a_result
->lock
.pid_writer
=
327 MyPidxx2Pid(((struct afs_lock
*)&(tc
->lock
))->pid_writer
);
328 a_result
->lock
.src_indicator
=
329 ((struct afs_lock
*)&(tc
->lock
))->src_indicator
;
331 a_result
->lock
.pid_last_reader
= 0;
332 a_result
->lock
.pid_writer
= 0;
333 a_result
->lock
.src_indicator
= 0;
338 * Found it - copy out its contents.
340 tl
= <able
[a_index
];
341 strcpy(a_result
->name
, tl
->name
);
342 a_result
->lock
.waitStates
=
343 ((struct afs_lock
*)(tl
->addr
))->wait_states
;
344 a_result
->lock
.exclLocked
=
345 ((struct afs_lock
*)(tl
->addr
))->excl_locked
;
346 a_result
->lock
.readersReading
=
347 ((struct afs_lock
*)(tl
->addr
))->readers_reading
;
348 a_result
->lock
.numWaiting
=
349 ((struct afs_lock
*)(tl
->addr
))->num_waiting
;
350 #ifdef INSTRUMENT_LOCKS
351 a_result
->lock
.pid_last_reader
=
352 MyPidxx2Pid(((struct afs_lock
*)(tl
->addr
))->pid_last_reader
);
353 a_result
->lock
.pid_writer
=
354 MyPidxx2Pid(((struct afs_lock
*)(tl
->addr
))->pid_writer
);
355 a_result
->lock
.src_indicator
=
356 ((struct afs_lock
*)(tl
->addr
))->src_indicator
;
358 a_result
->lock
.pid_last_reader
= 0;
359 a_result
->lock
.pid_writer
= 0;
360 a_result
->lock
.src_indicator
= 0;
371 } /*SRXAFSCB_GetLock */
374 /*------------------------------------------------------------------------
375 * static ClearCallBack
378 * Clear out callback information for the specified file, or
379 * even a whole volume. Used to worry about callback was from
380 * within the particular cell or not. Now we don't bother with
381 * that anymore; it's not worth the time.
384 * a_conn : Ptr to Rx connection involved.
385 * a_fid : Ptr to AFS fid being cleared.
391 * Nothing interesting.
396 Appears to need to be called with GLOCK held, as the icl_Event4 stuff asserts otherwise
398 *------------------------------------------------------------------------*/
401 ClearCallBack(struct rx_connection
*a_conn
,
402 struct AFSFid
*a_fid
)
406 struct VenusFid localFid
;
408 #ifdef AFS_DARWIN80_ENV
412 AFS_STATCNT(ClearCallBack
);
417 * XXXX Don't hold any server locks here because of callback protocol XXX
420 localFid
.Fid
.Volume
= a_fid
->Volume
;
421 localFid
.Fid
.Vnode
= a_fid
->Vnode
;
422 localFid
.Fid
.Unique
= a_fid
->Unique
;
425 * Volume ID of zero means don't do anything.
427 if (a_fid
->Volume
!= 0) {
428 if (a_fid
->Vnode
== 0) {
429 struct afs_q
*tq
, *uq
;
431 * Clear callback for the whole volume. Zip through the
432 * hash chain, nullifying entries whose volume ID matches.
435 ObtainReadLock(&afs_xvcache
);
436 i
= VCHashV(&localFid
);
437 for (tq
= afs_vhashTV
[i
].prev
; tq
!= &afs_vhashTV
[i
]; tq
= uq
) {
440 if (tvc
->f
.fid
.Fid
.Volume
== a_fid
->Volume
) {
441 tvc
->callback
= NULL
;
443 localFid
.Cell
= tvc
->f
.fid
.Cell
;
444 tvc
->dchint
= NULL
; /* invalidate hints */
445 if (tvc
->f
.states
& CVInit
) {
446 ReleaseReadLock(&afs_xvcache
);
447 afs_osi_Sleep(&tvc
->f
.states
);
450 #if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_HPUX_ENV) || defined(AFS_LINUX20_ENV)
453 #ifdef AFS_DARWIN80_ENV
454 if (tvc
->f
.states
& CDeadVnode
) {
455 ReleaseReadLock(&afs_xvcache
);
456 afs_osi_Sleep(&tvc
->f
.states
);
472 ReleaseReadLock(&afs_xvcache
);
473 afs_StaleVCacheFlags(tvc
, 0, CUnique
| CBulkFetching
);
475 if (tvc
->f
.fid
.Fid
.Vnode
& 1)
479 afs_Trace3(afs_iclSetp
, CM_TRACE_CALLBACK
,
480 ICL_TYPE_POINTER
, tvc
, ICL_TYPE_INT32
,
481 tvc
->f
.states
, ICL_TYPE_INT32
,
483 #ifdef AFS_DARWIN80_ENV
484 vnode_put(AFSTOV(tvc
));
486 ObtainReadLock(&afs_xvcache
);
489 } else if ((tvc
->f
.states
& CMValid
)
490 && (tvc
->mvid
.target_root
->Fid
.Volume
== a_fid
->Volume
)) {
491 tvc
->f
.states
&= ~CMValid
;
493 localFid
.Cell
= tvc
->mvid
.target_root
->Cell
;
496 ReleaseReadLock(&afs_xvcache
);
499 * XXXX Don't hold any locks here XXXX
501 tv
= afs_FindVolume(&localFid
, 0);
503 afs_ResetVolumeInfo(tv
);
504 afs_PutVolume(tv
, 0);
505 /* invalidate mtpoint? */
507 } /*Clear callbacks for whole volume */
510 * Clear callbacks just for the one file.
514 if (a_fid
->Vnode
& 1)
515 afs_oddCBs
++; /*Could do this on volume basis, too */
517 afs_evenCBs
++; /*A particular fid was specified */
519 ObtainReadLock(&afs_xvcache
);
520 i
= VCHash(&localFid
);
521 for (tvc
= afs_vhashT
[i
]; tvc
; tvc
= uvc
) {
523 if (tvc
->f
.fid
.Fid
.Vnode
== a_fid
->Vnode
524 && tvc
->f
.fid
.Fid
.Volume
== a_fid
->Volume
525 && tvc
->f
.fid
.Fid
.Unique
== a_fid
->Unique
) {
526 tvc
->callback
= NULL
;
527 tvc
->dchint
= NULL
; /* invalidate hints */
528 if (tvc
->f
.states
& CVInit
) {
529 ReleaseReadLock(&afs_xvcache
);
530 afs_osi_Sleep(&tvc
->f
.states
);
533 #if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_HPUX_ENV) || defined(AFS_LINUX20_ENV)
536 #ifdef AFS_DARWIN80_ENV
537 if (tvc
->f
.states
& CDeadVnode
) {
538 ReleaseReadLock(&afs_xvcache
);
539 afs_osi_Sleep(&tvc
->f
.states
);
555 ReleaseReadLock(&afs_xvcache
);
556 afs_StaleVCacheFlags(tvc
, 0, CUnique
| CBulkFetching
);
557 afs_Trace3(afs_iclSetp
, CM_TRACE_CALLBACK
,
558 ICL_TYPE_POINTER
, tvc
, ICL_TYPE_INT32
,
559 tvc
->f
.states
, ICL_TYPE_LONG
, 0);
561 lastCallBack_vnode
= afid
->Vnode
;
562 lastCallBack_dv
= tvc
->mstat
.DataVersion
.low
;
563 osi_GetuTime(&lastCallBack_time
);
565 #ifdef AFS_DARWIN80_ENV
566 vnode_put(AFSTOV(tvc
));
568 ObtainReadLock(&afs_xvcache
);
572 } /*Walk through hash table */
573 ReleaseReadLock(&afs_xvcache
);
574 } /*Clear callbacks for one file */
577 /*Fid has non-zero volume ID */
579 * Always return a predictable value.
586 /*------------------------------------------------------------------------
587 * EXPORTED SRXAFSCB_CallBack
590 * Routine called by the server-side callback RPC interface to
591 * implement passing in callback information.
595 * a_call : Ptr to Rx call on which this request came in.
596 * a_fids : Ptr to array of fids involved.
597 * a_callbacks : Ptr to matching callback info for the fids.
603 * Nothing interesting.
607 *------------------------------------------------------------------------*/
610 SRXAFSCB_CallBack(struct rx_call
*a_call
, struct AFSCBFids
*a_fids
,
611 struct AFSCBs
*a_callbacks
)
613 int i
; /*Loop variable */
614 struct AFSFid
*tfid
; /*Ptr to current fid */
615 struct rx_connection
*tconn
; /*Call's connection */
621 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_CALLBACK
);
623 AFS_STATCNT(SRXAFSCB_CallBack
);
624 if (!(tconn
= rx_ConnectionOf(a_call
)))
626 tfid
= (struct AFSFid
*)a_fids
->AFSCBFids_val
;
629 * For now, we ignore callbacks, since the File Server only *breaks*
630 * callbacks at present.
632 for (i
= 0; i
< a_fids
->AFSCBFids_len
; i
++)
633 ClearCallBack(tconn
, &tfid
[i
]);
641 } /*SRXAFSCB_CallBack */
644 /*------------------------------------------------------------------------
645 * EXPORTED SRXAFSCB_Probe
648 * Routine called by the server-side callback RPC interface to
649 * implement ``probing'' the Cache Manager, just making sure it's
653 * a_call : Ptr to Rx call on which this request came in.
659 * Nothing interesting.
663 *------------------------------------------------------------------------*/
666 SRXAFSCB_Probe(struct rx_call
*a_call
)
672 AFS_STATCNT(SRXAFSCB_Probe
);
674 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_PROBE
);
681 } /*SRXAFSCB_Probe */
684 /*------------------------------------------------------------------------
685 * EXPORTED SRXAFSCB_InitCallBackState
688 * Routine called by the server-side callback RPC interface to
689 * implement clearing all callbacks from this host.
692 * a_call : Ptr to Rx call on which this request came in.
698 * Nothing interesting.
702 *------------------------------------------------------------------------*/
705 SRXAFSCB_InitCallBackState(struct rx_call
*a_call
)
709 struct rx_connection
*tconn
;
710 struct rx_peer
*peer
;
717 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_INITCALLBACKSTATE
);
718 AFS_STATCNT(SRXAFSCB_InitCallBackState
);
721 * Find the address of the host making this call
723 if ((tconn
= rx_ConnectionOf(a_call
)) && (peer
= rx_PeerOf(tconn
))) {
726 afs_oddCBs
++; /*Including any missed via create race */
727 afs_evenCBs
++; /*Including any missed via create race */
729 ts
= afs_FindServer(rx_HostOf(peer
), rx_PortOf(peer
), (afsUUID
*) 0,
732 for (i
= 0; i
< VCSIZE
; i
++)
733 for (tvc
= afs_vhashT
[i
]; tvc
; tvc
= tvc
->hnext
) {
734 if (tvc
->callback
== ts
) {
735 afs_StaleVCacheFlags(tvc
, AFS_STALEVC_NODNLC
|
737 CUnique
| CBulkFetching
);
741 /* capabilities need be requested again */
742 ts
->flags
&= ~SCAPS_KNOWN
;
747 /* find any volumes residing on this server and flush their state */
752 for (i
= 0; i
< NVOLS
; i
++)
753 for (tv
= afs_volumes
[i
]; tv
; tv
= tv
->next
) {
754 for (j
= 0; j
< AFS_MAXHOSTS
; j
++)
755 if (tv
->serverHost
[j
] == ts
)
756 afs_ResetVolumeInfo(tv
);
759 osi_dnlc_purge(); /* may be a little bit extreme */
768 } /*SRXAFSCB_InitCallBackState */
771 /*------------------------------------------------------------------------
772 * EXPORTED SRXAFSCB_XStatsVersion
775 * Routine called by the server-side callback RPC interface to
776 * implement pulling out the xstat version number for the Cache
780 * a_versionP : Ptr to the version number variable to set.
786 * Nothing interesting.
790 *------------------------------------------------------------------------*/
793 SRXAFSCB_XStatsVersion(struct rx_call
*a_call
, afs_int32
* a_versionP
)
800 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_XSTATSVERSION
);
802 *a_versionP
= AFSCB_XSTAT_VERSION
;
809 } /*SRXAFSCB_XStatsVersion */
812 /*------------------------------------------------------------------------
813 * EXPORTED SRXAFSCB_GetXStats
816 * Routine called by the server-side callback RPC interface to
817 * implement getting the given data collection from the extended
818 * Cache Manager statistics.
821 * a_call : Ptr to Rx call on which this request came in.
822 * a_clientVersionNum : Client version number.
823 * a_opCode : Desired operation.
824 * a_serverVersionNumP : Ptr to version number to set.
825 * a_timeP : Ptr to time value (seconds) to set.
826 * a_dataArray : Ptr to variable array structure to return
833 * Nothing interesting.
837 *------------------------------------------------------------------------*/
840 SRXAFSCB_GetXStats(struct rx_call
*a_call
, afs_int32 a_clientVersionNum
,
841 afs_int32 a_collectionNumber
, afs_int32
* a_srvVersionNumP
,
842 afs_int32
* a_timeP
, AFSCB_CollData
* a_dataP
)
844 int code
; /*Return value */
845 afs_int32
*dataBuffP
; /*Ptr to data to be returned */
846 afs_int32 dataBytes
; /*Bytes in data buffer */
851 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_GETXSTATS
);
854 * Record the time of day and the server version number.
856 *a_srvVersionNumP
= AFSCB_XSTAT_VERSION
;
857 *a_timeP
= osi_Time();
860 * Stuff the appropriate data in there (assume victory)
866 * We're not keeping stats, so just return successfully with
869 a_dataP
->AFSCB_CollData_len
= 0;
870 a_dataP
->AFSCB_CollData_val
= NULL
;
872 switch (a_collectionNumber
) {
873 case AFSCB_XSTATSCOLL_CALL_INFO
:
875 * Pass back all the call-count-related data.
877 * >>> We are forced to allocate a separate area in which to
878 * >>> put this stuff in by the RPC stub generator, since it
879 * >>> will be freed at the tail end of the server stub code.
881 dataBytes
= sizeof(struct afs_CMStats
);
882 dataBuffP
= (afs_int32
*) afs_osi_Alloc(dataBytes
);
883 osi_Assert(dataBuffP
!= NULL
);
884 memcpy((char *)dataBuffP
, (char *)&afs_cmstats
, dataBytes
);
885 a_dataP
->AFSCB_CollData_len
= dataBytes
>> 2;
886 a_dataP
->AFSCB_CollData_val
= dataBuffP
;
889 case AFSCB_XSTATSCOLL_PERF_INFO
:
891 * Update and then pass back all the performance-related data.
892 * Note: the only performance fields that need to be computed
893 * at this time are the number of accesses for this collection
894 * and the current server record info.
896 * >>> We are forced to allocate a separate area in which to
897 * >>> put this stuff in by the RPC stub generator, since it
898 * >>> will be freed at the tail end of the server stub code.
900 afs_stats_cmperf
.numPerfCalls
++;
902 dataBytes
= sizeof(afs_stats_cmperf
);
903 dataBuffP
= (afs_int32
*) afs_osi_Alloc(dataBytes
);
904 osi_Assert(dataBuffP
!= NULL
);
905 memcpy((char *)dataBuffP
, (char *)&afs_stats_cmperf
, dataBytes
);
906 a_dataP
->AFSCB_CollData_len
= dataBytes
>> 2;
907 a_dataP
->AFSCB_CollData_val
= dataBuffP
;
910 case AFSCB_XSTATSCOLL_FULL_PERF_INFO
:
912 * Pass back the full range of performance and statistical
913 * data available. We have to bring the normal performance
914 * data collection up to date, then copy that data into
915 * the full collection.
917 * >>> We are forced to allocate a separate area in which to
918 * >>> put this stuff in by the RPC stub generator, since it
919 * >>> will be freed at the tail end of the server stub code.
921 afs_stats_cmperf
.numPerfCalls
++;
923 memcpy((char *)(&(afs_stats_cmfullperf
.perf
)),
924 (char *)(&afs_stats_cmperf
), sizeof(struct afs_stats_CMPerf
));
925 afs_stats_cmfullperf
.numFullPerfCalls
++;
927 dataBytes
= sizeof(afs_stats_cmfullperf
);
928 dataBuffP
= (afs_int32
*) afs_osi_Alloc(dataBytes
);
929 osi_Assert(dataBuffP
!= NULL
);
930 memcpy((char *)dataBuffP
, (char *)(&afs_stats_cmfullperf
), dataBytes
);
931 a_dataP
->AFSCB_CollData_len
= dataBytes
>> 2;
932 a_dataP
->AFSCB_CollData_val
= dataBuffP
;
937 * Illegal collection number.
939 a_dataP
->AFSCB_CollData_len
= 0;
940 a_dataP
->AFSCB_CollData_val
= NULL
;
942 } /*Switch on collection number */
943 #endif /* AFS_NOSTATS */
951 } /*SRXAFSCB_GetXStats */
954 /*------------------------------------------------------------------------
955 * EXPORTED afs_RXCallBackServer
958 * Body of the thread supporting callback services.
967 * Nothing interesting.
971 *------------------------------------------------------------------------*/
974 afs_RXCallBackServer(void)
976 AFS_STATCNT(afs_RXCallBackServer
);
981 afs_osi_Sleep(&afs_server
);
985 * Donate this process to Rx.
990 } /*afs_RXCallBackServer */
993 /*------------------------------------------------------------------------
994 * EXPORTED shutdown_CB
997 * Zero out important Cache Manager data structures.
1006 * Nothing interesting.
1010 *------------------------------------------------------------------------*/
1015 AFS_STATCNT(shutdown_CB
);
1017 if (afs_cold_shutdown
) {
1018 afs_oddCBs
= afs_evenCBs
= afs_allCBs
= afs_allZaps
= afs_oddZaps
=
1019 afs_evenZaps
= afs_connectBacks
= 0;
1026 /*------------------------------------------------------------------------
1027 * EXPORTED SRXAFSCB_InitCallBackState2
1030 * This routine was used in the AFS 3.5 beta release, but not anymore.
1031 * It has since been replaced by SRXAFSCB_InitCallBackState3.
1034 * a_call : Ptr to Rx call on which this request came in.
1037 * RXGEN_OPCODE (always).
1040 * Nothing interesting.
1044 *------------------------------------------------------------------------*/
1047 SRXAFSCB_InitCallBackState2(struct rx_call
*a_call
,
1048 struct interfaceAddr
*addr
)
1050 return RXGEN_OPCODE
;
1053 /*------------------------------------------------------------------------
1054 * EXPORTED SRXAFSCB_WhoAreYou
1057 * Routine called by the server-side callback RPC interface to
1058 * obtain a unique identifier for the client. The server uses
1059 * this identifier to figure out whether or not two RX connections
1060 * are from the same client, and to find out which addresses go
1061 * with which clients.
1064 * a_call : Ptr to Rx call on which this request came in.
1065 * addr: Ptr to return the list of interfaces for this client.
1071 * Nothing interesting.
1075 *------------------------------------------------------------------------*/
1078 SRXAFSCB_WhoAreYou(struct rx_call
*a_call
, struct interfaceAddr
*addr
)
1085 AFS_STATCNT(SRXAFSCB_WhoAreYou
);
1087 memset(addr
, 0, sizeof(*addr
));
1089 ObtainReadLock(&afs_xinterface
);
1091 /* return all network interface addresses */
1092 addr
->numberOfInterfaces
= afs_cb_interface
.numberOfInterfaces
;
1093 addr
->uuid
= afs_cb_interface
.uuid
;
1094 for (i
= 0; i
< afs_cb_interface
.numberOfInterfaces
; i
++) {
1095 addr
->addr_in
[i
] = ntohl(afs_cb_interface
.addr_in
[i
]);
1096 addr
->subnetmask
[i
] = ntohl(afs_cb_interface
.subnetmask
[i
]);
1097 addr
->mtu
[i
] = ntohl(afs_cb_interface
.mtu
[i
]);
1100 ReleaseReadLock(&afs_xinterface
);
1108 /*------------------------------------------------------------------------
1109 * EXPORTED SRXAFSCB_InitCallBackState3
1112 * Routine called by the server-side callback RPC interface to
1113 * implement clearing all callbacks from this host.
1116 * a_call : Ptr to Rx call on which this request came in.
1122 * Nothing interesting.
1126 *------------------------------------------------------------------------*/
1129 SRXAFSCB_InitCallBackState3(struct rx_call
*a_call
, afsUUID
* a_uuid
)
1134 * TBD: Lookup the server by the UUID instead of its IP address.
1136 code
= SRXAFSCB_InitCallBackState(a_call
);
1142 /*------------------------------------------------------------------------
1143 * EXPORTED SRXAFSCB_ProbeUuid
1146 * Routine called by the server-side callback RPC interface to
1147 * implement ``probing'' the Cache Manager, just making sure it's
1148 * still there is still the same client it used to be.
1151 * a_call : Ptr to Rx call on which this request came in.
1152 * a_uuid : Ptr to UUID that must match the client's UUID.
1155 * 0 if a_uuid matches the UUID for this client
1156 * Non-zero otherwize
1159 * Nothing interesting.
1163 *------------------------------------------------------------------------*/
1166 SRXAFSCB_ProbeUuid(struct rx_call
*a_call
, afsUUID
* a_uuid
)
1172 AFS_STATCNT(SRXAFSCB_Probe
);
1174 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_PROBE
);
1175 if (!afs_uuid_equal(a_uuid
, &afs_cb_interface
.uuid
))
1176 code
= 1; /* failure */
1185 /*------------------------------------------------------------------------
1186 * EXPORTED SRXAFSCB_GetServerPrefs
1189 * Routine to list server preferences used by this client.
1192 * a_call : Ptr to Rx call on which this request came in.
1193 * a_index : Input server index
1194 * a_srvr_addr : Output server address in host byte order
1195 * (0xffffffff on last server)
1196 * a_srvr_rank : Output server rank
1202 * Nothing interesting.
1206 *------------------------------------------------------------------------*/
1209 SRXAFSCB_GetServerPrefs(struct rx_call
*a_call
, afs_int32 a_index
,
1210 afs_int32
* a_srvr_addr
, afs_int32
* a_srvr_rank
)
1216 AFS_STATCNT(SRXAFSCB_GetServerPrefs
);
1218 ObtainReadLock(&afs_xserver
);
1220 /* Search the hash table for the server with this index */
1221 *a_srvr_addr
= 0xffffffff;
1222 *a_srvr_rank
= 0xffffffff;
1223 for (i
= 0, j
= 0; j
< NSERVERS
&& i
<= a_index
; j
++) {
1224 for (sa
= afs_srvAddrs
[j
]; sa
&& i
<= a_index
; sa
= sa
->next_bkt
, i
++) {
1226 *a_srvr_addr
= ntohl(sa
->sa_ip
);
1227 *a_srvr_rank
= sa
->sa_iprank
;
1232 ReleaseReadLock(&afs_xserver
);
1240 /*------------------------------------------------------------------------
1241 * EXPORTED SRXAFSCB_GetCellServDB
1244 * Routine to list cells configured for this client
1247 * a_call : Ptr to Rx call on which this request came in.
1248 * a_index : Input cell index
1249 * a_name : Output cell name ("" on last cell)
1250 * a_hosts : Output cell database servers in host byte order.
1256 * Nothing interesting.
1260 *------------------------------------------------------------------------*/
1263 SRXAFSCB_GetCellServDB(struct rx_call
*a_call
, afs_int32 a_index
,
1264 char **a_name
, serverList
* a_hosts
)
1268 char *t_name
, *p_name
= NULL
;
1271 AFS_STATCNT(SRXAFSCB_GetCellServDB
);
1273 tcell
= afs_GetCellByIndex(a_index
, READ_LOCK
);
1277 a_hosts
->serverList_val
= 0;
1278 a_hosts
->serverList_len
= 0;
1280 p_name
= tcell
->cellName
;
1281 for (j
= 0; j
< AFSMAXCELLHOSTS
&& tcell
->cellHosts
[j
]; j
++);
1283 a_hosts
->serverList_val
= afs_osi_Alloc(j
* sizeof(afs_int32
));
1284 osi_Assert(a_hosts
->serverList_val
!= NULL
);
1285 a_hosts
->serverList_len
= j
;
1286 for (j
= 0; j
< AFSMAXCELLHOSTS
&& tcell
->cellHosts
[j
]; j
++)
1287 a_hosts
->serverList_val
[j
] =
1288 ntohl(tcell
->cellHosts
[j
]->addr
->sa_ip
);
1289 afs_PutCell(tcell
, READ_LOCK
);
1292 t_name
= afs_osi_Alloc(i
+ 1);
1293 if (t_name
== NULL
) {
1295 afs_osi_Free(a_hosts
->serverList_val
, (j
* sizeof(afs_int32
)));
1302 memcpy(t_name
, p_name
, i
);
1311 /*------------------------------------------------------------------------
1312 * EXPORTED SRXAFSCB_GetLocalCell
1315 * Routine to return name of client's local cell
1318 * a_call : Ptr to Rx call on which this request came in.
1319 * a_name : Output cell name
1325 * Nothing interesting.
1329 *------------------------------------------------------------------------*/
1332 SRXAFSCB_GetLocalCell(struct rx_call
*a_call
, char **a_name
)
1336 char *t_name
, *p_name
= NULL
;
1339 AFS_STATCNT(SRXAFSCB_GetLocalCell
);
1341 /* Search the list for the primary cell. Cell number 1 is only
1342 * the primary cell is when no other cell is explicitly marked as
1343 * the primary cell. */
1344 tcell
= afs_GetPrimaryCell(READ_LOCK
);
1346 p_name
= tcell
->cellName
;
1348 plen
= strlen(p_name
);
1351 t_name
= afs_osi_Alloc(plen
+ 1);
1352 if (t_name
== NULL
) {
1354 afs_PutCell(tcell
, READ_LOCK
);
1359 t_name
[plen
] = '\0';
1361 memcpy(t_name
, p_name
, plen
);
1367 afs_PutCell(tcell
, READ_LOCK
);
1373 * afs_MarshallCacheConfig - marshall client cache configuration
1377 * IN callerVersion - the rpc stat version of the caller.
1379 * IN config - client cache configuration.
1381 * OUT ptr - buffer where configuration is marshalled.
1388 afs_MarshallCacheConfig(afs_uint32 callerVersion
, cm_initparams_v1
* config
,
1391 AFS_STATCNT(afs_MarshallCacheConfig
);
1393 * We currently only support version 1.
1395 *(ptr
++) = config
->nChunkFiles
;
1396 *(ptr
++) = config
->nStatCaches
;
1397 *(ptr
++) = config
->nDataCaches
;
1398 *(ptr
++) = config
->nVolumeCaches
;
1399 *(ptr
++) = config
->firstChunkSize
;
1400 *(ptr
++) = config
->otherChunkSize
;
1401 *(ptr
++) = config
->cacheSize
;
1402 *(ptr
++) = config
->setTime
;
1403 *(ptr
++) = config
->memCache
;
1407 /*------------------------------------------------------------------------
1408 * EXPORTED SRXAFSCB_GetCacheConfig
1411 * Routine to return parameters used to initialize client cache.
1412 * Client may request any format version. Server may not return
1413 * format version greater than version requested by client.
1416 * a_call: Ptr to Rx call on which this request came in.
1417 * callerVersion: Data format version desired by the client.
1418 * serverVersion: Data format version of output data.
1419 * configCount: Number bytes allocated for output data.
1420 * config: Client cache configuration.
1426 * Nothing interesting.
1430 *------------------------------------------------------------------------*/
1433 SRXAFSCB_GetCacheConfig(struct rx_call
*a_call
, afs_uint32 callerVersion
,
1434 afs_uint32
* serverVersion
, afs_uint32
* configCount
,
1435 cacheConfig
* config
)
1437 afs_uint32
*t_config
;
1439 cm_initparams_v1 cm_config
;
1442 AFS_STATCNT(SRXAFSCB_GetCacheConfig
);
1445 * Currently only support version 1
1447 allocsize
= sizeof(cm_initparams_v1
);
1448 t_config
= afs_osi_Alloc(allocsize
);
1449 if (t_config
== NULL
) {
1454 cm_config
.nChunkFiles
= cm_initParams
.cmi_nChunkFiles
;
1455 cm_config
.nStatCaches
= cm_initParams
.cmi_nStatCaches
;
1456 cm_config
.nDataCaches
= cm_initParams
.cmi_nDataCaches
;
1457 cm_config
.nVolumeCaches
= cm_initParams
.cmi_nVolumeCaches
;
1458 cm_config
.firstChunkSize
= cm_initParams
.cmi_firstChunkSize
;
1459 cm_config
.otherChunkSize
= cm_initParams
.cmi_otherChunkSize
;
1460 cm_config
.cacheSize
= cm_initParams
.cmi_cacheSize
;
1461 cm_config
.setTime
= cm_initParams
.cmi_setTime
;
1462 cm_config
.memCache
= cm_initParams
.cmi_memCache
;
1464 afs_MarshallCacheConfig(callerVersion
, &cm_config
, t_config
);
1466 *serverVersion
= AFS_CLIENT_RETRIEVAL_FIRST_EDITION
;
1467 *configCount
= allocsize
;
1468 config
->cacheConfig_val
= t_config
;
1469 config
->cacheConfig_len
= allocsize
/ sizeof(afs_uint32
);
1476 /*------------------------------------------------------------------------
1477 * EXPORTED SRXAFSCB_FetchData
1480 * Routine to do third party move from a remioserver to the original
1481 * issuer of an ArchiveData request. Presently supported only by the
1482 * "fs" command, not by the AFS client.
1485 * rxcall: Ptr to Rx call on which this request came in.
1486 * Fid: pointer to AFSFid structure.
1487 * Fd: File descriptor inside fs command.
1488 * Position: Offset in the file.
1489 * Length: Data length to transfer.
1490 * TotalLength: Pointer to total file length field
1496 * Nothing interesting.
1499 *------------------------------------------------------------------------*/
1501 SRXAFSCB_FetchData(struct rx_call
*rxcall
, struct AFSFid
*Fid
, afs_int32 Fd
,
1502 afs_int64 Position
, afs_int64 Length
,
1503 afs_int64
* TotalLength
)
1508 /*------------------------------------------------------------------------
1509 * EXPORTED SRXAFSCB_StoreData
1512 * Routine to do third party move from a remioserver to the original
1513 * issuer of a RetrieveData request. Presently supported only by the
1514 * "fs" command, not by the AFS client.
1517 * rxcall: Ptr to Rx call on which this request came in.
1518 * Fid: pointer to AFSFid structure.
1519 * Fd: File descriptor inside fs command.
1520 * Position: Offset in the file.
1521 * Length: Data length to transfer.
1522 * TotalLength: Pointer to total file length field
1528 * Nothing interesting.
1532 *------------------------------------------------------------------------*/
1534 SRXAFSCB_StoreData(struct rx_call
*rxcall
, struct AFSFid
*Fid
, afs_int32 Fd
,
1535 afs_int64 Position
, afs_int64 Length
,
1536 afs_int64
* TotalLength
)
1541 /*------------------------------------------------------------------------
1542 * EXPORTED SRXAFSCB_GetCellByNum
1545 * Routine to get information about a cell specified by its
1546 * cell number (returned by GetCE/GetCE64).
1549 * a_call : Ptr to Rx call on which this request came in.
1550 * a_cellnum : Input cell number
1551 * a_name : Output cell name (one zero byte when no such cell).
1552 * a_hosts : Output cell database servers in host byte order.
1558 * Nothing interesting.
1562 *------------------------------------------------------------------------*/
1565 SRXAFSCB_GetCellByNum(struct rx_call
*a_call
, afs_int32 a_cellnum
,
1566 char **a_name
, serverList
* a_hosts
)
1572 AFS_STATCNT(SRXAFSCB_GetCellByNum
);
1574 a_hosts
->serverList_val
= 0;
1575 a_hosts
->serverList_len
= 0;
1577 tcell
= afs_GetCellStale(a_cellnum
, READ_LOCK
);
1579 *a_name
= afs_strdup("");
1584 ObtainReadLock(&tcell
->lock
);
1585 *a_name
= afs_strdup(tcell
->cellName
);
1587 for (sn
= 0; sn
< AFSMAXCELLHOSTS
&& tcell
->cellHosts
[sn
]; sn
++);
1588 a_hosts
->serverList_len
= sn
;
1589 a_hosts
->serverList_val
= afs_osi_Alloc(sn
* sizeof(afs_int32
));
1590 osi_Assert(a_hosts
->serverList_val
!= NULL
);
1592 for (i
= 0; i
< sn
; i
++)
1593 a_hosts
->serverList_val
[i
] = ntohl(tcell
->cellHosts
[i
]->addr
->sa_ip
);
1594 ReleaseReadLock(&tcell
->lock
);
1595 afs_PutCell(tcell
, READ_LOCK
);
1602 SRXAFSCB_TellMeAboutYourself(struct rx_call
*a_call
,
1603 struct interfaceAddr
*addr
,
1604 Capabilities
* capabilities
)
1608 afs_uint32
*dataBuffP
;
1609 afs_int32 dataBytes
;
1613 AFS_STATCNT(SRXAFSCB_WhoAreYou
);
1615 ObtainReadLock(&afs_xinterface
);
1617 /* return all network interface addresses */
1618 memset(addr
, 0, sizeof(*addr
));
1619 addr
->numberOfInterfaces
= afs_cb_interface
.numberOfInterfaces
;
1620 addr
->uuid
= afs_cb_interface
.uuid
;
1621 for (i
= 0; i
< afs_cb_interface
.numberOfInterfaces
; i
++) {
1622 addr
->addr_in
[i
] = ntohl(afs_cb_interface
.addr_in
[i
]);
1623 addr
->subnetmask
[i
] = ntohl(afs_cb_interface
.subnetmask
[i
]);
1624 addr
->mtu
[i
] = ntohl(afs_cb_interface
.mtu
[i
]);
1627 ReleaseReadLock(&afs_xinterface
);
1631 dataBytes
= 1 * sizeof(afs_uint32
);
1632 dataBuffP
= afs_osi_Alloc(dataBytes
);
1633 osi_Assert(dataBuffP
!= NULL
);
1634 dataBuffP
[0] = CLIENT_CAPABILITY_ERRORTRANS
;
1635 capabilities
->Capabilities_len
= dataBytes
/ sizeof(afs_uint32
);
1636 capabilities
->Capabilities_val
= dataBuffP
;
1642 #if 0 && defined(AFS_LINUX24_ENV)
1643 extern struct vcache
*afs_globalVp
;
1645 int recurse_dcache_parent(parent
, a_index
, addr
, inode
, flags
, time
, fileName
)
1646 struct dentry
* parent
;
1654 struct dentry
*this_parent
= parent
;
1655 struct list_head
*next
;
1657 struct dentry
*dentry
;
1660 next
= this_parent
->d_subdirs
.next
;
1662 while (next
!= &this_parent
->d_subdirs
) {
1663 struct list_head
*tmp
= next
;
1664 dentry
= list_entry(tmp
, struct dentry
, d_child
);
1670 * Descend a level if the d_subdirs list is non-empty.
1672 if (!list_empty(&dentry
->d_subdirs
)) {
1673 this_parent
= dentry
;
1678 * All done at this level ... ascend and resume the search.
1680 if (this_parent
!= parent
) {
1681 next
= this_parent
->d_child
.next
;
1682 this_parent
= this_parent
->d_parent
;
1688 if (d_unhashed(dentry
))
1693 *fileName
= afs_strdup(dentry
->d_name
.name
?dentry
->d_name
.name
:"");
1694 *inode
= ITOAFS(dentry
->d_inode
);
1695 *addr
= atomic_read(&(dentry
)->d_count
);
1696 *time
= dentry
->d_time
;
1705 SRXAFSCB_GetDE(struct rx_call
*a_call
, afs_int32 a_index
, afs_int32
*addr
,
1706 afs_int32
*inode
, afs_int32
*flags
, afs_int32
*time
,
1708 { /*SRXAFSCB_GetDE*/
1709 int code
= 0; /*Return code*/
1710 #if 0 && defined(AFS_LINUX24_ENV)
1711 int i
; /*Loop variable*/
1712 struct vcache
*tvc
= afs_globalVp
;
1713 struct dentry
*dentry
;
1714 struct list_head
*cur
, *head
= &(AFSTOI(tvc
))->i_dentry
;
1716 #ifdef RX_ENABLE_LOCKS
1718 #endif /* RX_ENABLE_LOCKS */
1720 #if defined(AFS_LINUX24_ENV)
1721 spin_lock(&dcache_lock
);
1725 while ((cur
= cur
->next
) != head
) {
1726 dentry
= list_entry(cur
, struct dentry
, d_alias
);
1728 dget_locked(dentry
);
1730 #if defined(AFS_LINUX24_ENV)
1731 spin_unlock(&dcache_lock
);
1737 if (recurse_dcache_parent(dentry
, a_index
, addr
, inode
, flags
, time
, fileName
) == 0) {
1748 *fileName
= afs_strdup("");
1752 if (d_unhashed(dentry
))
1757 *fileName
= afs_strdup(dentry
->d_name
.name
?dentry
->d_name
.name
:"");
1758 *inode
= ITOAFS(dentry
->d_inode
);
1759 *addr
= atomic_read(&(dentry
)->d_count
);
1760 *time
= dentry
->d_time
;
1767 #ifdef RX_ENABLE_LOCKS
1769 #endif /* RX_ENABLE_LOCKS */
1773 } /*SRXAFSCB_GetDE*/