backport to buster
[hcoop/debian/openafs.git] / src / afs / afs_callback.c
CommitLineData
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
25afs_int32 afs_allCBs = 0; /*Break callbacks on all objects */
26afs_int32 afs_oddCBs = 0; /*Break callbacks on dirs */
27afs_int32 afs_evenCBs = 0; /*Break callbacks received on files */
28afs_int32 afs_allZaps = 0; /*Objects entries deleted */
29afs_int32 afs_oddZaps = 0; /*Dir cache entries deleted */
30afs_int32 afs_evenZaps = 0; /*File cache entries deleted */
31afs_int32 afs_connectBacks = 0;
32
33/*
34 * Some debugging aids.
35 */
36static 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};
67unsigned long lastCallBack_vnode;
68unsigned int lastCallBack_dv;
69osi_timeval_t lastCallBack_time;
70
71/* these are for storing alternate interface addresses */
72struct 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
97int
98SRXAFSCB_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
184int
185SRXAFSCB_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
291int
292SRXAFSCB_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 = &ltable[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
396Appears to need to be called with GLOCK held, as the icl_Event4 stuff asserts otherwise
397
398 *------------------------------------------------------------------------*/
399
400static int
401ClearCallBack(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 */
434loop1:
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 */
518loop2:
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
609int
610SRXAFSCB_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
665int
666SRXAFSCB_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
704int
705SRXAFSCB_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
792int
793SRXAFSCB_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
839int
840SRXAFSCB_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
973int
974afs_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
1012int
1013shutdown_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
1046int
1047SRXAFSCB_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
1077int
1078SRXAFSCB_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
1128int
1129SRXAFSCB_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
1165int
1166SRXAFSCB_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
1208int
1209SRXAFSCB_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
1262int
1263SRXAFSCB_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
1331int
1332SRXAFSCB_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 */
1387static void
1388afs_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
1432int
1433SRXAFSCB_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 *------------------------------------------------------------------------*/
1500int
1501SRXAFSCB_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 *------------------------------------------------------------------------*/
1533int
1534SRXAFSCB_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
1564int
1565SRXAFSCB_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
1601int
1602SRXAFSCB_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)
1643extern struct vcache *afs_globalVp;
1644
1645int 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
1659repeat:
1660 next = this_parent->d_subdirs.next;
1661resume:
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
1704int
1705SRXAFSCB_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
1765fcnDone:
1766
1767#ifdef RX_ENABLE_LOCKS
1768 AFS_GUNLOCK();
1769#endif /* RX_ENABLE_LOCKS */
1770#endif
1771 return(code);
1772
1773} /*SRXAFSCB_GetDE*/