#endif
#endif
#else /* AFS_VFSINCL_ENV */
-#ifdef AFS_OSF_ENV
-#include <ufs/inode.h>
-#else /* AFS_OSF_ENV */
#if !defined(AFS_LINUX20_ENV) && !defined(AFS_XBSD_ENV) && !defined(AFS_DARWIN_ENV)
#include <sys/inode.h>
#endif
-#endif
#endif /* AFS_VFSINCL_ENV */
#endif /* AFS_SGI_ENV */
#ifdef AFS_AIX_ENV
#include <pthread.h>
#endif
-#ifdef AFS_OSF_ENV
-extern void *calloc();
-#endif
-static char *TimeStamp(time_t clock, int precision);
+#define SALV_BUFFER_SIZE 1024
+
+static char *TimeStamp(char *buffer, size_t size, time_t clock, int precision);
int debug; /* -d flag */
int PartsPerDisk = 8; /* Salvage up to 8 partitions on same disk sequentially */
int forceR = 0; /* -b flag */
int ShowLog = 0; /* -showlog flag */
+char *ShowLogFilename = NULL; /* log file name for -showlog */
int ShowSuid = 0; /* -showsuid flag */
int ShowMounts = 0; /* -showmounts flag */
int orphans = ORPH_IGNORE; /* -orphans option */
int Showmode = 0;
-
-
-#ifndef AFS_NT40_ENV
-int useSyslog = 0; /* -syslog flag */
-int useSyslogFacility = LOG_DAEMON; /* -syslogfacility option */
-#endif
+int ClientMode = 0; /* running as salvager server client */
#ifdef AFS_NT40_ENV
int canfork = 0;
int ForceSalvage; /* If salvage should occur despite the DONT_SALVAGE flag
* in the volume header */
-FILE *logFile = 0; /* one of {/usr/afs/logs,/vice/file}/SalvageLog */
-
#define ROOTINODE 2 /* Root inode of a 4.2 Unix file system
* partition */
/**
/* Forward declarations */
+static void QuietExit(int) AFS_NORETURN;
+static void SalvageShowLog(void);
static int IsVnodeOrphaned(struct SalvInfo *salvinfo, VnodeId vnode);
static int AskVolumeSummary(struct SalvInfo *salvinfo,
VolumeId singleVolumeNumber);
static void MaybeAskOnline(struct SalvInfo *salvinfo, VolumeId volumeId);
static void AskError(struct SalvInfo *salvinfo, VolumeId volumeId);
-#if defined(AFS_DEMAND_ATTACH_FS) || defined(AFS_DEMAND_ATTACH_UTIL)
+#ifdef AFS_DEMAND_ATTACH_FS
static int LockVolume(struct SalvInfo *salvinfo, VolumeId volumeId);
-#endif /* AFS_DEMAND_ATTACH_FS || AFS_DEMAND_ATTACH_UTIL */
+#endif /* AFS_DEMAND_ATTACH_FS */
/* Uniquifier stored in the Inode */
static Unique
struct job *thisjob = 0;
static int numjobs = 0;
static int jobcount = 0;
- char buf[1024];
int wstatus;
struct job *oldjob;
int startjob;
FILE *passLog;
- char logFileName[256];
int i, j, pid;
if (partP) {
numjobs++;
} else {
int fd;
+ char *filename;
+ struct logOptions logopts;
+
+ memset(&logopts, 0, sizeof(logopts));
+ logopts.lopt_dest = logDest_file;
- ShowLog = 0;
for (fd = 0; fd < 16; fd++)
close(fd);
open(OS_DIRSEP, 0);
dup2(0, 1);
dup2(0, 2);
-#ifndef AFS_NT40_ENV
- if (useSyslog) {
- openlog("salvager", LOG_PID, useSyslogFacility);
- } else
-#endif
- {
- snprintf(logFileName, sizeof logFileName, "%s.%d",
+
+ ShowLog = 0; /* Child processes do not display. */
+ if (asprintf(&filename, "%s.%d",
AFSDIR_SERVER_SLVGLOG_FILEPATH,
- jobs[startjob]->jobnumb);
- logFile = afs_fopen(logFileName, "w");
+ jobs[startjob]->jobnumb) >= 0) {
+ logopts.lopt_filename = filename;
+ OpenLog(&logopts);
+ free(filename);
}
- if (!logFile)
- logFile = stdout;
SalvageFileSys1(jobs[startjob]->partP, 0);
Exit(0);
}
} /* while ( thisjob || (!partP && numjobs > 0) ) */
- /* If waited for all jobs to complete, now collect log files and return */
-#ifndef AFS_NT40_ENV
- if (!useSyslog) /* if syslogging - no need to collect */
-#endif
+ /*
+ * If waited for all jobs to complete, now collect log files and return.
+ * No files can be collected when logging to the system log (syslog).
+ */
+ if (GetLogDest() == logDest_file) {
if (!partP) {
- for (i = 0; i < jobcount; i++) {
- snprintf(logFileName, sizeof logFileName, "%s.%d",
- AFSDIR_SERVER_SLVGLOG_FILEPATH, i);
- if ((passLog = afs_fopen(logFileName, "r"))) {
- while (fgets(buf, sizeof(buf), passLog)) {
- fputs(buf, logFile);
+ char *buf = calloc(1, SALV_BUFFER_SIZE);
+ char *logFileName;
+
+ if (buf == NULL) {
+ Log("out of memory");
+ } else {
+ for (i = 0; i < jobcount; i++) {
+ if (asprintf(&logFileName, "%s.%d",
+ AFSDIR_SERVER_SLVGLOG_FILEPATH, i) < 0) {
+ Log("out of memory");
+ break;
+ }
+ if ((passLog = afs_fopen(logFileName, "r"))) {
+ while (fgets(buf, SALV_BUFFER_SIZE, passLog)) {
+ WriteLogBuffer(buf, strlen(buf));
+ }
+ fclose(passLog);
}
- fclose(passLog);
+ (void)unlink(logFileName);
+ free(logFileName);
}
- (void)unlink(logFileName);
+ free(buf);
}
- fflush(logFile);
}
+ }
return;
}
if (!canfork || debug || Fork() == 0) {
SalvageFileSys1(partP, singleVolumeNumber);
if (canfork && !debug) {
- ShowLog = 0;
- Exit(0);
+ QuietExit(0);
}
} else
Wait("SalvageFileSys");
Abort("Raced too many times with fileserver restarts while trying to "
"checkout/lock volumes; Aborted\n");
}
-#if defined(AFS_DEMAND_ATTACH_FS) || defined(AFS_DEMAND_ATTACH_UTIL)
+#ifdef AFS_DEMAND_ATTACH_FS
if (tries > 1) {
/* unlock all previous volume locks, since we're about to lock them
* again */
VLockFileReinit(&partP->volLockFile);
}
-#endif /* AFS_DEMAND_ATTACH_FS || AFS_DEMAND_ATTACH_UTIL */
+#endif /* AFS_DEMAND_ATTACH_FS */
salvinfo->fileSysPartition = partP;
salvinfo->fileSysDevice = salvinfo->fileSysPartition->device;
#endif
if (singleVolumeNumber) {
-#if !(defined(AFS_DEMAND_ATTACH_FS) || defined(AFS_DEMAND_ATTACH_UTIL))
+#ifndef AFS_DEMAND_ATTACH_FS
/* only non-DAFS locks the partition when salvaging a single volume;
* DAFS will lock the individual volumes in the VG */
VLockPartition(partP->name);
-#endif /* !(AFS_DEMAND_ATTACH_FS || AFS_DEMAND_ATTACH_UTIL) */
+#endif /* !AFS_DEMAND_ATTACH_FS */
ForceSalvage = 1;
salvinfo->useFSYNC = 1;
AskOffline(salvinfo, singleVolumeNumber);
-#if defined(AFS_DEMAND_ATTACH_FS) || defined(AFS_DEMAND_ATTACH_UTIL)
+#ifdef AFS_DEMAND_ATTACH_FS
if (LockVolume(salvinfo, singleVolumeNumber)) {
goto retry;
}
-#endif /* AFS_DEMAND_ATTACH_FS || AFS_DEMAND_ATTACH_UTIL */
+#endif /* AFS_DEMAND_ATTACH_FS */
} else {
salvinfo->useFSYNC = 0;
if (!Testing && singleVolumeNumber) {
int foundSVN = 0;
-#if defined(AFS_DEMAND_ATTACH_FS) || defined(AFS_DEMAND_ATTACH_UTIL)
+#ifdef AFS_DEMAND_ATTACH_FS
/* unlock vol headers so the fs can attach them when we AskOnline */
VLockFileReinit(&salvinfo->fileSysPartition->volLockFile);
-#endif /* AFS_DEMAND_ATTACH_FS || AFS_DEMAND_ATTACH_UTIL */
+#endif /* AFS_DEMAND_ATTACH_FS */
/* Step through the volumeSummary list and set all volumes on-line.
* Most volumes were taken off-line in GetVolumeSummary.
goto error;
}
if (canfork && !debug) {
- ShowLog = 0;
- Exit(0);
+ QuietExit(0);
}
} else {
if (Wait("Inode summary") == -1) {
AskOffline(salvinfo, summary.header.id);
-#if defined(AFS_DEMAND_ATTACH_FS) || defined(AFS_DEMAND_ATTACH_UTIL)
+#ifdef AFS_DEMAND_ATTACH_FS
if (!badname) {
/* don't lock the volume if the header is bad, since we're
* about to delete it anyway. */
return -1;
}
}
-#endif /* AFS_DEMAND_ATTACH_FS || AFS_DEMAND_ATTACH_UTIL */
+#endif /* AFS_DEMAND_ATTACH_FS */
}
}
if (badname) {
return 0;
}
-/* Find the link table. This should be associated with the RW volume or, if
- * a RO only site, then the RO volume. For now, be cautious and hunt carefully.
+#ifdef AFS_NAMEI_ENV
+/* Find the link table. This should be associated with the RW volume, even
+ * if there is only an RO volume at this site.
*/
-Inode
+static Inode
FindLinkHandle(struct InodeSummary *isp, int nVols,
struct ViceInodeInfo *allInodes)
{
for (i = 0; i < nVols; i++) {
ip = allInodes + isp[i].index;
for (j = 0; j < isp[i].nSpecialInodes; j++) {
- if (ip[j].u.special.type == VI_LINKTABLE)
+ if (ip[j].u.special.volumeId == isp->RWvolumeId &&
+ ip[j].u.special.parentId == isp->RWvolumeId &&
+ ip[j].u.special.type == VI_LINKTABLE) {
return ip[j].inodeNumber;
+ }
}
}
return (Inode) - 1;
}
+static int
+CheckDupLinktable(struct SalvInfo *salvinfo, struct InodeSummary *isp, struct ViceInodeInfo *ip)
+{
+ afs_ino_str_t stmp;
+ if (ip->u.vnode.vnodeNumber != INODESPECIAL) {
+ /* not a linktable; process as a normal file */
+ return 0;
+ }
+ if (ip->u.special.type != VI_LINKTABLE) {
+ /* not a linktable; process as a normal file */
+ return 0;
+ }
+
+ /* make sure nothing inc/decs it */
+ ip->linkCount = 0;
+
+ if (ip->u.special.volumeId == ip->u.special.parentId) {
+ /* This is a little weird, but shouldn't break anything, and there is
+ * no known way that this can happen; just do nothing, in case deleting
+ * it would screw something up. */
+ Log("Inode %s appears to be a valid linktable for id (%u), but it's not\n",
+ PrintInode(stmp, ip->inodeNumber), ip->u.special.parentId);
+ Log("the linktable for our volume group (%u). This is unusual, since\n",
+ isp->RWvolumeId);
+ Log("there should only be one linktable per volume group. I'm leaving\n");
+ Log("it alone, just to be safe.\n");
+ return -1;
+ }
+
+ Log("Linktable %s appears to be invalid (parentid/volumeid mismatch: %u != %u)\n",
+ PrintInode(stmp, ip->inodeNumber), ip->u.special.parentId, ip->u.special.volumeId);
+ if (Testing) {
+ Log("Would have deleted linktable inode %s\n", PrintInode(stmp, ip->inodeNumber));
+ } else {
+ IHandle_t *tmpH;
+ namei_t ufs_name;
+
+ Log("Deleting linktable inode %s\n", PrintInode(stmp, ip->inodeNumber));
+ IH_INIT(tmpH, salvinfo->fileSysDevice, isp->RWvolumeId, ip->inodeNumber);
+ namei_HandleToName(&ufs_name, tmpH);
+ if (unlink(ufs_name.n_path) < 0) {
+ Log("Error %d unlinking path %s\n", errno, ufs_name.n_path);
+ }
+ }
+
+ return -1;
+}
+#endif
+
int
CreateLinkTable(struct SalvInfo *salvinfo, struct InodeSummary *isp, Inode ino)
{
if (Testing) {
IH_INIT(salvinfo->VGLinkH, salvinfo->fileSysDevice, -1, -1);
} else {
- int i, j;
- struct ViceInodeInfo *ip;
+ int i, j;
+ struct ViceInodeInfo *ip;
CreateLinkTable(salvinfo, isp, ino);
fdP = IH_OPEN(salvinfo->VGLinkH);
- /* Sync fake 1 link counts to the link table, now that it exists */
- if (fdP) {
- for (i = 0; i < nVols; i++) {
- ip = allInodes + isp[i].index;
- for (j = isp[i].nSpecialInodes; j < isp[i].nInodes; j++) {
- namei_SetLinkCount(fdP, ip[j].inodeNumber, 1, 1);
+ /* Sync fake 1 link counts to the link table, now that it exists */
+ if (fdP) {
+ for (i = 0; i < nVols; i++) {
+ ip = allInodes + isp[i].index;
+ for (j = isp[i].nSpecialInodes; j < isp[i].nInodes; j++) {
+ namei_SetLinkCount(fdP, ip[j].inodeNumber, 1, 0);
+ ip[j].linkCount = 1;
}
- }
+ }
}
}
}
int rw = (i == 0);
struct InodeSummary *lisp = &isp[i];
#ifdef AFS_NAMEI_ENV
- /* If only the RO is present on this partition, the link table
- * shows up as a RW volume special file. Need to make sure the
- * salvager doesn't try to salvage the non-existent RW.
- */
- if (rw && nVols > 1 && isp[i].nSpecialInodes == 1) {
- /* If this only special inode is the link table, continue */
- if (inodes->u.special.type == VI_LINKTABLE) {
- haveRWvolume = 0;
- continue;
+ if (rw && (nVols > 1 || isp[i].nSpecialInodes == isp[i].nInodes)) {
+ /* If nVols > 1, we have more than one vol in this volgroup, so
+ * the RW inodes we detected may just be for the linktable, and
+ * there is no actual RW volume.
+ *
+ * Additionally, if we only have linktable inodes (no other
+ * special inodes, no data inodes), there is also no actual RW
+ * volume to salvage; this is just cruft left behind by something
+ * else. In that case nVols will only be 1, though, so also
+ * perform this linktables-only check if we don't have any
+ * non-special inodes. */
+ int inode_i;
+ int all_linktables = 1;
+ for (inode_i = 0; inode_i < isp[i].nSpecialInodes; inode_i++) {
+ if (inodes[inode_i].u.special.type != VI_LINKTABLE) {
+ all_linktables = 0;
+ break;
+ }
+ }
+ if (all_linktables) {
+ /* All we have are linktable special inodes, so skip salvaging
+ * the RW; there was never an RW volume here. If we don't do
+ * this, we risk creating a new "phantom" RW that the VLDB
+ * doesn't know about, which is confusing and can cause
+ * problems. */
+ haveRWvolume = 0;
+ continue;
}
}
#endif
dec_VGLinkH = ip->linkCount - salvinfo->VGLinkH_cnt;
VGLinkH_p1 = ip->u.param[0];
continue; /* Deal with this last. */
+ } else if (CheckDupLinktable(salvinfo, isp, ip)) {
+ /* Don't touch this inode; CheckDupLinktable has handled it */
+ continue;
}
#endif
if (ip->linkCount != 0 && TraceBadLinkCounts) {
TraceBadLinkCounts--; /* Limit reports, per volume */
Log("#### DEBUG #### Link count incorrect by %d; inode %s, size %llu, p=(%u,%u,%u,%u)\n", ip->linkCount, PrintInode(stmp, ip->inodeNumber), (afs_uintmax_t) ip->byteCount, ip->u.param[0], ip->u.param[1], ip->u.param[2], ip->u.param[3]); /* VolumeId in param */
}
+
+ /* If ip->linkCount is non-zero at this point, then the linkcount
+ * for the inode on disk is wrong. Initially linkCount is set to
+ * the actual link count of the inode on disk, and then we (the
+ * salvager) decrement it for every reference to that inode that we
+ * find. So if linkCount is still positive by this point, it means
+ * that the linkcount on disk is too high, so we should DEC the
+ * inode. If linkCount is negative, it means the linkcount is too
+ * low, so we should INC the inode.
+ *
+ * If we get an error while INC'ing or DEC'ing, that's a little
+ * odd and indicates a bug, but try to continue anyway, so the
+ * volume may still be made accessible. */
while (ip->linkCount > 0) {
- /* below used to assert, not break */
if (!Testing) {
if (IH_DEC(salvinfo->VGLinkH, ip->inodeNumber, ip->u.param[0])) {
Log("idec failed. inode %s errno %d\n",
ip->linkCount--;
}
while (ip->linkCount < 0) {
- /* these used to be asserts */
if (!Testing) {
if (IH_INC(salvinfo->VGLinkH, ip->inodeNumber, ip->u.param[0])) {
Log("iinc failed. inode %s errno %d\n",
IH_RELEASE(salvinfo->VGLinkH);
if (canfork && !debug) {
- ShowLog = 0;
- Exit(0);
+ QuietExit(0);
}
}
if (sp->inodeType == VI_VOLINFO) {
salvinfo->VolInfo = header.volumeInfo;
if (check) {
- char update[25];
+ char update[64];
+ char buffer[64];
if (salvinfo->VolInfo.updateDate) {
- strcpy(update, TimeStamp(salvinfo->VolInfo.updateDate, 0));
+ strcpy(update, TimeStamp(buffer, sizeof(buffer), salvinfo->VolInfo.updateDate, 0));
if (!Showmode)
Log("%s (%" AFS_VOLID_FMT ") %supdated %s\n", salvinfo->VolInfo.name,
afs_printable_VolumeId_lu(salvinfo->VolInfo.id),
(Testing ? "it would have been " : ""), update);
} else {
- strcpy(update, TimeStamp(salvinfo->VolInfo.creationDate, 0));
+ strcpy(update, TimeStamp(buffer, sizeof(buffer), salvinfo->VolInfo.creationDate, 0));
if (!Showmode)
Log("%s (%" AFS_VOLID_FMT ") not updated (created %s)\n",
salvinfo->VolInfo.name, afs_printable_VolumeId_lu(salvinfo->VolInfo.id), update);
vnodeIndexOffset(vcp, dir->vnodeNumber), (char *)&vnode,
sizeof(vnode));
opr_Assert(lcode == sizeof(vnode));
-#if 0
-#ifdef AFS_NT40_ENV
- nt_sync(salvinfo->fileSysDevice);
-#else
- sync(); /* this is slow, but hopefully rarely called. We don't have
- * an open FD on the file itself to fsync.
- */
-#endif
-#else
- salvinfo->vnodeInfo[vLarge].handle->ih_synced = 1;
-#endif
+ IH_CONDSYNC(salvinfo->vnodeInfo[vLarge].handle);
+
/* make sure old directory file is really closed */
fdP = IH_OPEN(dir->dirHandle.dirh_handle);
FDH_REALLYCLOSE(fdP);
* or if the directory is orphaned.
*/
if (!vnodeEssence->unique || (vnodeEssence->unique) != unique) {
- if (!vnodeEssence->unique
- && ((strcmp(name, "..") == 0) || (strcmp(name, ".") == 0))) {
- /* This is an orphaned directory. Don't delete the . or ..
- * entry. Otherwise, it will get created in the next
- * salvage and deleted again here. So Just skip it.
- */
- return 0;
- }
-
todelete = ((!vnodeEssence->unique || dirOrphaned) ? 1 : 0);
- if (!Showmode) {
- Log("dir vnode %u: %s" OS_DIRSEP "%s (vnode %u): unique changed from %u to %u %s\n", dir->vnodeNumber, (dir->name ? dir->name : "??"), name, vnodeNumber, unique, vnodeEssence->unique, (!todelete ? "" : (Testing ? "-- would have deleted" : "-- deleted")));
- }
- if (!Testing) {
- AFSFid fid;
- fid.Vnode = vnodeNumber;
- fid.Unique = vnodeEssence->unique;
- CopyOnWrite(salvinfo, dir);
- opr_Verify(afs_dir_Delete(&dir->dirHandle, name) == 0);
- if (!todelete)
- opr_Verify(afs_dir_Create(&dir->dirHandle, name, &fid) == 0);
+ if (todelete
+ && ((strcmp(name, "..") == 0) || (strcmp(name, ".") == 0))) {
+ if (dirOrphaned) {
+ /* This is an orphaned directory. Don't delete the . or ..
+ * entry. Otherwise, it will get created in the next
+ * salvage and deleted again here. So Just skip it.
+ * */
+ return 0;
+ }
+ /* (vnodeEssence->unique == 0 && ('.' || '..'));
+ * Entries arriving here should be deleted, but the directory
+ * is not orphaned. Therefore, the entry must be pointing at
+ * the wrong vnode. Skip the 'else' clause and fall through;
+ * the code below will repair the entry so it correctly points
+ * at the vnode of the current directory (if '.') or the parent
+ * directory (if '..'). */
+ } else {
+ if (!Showmode) {
+ Log("dir vnode %u: %s" OS_DIRSEP "%s (vnode %u): unique changed from %u to %u %s\n",
+ dir->vnodeNumber, (dir->name ? dir->name : "??"), name, vnodeNumber, unique,
+ vnodeEssence->unique, (!todelete ? "" : (Testing ? "-- would have deleted" : "-- deleted")));
+ }
+ if (!Testing) {
+ AFSFid fid;
+ fid.Vnode = vnodeNumber;
+ fid.Unique = vnodeEssence->unique;
+ CopyOnWrite(salvinfo, dir);
+ opr_Verify(afs_dir_Delete(&dir->dirHandle, name) == 0);
+ if (!todelete)
+ opr_Verify(afs_dir_Create(&dir->dirHandle, name, &fid) == 0);
+ }
+ if (todelete)
+ return 0; /* no need to continue */
}
- if (todelete)
- return 0; /* no need to continue */
}
if (strcmp(name, ".") == 0) {
/* Make sure the uniquifer is big enough: maxunique is the real maxUniquifier */
if (volHeader.uniquifier < (maxunique + 1)) {
if (!Showmode)
- Log("Volume uniquifier is too low; fixed\n");
+ Log("Volume uniquifier %u is too low (max uniq %u); fixed\n", volHeader.uniquifier, maxunique);
/* Plus 2,000 in case there are workstations out there with
* cached vnodes that have since been deleted
*/
}
#endif /* FSSYNC_BUILD_CLIENT */
-#if defined(AFS_DEMAND_ATTACH_FS) || defined(AFS_DEMAND_ATTACH_UTIL)
+#ifdef AFS_DEMAND_ATTACH_FS
if (!salvinfo->useFSYNC) {
/* A volume's contents have changed, but the fileserver will not
* break callbacks on the volume until it tries to load the vol
volHeader.inUse = 0; /* clear flag indicating inUse@last crash */
volHeader.needsSalvaged = 0; /* clear 'damaged' flag */
volHeader.inService = 1; /* allow service again */
- volHeader.needsCallback = (salvinfo->VolumeChanged != 0);
+ if (salvinfo->VolumeChanged) {
+ volHeader.needsCallback = 1;
+ volHeader.updateDate = time(NULL);
+ } else {
+ volHeader.needsCallback = 0;
+ }
volHeader.dontSalvage = DONT_SALVAGE;
salvinfo->VolumeChanged = 0;
if (!Testing) {
}
}
-#if defined(AFS_DEMAND_ATTACH_FS) || defined(AFS_DEMAND_ATTACH_UTIL)
+#ifdef AFS_DEMAND_ATTACH_FS
/**
* Locks a volume on disk for salvaging.
*
return 0;
}
-#endif /* AFS_DEMAND_ATTACH_FS || AFS_DEMAND_ATTACH_UTIL */
+#endif /* AFS_DEMAND_ATTACH_FS */
static void
AskError(struct SalvInfo *salvinfo, VolumeId volumeId)
Log("AskOffline: fssync protocol mismatch (bad command word '%d'); salvage aborting.\n",
FSYNC_VOL_OFF);
if (AskDAFS()) {
-#if defined(AFS_DEMAND_ATTACH_FS) || defined(AFS_DEMAND_ATTACH_UTIL)
+#ifdef AFS_DEMAND_ATTACH_FS
Log("AskOffline: please make sure dafileserver, davolserver, salvageserver and dasalvager binaries are same version.\n");
#else
Log("AskOffline: fileserver is DAFS but we are not.\n");
#endif
} else {
-#if defined(AFS_DEMAND_ATTACH_FS) || defined(AFS_DEMAND_ATTACH_UTIL)
+#ifdef AFS_DEMAND_ATTACH_FS
Log("AskOffline: fileserver is not DAFS but we are.\n");
#else
Log("AskOffline: please make sure fileserver, volserver and salvager binaries are same version.\n");
Log("AskOnline: fssync protocol mismatch (bad command word '%d')\n",
FSYNC_VOL_DONE);
if (AskDAFS()) {
-#if defined(AFS_DEMAND_ATTACH_FS) || defined(AFS_DEMAND_ATTACH_UTIL)
+#ifdef AFS_DEMAND_ATTACH_FS
Log("AskOnline: please make sure dafileserver, davolserver, salvageserver and dasalvager binaries are same version.\n");
#else
Log("AskOnline: fileserver is DAFS but we are not.\n");
#endif
} else {
-#if defined(AFS_DEMAND_ATTACH_FS) || defined(AFS_DEMAND_ATTACH_UTIL)
+#ifdef AFS_DEMAND_ATTACH_FS
Log("AskOnline: fileserver is not DAFS but we are.\n");
#else
Log("AskOnline: please make sure fileserver, volserver and salvager binaries are same version.\n");
return f;
}
-void
-Exit(int code)
+static void
+QuietExit(int code)
{
- if (ShowLog)
- showlog();
-
#ifdef AFS_DEMAND_ATTACH_FS
if (programType == salvageServer) {
/* release all volume locks before closing down our SYNC channels.
#endif
}
+void
+Exit(int code)
+{
+ SalvageShowLog();
+ QuietExit(code);
+}
+
+
int
Wait(char *prog)
{
}
static char *
-TimeStamp(time_t clock, int precision)
+TimeStamp(char *buffer, size_t size, time_t clock, int precision)
{
struct tm *lt;
- static char timestamp[20];
+ size_t nbytes;
+
lt = localtime(&clock);
if (precision)
- (void)strftime(timestamp, 20, "%m/%d/%Y %H:%M:%S", lt);
+ nbytes = strftime(buffer, size, "%m/%d/%Y %H:%M:%S", lt);
else
- (void)strftime(timestamp, 20, "%m/%d/%Y %H:%M", lt);
- return timestamp;
+ nbytes = strftime(buffer, size, "%m/%d/%Y %H:%M", lt);
+ if (nbytes == 0)
+ memset(buffer, 0, size);
+ return buffer;
}
-void
-CheckLogFile(char * log_path)
-{
- char oldSlvgLog[AFSDIR_PATH_MAX];
-
-#ifndef AFS_NT40_ENV
- if (useSyslog) {
- ShowLog = 0;
- return;
- }
-#endif
-
- strcpy(oldSlvgLog, log_path);
- strcat(oldSlvgLog, ".old");
- if (!logFile) {
- rk_rename(log_path, oldSlvgLog);
- logFile = afs_fopen(log_path, "a");
-
- if (!logFile) { /* still nothing, use stdout */
- logFile = stdout;
- ShowLog = 0;
- }
-#ifndef AFS_NAMEI_ENV
- AFS_DEBUG_IOPS_LOG(logFile);
-#endif
- }
-}
-
-#ifndef AFS_NT40_ENV
-void
-TimeStampLogFile(char * log_path)
-{
- char stampSlvgLog[AFSDIR_PATH_MAX];
- struct tm *lt;
- time_t now;
-
- now = time(0);
- lt = localtime(&now);
- snprintf(stampSlvgLog, sizeof stampSlvgLog,
- "%s.%04d-%02d-%02d.%02d:%02d:%02d", log_path,
- lt->tm_year + 1900, lt->tm_mon + 1, lt->tm_mday, lt->tm_hour,
- lt->tm_min, lt->tm_sec);
-
- /* try to link the logfile to a timestamped filename */
- /* if it fails, oh well, nothing we can do */
- link(log_path, stampSlvgLog);
-}
-#endif
-
-void
-showlog(void)
+static void
+SalvageShowLog(void)
{
char line[256];
+ char *filename;
+ FILE *logFile;
-#ifndef AFS_NT40_ENV
- if (useSyslog) {
- printf("Can't show log since using syslog.\n");
- fflush(stdout);
- return;
- }
-#endif
-
- if (logFile) {
- rewind(logFile);
- fclose(logFile);
+ if (ShowLog == 0 || ClientMode) {
+ return; /* nothing to do */
}
+ filename = strdup(GetLogFilename());
+ opr_Assert(filename != NULL);
+ CloseLog();
- logFile = afs_fopen(AFSDIR_SERVER_SLVGLOG_FILEPATH, "r");
-
+ logFile = afs_fopen(filename, "r");
if (!logFile)
- printf("Can't read %s, exiting\n", AFSDIR_SERVER_SLVGLOG_FILEPATH);
+ printf("Can't read %s, exiting\n", ShowLogFilename);
else {
- rewind(logFile);
while (fgets(line, sizeof(line), logFile))
printf("%s", line);
fflush(stdout);
}
+ free(filename);
+}
+
+static void
+vLog(const char *format, va_list args)
+{
+ if (!ClientMode) {
+ vFSLog(format, args);
+ } else {
+ struct timeval now;
+ char buffer[64];
+
+ gettimeofday(&now, NULL);
+ fprintf(stderr, "%s ", TimeStamp(buffer, sizeof(buffer), now.tv_sec, 1));
+ vfprintf(stderr, format, args);
+ fflush(stderr);
+ }
}
void
Log(const char *format, ...)
{
- struct timeval now;
- char tmp[1024];
va_list args;
va_start(args, format);
- vsnprintf(tmp, sizeof tmp, format, args);
+ vLog(format, args);
va_end(args);
-#ifndef AFS_NT40_ENV
- if (useSyslog) {
- syslog(LOG_INFO, "%s", tmp);
- } else
-#endif
- if (logFile) {
- gettimeofday(&now, NULL);
- fprintf(logFile, "%s %s", TimeStamp(now.tv_sec, 1), tmp);
- fflush(logFile);
- }
}
void
Abort(const char *format, ...)
{
va_list args;
- char tmp[1024];
va_start(args, format);
- vsnprintf(tmp, sizeof tmp, format, args);
+ vLog(format, args);
va_end(args);
-#ifndef AFS_NT40_ENV
- if (useSyslog) {
- syslog(LOG_INFO, "%s", tmp);
- } else
-#endif
- if (logFile) {
- fprintf(logFile, "%s", tmp);
- fflush(logFile);
- if (ShowLog)
- showlog();
- }
-
+ SalvageShowLog();
if (debug)
abort();
- Exit(1);
+ QuietExit(1);
}
char *
nt_SetupPartitionSalvage(void *datap, int len)
{
childJob_t *jobp = (childJob_t *) datap;
- char logname[AFSDIR_PATH_MAX];
+ char *logname;
if (len != sizeof(childJob_t))
return -1;
myjob = *jobp;
/* Open logFile */
- (void)sprintf(logname, "%s.%d", AFSDIR_SERVER_SLVGLOG_FILEPATH,
- myjob.cj_number);
- logFile = afs_fopen(logname, "w");
- if (!logFile)
- logFile = stdout;
+ if (asprintf(&logname, "%s.%d", AFSDIR_SERVER_SLVGLOG_FILEPATH,
+ myjob.cj_number) < 0)
+ return -1;
+ OpenLog(logname);
+ free(logname);
return 0;
}