2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
11 * Information Technology Center
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.
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:
24 * -rootvol The name of the root volume to use.
25 * -stat The number of stat cache entries.
26 * -hosts [OBSOLETE] List of servers to check for volume location info FOR THE
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 [IGNORED] Keep checking the time to avoid drift.
34 * -rxmaxmtu Set the max mtu to help with VPN issues.
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)
45 * -chunksize [n] 2^n is the chunksize to be used. 0 is default.
46 * -dcache The number of data cache entries.
47 * -volumes The number of volume entries.
48 * -biods Number of bkg I/O daemons (AIX3.1 only)
49 * -prealloc Number of preallocated "small" memory blocks
50 * -logfile [IGNORED] Place where to put the logfile (default in
52 * -waitclose make close calls always synchronous (slows em down, tho)
53 * -files_per_subdir [n] number of files per cache subdir. (def=2048)
54 * -shutdown Shutdown afs daemons
55 * -enable_peer_stats Collect RPC statistics by peer.
56 * -enable_process_stats Collect RPC statistics for this process.
57 * -mem_alloc_sleep [IGNORED] Sleep when allocating memory.
58 * -afsdb Enable AFSDB support.
59 * -dynroot Enable dynroot support.
60 * -dynroot-sparse Enable dynroot support with minimal cell list.
61 * -fakestat Enable fake stat() for cross-cell mounts.
62 * -fakestat-all Enable fake stat() for all mounts.
63 * -nomount Do not mount /afs.
64 * -backuptree Prefer backup volumes for mountpoints in backup volumes.
65 * -rxbind Bind the rx socket.
66 * -rxpck Value for rx_extraPackets.
67 * -splitcache RW/RO ratio for cache.
68 * -rxmaxfrags Max number of UDP fragments per rx packet.
69 * -inumcalc inode number calculation method; 0=compat, 1=MD5 digest
70 * -volume-ttl vldb cache timeout in seconds
71 *---------------------------------------------------------------------------*/
73 #include <afsconfig.h>
74 #include <afs/param.h>
75 /* darwin dirent.h doesn't give us the prototypes we want if KERNEL is
76 * defined, and roken includes dirent */
77 #if defined(UKERNEL) && defined(AFS_USR_DARWIN_ENV)
89 #include <afs/opr_assert.h>
95 #include <afs/afsutil.h>
99 #include <hcrypto/rand.h>
101 /* darwin dirent.h doesn't give us the prototypes we want if KERNEL is
103 #if defined(UKERNEL) && defined(AFS_USR_DARWIN_ENV)
111 #ifdef HAVE_SYS_FS_TYPES_H
112 #include <sys/fs_types.h>
115 #if defined(HAVE_SYS_MOUNT_H) && !defined(AFS_ARM_DARWIN_ENV)
116 #include <sys/mount.h>
119 #ifdef HAVE_SYS_FCNTL_H
120 #include <sys/fcntl.h>
123 #ifdef HAVE_SYS_MNTTAB_H
124 #include <sys/mnttab.h>
127 #ifdef HAVE_SYS_MNTENT_H
128 #include <sys/mntent.h>
135 #ifdef HAVE_SYS_VFS_H
139 #ifdef HAVE_SYS_FSTYP_H
140 #include <sys/fstyp.h>
145 #include <afs/afs_args.h>
146 #include <afs/cellconfig.h>
147 #include <afs/afssyscalls.h>
148 #include <afs/afsutil.h>
149 #include <afs/sys_prototypes.h>
151 #if defined(AFS_SGI62_ENV) && !defined(AFS_SGI65_ENV)
153 #include <symconst.h>
159 #ifdef AFS_DARWIN_ENV
160 #ifdef AFS_DARWIN80_ENV
161 #include <sys/xattr.h>
163 #include <CoreFoundation/CoreFoundation.h>
165 static int event_pid
;
166 #ifndef AFS_ARM_DARWIN_ENV
167 #define MACOS_EVENT_HANDLING 1
169 #endif /* AFS_DARWIN_ENV */
171 #if AFS_HAVE_STATVFS || defined(HAVE_SYS_STATVFS_H)
172 #include <sys/statvfs.h>
174 #if defined(AFS_SUN_ENV)
177 #ifdef HAVE_SYS_STATFS_H
178 #include <sys/statfs.h>
187 #define CACHEINFOFILE "cacheinfo"
188 #define DCACHEFILE "CacheItems"
189 #define VOLINFOFILE "VolumeItems"
190 #define CELLINFOFILE "CellItems"
192 #define MAXIPADDRS 1024
194 char LclCellName
[64];
196 #define MAX_CACHE_LOOPS 4
200 * Internet address (old style... should be updated). This was pulled out of the old 4.2
201 * version of <netinet/in.h>, since it's still useful.
206 u_char s_b1
, s_b2
, s_b3
, s_b4
;
215 #define mPrintIPAddr(ipaddr) printf("[%d.%d.%d.%d] ", \
216 ((struct in_addr_42 *) &(ipaddr))->S_un.S_un_b.s_b1, \
217 ((struct in_addr_42 *) &(ipaddr))->S_un.S_un_b.s_b2, \
218 ((struct in_addr_42 *) &(ipaddr))->S_un.S_un_b.s_b3, \
219 ((struct in_addr_42 *) &(ipaddr))->S_un.S_un_b.s_b4)
222 * Global configuration variables.
224 static int enable_rxbind
= 0;
225 static int afs_shutdown
= 0;
226 static int cacheBlocks
; /*Num blocks in the cache */
227 static int cacheFiles
; /*Optimal # of files in workstation cache */
228 static int rwpct
= 0;
229 static int ropct
= 0;
230 static int cacheStatEntries
; /*Number of stat cache entries */
231 static char *cacheBaseDir
; /*Where the workstation AFS cache lives */
232 static char *confDir
; /*Where the workstation AFS configuration lives */
233 static char fullpn_DCacheFile
[1024]; /*Full pathname of DCACHEFILE */
234 static char fullpn_VolInfoFile
[1024]; /*Full pathname of VOLINFOFILE */
235 static char fullpn_CellInfoFile
[1024]; /*Full pathanem of CELLINFOFILE */
236 static char fullpn_CacheInfo
[1024]; /*Full pathname of CACHEINFO */
237 static char fullpn_VFile
[1024]; /*Full pathname of data cache files */
238 static char *vFilePtr
; /*Ptr to the number part of above pathname */
239 static int sawCacheMountDir
= 0; /* from cmd line */
240 static int sawCacheBaseDir
= 0;
241 static int sawCacheBlocks
= 0;
242 static int sawDCacheSize
= 0;
244 static int sawBiod
= 0;
246 static int sawCacheStatEntries
= 0;
247 char *afsd_cacheMountDir
;
248 static char *rootVolume
= NULL
;
250 static int createAndTrunc
= O_RDWR
| O_CREAT
| O_TRUNC
; /*Create & truncate on open */
252 static int createAndTrunc
= O_CREAT
| O_TRUNC
; /*Create & truncate on open */
254 static int ownerRWmode
= 0600; /*Read/write OK by owner */
255 static int filesSet
= 0; /*True if number of files explicitly set */
256 static int nFilesPerDir
= 2048; /* # files per cache dir */
257 #if defined(AFS_CACHE_BYPASS)
258 #define AFSD_NDAEMONS 4
260 #define AFSD_NDAEMONS 2
262 static int nDaemons
= AFSD_NDAEMONS
; /* Number of background daemons */
263 static int chunkSize
= 0; /* 2^chunkSize bytes per chunk */
264 static int dCacheSize
; /* # of dcache entries */
265 static int vCacheSize
= 200; /* # of volume cache entries */
266 static int rootVolSet
= 0; /*True if root volume name explicitly set */
267 int addrNum
; /*Cell server address index being printed */
268 static int cacheFlags
= 0; /*Flags to cache manager */
270 static int nBiods
= 5; /* AIX3.1 only */
272 static int preallocs
= 400; /* Def # of allocated memory blocks */
273 static int enable_peer_stats
= 0; /* enable rx stats */
274 static int enable_process_stats
= 0; /* enable rx stats */
275 static int enable_afsdb
= 0; /* enable AFSDB support */
276 static int enable_dynroot
= 0; /* enable dynroot support */
277 static int enable_fakestat
= 0; /* enable fakestat support */
278 static int enable_backuptree
= 0; /* enable backup tree support */
279 static int enable_nomount
= 0; /* do not mount */
280 static int enable_splitcache
= 0;
281 static char *inumcalc
= NULL
; /* inode number calculation method */
282 static int afsd_dynamic_vcaches
= 0; /* Enable dynamic-vcache support */
283 int afsd_verbose
= 0; /*Are we being chatty? */
284 int afsd_debug
= 0; /*Are we printing debugging info? */
285 static int afsd_CloseSynch
= 0; /*Are closes synchronous or not? */
286 static int rxmaxmtu
= 0; /* Are we forcing a limit on the mtu? */
287 static int rxmaxfrags
= 0; /* Are we forcing a limit on frags? */
288 static int volume_ttl
= 0; /* enable vldb cache timeout support */
291 #define AFSD_INO_T ino64_t
293 #define AFSD_INO_T afs_uint32
295 struct afsd_file_list
{
297 struct afsd_file_list
*next
;
299 struct afsd_file_list
**cache_dir_filelist
= NULL
;
300 int *cache_dir_list
= NULL
; /* Array of cache subdirs */
301 int *dir_for_V
= NULL
; /* Array: dir of each cache file.
302 * -1: file does not exist
303 * -2: file exists in top-level
304 * >=0: file exists in Dxxx
306 #if !defined(AFS_CACHE_VNODE_PATH) && !defined(AFS_LINUX26_ENV)
307 AFSD_INO_T
*inode_for_V
; /* Array of inodes for desired
310 int missing_DCacheFile
= 1; /*Is the DCACHEFILE missing? */
311 int missing_VolInfoFile
= 1; /*Is the VOLINFOFILE missing? */
312 int missing_CellInfoFile
= 1; /*Is the CELLINFOFILE missing? */
313 int afsd_rmtsys
= 0; /* Default: don't support rmtsys */
314 struct afs_cacheParams cparams
; /* params passed to cache manager */
316 int PartSizeOverflow(char *path
, int cs
);
318 static int afsd_syscall(int code
, ...);
320 #if defined(AFS_SUN510_ENV) && defined(RXK_LISTENER_ENV)
321 static void fork_rx_syscall_wait(const char *rn
, int syscall
, ...);
323 static void fork_rx_syscall(const char *rn
, int syscall
, ...);
324 static void fork_syscall(const char *rn
, int syscall
, ...);
370 #ifdef MACOS_EVENT_HANDLING
371 #include <SystemConfiguration/SystemConfiguration.h>
372 #include <SystemConfiguration/SCDynamicStore.h>
374 #include <IOKit/pwr_mgt/IOPMLib.h>
375 #include <IOKit/IOMessage.h>
377 static io_connect_t root_port
;
378 static IONotificationPortRef notify
;
379 static io_object_t iterator
;
380 static CFRunLoopSourceRef source
;
383 afsd_sleep_callback(void * refCon
, io_service_t service
,
384 natural_t messageType
, void * messageArgument
)
386 switch (messageType
) {
387 case kIOMessageCanSystemSleep
:
388 /* Idle sleep is about to kick in; can
389 prevent sleep by calling IOCancelPowerChange, otherwise
390 if we don't ack in 30s the system sleeps anyway */
393 IOAllowPowerChange(root_port
, (long)messageArgument
);
396 case kIOMessageSystemWillSleep
:
397 /* The system WILL go to sleep. Ack or suffer delay */
399 IOAllowPowerChange(root_port
, (long)messageArgument
);
402 case kIOMessageSystemWillRestart
:
403 /* The system WILL restart. Ack or suffer delay */
405 IOAllowPowerChange(root_port
, (long)messageArgument
);
408 case kIOMessageSystemWillPowerOn
:
409 case kIOMessageSystemHasPoweredOn
:
410 /* coming back from sleep */
412 IOAllowPowerChange(root_port
, (long)messageArgument
);
416 IOAllowPowerChange(root_port
, (long)messageArgument
);
422 afsd_update_addresses(CFRunLoopTimerRef timer
, void *info
)
424 /* parse multihomed address files */
425 afs_uint32 addrbuf
[MAXIPADDRS
], maskbuf
[MAXIPADDRS
],
430 code
= afsconf_ParseNetFiles(addrbuf
, maskbuf
, mtubuf
, MAXIPADDRS
,
431 reason
, AFSDIR_CLIENT_NETINFO_FILEPATH
,
432 AFSDIR_CLIENT_NETRESTRICT_FILEPATH
);
435 /* Note we're refreshing */
436 code
= code
| 0x40000000;
437 afsd_syscall(AFSOP_ADVISEADDR
, code
, addrbuf
, maskbuf
, mtubuf
);
439 printf("ADVISEADDR: Error in specifying interface addresses:%s\n",
442 /* Since it's likely this means our DNS server changed, reinit now */
447 /* This function is called when the system's ip addresses may have changed. */
449 afsd_ipaddr_callback (SCDynamicStoreRef store
, CFArrayRef changed_keys
, void *info
)
451 CFRunLoopTimerRef timer
;
453 timer
= CFRunLoopTimerCreate (NULL
, CFAbsoluteTimeGetCurrent () + 1.0,
454 0.0, 0, 0, afsd_update_addresses
, NULL
);
455 CFRunLoopAddTimer (CFRunLoopGetCurrent (), timer
,
456 kCFRunLoopDefaultMode
);
461 afsd_event_cleanup(int signo
) {
463 CFRunLoopRemoveSource(CFRunLoopGetCurrent(), source
, kCFRunLoopDefaultMode
);
465 IODeregisterForSystemPower(&iterator
);
466 IOServiceClose(root_port
);
467 IONotificationPortDestroy(notify
);
471 /* Adapted from "Living in a Dynamic TCP/IP Environment" technote. */
473 afsd_install_events(void)
475 SCDynamicStoreContext ctx
= {0};
476 SCDynamicStoreRef store
;
478 root_port
= IORegisterForSystemPower(0,¬ify
,afsd_sleep_callback
,&iterator
);
481 CFRunLoopAddSource(CFRunLoopGetCurrent(),
482 IONotificationPortGetRunLoopSource(notify
),
483 kCFRunLoopDefaultMode
);
487 store
= SCDynamicStoreCreate (NULL
,
488 CFSTR ("AddIPAddressListChangeCallbackSCF"),
489 afsd_ipaddr_callback
, &ctx
);
494 /* Request IPV4 address change notification */
495 keys
[0] = (SCDynamicStoreKeyCreateNetworkServiceEntity
496 (NULL
, kSCDynamicStoreDomainState
,
497 kSCCompAnyRegex
, kSCEntNetIPv4
));
500 /* This should tell us when the hostname(s) change. do we care? */
501 keys
[N
] = SCDynamicStoreKeyCreateHostNames (NULL
);
504 if (keys
[0] != NULL
) {
505 CFArrayRef pattern_array
;
507 pattern_array
= CFArrayCreate (NULL
, keys
, 1,
508 &kCFTypeArrayCallBacks
);
510 if (pattern_array
!= NULL
)
512 SCDynamicStoreSetNotificationKeys (store
, NULL
, pattern_array
);
513 source
= SCDynamicStoreCreateRunLoopSource (NULL
, store
, 0);
515 CFRelease (pattern_array
);
525 if (source
!= NULL
) {
526 CFRunLoopAddSource (CFRunLoopGetCurrent(),
527 source
, kCFRunLoopDefaultMode
);
530 signal(SIGTERM
, afsd_event_cleanup
);
536 /* ParseArgs is now obsolete, being handled by cmd */
538 /*------------------------------------------------------------------------------
542 * Open the file containing the description of the workstation's AFS cache
543 * and pull out its contents. The format of this file is as follows:
545 * cacheMountDir:cacheBaseDir:cacheBlocks
551 * 0 if everything went well,
555 * Nothing interesting.
559 *---------------------------------------------------------------------------*/
562 ParseCacheInfoFile(void)
564 static char rn
[] = "ParseCacheInfoFile"; /*This routine's name */
565 FILE *cachefd
; /*Descriptor for cache info file */
566 int parseResult
; /*Result of our fscanf() */
568 char tCacheBaseDir
[1024], *tbd
, tCacheMountDir
[1024], *tmd
;
571 printf("%s: Opening cache info file '%s'...\n", rn
, fullpn_CacheInfo
);
573 cachefd
= fopen(fullpn_CacheInfo
, "r");
575 printf("%s: Can't read cache info file '%s'\n", rn
, fullpn_CacheInfo
);
580 * Parse the contents of the cache info file. All chars up to the first
581 * colon are the AFS mount directory, all chars to the next colon are the
582 * full path name of the workstation cache directory and all remaining chars
583 * represent the number of blocks in the cache.
585 tCacheMountDir
[0] = tCacheBaseDir
[0] = '\0';
587 fscanf(cachefd
, "%1024[^:]:%1024[^:]:%d", tCacheMountDir
,
588 tCacheBaseDir
, &tCacheBlocks
);
591 * Regardless of how the parse went, we close the cache info file.
595 if (parseResult
== EOF
|| parseResult
< 3) {
596 printf("%s: Format error in cache info file!\n", rn
);
597 if (parseResult
== EOF
)
598 printf("\tEOF encountered before any field parsed.\n");
600 printf("\t%d out of 3 fields successfully parsed.\n",
606 for (tmd
= tCacheMountDir
; *tmd
== '\n' || *tmd
== ' ' || *tmd
== '\t';
608 for (tbd
= tCacheBaseDir
; *tbd
== '\n' || *tbd
== ' ' || *tbd
== '\t';
610 /* now copy in the fields not explicitly overridden by cmd args */
611 if (!sawCacheMountDir
)
612 afsd_cacheMountDir
= strdup(tmd
);
613 if (!sawCacheBaseDir
)
614 cacheBaseDir
= strdup(tbd
);
616 cacheBlocks
= tCacheBlocks
;
619 printf("%s: Cache info file successfully parsed:\n", rn
);
621 ("\tcacheMountDir: '%s'\n\tcacheBaseDir: '%s'\n\tcacheBlocks: %d\n",
622 tmd
, tbd
, tCacheBlocks
);
624 if (!(cacheFlags
& AFSCALL_INIT_MEMCACHE
)) {
625 return (PartSizeOverflow(tbd
, cacheBlocks
));
632 * All failures to open the partition are ignored. Also if the cache dir
633 * isn't a mounted partition it's also ignored since we can't guarantee
634 * what will be stored afterwards. Too many if's. This is now purely
635 * advisory. ODS with over 2G partition also gives warning message.
638 * 0 if everything went well,
642 PartSizeOverflow(char *path
, int cs
)
645 afs_int64 totalblks
, mint
;
646 #if AFS_HAVE_STATVFS || defined(HAVE_SYS_STATVFS_H)
647 struct statvfs statbuf
;
649 if (statvfs(path
, &statbuf
) != 0) {
652 ("statvfs failed on %s; skip checking for adequate partition space\n",
656 totalblks
= statbuf
.f_blocks
;
657 bsize
= statbuf
.f_frsize
;
659 if (strcmp(statbuf
.f_basetype
, "jfs")) {
660 fprintf(stderr
, "Cache filesystem '%s' must be jfs (now %s)\n",
661 path
, statbuf
.f_basetype
);
664 #endif /* AFS_AIX51_ENV */
666 #else /* AFS_HAVE_STATVFS */
667 struct statfs statbuf
;
669 if (statfs(path
, &statbuf
) < 0) {
672 ("statfs failed on %s; skip checking for adequate partition space\n",
676 totalblks
= statbuf
.f_blocks
;
677 bsize
= statbuf
.f_bsize
;
680 return 0; /* success */
682 /* now free and totalblks are in fragment units, but we want them in 1K units */
684 totalblks
*= (bsize
/ 1024);
686 totalblks
/= (1024 / bsize
);
689 mint
= totalblks
/ 100 * 95;
692 ("Cache size (%d) must be less than 95%% of partition size (which is %lld). Lower cache size\n",
700 /*-----------------------------------------------------------------------------
704 * Given the final component of a filename expected to be a data cache file,
705 * return the integer corresponding to the file. Note: we reject names that
706 * are not a ``V'' followed by an integer. We also reject those names having
707 * the right format but lying outside the range [0..cacheFiles-1].
710 * fname : Char ptr to the filename to parse.
711 * max : integer for the highest number to accept
714 * >= 0 iff the file is really a data cache file numbered from 0 to cacheFiles-1, or
718 * Nothing interesting.
722 *---------------------------------------------------------------------------*/
725 doGetXFileNumber(char *fname
, char filechar
, int maxNum
)
727 int computedVNumber
; /*The computed file number we return */
728 int filenameLen
; /*Number of chars in filename */
729 int currDigit
; /*Current digit being processed */
732 * The filename must have at least two characters, the first of which must be a ``filechar''
733 * and the second of which cannot be a zero unless the file is exactly two chars long.
735 filenameLen
= strlen(fname
);
738 if (fname
[0] != filechar
)
740 if ((filenameLen
> 2) && (fname
[1] == '0'))
744 * Scan through the characters in the given filename, failing immediately if a non-digit
747 for (currDigit
= 1; currDigit
< filenameLen
; currDigit
++)
748 if (isdigit(fname
[currDigit
]) == 0)
752 * All relevant characters are digits. Pull out the decimal number they represent.
753 * Reject it if it's out of range, otherwise return it.
755 computedVNumber
= atoi(++fname
);
756 if (computedVNumber
< cacheFiles
)
757 return (computedVNumber
);
763 GetVFileNumber(char *fname
, int maxFile
)
765 return doGetXFileNumber(fname
, 'V', maxFile
);
769 GetDDirNumber(char *fname
, int maxDir
)
771 return doGetXFileNumber(fname
, 'D', maxDir
);
775 /*-----------------------------------------------------------------------------
779 * Given a full pathname for a file we need to create for the workstation AFS
780 * cache, go ahead and create the file.
783 * fname : Full pathname of file to create.
784 * statp : A pointer to a stat buffer which, if NON-NULL, will be
788 * 0 iff the file was created,
792 * The given cache file has been found to be missing.
796 *---------------------------------------------------------------------------*/
799 CreateCacheSubDir(char *basename
, int dirNum
)
801 static char rn
[] = "CreateCacheSubDir"; /* Routine Name */
805 /* Build the new cache subdirectory */
806 sprintf(dir
, "%s/D%d", basename
, dirNum
);
809 printf("%s: Creating cache subdir '%s'\n", rn
, dir
);
811 if ((ret
= mkdir(dir
, 0700)) != 0) {
812 printf("%s: Can't create '%s', error return is %d (%d)\n", rn
, dir
,
818 /* Mark this directory as created */
819 cache_dir_list
[dirNum
] = 0;
821 /* And return success */
826 SetNoBackupAttr(char *fullpn
)
828 #ifdef AFS_DARWIN80_ENV
831 ret
= setxattr(fullpn
, "com.apple.metadata:com_apple_backup_excludeItem",
832 "com.apple.backupd", strlen("com.apple.backupd"), 0,
837 fprintf(stderr
, "afsd: Warning: failed to set attribute to preclude cache backup: %s\n", strerror(errno
));
844 MoveCacheFile(char *basename
, int fromDir
, int toDir
, int cacheFile
,
847 static char rn
[] = "MoveCacheFile";
848 char from
[1024], to
[1024];
851 if (cache_dir_list
[toDir
] < 0
852 && (ret
= CreateCacheSubDir(basename
, toDir
))) {
853 printf("%s: Can't create directory '%s/D%d'\n", rn
, basename
, toDir
);
857 /* Build the from,to dir */
859 /* old-style location */
860 snprintf(from
, sizeof(from
), "%s/V%d", basename
, cacheFile
);
862 snprintf(from
, sizeof(from
), "%s/D%d/V%d", basename
, fromDir
,
866 snprintf(to
, sizeof(from
), "%s/D%d/V%d", basename
, toDir
, cacheFile
);
869 printf("%s: Moving cacheFile from '%s' to '%s'\n", rn
, from
, to
);
871 if ((ret
= rename(from
, to
)) != 0) {
872 printf("%s: Can't rename '%s' to '%s', error return is %d (%d)\n", rn
,
873 from
, to
, ret
, errno
);
878 /* Reset directory pointer; fix file counts */
879 dir_for_V
[cacheFile
] = toDir
;
880 cache_dir_list
[toDir
]++;
881 if (fromDir
< maxDir
&& fromDir
>= 0)
882 cache_dir_list
[fromDir
]--;
888 CreateCacheFile(char *fname
, struct stat
*statp
)
890 static char rn
[] = "CreateCacheFile"; /*Routine name */
891 int cfd
; /*File descriptor to AFS cache file */
892 int closeResult
; /*Result of close() */
895 printf("%s: Creating cache file '%s'\n", rn
, fname
);
896 cfd
= open(fname
, createAndTrunc
, ownerRWmode
);
898 printf("%s: Can't create '%s', error return is %d (%d)\n", rn
, fname
,
903 closeResult
= fstat(cfd
, statp
);
906 ("%s: Can't stat newly-created AFS cache file '%s' (code %d)\n",
911 closeResult
= close(cfd
);
914 ("%s: Can't close newly-created AFS cache file '%s' (code %d)\n",
923 CreateFileIfMissing(char *fullpn
, int missing
)
926 if (CreateCacheFile(fullpn
, NULL
))
927 printf("CreateFileIfMissing: Can't create '%s'\n", fullpn
);
932 UnlinkUnwantedFile(char *rn
, char *fullpn_FileToDelete
, char *fileToDelete
)
934 if (unlink(fullpn_FileToDelete
)) {
935 if ((errno
== EISDIR
|| errno
== EPERM
) && *fileToDelete
== 'D') {
936 if (rmdir(fullpn_FileToDelete
)) {
937 printf("%s: Can't rmdir '%s', errno is %d\n", rn
,
938 fullpn_FileToDelete
, errno
);
941 printf("%s: Can't unlink '%s', errno is %d\n", rn
,
942 fullpn_FileToDelete
, errno
);
946 /*-----------------------------------------------------------------------------
950 * Sweep through the AFS cache directory, recording the inode number for
951 * each valid data cache file there. Also, delete any file that doesn't belong
952 * in the cache directory during this sweep, and remember which of the other
953 * residents of this directory were seen. After the sweep, we create any data
954 * cache files that were missing.
957 * vFilesFound : Set to the number of data cache files found.
960 * 0 if everything went well,
964 * This routine may be called several times. If the number of data cache files
965 * found is less than the global cacheFiles, then the caller will need to call it
966 * again to record the inodes of the missing zero-length data cache files created
967 * in the previous call.
970 * Fills up the global inode_for_V array, may create and/or delete files as
972 *---------------------------------------------------------------------------*/
976 doSweepAFSCache(int *vFilesFound
,
977 char *directory
, /* /path/to/cache/directory */
978 int dirNum
, /* current directory number */
979 int maxDir
) /* maximum directory number */
981 static char rn
[] = "doSweepAFSCache"; /* Routine Name */
982 char fullpn_FileToDelete
[1024]; /*File to be deleted from cache */
983 char *fileToDelete
; /*Ptr to last component of above */
984 DIR *cdirp
; /*Ptr to cache directory structure */
986 struct dirent64
*currp
; /*Current directory entry */
988 struct dirent
*currp
; /*Current directory entry */
990 int vFileNum
; /*Data cache file's associated number */
991 int thisDir
; /* A directory number */
995 printf("%s: Opening cache directory '%s'\n", rn
, directory
);
997 if (chmod(directory
, 0700)) { /* force it to be 700 */
998 printf("%s: Can't 'chmod 0700' the cache dir, '%s'.\n", rn
,
1002 cdirp
= opendir(directory
);
1003 if (cdirp
== (DIR *) 0) {
1004 printf("%s: Can't open AFS cache directory, '%s'.\n", rn
, directory
);
1009 * Scan the directory entries, remembering data cache file inodes
1010 * and the existance of other important residents. Recurse into
1011 * the data subdirectories.
1013 * Delete all files and directories that don't belong here.
1015 sprintf(fullpn_FileToDelete
, "%s/", directory
);
1016 fileToDelete
= fullpn_FileToDelete
+ strlen(fullpn_FileToDelete
);
1018 #ifdef AFS_SGI62_ENV
1019 for (currp
= readdir64(cdirp
); currp
; currp
= readdir64(cdirp
))
1021 for (currp
= readdir(cdirp
); currp
; currp
= readdir(cdirp
))
1025 printf("%s: Current directory entry:\n", rn
);
1026 #if defined(AFS_SGI62_ENV) || defined(AFS_DARWIN90_ENV)
1027 printf("\tinode=%" AFS_INT64_FMT
", reclen=%d, name='%s'\n", currp
->d_ino
,
1028 currp
->d_reclen
, currp
->d_name
);
1029 #elif defined(AFS_DFBSD_ENV) || defined(AFS_USR_DFBSD_ENV)
1030 printf("\tinode=%ld, name='%s'\n", (long)currp
->d_ino
, currp
->d_name
);
1032 printf("\tinode=%ld, reclen=%d, name='%s'\n", (long)currp
->d_ino
,
1033 currp
->d_reclen
, currp
->d_name
);
1038 * If dirNum < 0, we are a top-level cache directory and should
1039 * only contain sub-directories and other sundry files. Therefore,
1040 * V-files are valid only if dirNum >= 0, and Directories are only
1041 * valid if dirNum < 0.
1044 if (*(currp
->d_name
) == 'V'
1045 && ((vFileNum
= GetVFileNumber(currp
->d_name
, cacheFiles
)) >=
1048 * Found a valid data cache filename. Remember this
1049 * file's inode, directory, and bump the number of files found
1050 * total and in this directory.
1052 #if !defined(AFS_CACHE_VNODE_PATH) && !defined(AFS_LINUX26_ENV)
1053 inode_for_V
[vFileNum
] = currp
->d_ino
;
1055 dir_for_V
[vFileNum
] = dirNum
; /* remember this directory */
1058 /* If we're in a real subdir, mark this file to be moved
1059 * if we've already got too many files in this directory
1061 assert(dirNum
>= 0);
1062 cache_dir_list
[dirNum
]++; /* keep directory's file count */
1063 if (cache_dir_list
[dirNum
] > nFilesPerDir
) {
1064 /* Too many files -- add to filelist */
1065 struct afsd_file_list
*tmp
= malloc(sizeof(*tmp
));
1068 ("%s: MALLOC FAILED allocating file_list entry\n",
1071 tmp
->fileNum
= vFileNum
;
1072 tmp
->next
= cache_dir_filelist
[dirNum
];
1073 cache_dir_filelist
[dirNum
] = tmp
;
1078 } else if (dirNum
< 0 && (*(currp
->d_name
) == 'D')
1079 && GetDDirNumber(currp
->d_name
, 1 << 30) >= 0) {
1081 if ((vFileNum
= GetDDirNumber(currp
->d_name
, maxDir
)) >= 0) {
1082 /* Found a valid cachefile sub-Directory. Remember this number
1083 * and recurse into it. Note that subdirs cannot have subdirs.
1086 } else if ((vFileNum
= GetDDirNumber(currp
->d_name
, 1 << 30)) >=
1088 /* This directory is going away, but figure out if there
1089 * are any cachefiles in here that should be saved by
1090 * moving them to other cache directories. This directory
1091 * will be removed later.
1096 /* Save the highest directory number we've seen */
1097 if (vFileNum
> highDir
)
1100 /* If this directory is staying, be sure to mark it as 'found' */
1102 cache_dir_list
[vFileNum
] = 0;
1104 /* Print the dirname for recursion */
1105 sprintf(fileToDelete
, "%s", currp
->d_name
);
1107 /* Note: vFileNum is the directory number */
1109 doSweepAFSCache(vFilesFound
, fullpn_FileToDelete
, vFileNum
,
1110 (retval
== 1 ? 0 : -1));
1112 printf("%s: Recursive sweep failed on directory %s\n", rn
,
1116 } else if (dirNum
< 0 && strcmp(currp
->d_name
, DCACHEFILE
) == 0) {
1118 * Found the file holding the dcache entries.
1120 missing_DCacheFile
= 0;
1121 SetNoBackupAttr(fullpn_DCacheFile
);
1122 } else if (dirNum
< 0 && strcmp(currp
->d_name
, VOLINFOFILE
) == 0) {
1124 * Found the file holding the volume info.
1126 missing_VolInfoFile
= 0;
1127 SetNoBackupAttr(fullpn_VolInfoFile
);
1128 } else if (dirNum
< 0 && strcmp(currp
->d_name
, CELLINFOFILE
) == 0) {
1130 * Found the file holding the cell info.
1132 missing_CellInfoFile
= 0;
1133 SetNoBackupAttr(fullpn_CellInfoFile
);
1134 } else if ((strcmp(currp
->d_name
, ".") == 0)
1135 || (strcmp(currp
->d_name
, "..") == 0) ||
1136 #ifdef AFS_DECOSF_ENV
1137 /* these are magic AdvFS files */
1138 (strcmp(currp
->d_name
, ".tags") == 0)
1139 || (strcmp(currp
->d_name
, "quota.user") == 0)
1140 || (strcmp(currp
->d_name
, "quota.group") == 0) ||
1142 #ifdef AFS_LINUX22_ENV
1143 /* this is the ext3 journal file */
1144 (strcmp(currp
->d_name
, ".journal") == 0) ||
1146 (strcmp(currp
->d_name
, "lost+found") == 0)) {
1148 * Don't do anything - this file is legit, and is to be left alone.
1152 * This file/directory doesn't belong in the cache. Nuke it.
1154 sprintf(fileToDelete
, "%s", currp
->d_name
);
1156 printf("%s: Deleting '%s'\n", rn
, fullpn_FileToDelete
);
1157 UnlinkUnwantedFile(rn
, fullpn_FileToDelete
, fileToDelete
);
1164 * Create all the cache files that are missing.
1166 CreateFileIfMissing(fullpn_DCacheFile
, missing_DCacheFile
);
1167 CreateFileIfMissing(fullpn_VolInfoFile
, missing_VolInfoFile
);
1168 CreateFileIfMissing(fullpn_CellInfoFile
, missing_CellInfoFile
);
1170 /* ADJUST CACHE FILES */
1172 /* First, let's walk through the list of files and figure out
1173 * if there are any leftover files in extra directories or
1174 * missing files. Move the former and create the latter in
1175 * subdirs with extra space.
1178 thisDir
= 0; /* Keep track of which subdir has space */
1180 for (vFileNum
= 0; vFileNum
< cacheFiles
; vFileNum
++) {
1181 if (dir_for_V
[vFileNum
] == -1) {
1182 /* This file does not exist. Create it in the first
1183 * subdir that still has extra space.
1185 while (thisDir
< maxDir
1186 && cache_dir_list
[thisDir
] >= nFilesPerDir
)
1188 if (thisDir
>= maxDir
)
1189 printf("%s: can't find directory to create V%d\n", rn
,
1193 #if !defined(AFS_CACHE_VNODE_PATH) && !defined(AFS_LINUX26_ENV)
1194 assert(inode_for_V
[vFileNum
] == (AFSD_INO_T
) 0);
1196 sprintf(vFilePtr
, "D%d/V%d", thisDir
, vFileNum
);
1198 printf("%s: Creating '%s'\n", rn
, fullpn_VFile
);
1199 if (cache_dir_list
[thisDir
] < 0
1200 && CreateCacheSubDir(directory
, thisDir
))
1201 printf("%s: Can't create directory for '%s'\n", rn
,
1203 if (CreateCacheFile(fullpn_VFile
, &statb
))
1204 printf("%s: Can't create '%s'\n", rn
, fullpn_VFile
);
1206 #if !defined(AFS_CACHE_VNODE_PATH) && !defined(AFS_LINUX26_ENV)
1207 inode_for_V
[vFileNum
] = statb
.st_ino
;
1209 dir_for_V
[vFileNum
] = thisDir
;
1210 cache_dir_list
[thisDir
]++;
1213 SetNoBackupAttr(fullpn_VFile
);
1216 } else if (dir_for_V
[vFileNum
] >= maxDir
1217 || dir_for_V
[vFileNum
] == -2) {
1218 /* This file needs to move; move it to the first subdir
1219 * that has extra space. (-2 means it's in the toplevel)
1221 while (thisDir
< maxDir
1222 && cache_dir_list
[thisDir
] >= nFilesPerDir
)
1224 if (thisDir
>= maxDir
)
1225 printf("%s: can't find directory to move V%d\n", rn
,
1229 (directory
, dir_for_V
[vFileNum
], thisDir
, vFileNum
,
1231 /* Cannot move. Ignore this file??? */
1238 /* At this point, we've moved all of the valid cache files
1239 * into the valid subdirs, and created all the extra
1240 * cachefiles we need to create. Next, rebalance any subdirs
1241 * with too many cache files into the directories with not
1242 * enough cache files. Note that thisDir currently sits at
1243 * the lowest subdir that _may_ have room.
1246 for (dirNum
= 0; dirNum
< maxDir
; dirNum
++) {
1247 struct afsd_file_list
*thisFile
;
1249 for (thisFile
= cache_dir_filelist
[dirNum
];
1250 thisFile
&& cache_dir_list
[dirNum
] >= nFilesPerDir
;
1251 thisFile
= thisFile
->next
) {
1252 while (thisDir
< maxDir
1253 && cache_dir_list
[thisDir
] >= nFilesPerDir
)
1255 if (thisDir
>= maxDir
)
1256 printf("%s: can't find directory to move V%d\n", rn
,
1260 (directory
, dirNum
, thisDir
, thisFile
->fileNum
,
1262 /* Cannot move. Ignore this file??? */
1266 } /* for each file to move */
1267 } /* for each directory */
1269 /* Remove any directories >= maxDir -- they should be empty */
1270 for (; highDir
>= maxDir
; highDir
--) {
1271 sprintf(fileToDelete
, "D%d", highDir
);
1272 UnlinkUnwantedFile(rn
, fullpn_FileToDelete
, fileToDelete
);
1278 * Close the directory, return success.
1281 printf("%s: Closing cache directory.\n", rn
);
1287 CheckCacheBaseDir(char *dir
)
1289 struct stat statbuf
;
1292 return "cache base dir not specified";
1294 if (stat(dir
, &statbuf
) != 0) {
1295 return "unable to stat cache base directory";
1298 /* might want to check here for anything else goofy, like cache pointed at a non-dedicated directory, etc */
1300 #ifdef AFS_LINUX24_ENV
1303 struct statfs statfsbuf
;
1305 res
= statfs(dir
, &statfsbuf
);
1307 return "unable to statfs cache base directory";
1309 #if !defined(AFS_LINUX26_ENV)
1310 if (statfsbuf
.f_type
== 0x52654973) { /* REISERFS_SUPER_MAGIC */
1311 return "cannot use reiserfs as cache partition";
1312 } else if (statfsbuf
.f_type
== 0x58465342) { /* XFS_SUPER_MAGIC */
1313 return "cannot use xfs as cache partition";
1314 } else if (statfsbuf
.f_type
== 0x01021994) { /* TMPFS_SUPER_MAGIC */
1315 return "cannot use tmpfs as cache partition";
1316 } else if (statfsbuf
.f_type
!= 0xEF53) {
1317 return "must use ext2 or ext3 for cache partition";
1326 struct statfs statfsbuf
;
1329 res
= statfs(dir
, &statfsbuf
);
1331 return "unable to statfs cache base directory";
1334 if (sysfs(GETFSTYP
, statfsbuf
.f_fsid
[1], name
) != 0) {
1335 return "unable to determine filesystem type for cache base dir";
1338 if (strcmp(name
, "hfs")) {
1339 return "can only use hfs filesystem for cache partition on hpux";
1348 struct stat statmnt
, statci
;
1350 if ((stat(dir
, &statci
) == 0)
1351 && ((vfstab
= fopen(MNTTAB
, "r")) != NULL
)) {
1352 while (getmntent(vfstab
, &mnt
) == 0) {
1353 if (strcmp(dir
, mnt
.mnt_mountp
) != 0) {
1357 if (cp
= hasmntopt(&mnt
, "dev="))
1359 (int)strtol(cp
+ strlen("dev="), NULL
,
1362 if ((rdev
== 0) && (stat(mnt
.mnt_mountp
, &statmnt
) == 0))
1363 rdev
= statmnt
.st_dev
;
1365 if ((rdev
== statci
.st_dev
)
1366 && (hasmntopt(&mnt
, "logging") != NULL
)) {
1370 "mounting a multi-use partition which contains the AFS cache with the\n\"logging\" option may deadlock your system.\n\n";
1384 SweepAFSCache(int *vFilesFound
)
1386 static char rn
[] = "SweepAFSCache"; /*Routine name */
1387 int maxDir
= (cacheFiles
+ nFilesPerDir
- 1) / nFilesPerDir
;
1392 if (cacheFlags
& AFSCALL_INIT_MEMCACHE
) {
1394 printf("%s: Memory Cache, no cache sweep done\n", rn
);
1398 if (cache_dir_list
== NULL
) {
1399 cache_dir_list
= malloc(maxDir
* sizeof(*cache_dir_list
));
1400 if (cache_dir_list
== NULL
) {
1401 printf("%s: Malloc Failed!\n", rn
);
1404 for (i
= 0; i
< maxDir
; i
++)
1405 cache_dir_list
[i
] = -1; /* Does not exist */
1408 if (cache_dir_filelist
== NULL
) {
1409 cache_dir_filelist
= calloc(maxDir
, sizeof(*cache_dir_filelist
));
1410 if (cache_dir_filelist
== NULL
) {
1411 printf("%s: Malloc Failed!\n", rn
);
1416 if (dir_for_V
== NULL
) {
1417 dir_for_V
= malloc(cacheFiles
* sizeof(*dir_for_V
));
1418 if (dir_for_V
== NULL
) {
1419 printf("%s: Malloc Failed!\n", rn
);
1422 for (i
= 0; i
< cacheFiles
; i
++)
1423 dir_for_V
[i
] = -1; /* Does not exist */
1426 /* Note, setting dirNum to -2 here will cause cachefiles found in
1427 * the toplevel directory to be marked in directory "-2". This
1428 * allows us to differentiate between 'file not seen' (-1) and
1429 * 'file seen in top-level' (-2). Then when we try to move the
1430 * file into a subdirectory, we know it's in the top-level instead
1431 * of some other cache subdir.
1433 return doSweepAFSCache(vFilesFound
, cacheBaseDir
, -2, maxDir
);
1437 ConfigCell(struct afsconf_cell
*aci
, void *arock
, struct afsconf_dir
*adir
)
1442 afs_int32 hosts
[MAXHOSTSPERCELL
];
1444 /* figure out if this is the home cell */
1445 isHomeCell
= (strcmp(aci
->name
, LclCellName
) == 0);
1447 cellFlags
= 2; /* not home, suid is forbidden */
1448 if (enable_dynroot
== 2)
1449 cellFlags
|= 8; /* don't display foreign cells until looked up */
1451 /* build address list */
1452 for (i
= 0; i
< MAXHOSTSPERCELL
; i
++)
1453 memcpy(&hosts
[i
], &aci
->hostAddr
[i
].sin_addr
, sizeof(afs_int32
));
1455 if (aci
->linkedCell
)
1456 cellFlags
|= 4; /* Flag that linkedCell arg exists,
1457 * for upwards compatibility */
1459 /* configure one cell */
1460 code
= afsd_syscall(AFSOP_ADDCELL2
, hosts
, /* server addresses */
1461 aci
->name
, /* cell name */
1462 cellFlags
, /* is this the home cell? */
1463 aci
->linkedCell
); /* Linked cell, if any */
1465 printf("Adding cell '%s': error %d\n", aci
->name
, code
);
1470 ConfigCellAlias(struct afsconf_cellalias
*aca
,
1471 void *arock
, struct afsconf_dir
*adir
)
1473 /* push the alias into the kernel */
1474 afsd_syscall(AFSOP_ADDCELLALIAS
, aca
->aliasName
, aca
->realName
);
1479 AfsdbLookupHandler(void)
1481 afs_int32 kernelMsg
[64];
1482 char acellName
[128];
1484 struct afsconf_cell acellInfo
;
1489 acellName
[0] = '\0';
1491 #ifdef MACOS_EVENT_HANDLING
1492 /* Fork the event handler also. */
1495 afsd_install_events();
1497 } else if (code
!= -1) {
1502 /* On some platforms you only get 4 args to an AFS call */
1503 int sizeArg
= ((sizeof acellName
) << 16) | (sizeof kernelMsg
);
1505 afsd_syscall(AFSOP_AFSDB_HANDLER
, acellName
, kernelMsg
, sizeArg
);
1506 if (code
) { /* Something is wrong? */
1511 if (*acellName
== 1) /* Shutting down */
1514 code
= afsconf_GetAfsdbInfo(acellName
, 0, &acellInfo
);
1519 kernelMsg
[0] = acellInfo
.numServers
;
1520 if (acellInfo
.timeout
)
1521 kernelMsg
[1] = acellInfo
.timeout
- time(0);
1524 for (i
= 0; i
< acellInfo
.numServers
; i
++)
1525 kernelMsg
[i
+ 2] = acellInfo
.hostAddr
[i
].sin_addr
.s_addr
;
1526 strncpy(acellName
, acellInfo
.name
, sizeof(acellName
));
1527 acellName
[sizeof(acellName
) - 1] = '\0';
1530 #ifdef AFS_DARWIN_ENV
1531 kill(event_pid
, SIGTERM
);
1540 struct afs_uspc_param
*uspc
;
1544 uspc
= calloc(1, sizeof(struct afs_uspc_param
));
1545 memset(srcName
, 0, sizeof(srcName
));
1546 memset(dstName
, 0, sizeof(dstName
));
1548 /* brscount starts at 0 */
1554 char srcpath
[BUFSIZ
];
1555 char dstpath
[BUFSIZ
];
1557 /* pushing in a buffer this large */
1560 code
= afsd_syscall(AFSOP_BKG_HANDLER
, uspc
, srcName
, dstName
);
1561 if (code
) { /* Something is wrong? */
1562 if (code
== -2) /* shutting down */
1570 switch (uspc
->reqtype
) {
1572 snprintf(srcpath
, BUFSIZ
, "/afs/.:mount/%d:%d:%d:%d/%s",
1573 uspc
->req
.umv
.sCell
, uspc
->req
.umv
.sVolume
,
1574 uspc
->req
.umv
.sVnode
, uspc
->req
.umv
.sUnique
, srcName
);
1575 snprintf(dstpath
, BUFSIZ
, "/afs/.:mount/%d:%d:%d:%d/%s",
1576 uspc
->req
.umv
.dCell
, uspc
->req
.umv
.dVolume
,
1577 uspc
->req
.umv
.dVnode
, uspc
->req
.umv
.dUnique
, dstName
);
1578 if ((child
= fork()) == 0) {
1579 /* first child does cp; second, rm. mv would re-enter. */
1581 switch (uspc
->req
.umv
.idtype
) {
1583 if (setuid(uspc
->req
.umv
.id
) != 0) {
1589 break; /* notreached */
1591 execl("/bin/cp", "(afsd EXDEV helper)", "-PRp", "--", srcpath
,
1592 dstpath
, (char *) NULL
);
1594 if (child
== (pid_t
) -1) {
1599 if (waitpid(child
, &status
, 0) == -1)
1601 else if (WIFEXITED(status
) != 0 && WEXITSTATUS(status
) == 0) {
1602 if ((child
= fork()) == 0) {
1603 switch (uspc
->req
.umv
.idtype
) {
1605 if (setuid(uspc
->req
.umv
.id
) != 0) {
1611 break; /* notreached */
1613 execl("/bin/rm", "(afsd EXDEV helper)", "-rf", "--",
1614 srcpath
, (char *) NULL
);
1616 if (child
== (pid_t
) -1) {
1620 if (waitpid(child
, &status
, 0) == -1)
1622 else if (WIFEXITED(status
) != 0) {
1623 /* rm exit status */
1624 uspc
->retval
= WEXITSTATUS(status
);
1626 /* rm signal status */
1627 uspc
->retval
= -(WTERMSIG(status
));
1630 /* error from cp: exit or signal status */
1631 uspc
->retval
= (WIFEXITED(status
) != 0) ?
1632 WEXITSTATUS(status
) : -(WTERMSIG(status
));
1634 memset(srcName
, 0, sizeof(srcName
));
1635 memset(dstName
, 0, sizeof(dstName
));
1639 /* unknown req type */
1648 afsdb_thread(void *rock
)
1650 /* Since the AFSDB lookup handler runs as a user process,
1651 * need to drop the controlling TTY, etc.
1653 if (afsd_daemon(0, 0) == -1) {
1654 printf("Error starting AFSDB lookup handler: %s\n",
1658 AfsdbLookupHandler();
1663 daemon_thread(void *rock
)
1666 /* Since the background daemon runs as a user process,
1667 * need to drop the controlling TTY, etc.
1669 if (afsd_daemon(0, 0) == -1) {
1670 printf("Error starting background daemon: %s\n",
1676 afsd_syscall(AFSOP_START_BKG
, 0);
1683 rmtsysd_thread(void *rock
)
1688 #endif /* !UKERNEL */
1691 * Check the command line and cacheinfo options.
1693 * @param[in] as parsed command line arguments
1695 * @note Invokes the shutdown syscall and exits with 0 when
1696 * -shutdown is given.
1699 CheckOptions(struct cmd_syndesc
*as
)
1701 afs_int32 code
; /*Result of fork() */
1705 #ifdef AFS_SGI65_ENV
1706 struct sched_param sp
;
1709 #ifdef AFS_SGI_VNODE_GLUE
1710 if (afs_init_kernel_config(-1) < 0) {
1711 printf("Can't determine NUMA configuration, not starting AFS.\n");
1716 cmd_OpenConfigFile(AFSDIR_CLIENT_CONFIG_FILE_FILEPATH
);
1717 cmd_SetCommandName("afsd");
1719 /* call atoi on the appropriate parsed results */
1720 if (cmd_OptionAsInt(as
, OPT_blocks
, &cacheBlocks
) == 0)
1723 if (cmd_OptionAsInt(as
, OPT_files
, &cacheFiles
) == 0)
1726 if (cmd_OptionAsString(as
, OPT_rootvol
, &rootVolume
) == 0)
1729 if (cmd_OptionAsInt(as
, OPT_stat
, &cacheStatEntries
) == 0)
1730 sawCacheStatEntries
= 1;
1732 if (cmd_OptionPresent(as
, OPT_memcache
)) {
1733 cacheBaseDir
= NULL
;
1734 sawCacheBaseDir
= 1;
1735 cacheFlags
|= AFSCALL_INIT_MEMCACHE
;
1738 if (cmd_OptionAsString(as
, OPT_cachedir
, &cacheBaseDir
) == 0)
1739 sawCacheBaseDir
= 1;
1741 if (cmd_OptionAsString(as
, OPT_mountdir
, &afsd_cacheMountDir
) == 0)
1742 sawCacheMountDir
= 1;
1744 cmd_OptionAsInt(as
, OPT_daemons
, &nDaemons
);
1746 afsd_verbose
= cmd_OptionPresent(as
, OPT_verbose
);
1748 if (cmd_OptionPresent(as
, OPT_rmtsys
)) {
1751 printf("-rmtsys not supported for UKERNEL\n");
1756 if (cmd_OptionPresent(as
, OPT_debug
)) {
1761 if (cmd_OptionAsInt(as
, OPT_chunksize
, &chunkSize
) == 0) {
1762 if (chunkSize
< 0 || chunkSize
> 30) {
1764 ("afsd:invalid chunk size (not in range 0-30), using default\n");
1769 if (cmd_OptionAsInt(as
, OPT_dcache
, &dCacheSize
) == 0)
1772 cmd_OptionAsInt(as
, OPT_volumes
, &vCacheSize
);
1774 if (cmd_OptionPresent(as
, OPT_biods
)) {
1776 #ifndef AFS_AIX32_ENV
1778 ("afsd: [-biods] currently only enabled for aix3.x VM supported systems\n");
1780 cmd_OptionAsInt(as
, OPT_biods
, &nBiods
);
1783 cmd_OptionAsInt(as
, OPT_prealloc
, &preallocs
);
1785 if (cmd_OptionAsString(as
, OPT_confdir
, &confDir
) == CMD_MISSING
) {
1786 confDir
= strdup(AFSDIR_CLIENT_ETC_DIRPATH
);
1788 sprintf(fullpn_CacheInfo
, "%s/%s", confDir
, CACHEINFOFILE
);
1790 if (cmd_OptionPresent(as
, OPT_logfile
)) {
1791 printf("afsd: Ignoring obsolete -logfile flag\n");
1794 afsd_CloseSynch
= cmd_OptionPresent(as
, OPT_waitclose
);
1796 if (cmd_OptionPresent(as
, OPT_shutdown
)) {
1800 * Cold shutdown is the default
1802 printf("afsd: Shutting down all afs processes and afs state\n");
1803 code
= afsd_syscall(AFSOP_SHUTDOWN
, 1);
1805 printf("afsd: AFS still mounted; Not shutting down\n");
1811 enable_peer_stats
= cmd_OptionPresent(as
, OPT_peerstats
);
1812 enable_process_stats
= cmd_OptionPresent(as
, OPT_processstats
);
1814 if (cmd_OptionPresent(as
, OPT_memallocsleep
)) {
1815 printf("afsd: -mem_alloc_sleep is deprecated -- ignored\n");
1818 enable_afsdb
= cmd_OptionPresent(as
, OPT_afsdb
);
1819 if (cmd_OptionPresent(as
, OPT_filesdir
)) {
1820 /* -files_per_subdir */
1822 cmd_OptionAsInt(as
, OPT_filesdir
, &res
);
1823 if (res
< 10 || res
> (1 << 30)) {
1825 ("afsd:invalid number of files per subdir, \"%s\". Ignored\n",
1826 as
->parms
[25].items
->data
);
1831 enable_dynroot
= cmd_OptionPresent(as
, OPT_dynroot
);
1833 if (cmd_OptionPresent(as
, OPT_fakestat
)) {
1834 enable_fakestat
= 2;
1836 if (cmd_OptionPresent(as
, OPT_fakestatall
)) {
1837 enable_fakestat
= 1;
1839 if (cmd_OptionPresent(as
, OPT_settime
)) {
1841 printf("afsd: -settime ignored\n");
1842 printf("afsd: the OpenAFS client no longer sets the system time; "
1843 "please use NTP or\n");
1844 printf("afsd: another such system to synchronize client time\n");
1847 enable_nomount
= cmd_OptionPresent(as
, OPT_nomount
);
1848 enable_backuptree
= cmd_OptionPresent(as
, OPT_backuptree
);
1849 enable_rxbind
= cmd_OptionPresent(as
, OPT_rxbind
);
1851 /* set rx_extraPackets */
1852 if (cmd_OptionPresent(as
, OPT_rxpck
)) {
1855 cmd_OptionAsInt(as
, OPT_rxpck
, &rxpck
);
1856 printf("afsd: set rxpck = %d\n", rxpck
);
1857 code
= afsd_syscall(AFSOP_SET_RXPCK
, rxpck
);
1859 printf("afsd: failed to set rxpck\n");
1863 if (cmd_OptionPresent(as
, OPT_splitcache
)) {
1867 cmd_OptionAsString(as
, OPT_splitcache
, &var
);
1869 if (var
== NULL
|| ((c
= strchr(var
, '/')) == NULL
))
1871 ("ignoring splitcache (specify as RW/RO percentages: 60/40)\n");
1873 ropct
= atoi(c
+ 1);
1876 if ((rwpct
!= 0) && (ropct
!= 0) && (ropct
+ rwpct
== 100)) {
1878 enable_splitcache
= 1;
1883 if (cmd_OptionPresent(as
, OPT_nodynvcache
)) {
1884 #ifdef AFS_MAXVCOUNT_ENV
1885 afsd_dynamic_vcaches
= 0;
1887 printf("afsd: Error toggling flag, dynamically allocated vcaches not supported on your platform\n");
1891 #ifdef AFS_MAXVCOUNT_ENV
1893 /* -dynamic-vcaches */
1894 afsd_dynamic_vcaches
= 1;
1898 printf("afsd: %s dynamically allocated vcaches\n", ( afsd_dynamic_vcaches
? "enabling" : "disabling" ));
1901 cmd_OptionAsInt(as
, OPT_rxmaxmtu
, &rxmaxmtu
);
1903 if (cmd_OptionPresent(as
, OPT_dynrootsparse
)) {
1907 cmd_OptionAsInt(as
, OPT_rxmaxfrags
, &rxmaxfrags
);
1908 if (cmd_OptionPresent(as
, OPT_inumcalc
)) {
1909 cmd_OptionAsString(as
, OPT_inumcalc
, &inumcalc
);
1911 cmd_OptionAsInt(as
, OPT_volume_ttl
, &volume_ttl
);
1913 /* parse cacheinfo file if this is a diskcache */
1914 if (ParseCacheInfoFile()) {
1924 static char rn
[] = "afsd"; /*Name of this routine */
1925 struct afsconf_dir
*cdir
; /* config dir */
1926 int lookupResult
; /*Result of GetLocalCellName() */
1928 int code
; /*Result of fork() */
1929 char *fsTypeMsg
= NULL
;
1930 int cacheIteration
; /*How many times through cache verification */
1931 int vFilesFound
; /*How many data cache files were found in sweep */
1932 int currVFile
; /*Current AFS cache file number passed in */
1935 * Pull out all the configuration info for the workstation's AFS cache and
1936 * the cellular community we're willing to let our users see.
1938 cdir
= afsconf_Open(confDir
);
1940 printf("afsd: some file missing or bad in %s\n", confDir
);
1945 afsconf_GetLocalCell(cdir
, LclCellName
, sizeof(LclCellName
));
1947 printf("%s: Can't get my home cell name! [Error is %d]\n", rn
,
1951 printf("%s: My home cell is '%s'\n", rn
, LclCellName
);
1954 if (!enable_nomount
) {
1955 if (afsd_check_mount(rn
, afsd_cacheMountDir
)) {
1960 /* do some random computations in memcache case to get things to work
1961 * reasonably no matter which parameters you set.
1963 if (cacheFlags
& AFSCALL_INIT_MEMCACHE
) {
1964 /* memory cache: size described either as blocks or dcache entries, but
1968 fprintf(stderr
, "%s: -files ignored with -memcache\n", rn
);
1970 if (sawDCacheSize
) {
1971 if (chunkSize
== 0) {
1972 chunkSize
= 13; /* 8k default chunksize for memcache */
1974 if (sawCacheBlocks
) {
1976 ("%s: can't set cache blocks and dcache size simultaneously when diskless.\n",
1980 /* compute the cache size based on # of chunks times the chunk size */
1981 i
= (1 << chunkSize
); /* bytes per chunk */
1982 cacheBlocks
= i
* dCacheSize
;
1983 sawCacheBlocks
= 1; /* so that ParseCacheInfoFile doesn't overwrite */
1985 if (chunkSize
== 0) {
1986 /* Try to autotune the memcache chunksize based on size
1987 * of memcache. This is done on the assumption that approx
1988 * 1024 chunks is suitable, it's a balance between enough
1989 * chunks to be useful and ramping up nicely when using larger
1990 * memcache to improve bulk read/write performance
1993 i
<= 21 && (1 << i
) / 1024 < (cacheBlocks
/ 1024); i
++);
1996 /* compute the dcache size from overall cache size and chunk size */
1997 if (chunkSize
> 10) {
1998 dCacheSize
= (cacheBlocks
>> (chunkSize
- 10));
1999 } else if (chunkSize
< 10) {
2000 dCacheSize
= (cacheBlocks
<< (10 - chunkSize
));
2002 dCacheSize
= cacheBlocks
;
2004 /* don't have to set sawDCacheSize here since it isn't overwritten
2005 * by ParseCacheInfoFile.
2009 printf("%s: chunkSize autotuned to %d\n", rn
, chunkSize
);
2011 /* kernel computes # of dcache entries as min of cacheFiles and
2012 * dCacheSize, so we now make them equal.
2014 cacheFiles
= dCacheSize
;
2017 * Compute the number of cache files based on cache size,
2018 * but only if -files isn't given on the command line.
2019 * Don't let # files be so small as to prevent full utilization
2020 * of the cache unless user has explicitly asked for it.
2022 if (chunkSize
== 0) {
2023 /* Set chunksize to 256kB - 1MB depending on cache size */
2024 if (cacheBlocks
< 500000) {
2026 } else if (cacheBlocks
< 1000000) {
2034 cacheFiles
= cacheBlocks
/ 32; /* Assume 32k avg filesize */
2036 cacheFiles
= max(cacheFiles
, 1000);
2038 /* Always allow more files than chunks. Presume average V-file
2039 * is ~67% of a chunk... (another guess, perhaps Honeyman will
2040 * have a grad student write a paper). i is KILOBYTES.
2042 i
= 1 << (chunkSize
< 10 ? 0 : chunkSize
- 10);
2043 cacheFiles
= max(cacheFiles
, 1.5 * (cacheBlocks
/ i
));
2045 /* never permit more files than blocks, while leaving space for
2046 * VolumeInfo and CacheItems files. VolumeInfo is usually 20K,
2047 * CacheItems is 50 Bytes / file (== 1K/20)
2049 #define CACHEITMSZ (cacheFiles / 20)
2050 #define VOLINFOSZ 50 /* 40kB has been seen, be conservative */
2051 #define CELLINFOSZ 4 /* Assuming disk block size is 4k ... */
2052 #define INFOSZ (VOLINFOSZ+CELLINFOSZ+CACHEITMSZ)
2054 /* Sanity check: If the obtained number of disk cache files
2055 * is larger than the number of available (4k) disk blocks, we're
2056 * doing something wrong. Fail hard so we can fix the bug instead
2057 * of silently hiding it like before */
2059 if (cacheFiles
> (cacheBlocks
- INFOSZ
) / 4) {
2061 "%s: ASSERT: cacheFiles %d diskblocks %d\n",
2062 rn
, cacheFiles
, (cacheBlocks
- INFOSZ
) / 4);
2065 if (cacheFiles
< 100)
2066 fprintf(stderr
, "%s: WARNING: cache probably too small!\n",
2070 printf("%s: cacheFiles autotuned to %d\n", rn
, cacheFiles
);
2073 /* This actually needs to
2075 2) not second-guess when a chunksize comes from the command line
2076 3) be less, um, small. 2^2??
2078 /* Sanity check chunkSize */
2079 i
= max(cacheBlocks
/ 1000, cacheBlocks
/ cacheFiles
);
2080 chunkSize
= min(chunkSize
, i
);
2081 chunkSize
= max(chunkSize
, 2);
2083 printf("%s: chunkSize autotuned to %d\n", rn
, chunkSize
);
2086 if (!sawDCacheSize
) {
2087 dCacheSize
= cacheFiles
/ 2;
2088 if (dCacheSize
> 10000) {
2091 if (dCacheSize
< 2000) {
2095 printf("%s: dCacheSize autotuned to %d\n", rn
, dCacheSize
);
2098 if (!sawCacheStatEntries
) {
2099 if (chunkSize
<= 13) {
2100 cacheStatEntries
= dCacheSize
/ 4;
2101 } else if (chunkSize
>= 16) {
2102 cacheStatEntries
= dCacheSize
* 1.5;
2104 cacheStatEntries
= dCacheSize
;
2107 printf("%s: cacheStatEntries autotuned to %d\n", rn
,
2111 #if !defined(AFS_CACHE_VNODE_PATH) && !defined(AFS_LINUX26_ENV)
2113 * Create and zero the inode table for the desired cache files.
2115 inode_for_V
= calloc(cacheFiles
, sizeof(AFSD_INO_T
));
2116 if (inode_for_V
== (AFSD_INO_T
*) 0) {
2118 ("%s: malloc() failed for cache file inode table with %d entries.\n",
2123 printf("%s: %d inode_for_V entries at %p, %lu bytes\n", rn
,
2124 cacheFiles
, inode_for_V
,
2125 (unsigned long)cacheFiles
* sizeof(AFSD_INO_T
));
2128 if (!(cacheFlags
& AFSCALL_INIT_MEMCACHE
)) {
2130 * Set up all the pathnames we'll need for later.
2132 sprintf(fullpn_DCacheFile
, "%s/%s", cacheBaseDir
, DCACHEFILE
);
2133 sprintf(fullpn_VolInfoFile
, "%s/%s", cacheBaseDir
, VOLINFOFILE
);
2134 sprintf(fullpn_CellInfoFile
, "%s/%s", cacheBaseDir
, CELLINFOFILE
);
2135 sprintf(fullpn_VFile
, "%s/", cacheBaseDir
);
2136 vFilePtr
= fullpn_VFile
+ strlen(fullpn_VFile
);
2138 fsTypeMsg
= CheckCacheBaseDir(cacheBaseDir
);
2141 printf("%s: WARNING: Cache dir check failed (%s)\n", rn
, fsTypeMsg
);
2143 printf("%s: ERROR: Cache dir check failed (%s)\n", rn
, fsTypeMsg
);
2150 * Set up all the kernel processes needed for AFS.
2153 setpgrp(getpid(), 0);
2157 * Set the primary cell name.
2159 afsd_syscall(AFSOP_SET_THISCELL
, LclCellName
);
2161 /* Initialize RX daemons and services */
2163 /* initialize the rx random number generator from user space */
2165 /* rand-fortuna wants at least 128 bytes of seed; be generous. */
2166 unsigned char seedbuf
[256];
2167 if (RAND_bytes(seedbuf
, sizeof(seedbuf
)) != 1) {
2168 printf("SEED_ENTROPY: Error retrieving seed entropy\n");
2170 afsd_syscall(AFSOP_SEED_ENTROPY
, seedbuf
, sizeof(seedbuf
));
2171 memset(seedbuf
, 0, sizeof(seedbuf
));
2172 /* parse multihomed address files */
2173 afs_uint32 addrbuf
[MAXIPADDRS
], maskbuf
[MAXIPADDRS
],
2176 code
= afsconf_ParseNetFiles(addrbuf
, maskbuf
, mtubuf
, MAXIPADDRS
, reason
,
2177 AFSDIR_CLIENT_NETINFO_FILEPATH
,
2178 AFSDIR_CLIENT_NETRESTRICT_FILEPATH
);
2181 code
= code
| 0x80000000;
2182 afsd_syscall(AFSOP_ADVISEADDR
, code
, addrbuf
, maskbuf
, mtubuf
);
2184 printf("ADVISEADDR: Error in specifying interface addresses:%s\n",
2188 /* Set realtime priority for most threads to same as for biod's. */
2189 afsd_set_afsd_rtpri();
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
2194 * preallocs are passed for both listener and callback server. Only
2195 * the one which actually does the initialization uses them though.
2197 if (preallocs
< cacheStatEntries
+ 50)
2198 preallocs
= cacheStatEntries
+ 50;
2199 #ifdef RXK_LISTENER_ENV
2201 printf("%s: Forking rx listener daemon.\n", rn
);
2202 # ifdef AFS_SUN510_ENV
2203 fork_rx_syscall_wait(rn
, AFSOP_RXLISTENER_DAEMON
, preallocs
,
2204 enable_peer_stats
, enable_process_stats
);
2205 # else /* !AFS_SUN510_ENV */
2206 fork_rx_syscall(rn
, AFSOP_RXLISTENER_DAEMON
, preallocs
, enable_peer_stats
,
2207 enable_process_stats
);
2208 # endif /* !AFS_SUN510_ENV */
2211 printf("%s: Forking rx callback listener.\n", rn
);
2212 #ifndef RXK_LISTENER_ENV
2213 fork_rx_syscall(rn
, AFSOP_START_RXCALLBACK
, preallocs
, enable_peer_stats
,
2214 enable_process_stats
);
2216 fork_syscall(rn
, AFSOP_START_RXCALLBACK
, preallocs
, 0, 0);
2218 #if defined(AFS_SUN5_ENV) || defined(RXK_LISTENER_ENV) || defined(RXK_UPCALL_ENV)
2220 printf("%s: Forking rxevent daemon.\n", rn
);
2221 fork_rx_syscall(rn
, AFSOP_RXEVENT_DAEMON
);
2226 printf("%s: Forking AFSDB lookup handler.\n", rn
);
2227 afsd_fork(0, afsdb_thread
, NULL
);
2229 code
= afsd_syscall(AFSOP_BASIC_INIT
, 1);
2231 printf("%s: Error %d in basic initialization.\n", rn
, code
);
2236 * Tell the kernel some basic information about the workstation's cache.
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
,
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
= 0;
2251 cparams
.memCacheFlag
= cacheFlags
;
2252 cparams
.dynamic_vcaches
= afsd_dynamic_vcaches
;
2253 afsd_syscall(AFSOP_CACHEINIT
, &cparams
);
2255 /* do it before we init the cache inodes */
2256 if (enable_splitcache
) {
2257 afsd_syscall(AFSOP_BUCKETPCT
, 1, rwpct
);
2258 afsd_syscall(AFSOP_BUCKETPCT
, 2, ropct
);
2261 if (afsd_CloseSynch
)
2262 afsd_syscall(AFSOP_CLOSEWAIT
);
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
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.
2274 printf("%s: Sweeping workstation's AFS cache directory.\n", rn
);
2276 /* Memory-cache based system doesn't need any of this */
2277 if (!(cacheFlags
& AFSCALL_INIT_MEMCACHE
)) {
2280 if (SweepAFSCache(&vFilesFound
)) {
2281 printf("%s: Error on sweep %d of workstation AFS cache \
2282 directory.\n", rn
, cacheIteration
);
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_LOOPS
));
2291 } else if (afsd_verbose
)
2292 printf("%s: Using memory cache, not swept\n", rn
);
2295 * Pass the kernel the name of the workstation cache file holding the
2299 printf("%s: Calling AFSOP_CACHEINFO: dcache file is '%s'\n", rn
,
2301 /* once again, meaningless for a memory-based cache. */
2302 if (!(cacheFlags
& AFSCALL_INIT_MEMCACHE
))
2303 afsd_syscall(AFSOP_CACHEINFO
, fullpn_DCacheFile
);
2306 * Pass the kernel the name of the workstation cache file holding the
2309 if (!(cacheFlags
& AFSCALL_INIT_MEMCACHE
)) {
2311 printf("%s: Calling AFSOP_CELLINFO: cell info file is '%s'\n", rn
,
2312 fullpn_CellInfoFile
);
2313 afsd_syscall(AFSOP_CELLINFO
, fullpn_CellInfoFile
);
2318 printf("%s: Setting rxmaxfrags in kernel = %d\n", rn
, rxmaxfrags
);
2319 code
= afsd_syscall(AFSOP_SET_RXMAXFRAGS
, rxmaxfrags
);
2321 printf("%s: Error seting rxmaxfrags\n", rn
);
2326 printf("%s: Setting rxmaxmtu in kernel = %d\n", rn
, rxmaxmtu
);
2327 code
= afsd_syscall(AFSOP_SET_RXMAXMTU
, rxmaxmtu
);
2329 printf("%s: Error seting rxmaxmtu\n", rn
);
2332 if (inumcalc
!= NULL
) {
2333 if (strcmp(inumcalc
, "compat") == 0) {
2335 printf("%s: Setting original inode number calculation method in kernel.\n",
2338 code
= afsd_syscall(AFSOP_SET_INUMCALC
, AFS_INUMCALC_COMPAT
);
2340 printf("%s: Error setting inode calculation method: code=%d.\n",
2343 } else if (strcmp(inumcalc
, "md5") == 0) {
2345 printf("%s: Setting md5 digest inode number calculation in kernel.\n",
2348 code
= afsd_syscall(AFSOP_SET_INUMCALC
, AFS_INUMCALC_MD5
);
2350 printf("%s: Error setting inode calculation method: code=%d.\n",
2354 printf("%s: Unknown value for -inumcalc: %s."
2355 "Using default inode calculation method.\n", rn
, inumcalc
);
2359 if (enable_dynroot
) {
2361 printf("%s: Enabling dynroot support in kernel%s.\n", rn
,
2362 (enable_dynroot
==2)?", not showing cells.":"");
2363 code
= afsd_syscall(AFSOP_SET_DYNROOT
, 1);
2365 printf("%s: Error enabling dynroot support.\n", rn
);
2368 if (enable_fakestat
) {
2370 printf("%s: Enabling fakestat support in kernel%s.\n", rn
,
2371 (enable_fakestat
==1)?" for all mountpoints."
2372 :" for crosscell mountpoints");
2373 code
= afsd_syscall(AFSOP_SET_FAKESTAT
, enable_fakestat
);
2375 printf("%s: Error enabling fakestat support.\n", rn
);
2378 if (enable_backuptree
) {
2380 printf("%s: Enabling backup tree support in kernel.\n", rn
);
2381 code
= afsd_syscall(AFSOP_SET_BACKUPTREE
, enable_backuptree
);
2383 printf("%s: Error enabling backup tree support.\n", rn
);
2387 * Tell the kernel about each cell in the configuration.
2389 afsconf_CellApply(cdir
, ConfigCell
, NULL
);
2390 afsconf_CellAliasApply(cdir
, ConfigCellAlias
, NULL
);
2392 /* Initialize AFS daemon threads. */
2394 printf("%s: Forking AFS daemon.\n", rn
);
2395 fork_syscall(rn
, AFSOP_START_AFS
);
2398 printf("%s: Forking Check Server Daemon.\n", rn
);
2399 fork_syscall(rn
, AFSOP_START_CS
);
2402 printf("%s: Forking %d background daemons.\n", rn
, nDaemons
);
2403 #if defined(AFS_SGI_ENV) && defined(AFS_SGI_SHORTSTACK)
2404 /* Add one because for sgi we always "steal" the first daemon for a
2405 * different task if we only have a 4K stack.
2409 for (i
= 0; i
< nDaemons
; i
++) {
2410 afsd_fork(0, daemon_thread
, NULL
);
2412 #ifdef AFS_AIX32_ENV
2414 nBiods
= nDaemons
* 2;
2417 for (i
= 0; i
< nBiods
; i
++) {
2418 fork_syscall(rn
, AFSOP_START_BKG
, nBiods
);
2423 * If the root volume has been explicitly set, tell the kernel.
2427 printf("%s: Calling AFSOP_ROOTVOLUME with '%s'\n", rn
,
2429 afsd_syscall(AFSOP_ROOTVOLUME
, rootVolume
);
2432 if (volume_ttl
!= 0) {
2434 printf("%s: Calling AFSOP_SET_VOLUME_TTL with '%d'\n", rn
, volume_ttl
);
2435 code
= afsd_syscall(AFSOP_SET_VOLUME_TTL
, volume_ttl
);
2437 printf("%s: Error setting volume ttl to %d seconds; code=%d.\n", rn
, volume_ttl
, code
);
2441 * Pass the kernel the name of the workstation cache file holding the
2442 * volume information.
2445 printf("%s: Calling AFSOP_VOLUMEINFO: volume info file is '%s'\n", rn
,
2446 fullpn_VolInfoFile
);
2447 /* once again, meaningless for a memory-based cache. */
2448 if (!(cacheFlags
& AFSCALL_INIT_MEMCACHE
))
2449 afsd_syscall(AFSOP_VOLUMEINFO
, fullpn_VolInfoFile
);
2452 * Give the kernel the names of the AFS files cached on the workstation's
2455 if (!(cacheFlags
& AFSCALL_INIT_MEMCACHE
)) {
2456 int nocachefile
= 0;
2459 ("%s: Calling AFSOP_CACHEFILE for each of the %d files in '%s'\n",
2460 rn
, cacheFiles
, cacheBaseDir
);
2461 /* ... and again ... */
2462 for (currVFile
= 0; currVFile
< cacheFiles
; currVFile
++) {
2464 sprintf(fullpn_VFile
, "%s/D%d/V%d", cacheBaseDir
, dir_for_V
[currVFile
], currVFile
);
2465 code
= afsd_syscall(AFSOP_CACHEFILE
, fullpn_VFile
);
2467 if (currVFile
== 0) {
2470 ("%s: Calling AFSOP_CACHEINODE for each of the %d files in '%s'\n",
2471 rn
, cacheFiles
, cacheBaseDir
);
2475 ("%s: Error calling AFSOP_CACHEFILE for '%s'\n",
2482 /* fall through to setup-by-inode */
2484 #if defined(AFS_SGI62_ENV) || !(defined(AFS_LINUX26_ENV) || defined(AFS_CACHE_VNODE_PATH))
2485 afsd_syscall(AFSOP_CACHEINODE
, inode_for_V
[currVFile
]);
2488 ("%s: Error calling AFSOP_CACHEINODE: not configured\n",
2496 * All the necessary info has been passed into the kernel to run an AFS
2497 * system. Give the kernel our go-ahead.
2500 printf("%s: Calling AFSOP_GO with cacheSetTime = %d\n", rn
,
2502 afsd_syscall(AFSOP_GO
, 0);
2505 * At this point, we have finished passing the kernel all the info
2506 * it needs to set up the AFS. Mount the AFS root.
2508 printf("%s: All AFS daemons started.\n", rn
);
2511 printf("%s: Forking trunc-cache daemon.\n", rn
);
2512 fork_syscall(rn
, AFSOP_START_TRUNCDAEMON
);
2514 if (!enable_nomount
) {
2515 afsd_mount_afs(rn
, afsd_cacheMountDir
);
2521 printf("%s: Forking 'rmtsys' daemon.\n", rn
);
2522 afsd_fork(0, rmtsysd_thread
, NULL
);
2523 code
= afsd_syscall(AFSOP_SET_RMTSYS_FLAG
, 1);
2525 printf("%s: Error enabling rmtsys support.\n", rn
);
2527 #endif /* !UKERNEL */
2529 * Exit successfully.
2535 #include "AFS_component_version_number.c"
2541 struct cmd_syndesc
*ts
;
2543 ts
= cmd_CreateSyntax(NULL
, NULL
, NULL
, 0, "start AFS");
2546 cmd_AddParmAtOffset(ts
, OPT_blocks
, "-blocks", CMD_SINGLE
,
2547 CMD_OPTIONAL
, "1024 byte blocks in cache");
2548 cmd_AddParmAtOffset(ts
, OPT_files
, "-files", CMD_SINGLE
,
2549 CMD_OPTIONAL
, "files in cache");
2550 cmd_AddParmAtOffset(ts
, OPT_rootvol
, "-rootvol", CMD_SINGLE
,
2551 CMD_OPTIONAL
, "name of AFS root volume");
2552 cmd_AddParmAtOffset(ts
, OPT_stat
, "-stat", CMD_SINGLE
,
2553 CMD_OPTIONAL
, "number of stat entries");
2554 cmd_AddParmAtOffset(ts
, OPT_memcache
, "-memcache", CMD_FLAG
,
2555 CMD_OPTIONAL
, "run diskless");
2556 cmd_AddParmAtOffset(ts
, OPT_cachedir
, "-cachedir", CMD_SINGLE
,
2557 CMD_OPTIONAL
, "cache directory");
2558 cmd_AddParmAtOffset(ts
, OPT_mountdir
, "-mountdir", CMD_SINGLE
,
2559 CMD_OPTIONAL
, "mount location");
2560 cmd_AddParmAtOffset(ts
, OPT_daemons
, "-daemons", CMD_SINGLE
,
2561 CMD_OPTIONAL
, "number of daemons to use");
2562 cmd_AddParmAtOffset(ts
, OPT_nosettime
, "-nosettime", CMD_FLAG
,
2563 CMD_OPTIONAL
, "don't set the time");
2564 cmd_AddParmAtOffset(ts
, OPT_verbose
, "-verbose", CMD_FLAG
,
2565 CMD_OPTIONAL
, "display lots of information");
2566 cmd_AddParmAtOffset(ts
, OPT_rmtsys
, "-rmtsys", CMD_FLAG
,
2567 CMD_OPTIONAL
, "start NFS rmtsysd program");
2568 cmd_AddParmAtOffset(ts
, OPT_debug
, "-debug", CMD_FLAG
,
2569 CMD_OPTIONAL
, "display debug info");
2570 cmd_AddParmAtOffset(ts
, OPT_chunksize
, "-chunksize", CMD_SINGLE
,
2571 CMD_OPTIONAL
, "log(2) of chunk size");
2572 cmd_AddParmAtOffset(ts
, OPT_dcache
, "-dcache", CMD_SINGLE
,
2573 CMD_OPTIONAL
, "number of dcache entries");
2574 cmd_AddParmAtOffset(ts
, OPT_volumes
, "-volumes", CMD_SINGLE
,
2575 CMD_OPTIONAL
, "number of volume entries");
2576 cmd_AddParmAtOffset(ts
, OPT_biods
, "-biods", CMD_SINGLE
,
2577 CMD_OPTIONAL
, "number of bkg I/O daemons (aix vm)");
2578 cmd_AddParmAtOffset(ts
, OPT_prealloc
, "-prealloc", CMD_SINGLE
,
2579 CMD_OPTIONAL
, "number of 'small' preallocated blocks");
2580 cmd_AddParmAtOffset(ts
, OPT_confdir
, "-confdir", CMD_SINGLE
,
2581 CMD_OPTIONAL
, "configuration directory");
2582 cmd_AddParmAtOffset(ts
, OPT_logfile
, "-logfile", CMD_SINGLE
,
2583 CMD_OPTIONAL
, "Place to keep the CM log");
2584 cmd_AddParmAtOffset(ts
, OPT_waitclose
, "-waitclose", CMD_FLAG
,
2585 CMD_OPTIONAL
, "make close calls synchronous");
2586 cmd_AddParmAtOffset(ts
, OPT_shutdown
, "-shutdown", CMD_FLAG
,
2587 CMD_OPTIONAL
, "Shutdown all afs state");
2588 cmd_AddParmAtOffset(ts
, OPT_peerstats
, "-enable_peer_stats", CMD_FLAG
,
2589 CMD_OPTIONAL
, "Collect rpc statistics by peer");
2590 cmd_AddParmAtOffset(ts
, OPT_processstats
, "-enable_process_stats",
2591 CMD_FLAG
, CMD_OPTIONAL
, "Collect rpc statistics for this process");
2592 cmd_AddParmAtOffset(ts
, OPT_memallocsleep
, "-mem_alloc_sleep",
2593 CMD_FLAG
, CMD_OPTIONAL
| CMD_HIDE
,
2594 "Allow sleeps when allocating memory cache");
2595 cmd_AddParmAtOffset(ts
, OPT_afsdb
, "-afsdb", CMD_FLAG
,
2596 CMD_OPTIONAL
, "Enable AFSDB support");
2597 cmd_AddParmAtOffset(ts
, OPT_filesdir
, "-files_per_subdir", CMD_SINGLE
,
2599 "log(2) of the number of cache files per "
2600 "cache subdirectory");
2601 cmd_AddParmAtOffset(ts
, OPT_dynroot
, "-dynroot", CMD_FLAG
,
2602 CMD_OPTIONAL
, "Enable dynroot support");
2603 cmd_AddParmAtOffset(ts
, OPT_fakestat
, "-fakestat", CMD_FLAG
,
2605 "Enable fakestat support for cross-cell mounts");
2606 cmd_AddParmAtOffset(ts
, OPT_fakestatall
, "-fakestat-all", CMD_FLAG
,
2608 "Enable fakestat support for all mounts");
2609 cmd_AddParmAtOffset(ts
, OPT_nomount
, "-nomount", CMD_FLAG
,
2610 CMD_OPTIONAL
, "Do not mount AFS");
2611 cmd_AddParmAtOffset(ts
, OPT_backuptree
, "-backuptree", CMD_FLAG
,
2613 "Prefer backup volumes for mountpoints in backup "
2615 cmd_AddParmAtOffset(ts
, OPT_rxbind
, "-rxbind", CMD_FLAG
,
2617 "Bind the Rx socket (one interface only)");
2618 cmd_AddParmAtOffset(ts
, OPT_settime
, "-settime", CMD_FLAG
,
2619 CMD_OPTIONAL
, "set the time");
2620 cmd_AddParmAtOffset(ts
, OPT_rxpck
, "-rxpck", CMD_SINGLE
, CMD_OPTIONAL
,
2621 "set rx_extraPackets to this value");
2622 cmd_AddParmAtOffset(ts
, OPT_splitcache
, "-splitcache", CMD_SINGLE
,
2624 "Percentage RW versus RO in cache (specify as 60/40)");
2625 cmd_AddParmAtOffset(ts
, OPT_nodynvcache
, "-disable-dynamic-vcaches",
2626 CMD_FLAG
, CMD_OPTIONAL
,
2627 "disable stat/vcache cache growing as needed");
2628 cmd_AddParmAtOffset(ts
, OPT_rxmaxmtu
, "-rxmaxmtu", CMD_SINGLE
,
2629 CMD_OPTIONAL
, "set rx max MTU to use");
2630 cmd_AddParmAtOffset(ts
, OPT_dynrootsparse
, "-dynroot-sparse", CMD_FLAG
,
2632 "Enable dynroot support with minimal cell list");
2633 cmd_AddParmAtOffset(ts
, OPT_rxmaxfrags
, "-rxmaxfrags", CMD_SINGLE
,
2635 "Set the maximum number of UDP fragments Rx should "
2636 "send/receive per Rx packet");
2637 cmd_AddParmAtOffset(ts
, OPT_inumcalc
, "-inumcalc", CMD_SINGLE
, CMD_OPTIONAL
,
2638 "Set inode number calculation method");
2639 cmd_AddParmAtOffset(ts
, OPT_volume_ttl
, "-volume-ttl", CMD_SINGLE
,
2641 "Set the vldb cache timeout value in seconds.");
2645 * Parse and check the command line options.
2647 * @note The -shutdown command is handled in CheckOptions().
2650 afsd_parse(int argc
, char **argv
)
2652 struct cmd_syndesc
*ts
= NULL
;
2655 code
= cmd_Parse(argc
, argv
, &ts
);
2659 code
= CheckOptions(ts
);
2660 cmd_FreeOptions(&ts
);
2665 * entry point for calling a syscall from another proc/thread.
2667 * @param[in] rock a struct afsd_syscall_args* specifying what syscall to call
2670 * @retval NULL always
2673 call_syscall_thread(void *rock
)
2675 struct afsd_syscall_args
*args
= rock
;
2679 afsd_set_rx_rtpri();
2682 code
= afsd_call_syscall(args
);
2683 if (code
&& args
->syscall
== AFSOP_START_CS
) {
2684 printf("%s: No check server daemon in client.\n", args
->rn
);
2693 afsd_syscall_populate(struct afsd_syscall_args
*args
, int syscall
, va_list ap
)
2695 afsd_syscall_param_t
*params
;
2697 memset(args
, 0, sizeof(struct afsd_syscall_args
));
2699 args
->syscall
= syscall
;
2700 params
= args
->params
;
2703 case AFSOP_RXEVENT_DAEMON
:
2704 case AFSOP_CLOSEWAIT
:
2705 case AFSOP_START_AFS
:
2706 case AFSOP_START_CS
:
2707 case AFSOP_START_TRUNCDAEMON
:
2709 case AFSOP_START_BKG
:
2710 case AFSOP_SHUTDOWN
:
2711 case AFSOP_SET_RXPCK
:
2712 case AFSOP_BASIC_INIT
:
2713 case AFSOP_SET_RXMAXFRAGS
:
2714 case AFSOP_SET_RXMAXMTU
:
2715 case AFSOP_SET_DYNROOT
:
2716 case AFSOP_SET_FAKESTAT
:
2717 case AFSOP_SET_BACKUPTREE
:
2718 case AFSOP_BUCKETPCT
:
2720 case AFSOP_SET_RMTSYS_FLAG
:
2721 case AFSOP_SET_INUMCALC
:
2722 case AFSOP_SET_VOLUME_TTL
:
2723 params
[0] = CAST_SYSCALL_PARAM((va_arg(ap
, int)));
2725 case AFSOP_SET_THISCELL
:
2726 case AFSOP_ROOTVOLUME
:
2727 case AFSOP_VOLUMEINFO
:
2728 case AFSOP_CACHEFILE
:
2729 case AFSOP_CACHEINFO
:
2730 case AFSOP_CACHEINIT
:
2731 case AFSOP_CELLINFO
:
2732 params
[0] = CAST_SYSCALL_PARAM((va_arg(ap
, void *)));
2734 case AFSOP_ADDCELLALIAS
:
2735 params
[0] = CAST_SYSCALL_PARAM((va_arg(ap
, void *)));
2736 params
[1] = CAST_SYSCALL_PARAM((va_arg(ap
, void *)));
2738 case AFSOP_AFSDB_HANDLER
:
2739 params
[0] = CAST_SYSCALL_PARAM((va_arg(ap
, void *)));
2740 params
[1] = CAST_SYSCALL_PARAM((va_arg(ap
, void *)));
2741 params
[2] = CAST_SYSCALL_PARAM((va_arg(ap
, int)));
2743 case AFSOP_BKG_HANDLER
:
2744 params
[0] = CAST_SYSCALL_PARAM((va_arg(ap
, void *)));
2745 params
[1] = CAST_SYSCALL_PARAM((va_arg(ap
, void *)));
2746 params
[2] = CAST_SYSCALL_PARAM((va_arg(ap
, void *)));
2748 case AFSOP_RXLISTENER_DAEMON
:
2749 case AFSOP_START_RXCALLBACK
:
2750 params
[0] = CAST_SYSCALL_PARAM((va_arg(ap
, int)));
2751 params
[1] = CAST_SYSCALL_PARAM((va_arg(ap
, int)));
2752 params
[2] = CAST_SYSCALL_PARAM((va_arg(ap
, int)));
2754 case AFSOP_ADVISEADDR
:
2755 params
[0] = CAST_SYSCALL_PARAM((va_arg(ap
, int)));
2756 params
[1] = CAST_SYSCALL_PARAM((va_arg(ap
, void *)));
2757 params
[2] = CAST_SYSCALL_PARAM((va_arg(ap
, void *)));
2758 params
[3] = CAST_SYSCALL_PARAM((va_arg(ap
, void *)));
2760 case AFSOP_ADDCELL2
:
2761 params
[0] = CAST_SYSCALL_PARAM((va_arg(ap
, void *)));
2762 params
[1] = CAST_SYSCALL_PARAM((va_arg(ap
, void *)));
2763 params
[2] = CAST_SYSCALL_PARAM((va_arg(ap
, afs_int32
)));
2764 params
[3] = CAST_SYSCALL_PARAM((va_arg(ap
, void *)));
2766 case AFSOP_CACHEINODE
:
2767 #if defined AFS_SGI62_ENV
2769 afs_int64 tmp
= va_arg(ap
, afs_int64
);
2770 params
[0] = CAST_SYSCALL_PARAM((afs_uint32
)(tmp
>> 32));
2771 params
[1] = CAST_SYSCALL_PARAM((afs_uint32
)(tmp
& 0xffffffff));
2774 params
[0] = CAST_SYSCALL_PARAM((va_arg(ap
, afs_uint32
)));
2777 case AFSOP_SEED_ENTROPY
:
2778 params
[0] = CAST_SYSCALL_PARAM((va_arg(ap
, void *)));
2779 params
[1] = CAST_SYSCALL_PARAM((va_arg(ap
, afs_uint32
)));
2782 printf("Unknown syscall enountered: %d\n", syscall
);
2788 * common code for calling a syscall in another proc/thread.
2790 * @param[in] rx 1 if this is a thread for RX stuff, 0 otherwise
2791 * @param[in] wait 1 if we should wait for the new proc/thread to finish, 0 to
2792 * let it run in the background
2793 * @param[in] rn the name of the running program
2794 * @param[in] syscall syscall to run
2797 fork_syscall_impl(int rx
, int wait
, const char *rn
, int syscall
, va_list ap
)
2799 struct afsd_syscall_args
*args
;
2801 args
= malloc(sizeof(*args
));
2802 afsd_syscall_populate(args
, syscall
, ap
);
2806 afsd_fork(wait
, call_syscall_thread
, args
);
2810 * call a syscall in another process or thread.
2813 fork_syscall(const char *rn
, int syscall
, ...)
2817 va_start(ap
, syscall
);
2818 fork_syscall_impl(0, 0, rn
, syscall
, ap
);
2823 * call a syscall in another process or thread, and give it RX priority.
2826 fork_rx_syscall(const char *rn
, int syscall
, ...)
2830 va_start(ap
, syscall
);
2831 fork_syscall_impl(1, 0, rn
, syscall
, ap
);
2835 #if defined(AFS_SUN510_ENV) && defined(RXK_LISTENER_ENV)
2837 * call a syscall in another process or thread, give it RX priority, and wait
2838 * for it to finish before returning.
2841 fork_rx_syscall_wait(const char *rn
, int syscall
, ...)
2845 va_start(ap
, syscall
);
2846 fork_syscall_impl(1, 1, rn
, syscall
, ap
);
2849 #endif /* AFS_SUN510_ENV && RXK_LISTENER_ENV */
2852 afsd_syscall(int syscall
, ...)
2855 struct afsd_syscall_args args
;
2857 va_start(ap
, syscall
);
2858 afsd_syscall_populate(&args
, syscall
, ap
);
2861 return afsd_call_syscall(&args
);