Bug Summary

File:afsd/afsd.c
Location:line 1873, column 27
Description:Access to field 'data' results in a dereference of a null pointer (loaded from field 'items')

Annotated Source Code

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 * Information Technology Center
12 * October 1987
13 *
14 * Description:
15 * The Andrew File System startup process. It is responsible for
16 * reading and parsing the various configuration files, starting up
17 * the kernel processes required by AFS and feeding the configuration
18 * information to the kernel.
19 *
20 * Recognized flags are:
21 * -blocks The number of blocks available in the workstation cache.
22 * -files The target number of files in the workstation cache (Default:
23 * 1000).
24 * -rootvol The name of the root volume to use.
25 * -stat The number of stat cache entries.
26 * -hosts List of servers to check for volume location info FOR THE
27 * HOME CELL.
28 * -memcache Use an in-memory cache rather than disk.
29 * -cachedir The base directory for the workstation cache.
30 * -mountdir The directory on which the AFS is to be mounted.
31 * -confdir The configuration directory .
32 * -nosettime Don't keep checking the time to avoid drift (default).
33 * -settime Keep checking the time to avoid drift.
34 * -rxmaxmtu Set the max mtu to help with VPN issues.
35 * -verbose Be chatty.
36 * -disable-dynamic-vcaches Disable the use of -stat value as the starting size of
37 * the size of the vcache/stat cache pool,
38 * but increase that pool dynamically as needed.
39 * -debug Print out additional debugging info.
40 * -kerndev [OBSOLETE] The kernel device for AFS.
41 * -dontfork [OBSOLETE] Don't fork off as a new process.
42 * -daemons The number of background daemons to start (Default: 2).
43 * -rmtsys Also fires up an afs remote sys call (e.g. pioctl, setpag)
44 * support daemon
45 * -chunksize [n] 2^n is the chunksize to be used. 0 is default.
46 * -dcache The number of data cache entries.
47 * -biods Number of bkg I/O daemons (AIX3.1 only)
48 * -prealloc Number of preallocated "small" memory blocks
49 * -logfile [OBSOLETE] Place where to put the logfile (default in
50 * <cache>/etc/AFSLog.
51 * -waitclose make close calls always synchronous (slows em down, tho)
52 * -files_per_subdir [n] number of files per cache subdir. (def=2048)
53 * -shutdown Shutdown afs daemons
54 *---------------------------------------------------------------------------*/
55
56#include <afsconfig.h>
57#include <afs/param.h>
58
59#ifdef IGNORE_SOME_GCC_WARNINGS
60# pragma GCC diagnostic warning "-Wdeprecated-declarations"
61#endif
62
63#define VFS1 1
64
65#include <afs/stds.h>
66
67#include <afs/cmd.h>
68
69#include "afsd.h"
70
71#include <afs/afs_assert.h>
72#include <afs/afsutil.h>
73#include <stdlib.h>
74#include <stdio.h>
75#include <signal.h>
76#include <string.h>
77#include <stdlib.h>
78#include <time.h>
79#include <sys/types.h>
80#include <sys/stat.h>
81#include <sys/file.h>
82#include <errno(* __error()).h>
83#include <sys/time.h>
84#include <sys/wait.h>
85
86/* darwin dirent.h doesn't give us the prototypes we want if KERNEL is
87 * defined */
88#if defined(UKERNEL) && defined(AFS_USR_DARWIN_ENV)
89# undef KERNEL
90# include <dirent.h>
91# define KERNEL
92#else
93# include <dirent.h>
94#endif
95
96
97#ifdef HAVE_SYS_PARAM_H1
98#include <sys/param.h>
99#endif
100
101#ifdef HAVE_SYS_FS_TYPES_H
102#include <sys/fs_types.h>
103#endif
104
105#if defined(HAVE_SYS_MOUNT_H1) && !defined(AFS_ARM_DARWIN_ENV)
106#include <sys/mount.h>
107#endif
108
109#ifdef HAVE_SYS_FCNTL_H1
110#include <sys/fcntl.h>
111#endif
112
113#ifdef HAVE_SYS_MNTTAB_H
114#include <sys/mnttab.h>
115#endif
116
117#ifdef HAVE_SYS_MNTENT_H
118#include <sys/mntent.h>
119#endif
120
121#ifdef HAVE_MNTENT_H
122#include <mntent.h>
123#endif
124
125#ifdef HAVE_SYS_VFS_H
126#include <sys/vfs.h>
127#endif
128
129#ifdef HAVE_SYS_FSTYP_H
130#include <sys/fstyp.h>
131#endif
132
133#ifdef HAVE_UNISTD_H1
134#include <unistd.h>
135#endif
136
137#ifdef HAVE_FCNTL_H1
138#include <fcntl.h>
139#endif
140
141#include <netinet/in.h>
142#include <afs/afs_args.h>
143#include <afs/cellconfig.h>
144#include <ctype.h>
145#include <afs/afssyscalls.h>
146#include <afs/afsutil.h>
147#include <afs/sys_prototypes.h>
148
149#ifdef AFS_SGI61_ENV
150#include <unistd.h>
151#include <libelf.h>
152#include <dwarf.h>
153#include <libdwarf.h>
154void set_staticaddrs(void);
155#endif /* AFS_SGI61_ENV */
156#if defined(AFS_SGI62_ENV) && !defined(AFS_SGI65_ENV)
157#include <sym.h>
158#include <symconst.h>
159#endif
160#ifdef AFS_SGI65_ENV
161#include <sched.h>
162#endif
163
164#ifdef AFS_DARWIN_ENV
165#ifdef AFS_DARWIN80_ENV
166#include <sys/ioctl.h>
167#include <sys/xattr.h>
168#endif
169#include <CoreFoundation/CoreFoundation.h>
170
171#include <SystemConfiguration/SystemConfiguration.h>
172#include <SystemConfiguration/SCDynamicStore.h>
173
174#ifndef AFS_ARM_DARWIN_ENV
175#include <IOKit/pwr_mgt/IOPMLib.h>
176#include <IOKit/IOMessage.h>
177
178static io_connect_t root_port;
179static IONotificationPortRef notify;
180static io_object_t iterator;
181#endif
182
183static CFRunLoopSourceRef source;
184
185static int event_pid;
186
187#endif /* AFS_DARWIN_ENV */
188
189#if AFS_HAVE_STATVFS1 || defined(HAVE_SYS_STATVFS_H1)
190#include <sys/statvfs.h>
191#else
192#if defined(AFS_SUN_ENV)
193#include <sys/vfs.h>
194#else
195#ifdef HAVE_SYS_STATFS_H
196#include <sys/statfs.h>
197#endif
198#endif
199#endif
200
201#undef VIRTUE
202#undef VICE
203
204
205#define CACHEINFOFILE"cacheinfo" "cacheinfo"
206#define DCACHEFILE"CacheItems" "CacheItems"
207#define VOLINFOFILE"VolumeItems" "VolumeItems"
208#define CELLINFOFILE"CellItems" "CellItems"
209
210#define MAXIPADDRS1024 1024
211
212char LclCellName[64];
213
214#define MAX_CACHE_LOOPS4 4
215
216
217/*
218 * Internet address (old style... should be updated). This was pulled out of the old 4.2
219 * version of <netinet/in.h>, since it's still useful.
220 */
221struct in_addr_42 {
222 union {
223 struct {
224 u_char s_b1, s_b2, s_b3, s_b4;
225 } S_un_b;
226 struct {
227 u_short s_w1, s_w2;
228 } S_un_w;
229 afs_uint32 S_addr;
230 } S_un;
231};
232
233#define mPrintIPAddr(ipaddr)printf("[%d.%d.%d.%d] ", ((struct in_addr_42 *) &(ipaddr)
)->S_un.S_un_b.s_b1, ((struct in_addr_42 *) &(ipaddr))
->S_un.S_un_b.s_b2, ((struct in_addr_42 *) &(ipaddr))->
S_un.S_un_b.s_b3, ((struct in_addr_42 *) &(ipaddr))->S_un
.S_un_b.s_b4)
printf("[%d.%d.%d.%d] ", \
234 ((struct in_addr_42 *) &(ipaddr))->S_un.S_un_b.s_b1, \
235 ((struct in_addr_42 *) &(ipaddr))->S_un.S_un_b.s_b2, \
236 ((struct in_addr_42 *) &(ipaddr))->S_un.S_un_b.s_b3, \
237 ((struct in_addr_42 *) &(ipaddr))->S_un.S_un_b.s_b4)
238
239/*
240 * Global configuration variables.
241 */
242static afs_int32 enable_rxbind = 0;
243static afs_int32 afs_shutdown = 0;
244static afs_int32 cacheBlocks; /*Num blocks in the cache */
245static afs_int32 cacheFiles; /*Optimal # of files in workstation cache */
246static afs_int32 rwpct = 0;
247static afs_int32 ropct = 0;
248static afs_int32 cacheStatEntries; /*Number of stat cache entries */
249static char cacheBaseDir[1024]; /*Where the workstation AFS cache lives */
250static char confDir[1024]; /*Where the workstation AFS configuration lives */
251static char fullpn_DCacheFile[1024]; /*Full pathname of DCACHEFILE */
252static char fullpn_VolInfoFile[1024]; /*Full pathname of VOLINFOFILE */
253static char fullpn_CellInfoFile[1024]; /*Full pathanem of CELLINFOFILE */
254static char fullpn_CacheInfo[1024]; /*Full pathname of CACHEINFO */
255static char fullpn_VFile[1024]; /*Full pathname of data cache files */
256static char *vFilePtr; /*Ptr to the number part of above pathname */
257static int sawCacheMountDir = 0; /* from cmd line */
258static int sawCacheBaseDir = 0;
259static int sawCacheBlocks = 0;
260static int sawDCacheSize = 0;
261#ifdef AFS_AIX32_ENV
262static int sawBiod = 0;
263#endif
264static int sawCacheStatEntries = 0;
265char afsd_cacheMountDir[1024]; /*Mount directory for AFS */
266static char rootVolume[64] = "root.afs"; /*AFS root volume name */
267static afs_int32 cacheSetTime = 0; /*Keep checking time to avoid drift? */
268#ifdef AFS_XBSD_ENV1
269static int createAndTrunc = O_RDWR0x0002 | O_CREAT0x0200 | O_TRUNC0x0400; /*Create & truncate on open */
270#else
271static int createAndTrunc = O_CREAT0x0200 | O_TRUNC0x0400; /*Create & truncate on open */
272#endif
273static int ownerRWmode = 0600; /*Read/write OK by owner */
274static int filesSet = 0; /*True if number of files explicitly set */
275static int nFilesPerDir = 2048; /* # files per cache dir */
276#if defined(AFS_CACHE_BYPASS)
277#define AFSD_NDAEMONS2 4
278#else
279#define AFSD_NDAEMONS2 2
280#endif
281static int nDaemons = AFSD_NDAEMONS2; /* Number of background daemons */
282static int chunkSize = 0; /* 2^chunkSize bytes per chunk */
283static int dCacheSize; /* # of dcache entries */
284static int vCacheSize = 200; /* # of volume cache entries */
285static int rootVolSet = 0; /*True if root volume name explicitly set */
286int addrNum; /*Cell server address index being printed */
287static int cacheFlags = 0; /*Flags to cache manager */
288#ifdef AFS_AIX32_ENV
289static int nBiods = 5; /* AIX3.1 only */
290#endif
291static int preallocs = 400; /* Def # of allocated memory blocks */
292static int enable_peer_stats = 0; /* enable rx stats */
293static int enable_process_stats = 0; /* enable rx stats */
294static int enable_afsdb = 0; /* enable AFSDB support */
295static int enable_dynroot = 0; /* enable dynroot support */
296static int enable_fakestat = 0; /* enable fakestat support */
297static int enable_backuptree = 0; /* enable backup tree support */
298static int enable_nomount = 0; /* do not mount */
299static int enable_splitcache = 0;
300static int afsd_dynamic_vcaches = 0; /* Enable dynamic-vcache support */
301int afsd_verbose = 0; /*Are we being chatty? */
302int afsd_debug = 0; /*Are we printing debugging info? */
303static int afsd_CloseSynch = 0; /*Are closes synchronous or not? */
304static int rxmaxmtu = 0; /* Are we forcing a limit on the mtu? */
305static int rxmaxfrags = 0; /* Are we forcing a limit on frags? */
306
307#ifdef AFS_SGI62_ENV
308#define AFSD_INO_Tafs_uint32 ino64_t
309#else
310#define AFSD_INO_Tafs_uint32 afs_uint32
311#endif
312struct afsd_file_list {
313 int fileNum;
314 struct afsd_file_list *next;
315};
316struct afsd_file_list **cache_dir_filelist = NULL((void *)0);
317int *cache_dir_list = NULL((void *)0); /* Array of cache subdirs */
318int *dir_for_V = NULL((void *)0); /* Array: dir of each cache file.
319 * -1: file does not exist
320 * -2: file exists in top-level
321 * >=0: file exists in Dxxx
322 */
323#if !defined(AFS_CACHE_VNODE_PATH) && !defined(AFS_LINUX26_ENV)
324AFSD_INO_Tafs_uint32 *inode_for_V; /* Array of inodes for desired
325 * cache files */
326#endif
327int missing_DCacheFile = 1; /*Is the DCACHEFILE missing? */
328int missing_VolInfoFile = 1; /*Is the VOLINFOFILE missing? */
329int missing_CellInfoFile = 1; /*Is the CELLINFOFILE missing? */
330int afsd_rmtsys = 0; /* Default: don't support rmtsys */
331struct afs_cacheParams cparams; /* params passed to cache manager */
332
333int PartSizeOverflow(char *path, int cs);
334
335#if defined(AFS_SUN510_ENV) && defined(RXK_LISTENER_ENV1)
336static void fork_rx_syscall_wait();
337#endif
338static void fork_rx_syscall();
339static void fork_syscall();
340
341#if defined(AFS_DARWIN_ENV) && !defined(AFS_ARM_DARWIN_ENV)
342static void
343afsd_sleep_callback(void * refCon, io_service_t service,
344 natural_t messageType, void * messageArgument )
345{
346 switch (messageType) {
347 case kIOMessageCanSystemSleep:
348 /* Idle sleep is about to kick in; can
349 prevent sleep by calling IOCancelPowerChange, otherwise
350 if we don't ack in 30s the system sleeps anyway */
351
352 /* allow it */
353 IOAllowPowerChange(root_port, (long)messageArgument);
354 break;
355
356 case kIOMessageSystemWillSleep:
357 /* The system WILL go to sleep. Ack or suffer delay */
358
359 IOAllowPowerChange(root_port, (long)messageArgument);
360 break;
361
362 case kIOMessageSystemWillRestart:
363 /* The system WILL restart. Ack or suffer delay */
364
365 IOAllowPowerChange(root_port, (long)messageArgument);
366 break;
367
368 case kIOMessageSystemWillPowerOn:
369 case kIOMessageSystemHasPoweredOn:
370 /* coming back from sleep */
371
372 IOAllowPowerChange(root_port, (long)messageArgument);
373 break;
374
375 default:
376 IOAllowPowerChange(root_port, (long)messageArgument);
377 break;
378 }
379}
380
381static void
382afsd_update_addresses(CFRunLoopTimerRef timer, void *info)
383{
384 /* parse multihomed address files */
385 afs_uint32 addrbuf[MAXIPADDRS1024], maskbuf[MAXIPADDRS1024],
386 mtubuf[MAXIPADDRS1024];
387 char reason[1024];
388 afs_int32 code;
389
390 code =
391 parseNetFiles(addrbuf, maskbuf, mtubuf, MAXIPADDRS1024, reason,
392 AFSDIR_CLIENT_NETINFO_FILEPATHgetDirPath(AFSDIR_CLIENT_NETINFO_FILEPATH_ID),
393 AFSDIR_CLIENT_NETRESTRICT_FILEPATHgetDirPath(AFSDIR_CLIENT_NETRESTRICT_FILEPATH_ID));
394
395 if (code > 0) {
396 /* Note we're refreshing */
397 code = code | 0x40000000;
398 afsd_call_syscall(AFSOP_ADVISEADDR17, code, addrbuf, maskbuf, mtubuf);
399 } else
400 printf("ADVISEADDR: Error in specifying interface addresses:%s\n",
401 reason);
402
403 /* Since it's likely this means our DNS server changed, reinit now */
404 if (enable_afsdb)
405 res_init();
406}
407
408/* This function is called when the system's ip addresses may have changed. */
409static void
410afsd_ipaddr_callback (SCDynamicStoreRef store, CFArrayRef changed_keys, void *info)
411{
412 CFRunLoopTimerRef timer;
413
414 timer = CFRunLoopTimerCreate (NULL((void *)0), CFAbsoluteTimeGetCurrent () + 1.0,
415 0.0, 0, 0, afsd_update_addresses, NULL((void *)0));
416 CFRunLoopAddTimer (CFRunLoopGetCurrent (), timer,
417 kCFRunLoopDefaultMode);
418 CFRelease (timer);
419}
420
421static void
422afsd_event_cleanup(int signo) {
423
424 CFRunLoopRemoveSource(CFRunLoopGetCurrent(), source, kCFRunLoopDefaultMode);
425 CFRelease (source);
426 IODeregisterForSystemPower(&iterator);
427 IOServiceClose(root_port);
428 IONotificationPortDestroy(notify);
429 exit(0);
430}
431
432/* Adapted from "Living in a Dynamic TCP/IP Environment" technote. */
433static void
434afsd_install_events(void)
435{
436 SCDynamicStoreContext ctx = {0};
437 SCDynamicStoreRef store;
438
439 root_port = IORegisterForSystemPower(0,&notify,afsd_sleep_callback,&iterator);
440
441 if (root_port) {
442 CFRunLoopAddSource(CFRunLoopGetCurrent(),
443 IONotificationPortGetRunLoopSource(notify),
444 kCFRunLoopDefaultMode);
445 }
446
447
448 store = SCDynamicStoreCreate (NULL((void *)0),
449 CFSTR ("AddIPAddressListChangeCallbackSCF"),
450 afsd_ipaddr_callback, &ctx);
451
452 if (store) {
453 const void *keys[1];
454
455 /* Request IPV4 address change notification */
456 keys[0] = (SCDynamicStoreKeyCreateNetworkServiceEntity
457 (NULL((void *)0), kSCDynamicStoreDomainState,
458 kSCCompAnyRegex, kSCEntNetIPv4));
459
460#if 0
461 /* This should tell us when the hostname(s) change. do we care? */
462 keys[N] = SCDynamicStoreKeyCreateHostNames (NULL((void *)0));
463#endif
464
465 if (keys[0] != NULL((void *)0)) {
466 CFArrayRef pattern_array;
467
468 pattern_array = CFArrayCreate (NULL((void *)0), keys, 1,
469 &kCFTypeArrayCallBacks);
470
471 if (pattern_array != NULL((void *)0))
472 {
473 SCDynamicStoreSetNotificationKeys (store, NULL((void *)0), pattern_array);
474 source = SCDynamicStoreCreateRunLoopSource (NULL((void *)0), store, 0);
475
476 CFRelease (pattern_array);
477 }
478
479 if (keys[0] != NULL((void *)0))
480 CFRelease (keys[0]);
481 }
482
483 CFRelease (store);
484 }
485
486 if (source != NULL((void *)0)) {
487 CFRunLoopAddSource (CFRunLoopGetCurrent(),
488 source, kCFRunLoopDefaultMode);
489 }
490
491 signal(SIGTERM15, afsd_event_cleanup);
492
493 CFRunLoopRun();
494}
495#endif
496
497/* ParseArgs is now obsolete, being handled by cmd */
498
499/*------------------------------------------------------------------------------
500 * ParseCacheInfoFile
501 *
502 * Description:
503 * Open the file containing the description of the workstation's AFS cache
504 * and pull out its contents. The format of this file is as follows:
505 *
506 * cacheMountDir:cacheBaseDir:cacheBlocks
507 *
508 * Arguments:
509 * None.
510 *
511 * Returns:
512 * 0 if everything went well,
513 * 1 otherwise.
514 *
515 * Environment:
516 * Nothing interesting.
517 *
518 * Side Effects:
519 * Sets globals.
520 *---------------------------------------------------------------------------*/
521
522int
523ParseCacheInfoFile(void)
524{
525 static char rn[] = "ParseCacheInfoFile"; /*This routine's name */
526 FILE *cachefd; /*Descriptor for cache info file */
527 int parseResult; /*Result of our fscanf() */
528 afs_int32 tCacheBlocks;
529 char tCacheBaseDir[1024], *tbd, tCacheMountDir[1024], *tmd;
530
531 if (afsd_debug)
532 printf("%s: Opening cache info file '%s'...\n", rn, fullpn_CacheInfo);
533
534 cachefd = fopen(fullpn_CacheInfo, "r");
535 if (!cachefd) {
536 printf("%s: Can't read cache info file '%s'\n", rn, fullpn_CacheInfo);
537 return (1);
538 }
539
540 /*
541 * Parse the contents of the cache info file. All chars up to the first
542 * colon are the AFS mount directory, all chars to the next colon are the
543 * full path name of the workstation cache directory and all remaining chars
544 * represent the number of blocks in the cache.
545 */
546 tCacheMountDir[0] = tCacheBaseDir[0] = '\0';
547 parseResult =
548 fscanf(cachefd, "%1024[^:]:%1024[^:]:%d", tCacheMountDir,
549 tCacheBaseDir, &tCacheBlocks);
550
551 /*
552 * Regardless of how the parse went, we close the cache info file.
553 */
554 fclose(cachefd);
555
556 if (parseResult == EOF(-1) || parseResult < 3) {
557 printf("%s: Format error in cache info file!\n", rn);
558 if (parseResult == EOF(-1))
559 printf("\tEOF encountered before any field parsed.\n");
560 else
561 printf("\t%d out of 3 fields successfully parsed.\n",
562 parseResult);
563
564 return (1);
565 }
566
567 for (tmd = tCacheMountDir; *tmd == '\n' || *tmd == ' ' || *tmd == '\t';
568 tmd++);
569 for (tbd = tCacheBaseDir; *tbd == '\n' || *tbd == ' ' || *tbd == '\t';
570 tbd++);
571 /* now copy in the fields not explicitly overridden by cmd args */
572 if (!sawCacheMountDir)
573 strcpy(afsd_cacheMountDir, tmd);
574 if (!sawCacheBaseDir)
575 strcpy(cacheBaseDir, tbd);
576 if (!sawCacheBlocks)
577 cacheBlocks = tCacheBlocks;
578
579 if (afsd_debug) {
580 printf("%s: Cache info file successfully parsed:\n", rn);
581 printf
582 ("\tcacheMountDir: '%s'\n\tcacheBaseDir: '%s'\n\tcacheBlocks: %d\n",
583 tmd, tbd, tCacheBlocks);
584 }
585 if (!(cacheFlags & AFSCALL_INIT_MEMCACHE0x1)) {
586 return (PartSizeOverflow(tbd, cacheBlocks));
587 }
588
589 return (0);
590}
591
592/*
593 * All failures to open the partition are ignored. Also if the cache dir
594 * isn't a mounted partition it's also ignored since we can't guarantee
595 * what will be stored afterwards. Too many if's. This is now purely
596 * advisory. ODS with over 2G partition also gives warning message.
597 *
598 * Returns:
599 * 0 if everything went well,
600 * 1 otherwise.
601 */
602int
603PartSizeOverflow(char *path, int cs)
604{
605 int bsize = -1;
606 afs_int64 totalblks, mint;
607#if AFS_HAVE_STATVFS1 || defined(HAVE_SYS_STATVFS_H1)
608 struct statvfs statbuf;
609
610 if (statvfs(path, &statbuf) != 0) {
611 if (afsd_debug)
612 printf
613 ("statvfs failed on %s; skip checking for adequate partition space\n",
614 path);
615 return 0;
616 }
617 totalblks = statbuf.f_blocks;
618 bsize = statbuf.f_frsize;
619#if AFS_AIX51_ENV
620 if (strcmp(statbuf.f_basetype, "jfs")) {
621 fprintf(stderr__stderrp, "Cache filesystem '%s' must be jfs (now %s)\n",
622 path, statbuf.f_basetype);
623 return 1;
624 }
625#endif /* AFS_AIX51_ENV */
626
627#else /* AFS_HAVE_STATVFS */
628 struct statfs statbuf;
629
630 if (statfs(path, &statbuf) < 0) {
631 if (afsd_debug)
632 printf
633 ("statfs failed on %s; skip checking for adequate partition space\n",
634 path);
635 return 0;
636 }
637 totalblks = statbuf.f_blocks;
638 bsize = statbuf.f_bsize;
639#endif
640 if (bsize == -1)
641 return 0; /* success */
642
643 /* now free and totalblks are in fragment units, but we want them in 1K units */
644 if (bsize >= 1024) {
645 totalblks *= (bsize / 1024);
646 } else {
647 totalblks /= (1024 / bsize);
648 }
649
650 mint = totalblks / 100 * 95;
651 if (cs > mint) {
652 printf
653 ("Cache size (%d) must be less than 95%% of partition size (which is %lld). Lower cache size\n",
654 cs, mint);
655 return 1;
656 }
657
658 return 0;
659}
660
661/*-----------------------------------------------------------------------------
662 * GetVFileNumber
663 *
664 * Description:
665 * Given the final component of a filename expected to be a data cache file,
666 * return the integer corresponding to the file. Note: we reject names that
667 * are not a ``V'' followed by an integer. We also reject those names having
668 * the right format but lying outside the range [0..cacheFiles-1].
669 *
670 * Arguments:
671 * fname : Char ptr to the filename to parse.
672 * max : integer for the highest number to accept
673 *
674 * Returns:
675 * >= 0 iff the file is really a data cache file numbered from 0 to cacheFiles-1, or
676 * -1 otherwise.
677 *
678 * Environment:
679 * Nothing interesting.
680 *
681 * Side Effects:
682 * None.
683 *---------------------------------------------------------------------------*/
684
685static int
686doGetXFileNumber(char *fname, char filechar, int maxNum)
687{
688 int computedVNumber; /*The computed file number we return */
689 int filenameLen; /*Number of chars in filename */
690 int currDigit; /*Current digit being processed */
691
692 /*
693 * The filename must have at least two characters, the first of which must be a ``filechar''
694 * and the second of which cannot be a zero unless the file is exactly two chars long.
695 */
696 filenameLen = strlen(fname);
697 if (filenameLen < 2)
698 return (-1);
699 if (fname[0] != filechar)
700 return (-1);
701 if ((filenameLen > 2) && (fname[1] == '0'))
702 return (-1);
703
704 /*
705 * Scan through the characters in the given filename, failing immediately if a non-digit
706 * is found.
707 */
708 for (currDigit = 1; currDigit < filenameLen; currDigit++)
709 if (isdigit(fname[currDigit])__isctype((fname[currDigit]), 0x00000400L) == 0)
710 return (-1);
711
712 /*
713 * All relevant characters are digits. Pull out the decimal number they represent.
714 * Reject it if it's out of range, otherwise return it.
715 */
716 computedVNumber = atoi(++fname);
717 if (computedVNumber < cacheFiles)
718 return (computedVNumber);
719 else
720 return (-1);
721}
722
723int
724GetVFileNumber(char *fname, int maxFile)
725{
726 return doGetXFileNumber(fname, 'V', maxFile);
727}
728
729int
730GetDDirNumber(char *fname, int maxDir)
731{
732 return doGetXFileNumber(fname, 'D', maxDir);
733}
734
735
736/*-----------------------------------------------------------------------------
737 * CreateCacheFile
738 *
739 * Description:
740 * Given a full pathname for a file we need to create for the workstation AFS
741 * cache, go ahead and create the file.
742 *
743 * Arguments:
744 * fname : Full pathname of file to create.
745 * statp : A pointer to a stat buffer which, if NON-NULL, will be
746 * filled by fstat()
747 *
748 * Returns:
749 * 0 iff the file was created,
750 * -1 otherwise.
751 *
752 * Environment:
753 * The given cache file has been found to be missing.
754 *
755 * Side Effects:
756 * As described.
757 *---------------------------------------------------------------------------*/
758
759static int
760CreateCacheSubDir(char *basename, int dirNum)
761{
762 static char rn[] = "CreateCacheSubDir"; /* Routine Name */
763 char dir[1024];
764 int ret;
765
766 /* Build the new cache subdirectory */
767 sprintf(dir, "%s/D%d", basename, dirNum);
768
769 if (afsd_debug)
770 printf("%s: Creating cache subdir '%s'\n", rn, dir);
771
772 if ((ret = mkdir(dir, 0700)) != 0) {
773 printf("%s: Can't create '%s', error return is %d (%d)\n", rn, dir,
774 ret, errno(* __error()));
775 if (errno(* __error()) != EEXIST17)
776 return (-1);
777 }
778
779 /* Mark this directory as created */
780 cache_dir_list[dirNum] = 0;
781
782 /* And return success */
783 return (0);
784}
785
786static void
787SetNoBackupAttr(char *fullpn)
788{
789#ifdef AFS_DARWIN80_ENV
790 int ret;
791
792 ret = setxattr(fullpn, "com.apple.metadata:com_apple_backup_excludeItem",
793 "com.apple.backupd", strlen("com.apple.backupd"), 0,
794 XATTR_CREATE);
795 if(ret < 0)
796 {
797 if(errno(* __error()) != EEXIST17)
798 fprintf(stderr__stderrp, "afsd: Warning: failed to set attribute to preclude cache backup: %s\n", strerror(errno(* __error())));
799 }
800#endif
801 return;
802}
803
804static int
805MoveCacheFile(char *basename, int fromDir, int toDir, int cacheFile,
806 int maxDir)
807{
808 static char rn[] = "MoveCacheFile";
809 char from[1024], to[1024];
810 int ret;
811
812 if (cache_dir_list[toDir] < 0
813 && (ret = CreateCacheSubDir(basename, toDir))) {
814 printf("%s: Can't create directory '%s/D%d'\n", rn, basename, toDir);
815 return ret;
816 }
817
818 /* Build the from,to dir */
819 if (fromDir < 0) {
820 /* old-style location */
821 snprintf(from, sizeof(from), "%s/V%d", basename, cacheFile);
822 } else {
823 snprintf(from, sizeof(from), "%s/D%d/V%d", basename, fromDir,
824 cacheFile);
825 }
826
827 snprintf(to, sizeof(from), "%s/D%d/V%d", basename, toDir, cacheFile);
828
829 if (afsd_verbose)
830 printf("%s: Moving cacheFile from '%s' to '%s'\n", rn, from, to);
831
832 if ((ret = rename(from, to)) != 0) {
833 printf("%s: Can't rename '%s' to '%s', error return is %d (%d)\n", rn,
834 from, to, ret, errno(* __error()));
835 return -1;
836 }
837 SetNoBackupAttr(to);
838
839 /* Reset directory pointer; fix file counts */
840 dir_for_V[cacheFile] = toDir;
841 cache_dir_list[toDir]++;
842 if (fromDir < maxDir && fromDir >= 0)
843 cache_dir_list[fromDir]--;
844
845 return 0;
846}
847
848int
849CreateCacheFile(char *fname, struct stat *statp)
850{
851 static char rn[] = "CreateCacheFile"; /*Routine name */
852 int cfd; /*File descriptor to AFS cache file */
853 int closeResult; /*Result of close() */
854
855 if (afsd_debug)
856 printf("%s: Creating cache file '%s'\n", rn, fname);
857 cfd = open(fname, createAndTrunc, ownerRWmode);
858 if (cfd <= 0) {
859 printf("%s: Can't create '%s', error return is %d (%d)\n", rn, fname,
860 cfd, errno(* __error()));
861 return (-1);
862 }
863 if (statp != NULL((void *)0)) {
864 closeResult = fstat(cfd, statp);
865 if (closeResult) {
866 printf
867 ("%s: Can't stat newly-created AFS cache file '%s' (code %d)\n",
868 rn, fname, errno(* __error()));
869 return (-1);
870 }
871 }
872 closeResult = close(cfd);
873 if (closeResult) {
874 printf
875 ("%s: Can't close newly-created AFS cache file '%s' (code %d)\n",
876 rn, fname, errno(* __error()));
877 return (-1);
878 }
879
880 return (0);
881}
882
883static void
884CreateFileIfMissing(char *fullpn, int missing)
885{
886 if (missing) {
887 if (CreateCacheFile(fullpn, NULL((void *)0)))
888 printf("CreateFileIfMissing: Can't create '%s'\n", fullpn);
889 }
890}
891
892static void
893UnlinkUnwantedFile(char *rn, char *fullpn_FileToDelete, char *fileToDelete)
894{
895 if (unlink(fullpn_FileToDelete)) {
896 if ((errno(* __error()) == EISDIR21 || errno(* __error()) == EPERM1) && *fileToDelete == 'D') {
897 if (rmdir(fullpn_FileToDelete)) {
898 printf("%s: Can't rmdir '%s', errno is %d\n", rn,
899 fullpn_FileToDelete, errno(* __error()));
900 }
901 } else
902 printf("%s: Can't unlink '%s', errno is %d\n", rn,
903 fullpn_FileToDelete, errno(* __error()));
904 }
905}
906
907/*-----------------------------------------------------------------------------
908 * SweepAFSCache
909 *
910 * Description:
911 * Sweep through the AFS cache directory, recording the inode number for
912 * each valid data cache file there. Also, delete any file that doesn't belong
913 * in the cache directory during this sweep, and remember which of the other
914 * residents of this directory were seen. After the sweep, we create any data
915 * cache files that were missing.
916 *
917 * Arguments:
918 * vFilesFound : Set to the number of data cache files found.
919 *
920 * Returns:
921 * 0 if everything went well,
922 * -1 otherwise.
923 *
924 * Environment:
925 * This routine may be called several times. If the number of data cache files
926 * found is less than the global cacheFiles, then the caller will need to call it
927 * again to record the inodes of the missing zero-length data cache files created
928 * in the previous call.
929 *
930 * Side Effects:
931 * Fills up the global inode_for_V array, may create and/or delete files as
932 * explained above.
933 *---------------------------------------------------------------------------*/
934
935
936static int
937doSweepAFSCache(int *vFilesFound,
938 char *directory, /* /path/to/cache/directory */
939 int dirNum, /* current directory number */
940 int maxDir) /* maximum directory number */
941{
942 static char rn[] = "doSweepAFSCache"; /* Routine Name */
943 char fullpn_FileToDelete[1024]; /*File to be deleted from cache */
944 char *fileToDelete; /*Ptr to last component of above */
945 DIR *cdirp; /*Ptr to cache directory structure */
946#ifdef AFS_SGI62_ENV
947 struct dirent64 *currp; /*Current directory entry */
948#else
949 struct dirent *currp; /*Current directory entry */
950#endif
951 int vFileNum; /*Data cache file's associated number */
952 int thisDir; /* A directory number */
953 int highDir = 0;
954
955 if (afsd_debug)
956 printf("%s: Opening cache directory '%s'\n", rn, directory);
957
958 if (chmod(directory, 0700)) { /* force it to be 700 */
959 printf("%s: Can't 'chmod 0700' the cache dir, '%s'.\n", rn,
960 directory);
961 return (-1);
962 }
963 cdirp = opendir(directory);
964 if (cdirp == (DIR *) 0) {
965 printf("%s: Can't open AFS cache directory, '%s'.\n", rn, directory);
966 return (-1);
967 }
968
969 /*
970 * Scan the directory entries, remembering data cache file inodes
971 * and the existance of other important residents. Recurse into
972 * the data subdirectories.
973 *
974 * Delete all files and directories that don't belong here.
975 */
976 sprintf(fullpn_FileToDelete, "%s/", directory);
977 fileToDelete = fullpn_FileToDelete + strlen(fullpn_FileToDelete);
978
979#ifdef AFS_SGI62_ENV
980 for (currp = readdir64(cdirp); currp; currp = readdir64(cdirp))
981#else
982 for (currp = readdir(cdirp); currp; currp = readdir(cdirp))
983#endif
984 {
985 if (afsd_debug) {
986 printf("%s: Current directory entry:\n", rn);
987#if defined(AFS_SGI62_ENV) || defined(AFS_DARWIN90_ENV)
988 printf("\tinode=%" AFS_INT64_FMT"lld" ", reclen=%d, name='%s'\n", currp->d_inod_fileno,
989 currp->d_reclen, currp->d_name);
990#elif defined(AFS_DFBSD_ENV) || defined(AFS_USR_DFBSD_ENV)
991 printf("\tinode=%ld, name='%s'\n", (long)currp->d_inod_fileno, currp->d_name);
992#else
993 printf("\tinode=%ld, reclen=%d, name='%s'\n", (long)currp->d_inod_fileno,
994 currp->d_reclen, currp->d_name);
995#endif
996 }
997
998 /*
999 * If dirNum < 0, we are a top-level cache directory and should
1000 * only contain sub-directories and other sundry files. Therefore,
1001 * V-files are valid only if dirNum >= 0, and Directories are only
1002 * valid if dirNum < 0.
1003 */
1004
1005 if (*(currp->d_name) == 'V'
1006 && ((vFileNum = GetVFileNumber(currp->d_name, cacheFiles)) >=
1007 0)) {
1008 /*
1009 * Found a valid data cache filename. Remember this
1010 * file's inode, directory, and bump the number of files found
1011 * total and in this directory.
1012 */
1013#if !defined(AFS_CACHE_VNODE_PATH) && !defined(AFS_LINUX26_ENV)
1014 inode_for_V[vFileNum] = currp->d_inod_fileno;
1015#endif
1016 dir_for_V[vFileNum] = dirNum; /* remember this directory */
1017
1018 if (!maxDir) {
1019 /* If we're in a real subdir, mark this file to be moved
1020 * if we've already got too many files in this directory
1021 */
1022 assert(dirNum >= 0)do{if (!(dirNum >= 0)) AssertionFailed("afsd.c", 1022);}while
(0)
;
1023 cache_dir_list[dirNum]++; /* keep directory's file count */
1024 if (cache_dir_list[dirNum] > nFilesPerDir) {
1025 /* Too many files -- add to filelist */
1026 struct afsd_file_list *tmp = (struct afsd_file_list *)
1027 malloc(sizeof(*tmp));
1028 if (!tmp)
1029 printf
1030 ("%s: MALLOC FAILED allocating file_list entry\n",
1031 rn);
1032 else {
1033 tmp->fileNum = vFileNum;
1034 tmp->next = cache_dir_filelist[dirNum];
1035 cache_dir_filelist[dirNum] = tmp;
1036 }
1037 }
1038 }
1039 (*vFilesFound)++;
1040 } else if (dirNum < 0 && (*(currp->d_name) == 'D')
1041 && GetDDirNumber(currp->d_name, 1 << 30) >= 0) {
1042 int retval = 0;
1043 if ((vFileNum = GetDDirNumber(currp->d_name, maxDir)) >= 0) {
1044 /* Found a valid cachefile sub-Directory. Remember this number
1045 * and recurse into it. Note that subdirs cannot have subdirs.
1046 */
1047 retval = 1;
1048 } else if ((vFileNum = GetDDirNumber(currp->d_name, 1 << 30)) >=
1049 0) {
1050 /* This directory is going away, but figure out if there
1051 * are any cachefiles in here that should be saved by
1052 * moving them to other cache directories. This directory
1053 * will be removed later.
1054 */
1055 retval = 2;
1056 }
1057
1058 /* Save the highest directory number we've seen */
1059 if (vFileNum > highDir)
1060 highDir = vFileNum;
1061
1062 /* If this directory is staying, be sure to mark it as 'found' */
1063 if (retval == 1)
1064 cache_dir_list[vFileNum] = 0;
1065
1066 /* Print the dirname for recursion */
1067 sprintf(fileToDelete, "%s", currp->d_name);
1068
1069 /* Note: vFileNum is the directory number */
1070 retval =
1071 doSweepAFSCache(vFilesFound, fullpn_FileToDelete, vFileNum,
1072 (retval == 1 ? 0 : -1));
1073 if (retval) {
1074 printf("%s: Recursive sweep failed on directory %s\n", rn,
1075 currp->d_name);
1076 return retval;
1077 }
1078 } else if (dirNum < 0 && strcmp(currp->d_name, DCACHEFILE"CacheItems") == 0) {
1079 /*
1080 * Found the file holding the dcache entries.
1081 */
1082 missing_DCacheFile = 0;
1083 SetNoBackupAttr(fullpn_DCacheFile);
1084 } else if (dirNum < 0 && strcmp(currp->d_name, VOLINFOFILE"VolumeItems") == 0) {
1085 /*
1086 * Found the file holding the volume info.
1087 */
1088 missing_VolInfoFile = 0;
1089 SetNoBackupAttr(fullpn_VolInfoFile);
1090 } else if (dirNum < 0 && strcmp(currp->d_name, CELLINFOFILE"CellItems") == 0) {
1091 /*
1092 * Found the file holding the cell info.
1093 */
1094 missing_CellInfoFile = 0;
1095 SetNoBackupAttr(fullpn_CellInfoFile);
1096 } else if ((strcmp(currp->d_name, ".") == 0)
1097 || (strcmp(currp->d_name, "..") == 0) ||
1098#ifdef AFS_DECOSF_ENV
1099 /* these are magic AdvFS files */
1100 (strcmp(currp->d_name, ".tags") == 0)
1101 || (strcmp(currp->d_name, "quota.user") == 0)
1102 || (strcmp(currp->d_name, "quota.group") == 0) ||
1103#endif
1104#ifdef AFS_LINUX22_ENV
1105 /* this is the ext3 journal file */
1106 (strcmp(currp->d_name, ".journal") == 0) ||
1107#endif
1108 (strcmp(currp->d_name, "lost+found") == 0)) {
1109 /*
1110 * Don't do anything - this file is legit, and is to be left alone.
1111 */
1112 } else {
1113 /*
1114 * This file/directory doesn't belong in the cache. Nuke it.
1115 */
1116 sprintf(fileToDelete, "%s", currp->d_name);
1117 if (afsd_verbose)
1118 printf("%s: Deleting '%s'\n", rn, fullpn_FileToDelete);
1119 UnlinkUnwantedFile(rn, fullpn_FileToDelete, fileToDelete);
1120 }
1121 }
1122
1123 if (dirNum < 0) {
1124
1125 /*
1126 * Create all the cache files that are missing.
1127 */
1128 CreateFileIfMissing(fullpn_DCacheFile, missing_DCacheFile);
1129 CreateFileIfMissing(fullpn_VolInfoFile, missing_VolInfoFile);
1130 CreateFileIfMissing(fullpn_CellInfoFile, missing_CellInfoFile);
1131
1132 /* ADJUST CACHE FILES */
1133
1134 /* First, let's walk through the list of files and figure out
1135 * if there are any leftover files in extra directories or
1136 * missing files. Move the former and create the latter in
1137 * subdirs with extra space.
1138 */
1139
1140 thisDir = 0; /* Keep track of which subdir has space */
1141
1142 for (vFileNum = 0; vFileNum < cacheFiles; vFileNum++) {
1143 if (dir_for_V[vFileNum] == -1) {
1144 /* This file does not exist. Create it in the first
1145 * subdir that still has extra space.
1146 */
1147 while (thisDir < maxDir
1148 && cache_dir_list[thisDir] >= nFilesPerDir)
1149 thisDir++;
1150 if (thisDir >= maxDir)
1151 printf("%s: can't find directory to create V%d\n", rn,
1152 vFileNum);
1153 else {
1154 struct stat statb;
1155#if !defined(AFS_CACHE_VNODE_PATH) && !defined(AFS_LINUX26_ENV)
1156 assert(inode_for_V[vFileNum] == (AFSD_INO_T) 0)do{if (!(inode_for_V[vFileNum] == (afs_uint32) 0)) AssertionFailed
("afsd.c", 1156);}while(0)
;
1157#endif
1158 sprintf(vFilePtr, "D%d/V%d", thisDir, vFileNum);
1159 if (afsd_verbose)
1160 printf("%s: Creating '%s'\n", rn, fullpn_VFile);
1161 if (cache_dir_list[thisDir] < 0
1162 && CreateCacheSubDir(directory, thisDir))
1163 printf("%s: Can't create directory for '%s'\n", rn,
1164 fullpn_VFile);
1165 if (CreateCacheFile(fullpn_VFile, &statb))
1166 printf("%s: Can't create '%s'\n", rn, fullpn_VFile);
1167 else {
1168#if !defined(AFS_CACHE_VNODE_PATH) && !defined(AFS_LINUX26_ENV)
1169 inode_for_V[vFileNum] = statb.st_ino;
1170#endif
1171 dir_for_V[vFileNum] = thisDir;
1172 cache_dir_list[thisDir]++;
1173 (*vFilesFound)++;
1174 }
1175 SetNoBackupAttr(fullpn_VFile);
1176 }
1177
1178 } else if (dir_for_V[vFileNum] >= maxDir
1179 || dir_for_V[vFileNum] == -2) {
1180 /* This file needs to move; move it to the first subdir
1181 * that has extra space. (-2 means it's in the toplevel)
1182 */
1183 while (thisDir < maxDir
1184 && cache_dir_list[thisDir] >= nFilesPerDir)
1185 thisDir++;
1186 if (thisDir >= maxDir)
1187 printf("%s: can't find directory to move V%d\n", rn,
1188 vFileNum);
1189 else {
1190 if (MoveCacheFile
1191 (directory, dir_for_V[vFileNum], thisDir, vFileNum,
1192 maxDir)) {
1193 /* Cannot move. Ignore this file??? */
1194 /* XXX */
1195 }
1196 }
1197 }
1198 } /* for */
1199
1200 /* At this point, we've moved all of the valid cache files
1201 * into the valid subdirs, and created all the extra
1202 * cachefiles we need to create. Next, rebalance any subdirs
1203 * with too many cache files into the directories with not
1204 * enough cache files. Note that thisDir currently sits at
1205 * the lowest subdir that _may_ have room.
1206 */
1207
1208 for (dirNum = 0; dirNum < maxDir; dirNum++) {
1209 struct afsd_file_list *thisFile;
1210
1211 for (thisFile = cache_dir_filelist[dirNum];
1212 thisFile && cache_dir_list[dirNum] >= nFilesPerDir;
1213 thisFile = thisFile->next) {
1214 while (thisDir < maxDir
1215 && cache_dir_list[thisDir] >= nFilesPerDir)
1216 thisDir++;
1217 if (thisDir >= maxDir)
1218 printf("%s: can't find directory to move V%d\n", rn,
1219 vFileNum);
1220 else {
1221 if (MoveCacheFile
1222 (directory, dirNum, thisDir, thisFile->fileNum,
1223 maxDir)) {
1224 /* Cannot move. Ignore this file??? */
1225 /* XXX */
1226 }
1227 }
1228 } /* for each file to move */
1229 } /* for each directory */
1230
1231 /* Remove any directories >= maxDir -- they should be empty */
1232 for (; highDir >= maxDir; highDir--) {
1233 sprintf(fileToDelete, "D%d", highDir);
1234 UnlinkUnwantedFile(rn, fullpn_FileToDelete, fileToDelete);
1235 }
1236 }
1237
1238 /* dirNum < 0 */
1239 /*
1240 * Close the directory, return success.
1241 */
1242 if (afsd_debug)
1243 printf("%s: Closing cache directory.\n", rn);
1244 closedir(cdirp);
1245 return (0);
1246}
1247
1248char *
1249CheckCacheBaseDir(char *dir)
1250{
1251 struct stat statbuf;
1252
1253 if (!dir) {
1254 return "cache base dir not specified";
1255 }
1256 if (stat(dir, &statbuf) != 0) {
1257 return "unable to stat cache base directory";
1258 }
1259
1260 /* might want to check here for anything else goofy, like cache pointed at a non-dedicated directory, etc */
1261
1262#ifdef AFS_LINUX24_ENV
1263 {
1264 int res;
1265 struct statfs statfsbuf;
1266
1267 res = statfs(dir, &statfsbuf);
1268 if (res != 0) {
1269 return "unable to statfs cache base directory";
1270 }
1271#if !defined(AFS_LINUX26_ENV)
1272 if (statfsbuf.f_type == 0x52654973) { /* REISERFS_SUPER_MAGIC */
1273 return "cannot use reiserfs as cache partition";
1274 } else if (statfsbuf.f_type == 0x58465342) { /* XFS_SUPER_MAGIC */
1275 return "cannot use xfs as cache partition";
1276 } else if (statfsbuf.f_type == 0x01021994) { /* TMPFS_SUPER_MAGIC */
1277 return "cannot use tmpfs as cache partition";
1278 } else if (statfsbuf.f_type != 0xEF53) {
1279 return "must use ext2 or ext3 for cache partition";
1280 }
1281#endif
1282 }
1283#endif
1284
1285#ifdef AFS_HPUX_ENV
1286 {
1287 int res;
1288 struct statfs statfsbuf;
1289 char name[FSTYPSZ];
1290
1291 res = statfs(dir, &statfsbuf);
1292 if (res != 0) {
1293 return "unable to statfs cache base directory";
1294 }
1295
1296 if (sysfs(GETFSTYP, statfsbuf.f_fsid[1], name) != 0) {
1297 return "unable to determine filesystem type for cache base dir";
1298 }
1299
1300 if (strcmp(name, "hfs")) {
1301 return "can only use hfs filesystem for cache partition on hpux";
1302 }
1303 }
1304#endif
1305
1306#ifdef AFS_SUN5_ENV
1307 {
1308 FILE *vfstab;
1309 struct mnttab mnt;
1310 struct stat statmnt, statci;
1311
1312 if ((stat(dir, &statci) == 0)
1313 && ((vfstab = fopen(MNTTAB, "r")) != NULL((void *)0))) {
1314 while (getmntent(vfstab, &mnt) == 0) {
1315 if (strcmp(dir, mnt.mnt_mountp) != 0) {
1316 char *cp;
1317 int rdev = 0;
1318
1319 if (cp = hasmntopt(&mnt, "dev="))
1320 rdev =
1321 (int)strtol(cp + strlen("dev="), (char **)NULL((void *)0),
1322 16);
1323
1324 if ((rdev == 0) && (stat(mnt.mnt_mountp, &statmnt) == 0))
1325 rdev = statmnt.st_dev;
1326
1327 if ((rdev == statci.st_dev)
1328 && (hasmntopt(&mnt, "logging") != NULL((void *)0))) {
1329
1330 fclose(vfstab);
1331 return
1332 "mounting a multi-use partition which contains the AFS cache with the\n\"logging\" option may deadlock your system.\n\n";
1333 }
1334 }
1335 }
1336
1337 fclose(vfstab);
1338 }
1339 }
1340#endif
1341
1342 return NULL((void *)0);
1343}
1344
1345int
1346SweepAFSCache(int *vFilesFound)
1347{
1348 static char rn[] = "SweepAFSCache"; /*Routine name */
1349 int maxDir = (cacheFiles + nFilesPerDir - 1) / nFilesPerDir;
1350 int i;
1351
1352 *vFilesFound = 0;
1353
1354 if (cacheFlags & AFSCALL_INIT_MEMCACHE0x1) {
1355 if (afsd_debug)
1356 printf("%s: Memory Cache, no cache sweep done\n", rn);
1357 return 0;
1358 }
1359
1360 if (cache_dir_list == NULL((void *)0)) {
1361 cache_dir_list = (int *)malloc(maxDir * sizeof(*cache_dir_list));
1362 if (cache_dir_list == NULL((void *)0)) {
1363 printf("%s: Malloc Failed!\n", rn);
1364 return (-1);
1365 }
1366 for (i = 0; i < maxDir; i++)
1367 cache_dir_list[i] = -1; /* Does not exist */
1368 }
1369
1370 if (cache_dir_filelist == NULL((void *)0)) {
1371 cache_dir_filelist = (struct afsd_file_list **)
1372 malloc(maxDir * sizeof(*cache_dir_filelist));
1373 if (cache_dir_filelist == NULL((void *)0)) {
1374 printf("%s: Malloc Failed!\n", rn);
1375 return (-1);
1376 }
1377 memset(cache_dir_filelist, 0, maxDir * sizeof(*cache_dir_filelist));
1378 }
1379
1380 if (dir_for_V == NULL((void *)0)) {
1381 dir_for_V = (int *)malloc(cacheFiles * sizeof(*dir_for_V));
1382 if (dir_for_V == NULL((void *)0)) {
1383 printf("%s: Malloc Failed!\n", rn);
1384 return (-1);
1385 }
1386 for (i = 0; i < cacheFiles; i++)
1387 dir_for_V[i] = -1; /* Does not exist */
1388 }
1389
1390 /* Note, setting dirNum to -2 here will cause cachefiles found in
1391 * the toplevel directory to be marked in directory "-2". This
1392 * allows us to differentiate between 'file not seen' (-1) and
1393 * 'file seen in top-level' (-2). Then when we try to move the
1394 * file into a subdirectory, we know it's in the top-level instead
1395 * of some other cache subdir.
1396 */
1397 return doSweepAFSCache(vFilesFound, cacheBaseDir, -2, maxDir);
1398}
1399
1400static int
1401ConfigCell(struct afsconf_cell *aci, void *arock, struct afsconf_dir *adir)
1402{
1403 int isHomeCell;
1404 int i, code;
1405 afs_int32 cellFlags = 0;
1406 afs_int32 hosts[MAXHOSTSPERCELL8];
1407
1408 /* figure out if this is the home cell */
1409 isHomeCell = (strcmp(aci->name, LclCellName) == 0);
1410 if (!isHomeCell) {
1411 cellFlags = 2; /* not home, suid is forbidden */
1412 if (enable_dynroot == 2)
1413 cellFlags |= 8; /* don't display foreign cells until looked up */
1414 }
1415 /* build address list */
1416 for (i = 0; i < MAXHOSTSPERCELL8; i++)
1417 memcpy(&hosts[i], &aci->hostAddr[i].sin_addr, sizeof(afs_int32));
1418
1419 if (aci->linkedCell)
1420 cellFlags |= 4; /* Flag that linkedCell arg exists,
1421 * for upwards compatibility */
1422
1423 /* configure one cell */
1424 code = afsd_call_syscall(AFSOP_ADDCELL229, hosts, /* server addresses */
1425 aci->name, /* cell name */
1426 cellFlags, /* is this the home cell? */
1427 aci->linkedCell); /* Linked cell, if any */
1428 if (code)
1429 printf("Adding cell '%s': error %d\n", aci->name, code);
1430 return 0;
1431}
1432
1433static int
1434ConfigCellAlias(struct afsconf_cellalias *aca,
1435 void *arock, struct afsconf_dir *adir)
1436{
1437 /* push the alias into the kernel */
1438 afsd_call_syscall(AFSOP_ADDCELLALIAS32, aca->aliasName, aca->realName);
1439 return 0;
1440}
1441
1442static void
1443AfsdbLookupHandler(void)
1444{
1445 afs_int32 kernelMsg[64];
1446 char acellName[128];
1447 afs_int32 code;
1448 struct afsconf_cell acellInfo;
1449 int i;
1450
1451 kernelMsg[0] = 0;
1452 kernelMsg[1] = 0;
1453 acellName[0] = '\0';
1454
1455#if defined(AFS_DARWIN_ENV) && !defined(AFS_ARM_DARWIN_ENV)
1456 /* Fork the event handler also. */
1457 code = fork();
1458 if (code == 0) {
1459 afsd_install_events();
1460 return;
1461 } else if (code != -1) {
1462 event_pid = code;
1463 }
1464#endif
1465 while (1) {
1466 /* On some platforms you only get 4 args to an AFS call */
1467 int sizeArg = ((sizeof acellName) << 16) | (sizeof kernelMsg);
1468 code =
1469 afsd_call_syscall(AFSOP_AFSDB_HANDLER30, acellName, kernelMsg, sizeArg);
1470 if (code) { /* Something is wrong? */
1471 sleep(1);
1472 continue;
1473 }
1474
1475 if (*acellName == 1) /* Shutting down */
1476 break;
1477
1478 code = afsconf_GetAfsdbInfo(acellName, 0, &acellInfo);
1479 if (code) {
1480 kernelMsg[0] = 0;
1481 kernelMsg[1] = 0;
1482 } else {
1483 kernelMsg[0] = acellInfo.numServers;
1484 if (acellInfo.timeout)
1485 kernelMsg[1] = acellInfo.timeout - time(0);
1486 else
1487 kernelMsg[1] = 0;
1488 for (i = 0; i < acellInfo.numServers; i++)
1489 kernelMsg[i + 2] = acellInfo.hostAddr[i].sin_addr.s_addr;
1490 strncpy(acellName, acellInfo.name, sizeof(acellName));
1491 acellName[sizeof(acellName) - 1] = '\0';
1492 }
1493 }
1494#ifdef AFS_DARWIN_ENV
1495 kill(event_pid, SIGTERM15);
1496#endif
1497}
1498
1499#ifdef AFS_DARWIN_ENV
1500static void
1501BkgHandler(void)
1502{
1503 afs_int32 code;
1504 struct afs_uspc_param *uspc;
1505 char srcName[256];
1506 char dstName[256];
1507
1508 uspc = (struct afs_uspc_param *)malloc(sizeof(struct afs_uspc_param));
1509 memset(uspc, 0, sizeof(struct afs_uspc_param));
1510 memset(srcName, 0, sizeof(srcName));
1511 memset(dstName, 0, sizeof(dstName));
1512
1513 /* brscount starts at 0 */
1514 uspc->ts = -1;
1515
1516 while (1) {
1517 pid_t child = 0;
1518 int status;
1519 char srcpath[BUFSIZ1024];
1520 char dstpath[BUFSIZ1024];
1521
1522 /* pushing in a buffer this large */
1523 uspc->bufSz = 256;
1524
1525 code = afsd_call_syscall(AFSOP_BKG_HANDLER41, uspc, srcName, dstName);
1526 if (code) { /* Something is wrong? */
1527 if (code == -2) /* shutting down */
1528 break;
1529
1530 sleep(1);
1531 uspc->retval = -1;
1532 continue;
1533 }
1534
1535 switch (uspc->reqtype) {
1536 case AFS_USPC_UMV1:
1537 snprintf(srcpath, BUFSIZ1024, "/afs/.:mount/%d:%d:%d:%d/%s",
1538 uspc->req.umv.sCell, uspc->req.umv.sVolume,
1539 uspc->req.umv.sVnode, uspc->req.umv.sUnique, srcName);
1540 snprintf(dstpath, BUFSIZ1024, "/afs/.:mount/%d:%d:%d:%d/%s",
1541 uspc->req.umv.dCell, uspc->req.umv.dVolume,
1542 uspc->req.umv.dVnode, uspc->req.umv.dUnique, dstName);
1543 if ((child = fork()) == 0) {
1544 /* first child does cp; second, rm. mv would re-enter. */
1545
1546 switch (uspc->req.umv.idtype) {
1547 case IDTYPE_UID0:
1548 if (setuid(uspc->req.umv.id) != 0) {
1549 exit(-1);
1550 }
1551 break;
1552 default:
1553 exit(-1);
1554 break; /* notreached */
1555 }
1556 execl("/bin/cp", "(afsd EXDEV helper)", "-PRp", "--", srcpath,
1557 dstpath, (char *) NULL((void *)0));
1558 }
1559 if (child == (pid_t) -1) {
1560 uspc->retval = -1;
1561 continue;
1562 }
1563
1564 if (waitpid(child, &status, 0) == -1)
1565 uspc->retval = EIO5;
1566 else if (WIFEXITED(status)(((status) & 0177) == 0) != 0 && WEXITSTATUS(status)((status) >> 8) == 0) {
1567 if ((child = fork()) == 0) {
1568 switch (uspc->req.umv.idtype) {
1569 case IDTYPE_UID0:
1570 if (setuid(uspc->req.umv.id) != 0) {
1571 exit(-1);
1572 }
1573 break;
1574 default:
1575 exit(-1);
1576 break; /* notreached */
1577 }
1578 execl("/bin/rm", "(afsd EXDEV helper)", "-rf", "--",
1579 srcpath, (char *) NULL((void *)0));
1580 }
1581 if (child == (pid_t) -1) {
1582 uspc->retval = -1;
1583 continue;
1584 }
1585 if (waitpid(child, &status, 0) == -1)
1586 uspc->retval = EIO5;
1587 else if (WIFEXITED(status)(((status) & 0177) == 0) != 0) {
1588 /* rm exit status */
1589 uspc->retval = WEXITSTATUS(status)((status) >> 8);
1590 } else {
1591 /* rm signal status */
1592 uspc->retval = -(WTERMSIG(status)(((status) & 0177)));
1593 }
1594 } else {
1595 /* error from cp: exit or signal status */
1596 uspc->retval = (WIFEXITED(status)(((status) & 0177) == 0) != 0) ?
1597 WEXITSTATUS(status)((status) >> 8) : -(WTERMSIG(status)(((status) & 0177)));
1598 }
1599 memset(srcName, 0, sizeof(srcName));
1600 memset(dstName, 0, sizeof(dstName));
1601 break;
1602
1603 default:
1604 /* unknown req type */
1605 uspc->retval = -1;
1606 break;
1607 }
1608 }
1609}
1610#endif
1611
1612static void *
1613afsdb_thread(void *rock)
1614{
1615 /* Since the AFSDB lookup handler runs as a user process,
1616 * need to drop the controlling TTY, etc.
1617 */
1618 if (afsd_daemon(0, 0) == -1) {
1619 printf("Error starting AFSDB lookup handler: %s\n",
1620 strerror(errno(* __error())));
1621 exit(1);
1622 }
1623 AfsdbLookupHandler();
1624 return NULL((void *)0);
1625}
1626
1627static void *
1628daemon_thread(void *rock)
1629{
1630#ifdef AFS_DARWIN80_ENV
1631 /* Since the background daemon runs as a user process,
1632 * need to drop the controlling TTY, etc.
1633 */
1634 if (afsd_daemon(0, 0) == -1) {
1635 printf("Error starting background daemon: %s\n",
1636 strerror(errno(* __error())));
1637 exit(1);
1638 }
1639 BkgHandler();
1640#elif defined(AFS_AIX32_ENV)
1641 afsd_call_syscall(AFSOP_START_BKG2, 0);
1642#else
1643 afsd_call_syscall(AFSOP_START_BKG2);
1644#endif
1645 return NULL((void *)0);
1646}
1647
1648#ifndef UKERNEL
1649static void *
1650rmtsysd_thread(void *rock)
1651{
1652 rmtsysd();
1653 return NULL((void *)0);
1654}
1655#endif /* !UKERNEL */
1656
1657int
1658mainproc(struct cmd_syndesc *as, void *arock)
1659{
1660 afs_int32 code; /*Result of fork() */
1661#ifdef AFS_SUN5_ENV
1662 struct stat st;
1663#endif
1664#ifdef AFS_SGI65_ENV
1665 struct sched_param sp;
1666#endif
1667
1668#ifdef AFS_SGI_VNODE_GLUE
1669 if (afs_init_kernel_config(-1) < 0) {
1670 printf("Can't determine NUMA configuration, not starting AFS.\n");
1671 exit(1);
1672 }
1673#endif
1674
1675 /* call atoi on the appropriate parsed results */
1676 if (as->parms[0].items) {
1
Taking false branch
1677 /* -blocks */
1678 cacheBlocks = atoi(as->parms[0].items->data);
1679 sawCacheBlocks = 1;
1680 }
1681 if (as->parms[1].items) {
2
Taking false branch
1682 /* -files */
1683 cacheFiles = atoi(as->parms[1].items->data);
1684 filesSet = 1; /* set when spec'd on cmd line */
1685 }
1686 if (as->parms[2].items) {
3
Taking false branch
1687 /* -rootvol */
1688 strcpy(rootVolume, as->parms[2].items->data);
1689 rootVolSet = 1;
1690 }
1691 if (as->parms[3].items) {
4
Taking false branch
1692 /* -stat */
1693 cacheStatEntries = atoi(as->parms[3].items->data);
1694 sawCacheStatEntries = 1;
1695 }
1696 if (as->parms[4].items) {
5
Taking false branch
1697 /* -memcache */
1698 cacheBaseDir[0] = '\0';
1699 sawCacheBaseDir = 1;
1700 cacheFlags |= AFSCALL_INIT_MEMCACHE0x1;
1701 }
1702 if (as->parms[5].items) {
6
Taking false branch
1703 /* -cachedir */
1704 strcpy(cacheBaseDir, as->parms[5].items->data);
1705 sawCacheBaseDir = 1;
1706 }
1707 if (as->parms[6].items) {
7
Taking false branch
1708 /* -mountdir */
1709 strcpy(afsd_cacheMountDir, as->parms[6].items->data);
1710 sawCacheMountDir = 1;
1711 }
1712 if (as->parms[7].items) {
8
Taking false branch
1713 /* -daemons */
1714 nDaemons = atoi(as->parms[7].items->data);
1715 }
1716 if (as->parms[8].items) {
9
Taking false branch
1717 /* -nosettime */
1718 cacheSetTime = 0;
1719 }
1720 if (as->parms[9].items) {
10
Taking false branch
1721 /* -verbose */
1722 afsd_verbose = 1;
1723 }
1724 if (as->parms[10].items) {
11
Taking false branch
1725 /* -rmtsys */
1726 afsd_rmtsys = 1;
1727#ifdef UKERNEL
1728 printf("-rmtsys not supported for UKERNEL\n");
1729 return -1;
1730#endif
1731 }
1732 if (as->parms[11].items) {
12
Taking false branch
1733 /* -debug */
1734 afsd_debug = 1;
1735 afsd_verbose = 1;
1736 }
1737 if (as->parms[12].items) {
13
Taking false branch
1738 /* -chunksize */
1739 chunkSize = atoi(as->parms[12].items->data);
1740 if (chunkSize < 0 || chunkSize > 30) {
1741 printf
1742 ("afsd:invalid chunk size (not in range 0-30), using default\n");
1743 chunkSize = 0;
1744 }
1745 }
1746 if (as->parms[13].items) {
14
Taking false branch
1747 /* -dcache */
1748 dCacheSize = atoi(as->parms[13].items->data);
1749 sawDCacheSize = 1;
1750 }
1751 if (as->parms[14].items) {
15
Taking false branch
1752 /* -volumes */
1753 vCacheSize = atoi(as->parms[14].items->data);
1754 }
1755 if (as->parms[15].items) {
16
Taking false branch
1756 /* -biods */
1757#ifndef AFS_AIX32_ENV
1758 printf
1759 ("afsd: [-biods] currently only enabled for aix3.x VM supported systems\n");
1760#else
1761 nBiods = atoi(as->parms[15].items->data);
1762 sawBiod = 1;
1763#endif
1764 }
1765 if (as->parms[16].items) {
17
Taking false branch
1766 /* -prealloc */
1767 preallocs = atoi(as->parms[16].items->data);
1768 }
1769 strcpy(confDir, AFSDIR_CLIENT_ETC_DIRPATHgetDirPath(AFSDIR_CLIENT_ETC_DIRPATH_ID));
1770 if (as->parms[17].items) {
18
Taking false branch
1771 /* -confdir */
1772 strcpy(confDir, as->parms[17].items->data);
1773 }
1774 sprintf(fullpn_CacheInfo, "%s/%s", confDir, CACHEINFOFILE"cacheinfo");
1775 if (as->parms[18].items) {
19
Taking false branch
1776 /* -logfile */
1777 printf("afsd: Ignoring obsolete -logfile flag\n");
1778 }
1779 if (as->parms[19].items) {
20
Taking false branch
1780 /* -waitclose */
1781 afsd_CloseSynch = 1;
1782 }
1783 if (as->parms[20].items) {
21
Taking false branch
1784 /* -shutdown */
1785 afs_shutdown = 1;
1786 /*
1787 * Cold shutdown is the default
1788 */
1789 printf("afsd: Shutting down all afs processes and afs state\n");
1790 code = afsd_call_syscall(AFSOP_SHUTDOWN201, 1);
1791 if (code) {
1792 printf("afsd: AFS still mounted; Not shutting down\n");
1793 exit(1);
1794 }
1795 exit(0);
1796 }
1797 if (as->parms[21].items) {
22
Taking false branch
1798 /* -enable_peer_stats */
1799 enable_peer_stats = 1;
1800 }
1801 if (as->parms[22].items) {
23
Taking false branch
1802 /* -enable_process_stats */
1803 enable_process_stats = 1;
1804 }
1805 if (as->parms[23].items) {
24
Taking false branch
1806 /* -mem_alloc_sleep */
1807 printf("afsd: -mem_alloc_sleep is deprecated -- ignored\n");
1808 }
1809 if (as->parms[24].items) {
25
Taking false branch
1810 /* -afsdb */
1811 enable_afsdb = 1;
1812 }
1813 if (as->parms[25].items) {
26
Taking false branch
1814 /* -files_per_subdir */
1815 int res = atoi(as->parms[25].items->data);
1816 if (res < 10 || res > (1 << 30)) {
1817 printf
1818 ("afsd:invalid number of files per subdir, \"%s\". Ignored\n",
1819 as->parms[25].items->data);
1820 } else {
1821 nFilesPerDir = res;
1822 }
1823 }
1824 if (as->parms[26].items) {
27
Taking false branch
1825 /* -dynroot */
1826 enable_dynroot = 1;
1827 }
1828 if (as->parms[27].items) {
28
Taking false branch
1829 /* -fakestat */
1830 enable_fakestat = 2;
1831 }
1832 if (as->parms[28].items) {
29
Taking false branch
1833 /* -fakestat-all */
1834 enable_fakestat = 1;
1835 }
1836 if (as->parms[29].items) {
30
Taking false branch
1837 /* -nomount */
1838 enable_nomount = 1;
1839 }
1840 if (as->parms[30].items) {
31
Taking false branch
1841 /* -backuptree */
1842 enable_backuptree = 1;
1843 }
1844 if (as->parms[31].items) {
32
Taking false branch
1845 /* -rxbind */
1846 enable_rxbind = 1;
1847 }
1848 if (as->parms[32].items) {
33
Taking false branch
1849 /* -settime */
1850 cacheSetTime = 1;
1851 }
1852
1853 /* set rx_extraPackets */
1854 if (as->parms[33].items) {
34
Taking false branch
1855 /* -rxpck */
1856 int rxpck = atoi(as->parms[33].items->data);
1857 printf("afsd: set rxpck = %d\n", rxpck);
1858 code = afsd_call_syscall(AFSOP_SET_RXPCK38, rxpck);
1859 if (code) {
1860 printf("afsd: failed to set rxpck\n");
1861 exit(1);
1862 }
1863 }
1864 if (as->parms[34].items) {
35
Taking true branch
1865 char *c;
1866 if (!as->parms[34].items->data ||
36
Taking false branch
1867 ((c = strchr(as->parms[34].items->data, '/')) == NULL((void *)0)))
1868 printf
1869 ("ignoring splitcache (specify as RW/RO percentages: 60/40)\n");
1870 else {
1871 ropct = atoi((char *)c + 1);
1872 *c = '\0';
1873 rwpct = atoi((char *)as->parms[30].items->data);
37
Access to field 'data' results in a dereference of a null pointer (loaded from field 'items')
1874 if ((rwpct != 0) && (ropct != 0) && (ropct + rwpct == 100)) {
1875 /* -splitcache */
1876 enable_splitcache = 1;
1877 }
1878 }
1879 }
1880 if (as->parms[35].items) {
1881#ifdef AFS_MAXVCOUNT_ENV
1882 /* -disable-dynamic-vcaches */
1883 afsd_dynamic_vcaches = 0;
1884#else
1885 printf("afsd: Error toggling flag, dynamically allocated vcaches not supported on your platform\n");
1886 exit(1);
1887#endif
1888 }
1889#ifdef AFS_MAXVCOUNT_ENV
1890 else {
1891 /* -dynamic-vcaches */
1892 afsd_dynamic_vcaches = 1;
1893 }
1894
1895 if (afsd_verbose)
1896 printf("afsd: %s dynamically allocated vcaches\n", ( afsd_dynamic_vcaches ? "enabling" : "disabling" ));
1897#endif
1898
1899 /* set -rxmaxmtu */
1900 if (as->parms[36].items) {
1901 /* -rxmaxmtu */
1902 rxmaxmtu = atoi(as->parms[36].items->data);
1903 }
1904 if (as->parms[37].items) {
1905 /* -dynroot-sparse */
1906 enable_dynroot = 2;
1907 }
1908 if (as->parms[38].items) {
1909 /* -rxmaxfrags */
1910 rxmaxfrags = atoi(as->parms[38].items->data);
1911 }
1912 return 0;
1913}
1914
1915int
1916afsd_run(void)
1917{
1918 static char rn[] = "afsd"; /*Name of this routine */
1919 struct afsconf_dir *cdir; /* config dir */
1920 int lookupResult; /*Result of GetLocalCellName() */
1921 int i;
1922 afs_int32 code; /*Result of fork() */
1923 char *fsTypeMsg = NULL((void *)0);
1924 int cacheIteration; /*How many times through cache verification */
1925 int vFilesFound; /*How many data cache files were found in sweep */
1926 int currVFile; /*Current AFS cache file number passed in */
1927
1928 /*
1929 * Pull out all the configuration info for the workstation's AFS cache and
1930 * the cellular community we're willing to let our users see.
1931 */
1932 cdir = afsconf_Open(confDir);
1933 if (!cdir) {
1934 printf("afsd: some file missing or bad in %s\n", confDir);
1935 exit(1);
1936 }
1937
1938 lookupResult =
1939 afsconf_GetLocalCell(cdir, LclCellName, sizeof(LclCellName));
1940 if (lookupResult) {
1941 printf("%s: Can't get my home cell name! [Error is %d]\n", rn,
1942 lookupResult);
1943 } else {
1944 if (afsd_verbose)
1945 printf("%s: My home cell is '%s'\n", rn, LclCellName);
1946 }
1947
1948 /* parse cacheinfo file if this is a diskcache */
1949 if (ParseCacheInfoFile()) {
1950 exit(1);
1951 }
1952
1953 if (!enable_nomount) {
1954 if (afsd_check_mount(rn, afsd_cacheMountDir)) {
1955 return -1;
1956 }
1957 }
1958
1959 /* do some random computations in memcache case to get things to work
1960 * reasonably no matter which parameters you set.
1961 */
1962 if (cacheFlags & AFSCALL_INIT_MEMCACHE0x1) {
1963 /* memory cache: size described either as blocks or dcache entries, but
1964 * not both.
1965 */
1966 if (filesSet) {
1967 fprintf(stderr__stderrp, "%s: -files ignored with -memcache\n", rn);
1968 }
1969 if (sawDCacheSize) {
1970 if (chunkSize == 0) {
1971 chunkSize = 13; /* 8k default chunksize for memcache */
1972 }
1973 if (sawCacheBlocks) {
1974 printf
1975 ("%s: can't set cache blocks and dcache size simultaneously when diskless.\n",
1976 rn);
1977 exit(1);
1978 }
1979 /* compute the cache size based on # of chunks times the chunk size */
1980 i = (1 << chunkSize); /* bytes per chunk */
1981 cacheBlocks = i * dCacheSize;
1982 sawCacheBlocks = 1; /* so that ParseCacheInfoFile doesn't overwrite */
1983 } else {
1984 if (chunkSize == 0) {
1985 /* Try to autotune the memcache chunksize based on size
1986 * of memcache. This is done on the assumption that approx
1987 * 1024 chunks is suitable, it's a balance between enough
1988 * chunks to be useful and ramping up nicely when using larger
1989 * memcache to improve bulk read/write performance
1990 */
1991 for (i = 14;
1992 i <= 21 && (1 << i) / 1024 < (cacheBlocks / 1024); i++);
1993 chunkSize = i - 1;
1994 }
1995 /* compute the dcache size from overall cache size and chunk size */
1996 if (chunkSize > 10) {
1997 dCacheSize = (cacheBlocks >> (chunkSize - 10));
1998 } else if (chunkSize < 10) {
1999 dCacheSize = (cacheBlocks << (10 - chunkSize));
2000 } else {
2001 dCacheSize = cacheBlocks;
2002 }
2003 /* don't have to set sawDCacheSize here since it isn't overwritten
2004 * by ParseCacheInfoFile.
2005 */
2006 }
2007 if (afsd_verbose)
2008 printf("%s: chunkSize autotuned to %d\n", rn, chunkSize);
2009
2010 /* kernel computes # of dcache entries as min of cacheFiles and
2011 * dCacheSize, so we now make them equal.
2012 */
2013 cacheFiles = dCacheSize;
2014 } else {
2015 /* Disk cache:
2016 * Compute the number of cache files based on cache size,
2017 * but only if -files isn't given on the command line.
2018 * Don't let # files be so small as to prevent full utilization
2019 * of the cache unless user has explicitly asked for it.
2020 */
2021 if (chunkSize == 0) {
2022 /* Set chunksize to 256kB - 1MB depending on cache size */
2023 if (cacheBlocks < 500000) {
2024 chunkSize = 18;
2025 } else if (cacheBlocks < 1000000) {
2026 chunkSize = 19;
2027 } else {
2028 chunkSize = 20;
2029 }
2030 }
2031 if (!filesSet) {
2032 cacheFiles = cacheBlocks / 32; /* Assume 32k avg filesize */
2033
2034 cacheFiles = max(cacheFiles, 1000)((cacheFiles) < (1000) ? (1000) : (cacheFiles));
2035
2036 /* Always allow more files than chunks. Presume average V-file
2037 * is ~67% of a chunk... (another guess, perhaps Honeyman will
2038 * have a grad student write a paper). i is KILOBYTES.
2039 */
2040 i = 1 << (chunkSize < 10 ? 0 : chunkSize - 10);
2041 cacheFiles = max(cacheFiles, 1.5 * (cacheBlocks / i))((cacheFiles) < (1.5 * (cacheBlocks / i)) ? (1.5 * (cacheBlocks
/ i)) : (cacheFiles))
;
2042
2043 /* never permit more files than blocks, while leaving space for
2044 * VolumeInfo and CacheItems files. VolumeInfo is usually 20K,
2045 * CacheItems is 50 Bytes / file (== 1K/20)
2046 */
2047#define CACHEITMSZ(cacheFiles / 20) (cacheFiles / 20)
2048#define VOLINFOSZ50 50 /* 40kB has been seen, be conservative */
2049#define CELLINFOSZ4 4 /* Assuming disk block size is 4k ... */
2050#define INFOSZ(50 +4 +(cacheFiles / 20)) (VOLINFOSZ50+CELLINFOSZ4+CACHEITMSZ(cacheFiles / 20))
2051
2052 /* Sanity check: If the obtained number of disk cache files
2053 * is larger than the number of available (4k) disk blocks, we're
2054 * doing something wrong. Fail hard so we can fix the bug instead
2055 * of silently hiding it like before */
2056
2057 if (cacheFiles > (cacheBlocks - INFOSZ(50 +4 +(cacheFiles / 20))) / 4) {
2058 fprintf(stderr__stderrp,
2059 "%s: ASSERT: cacheFiles %d diskblocks %d\n",
2060 rn, cacheFiles, (cacheBlocks - INFOSZ(50 +4 +(cacheFiles / 20))) / 4);
2061 exit(1);
2062 }
2063 if (cacheFiles < 100)
2064 fprintf(stderr__stderrp, "%s: WARNING: cache probably too small!\n",
2065 rn);
2066
2067 if (afsd_verbose)
2068 printf("%s: cacheFiles autotuned to %d\n", rn, cacheFiles);
2069 }
2070#if 0
2071 /* This actually needs to
2072 1) use powers of 2
2073 2) not second-guess when a chunksize comes from the command line
2074 3) be less, um, small. 2^2??
2075 */
2076 /* Sanity check chunkSize */
2077 i = max(cacheBlocks / 1000, cacheBlocks / cacheFiles)((cacheBlocks / 1000) < (cacheBlocks / cacheFiles) ? (cacheBlocks
/ cacheFiles) : (cacheBlocks / 1000))
;
2078 chunkSize = min(chunkSize, i)(((chunkSize) < (i)) ? (chunkSize) : (i));
2079 chunkSize = max(chunkSize, 2)((chunkSize) < (2) ? (2) : (chunkSize));
2080 if (afsd_verbose)
2081 printf("%s: chunkSize autotuned to %d\n", rn, chunkSize);
2082#endif
2083
2084 if (!sawDCacheSize) {
2085 dCacheSize = cacheFiles / 2;
2086 if (dCacheSize > 10000) {
2087 dCacheSize = 10000;
2088 }
2089 if (dCacheSize < 2000) {
2090 dCacheSize = 2000;
2091 }
2092 if (afsd_verbose)
2093 printf("%s: dCacheSize autotuned to %d\n", rn, dCacheSize);
2094 }
2095 }
2096 if (!sawCacheStatEntries) {
2097 if (chunkSize <= 13) {
2098 cacheStatEntries = dCacheSize / 4;
2099 } else if (chunkSize >= 16) {
2100 cacheStatEntries = dCacheSize * 1.5;
2101 } else {
2102 cacheStatEntries = dCacheSize;
2103 }
2104 if (afsd_verbose)
2105 printf("%s: cacheStatEntries autotuned to %d\n", rn,
2106 cacheStatEntries);
2107 }
2108
2109#if !defined(AFS_CACHE_VNODE_PATH) && !defined(AFS_LINUX26_ENV)
2110 /*
2111 * Create and zero the inode table for the desired cache files.
2112 */
2113 inode_for_V = (AFSD_INO_Tafs_uint32 *) malloc(cacheFiles * sizeof(AFSD_INO_Tafs_uint32));
2114 if (inode_for_V == (AFSD_INO_Tafs_uint32 *) 0) {
2115 printf
2116 ("%s: malloc() failed for cache file inode table with %d entries.\n",
2117 rn, cacheFiles);
2118 exit(1);
2119 }
2120 memset(inode_for_V, '\0', (cacheFiles * sizeof(AFSD_INO_Tafs_uint32)));
2121 if (afsd_debug)
2122 printf("%s: %d inode_for_V entries at 0x%x, %lu bytes\n", rn,
2123 cacheFiles, inode_for_V, (cacheFiles * sizeof(AFSD_INO_Tafs_uint32)));
2124#endif
2125
2126 /*
2127 * Set up all the pathnames we'll need for later.
2128 */
2129 sprintf(fullpn_DCacheFile, "%s/%s", cacheBaseDir, DCACHEFILE"CacheItems");
2130 sprintf(fullpn_VolInfoFile, "%s/%s", cacheBaseDir, VOLINFOFILE"VolumeItems");
2131 sprintf(fullpn_CellInfoFile, "%s/%s", cacheBaseDir, CELLINFOFILE"CellItems");
2132 sprintf(fullpn_VFile, "%s/", cacheBaseDir);
2133 vFilePtr = fullpn_VFile + strlen(fullpn_VFile);
2134
2135 if (!(cacheFlags & AFSCALL_INIT_MEMCACHE0x1)
2136 && (fsTypeMsg = CheckCacheBaseDir(cacheBaseDir))) {
2137#ifdef AFS_SUN5_ENV
2138 printf("%s: WARNING: Cache dir check failed (%s)\n", rn, fsTypeMsg);
2139#else
2140 printf("%s: ERROR: Cache dir check failed (%s)\n", rn, fsTypeMsg);
2141 exit(1);
2142#endif
2143 }
2144
2145 /*
2146 * Set up all the kernel processes needed for AFS.
2147 */
2148#ifdef mac2
2149 setpgrp(getpid(), 0);
2150#endif /* mac2 */
2151
2152 /*
2153 * Set the primary cell name.
2154 */
2155 afsd_call_syscall(AFSOP_SET_THISCELL35, LclCellName);
2156
2157 /* Initialize RX daemons and services */
2158
2159 /* initialize the rx random number generator from user space */
2160 {
2161 /* parse multihomed address files */
2162 afs_uint32 addrbuf[MAXIPADDRS1024], maskbuf[MAXIPADDRS1024],
2163 mtubuf[MAXIPADDRS1024];
2164 char reason[1024];
2165 code =
2166 parseNetFiles(addrbuf, maskbuf, mtubuf, MAXIPADDRS1024, reason,
2167 AFSDIR_CLIENT_NETINFO_FILEPATHgetDirPath(AFSDIR_CLIENT_NETINFO_FILEPATH_ID),
2168 AFSDIR_CLIENT_NETRESTRICT_FILEPATHgetDirPath(AFSDIR_CLIENT_NETRESTRICT_FILEPATH_ID));
2169 if (code > 0) {
2170 if (enable_rxbind)
2171 code = code | 0x80000000;
2172 afsd_call_syscall(AFSOP_ADVISEADDR17, code, addrbuf, maskbuf, mtubuf);
2173 } else
2174 printf("ADVISEADDR: Error in specifying interface addresses:%s\n",
2175 reason);
2176 }
2177
2178 /* Set realtime priority for most threads to same as for biod's. */
2179 afsd_set_afsd_rtpri();
2180
2181#ifdef AFS_SGI53_ENV
2182#ifdef AFS_SGI61_ENV
2183 set_staticaddrs();
2184#else /* AFS_SGI61_ENV */
2185 code = get_nfsstaticaddr();
2186 if (code)
2187 afsd_call_syscall(AFSOP_NFSSTATICADDR, code);
2188#endif /* AFS_SGI61_ENV */
2189#endif /* AFS_SGI_53_ENV */
2190
2191 /* Start listener, then callback listener. Lastly, start rx event daemon.
2192 * Change in ordering is so that Linux port has socket fd in listener
2193 * process.
2194 * preallocs are passed for both listener and callback server. Only
2195 * the one which actually does the initialization uses them though.
2196 */
2197 if (preallocs < cacheStatEntries + 50)
2198 preallocs = cacheStatEntries + 50;
2199#ifdef RXK_LISTENER_ENV1
2200 if (afsd_verbose)
2201 printf("%s: Forking rx listener daemon.\n", rn);
2202# ifdef AFS_SUN510_ENV
2203 fork_rx_syscall_wait(rn, AFSOP_RXLISTENER_DAEMON48, preallocs,
2204 enable_peer_stats, enable_process_stats);
2205# else /* !AFS_SUN510_ENV */
2206 fork_rx_syscall(rn, AFSOP_RXLISTENER_DAEMON48, preallocs, enable_peer_stats,
2207 enable_process_stats);
2208# endif /* !AFS_SUN510_ENV */
2209#endif
2210 if (afsd_verbose)
2211 printf("%s: Forking rx callback listener.\n", rn);
2212#ifndef RXK_LISTENER_ENV1
2213 fork_rx_syscall(rn, AFSOP_START_RXCALLBACK0, preallocs, enable_peer_stats,
2214 enable_process_stats);
2215#else
2216 fork_syscall(rn, AFSOP_START_RXCALLBACK0, preallocs);
2217#endif
2218#if defined(AFS_SUN5_ENV) || defined(RXK_LISTENER_ENV1) || defined(RXK_UPCALL_ENV)
2219 if (afsd_verbose)
2220 printf("%s: Forking rxevent daemon.\n", rn);
2221 fork_rx_syscall(rn, AFSOP_RXEVENT_DAEMON19);
2222#endif
2223
2224 if (enable_afsdb) {
2225 if (afsd_verbose)
2226 printf("%s: Forking AFSDB lookup handler.\n", rn);
2227 afsd_fork(0, afsdb_thread, NULL((void *)0));
2228 }
2229 code = afsd_call_syscall(AFSOP_BASIC_INIT36, 1);
2230 if (code) {
2231 printf("%s: Error %d in basic initialization.\n", rn, code);
2232 exit(1);
2233 }
2234
2235 /*
2236 * Tell the kernel some basic information about the workstation's cache.
2237 */
2238 if (afsd_verbose)
2239 printf
2240 ("%s: Calling AFSOP_CACHEINIT: %d stat cache entries, %d optimum cache files, %d blocks in the cache, flags = 0x%x, dcache entries %d\n",
2241 rn, cacheStatEntries, cacheFiles, cacheBlocks, cacheFlags,
2242 dCacheSize);
2243 memset(&cparams, '\0', sizeof(cparams));
2244 cparams.cacheScaches = cacheStatEntries;
2245 cparams.cacheFiles = cacheFiles;
2246 cparams.cacheBlocks = cacheBlocks;
2247 cparams.cacheDcaches = dCacheSize;
2248 cparams.cacheVolumes = vCacheSize;
2249 cparams.chunkSize = chunkSize;
2250 cparams.setTimeFlag = cacheSetTime;
2251 cparams.memCacheFlag = cacheFlags;
2252 cparams.dynamic_vcaches = afsd_dynamic_vcaches;
2253 afsd_call_syscall(AFSOP_CACHEINIT6, &cparams);
2254
2255 /* do it before we init the cache inodes */
2256 if (enable_splitcache) {
2257 afsd_call_syscall(AFSOP_BUCKETPCT39, 1, rwpct);
2258 afsd_call_syscall(AFSOP_BUCKETPCT39, 2, ropct);
2259 }
2260
2261 if (afsd_CloseSynch)
2262 afsd_call_syscall(AFSOP_CLOSEWAIT18);
2263
2264 /*
2265 * Sweep the workstation AFS cache directory, remembering the inodes of
2266 * valid files and deleting extraneous files. Keep sweeping until we
2267 * have the right number of data cache files or we've swept too many
2268 * times.
2269 *
2270 * This also creates files in the cache directory like VolumeItems and
2271 * CellItems, and thus must be ran before those are sent to the kernel.
2272 */
2273 if (afsd_verbose)
2274 printf("%s: Sweeping workstation's AFS cache directory.\n", rn);
2275 cacheIteration = 0;
2276 /* Memory-cache based system doesn't need any of this */
2277 if (!(cacheFlags & AFSCALL_INIT_MEMCACHE0x1)) {
2278 do {
2279 cacheIteration++;
2280 if (SweepAFSCache(&vFilesFound)) {
2281 printf("%s: Error on sweep %d of workstation AFS cache \
2282 directory.\n", rn, cacheIteration);
2283 exit(1);
2284 }
2285 if (afsd_verbose)
2286 printf
2287 ("%s: %d out of %d data cache files found in sweep %d.\n",
2288 rn, vFilesFound, cacheFiles, cacheIteration);
2289 } while ((vFilesFound < cacheFiles)
2290 && (cacheIteration < MAX_CACHE_LOOPS4));
2291 } else if (afsd_verbose)
2292 printf("%s: Using memory cache, not swept\n", rn);
2293
2294 /*
2295 * Pass the kernel the name of the workstation cache file holding the
2296 * dcache entries.
2297 */
2298 if (afsd_debug)
2299 printf("%s: Calling AFSOP_CACHEINFO: dcache file is '%s'\n", rn,
2300 fullpn_DCacheFile);
2301 /* once again, meaningless for a memory-based cache. */
2302 if (!(cacheFlags & AFSCALL_INIT_MEMCACHE0x1))
2303 afsd_call_syscall(AFSOP_CACHEINFO7, fullpn_DCacheFile);
2304
2305 /*
2306 * Pass the kernel the name of the workstation cache file holding the
2307 * cell information.
2308 */
2309 if (!(cacheFlags & AFSCALL_INIT_MEMCACHE0x1)) {
2310 if (afsd_debug)
2311 printf("%s: Calling AFSOP_CELLINFO: cell info file is '%s'\n", rn,
2312 fullpn_CellInfoFile);
2313 afsd_call_syscall(AFSOP_CELLINFO34, fullpn_CellInfoFile);
2314 }
2315
2316 if (rxmaxfrags) {
2317 if (afsd_verbose)
2318 printf("%s: Setting rxmaxfrags in kernel = %d\n", rn, rxmaxfrags);
2319 code = afsd_call_syscall(AFSOP_SET_RXMAXFRAGS43, rxmaxfrags);
2320 if (code)
2321 printf("%s: Error seting rxmaxfrags\n", rn);
2322 }
2323
2324 if (rxmaxmtu) {
2325 if (afsd_verbose)
2326 printf("%s: Setting rxmaxmtu in kernel = %d\n", rn, rxmaxmtu);
2327 code = afsd_call_syscall(AFSOP_SET_RXMAXMTU40, rxmaxmtu);
2328 if (code)
2329 printf("%s: Error seting rxmaxmtu\n", rn);
2330 }
2331
2332 if (enable_dynroot) {
2333 if (afsd_verbose)
2334 printf("%s: Enabling dynroot support in kernel%s.\n", rn,
2335 (enable_dynroot==2)?", not showing cells.":"");
2336 code = afsd_call_syscall(AFSOP_SET_DYNROOT31, 1);
2337 if (code)
2338 printf("%s: Error enabling dynroot support.\n", rn);
2339 }
2340
2341 if (enable_fakestat) {
2342 if (afsd_verbose)
2343 printf("%s: Enabling fakestat support in kernel%s.\n", rn,
2344 (enable_fakestat==2)?" for all mountpoints."
2345 :" for crosscell mountpoints");
2346 code = afsd_call_syscall(AFSOP_SET_FAKESTAT33, enable_fakestat);
2347 if (code)
2348 printf("%s: Error enabling fakestat support.\n", rn);
2349 }
2350
2351 if (enable_backuptree) {
2352 if (afsd_verbose)
2353 printf("%s: Enabling backup tree support in kernel.\n", rn);
2354 code = afsd_call_syscall(AFSOP_SET_BACKUPTREE37, enable_backuptree);
2355 if (code)
2356 printf("%s: Error enabling backup tree support.\n", rn);
2357 }
2358
2359 /*
2360 * Tell the kernel about each cell in the configuration.
2361 */
2362 afsconf_CellApply(cdir, ConfigCell, NULL((void *)0));
2363 afsconf_CellAliasApply(cdir, ConfigCellAlias, NULL((void *)0));
2364
2365 /* Initialize AFS daemon threads. */
2366 if (afsd_verbose)
2367 printf("%s: Forking AFS daemon.\n", rn);
2368 fork_syscall(rn, AFSOP_START_AFS1);
2369
2370 if (afsd_verbose)
2371 printf("%s: Forking Check Server Daemon.\n", rn);
2372 fork_syscall(rn, AFSOP_START_CS4);
2373
2374 if (afsd_verbose)
2375 printf("%s: Forking %d background daemons.\n", rn, nDaemons);
2376#if defined(AFS_SGI_ENV) && defined(AFS_SGI_SHORTSTACK)
2377 /* Add one because for sgi we always "steal" the first daemon for a
2378 * different task if we only have a 4K stack.
2379 */
2380 nDaemons++;
2381#endif
2382 for (i = 0; i < nDaemons; i++) {
2383 afsd_fork(0, daemon_thread, NULL((void *)0));
2384 }
2385#ifdef AFS_AIX32_ENV
2386 if (!sawBiod)
2387 nBiods = nDaemons * 2;
2388 if (nBiods < 5)
2389 nBiods = 5;
2390 for (i = 0; i < nBiods; i++) {
2391 fork_syscall(rn, AFSOP_START_BKG2, nBiods);
2392 }
2393#endif
2394
2395 /*
2396 * If the root volume has been explicitly set, tell the kernel.
2397 */
2398 if (rootVolSet) {
2399 if (afsd_verbose)
2400 printf("%s: Calling AFSOP_ROOTVOLUME with '%s'\n", rn,
2401 rootVolume);
2402 afsd_call_syscall(AFSOP_ROOTVOLUME12, rootVolume);
2403 }
2404
2405 /*
2406 * Pass the kernel the name of the workstation cache file holding the
2407 * volume information.
2408 */
2409 if (afsd_debug)
2410 printf("%s: Calling AFSOP_VOLUMEINFO: volume info file is '%s'\n", rn,
2411 fullpn_VolInfoFile);
2412 /* once again, meaningless for a memory-based cache. */
2413 if (!(cacheFlags & AFSCALL_INIT_MEMCACHE0x1))
2414 afsd_call_syscall(AFSOP_VOLUMEINFO8, fullpn_VolInfoFile);
2415
2416 /*
2417 * Give the kernel the names of the AFS files cached on the workstation's
2418 * disk.
2419 */
2420 if (afsd_debug)
2421 printf
2422 ("%s: Calling AFSOP_CACHEFILE for each of the %d files in '%s'\n",
2423 rn, cacheFiles, cacheBaseDir);
2424 if (!(cacheFlags & AFSCALL_INIT_MEMCACHE0x1)) {
2425 /* ... and again ... */
2426 int nocachefile = 0;
2427 for (currVFile = 0; currVFile < cacheFiles; currVFile++) {
2428 if (!nocachefile) {
2429 sprintf(fullpn_VFile, "%s/D%d/V%d", cacheBaseDir, dir_for_V[currVFile], currVFile);
2430 code = afsd_call_syscall(AFSOP_CACHEFILE9, fullpn_VFile);
2431 if (code) {
2432 if (currVFile == 0) {
2433 if (afsd_debug)
2434 printf
2435 ("%s: Calling AFSOP_CACHEINODE for each of the %d files in '%s'\n",
2436 rn, cacheFiles, cacheBaseDir);
2437 nocachefile = 1;
2438 } else {
2439 printf
2440 ("%s: Error calling AFSOP_CACHEFILE for '%s'\n",
2441 rn, fullpn_VFile);
2442 exit(1);
2443 }
2444 } else {
2445 continue;
2446 }
2447 /* fall through to setup-by-inode */
2448 }
2449#ifdef AFS_SGI62_ENV
2450 afsd_call_syscall(AFSOP_CACHEINODE10,
2451 (afs_uint32) (inode_for_V[currVFile] >> 32),
2452 (afs_uint32) (inode_for_V[currVFile] & 0xffffffff));
2453#elif !(defined(AFS_LINUX26_ENV) || defined(AFS_CACHE_VNODE_PATH))
2454 afsd_call_syscall(AFSOP_CACHEINODE10, inode_for_V[currVFile]);
2455#else
2456 printf
2457 ("%s: Error calling AFSOP_CACHEINODE: not configured\n",
2458 rn);
2459 exit(1);
2460#endif
2461 }
2462 }
2463 /*end for */
2464 /*
2465 * All the necessary info has been passed into the kernel to run an AFS
2466 * system. Give the kernel our go-ahead.
2467 */
2468 if (afsd_debug)
2469 printf("%s: Calling AFSOP_GO with cacheSetTime = %d\n", rn,
2470 cacheSetTime);
2471 afsd_call_syscall(AFSOP_GO100, cacheSetTime);
2472
2473 /*
2474 * At this point, we have finished passing the kernel all the info
2475 * it needs to set up the AFS. Mount the AFS root.
2476 */
2477 printf("%s: All AFS daemons started.\n", rn);
2478
2479 if (afsd_verbose)
2480 printf("%s: Forking trunc-cache daemon.\n", rn);
2481 fork_syscall(rn, AFSOP_START_TRUNCDAEMON3);
2482
2483 if (!enable_nomount) {
2484 afsd_mount_afs(rn, afsd_cacheMountDir);
2485 }
2486
2487#ifndef UKERNEL
2488 if (afsd_rmtsys) {
2489 if (afsd_verbose)
2490 printf("%s: Forking 'rmtsys' daemon.\n", rn);
2491 afsd_fork(0, rmtsysd_thread, NULL((void *)0));
2492 }
2493#endif /* !UKERNEL */
2494 /*
2495 * Exit successfully.
2496 */
2497 return 0;
2498}
2499
2500#include "AFS_component_version_number.c"
2501
2502void
2503afsd_init(void)
2504{
2505 struct cmd_syndesc *ts;
2506
2507 ts = cmd_CreateSyntax(NULL((void *)0), mainproc, NULL((void *)0), "start AFS");
2508
2509 /* 0 - 10 */
2510 cmd_AddParm(ts, "-blocks", CMD_SINGLE2, CMD_OPTIONAL1,
2511 "1024 byte blocks in cache");
2512 cmd_AddParm(ts, "-files", CMD_SINGLE2, CMD_OPTIONAL1, "files in cache");
2513 cmd_AddParm(ts, "-rootvol", CMD_SINGLE2, CMD_OPTIONAL1,
2514 "name of AFS root volume");
2515 cmd_AddParm(ts, "-stat", CMD_SINGLE2, CMD_OPTIONAL1,
2516 "number of stat entries");
2517 cmd_AddParm(ts, "-memcache", CMD_FLAG1, CMD_OPTIONAL1, "run diskless");
2518 cmd_AddParm(ts, "-cachedir", CMD_SINGLE2, CMD_OPTIONAL1, "cache directory");
2519 cmd_AddParm(ts, "-mountdir", CMD_SINGLE2, CMD_OPTIONAL1, "mount location");
2520 cmd_AddParm(ts, "-daemons", CMD_SINGLE2, CMD_OPTIONAL1,
2521 "number of daemons to use");
2522 cmd_AddParm(ts, "-nosettime", CMD_FLAG1, CMD_OPTIONAL1,
2523 "don't set the time");
2524 cmd_AddParm(ts, "-verbose", CMD_FLAG1, CMD_OPTIONAL1,
2525 "display lots of information");
2526 cmd_AddParm(ts, "-rmtsys", CMD_FLAG1, CMD_OPTIONAL1,
2527 "start NFS rmtsysd program");
2528
2529 /* 11 - 20 */
2530 cmd_AddParm(ts, "-debug", CMD_FLAG1, CMD_OPTIONAL1, "display debug info");
2531 cmd_AddParm(ts, "-chunksize", CMD_SINGLE2, CMD_OPTIONAL1,
2532 "log(2) of chunk size");
2533 cmd_AddParm(ts, "-dcache", CMD_SINGLE2, CMD_OPTIONAL1,
2534 "number of dcache entries");
2535 cmd_AddParm(ts, "-volumes", CMD_SINGLE2, CMD_OPTIONAL1,
2536 "number of volume entries");
2537 cmd_AddParm(ts, "-biods", CMD_SINGLE2, CMD_OPTIONAL1,
2538 "number of bkg I/O daemons (aix vm)");
2539 cmd_AddParm(ts, "-prealloc", CMD_SINGLE2, CMD_OPTIONAL1,
2540 "number of 'small' preallocated blocks");
2541 cmd_AddParm(ts, "-confdir", CMD_SINGLE2, CMD_OPTIONAL1,
2542 "configuration directory");
2543 cmd_AddParm(ts, "-logfile", CMD_SINGLE2, CMD_OPTIONAL1,
2544 "Place to keep the CM log");
2545 cmd_AddParm(ts, "-waitclose", CMD_FLAG1, CMD_OPTIONAL1,
2546 "make close calls synchronous");
2547 cmd_AddParm(ts, "-shutdown", CMD_FLAG1, CMD_OPTIONAL1,
2548 "Shutdown all afs state");
2549 /* 21 - 30 */
2550 cmd_AddParm(ts, "-enable_peer_stats", CMD_FLAG1, CMD_OPTIONAL1 | CMD_HIDE4,
2551 "Collect rpc statistics by peer");
2552 cmd_AddParm(ts, "-enable_process_stats", CMD_FLAG1,
2553 CMD_OPTIONAL1 | CMD_HIDE4,
2554 "Collect rpc statistics for this process");
2555 cmd_AddParm(ts, "-mem_alloc_sleep", CMD_FLAG1, (CMD_OPTIONAL1 | CMD_HIDE4),
2556 "Allow sleeps when allocating memory cache");
2557 cmd_AddParm(ts, "-afsdb", CMD_FLAG1, (CMD_OPTIONAL1),
2558 "Enable AFSDB support");
2559 cmd_AddParm(ts, "-files_per_subdir", CMD_SINGLE2, CMD_OPTIONAL1,
2560 "log(2) of the number of cache files per cache subdirectory");
2561 cmd_AddParm(ts, "-dynroot", CMD_FLAG1, CMD_OPTIONAL1,
2562 "Enable dynroot support");
2563 cmd_AddParm(ts, "-fakestat", CMD_FLAG1, CMD_OPTIONAL1,
2564 "Enable fakestat support for cross-cell mounts");
2565 cmd_AddParm(ts, "-fakestat-all", CMD_FLAG1, CMD_OPTIONAL1,
2566 "Enable fakestat support for all mounts");
2567 cmd_AddParm(ts, "-nomount", CMD_FLAG1, CMD_OPTIONAL1, "Do not mount AFS");
2568 cmd_AddParm(ts, "-backuptree", CMD_FLAG1, CMD_OPTIONAL1,
2569 "Prefer backup volumes for mointpoints in backup volumes");
2570 /* 31 - 40 */
2571 cmd_AddParm(ts, "-rxbind", CMD_FLAG1, CMD_OPTIONAL1,
2572 "Bind the Rx socket (one interface only)");
2573 cmd_AddParm(ts, "-settime", CMD_FLAG1, CMD_OPTIONAL1, "set the time");
2574 cmd_AddParm(ts, "-rxpck", CMD_SINGLE2, CMD_OPTIONAL1,
2575 "set rx_extraPackets to this value");
2576 cmd_AddParm(ts, "-splitcache", CMD_SINGLE2, CMD_OPTIONAL1,
2577 "Percentage RW versus RO in cache (specify as 60/40)");
2578 cmd_AddParm(ts, "-disable-dynamic-vcaches", CMD_FLAG1, CMD_OPTIONAL1,
2579 "disable stat/vcache cache growing as needed");
2580 cmd_AddParm(ts, "-rxmaxmtu", CMD_SINGLE2, CMD_OPTIONAL1, "set rx max MTU to use");
2581 cmd_AddParm(ts, "-dynroot-sparse", CMD_FLAG1, CMD_OPTIONAL1,
2582 "Enable dynroot support with minimal cell list");
2583 cmd_AddParm(ts, "-rxmaxfrags", CMD_SINGLE2, CMD_OPTIONAL1,
2584 "Set the maximum number of UDP fragments Rx should send/receive"
2585 " per Rx packet");
2586}
2587
2588int
2589afsd_parse(int argc, char **argv)
2590{
2591 return cmd_Dispatch(argc, argv);
2592}
2593
2594#ifdef AFS_SGI53_ENV
2595#ifdef AFS_SGI61_ENV
2596/* The dwarf structures are searched to find entry points of static functions
2597 * and the addresses of static variables. The file name as well as the
2598 * sybmol name is reaquired.
2599 */
2600
2601/* Contains list of names to find in given file. */
2602typedef struct {
2603 char *name; /* Name of variable or function. */
2604 afs_hyper_t addr; /* Address of function, undefined if not found. */
2605 Dwarf_Half type; /* DW_AT_location for vars, DW_AT_lowpc for func's */
2606 char found; /* set if found. */
2607} staticAddrList;
2608
2609typedef struct {
2610 char *file; /* Name of file containing vars or funcs */
2611 staticAddrList *addrList; /* List of vars and/or funcs. */
2612 int nAddrs; /* # of addrList's */
2613 int found; /* set if we've found this file already. */
2614} staticNameList;
2615
2616/* routines used to find addresses in /unix */
2617#if defined(AFS_SGI62_ENV) && !defined(AFS_SGI65_ENV)
2618void findMDebugStaticAddresses(staticNameList *, int, int);
2619#endif
2620void findDwarfStaticAddresses(staticNameList *, int);
2621void findElfAddresses(Dwarf_Debug, Dwarf_Die, staticNameList *);
2622void getElfAddress(Dwarf_Debug, Dwarf_Die, staticAddrList *);
2623
2624#if defined(AFS_SGI62_ENV) && !defined(AFS_SGI65_ENV)
2625#define AFS_N_FILELISTS 2
2626#define AFS_SYMS_NEEDED 3
2627#else /* AFS_SGI62_ENV */
2628#define AFS_N_FILELISTS 1
2629#endif /* AFS_SGI62_ENV */
2630
2631
2632
2633void
2634set_staticaddrs(void)
2635{
2636 staticNameList fileList[AFS_N_FILELISTS];
2637
2638 fileList[0].addrList =
2639 (staticAddrList *) calloc(1, sizeof(staticAddrList));
2640 if (!fileList[0].addrList) {
2641 printf("set_staticaddrs: Can't calloc fileList[0].addrList\n");
2642 return;
2643 }
2644 fileList[0].file = "nfs_server.c";
2645 fileList[0].found = 0;
2646 fileList[0].nAddrs = 1;
2647 fileList[0].addrList[0].name = "rfsdisptab_v2";
2648 fileList[0].addrList[0].type = DW_AT_location;
2649 fileList[0].addrList[0].found = 0;
2650
2651#if defined(AFS_SGI62_ENV) && !defined(AFS_SGI65_ENV)
2652 fileList[1].addrList =
2653 (staticAddrList *) calloc(2, sizeof(staticAddrList));
2654 if (!fileList[1].addrList) {
2655 printf("set_staticaddrs: Can't malloc fileList[1].addrList\n");
2656 return;
2657 }
2658 fileList[1].file = "uipc_socket.c";
2659 fileList[1].found = 0;
2660 fileList[1].nAddrs = 2;
2661 fileList[1].addrList[0].name = "sblock";
2662 fileList[1].addrList[0].type = DW_AT_low_pc;
2663 fileList[1].addrList[0].found = 0;
2664 fileList[1].addrList[1].name = "sbunlock";
2665 fileList[1].addrList[1].type = DW_AT_low_pc;
2666 fileList[1].addrList[1].found = 0;
2667
2668 if (64 != sysconf(_SC_KERN_POINTERS))
2669 findMDebugStaticAddresses(fileList, AFS_N_FILELISTS, AFS_SYMS_NEEDED);
2670 else
2671#endif /* AFS_SGI62_ENV */
2672 findDwarfStaticAddresses(fileList, AFS_N_FILELISTS);
2673
2674 if (fileList[0].addrList[0].found) {
2675 afsd_call_syscall(AFSOP_NFSSTATICADDR2, fileList[0].addrList[0].addr.high,
2676 fileList[0].addrList[0].addr.low);
2677 } else {
2678 if (afsd_verbose)
2679 printf("NFS V2 is not present in the kernel.\n");
2680 }
2681 free(fileList[0].addrList);
2682#if defined(AFS_SGI62_ENV) && !defined(AFS_SGI65_ENV)
2683 if (fileList[1].addrList[0].found && fileList[1].addrList[1].found) {
2684 afsd_call_syscall(AFSOP_SBLOCKSTATICADDR2,
2685 fileList[1].addrList[0].addr.high,
2686 fileList[1].addrList[0].addr.low,
2687 fileList[1].addrList[1].addr.high,
2688 fileList[1].addrList[1].addr.low);
2689 } else {
2690 if (!fileList[1].addrList[0].found)
2691 printf("Can't find %s in kernel. Exiting.\n",
2692 fileList[1].addrList[0].name);
2693 if (!fileList[1].addrList[0].found)
2694 printf("Can't find %s in kernel. Exiting.\n",
2695 fileList[1].addrList[1].name);
2696 exit(1);
2697 }
2698 free(fileList[1].addrList);
2699#endif /* AFS_SGI62_ENV */
2700}
2701
2702
2703/* Find addresses for static variables and functions. */
2704void
2705findDwarfStaticAddresses(staticNameList * nameList, int nLists)
2706{
2707 int fd;
2708 int i;
2709 int found = 0;
2710 int code;
2711 char *s;
2712 char *hname = (char *)0;
2713 Dwarf_Unsigned dwarf_access = O_RDONLY0x0000;
2714 Dwarf_Debug dwarf_debug;
2715 Dwarf_Error dwarf_error;
2716 Dwarf_Unsigned dwarf_cu_header_length;
2717 Dwarf_Unsigned dwarf_abbrev_offset;
2718 Dwarf_Half dwarf_address_size;
2719 Dwarf_Unsigned next_cu_header;
2720 Dwarf_Die dwarf_die;
2721 Dwarf_Die dwarf_next_die;
2722 Dwarf_Die dwarf_child_die;
2723
2724 if (elf_version(EV_CURRENT) == EV_NONE) {
2725 printf("findDwarfStaticAddresses: Bad elf version.\n");
2726 return;
2727 }
2728
2729 if ((fd = open("/unix", O_RDONLY0x0000, 0)) < 0) {
2730 printf("findDwarfStaticAddresses: Failed to open /unix.\n");
2731 return;
2732 }
2733 code =
2734 dwarf_init(fd, dwarf_access, NULL((void *)0), NULL((void *)0), &dwarf_debug, &dwarf_error);
2735 if (code != DW_DLV_OK) {
2736 /* Nope hope for the elves and dwarves, try intermediate code. */
2737 close(fd);
2738 return;
2739 }
2740
2741 found = 0;
2742 while (1) {
2743 /* Run through the headers until we find ones for files we've
2744 * specified in nameList.
2745 */
2746 code =
2747 dwarf_next_cu_header(dwarf_debug, &dwarf_cu_header_length, NULL((void *)0),
2748 &dwarf_abbrev_offset, &dwarf_address_size,
2749 &next_cu_header, &dwarf_error);
2750 if (code == DW_DLV_NO_ENTRY) {
2751 break;
2752 } else if (code == DW_DLV_ERROR) {
2753 printf("findDwarfStaticAddresses: Error reading headers: %s\n",
2754 dwarf_errmsg(dwarf_error));
2755 break;
2756 }
2757
2758 code = dwarf_siblingof(dwarf_debug, NULL((void *)0), &dwarf_die, &dwarf_error);
2759 if (code != DW_DLV_OK) {
2760 printf("findDwarfStaticAddresses: Can't get first die. %s\n",
2761 (code == DW_DLV_ERROR) ? dwarf_errmsg(dwarf_error) : "");
2762 break;
2763 }
2764
2765 /* This is the header, test the name. */
2766 code = dwarf_diename(dwarf_die, &hname, &dwarf_error);
2767 if (code == DW_DLV_OK) {
2768 s = strrchr(hname, '/');
2769 for (i = 0; i < nLists; i++) {
2770 if (s && !strcmp(s + 1, nameList[i].file)) {
2771 findElfAddresses(dwarf_debug, dwarf_die, &nameList[i]);
2772 found++;
2773 break;
2774 }
2775 }
2776 } else {
2777 printf
2778 ("findDwarfStaticAddresses: Can't get name of current header. %s\n",
2779 (code == DW_DLV_ERROR) ? dwarf_errmsg(dwarf_error) : "");
2780 break;
2781 }
2782 dwarf_dealloc(dwarf_debug, hname, DW_DLA_STRING);
2783 hname = (char *)0;
2784 if (found >= nLists) { /* we're done */
2785 break;
2786 }
2787 }
2788
2789 /* Frees up all allocated space. */
2790 (void)dwarf_finish(dwarf_debug, &dwarf_error);
2791 close(fd);
2792}
2793
2794void
2795findElfAddresses(Dwarf_Debug dwarf_debug, Dwarf_Die dwarf_die,
2796 staticNameList * nameList)
2797{
2798 int i;
2799 Dwarf_Error dwarf_error;
2800 Dwarf_Die dwarf_next_die;
2801 Dwarf_Die dwarf_child_die;
2802 Dwarf_Attribute dwarf_return_attr;
2803 char *vname = (char *)0;
2804 int found = 0;
2805 int code;
2806
2807 /* Drop into this die to find names in addrList. */
2808 code = dwarf_child(dwarf_die, &dwarf_child_die, &dwarf_error);
2809 if (code != DW_DLV_OK) {
2810 printf("findElfAddresses: Can't get child die. %s\n",
2811 (code == DW_DLV_ERROR) ? dwarf_errmsg(dwarf_error) : "");
2812 return;
2813 }
2814
2815 /* Try to find names in each sibling. */
2816 dwarf_next_die = (Dwarf_Die) 0;
2817 do {
2818 code = dwarf_diename(dwarf_child_die, &vname, &dwarf_error);
2819 /* It's possible that some siblings don't have names. */
2820 if (code == DW_DLV_OK) {
2821 for (i = 0; i < nameList->nAddrs; i++) {
2822 if (!nameList->addrList[i].found) {
2823 if (!strcmp(vname, nameList->addrList[i].name)) {
2824 getElfAddress(dwarf_debug, dwarf_child_die,
2825 &(nameList->addrList[i]));
2826 found++;
2827 break;
2828 }
2829 }
2830 }
2831 }
2832 if (dwarf_next_die)
2833 dwarf_dealloc(dwarf_debug, dwarf_next_die, DW_DLA_DIE);
2834
2835 if (found >= nameList->nAddrs) { /* we're done. */
2836 break;
2837 }
2838
2839 dwarf_next_die = dwarf_child_die;
2840 code =
2841 dwarf_siblingof(dwarf_debug, dwarf_next_die, &dwarf_child_die,
2842 &dwarf_error);
2843
2844 } while (code == DW_DLV_OK);
2845}
2846
2847/* Get address out of current die. */
2848void
2849getElfAddress(Dwarf_Debug dwarf_debug, Dwarf_Die dwarf_child_die,
2850 staticAddrList * addrList)
2851{
2852 int i;
2853 Dwarf_Error dwarf_error;
2854 Dwarf_Attribute dwarf_return_attr;
2855 Dwarf_Bool dwarf_return_bool;
2856 Dwarf_Locdesc *llbuf = NULL((void *)0);
2857 Dwarf_Signed listlen;
2858 off64_t addr = (off64_t) 0;
2859 int code;
2860
2861 code =
2862 dwarf_hasattr(dwarf_child_die, addrList->type, &dwarf_return_bool,
2863 &dwarf_error);
2864 if ((code != DW_DLV_OK) || (!dwarf_return_bool)) {
2865 printf("getElfAddress: no address given for %s. %s\n", addrList->name,
2866 (code == DW_DLV_ERROR) ? dwarf_errmsg(dwarf_error) : "");
2867 return;
2868 }
2869 code =
2870 dwarf_attr(dwarf_child_die, addrList->type, &dwarf_return_attr,
2871 &dwarf_error);
2872 if (code != DW_DLV_OK) {
2873 printf("getElfAddress: Can't get attribute. %s\n",
2874 (code == DW_DLV_ERROR) ? dwarf_errmsg(dwarf_error) : "");
2875 return;
2876 }
2877
2878 switch (addrList->type) {
2879 case DW_AT_location:
2880 code =
2881 dwarf_loclist(dwarf_return_attr, &llbuf, &listlen, &dwarf_error);
2882 if (code != DW_DLV_OK) {
2883 printf("getElfAddress: Can't get location for %s. %s\n",
2884 addrList->name,
2885 (code == DW_DLV_ERROR) ? dwarf_errmsg(dwarf_error) : "");
2886 return;
2887 }
2888 if ((listlen != 1) || (llbuf[0].ld_cents != 1)) {
2889 printf("getElfAddress: %s has more than one address.\n",
2890 addrList->name);
2891 return;
2892 }
2893 addr = llbuf[0].ld_s[0].lr_number;
2894 break;
2895
2896 case DW_AT_low_pc:
2897 code =
2898 dwarf_lowpc(dwarf_child_die, (Dwarf_Addr *) & addr, &dwarf_error);
2899 if (code != DW_DLV_OK) {
2900 printf("getElfAddress: Can't get lowpc for %s. %s\n",
2901 addrList->name,
2902 (code == DW_DLV_ERROR) ? dwarf_errmsg(dwarf_error) : "");
2903 return;
2904 }
2905 break;
2906
2907 default:
2908 printf("getElfAddress: Bad case %d in switch.\n", addrList->type);
2909 return;
2910 }
2911
2912 addrList->addr.high = (addr >> 32) & 0xffffffff;
2913 addrList->addr.low = addr & 0xffffffff;
2914 addrList->found = 1;
2915}
2916
2917#if defined(AFS_SGI62_ENV) && !defined(AFS_SGI65_ENV)
2918/* Find symbols in the .mdebug section for 32 bit kernels. */
2919/*
2920 * do_mdebug()
2921 * On 32bit platforms, we're still using the ucode compilers to build
2922 * the kernel, so we need to get our static text/data from the .mdebug
2923 * section instead of the .dwarf sections.
2924 */
2925/* SearchNameList searches our bizarre structs for the given string.
2926 * If found, sets the found bit and the address and returns 1.
2927 * Not found returns 0.
2928 */
2929int
2930SearchNameList(char *name, afs_uint32 addr, staticNameList * nameList,
2931 int nLists)
2932{
2933 int i, j;
2934 for (i = 0; i < nLists; i++) {
2935 for (j = 0; j < nameList[i].nAddrs; j++) {
2936 if (nameList[i].addrList[j].found)
2937 continue;
2938 if (!strcmp(name, nameList[i].addrList[j].name)) {
2939 nameList[i].addrList[j].addr.high = 0;
2940 nameList[i].addrList[j].addr.low = addr;
2941 nameList[i].addrList[j].found = 1;
2942 return 1;
2943 }
2944 }
2945 }
2946 return 0;
2947}
2948
2949static void
2950SearchMDebug(Elf_Scn * scnp, Elf32_Shdr * shdrp, staticNameList * nameList,
2951 int nLists, int needed)
2952{
2953 long *buf = (long *)(elf_getdata(scnp, NULL((void *)0))->d_buf);
2954 u_long addr, mdoff = shdrp->sh_offset;
2955 HDRR *hdrp;
2956 SYMR *symbase, *symp, *symend;
2957 FDR *fdrbase, *fdrp;
2958 int i, j;
2959 char *strbase, *str;
2960 int ifd;
2961 int nFound = 0;
2962
2963 /* get header */
2964 addr = (__psunsigned_t) buf;
2965 hdrp = (HDRR *) addr;
2966
2967 /* setup base addresses */
2968 addr = (u_long) buf + (u_long) (hdrp->cbFdOffset - mdoff);
2969 fdrbase = (FDR *) addr;
2970 addr = (u_long) buf + (u_long) (hdrp->cbSymOffset - mdoff);
2971 symbase = (SYMR *) addr;
2972 addr = (u_long) buf + (u_long) (hdrp->cbSsOffset - mdoff);
2973 strbase = (char *)addr;
2974
2975#define KEEPER(a,b) ((a == stStaticProc && b == scText) || \
2976 (a == stStatic && (b == scData || b == scBss || \
2977 b == scSBss || b == scSData)))
2978
2979 for (fdrp = fdrbase; fdrp < &fdrbase[hdrp->ifdMax]; fdrp++) {
2980 str = strbase + fdrp->issBase + fdrp->rss;
2981
2982 /* local symbols for each fd */
2983 for (symp = &symbase[fdrp->isymBase];
2984 symp < &symbase[fdrp->isymBase + fdrp->csym]; symp++) {
2985 if (KEEPER(symp->st, symp->sc)) {
2986 if (symp->value == 0)
2987 continue;
2988
2989 str = strbase + fdrp->issBase + symp->iss;
2990 /* Look for AFS symbols of interest */
2991 if (SearchNameList(str, symp->value, nameList, nLists)) {
2992 nFound++;
2993 if (nFound >= needed)
2994 return;
2995 }
2996 }
2997 }
2998 }
2999}
3000
3001/*
3002 * returns section with the name of scn_name, & puts its header in shdr64 or
3003 * shdr32 based on elf's file type
3004 *
3005 */
3006Elf_Scn *
3007findMDebugSection(Elf * elf, char *scn_name)
3008{
3009 Elf64_Ehdr *ehdr64;
3010 Elf32_Ehdr *ehdr32;
3011 Elf_Scn *scn = NULL((void *)0);
3012 Elf64_Shdr *shdr64;
3013 Elf32_Shdr *shdr32;
3014
3015 if ((ehdr32 = elf32_getehdr(elf)) == NULL((void *)0))
3016 return (NULL((void *)0));
3017 do {
3018 if ((scn = elf_nextscn(elf, scn)) == NULL((void *)0))
3019 break;
3020 if ((shdr32 = elf32_getshdr(scn)) == NULL((void *)0))
3021 return (NULL((void *)0));
3022 } while (strcmp
3023 (scn_name,
3024 elf_strptr(elf, ehdr32->e_shstrndx, shdr32->sh_name)));
3025
3026 return (scn);
3027}
3028
3029
3030void
3031findMDebugStaticAddresses(staticNameList * nameList, int nLists, int needed)
3032{
3033 int fd;
3034 Elf *elf;
3035 Elf_Scn *mdebug_scn;
3036 Elf32_Shdr *mdebug_shdr;
3037 char *names;
3038
3039 if ((fd = open("/unix", O_RDONLY0x0000)) == -1) {
3040 printf("findMDebugStaticAddresses: Failed to open /unix.\n");
3041 return;
3042 }
3043
3044 (void)elf_version(EV_CURRENT);
3045 if ((elf = elf_begin(fd, ELF_C_READ, NULL((void *)0))) == NULL((void *)0)) {
3046 printf
3047 ("findMDebugStaticAddresses: /unix doesn't seem to be an elf file\n");
3048 close(fd);
3049 return;
3050 }
3051 mdebug_scn = findMDebugSection(elf, ".mdebug");
3052 if (!mdebug_scn) {
3053 printf("findMDebugStaticAddresses: Can't find .mdebug section.\n");
3054 goto find_end;
3055 }
3056 mdebug_shdr = elf32_getshdr(mdebug_scn);
3057 if (!mdebug_shdr) {
3058 printf("findMDebugStaticAddresses: Can't find .mdebug header.\n");
3059 goto find_end;
3060 }
3061
3062 (void)SearchMDebug(mdebug_scn, mdebug_shdr, nameList, nLists, needed);
3063
3064 find_end:
3065 elf_end(elf);
3066 close(fd);
3067}
3068#endif /* AFS_SGI62_ENV */
3069
3070#else /* AFS_SGI61_ENV */
3071#include <nlist.h>
3072struct nlist nlunix[] = {
3073 {"rfsdisptab_v2"},
3074 {0},
3075};
3076
3077get_nfsstaticaddr()
3078{
3079 int i, j, kmem, count;
3080
3081 if ((kmem = open("/dev/kmem", O_RDONLY0x0000)) < 0) {
3082 printf("Warning: can't open /dev/kmem\n");
3083 return 0;
3084 }
3085 if ((j = nlist("/unix", nlunix)) < 0) {
3086 printf("Warning: can't nlist /unix\n");
3087 return 0;
3088 }
3089 i = nlunix[0].n_value;
3090 if (lseek(kmem, i, L_SET0 /*0 */ ) != i) {
3091 printf("Warning: can't lseek to %x\n", i);
3092 return 0;
3093 }
3094 if ((j = read(kmem, &count, sizeof count)) != sizeof count) {
3095 printf("WARNING: kmem read at %x failed\n", i);
3096 return 0;
3097 }
3098 return i;
3099}
3100#endif /* AFS_SGI61_ENV */
3101#endif /* AFS_SGI53_ENV */
3102
3103struct afsd_syscall_args {
3104 long syscall;
3105 long param1;
3106 long param2;
3107 long param3;
3108 long param4;
3109 long param5;
3110 const char *rn;
3111 int rxpri;
3112};
3113
3114/**
3115 * entry point for calling a syscall from another proc/thread.
3116 *
3117 * @param[in] rock a struct afsd_syscall_args* specifying what syscall to call
3118 *
3119 * @return unused
3120 * @retval NULL always
3121 */
3122static void *
3123call_syscall_thread(void *rock)
3124{
3125 struct afsd_syscall_args *args = rock;
3126 int code;
3127
3128 if (args->rxpri) {
3129 afsd_set_rx_rtpri();
3130 }
3131
3132 code = afsd_call_syscall(args->syscall, args->param1, args->param2,
3133 args->param3, args->param4, args->param5);
3134 if (code && args->syscall == AFSOP_START_CS4) {
3135 printf("%s: No check server daemon in client.\n", args->rn);
3136 }
3137
3138 free(args);
3139
3140 return NULL((void *)0);
3141}
3142
3143/**
3144 * common code for calling a syscall in another proc/thread.
3145 *
3146 * @param[in] rx 1 if this is a thread for RX stuff, 0 otherwise
3147 * @param[in] wait 1 if we should wait for the new proc/thread to finish, 0 to
3148 * let it run in the background
3149 * @param[in] rn the name of the running program
3150 * @param[in] syscall syscall to run
3151 */
3152static void
3153fork_syscall_impl(int rx, int wait, const char *rn, long syscall, long param1,
3154 long param2, long param3, long param4, long param5)
3155{
3156 struct afsd_syscall_args *args;
3157
3158 args = malloc(sizeof(*args));
3159
3160 args->syscall = syscall;
3161 args->param1 = param1;
3162 args->param2 = param2;
3163 args->param3 = param3;
3164 args->param4 = param4;
3165 args->param5 = param5;
3166 args->rxpri = rx;
3167 args->rn = rn;
3168
3169 afsd_fork(wait, call_syscall_thread, args);
3170}
3171
3172/**
3173 * call a syscall in another process or thread.
3174 */
3175static void
3176fork_syscall(const char *rn, long syscall, long param1, long param2,
3177 long param3, long param4, long param5)
3178{
3179 fork_syscall_impl(0, 0, rn, syscall, param1, param2, param3, param4, param5);
3180}
3181
3182/**
3183 * call a syscall in another process or thread, and give it RX priority.
3184 */
3185static void
3186fork_rx_syscall(const char *rn, long syscall, long param1, long param2,
3187 long param3, long param4, long param5)
3188{
3189 fork_syscall_impl(1, 0, rn, syscall, param1, param2, param3, param4, param5);
3190}
3191
3192#if defined(AFS_SUN510_ENV) && defined(RXK_LISTENER_ENV1)
3193/**
3194 * call a syscall in another process or thread, give it RX priority, and wait
3195 * for it to finish before returning.
3196 */
3197static void
3198fork_rx_syscall_wait(const char *rn, long syscall, long param1, long param2,
3199 long param3, long param4, long param5)
3200{
3201 fork_syscall_impl(1, 1, rn, syscall, param1, param2, param3, param4, param5);
3202}
3203#endif /* AFS_SUN510_ENV && RXK_LISTENER_ENV */