Commit | Line | Data |
---|---|---|
805e021f CE |
1 | /* |
2 | * Copyright 2000, International Business Machines Corporation and others. | |
3 | * All Rights Reserved. | |
4 | * | |
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 | |
8 | */ | |
9 | ||
10 | /* | |
11 | * afs_callback.c: | |
12 | * Exported routines (and their private support) to implement | |
13 | * the callback RPC interface. | |
14 | */ | |
15 | ||
16 | #include <afsconfig.h> | |
17 | #include "afs/param.h" | |
18 | ||
19 | ||
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" | |
24 | ||
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; | |
32 | ||
33 | /* | |
34 | * Some debugging aids. | |
35 | */ | |
36 | static struct ltable { | |
37 | char *name; | |
38 | char *addr; | |
39 | } ltable[] = { | |
40 | { | |
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}, | |
55 | { | |
56 | "afs_xsrvAddr", (char *)&afs_xsrvAddr}, | |
57 | { | |
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}, | |
66 | }; | |
67 | unsigned long lastCallBack_vnode; | |
68 | unsigned int lastCallBack_dv; | |
69 | osi_timeval_t lastCallBack_time; | |
70 | ||
71 | /* these are for storing alternate interface addresses */ | |
72 | struct interfaceAddr afs_cb_interface; | |
73 | ||
74 | /*------------------------------------------------------------------------ | |
75 | * EXPORTED SRXAFSCB_GetCE | |
76 | * | |
77 | * Description: | |
78 | * Routine called by the server-side callback RPC interface to | |
79 | * implement pulling out the contents of the i'th cache entry. | |
80 | * | |
81 | * Arguments: | |
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. | |
85 | * | |
86 | * Returns: | |
87 | * 0 if everything went fine, | |
88 | * 1 if we were given a bad index. | |
89 | * | |
90 | * Environment: | |
91 | * Nothing interesting. | |
92 | * | |
93 | * Side Effects: | |
94 | * As advertised. | |
95 | *------------------------------------------------------------------------*/ | |
96 | ||
97 | int | |
98 | SRXAFSCB_GetCE(struct rx_call *a_call, afs_int32 a_index, | |
99 | struct AFSDBCacheEntry *a_result) | |
100 | { | |
101 | ||
102 | int i; /*Loop variable */ | |
103 | struct vcache *tvc; /*Ptr to current cache entry */ | |
104 | int code; /*Return code */ | |
105 | XSTATS_DECLS; | |
106 | ||
107 | RX_AFS_GLOCK(); | |
108 | ||
109 | XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_GETCE); | |
110 | ||
111 | AFS_STATCNT(SRXAFSCB_GetCE); | |
112 | for (i = 0; i < VCSIZE; i++) { | |
113 | for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) { | |
114 | if (a_index == 0) | |
115 | goto searchDone; | |
116 | a_index--; | |
117 | } /*Zip through current hash chain */ | |
118 | } /*Zip through hash chains */ | |
119 | ||
120 | searchDone: | |
121 | if (tvc == NULL) { | |
122 | /*Past EOF */ | |
123 | code = 1; | |
124 | goto fcnDone; | |
125 | } | |
126 | ||
127 | /* | |
128 | * Copy out the located entry. | |
129 | */ | |
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; | |
143 | #else | |
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; | |
159 | } else { | |
160 | #ifdef AFS_DARWIN80_ENV | |
161 | a_result->refCount = vnode_isinuse(AFSTOV(tvc),0)?1:0; /* XXX fix */ | |
162 | #else | |
163 | a_result->refCount = VREFCOUNT(tvc); | |
164 | #endif | |
165 | } | |
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; | |
170 | code = 0; | |
171 | ||
172 | /* | |
173 | * Return our results. | |
174 | */ | |
175 | fcnDone: | |
176 | XSTATS_END_TIME; | |
177 | ||
178 | RX_AFS_GUNLOCK(); | |
179 | ||
180 | return (code); | |
181 | ||
182 | } /*SRXAFSCB_GetCE */ | |
183 | ||
184 | int | |
185 | SRXAFSCB_GetCE64(struct rx_call *a_call, afs_int32 a_index, | |
186 | struct AFSDBCacheEntry64 *a_result) | |
187 | { | |
188 | int i; /*Loop variable */ | |
189 | struct vcache *tvc; /*Ptr to current cache entry */ | |
190 | int code; /*Return code */ | |
191 | XSTATS_DECLS; | |
192 | ||
193 | RX_AFS_GLOCK(); | |
194 | ||
195 | XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_GETCE); | |
196 | ||
197 | AFS_STATCNT(SRXAFSCB_GetCE64); | |
198 | for (i = 0; i < VCSIZE; i++) { | |
199 | for (tvc = afs_vhashT[i]; tvc; tvc = tvc->hnext) { | |
200 | if (a_index == 0) | |
201 | goto searchDone; | |
202 | a_index--; | |
203 | } /*Zip through current hash chain */ | |
204 | } /*Zip through hash chains */ | |
205 | ||
206 | searchDone: | |
207 | if (tvc == NULL) { | |
208 | /*Past EOF */ | |
209 | code = 1; | |
210 | goto fcnDone; | |
211 | } | |
212 | ||
213 | /* | |
214 | * Copy out the located entry. | |
215 | */ | |
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; | |
229 | #else | |
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; | |
241 | } else { | |
242 | #ifdef AFS_DARWIN80_ENV | |
243 | a_result->refCount = vnode_isinuse(AFSTOV(tvc),0)?1:0; /* XXX fix */ | |
244 | #else | |
245 | a_result->refCount = VREFCOUNT(tvc); | |
246 | #endif | |
247 | } | |
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; | |
252 | code = 0; | |
253 | ||
254 | /* | |
255 | * Return our results. | |
256 | */ | |
257 | fcnDone: | |
258 | XSTATS_END_TIME; | |
259 | ||
260 | RX_AFS_GUNLOCK(); | |
261 | ||
262 | return (code); | |
263 | ||
264 | } /*SRXAFSCB_GetCE64 */ | |
265 | ||
266 | ||
267 | /*------------------------------------------------------------------------ | |
268 | * EXPORTED SRXAFSCB_GetLock | |
269 | * | |
270 | * Description: | |
271 | * Routine called by the server-side callback RPC interface to | |
272 | * implement pulling out the contents of a lock in the lock | |
273 | * table. | |
274 | * | |
275 | * Arguments: | |
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. | |
279 | * | |
280 | * Returns: | |
281 | * 0 if everything went fine, | |
282 | * 1 if we were given a bad index. | |
283 | * | |
284 | * Environment: | |
285 | * Nothing interesting. | |
286 | * | |
287 | * Side Effects: | |
288 | * As advertised. | |
289 | *------------------------------------------------------------------------*/ | |
290 | ||
291 | int | |
292 | SRXAFSCB_GetLock(struct rx_call *a_call, afs_int32 a_index, | |
293 | struct AFSDBLock *a_result) | |
294 | { | |
295 | struct ltable *tl; /*Ptr to lock table entry */ | |
296 | int nentries; /*Num entries in table */ | |
297 | int code; /*Return code */ | |
298 | XSTATS_DECLS; | |
299 | ||
300 | RX_AFS_GLOCK(); | |
301 | ||
302 | XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_GETLOCK); | |
303 | ||
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) { | |
308 | /* | |
309 | * Past EOF | |
310 | */ | |
311 | code = 1; | |
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; | |
330 | #else | |
331 | a_result->lock.pid_last_reader = 0; | |
332 | a_result->lock.pid_writer = 0; | |
333 | a_result->lock.src_indicator = 0; | |
334 | #endif | |
335 | code = 0; | |
336 | } else { | |
337 | /* | |
338 | * Found it - copy out its contents. | |
339 | */ | |
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; | |
357 | #else | |
358 | a_result->lock.pid_last_reader = 0; | |
359 | a_result->lock.pid_writer = 0; | |
360 | a_result->lock.src_indicator = 0; | |
361 | #endif | |
362 | code = 0; | |
363 | } | |
364 | ||
365 | XSTATS_END_TIME; | |
366 | ||
367 | RX_AFS_GUNLOCK(); | |
368 | ||
369 | return (code); | |
370 | ||
371 | } /*SRXAFSCB_GetLock */ | |
372 | ||
373 | ||
374 | /*------------------------------------------------------------------------ | |
375 | * static ClearCallBack | |
376 | * | |
377 | * Description: | |
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. | |
382 | * | |
383 | * Arguments: | |
384 | * a_conn : Ptr to Rx connection involved. | |
385 | * a_fid : Ptr to AFS fid being cleared. | |
386 | * | |
387 | * Returns: | |
388 | * 0 (always) | |
389 | * | |
390 | * Environment: | |
391 | * Nothing interesting. | |
392 | * | |
393 | * Side Effects: | |
394 | * As advertised. | |
395 | ||
396 | Appears to need to be called with GLOCK held, as the icl_Event4 stuff asserts otherwise | |
397 | ||
398 | *------------------------------------------------------------------------*/ | |
399 | ||
400 | static int | |
401 | ClearCallBack(struct rx_connection *a_conn, | |
402 | struct AFSFid *a_fid) | |
403 | { | |
404 | struct vcache *tvc; | |
405 | int i; | |
406 | struct VenusFid localFid; | |
407 | struct volume *tv; | |
408 | #ifdef AFS_DARWIN80_ENV | |
409 | vnode_t vp; | |
410 | #endif | |
411 | ||
412 | AFS_STATCNT(ClearCallBack); | |
413 | ||
414 | AFS_ASSERT_GLOCK(); | |
415 | ||
416 | /* | |
417 | * XXXX Don't hold any server locks here because of callback protocol XXX | |
418 | */ | |
419 | localFid.Cell = 0; | |
420 | localFid.Fid.Volume = a_fid->Volume; | |
421 | localFid.Fid.Vnode = a_fid->Vnode; | |
422 | localFid.Fid.Unique = a_fid->Unique; | |
423 | ||
424 | /* | |
425 | * Volume ID of zero means don't do anything. | |
426 | */ | |
427 | if (a_fid->Volume != 0) { | |
428 | if (a_fid->Vnode == 0) { | |
429 | struct afs_q *tq, *uq; | |
430 | /* | |
431 | * Clear callback for the whole volume. Zip through the | |
432 | * hash chain, nullifying entries whose volume ID matches. | |
433 | */ | |
434 | loop1: | |
435 | ObtainReadLock(&afs_xvcache); | |
436 | i = VCHashV(&localFid); | |
437 | for (tq = afs_vhashTV[i].prev; tq != &afs_vhashTV[i]; tq = uq) { | |
438 | uq = QPrev(tq); | |
439 | tvc = QTOVH(tq); | |
440 | if (tvc->f.fid.Fid.Volume == a_fid->Volume) { | |
441 | tvc->callback = NULL; | |
442 | if (!localFid.Cell) | |
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); | |
448 | goto loop1; | |
449 | } | |
450 | #if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_HPUX_ENV) || defined(AFS_LINUX20_ENV) | |
451 | AFS_FAST_HOLD(tvc); | |
452 | #else | |
453 | #ifdef AFS_DARWIN80_ENV | |
454 | if (tvc->f.states & CDeadVnode) { | |
455 | ReleaseReadLock(&afs_xvcache); | |
456 | afs_osi_Sleep(&tvc->f.states); | |
457 | goto loop1; | |
458 | } | |
459 | vp = AFSTOV(tvc); | |
460 | if (vnode_get(vp)) | |
461 | continue; | |
462 | if (vnode_ref(vp)) { | |
463 | AFS_GUNLOCK(); | |
464 | vnode_put(vp); | |
465 | AFS_GLOCK(); | |
466 | continue; | |
467 | } | |
468 | #else | |
469 | AFS_FAST_HOLD(tvc); | |
470 | #endif | |
471 | #endif | |
472 | ReleaseReadLock(&afs_xvcache); | |
473 | afs_StaleVCacheFlags(tvc, 0, CUnique | CBulkFetching); | |
474 | afs_allCBs++; | |
475 | if (tvc->f.fid.Fid.Vnode & 1) | |
476 | afs_oddCBs++; | |
477 | else | |
478 | afs_evenCBs++; | |
479 | afs_Trace3(afs_iclSetp, CM_TRACE_CALLBACK, | |
480 | ICL_TYPE_POINTER, tvc, ICL_TYPE_INT32, | |
481 | tvc->f.states, ICL_TYPE_INT32, | |
482 | a_fid->Volume); | |
483 | #ifdef AFS_DARWIN80_ENV | |
484 | vnode_put(AFSTOV(tvc)); | |
485 | #endif | |
486 | ObtainReadLock(&afs_xvcache); | |
487 | uq = QPrev(tq); | |
488 | AFS_FAST_RELE(tvc); | |
489 | } else if ((tvc->f.states & CMValid) | |
490 | && (tvc->mvid.target_root->Fid.Volume == a_fid->Volume)) { | |
491 | tvc->f.states &= ~CMValid; | |
492 | if (!localFid.Cell) | |
493 | localFid.Cell = tvc->mvid.target_root->Cell; | |
494 | } | |
495 | } | |
496 | ReleaseReadLock(&afs_xvcache); | |
497 | ||
498 | /* | |
499 | * XXXX Don't hold any locks here XXXX | |
500 | */ | |
501 | tv = afs_FindVolume(&localFid, 0); | |
502 | if (tv) { | |
503 | afs_ResetVolumeInfo(tv); | |
504 | afs_PutVolume(tv, 0); | |
505 | /* invalidate mtpoint? */ | |
506 | } | |
507 | } /*Clear callbacks for whole volume */ | |
508 | else { | |
509 | /* | |
510 | * Clear callbacks just for the one file. | |
511 | */ | |
512 | struct vcache *uvc; | |
513 | afs_allCBs++; | |
514 | if (a_fid->Vnode & 1) | |
515 | afs_oddCBs++; /*Could do this on volume basis, too */ | |
516 | else | |
517 | afs_evenCBs++; /*A particular fid was specified */ | |
518 | loop2: | |
519 | ObtainReadLock(&afs_xvcache); | |
520 | i = VCHash(&localFid); | |
521 | for (tvc = afs_vhashT[i]; tvc; tvc = uvc) { | |
522 | uvc = tvc->hnext; | |
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); | |
531 | goto loop2; | |
532 | } | |
533 | #if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_HPUX_ENV) || defined(AFS_LINUX20_ENV) | |
534 | AFS_FAST_HOLD(tvc); | |
535 | #else | |
536 | #ifdef AFS_DARWIN80_ENV | |
537 | if (tvc->f.states & CDeadVnode) { | |
538 | ReleaseReadLock(&afs_xvcache); | |
539 | afs_osi_Sleep(&tvc->f.states); | |
540 | goto loop2; | |
541 | } | |
542 | vp = AFSTOV(tvc); | |
543 | if (vnode_get(vp)) | |
544 | continue; | |
545 | if (vnode_ref(vp)) { | |
546 | AFS_GUNLOCK(); | |
547 | vnode_put(vp); | |
548 | AFS_GLOCK(); | |
549 | continue; | |
550 | } | |
551 | #else | |
552 | AFS_FAST_HOLD(tvc); | |
553 | #endif | |
554 | #endif | |
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); | |
560 | #ifdef CBDEBUG | |
561 | lastCallBack_vnode = afid->Vnode; | |
562 | lastCallBack_dv = tvc->mstat.DataVersion.low; | |
563 | osi_GetuTime(&lastCallBack_time); | |
564 | #endif /* CBDEBUG */ | |
565 | #ifdef AFS_DARWIN80_ENV | |
566 | vnode_put(AFSTOV(tvc)); | |
567 | #endif | |
568 | ObtainReadLock(&afs_xvcache); | |
569 | uvc = tvc->hnext; | |
570 | AFS_FAST_RELE(tvc); | |
571 | } | |
572 | } /*Walk through hash table */ | |
573 | ReleaseReadLock(&afs_xvcache); | |
574 | } /*Clear callbacks for one file */ | |
575 | } | |
576 | ||
577 | /*Fid has non-zero volume ID */ | |
578 | /* | |
579 | * Always return a predictable value. | |
580 | */ | |
581 | return (0); | |
582 | ||
583 | } /*ClearCallBack */ | |
584 | ||
585 | ||
586 | /*------------------------------------------------------------------------ | |
587 | * EXPORTED SRXAFSCB_CallBack | |
588 | * | |
589 | * Description: | |
590 | * Routine called by the server-side callback RPC interface to | |
591 | * implement passing in callback information. | |
592 | * table. | |
593 | * | |
594 | * Arguments: | |
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. | |
598 | * | |
599 | * Returns: | |
600 | * 0 (always). | |
601 | * | |
602 | * Environment: | |
603 | * Nothing interesting. | |
604 | * | |
605 | * Side Effects: | |
606 | * As advertised. | |
607 | *------------------------------------------------------------------------*/ | |
608 | ||
609 | int | |
610 | SRXAFSCB_CallBack(struct rx_call *a_call, struct AFSCBFids *a_fids, | |
611 | struct AFSCBs *a_callbacks) | |
612 | { | |
613 | int i; /*Loop variable */ | |
614 | struct AFSFid *tfid; /*Ptr to current fid */ | |
615 | struct rx_connection *tconn; /*Call's connection */ | |
616 | int code = 0; | |
617 | XSTATS_DECLS; | |
618 | ||
619 | RX_AFS_GLOCK(); | |
620 | ||
621 | XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_CALLBACK); | |
622 | ||
623 | AFS_STATCNT(SRXAFSCB_CallBack); | |
624 | if (!(tconn = rx_ConnectionOf(a_call))) | |
625 | return (0); | |
626 | tfid = (struct AFSFid *)a_fids->AFSCBFids_val; | |
627 | ||
628 | /* | |
629 | * For now, we ignore callbacks, since the File Server only *breaks* | |
630 | * callbacks at present. | |
631 | */ | |
632 | for (i = 0; i < a_fids->AFSCBFids_len; i++) | |
633 | ClearCallBack(tconn, &tfid[i]); | |
634 | ||
635 | XSTATS_END_TIME; | |
636 | ||
637 | RX_AFS_GUNLOCK(); | |
638 | ||
639 | return (0); | |
640 | ||
641 | } /*SRXAFSCB_CallBack */ | |
642 | ||
643 | ||
644 | /*------------------------------------------------------------------------ | |
645 | * EXPORTED SRXAFSCB_Probe | |
646 | * | |
647 | * Description: | |
648 | * Routine called by the server-side callback RPC interface to | |
649 | * implement ``probing'' the Cache Manager, just making sure it's | |
650 | * still there. | |
651 | * | |
652 | * Arguments: | |
653 | * a_call : Ptr to Rx call on which this request came in. | |
654 | * | |
655 | * Returns: | |
656 | * 0 (always). | |
657 | * | |
658 | * Environment: | |
659 | * Nothing interesting. | |
660 | * | |
661 | * Side Effects: | |
662 | * As advertised. | |
663 | *------------------------------------------------------------------------*/ | |
664 | ||
665 | int | |
666 | SRXAFSCB_Probe(struct rx_call *a_call) | |
667 | { | |
668 | int code = 0; | |
669 | XSTATS_DECLS; | |
670 | ||
671 | RX_AFS_GLOCK(); | |
672 | AFS_STATCNT(SRXAFSCB_Probe); | |
673 | ||
674 | XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_PROBE); | |
675 | XSTATS_END_TIME; | |
676 | ||
677 | RX_AFS_GUNLOCK(); | |
678 | ||
679 | return (0); | |
680 | ||
681 | } /*SRXAFSCB_Probe */ | |
682 | ||
683 | ||
684 | /*------------------------------------------------------------------------ | |
685 | * EXPORTED SRXAFSCB_InitCallBackState | |
686 | * | |
687 | * Description: | |
688 | * Routine called by the server-side callback RPC interface to | |
689 | * implement clearing all callbacks from this host. | |
690 | * | |
691 | * Arguments: | |
692 | * a_call : Ptr to Rx call on which this request came in. | |
693 | * | |
694 | * Returns: | |
695 | * 0 (always). | |
696 | * | |
697 | * Environment: | |
698 | * Nothing interesting. | |
699 | * | |
700 | * Side Effects: | |
701 | * As advertised. | |
702 | *------------------------------------------------------------------------*/ | |
703 | ||
704 | int | |
705 | SRXAFSCB_InitCallBackState(struct rx_call *a_call) | |
706 | { | |
707 | int i; | |
708 | struct vcache *tvc; | |
709 | struct rx_connection *tconn; | |
710 | struct rx_peer *peer; | |
711 | struct server *ts; | |
712 | int code = 0; | |
713 | XSTATS_DECLS; | |
714 | ||
715 | RX_AFS_GLOCK(); | |
716 | ||
717 | XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_INITCALLBACKSTATE); | |
718 | AFS_STATCNT(SRXAFSCB_InitCallBackState); | |
719 | ||
720 | /* | |
721 | * Find the address of the host making this call | |
722 | */ | |
723 | if ((tconn = rx_ConnectionOf(a_call)) && (peer = rx_PeerOf(tconn))) { | |
724 | ||
725 | afs_allCBs++; | |
726 | afs_oddCBs++; /*Including any missed via create race */ | |
727 | afs_evenCBs++; /*Including any missed via create race */ | |
728 | ||
729 | ts = afs_FindServer(rx_HostOf(peer), rx_PortOf(peer), (afsUUID *) 0, | |
730 | 0); | |
731 | if (ts) { | |
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 | | |
736 | AFS_STALEVC_CLEARCB, | |
737 | CUnique | CBulkFetching); | |
738 | } | |
739 | } | |
740 | ||
741 | /* capabilities need be requested again */ | |
742 | ts->flags &= ~SCAPS_KNOWN; | |
743 | } | |
744 | ||
745 | ||
746 | ||
747 | /* find any volumes residing on this server and flush their state */ | |
748 | { | |
749 | struct volume *tv; | |
750 | int j; | |
751 | ||
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); | |
757 | } | |
758 | } | |
759 | osi_dnlc_purge(); /* may be a little bit extreme */ | |
760 | } | |
761 | ||
762 | XSTATS_END_TIME; | |
763 | ||
764 | RX_AFS_GUNLOCK(); | |
765 | ||
766 | return (0); | |
767 | ||
768 | } /*SRXAFSCB_InitCallBackState */ | |
769 | ||
770 | ||
771 | /*------------------------------------------------------------------------ | |
772 | * EXPORTED SRXAFSCB_XStatsVersion | |
773 | * | |
774 | * Description: | |
775 | * Routine called by the server-side callback RPC interface to | |
776 | * implement pulling out the xstat version number for the Cache | |
777 | * Manager. | |
778 | * | |
779 | * Arguments: | |
780 | * a_versionP : Ptr to the version number variable to set. | |
781 | * | |
782 | * Returns: | |
783 | * 0 (always) | |
784 | * | |
785 | * Environment: | |
786 | * Nothing interesting. | |
787 | * | |
788 | * Side Effects: | |
789 | * As advertised. | |
790 | *------------------------------------------------------------------------*/ | |
791 | ||
792 | int | |
793 | SRXAFSCB_XStatsVersion(struct rx_call *a_call, afs_int32 * a_versionP) | |
794 | { | |
795 | int code = 0; | |
796 | ||
797 | XSTATS_DECLS; | |
798 | ||
799 | RX_AFS_GLOCK(); | |
800 | XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_XSTATSVERSION); | |
801 | ||
802 | *a_versionP = AFSCB_XSTAT_VERSION; | |
803 | ||
804 | XSTATS_END_TIME; | |
805 | ||
806 | RX_AFS_GUNLOCK(); | |
807 | ||
808 | return (0); | |
809 | } /*SRXAFSCB_XStatsVersion */ | |
810 | ||
811 | ||
812 | /*------------------------------------------------------------------------ | |
813 | * EXPORTED SRXAFSCB_GetXStats | |
814 | * | |
815 | * Description: | |
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. | |
819 | * | |
820 | * Arguments: | |
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 | |
827 | * stuff in. | |
828 | * | |
829 | * Returns: | |
830 | * 0 (always). | |
831 | * | |
832 | * Environment: | |
833 | * Nothing interesting. | |
834 | * | |
835 | * Side Effects: | |
836 | * As advertised. | |
837 | *------------------------------------------------------------------------*/ | |
838 | ||
839 | int | |
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) | |
843 | { | |
844 | int code; /*Return value */ | |
845 | afs_int32 *dataBuffP; /*Ptr to data to be returned */ | |
846 | afs_int32 dataBytes; /*Bytes in data buffer */ | |
847 | XSTATS_DECLS; | |
848 | ||
849 | RX_AFS_GLOCK(); | |
850 | ||
851 | XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_GETXSTATS); | |
852 | ||
853 | /* | |
854 | * Record the time of day and the server version number. | |
855 | */ | |
856 | *a_srvVersionNumP = AFSCB_XSTAT_VERSION; | |
857 | *a_timeP = osi_Time(); | |
858 | ||
859 | /* | |
860 | * Stuff the appropriate data in there (assume victory) | |
861 | */ | |
862 | code = 0; | |
863 | ||
864 | #ifdef AFS_NOSTATS | |
865 | /* | |
866 | * We're not keeping stats, so just return successfully with | |
867 | * no data. | |
868 | */ | |
869 | a_dataP->AFSCB_CollData_len = 0; | |
870 | a_dataP->AFSCB_CollData_val = NULL; | |
871 | #else | |
872 | switch (a_collectionNumber) { | |
873 | case AFSCB_XSTATSCOLL_CALL_INFO: | |
874 | /* | |
875 | * Pass back all the call-count-related data. | |
876 | * | |
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. | |
880 | */ | |
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; | |
887 | break; | |
888 | ||
889 | case AFSCB_XSTATSCOLL_PERF_INFO: | |
890 | /* | |
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. | |
895 | * | |
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. | |
899 | */ | |
900 | afs_stats_cmperf.numPerfCalls++; | |
901 | afs_CountServers(); | |
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; | |
908 | break; | |
909 | ||
910 | case AFSCB_XSTATSCOLL_FULL_PERF_INFO: | |
911 | /* | |
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. | |
916 | * | |
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. | |
920 | */ | |
921 | afs_stats_cmperf.numPerfCalls++; | |
922 | afs_CountServers(); | |
923 | memcpy((char *)(&(afs_stats_cmfullperf.perf)), | |
924 | (char *)(&afs_stats_cmperf), sizeof(struct afs_stats_CMPerf)); | |
925 | afs_stats_cmfullperf.numFullPerfCalls++; | |
926 | ||
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; | |
933 | break; | |
934 | ||
935 | default: | |
936 | /* | |
937 | * Illegal collection number. | |
938 | */ | |
939 | a_dataP->AFSCB_CollData_len = 0; | |
940 | a_dataP->AFSCB_CollData_val = NULL; | |
941 | code = 1; | |
942 | } /*Switch on collection number */ | |
943 | #endif /* AFS_NOSTATS */ | |
944 | ||
945 | XSTATS_END_TIME; | |
946 | ||
947 | RX_AFS_GUNLOCK(); | |
948 | ||
949 | return (code); | |
950 | ||
951 | } /*SRXAFSCB_GetXStats */ | |
952 | ||
953 | ||
954 | /*------------------------------------------------------------------------ | |
955 | * EXPORTED afs_RXCallBackServer | |
956 | * | |
957 | * Description: | |
958 | * Body of the thread supporting callback services. | |
959 | * | |
960 | * Arguments: | |
961 | * None. | |
962 | * | |
963 | * Returns: | |
964 | * 0 (always). | |
965 | * | |
966 | * Environment: | |
967 | * Nothing interesting. | |
968 | * | |
969 | * Side Effects: | |
970 | * As advertised. | |
971 | *------------------------------------------------------------------------*/ | |
972 | ||
973 | int | |
974 | afs_RXCallBackServer(void) | |
975 | { | |
976 | AFS_STATCNT(afs_RXCallBackServer); | |
977 | ||
978 | while (1) { | |
979 | if (afs_server) | |
980 | break; | |
981 | afs_osi_Sleep(&afs_server); | |
982 | } | |
983 | ||
984 | /* | |
985 | * Donate this process to Rx. | |
986 | */ | |
987 | rx_ServerProc(NULL); | |
988 | return (0); | |
989 | ||
990 | } /*afs_RXCallBackServer */ | |
991 | ||
992 | ||
993 | /*------------------------------------------------------------------------ | |
994 | * EXPORTED shutdown_CB | |
995 | * | |
996 | * Description: | |
997 | * Zero out important Cache Manager data structures. | |
998 | * | |
999 | * Arguments: | |
1000 | * None. | |
1001 | * | |
1002 | * Returns: | |
1003 | * 0 (always). | |
1004 | * | |
1005 | * Environment: | |
1006 | * Nothing interesting. | |
1007 | * | |
1008 | * Side Effects: | |
1009 | * As advertised. | |
1010 | *------------------------------------------------------------------------*/ | |
1011 | ||
1012 | int | |
1013 | shutdown_CB(void) | |
1014 | { | |
1015 | AFS_STATCNT(shutdown_CB); | |
1016 | ||
1017 | if (afs_cold_shutdown) { | |
1018 | afs_oddCBs = afs_evenCBs = afs_allCBs = afs_allZaps = afs_oddZaps = | |
1019 | afs_evenZaps = afs_connectBacks = 0; | |
1020 | } | |
1021 | ||
1022 | return (0); | |
1023 | ||
1024 | } /*shutdown_CB */ | |
1025 | ||
1026 | /*------------------------------------------------------------------------ | |
1027 | * EXPORTED SRXAFSCB_InitCallBackState2 | |
1028 | * | |
1029 | * Description: | |
1030 | * This routine was used in the AFS 3.5 beta release, but not anymore. | |
1031 | * It has since been replaced by SRXAFSCB_InitCallBackState3. | |
1032 | * | |
1033 | * Arguments: | |
1034 | * a_call : Ptr to Rx call on which this request came in. | |
1035 | * | |
1036 | * Returns: | |
1037 | * RXGEN_OPCODE (always). | |
1038 | * | |
1039 | * Environment: | |
1040 | * Nothing interesting. | |
1041 | * | |
1042 | * Side Effects: | |
1043 | * None | |
1044 | *------------------------------------------------------------------------*/ | |
1045 | ||
1046 | int | |
1047 | SRXAFSCB_InitCallBackState2(struct rx_call *a_call, | |
1048 | struct interfaceAddr *addr) | |
1049 | { | |
1050 | return RXGEN_OPCODE; | |
1051 | } | |
1052 | ||
1053 | /*------------------------------------------------------------------------ | |
1054 | * EXPORTED SRXAFSCB_WhoAreYou | |
1055 | * | |
1056 | * Description: | |
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. | |
1062 | * | |
1063 | * Arguments: | |
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. | |
1066 | * | |
1067 | * Returns: | |
1068 | * 0 (Always) | |
1069 | * | |
1070 | * Environment: | |
1071 | * Nothing interesting. | |
1072 | * | |
1073 | * Side Effects: | |
1074 | * As advertised. | |
1075 | *------------------------------------------------------------------------*/ | |
1076 | ||
1077 | int | |
1078 | SRXAFSCB_WhoAreYou(struct rx_call *a_call, struct interfaceAddr *addr) | |
1079 | { | |
1080 | int i; | |
1081 | int code = 0; | |
1082 | ||
1083 | RX_AFS_GLOCK(); | |
1084 | ||
1085 | AFS_STATCNT(SRXAFSCB_WhoAreYou); | |
1086 | ||
1087 | memset(addr, 0, sizeof(*addr)); | |
1088 | ||
1089 | ObtainReadLock(&afs_xinterface); | |
1090 | ||
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]); | |
1098 | } | |
1099 | ||
1100 | ReleaseReadLock(&afs_xinterface); | |
1101 | ||
1102 | RX_AFS_GUNLOCK(); | |
1103 | ||
1104 | return code; | |
1105 | } | |
1106 | ||
1107 | ||
1108 | /*------------------------------------------------------------------------ | |
1109 | * EXPORTED SRXAFSCB_InitCallBackState3 | |
1110 | * | |
1111 | * Description: | |
1112 | * Routine called by the server-side callback RPC interface to | |
1113 | * implement clearing all callbacks from this host. | |
1114 | * | |
1115 | * Arguments: | |
1116 | * a_call : Ptr to Rx call on which this request came in. | |
1117 | * | |
1118 | * Returns: | |
1119 | * 0 (always). | |
1120 | * | |
1121 | * Environment: | |
1122 | * Nothing interesting. | |
1123 | * | |
1124 | * Side Effects: | |
1125 | * As advertised. | |
1126 | *------------------------------------------------------------------------*/ | |
1127 | ||
1128 | int | |
1129 | SRXAFSCB_InitCallBackState3(struct rx_call *a_call, afsUUID * a_uuid) | |
1130 | { | |
1131 | int code; | |
1132 | ||
1133 | /* | |
1134 | * TBD: Lookup the server by the UUID instead of its IP address. | |
1135 | */ | |
1136 | code = SRXAFSCB_InitCallBackState(a_call); | |
1137 | ||
1138 | return code; | |
1139 | } | |
1140 | ||
1141 | ||
1142 | /*------------------------------------------------------------------------ | |
1143 | * EXPORTED SRXAFSCB_ProbeUuid | |
1144 | * | |
1145 | * Description: | |
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. | |
1149 | * | |
1150 | * Arguments: | |
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. | |
1153 | * | |
1154 | * Returns: | |
1155 | * 0 if a_uuid matches the UUID for this client | |
1156 | * Non-zero otherwize | |
1157 | * | |
1158 | * Environment: | |
1159 | * Nothing interesting. | |
1160 | * | |
1161 | * Side Effects: | |
1162 | * As advertised. | |
1163 | *------------------------------------------------------------------------*/ | |
1164 | ||
1165 | int | |
1166 | SRXAFSCB_ProbeUuid(struct rx_call *a_call, afsUUID * a_uuid) | |
1167 | { | |
1168 | int code = 0; | |
1169 | XSTATS_DECLS; | |
1170 | ||
1171 | RX_AFS_GLOCK(); | |
1172 | AFS_STATCNT(SRXAFSCB_Probe); | |
1173 | ||
1174 | XSTATS_START_CMTIME(AFS_STATS_CM_RPCIDX_PROBE); | |
1175 | if (!afs_uuid_equal(a_uuid, &afs_cb_interface.uuid)) | |
1176 | code = 1; /* failure */ | |
1177 | XSTATS_END_TIME; | |
1178 | ||
1179 | RX_AFS_GUNLOCK(); | |
1180 | ||
1181 | return code; | |
1182 | } | |
1183 | ||
1184 | ||
1185 | /*------------------------------------------------------------------------ | |
1186 | * EXPORTED SRXAFSCB_GetServerPrefs | |
1187 | * | |
1188 | * Description: | |
1189 | * Routine to list server preferences used by this client. | |
1190 | * | |
1191 | * Arguments: | |
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 | |
1197 | * | |
1198 | * Returns: | |
1199 | * 0 on success | |
1200 | * | |
1201 | * Environment: | |
1202 | * Nothing interesting. | |
1203 | * | |
1204 | * Side Effects: | |
1205 | * As advertised. | |
1206 | *------------------------------------------------------------------------*/ | |
1207 | ||
1208 | int | |
1209 | SRXAFSCB_GetServerPrefs(struct rx_call *a_call, afs_int32 a_index, | |
1210 | afs_int32 * a_srvr_addr, afs_int32 * a_srvr_rank) | |
1211 | { | |
1212 | int i, j; | |
1213 | struct srvAddr *sa; | |
1214 | ||
1215 | RX_AFS_GLOCK(); | |
1216 | AFS_STATCNT(SRXAFSCB_GetServerPrefs); | |
1217 | ||
1218 | ObtainReadLock(&afs_xserver); | |
1219 | ||
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++) { | |
1225 | if (i == a_index) { | |
1226 | *a_srvr_addr = ntohl(sa->sa_ip); | |
1227 | *a_srvr_rank = sa->sa_iprank; | |
1228 | } | |
1229 | } | |
1230 | } | |
1231 | ||
1232 | ReleaseReadLock(&afs_xserver); | |
1233 | ||
1234 | RX_AFS_GUNLOCK(); | |
1235 | ||
1236 | return 0; | |
1237 | } | |
1238 | ||
1239 | ||
1240 | /*------------------------------------------------------------------------ | |
1241 | * EXPORTED SRXAFSCB_GetCellServDB | |
1242 | * | |
1243 | * Description: | |
1244 | * Routine to list cells configured for this client | |
1245 | * | |
1246 | * Arguments: | |
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. | |
1251 | * | |
1252 | * Returns: | |
1253 | * 0 on success | |
1254 | * | |
1255 | * Environment: | |
1256 | * Nothing interesting. | |
1257 | * | |
1258 | * Side Effects: | |
1259 | * As advertised. | |
1260 | *------------------------------------------------------------------------*/ | |
1261 | ||
1262 | int | |
1263 | SRXAFSCB_GetCellServDB(struct rx_call *a_call, afs_int32 a_index, | |
1264 | char **a_name, serverList * a_hosts) | |
1265 | { | |
1266 | afs_int32 i, j = 0; | |
1267 | struct cell *tcell; | |
1268 | char *t_name, *p_name = NULL; | |
1269 | ||
1270 | RX_AFS_GLOCK(); | |
1271 | AFS_STATCNT(SRXAFSCB_GetCellServDB); | |
1272 | ||
1273 | tcell = afs_GetCellByIndex(a_index, READ_LOCK); | |
1274 | ||
1275 | if (!tcell) { | |
1276 | i = 0; | |
1277 | a_hosts->serverList_val = 0; | |
1278 | a_hosts->serverList_len = 0; | |
1279 | } else { | |
1280 | p_name = tcell->cellName; | |
1281 | for (j = 0; j < AFSMAXCELLHOSTS && tcell->cellHosts[j]; j++); | |
1282 | i = strlen(p_name); | |
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); | |
1290 | } | |
1291 | ||
1292 | t_name = afs_osi_Alloc(i + 1); | |
1293 | if (t_name == NULL) { | |
1294 | if (tcell != NULL) | |
1295 | afs_osi_Free(a_hosts->serverList_val, (j * sizeof(afs_int32))); | |
1296 | RX_AFS_GUNLOCK(); | |
1297 | return ENOMEM; | |
1298 | } | |
1299 | ||
1300 | t_name[i] = '\0'; | |
1301 | if (p_name) | |
1302 | memcpy(t_name, p_name, i); | |
1303 | ||
1304 | RX_AFS_GUNLOCK(); | |
1305 | ||
1306 | *a_name = t_name; | |
1307 | return 0; | |
1308 | } | |
1309 | ||
1310 | ||
1311 | /*------------------------------------------------------------------------ | |
1312 | * EXPORTED SRXAFSCB_GetLocalCell | |
1313 | * | |
1314 | * Description: | |
1315 | * Routine to return name of client's local cell | |
1316 | * | |
1317 | * Arguments: | |
1318 | * a_call : Ptr to Rx call on which this request came in. | |
1319 | * a_name : Output cell name | |
1320 | * | |
1321 | * Returns: | |
1322 | * 0 on success | |
1323 | * | |
1324 | * Environment: | |
1325 | * Nothing interesting. | |
1326 | * | |
1327 | * Side Effects: | |
1328 | * As advertised. | |
1329 | *------------------------------------------------------------------------*/ | |
1330 | ||
1331 | int | |
1332 | SRXAFSCB_GetLocalCell(struct rx_call *a_call, char **a_name) | |
1333 | { | |
1334 | int plen; | |
1335 | struct cell *tcell; | |
1336 | char *t_name, *p_name = NULL; | |
1337 | ||
1338 | RX_AFS_GLOCK(); | |
1339 | AFS_STATCNT(SRXAFSCB_GetLocalCell); | |
1340 | ||
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); | |
1345 | if (tcell) | |
1346 | p_name = tcell->cellName; | |
1347 | if (p_name) | |
1348 | plen = strlen(p_name); | |
1349 | else | |
1350 | plen = 0; | |
1351 | t_name = afs_osi_Alloc(plen + 1); | |
1352 | if (t_name == NULL) { | |
1353 | if (tcell) | |
1354 | afs_PutCell(tcell, READ_LOCK); | |
1355 | RX_AFS_GUNLOCK(); | |
1356 | return ENOMEM; | |
1357 | } | |
1358 | ||
1359 | t_name[plen] = '\0'; | |
1360 | if (p_name) | |
1361 | memcpy(t_name, p_name, plen); | |
1362 | ||
1363 | RX_AFS_GUNLOCK(); | |
1364 | ||
1365 | *a_name = t_name; | |
1366 | if (tcell) | |
1367 | afs_PutCell(tcell, READ_LOCK); | |
1368 | return 0; | |
1369 | } | |
1370 | ||
1371 | ||
1372 | /* | |
1373 | * afs_MarshallCacheConfig - marshall client cache configuration | |
1374 | * | |
1375 | * PARAMETERS | |
1376 | * | |
1377 | * IN callerVersion - the rpc stat version of the caller. | |
1378 | * | |
1379 | * IN config - client cache configuration. | |
1380 | * | |
1381 | * OUT ptr - buffer where configuration is marshalled. | |
1382 | * | |
1383 | * RETURN CODES | |
1384 | * | |
1385 | * Returns void. | |
1386 | */ | |
1387 | static void | |
1388 | afs_MarshallCacheConfig(afs_uint32 callerVersion, cm_initparams_v1 * config, | |
1389 | afs_uint32 * ptr) | |
1390 | { | |
1391 | AFS_STATCNT(afs_MarshallCacheConfig); | |
1392 | /* | |
1393 | * We currently only support version 1. | |
1394 | */ | |
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; | |
1404 | } | |
1405 | ||
1406 | ||
1407 | /*------------------------------------------------------------------------ | |
1408 | * EXPORTED SRXAFSCB_GetCacheConfig | |
1409 | * | |
1410 | * Description: | |
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. | |
1414 | * | |
1415 | * Arguments: | |
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. | |
1421 | * | |
1422 | * Returns: | |
1423 | * 0 on success | |
1424 | * | |
1425 | * Environment: | |
1426 | * Nothing interesting. | |
1427 | * | |
1428 | * Side Effects: | |
1429 | * As advertised. | |
1430 | *------------------------------------------------------------------------*/ | |
1431 | ||
1432 | int | |
1433 | SRXAFSCB_GetCacheConfig(struct rx_call *a_call, afs_uint32 callerVersion, | |
1434 | afs_uint32 * serverVersion, afs_uint32 * configCount, | |
1435 | cacheConfig * config) | |
1436 | { | |
1437 | afs_uint32 *t_config; | |
1438 | size_t allocsize; | |
1439 | cm_initparams_v1 cm_config; | |
1440 | ||
1441 | RX_AFS_GLOCK(); | |
1442 | AFS_STATCNT(SRXAFSCB_GetCacheConfig); | |
1443 | ||
1444 | /* | |
1445 | * Currently only support version 1 | |
1446 | */ | |
1447 | allocsize = sizeof(cm_initparams_v1); | |
1448 | t_config = afs_osi_Alloc(allocsize); | |
1449 | if (t_config == NULL) { | |
1450 | RX_AFS_GUNLOCK(); | |
1451 | return ENOMEM; | |
1452 | } | |
1453 | ||
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; | |
1463 | ||
1464 | afs_MarshallCacheConfig(callerVersion, &cm_config, t_config); | |
1465 | ||
1466 | *serverVersion = AFS_CLIENT_RETRIEVAL_FIRST_EDITION; | |
1467 | *configCount = allocsize; | |
1468 | config->cacheConfig_val = t_config; | |
1469 | config->cacheConfig_len = allocsize / sizeof(afs_uint32); | |
1470 | ||
1471 | RX_AFS_GUNLOCK(); | |
1472 | ||
1473 | return 0; | |
1474 | } | |
1475 | ||
1476 | /*------------------------------------------------------------------------ | |
1477 | * EXPORTED SRXAFSCB_FetchData | |
1478 | * | |
1479 | * Description: | |
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. | |
1483 | * | |
1484 | * Arguments: | |
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 | |
1491 | * | |
1492 | * Returns: | |
1493 | * 0 on success | |
1494 | * | |
1495 | * Environment: | |
1496 | * Nothing interesting. | |
1497 | * | |
1498 | * Side Effects: | |
1499 | *------------------------------------------------------------------------*/ | |
1500 | int | |
1501 | SRXAFSCB_FetchData(struct rx_call *rxcall, struct AFSFid *Fid, afs_int32 Fd, | |
1502 | afs_int64 Position, afs_int64 Length, | |
1503 | afs_int64 * TotalLength) | |
1504 | { | |
1505 | return ENOSYS; | |
1506 | } | |
1507 | ||
1508 | /*------------------------------------------------------------------------ | |
1509 | * EXPORTED SRXAFSCB_StoreData | |
1510 | * | |
1511 | * Description: | |
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. | |
1515 | * | |
1516 | * Arguments: | |
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 | |
1523 | * | |
1524 | * Returns: | |
1525 | * 0 on success | |
1526 | * | |
1527 | * Environment: | |
1528 | * Nothing interesting. | |
1529 | * | |
1530 | * Side Effects: | |
1531 | * As advertised. | |
1532 | *------------------------------------------------------------------------*/ | |
1533 | int | |
1534 | SRXAFSCB_StoreData(struct rx_call *rxcall, struct AFSFid *Fid, afs_int32 Fd, | |
1535 | afs_int64 Position, afs_int64 Length, | |
1536 | afs_int64 * TotalLength) | |
1537 | { | |
1538 | return ENOSYS; | |
1539 | } | |
1540 | ||
1541 | /*------------------------------------------------------------------------ | |
1542 | * EXPORTED SRXAFSCB_GetCellByNum | |
1543 | * | |
1544 | * Description: | |
1545 | * Routine to get information about a cell specified by its | |
1546 | * cell number (returned by GetCE/GetCE64). | |
1547 | * | |
1548 | * Arguments: | |
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. | |
1553 | * | |
1554 | * Returns: | |
1555 | * 0 on success | |
1556 | * | |
1557 | * Environment: | |
1558 | * Nothing interesting. | |
1559 | * | |
1560 | * Side Effects: | |
1561 | * As advertised. | |
1562 | *------------------------------------------------------------------------*/ | |
1563 | ||
1564 | int | |
1565 | SRXAFSCB_GetCellByNum(struct rx_call *a_call, afs_int32 a_cellnum, | |
1566 | char **a_name, serverList * a_hosts) | |
1567 | { | |
1568 | afs_int32 i, sn; | |
1569 | struct cell *tcell; | |
1570 | ||
1571 | RX_AFS_GLOCK(); | |
1572 | AFS_STATCNT(SRXAFSCB_GetCellByNum); | |
1573 | ||
1574 | a_hosts->serverList_val = 0; | |
1575 | a_hosts->serverList_len = 0; | |
1576 | ||
1577 | tcell = afs_GetCellStale(a_cellnum, READ_LOCK); | |
1578 | if (!tcell) { | |
1579 | *a_name = afs_strdup(""); | |
1580 | RX_AFS_GUNLOCK(); | |
1581 | return 0; | |
1582 | } | |
1583 | ||
1584 | ObtainReadLock(&tcell->lock); | |
1585 | *a_name = afs_strdup(tcell->cellName); | |
1586 | ||
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); | |
1591 | ||
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); | |
1596 | ||
1597 | RX_AFS_GUNLOCK(); | |
1598 | return 0; | |
1599 | } | |
1600 | ||
1601 | int | |
1602 | SRXAFSCB_TellMeAboutYourself(struct rx_call *a_call, | |
1603 | struct interfaceAddr *addr, | |
1604 | Capabilities * capabilities) | |
1605 | { | |
1606 | int i; | |
1607 | int code = 0; | |
1608 | afs_uint32 *dataBuffP; | |
1609 | afs_int32 dataBytes; | |
1610 | ||
1611 | RX_AFS_GLOCK(); | |
1612 | ||
1613 | AFS_STATCNT(SRXAFSCB_WhoAreYou); | |
1614 | ||
1615 | ObtainReadLock(&afs_xinterface); | |
1616 | ||
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]); | |
1625 | } | |
1626 | ||
1627 | ReleaseReadLock(&afs_xinterface); | |
1628 | ||
1629 | RX_AFS_GUNLOCK(); | |
1630 | ||
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; | |
1637 | ||
1638 | return code; | |
1639 | } | |
1640 | ||
1641 | ||
1642 | #if 0 && defined(AFS_LINUX24_ENV) | |
1643 | extern struct vcache *afs_globalVp; | |
1644 | ||
1645 | int recurse_dcache_parent(parent, a_index, addr, inode, flags, time, fileName) | |
1646 | struct dentry * parent; | |
1647 | afs_int32 a_index; | |
1648 | afs_int32 *addr; | |
1649 | afs_int32 *inode; | |
1650 | afs_int32 *flags; | |
1651 | afs_int32 *time; | |
1652 | char ** fileName; | |
1653 | { | |
1654 | struct dentry *this_parent = parent; | |
1655 | struct list_head *next; | |
1656 | int found = 0; | |
1657 | struct dentry *dentry; | |
1658 | ||
1659 | repeat: | |
1660 | next = this_parent->d_subdirs.next; | |
1661 | resume: | |
1662 | while (next != &this_parent->d_subdirs) { | |
1663 | struct list_head *tmp = next; | |
1664 | dentry = list_entry(tmp, struct dentry, d_child); | |
1665 | if (a_index == 0) | |
1666 | goto searchdone3; | |
1667 | a_index--; | |
1668 | next = tmp->next; | |
1669 | /* | |
1670 | * Descend a level if the d_subdirs list is non-empty. | |
1671 | */ | |
1672 | if (!list_empty(&dentry->d_subdirs)) { | |
1673 | this_parent = dentry; | |
1674 | goto repeat; | |
1675 | } | |
1676 | } | |
1677 | /* | |
1678 | * All done at this level ... ascend and resume the search. | |
1679 | */ | |
1680 | if (this_parent != parent) { | |
1681 | next = this_parent->d_child.next; | |
1682 | this_parent = this_parent->d_parent; | |
1683 | goto resume; | |
1684 | } | |
1685 | goto ret; | |
1686 | ||
1687 | searchdone3: | |
1688 | if (d_unhashed(dentry)) | |
1689 | *flags = 1; | |
1690 | else | |
1691 | *flags = 0; | |
1692 | ||
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; | |
1697 | ||
1698 | return 0; | |
1699 | ret: | |
1700 | return 1; | |
1701 | } | |
1702 | #endif | |
1703 | ||
1704 | int | |
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, | |
1707 | char ** fileName) | |
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; | |
1715 | ||
1716 | #ifdef RX_ENABLE_LOCKS | |
1717 | AFS_GLOCK(); | |
1718 | #endif /* RX_ENABLE_LOCKS */ | |
1719 | ||
1720 | #if defined(AFS_LINUX24_ENV) | |
1721 | spin_lock(&dcache_lock); | |
1722 | #endif | |
1723 | ||
1724 | cur = head; | |
1725 | while ((cur = cur->next) != head) { | |
1726 | dentry = list_entry(cur, struct dentry, d_alias); | |
1727 | ||
1728 | dget_locked(dentry); | |
1729 | ||
1730 | #if defined(AFS_LINUX24_ENV) | |
1731 | spin_unlock(&dcache_lock); | |
1732 | #endif | |
1733 | if (a_index == 0) | |
1734 | goto searchdone2; | |
1735 | a_index--; | |
1736 | ||
1737 | if (recurse_dcache_parent(dentry, a_index, addr, inode, flags, time, fileName) == 0) { | |
1738 | dput(dentry); | |
1739 | code = 0; | |
1740 | goto fcnDone; | |
1741 | } | |
1742 | dput(dentry); | |
1743 | } | |
1744 | searchdone2: | |
1745 | if (cur == head) { | |
1746 | /*Past EOF*/ | |
1747 | code = 1; | |
1748 | *fileName = afs_strdup(""); | |
1749 | goto fcnDone; | |
1750 | } | |
1751 | ||
1752 | if (d_unhashed(dentry)) | |
1753 | *flags = 1; | |
1754 | else | |
1755 | *flags = 0; | |
1756 | ||
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; | |
1761 | ||
1762 | dput(dentry); | |
1763 | code = 0; | |
1764 | ||
1765 | fcnDone: | |
1766 | ||
1767 | #ifdef RX_ENABLE_LOCKS | |
1768 | AFS_GUNLOCK(); | |
1769 | #endif /* RX_ENABLE_LOCKS */ | |
1770 | #endif | |
1771 | return(code); | |
1772 | ||
1773 | } /*SRXAFSCB_GetDE*/ |