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
},
63 { "afsdb_client_lock", (char *)&afsdb_client_lock
},
64 { "afsdb_req_lock", (char *)&afsdb_req_lock
},
65 { "afs_discon_lock", (char *)&afs_discon_lock
},
66 { "afs_disconDirtyLock", (char *)&afs_disconDirtyLock
},
67 { "afs_discon_vc_dirty", (char *)&afs_xvcdirty
},
68 { "afs_dynrootDirLock", (char *)&afs_dynrootDirLock
},
69 { "afs_dynSymlinkLock", (char *)&afs_dynSymlinkLock
},
71 unsigned long lastCallBack_vnode
;
72 unsigned int lastCallBack_dv
;
73 osi_timeval_t lastCallBack_time
;
75 /* these are for storing alternate interface addresses */
76 struct interfaceAddr afs_cb_interface
;
78 /*------------------------------------------------------------------------
79 * EXPORTED SRXAFSCB_GetCE
82 * Routine called by the server-side callback RPC interface to
83 * implement pulling out the contents of the i'th cache entry.
86 * a_call : Ptr to Rx call on which this request came in.
87 * a_index : Index of desired cache entry.
88 * a_result : Ptr to a buffer for the given cache entry.
91 * 0 if everything went fine,
92 * 1 if we were given a bad index.
95 * Nothing interesting.
99 *------------------------------------------------------------------------*/
102 SRXAFSCB_GetCE(struct rx_call
*a_call
, afs_int32 a_index
,
103 struct AFSDBCacheEntry
*a_result
)
106 int i
; /*Loop variable */
107 struct vcache
*tvc
; /*Ptr to current cache entry */
108 int code
; /*Return code */
113 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_GETCE
);
115 AFS_STATCNT(SRXAFSCB_GetCE
);
116 for (i
= 0; i
< VCSIZE
; i
++) {
117 for (tvc
= afs_vhashT
[i
]; tvc
; tvc
= tvc
->hnext
) {
121 } /*Zip through current hash chain */
122 } /*Zip through hash chains */
132 * Copy out the located entry.
134 a_result
->addr
= afs_data_pointer_to_int32(tvc
);
135 a_result
->cell
= tvc
->f
.fid
.Cell
;
136 a_result
->netFid
.Volume
= tvc
->f
.fid
.Fid
.Volume
;
137 a_result
->netFid
.Vnode
= tvc
->f
.fid
.Fid
.Vnode
;
138 a_result
->netFid
.Unique
= tvc
->f
.fid
.Fid
.Unique
;
139 a_result
->lock
.waitStates
= tvc
->lock
.wait_states
;
140 a_result
->lock
.exclLocked
= tvc
->lock
.excl_locked
;
141 a_result
->lock
.readersReading
= tvc
->lock
.readers_reading
;
142 a_result
->lock
.numWaiting
= tvc
->lock
.num_waiting
;
143 #if defined(INSTRUMENT_LOCKS)
144 a_result
->lock
.pid_last_reader
= MyPidxx2Pid(tvc
->lock
.pid_last_reader
);
145 a_result
->lock
.pid_writer
= MyPidxx2Pid(tvc
->lock
.pid_writer
);
146 a_result
->lock
.src_indicator
= tvc
->lock
.src_indicator
;
148 /* On osf20 , the vcache does not maintain these three fields */
149 a_result
->lock
.pid_last_reader
= 0;
150 a_result
->lock
.pid_writer
= 0;
151 a_result
->lock
.src_indicator
= 0;
152 #endif /* INSTRUMENT_LOCKS */
153 #ifdef AFS_64BIT_CLIENT
154 a_result
->Length
= (afs_int32
) tvc
->f
.m
.Length
& 0xffffffff;
155 #else /* AFS_64BIT_CLIENT */
156 a_result
->Length
= tvc
->f
.m
.Length
;
157 #endif /* AFS_64BIT_CLIENT */
158 a_result
->DataVersion
= hgetlo(tvc
->f
.m
.DataVersion
);
159 a_result
->callback
= afs_data_pointer_to_int32(tvc
->callback
); /* XXXX Now a pointer; change it XXXX */
160 a_result
->cbExpires
= tvc
->cbExpires
;
161 if (tvc
->f
.states
& CVInit
) {
162 a_result
->refCount
= 1;
164 #ifdef AFS_DARWIN80_ENV
165 a_result
->refCount
= vnode_isinuse(AFSTOV(tvc
),0)?1:0; /* XXX fix */
167 a_result
->refCount
= VREFCOUNT(tvc
);
170 a_result
->opens
= tvc
->opens
;
171 a_result
->writers
= tvc
->execsOrWriters
;
172 a_result
->mvstat
= tvc
->mvstat
;
173 a_result
->states
= tvc
->f
.states
;
177 * Return our results.
186 } /*SRXAFSCB_GetCE */
189 SRXAFSCB_GetCE64(struct rx_call
*a_call
, afs_int32 a_index
,
190 struct AFSDBCacheEntry64
*a_result
)
192 int i
; /*Loop variable */
193 struct vcache
*tvc
; /*Ptr to current cache entry */
194 int code
; /*Return code */
199 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_GETCE
);
201 AFS_STATCNT(SRXAFSCB_GetCE64
);
202 for (i
= 0; i
< VCSIZE
; i
++) {
203 for (tvc
= afs_vhashT
[i
]; tvc
; tvc
= tvc
->hnext
) {
207 } /*Zip through current hash chain */
208 } /*Zip through hash chains */
218 * Copy out the located entry.
220 a_result
->addr
= afs_data_pointer_to_int32(tvc
);
221 a_result
->cell
= tvc
->f
.fid
.Cell
;
222 a_result
->netFid
.Volume
= tvc
->f
.fid
.Fid
.Volume
;
223 a_result
->netFid
.Vnode
= tvc
->f
.fid
.Fid
.Vnode
;
224 a_result
->netFid
.Unique
= tvc
->f
.fid
.Fid
.Unique
;
225 a_result
->lock
.waitStates
= tvc
->lock
.wait_states
;
226 a_result
->lock
.exclLocked
= tvc
->lock
.excl_locked
;
227 a_result
->lock
.readersReading
= tvc
->lock
.readers_reading
;
228 a_result
->lock
.numWaiting
= tvc
->lock
.num_waiting
;
229 #if defined(INSTRUMENT_LOCKS)
230 a_result
->lock
.pid_last_reader
= MyPidxx2Pid(tvc
->lock
.pid_last_reader
);
231 a_result
->lock
.pid_writer
= MyPidxx2Pid(tvc
->lock
.pid_writer
);
232 a_result
->lock
.src_indicator
= tvc
->lock
.src_indicator
;
234 /* On osf20 , the vcache does not maintain these three fields */
235 a_result
->lock
.pid_last_reader
= 0;
236 a_result
->lock
.pid_writer
= 0;
237 a_result
->lock
.src_indicator
= 0;
238 #endif /* INSTRUMENT_LOCKS */
239 a_result
->Length
= tvc
->f
.m
.Length
;
240 a_result
->DataVersion
= hgetlo(tvc
->f
.m
.DataVersion
);
241 a_result
->callback
= afs_data_pointer_to_int32(tvc
->callback
); /* XXXX Now a pointer; change it XXXX */
242 a_result
->cbExpires
= tvc
->cbExpires
;
243 if (tvc
->f
.states
& CVInit
) {
244 a_result
->refCount
= 1;
246 #ifdef AFS_DARWIN80_ENV
247 a_result
->refCount
= vnode_isinuse(AFSTOV(tvc
),0)?1:0; /* XXX fix */
249 a_result
->refCount
= VREFCOUNT(tvc
);
252 a_result
->opens
= tvc
->opens
;
253 a_result
->writers
= tvc
->execsOrWriters
;
254 a_result
->mvstat
= tvc
->mvstat
;
255 a_result
->states
= tvc
->f
.states
;
259 * Return our results.
268 } /*SRXAFSCB_GetCE64 */
271 /*------------------------------------------------------------------------
272 * EXPORTED SRXAFSCB_GetLock
275 * Routine called by the server-side callback RPC interface to
276 * implement pulling out the contents of a lock in the lock
280 * a_call : Ptr to Rx call on which this request came in.
281 * a_index : Index of desired lock.
282 * a_result : Ptr to a buffer for the given lock.
285 * 0 if everything went fine,
286 * 1 if we were given a bad index.
289 * Nothing interesting.
293 *------------------------------------------------------------------------*/
296 SRXAFSCB_GetLock(struct rx_call
*a_call
, afs_int32 a_index
,
297 struct AFSDBLock
*a_result
)
299 struct ltable
*tl
; /*Ptr to lock table entry */
300 int nentries
; /*Num entries in table */
301 int code
; /*Return code */
306 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_GETLOCK
);
308 AFS_STATCNT(SRXAFSCB_GetLock
);
309 nentries
= sizeof(ltable
) / sizeof(struct ltable
);
310 if (a_index
< 0 || a_index
>= nentries
+afs_cellindex
) {
315 } else if (a_index
>= nentries
) {
316 struct cell
*tc
= afs_GetCellByIndex(a_index
-nentries
, 0);
317 strcpy(a_result
->name
, tc
->cellName
);
318 a_result
->lock
.waitStates
=
319 ((struct afs_lock
*)&(tc
->lock
))->wait_states
;
320 a_result
->lock
.exclLocked
=
321 ((struct afs_lock
*)&(tc
->lock
))->excl_locked
;
322 a_result
->lock
.readersReading
=
323 ((struct afs_lock
*)&(tc
->lock
))->readers_reading
;
324 a_result
->lock
.numWaiting
=
325 ((struct afs_lock
*)&(tc
->lock
))->num_waiting
;
326 #ifdef INSTRUMENT_LOCKS
327 a_result
->lock
.pid_last_reader
=
328 MyPidxx2Pid(((struct afs_lock
*)&(tc
->lock
))->pid_last_reader
);
329 a_result
->lock
.pid_writer
=
330 MyPidxx2Pid(((struct afs_lock
*)&(tc
->lock
))->pid_writer
);
331 a_result
->lock
.src_indicator
=
332 ((struct afs_lock
*)&(tc
->lock
))->src_indicator
;
334 a_result
->lock
.pid_last_reader
= 0;
335 a_result
->lock
.pid_writer
= 0;
336 a_result
->lock
.src_indicator
= 0;
341 * Found it - copy out its contents.
343 tl
= <able
[a_index
];
344 strcpy(a_result
->name
, tl
->name
);
345 a_result
->lock
.waitStates
=
346 ((struct afs_lock
*)(tl
->addr
))->wait_states
;
347 a_result
->lock
.exclLocked
=
348 ((struct afs_lock
*)(tl
->addr
))->excl_locked
;
349 a_result
->lock
.readersReading
=
350 ((struct afs_lock
*)(tl
->addr
))->readers_reading
;
351 a_result
->lock
.numWaiting
=
352 ((struct afs_lock
*)(tl
->addr
))->num_waiting
;
353 #ifdef INSTRUMENT_LOCKS
354 a_result
->lock
.pid_last_reader
=
355 MyPidxx2Pid(((struct afs_lock
*)(tl
->addr
))->pid_last_reader
);
356 a_result
->lock
.pid_writer
=
357 MyPidxx2Pid(((struct afs_lock
*)(tl
->addr
))->pid_writer
);
358 a_result
->lock
.src_indicator
=
359 ((struct afs_lock
*)(tl
->addr
))->src_indicator
;
361 a_result
->lock
.pid_last_reader
= 0;
362 a_result
->lock
.pid_writer
= 0;
363 a_result
->lock
.src_indicator
= 0;
374 } /*SRXAFSCB_GetLock */
377 /*------------------------------------------------------------------------
378 * static ClearCallBack
381 * Clear out callback information for the specified file, or
382 * even a whole volume. Used to worry about callback was from
383 * within the particular cell or not. Now we don't bother with
384 * that anymore; it's not worth the time.
387 * a_conn : Ptr to Rx connection involved.
388 * a_fid : Ptr to AFS fid being cleared.
394 * Nothing interesting.
399 Appears to need to be called with GLOCK held, as the icl_Event4 stuff asserts otherwise
401 *------------------------------------------------------------------------*/
404 ClearCallBack(struct rx_connection
*a_conn
,
405 struct AFSFid
*a_fid
)
409 struct VenusFid localFid
;
411 #ifdef AFS_DARWIN80_ENV
415 AFS_STATCNT(ClearCallBack
);
420 * XXXX Don't hold any server locks here because of callback protocol XXX
423 localFid
.Fid
.Volume
= a_fid
->Volume
;
424 localFid
.Fid
.Vnode
= a_fid
->Vnode
;
425 localFid
.Fid
.Unique
= a_fid
->Unique
;
428 * Volume ID of zero means don't do anything.
430 if (a_fid
->Volume
!= 0) {
431 if (a_fid
->Vnode
== 0) {
432 struct afs_q
*tq
, *uq
;
434 * Clear callback for the whole volume. Zip through the
435 * hash chain, nullifying entries whose volume ID matches.
438 ObtainReadLock(&afs_xvcache
);
439 i
= VCHashV(&localFid
);
440 for (tq
= afs_vhashTV
[i
].prev
; tq
!= &afs_vhashTV
[i
]; tq
= uq
) {
443 if (tvc
->f
.fid
.Fid
.Volume
== a_fid
->Volume
) {
444 tvc
->callback
= NULL
;
446 localFid
.Cell
= tvc
->f
.fid
.Cell
;
447 tvc
->dchint
= NULL
; /* invalidate hints */
448 if (tvc
->f
.states
& CVInit
) {
449 ReleaseReadLock(&afs_xvcache
);
450 afs_osi_Sleep(&tvc
->f
.states
);
453 #if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_HPUX_ENV) || defined(AFS_LINUX20_ENV)
456 #ifdef AFS_DARWIN80_ENV
457 if (tvc
->f
.states
& CDeadVnode
) {
458 ReleaseReadLock(&afs_xvcache
);
459 afs_osi_Sleep(&tvc
->f
.states
);
475 ReleaseReadLock(&afs_xvcache
);
476 afs_StaleVCacheFlags(tvc
, 0, CUnique
| CBulkFetching
);
478 if (tvc
->f
.fid
.Fid
.Vnode
& 1)
482 afs_Trace3(afs_iclSetp
, CM_TRACE_CALLBACK
,
483 ICL_TYPE_POINTER
, tvc
, ICL_TYPE_INT32
,
484 tvc
->f
.states
, ICL_TYPE_INT32
,
486 #ifdef AFS_DARWIN80_ENV
487 vnode_put(AFSTOV(tvc
));
489 ObtainReadLock(&afs_xvcache
);
492 } else if ((tvc
->f
.states
& CMValid
)
493 && (tvc
->mvid
.target_root
->Fid
.Volume
== a_fid
->Volume
)) {
494 tvc
->f
.states
&= ~CMValid
;
496 localFid
.Cell
= tvc
->mvid
.target_root
->Cell
;
499 ReleaseReadLock(&afs_xvcache
);
502 * XXXX Don't hold any locks here XXXX
504 tv
= afs_FindVolume(&localFid
, 0);
506 afs_ResetVolumeInfo(tv
);
507 afs_PutVolume(tv
, 0);
508 /* invalidate mtpoint? */
510 } /*Clear callbacks for whole volume */
513 * Clear callbacks just for the one file.
517 if (a_fid
->Vnode
& 1)
518 afs_oddCBs
++; /*Could do this on volume basis, too */
520 afs_evenCBs
++; /*A particular fid was specified */
522 ObtainReadLock(&afs_xvcache
);
523 i
= VCHash(&localFid
);
524 for (tvc
= afs_vhashT
[i
]; tvc
; tvc
= uvc
) {
526 if (tvc
->f
.fid
.Fid
.Vnode
== a_fid
->Vnode
527 && tvc
->f
.fid
.Fid
.Volume
== a_fid
->Volume
528 && tvc
->f
.fid
.Fid
.Unique
== a_fid
->Unique
) {
529 tvc
->callback
= NULL
;
530 tvc
->dchint
= NULL
; /* invalidate hints */
531 if (tvc
->f
.states
& CVInit
) {
532 ReleaseReadLock(&afs_xvcache
);
533 afs_osi_Sleep(&tvc
->f
.states
);
536 #if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_HPUX_ENV) || defined(AFS_LINUX20_ENV)
539 #ifdef AFS_DARWIN80_ENV
540 if (tvc
->f
.states
& CDeadVnode
) {
541 ReleaseReadLock(&afs_xvcache
);
542 afs_osi_Sleep(&tvc
->f
.states
);
558 ReleaseReadLock(&afs_xvcache
);
559 afs_StaleVCacheFlags(tvc
, 0, CUnique
| CBulkFetching
);
560 afs_Trace3(afs_iclSetp
, CM_TRACE_CALLBACK
,
561 ICL_TYPE_POINTER
, tvc
, ICL_TYPE_INT32
,
562 tvc
->f
.states
, ICL_TYPE_LONG
, 0);
564 lastCallBack_vnode
= afid
->Vnode
;
565 lastCallBack_dv
= tvc
->mstat
.DataVersion
.low
;
566 osi_GetuTime(&lastCallBack_time
);
568 #ifdef AFS_DARWIN80_ENV
569 vnode_put(AFSTOV(tvc
));
571 ObtainReadLock(&afs_xvcache
);
575 } /*Walk through hash table */
576 ReleaseReadLock(&afs_xvcache
);
577 } /*Clear callbacks for one file */
580 /*Fid has non-zero volume ID */
582 * Always return a predictable value.
589 /*------------------------------------------------------------------------
590 * EXPORTED SRXAFSCB_CallBack
593 * Routine called by the server-side callback RPC interface to
594 * implement passing in callback information.
598 * a_call : Ptr to Rx call on which this request came in.
599 * a_fids : Ptr to array of fids involved.
600 * a_callbacks : Ptr to matching callback info for the fids.
606 * Nothing interesting.
610 *------------------------------------------------------------------------*/
613 SRXAFSCB_CallBack(struct rx_call
*a_call
, struct AFSCBFids
*a_fids
,
614 struct AFSCBs
*a_callbacks
)
616 int i
; /*Loop variable */
617 struct AFSFid
*tfid
; /*Ptr to current fid */
618 struct rx_connection
*tconn
; /*Call's connection */
624 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_CALLBACK
);
626 AFS_STATCNT(SRXAFSCB_CallBack
);
627 if (!(tconn
= rx_ConnectionOf(a_call
)))
629 tfid
= (struct AFSFid
*)a_fids
->AFSCBFids_val
;
632 * For now, we ignore callbacks, since the File Server only *breaks*
633 * callbacks at present.
635 for (i
= 0; i
< a_fids
->AFSCBFids_len
; i
++)
636 ClearCallBack(tconn
, &tfid
[i
]);
644 } /*SRXAFSCB_CallBack */
647 /*------------------------------------------------------------------------
648 * EXPORTED SRXAFSCB_Probe
651 * Routine called by the server-side callback RPC interface to
652 * implement ``probing'' the Cache Manager, just making sure it's
656 * a_call : Ptr to Rx call on which this request came in.
662 * Nothing interesting.
666 *------------------------------------------------------------------------*/
669 SRXAFSCB_Probe(struct rx_call
*a_call
)
675 AFS_STATCNT(SRXAFSCB_Probe
);
677 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_PROBE
);
684 } /*SRXAFSCB_Probe */
687 /*------------------------------------------------------------------------
688 * EXPORTED SRXAFSCB_InitCallBackState
691 * Routine called by the server-side callback RPC interface to
692 * implement clearing all callbacks from this host.
695 * a_call : Ptr to Rx call on which this request came in.
701 * Nothing interesting.
705 *------------------------------------------------------------------------*/
708 SRXAFSCB_InitCallBackState(struct rx_call
*a_call
)
712 struct rx_connection
*tconn
;
713 struct rx_peer
*peer
;
720 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_INITCALLBACKSTATE
);
721 AFS_STATCNT(SRXAFSCB_InitCallBackState
);
724 * Find the address of the host making this call
726 if ((tconn
= rx_ConnectionOf(a_call
)) && (peer
= rx_PeerOf(tconn
))) {
729 afs_oddCBs
++; /*Including any missed via create race */
730 afs_evenCBs
++; /*Including any missed via create race */
732 ts
= afs_FindServer(rx_HostOf(peer
), rx_PortOf(peer
), (afsUUID
*) 0,
735 for (i
= 0; i
< VCSIZE
; i
++)
736 for (tvc
= afs_vhashT
[i
]; tvc
; tvc
= tvc
->hnext
) {
737 if (tvc
->callback
== ts
) {
738 afs_StaleVCacheFlags(tvc
, AFS_STALEVC_NODNLC
|
740 CUnique
| CBulkFetching
);
744 /* capabilities need be requested again */
745 ts
->flags
&= ~SCAPS_KNOWN
;
750 /* find any volumes residing on this server and flush their state */
755 for (i
= 0; i
< NVOLS
; i
++)
756 for (tv
= afs_volumes
[i
]; tv
; tv
= tv
->next
) {
757 for (j
= 0; j
< AFS_MAXHOSTS
; j
++)
758 if (tv
->serverHost
[j
] == ts
)
759 afs_ResetVolumeInfo(tv
);
762 osi_dnlc_purge(); /* may be a little bit extreme */
771 } /*SRXAFSCB_InitCallBackState */
774 /*------------------------------------------------------------------------
775 * EXPORTED SRXAFSCB_XStatsVersion
778 * Routine called by the server-side callback RPC interface to
779 * implement pulling out the xstat version number for the Cache
783 * a_versionP : Ptr to the version number variable to set.
789 * Nothing interesting.
793 *------------------------------------------------------------------------*/
796 SRXAFSCB_XStatsVersion(struct rx_call
*a_call
, afs_int32
* a_versionP
)
803 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_XSTATSVERSION
);
805 *a_versionP
= AFSCB_XSTAT_VERSION
;
812 } /*SRXAFSCB_XStatsVersion */
815 /*------------------------------------------------------------------------
816 * EXPORTED SRXAFSCB_GetXStats
819 * Routine called by the server-side callback RPC interface to
820 * implement getting the given data collection from the extended
821 * Cache Manager statistics.
824 * a_call : Ptr to Rx call on which this request came in.
825 * a_clientVersionNum : Client version number.
826 * a_opCode : Desired operation.
827 * a_serverVersionNumP : Ptr to version number to set.
828 * a_timeP : Ptr to time value (seconds) to set.
829 * a_dataArray : Ptr to variable array structure to return
836 * Nothing interesting.
840 *------------------------------------------------------------------------*/
843 SRXAFSCB_GetXStats(struct rx_call
*a_call
, afs_int32 a_clientVersionNum
,
844 afs_int32 a_collectionNumber
, afs_int32
* a_srvVersionNumP
,
845 afs_int32
* a_timeP
, AFSCB_CollData
* a_dataP
)
847 int code
; /*Return value */
848 afs_int32
*dataBuffP
; /*Ptr to data to be returned */
849 afs_int32 dataBytes
; /*Bytes in data buffer */
854 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_GETXSTATS
);
857 * Record the time of day and the server version number.
859 *a_srvVersionNumP
= AFSCB_XSTAT_VERSION
;
860 *a_timeP
= osi_Time();
863 * Stuff the appropriate data in there (assume victory)
869 * We're not keeping stats, so just return successfully with
872 a_dataP
->AFSCB_CollData_len
= 0;
873 a_dataP
->AFSCB_CollData_val
= NULL
;
875 switch (a_collectionNumber
) {
876 case AFSCB_XSTATSCOLL_CALL_INFO
:
878 * Pass back all the call-count-related data.
880 * >>> We are forced to allocate a separate area in which to
881 * >>> put this stuff in by the RPC stub generator, since it
882 * >>> will be freed at the tail end of the server stub code.
884 dataBytes
= sizeof(struct afs_CMStats
);
885 dataBuffP
= (afs_int32
*) afs_osi_Alloc(dataBytes
);
886 osi_Assert(dataBuffP
!= NULL
);
887 memcpy((char *)dataBuffP
, (char *)&afs_cmstats
, dataBytes
);
888 a_dataP
->AFSCB_CollData_len
= dataBytes
>> 2;
889 a_dataP
->AFSCB_CollData_val
= dataBuffP
;
892 case AFSCB_XSTATSCOLL_PERF_INFO
:
894 * Update and then pass back all the performance-related data.
895 * Note: the only performance fields that need to be computed
896 * at this time are the number of accesses for this collection
897 * and the current server record info.
899 * >>> We are forced to allocate a separate area in which to
900 * >>> put this stuff in by the RPC stub generator, since it
901 * >>> will be freed at the tail end of the server stub code.
903 afs_stats_cmperf
.numPerfCalls
++;
905 dataBytes
= sizeof(afs_stats_cmperf
);
906 dataBuffP
= (afs_int32
*) afs_osi_Alloc(dataBytes
);
907 osi_Assert(dataBuffP
!= NULL
);
908 memcpy((char *)dataBuffP
, (char *)&afs_stats_cmperf
, dataBytes
);
909 a_dataP
->AFSCB_CollData_len
= dataBytes
>> 2;
910 a_dataP
->AFSCB_CollData_val
= dataBuffP
;
913 case AFSCB_XSTATSCOLL_FULL_PERF_INFO
:
915 * Pass back the full range of performance and statistical
916 * data available. We have to bring the normal performance
917 * data collection up to date, then copy that data into
918 * the full collection.
920 * >>> We are forced to allocate a separate area in which to
921 * >>> put this stuff in by the RPC stub generator, since it
922 * >>> will be freed at the tail end of the server stub code.
924 afs_stats_cmperf
.numPerfCalls
++;
926 memcpy((char *)(&(afs_stats_cmfullperf
.perf
)),
927 (char *)(&afs_stats_cmperf
), sizeof(struct afs_stats_CMPerf
));
928 afs_stats_cmfullperf
.numFullPerfCalls
++;
930 dataBytes
= sizeof(afs_stats_cmfullperf
);
931 dataBuffP
= (afs_int32
*) afs_osi_Alloc(dataBytes
);
932 osi_Assert(dataBuffP
!= NULL
);
933 memcpy((char *)dataBuffP
, (char *)(&afs_stats_cmfullperf
), dataBytes
);
934 a_dataP
->AFSCB_CollData_len
= dataBytes
>> 2;
935 a_dataP
->AFSCB_CollData_val
= dataBuffP
;
940 * Illegal collection number.
942 a_dataP
->AFSCB_CollData_len
= 0;
943 a_dataP
->AFSCB_CollData_val
= NULL
;
945 } /*Switch on collection number */
946 #endif /* AFS_NOSTATS */
954 } /*SRXAFSCB_GetXStats */
957 /*------------------------------------------------------------------------
958 * EXPORTED afs_RXCallBackServer
961 * Body of the thread supporting callback services.
970 * Nothing interesting.
974 *------------------------------------------------------------------------*/
977 afs_RXCallBackServer(void)
979 AFS_STATCNT(afs_RXCallBackServer
);
984 afs_osi_Sleep(&afs_server
);
988 * Donate this process to Rx.
993 } /*afs_RXCallBackServer */
996 /*------------------------------------------------------------------------
997 * EXPORTED shutdown_CB
1000 * Zero out important Cache Manager data structures.
1009 * Nothing interesting.
1013 *------------------------------------------------------------------------*/
1018 AFS_STATCNT(shutdown_CB
);
1020 if (afs_cold_shutdown
) {
1021 afs_oddCBs
= afs_evenCBs
= afs_allCBs
= afs_allZaps
= afs_oddZaps
=
1022 afs_evenZaps
= afs_connectBacks
= 0;
1029 /*------------------------------------------------------------------------
1030 * EXPORTED SRXAFSCB_InitCallBackState2
1033 * This routine was used in the AFS 3.5 beta release, but not anymore.
1034 * It has since been replaced by SRXAFSCB_InitCallBackState3.
1037 * a_call : Ptr to Rx call on which this request came in.
1040 * RXGEN_OPCODE (always).
1043 * Nothing interesting.
1047 *------------------------------------------------------------------------*/
1050 SRXAFSCB_InitCallBackState2(struct rx_call
*a_call
,
1051 struct interfaceAddr
*addr
)
1053 return RXGEN_OPCODE
;
1056 /*------------------------------------------------------------------------
1057 * EXPORTED SRXAFSCB_WhoAreYou
1060 * Routine called by the server-side callback RPC interface to
1061 * obtain a unique identifier for the client. The server uses
1062 * this identifier to figure out whether or not two RX connections
1063 * are from the same client, and to find out which addresses go
1064 * with which clients.
1067 * a_call : Ptr to Rx call on which this request came in.
1068 * addr: Ptr to return the list of interfaces for this client.
1074 * Nothing interesting.
1078 *------------------------------------------------------------------------*/
1081 SRXAFSCB_WhoAreYou(struct rx_call
*a_call
, struct interfaceAddr
*addr
)
1088 AFS_STATCNT(SRXAFSCB_WhoAreYou
);
1090 memset(addr
, 0, sizeof(*addr
));
1092 ObtainReadLock(&afs_xinterface
);
1094 /* return all network interface addresses */
1095 addr
->numberOfInterfaces
= afs_cb_interface
.numberOfInterfaces
;
1096 addr
->uuid
= afs_cb_interface
.uuid
;
1097 for (i
= 0; i
< afs_cb_interface
.numberOfInterfaces
; i
++) {
1098 addr
->addr_in
[i
] = ntohl(afs_cb_interface
.addr_in
[i
]);
1099 addr
->subnetmask
[i
] = ntohl(afs_cb_interface
.subnetmask
[i
]);
1100 addr
->mtu
[i
] = ntohl(afs_cb_interface
.mtu
[i
]);
1103 ReleaseReadLock(&afs_xinterface
);
1111 /*------------------------------------------------------------------------
1112 * EXPORTED SRXAFSCB_InitCallBackState3
1115 * Routine called by the server-side callback RPC interface to
1116 * implement clearing all callbacks from this host.
1119 * a_call : Ptr to Rx call on which this request came in.
1125 * Nothing interesting.
1129 *------------------------------------------------------------------------*/
1132 SRXAFSCB_InitCallBackState3(struct rx_call
*a_call
, afsUUID
* a_uuid
)
1137 * TBD: Lookup the server by the UUID instead of its IP address.
1139 code
= SRXAFSCB_InitCallBackState(a_call
);
1145 /*------------------------------------------------------------------------
1146 * EXPORTED SRXAFSCB_ProbeUuid
1149 * Routine called by the server-side callback RPC interface to
1150 * implement ``probing'' the Cache Manager, just making sure it's
1151 * still there is still the same client it used to be.
1154 * a_call : Ptr to Rx call on which this request came in.
1155 * a_uuid : Ptr to UUID that must match the client's UUID.
1158 * 0 if a_uuid matches the UUID for this client
1159 * Non-zero otherwize
1162 * Nothing interesting.
1166 *------------------------------------------------------------------------*/
1169 SRXAFSCB_ProbeUuid(struct rx_call
*a_call
, afsUUID
* a_uuid
)
1175 AFS_STATCNT(SRXAFSCB_Probe
);
1177 XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_PROBE
);
1178 if (!afs_uuid_equal(a_uuid
, &afs_cb_interface
.uuid
))
1179 code
= 1; /* failure */
1188 /*------------------------------------------------------------------------
1189 * EXPORTED SRXAFSCB_GetServerPrefs
1192 * Routine to list server preferences used by this client.
1195 * a_call : Ptr to Rx call on which this request came in.
1196 * a_index : Input server index
1197 * a_srvr_addr : Output server address in host byte order
1198 * (0xffffffff on last server)
1199 * a_srvr_rank : Output server rank
1205 * Nothing interesting.
1209 *------------------------------------------------------------------------*/
1212 SRXAFSCB_GetServerPrefs(struct rx_call
*a_call
, afs_int32 a_index
,
1213 afs_int32
* a_srvr_addr
, afs_int32
* a_srvr_rank
)
1219 AFS_STATCNT(SRXAFSCB_GetServerPrefs
);
1221 ObtainReadLock(&afs_xserver
);
1223 /* Search the hash table for the server with this index */
1224 *a_srvr_addr
= 0xffffffff;
1225 *a_srvr_rank
= 0xffffffff;
1226 for (i
= 0, j
= 0; j
< NSERVERS
&& i
<= a_index
; j
++) {
1227 for (sa
= afs_srvAddrs
[j
]; sa
&& i
<= a_index
; sa
= sa
->next_bkt
, i
++) {
1229 *a_srvr_addr
= ntohl(sa
->sa_ip
);
1230 *a_srvr_rank
= sa
->sa_iprank
;
1235 ReleaseReadLock(&afs_xserver
);
1243 /*------------------------------------------------------------------------
1244 * EXPORTED SRXAFSCB_GetCellServDB
1247 * Routine to list cells configured for this client
1250 * a_call : Ptr to Rx call on which this request came in.
1251 * a_index : Input cell index
1252 * a_name : Output cell name ("" on last cell)
1253 * a_hosts : Output cell database servers in host byte order.
1259 * Nothing interesting.
1263 *------------------------------------------------------------------------*/
1266 SRXAFSCB_GetCellServDB(struct rx_call
*a_call
, afs_int32 a_index
,
1267 char **a_name
, serverList
* a_hosts
)
1271 char *t_name
, *p_name
= NULL
;
1274 AFS_STATCNT(SRXAFSCB_GetCellServDB
);
1276 tcell
= afs_GetCellByIndex(a_index
, READ_LOCK
);
1280 a_hosts
->serverList_val
= 0;
1281 a_hosts
->serverList_len
= 0;
1283 p_name
= tcell
->cellName
;
1284 for (j
= 0; j
< AFSMAXCELLHOSTS
&& tcell
->cellHosts
[j
]; j
++);
1286 a_hosts
->serverList_val
= afs_osi_Alloc(j
* sizeof(afs_int32
));
1287 osi_Assert(a_hosts
->serverList_val
!= NULL
);
1288 a_hosts
->serverList_len
= j
;
1289 for (j
= 0; j
< AFSMAXCELLHOSTS
&& tcell
->cellHosts
[j
]; j
++)
1290 a_hosts
->serverList_val
[j
] =
1291 ntohl(tcell
->cellHosts
[j
]->addr
->sa_ip
);
1292 afs_PutCell(tcell
, READ_LOCK
);
1295 t_name
= afs_osi_Alloc(i
+ 1);
1296 if (t_name
== NULL
) {
1298 afs_osi_Free(a_hosts
->serverList_val
, (j
* sizeof(afs_int32
)));
1305 memcpy(t_name
, p_name
, i
);
1314 /*------------------------------------------------------------------------
1315 * EXPORTED SRXAFSCB_GetLocalCell
1318 * Routine to return name of client's local cell
1321 * a_call : Ptr to Rx call on which this request came in.
1322 * a_name : Output cell name
1328 * Nothing interesting.
1332 *------------------------------------------------------------------------*/
1335 SRXAFSCB_GetLocalCell(struct rx_call
*a_call
, char **a_name
)
1339 char *t_name
, *p_name
= NULL
;
1342 AFS_STATCNT(SRXAFSCB_GetLocalCell
);
1344 /* Search the list for the primary cell. Cell number 1 is only
1345 * the primary cell is when no other cell is explicitly marked as
1346 * the primary cell. */
1347 tcell
= afs_GetPrimaryCell(READ_LOCK
);
1349 p_name
= tcell
->cellName
;
1351 plen
= strlen(p_name
);
1354 t_name
= afs_osi_Alloc(plen
+ 1);
1355 if (t_name
== NULL
) {
1357 afs_PutCell(tcell
, READ_LOCK
);
1362 t_name
[plen
] = '\0';
1364 memcpy(t_name
, p_name
, plen
);
1370 afs_PutCell(tcell
, READ_LOCK
);
1376 * afs_MarshallCacheConfig - marshall client cache configuration
1380 * IN callerVersion - the rpc stat version of the caller.
1382 * IN config - client cache configuration.
1384 * OUT ptr - buffer where configuration is marshalled.
1391 afs_MarshallCacheConfig(afs_uint32 callerVersion
, cm_initparams_v1
* config
,
1394 AFS_STATCNT(afs_MarshallCacheConfig
);
1396 * We currently only support version 1.
1398 *(ptr
++) = config
->nChunkFiles
;
1399 *(ptr
++) = config
->nStatCaches
;
1400 *(ptr
++) = config
->nDataCaches
;
1401 *(ptr
++) = config
->nVolumeCaches
;
1402 *(ptr
++) = config
->firstChunkSize
;
1403 *(ptr
++) = config
->otherChunkSize
;
1404 *(ptr
++) = config
->cacheSize
;
1405 *(ptr
++) = config
->setTime
;
1406 *(ptr
++) = config
->memCache
;
1410 /*------------------------------------------------------------------------
1411 * EXPORTED SRXAFSCB_GetCacheConfig
1414 * Routine to return parameters used to initialize client cache.
1415 * Client may request any format version. Server may not return
1416 * format version greater than version requested by client.
1419 * a_call: Ptr to Rx call on which this request came in.
1420 * callerVersion: Data format version desired by the client.
1421 * serverVersion: Data format version of output data.
1422 * configCount: Number bytes allocated for output data.
1423 * config: Client cache configuration.
1429 * Nothing interesting.
1433 *------------------------------------------------------------------------*/
1436 SRXAFSCB_GetCacheConfig(struct rx_call
*a_call
, afs_uint32 callerVersion
,
1437 afs_uint32
* serverVersion
, afs_uint32
* configCount
,
1438 cacheConfig
* config
)
1440 afs_uint32
*t_config
;
1442 cm_initparams_v1 cm_config
;
1445 AFS_STATCNT(SRXAFSCB_GetCacheConfig
);
1448 * Currently only support version 1
1450 allocsize
= sizeof(cm_initparams_v1
);
1451 t_config
= afs_osi_Alloc(allocsize
);
1452 if (t_config
== NULL
) {
1457 cm_config
.nChunkFiles
= cm_initParams
.cmi_nChunkFiles
;
1458 cm_config
.nStatCaches
= cm_initParams
.cmi_nStatCaches
;
1459 cm_config
.nDataCaches
= cm_initParams
.cmi_nDataCaches
;
1460 cm_config
.nVolumeCaches
= cm_initParams
.cmi_nVolumeCaches
;
1461 cm_config
.firstChunkSize
= cm_initParams
.cmi_firstChunkSize
;
1462 cm_config
.otherChunkSize
= cm_initParams
.cmi_otherChunkSize
;
1463 cm_config
.cacheSize
= cm_initParams
.cmi_cacheSize
;
1464 cm_config
.setTime
= cm_initParams
.cmi_setTime
;
1465 cm_config
.memCache
= cm_initParams
.cmi_memCache
;
1467 afs_MarshallCacheConfig(callerVersion
, &cm_config
, t_config
);
1469 *serverVersion
= AFS_CLIENT_RETRIEVAL_FIRST_EDITION
;
1470 *configCount
= allocsize
;
1471 config
->cacheConfig_val
= t_config
;
1472 config
->cacheConfig_len
= allocsize
/ sizeof(afs_uint32
);
1479 /*------------------------------------------------------------------------
1480 * EXPORTED SRXAFSCB_FetchData
1483 * Routine to do third party move from a remioserver to the original
1484 * issuer of an ArchiveData request. Presently supported only by the
1485 * "fs" command, not by the AFS client.
1488 * rxcall: Ptr to Rx call on which this request came in.
1489 * Fid: pointer to AFSFid structure.
1490 * Fd: File descriptor inside fs command.
1491 * Position: Offset in the file.
1492 * Length: Data length to transfer.
1493 * TotalLength: Pointer to total file length field
1499 * Nothing interesting.
1502 *------------------------------------------------------------------------*/
1504 SRXAFSCB_FetchData(struct rx_call
*rxcall
, struct AFSFid
*Fid
, afs_int32 Fd
,
1505 afs_int64 Position
, afs_int64 Length
,
1506 afs_int64
* TotalLength
)
1511 /*------------------------------------------------------------------------
1512 * EXPORTED SRXAFSCB_StoreData
1515 * Routine to do third party move from a remioserver to the original
1516 * issuer of a RetrieveData request. Presently supported only by the
1517 * "fs" command, not by the AFS client.
1520 * rxcall: Ptr to Rx call on which this request came in.
1521 * Fid: pointer to AFSFid structure.
1522 * Fd: File descriptor inside fs command.
1523 * Position: Offset in the file.
1524 * Length: Data length to transfer.
1525 * TotalLength: Pointer to total file length field
1531 * Nothing interesting.
1535 *------------------------------------------------------------------------*/
1537 SRXAFSCB_StoreData(struct rx_call
*rxcall
, struct AFSFid
*Fid
, afs_int32 Fd
,
1538 afs_int64 Position
, afs_int64 Length
,
1539 afs_int64
* TotalLength
)
1544 /*------------------------------------------------------------------------
1545 * EXPORTED SRXAFSCB_GetCellByNum
1548 * Routine to get information about a cell specified by its
1549 * cell number (returned by GetCE/GetCE64).
1552 * a_call : Ptr to Rx call on which this request came in.
1553 * a_cellnum : Input cell number
1554 * a_name : Output cell name (one zero byte when no such cell).
1555 * a_hosts : Output cell database servers in host byte order.
1561 * Nothing interesting.
1565 *------------------------------------------------------------------------*/
1568 SRXAFSCB_GetCellByNum(struct rx_call
*a_call
, afs_int32 a_cellnum
,
1569 char **a_name
, serverList
* a_hosts
)
1575 AFS_STATCNT(SRXAFSCB_GetCellByNum
);
1577 a_hosts
->serverList_val
= 0;
1578 a_hosts
->serverList_len
= 0;
1580 tcell
= afs_GetCellStale(a_cellnum
, READ_LOCK
);
1582 *a_name
= afs_strdup("");
1587 ObtainReadLock(&tcell
->lock
);
1588 *a_name
= afs_strdup(tcell
->cellName
);
1590 for (sn
= 0; sn
< AFSMAXCELLHOSTS
&& tcell
->cellHosts
[sn
]; sn
++);
1591 a_hosts
->serverList_len
= sn
;
1592 a_hosts
->serverList_val
= afs_osi_Alloc(sn
* sizeof(afs_int32
));
1593 osi_Assert(a_hosts
->serverList_val
!= NULL
);
1595 for (i
= 0; i
< sn
; i
++)
1596 a_hosts
->serverList_val
[i
] = ntohl(tcell
->cellHosts
[i
]->addr
->sa_ip
);
1597 ReleaseReadLock(&tcell
->lock
);
1598 afs_PutCell(tcell
, READ_LOCK
);
1605 SRXAFSCB_TellMeAboutYourself(struct rx_call
*a_call
,
1606 struct interfaceAddr
*addr
,
1607 Capabilities
* capabilities
)
1611 afs_uint32
*dataBuffP
;
1612 afs_int32 dataBytes
;
1616 AFS_STATCNT(SRXAFSCB_WhoAreYou
);
1618 ObtainReadLock(&afs_xinterface
);
1620 /* return all network interface addresses */
1621 addr
->numberOfInterfaces
= afs_cb_interface
.numberOfInterfaces
;
1622 addr
->uuid
= afs_cb_interface
.uuid
;
1623 for (i
= 0; i
< afs_cb_interface
.numberOfInterfaces
; i
++) {
1624 addr
->addr_in
[i
] = ntohl(afs_cb_interface
.addr_in
[i
]);
1625 addr
->subnetmask
[i
] = ntohl(afs_cb_interface
.subnetmask
[i
]);
1626 addr
->mtu
[i
] = ntohl(afs_cb_interface
.mtu
[i
]);
1629 ReleaseReadLock(&afs_xinterface
);
1633 dataBytes
= 1 * sizeof(afs_uint32
);
1634 dataBuffP
= afs_osi_Alloc(dataBytes
);
1635 osi_Assert(dataBuffP
!= NULL
);
1636 dataBuffP
[0] = CLIENT_CAPABILITY_ERRORTRANS
;
1637 capabilities
->Capabilities_len
= dataBytes
/ sizeof(afs_uint32
);
1638 capabilities
->Capabilities_val
= dataBuffP
;
1644 #if 0 && defined(AFS_LINUX24_ENV)
1645 extern struct vcache
*afs_globalVp
;
1647 int recurse_dcache_parent(parent
, a_index
, addr
, inode
, flags
, time
, fileName
)
1648 struct dentry
* parent
;
1656 struct dentry
*this_parent
= parent
;
1657 struct list_head
*next
;
1659 struct dentry
*dentry
;
1662 next
= this_parent
->d_subdirs
.next
;
1664 while (next
!= &this_parent
->d_subdirs
) {
1665 struct list_head
*tmp
= next
;
1666 dentry
= list_entry(tmp
, struct dentry
, d_child
);
1672 * Descend a level if the d_subdirs list is non-empty.
1674 if (!list_empty(&dentry
->d_subdirs
)) {
1675 this_parent
= dentry
;
1680 * All done at this level ... ascend and resume the search.
1682 if (this_parent
!= parent
) {
1683 next
= this_parent
->d_child
.next
;
1684 this_parent
= this_parent
->d_parent
;
1690 if (d_unhashed(dentry
))
1695 *fileName
= afs_strdup(dentry
->d_name
.name
?dentry
->d_name
.name
:"");
1696 *inode
= ITOAFS(dentry
->d_inode
);
1697 *addr
= atomic_read(&(dentry
)->d_count
);
1698 *time
= dentry
->d_time
;
1707 SRXAFSCB_GetDE(struct rx_call
*a_call
, afs_int32 a_index
, afs_int32
*addr
,
1708 afs_int32
*inode
, afs_int32
*flags
, afs_int32
*time
,
1710 { /*SRXAFSCB_GetDE*/
1711 int code
= 0; /*Return code*/
1712 #if 0 && defined(AFS_LINUX24_ENV)
1713 int i
; /*Loop variable*/
1714 struct vcache
*tvc
= afs_globalVp
;
1715 struct dentry
*dentry
;
1716 struct list_head
*cur
, *head
= &(AFSTOI(tvc
))->i_dentry
;
1718 #ifdef RX_ENABLE_LOCKS
1720 #endif /* RX_ENABLE_LOCKS */
1722 #if defined(AFS_LINUX24_ENV)
1723 spin_lock(&dcache_lock
);
1727 while ((cur
= cur
->next
) != head
) {
1728 dentry
= list_entry(cur
, struct dentry
, d_alias
);
1730 dget_locked(dentry
);
1732 #if defined(AFS_LINUX24_ENV)
1733 spin_unlock(&dcache_lock
);
1739 if (recurse_dcache_parent(dentry
, a_index
, addr
, inode
, flags
, time
, fileName
) == 0) {
1750 *fileName
= afs_strdup("");
1754 if (d_unhashed(dentry
))
1759 *fileName
= afs_strdup(dentry
->d_name
.name
?dentry
->d_name
.name
:"");
1760 *inode
= ITOAFS(dentry
->d_inode
);
1761 *addr
= atomic_read(&(dentry
)->d_count
);
1762 *time
= dentry
->d_time
;
1769 #ifdef RX_ENABLE_LOCKS
1771 #endif /* RX_ENABLE_LOCKS */
1775 } /*SRXAFSCB_GetDE*/