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
13 * Institution: The Information Technology Center, Carnegie-Mellon University
17 /* Main program file. Define globals. */
20 #include <afsconfig.h>
21 #include <afs/param.h>
33 #include <WINNT/afsevent.h>
35 #include <sys/param.h>
39 #endif /* ITIMER_REAL */
42 #define WCOREDUMP(x) ((x) & 0200)
45 #include <afs/afsint.h>
46 #include <afs/afs_assert.h>
47 #if !defined(AFS_SGI_ENV) && !defined(AFS_NT40_ENV)
48 #if defined(AFS_VFSINCL_ENV)
49 #include <sys/vnode.h>
51 #include <sys/fs/ufs_inode.h>
53 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
54 #include <ufs/ufs/dinode.h>
55 #include <ufs/ffs/fs.h>
57 #include <ufs/inode.h>
60 #else /* AFS_VFSINCL_ENV */
62 #include <ufs/inode.h>
63 #else /* AFS_OSF_ENV */
64 #if !defined(AFS_LINUX20_ENV) && !defined(AFS_XBSD_ENV) && !defined(AFS_DARWIN_ENV)
65 #include <sys/inode.h>
68 #endif /* AFS_VFSINCL_ENV */
69 #endif /* AFS_SGI_ENV */
72 #include <sys/lockf.h>
76 #include <checklist.h>
78 #if defined(AFS_SGI_ENV)
83 #if defined(AFS_SUN_ENV) || defined(AFS_SUN5_ENV)
86 #include <sys/mnttab.h>
87 #include <sys/mntent.h>
92 #endif /* AFS_SGI_ENV */
93 #endif /* AFS_HPUX_ENV */
98 #include <afs/osi_inode.h>
102 #include <afs/afsutil.h>
103 #include <afs/fileutil.h>
104 #include <afs/procmgmt.h> /* signal(), kill(), wait(), etc. */
112 #include <afs/afssyscalls.h>
116 #include "partition.h"
117 #include "daemon_com.h"
119 #include "salvsync.h"
120 #include "viceinode.h"
122 #include "vol-salvage.h"
126 pthread_t main_thread
;
129 static int get_salvage_lock
= 0;
132 handleit(struct cmd_syndesc
*as
, void *arock
)
135 char pname
[100], *temp
;
136 afs_int32 seenpart
= 0, seenvol
= 0;
141 afs_int32 seenany
= 0;
144 VolumePackageOptions opts
;
145 struct DiskPartition64
*partP
;
147 #ifdef AFS_SGI_VNODE_GLUE
148 if (afs_init_kernel_config(-1) < 0) {
150 ("Can't determine NUMA configuration, not starting salvager.\n");
158 for (i
= 0; i
< CMD_MAXPARMS
; i
++) {
159 if (as
->parms
[i
].items
) {
167 "Exiting immediately without salvage. Look into the FileLog to find volumes which really need to be salvaged!";
178 #endif /* FAST_RESTART */
179 if ((ti
= as
->parms
[0].items
)) { /* -partition */
181 strncpy(pname
, ti
->data
, 100);
183 if ((ti
= as
->parms
[1].items
)) { /* -volumeid */
188 ("You must also specify '-partition' option with the '-volumeid' option\n");
192 vid_l
= strtoul(ti
->data
, &end
, 10);
193 if (vid_l
>= MAX_AFS_UINT32
|| vid_l
== ULONG_MAX
|| *end
!= '\0') {
194 Log("salvage: invalid volume id specified; salvage aborted\n");
197 vid
= (VolumeId
)vid_l
;
199 if (as
->parms
[2].items
) /* -debug */
201 if (as
->parms
[3].items
) /* -nowrite */
203 if (as
->parms
[4].items
) /* -inodes */
205 if (as
->parms
[5].items
|| as
->parms
[21].items
) /* -force, -f */
207 if (as
->parms
[6].items
) /* -oktozap */
209 if (as
->parms
[7].items
) /* -rootinodes */
211 if (as
->parms
[8].items
) /* -RebuildDirs */
213 if (as
->parms
[9].items
) /* -ForceReads */
215 if ((ti
= as
->parms
[10].items
)) { /* -Parallel # */
217 if (strncmp(temp
, "all", 3) == 0) {
221 if (strlen(temp
) != 0) {
222 Parallel
= atoi(temp
);
225 if (Parallel
> MAXPARALLEL
) {
226 printf("Setting parallel salvages to maximum of %d \n",
228 Parallel
= MAXPARALLEL
;
232 if ((ti
= as
->parms
[11].items
)) { /* -tmpdir */
236 dirp
= opendir(tmpdir
);
239 ("Can't open temporary placeholder dir %s; using current partition \n",
245 if ((ti
= as
->parms
[12].items
)) /* -showlog */
247 if ((ti
= as
->parms
[13].items
)) { /* -showsuid */
252 if ((ti
= as
->parms
[14].items
)) { /* -showmounts */
257 if ((ti
= as
->parms
[15].items
)) { /* -orphans */
259 orphans
= ORPH_IGNORE
;
260 else if (strcmp(ti
->data
, "remove") == 0
261 || strcmp(ti
->data
, "r") == 0)
262 orphans
= ORPH_REMOVE
;
263 else if (strcmp(ti
->data
, "attach") == 0
264 || strcmp(ti
->data
, "a") == 0)
265 orphans
= ORPH_ATTACH
;
267 #ifndef AFS_NT40_ENV /* ignore options on NT */
268 if ((ti
= as
->parms
[16].items
)) { /* -syslog */
272 if ((ti
= as
->parms
[17].items
)) { /* -syslogfacility */
273 useSyslogFacility
= atoi(ti
->data
);
276 if ((ti
= as
->parms
[18].items
)) { /* -datelogs */
277 TimeStampLogFile((char *)AFSDIR_SERVER_SLVGLOG_FILEPATH
);
282 if (ti
= as
->parms
[19].items
) { /* -DontSalvage */
284 "Exiting immediately without salvage. Look into the FileLog to find volumes which really need to be salvaged!";
296 /* Note: if seenvol we initialize this as a standard volume utility: this has the
297 * implication that the file server may be running; negotations have to be made with
298 * the file server in this case to take the read write volume and associated read-only
299 * volumes off line before salvaging */
302 if (afs_winsockInit() < 0) {
303 ReportErrorEventAlt(AFSEVT_SVR_WINSOCK_INIT_FAILED
, 0,
304 AFSDIR_SALVAGER_FILE
, 0);
305 Log("Failed to initailize winsock, exiting.\n");
317 VOptDefaults(pt
, &opts
);
318 if (VInitVolumePackage2(pt
, &opts
)) {
319 Log("errors encountered initializing volume package; salvage aborted\n");
323 /* defer lock until we init volume package */
324 if (get_salvage_lock
) {
325 if (seenvol
&& AskDAFS()) /* support forceDAFS */
326 ObtainSharedSalvageLock();
332 * Ok to defer this as Exit will clean up and no real work is done
333 * init'ing volume package
337 #ifdef AFS_DEMAND_ATTACH_FS
340 "The DAFS dasalvager cannot be run with a non-DAFS fileserver. Please use 'salvager'.";
342 if (!msg
&& !as
->parms
[20].items
) {
344 "The standalone salvager cannot be run concurrently with a Demand Attach Fileserver. Please use 'salvageserver -client <partition> <volume id>' to manually schedule volume salvages with the salvageserver (new versions of 'bos salvage' automatically do this for you). Or, if you insist on using the standalone salvager, add the -forceDAFS flag to your salvager command line.";
349 "The non-DAFS salvager cannot be run with a Demand Attach Fileserver. Please use 'salvageserver -client <partition> <volume id>' to manually schedule volume salvages with the salvageserver (new versions of 'bos salvage' automatically do this for you). Or, if you insist on using the standalone salvager, run dasalvager with the -forceDAFS flag.";
366 if (myjob
.cj_number
!= NOT_CHILD
) {
369 (void)strcpy(pname
, myjob
.cj_part
);
374 for (partP
= DiskPartitionList
; partP
; partP
= partP
->next
) {
375 SalvageFileSysParallel(partP
);
377 SalvageFileSysParallel(0);
379 partP
= VGetPartition(pname
, 0);
381 Log("salvage: Unknown or unmounted partition %s; salvage aborted\n", pname
);
385 SalvageFileSys(partP
, 0);
387 /* Salvage individual volume */
388 SalvageFileSys(partP
, vid
);
396 #include "AFS_component_version_number.c"
400 main(int argc
, char **argv
)
402 struct cmd_syndesc
*ts
;
405 extern char cml_version_number
[];
409 * The following signal action for AIX is necessary so that in case of a
410 * crash (i.e. core is generated) we can include the user's data section
411 * in the core dump. Unfortunately, by default, only a partial core is
412 * generated which, in many cases, isn't too useful.
414 struct sigaction nsa
;
416 sigemptyset(&nsa
.sa_mask
);
417 nsa
.sa_handler
= SIG_DFL
;
418 nsa
.sa_flags
= SA_FULLDUMP
;
419 sigaction(SIGABRT
, &nsa
, NULL
);
420 sigaction(SIGSEGV
, &nsa
, NULL
);
423 /* Initialize directory paths */
424 if (!(initAFSDirPath() & AFSDIR_SERVER_PATHS_OK
)) {
426 ReportErrorEventAlt(AFSEVT_SVR_NO_INSTALL_DIR
, 0, argv
[0], 0);
428 fprintf(stderr
, "%s: Unable to obtain AFS server directory.\n",
433 /* Default to binary mode for fopen() */
434 _set_fmode(_O_BINARY
);
436 main_thread
= pthread_self();
437 if (spawnDatap
&& spawnDataLen
) {
438 /* This is a child per partition salvager. Don't setup log or
439 * try to lock the salvager lock.
441 if (nt_SetupPartitionSalvage(spawnDatap
, spawnDataLen
) < 0)
445 /* All entries to the log will be appended. Useful if there are
446 * multiple salvagers appending to the log.
449 CheckLogFile((char *)AFSDIR_SERVER_SLVGLOG_FILEPATH
);
451 #ifdef AFS_LINUX20_ENV
452 fcntl(fileno(logFile
), F_SETFL
, O_APPEND
); /* Isn't this redundant? */
454 fcntl(fileno(logFile
), F_SETFL
, FAPPEND
); /* Isn't this redundant? */
460 if (geteuid() != 0) {
461 printf("Salvager must be run as root.\n");
467 /* bad for normal help flag processing, but can do nada */
469 fprintf(logFile
, "%s\n", cml_version_number
);
470 LogCommandLine(argc
, argv
, "SALVAGER", SalvageVersion
, "STARTING AFS",
473 /* Get and hold a lock for the duration of the salvage to make sure
474 * that no other salvage runs at the same time. The routine
475 * VInitVolumePackage2 (called below) makes sure that a file server or
476 * other volume utilities don't interfere with the salvage.
478 get_salvage_lock
= 1;
483 ts
= cmd_CreateSyntax("initcmd", handleit
, NULL
, "initialize the program");
484 cmd_AddParm(ts
, "-partition", CMD_SINGLE
, CMD_OPTIONAL
,
485 "Name of partition to salvage");
486 cmd_AddParm(ts
, "-volumeid", CMD_SINGLE
, CMD_OPTIONAL
,
487 "Volume Id to salvage");
488 cmd_AddParm(ts
, "-debug", CMD_FLAG
, CMD_OPTIONAL
,
489 "Run in Debugging mode");
490 cmd_AddParm(ts
, "-nowrite", CMD_FLAG
, CMD_OPTIONAL
,
491 "Run readonly/test mode");
492 cmd_AddParm(ts
, "-inodes", CMD_FLAG
, CMD_OPTIONAL
,
493 "Just list affected afs inodes - debugging flag");
494 cmd_AddParm(ts
, "-force", CMD_FLAG
, CMD_OPTIONAL
, "Force full salvaging");
495 cmd_AddParm(ts
, "-oktozap", CMD_FLAG
, CMD_OPTIONAL
,
496 "Give permission to destroy bogus inodes/volumes - debugging flag");
497 cmd_AddParm(ts
, "-rootinodes", CMD_FLAG
, CMD_OPTIONAL
,
498 "Show inodes owned by root - debugging flag");
499 cmd_AddParm(ts
, "-salvagedirs", CMD_FLAG
, CMD_OPTIONAL
,
500 "Force rebuild/salvage of all directories");
501 cmd_AddParm(ts
, "-blockreads", CMD_FLAG
, CMD_OPTIONAL
,
502 "Read smaller blocks to handle IO/bad blocks");
503 cmd_AddParm(ts
, "-parallel", CMD_SINGLE
, CMD_OPTIONAL
,
504 "# of max parallel partition salvaging");
505 cmd_AddParm(ts
, "-tmpdir", CMD_SINGLE
, CMD_OPTIONAL
,
506 "Name of dir to place tmp files ");
507 cmd_AddParm(ts
, "-showlog", CMD_FLAG
, CMD_OPTIONAL
,
508 "Show log file upon completion");
509 cmd_AddParm(ts
, "-showsuid", CMD_FLAG
, CMD_OPTIONAL
,
510 "Report on suid/sgid files");
511 cmd_AddParm(ts
, "-showmounts", CMD_FLAG
, CMD_OPTIONAL
,
512 "Report on mountpoints");
513 cmd_AddParm(ts
, "-orphans", CMD_SINGLE
, CMD_OPTIONAL
,
514 "ignore | remove | attach");
516 /* note - syslog isn't avail on NT, but if we make it conditional, have
517 * to deal with screwy offsets for cmd params */
518 cmd_AddParm(ts
, "-syslog", CMD_FLAG
, CMD_OPTIONAL
,
519 "Write salvage log to syslogs");
520 cmd_AddParm(ts
, "-syslogfacility", CMD_SINGLE
, CMD_OPTIONAL
,
521 "Syslog facility number to use");
522 cmd_AddParm(ts
, "-datelogs", CMD_FLAG
, CMD_OPTIONAL
,
523 "Include timestamp in logfile filename");
525 cmd_AddParm(ts
, "-DontSalvage", CMD_FLAG
, CMD_OPTIONAL
,
526 "Don't salvage. This my be set in BosConfig to let the fileserver restart immediately after a crash. Bad volumes will be taken offline");
527 #elif defined(AFS_DEMAND_ATTACH_FS)
528 cmd_Seek(ts
, 20); /* skip DontSalvage */
529 cmd_AddParm(ts
, "-forceDAFS", CMD_FLAG
, CMD_OPTIONAL
,
530 "For Demand Attach Fileserver, permit a manual volume salvage outside of the salvageserver");
531 #endif /* FAST_RESTART */
532 cmd_Seek(ts
, 21); /* skip DontSalvage and forceDAFS if needed */
533 cmd_AddParm(ts
, "-f", CMD_FLAG
, CMD_OPTIONAL
, "Alias for -force");
534 err
= cmd_Dispatch(argc
, argv
);
536 return 0; /* not reached */