#include <afs/procmgmt.h>
#include <roken.h>
-#ifndef AFS_NT40_ENV
-#include <sys/param.h>
-#include <sys/file.h>
-#ifndef ITIMER_REAL
-#include <sys/time.h>
-#endif /* ITIMER_REAL */
+#ifdef HAVE_SYS_FILE_H
+# include <sys/file.h>
#endif
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <dirent.h>
-#include <sys/stat.h>
-#include <time.h>
-#include <errno.h>
+
#ifdef AFS_NT40_ENV
-#include <io.h>
#include <WINNT/afsevent.h>
#endif
#ifndef WCOREDUMP
#define WCOREDUMP(x) ((x) & 0200)
#endif
-#include <rx/xdr.h>
+#include <afs/opr.h>
+#ifdef AFS_PTHREAD_ENV
+# include <opr/lock.h>
+#endif
+
#include <afs/afsint.h>
-#include <afs/afs_assert.h>
#if !defined(AFS_SGI_ENV) && !defined(AFS_NT40_ENV)
#if defined(AFS_VFSINCL_ENV)
#include <sys/vnode.h>
#ifdef AFS_OSF_ENV
#include <ufs/inode.h>
#else /* AFS_OSF_ENV */
-#if !defined(AFS_LINUX20_ENV) && !defined(AFS_XBSD_ENV) && !defined(AFS_ARM_DARWIN_ENV)
+#if !defined(AFS_LINUX20_ENV) && !defined(AFS_XBSD_ENV) && !defined(AFS_DARWIN_ENV)
#include <sys/inode.h>
#endif
#endif
#include <sys/lockf.h>
#else
#ifdef AFS_HPUX_ENV
-#include <unistd.h>
#include <checklist.h>
#else
#if defined(AFS_SGI_ENV)
-#include <unistd.h>
-#include <fcntl.h>
#include <mntent.h>
#else
#if defined(AFS_SUN_ENV) || defined(AFS_SUN5_ENV)
#ifdef AFS_SUN5_ENV
-#include <unistd.h>
#include <sys/mnttab.h>
#include <sys/mntent.h>
#else
#endif /* AFS_HPUX_ENV */
#endif
#endif
-#include <fcntl.h>
#ifndef AFS_NT40_ENV
#include <afs/osi_inode.h>
#endif
#include <afs/dir.h>
#include <afs/afsutil.h>
#include <afs/fileutil.h>
-#include <afs/procmgmt.h> /* signal(), kill(), wait(), etc. */
-#ifndef AFS_NT40_ENV
-#include <syslog.h>
-#endif
+#include <rx/rx_queue.h>
#include "nfs.h"
#include "lwp.h"
#include "volume.h"
#include "partition.h"
#include "daemon_com.h"
+#include "daemon_com_inline.h"
#include "fssync.h"
+#include "fssync_inline.h"
#include "volume_inline.h"
#include "salvsync.h"
#include "viceinode.h"
#include <pthread.h>
#endif
+#define SALV_BUFFER_SIZE 1024
+
#ifdef AFS_OSF_ENV
extern void *calloc();
#endif
-static char *TimeStamp(time_t clock, int precision);
+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 */
/**
struct SalvInfo {
Device fileSysDevice; /**< The device number of the current partition
* being salvaged */
- char fileSysPath[8]; /**< The path of the mounted partition currently
+ char fileSysPath[9]; /**< The path of the mounted partition currently
* being salvaged, i.e. the directory containing
* the volume headers */
char *fileSysPathName; /**< NT needs this to make name pretty log. */
/* 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);
#ifdef AFS_DEMAND_ATTACH_FS
static int LockVolume(struct SalvInfo *salvinfo, VolumeId volumeId);
FILE *mntfp;
struct mntent *mntent;
- osi_Assert(mntfp = setmntent(MOUNTED, "r"));
+ opr_Verify(mntfp = setmntent(MOUNTED, "r"));
while (mntent = getmntent(mntfp)) {
if (!strcmp(part, mntent->mnt_dir))
break;
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) {
/* We have a partition to salvage. Copy it into thisjob */
- thisjob = (struct job *)malloc(sizeof(struct job));
+ thisjob = calloc(1, sizeof(struct job));
if (!thisjob) {
Log("Can't salvage '%s'. Not enough memory\n", partP->name);
return;
}
- memset(thisjob, 0, sizeof(struct job));
thisjob->partP = partP;
thisjob->jobnumb = jobcount;
jobcount++;
* job to finish. When it's done, clean up after it.
*/
pid = wait(&wstatus);
- osi_Assert(pid != -1);
+ opr_Assert(pid != -1);
for (j = 0; j < numjobs; j++) { /* Find which job it is */
if (pid == jobs[j]->pid)
break;
}
- osi_Assert(j < numjobs);
+ opr_Assert(j < numjobs);
if (WCOREDUMP(wstatus)) { /* Say if the job core dumped */
Log("Salvage of %s core dumped!\n", jobs[j]->partP->name);
}
numjobs++;
} else {
int fd;
+ char *logFileName;
- 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
- {
- (void)afs_snprintf(logFileName, sizeof logFileName,
- "%s.%d",
- AFSDIR_SERVER_SLVGLOG_FILEPATH,
- jobs[startjob]->jobnumb);
- logFile = afs_fopen(logFileName, "w");
+
+ ShowLog = 0; /* Child processes do not display. */
+ if (asprintf(&logFileName, "%s.%d",
+ AFSDIR_SERVER_SLVGLOG_FILEPATH,
+ jobs[startjob]->jobnumb) >= 0) {
+ OpenLog(logFileName);
+ free(logFileName);
}
- if (!logFile)
- logFile = stdout;
SalvageFileSys1(jobs[startjob]->partP, 0);
Exit(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 */
+ if (!serverLogSyslog) /* if syslogging - no need to collect */
#endif
if (!partP) {
- for (i = 0; i < jobcount; i++) {
- (void)afs_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;
}
- fclose(passLog);
+ if ((passLog = afs_fopen(logFileName, "r"))) {
+ while (fgets(buf, SALV_BUFFER_SIZE, passLog)) {
+ WriteLogBuffer(buf, strlen(buf));
+ }
+ 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");
DIR *dirp;
struct dirent *dp;
- osi_Assert((dirp = opendir(salvinfo->fileSysPath)) != NULL);
+ opr_Verify((dirp = opendir(salvinfo->fileSysPath)) != NULL);
while ((dp = readdir(dirp))) {
if (!strncmp(dp->d_name, "salvage.inodes.", 15)
|| !strncmp(dp->d_name, "salvage.temp.", 13)) {
OS_SEEK(salvinfo->inodeFd, 0L, SEEK_SET);
if (ListInodeOption) {
PrintInodeList(salvinfo);
+ if (singleVolumeNumber) {
+ /* We've checked out the volume from the fileserver, and we need
+ * to give it back. We don't know if the volume exists or not,
+ * so we don't know whether to AskOnline or not. Try to determine
+ * if the volume exists by trying to read the volume header, and
+ * AskOnline if it is readable. */
+ MaybeAskOnline(salvinfo, singleVolumeNumber);
+ }
return;
}
/* enumerate volumes in the partition.
goto retry;
}
+ if (singleVolumeNumber) {
+ /* If we delete a volume during the salvage, we indicate as such by
+ * setting the volsummary->deleted field. We need to know if we
+ * deleted a volume or not in order to know which volumes to bring
+ * back online after the salvage. If we fork, we will lose this
+ * information, since volsummary->deleted will not get set in the
+ * parent. So, don't fork. */
+ canfork = 0;
+ }
+
for (i = j = 0, vsp = salvinfo->volumeSummaryp, esp = vsp + salvinfo->nVolumes;
i < salvinfo->nVolumesInInodeFile; i = j) {
VolumeId rwvid = salvinfo->inodeSummary[i].RWvolumeId;
* If there is one here that is not in the inode volume list,
* delete it now. */
for (; vsp < esp && (vsp->header.parent < rwvid); vsp++) {
- if (vsp->fileName)
+ if (vsp->unused)
DeleteExtraVolumeHeaderFile(salvinfo, vsp);
}
/* Now match up the volume summary info from the root directory with the
for (tsp = vsp; tsp < esp && (tsp->header.parent == rwvid); tsp++) {
if (tsp->header.id == vid) {
salvinfo->inodeSummary[j].volSummary = tsp;
- tsp->fileName = 0;
+ tsp->unused = 0;
break;
}
}
/* Salvage the group of volumes (several read-only + 1 read/write)
* starting with the current read-only volume we're looking at.
*/
- SalvageVolumeGroup(salvinfo, &salvinfo->inodeSummary[i], j - i);
+#ifdef AFS_NT40_ENV
+ nt_SalvageVolumeGroup(salvinfo, &salvinfo->inodeSummary[i], j - i);
+#else
+ DoSalvageVolumeGroup(salvinfo, &salvinfo->inodeSummary[i], j - i);
+#endif /* AFS_NT40_ENV */
+
}
/* Delete any additional volumes that were listed in the partition but which didn't have any corresponding inodes */
for (; vsp < esp; vsp++) {
- if (vsp->fileName)
+ if (vsp->unused)
DeleteExtraVolumeHeaderFile(salvinfo, vsp);
}
DeleteExtraVolumeHeaderFile(struct SalvInfo *salvinfo, struct VolumeSummary *vsp)
{
char path[64];
- sprintf(path, "%s" OS_DIRSEP "%s", salvinfo->fileSysPath, vsp->fileName);
+ char filename[VMAXPATHLEN];
+
+ if (vsp->deleted) {
+ return;
+ }
+
+ VolumeExternalName_r(vsp->header.id, filename, sizeof(filename));
+ sprintf(path, "%s" OS_DIRSEP "%s", salvinfo->fileSysPath, filename);
if (!Showmode)
Log("The volume header file %s is not associated with any actual data (%sdeleted)\n", path, (Testing ? "would have been " : ""));
afs_int32 code;
code = VDestroyVolumeDiskHeader(salvinfo->fileSysPartition, vsp->header.id, vsp->header.parent);
if (code) {
- Log("Error %ld destroying volume disk header for volume %lu\n",
+ Log("Error %ld destroying volume disk header for volume %" AFS_VOLID_FMT "\n",
afs_printable_int32_ld(code),
- afs_printable_uint32_lu(vsp->header.id));
+ afs_printable_VolumeId_lu(vsp->header.id));
}
- /* make sure we actually delete the fileName file; ENOENT
+ /* make sure we actually delete the header file; ENOENT
* is fine, since VDestroyVolumeDiskHeader probably already
* unlinked it */
if (unlink(path) && errno != ENOENT) {
}
vsp->deleted = 1;
}
- vsp->fileName = 0;
}
int
}
int
-OnlyOneVolume(struct ViceInodeInfo *inodeinfo, afs_uint32 singleVolumeNumber, void *rock)
+OnlyOneVolume(struct ViceInodeInfo *inodeinfo, VolumeId singleVolumeNumber, void *rock)
{
if (inodeinfo->u.vnode.vnodeNumber == INODESPECIAL)
return (inodeinfo->u.special.parentId == singleVolumeNumber);
char *part = salvinfo->fileSysPath;
char *tdir;
int i;
+ int retcode = 0;
+ int deleted = 0;
afs_sfsize_t st_size;
/* This file used to come from vfsck; cobble it up ourselves now... */
singleVolumeNumber, &forceSal, forceR, wpath, NULL)) < 0) {
if (err == -2) {
Log("*** I/O error %d when writing a tmp inode file; Not salvaged %s ***\nIncrease space on partition or use '-tmpdir'\n", errno, dev);
- return -1;
+ retcode = -1;
+ goto error;
}
Abort("Unable to get inodes for \"%s\"; not salvaged\n", dev);
}
(void)_putenv("TMP="); /* If "TMP" is set, then that overrides tdir. */
(void)strcpy(summaryFileName, _tempnam(tdir, "salvage.temp."));
#else
- (void)afs_snprintf(summaryFileName, sizeof summaryFileName,
- "%s" OS_DIRSEP "salvage.temp.%d", tdir, getpid());
+ snprintf(summaryFileName, sizeof summaryFileName,
+ "%s" OS_DIRSEP "salvage.temp.%d", tdir, getpid());
#endif
summaryFile = OS_OPEN(summaryFileName, O_RDWR|O_APPEND|O_CREAT, 0666);
if (summaryFile == INVALID_FD) {
else {
struct VolumeSummary *vsp;
int i;
+ int foundSVN = 0;
GetVolumeSummary(salvinfo, singleVolumeNumber);
for (i = 0, vsp = salvinfo->volumeSummaryp; i < salvinfo->nVolumes; i++) {
- if (vsp->fileName)
+ if (vsp->unused) {
+ if (vsp->header.id == singleVolumeNumber) {
+ foundSVN = 1;
+ }
DeleteExtraVolumeHeaderFile(salvinfo, vsp);
+ }
+ }
+
+ if (!foundSVN) {
+ if (Testing) {
+ MaybeAskOnline(salvinfo, singleVolumeNumber);
+ } else {
+ /* make sure we get rid of stray .vol headers, even if
+ * they're not in our volume summary (might happen if
+ * e.g. something else created them and they're not in the
+ * fileserver VGC) */
+ VDestroyVolumeDiskHeader(salvinfo->fileSysPartition,
+ singleVolumeNumber, 0 /*parent*/);
+ AskDelete(salvinfo, singleVolumeNumber);
+ }
}
}
Log("%s vice inodes on %s; not salvaged\n",
singleVolumeNumber ? "No applicable" : "No", dev);
- return -1;
+ retcode = -1;
+ deleted = 1;
+ goto error;
}
- ip = (struct ViceInodeInfo *)malloc(nInodes*sizeof(struct ViceInodeInfo));
+ ip = malloc(nInodes*sizeof(struct ViceInodeInfo));
if (ip == NULL) {
OS_CLOSE(summaryFile);
Abort
if (OS_WRITE(summaryFile, &summary, sizeof(summary)) != sizeof(summary)) {
Log("Difficulty writing summary file (errno = %d); %s not salvaged\n", errno, dev);
OS_CLOSE(summaryFile);
- return -1;
+ retcode = -1;
+ goto error;
}
summary.index += (summary.nInodes);
nInodes -= summary.nInodes;
if (OS_SYNC(summaryFile) == -1) {
Log("Unable to write summary file (errno = %d); %s not salvaged\n", errno, dev);
OS_CLOSE(summaryFile);
- return -1;
+ retcode = -1;
+ goto error;
}
if (canfork && !debug) {
- ShowLog = 0;
- Exit(0);
+ QuietExit(0);
}
} else {
if (Wait("Inode summary") == -1) {
}
st_size = OS_SIZE(summaryFile);
- osi_Assert(st_size >= 0);
+ opr_Assert(st_size >= 0);
if (st_size != 0) {
int ret;
- salvinfo->inodeSummary = (struct InodeSummary *)malloc(st_size);
- osi_Assert(salvinfo->inodeSummary != NULL);
+ salvinfo->inodeSummary = malloc(st_size);
+ opr_Assert(salvinfo->inodeSummary != NULL);
/* For GNU we need to do lseek to get the file pointer moved. */
- osi_Assert(OS_SEEK(summaryFile, 0, SEEK_SET) == 0);
+ opr_Assert(OS_SEEK(summaryFile, 0, SEEK_SET) == 0);
ret = OS_READ(summaryFile, salvinfo->inodeSummary, st_size);
- osi_Assert(ret == st_size);
+ opr_Assert(ret == st_size);
}
salvinfo->nVolumesInInodeFile = st_size / sizeof(struct InodeSummary);
for (i = 0; i < salvinfo->nVolumesInInodeFile; i++) {
}
Log("%d nVolumesInInodeFile %lu \n",salvinfo->nVolumesInInodeFile,(unsigned long)st_size);
OS_CLOSE(summaryFile);
- return 0;
+
+ error:
+ if (retcode && singleVolumeNumber && !deleted) {
+ AskError(salvinfo, singleVolumeNumber);
+ }
+
+ return retcode;
}
/* Comparison routine for volume sort.
}
if (code) {
- Log("fileserver refused VGCQuery request for volume %lu on "
+ Log("fileserver refused VGCQuery request for volume %" AFS_VOLID_FMT " on "
"partition %s, code %ld reason %ld\n",
- afs_printable_uint32_lu(singleVolumeNumber),
+ afs_printable_VolumeId_lu(singleVolumeNumber),
salvinfo->fileSysPartition->name,
afs_printable_int32_ld(code),
afs_printable_int32_ld(res.hdr.reason));
}
if (q_res.rw != singleVolumeNumber) {
- Log("fileserver requested salvage of clone %lu; scheduling salvage of volume group %lu...\n",
- afs_printable_uint32_lu(singleVolumeNumber),
- afs_printable_uint32_lu(q_res.rw));
+ Log("fileserver requested salvage of clone %" AFS_VOLID_FMT "; scheduling salvage of volume group %" AFS_VOLID_FMT "...\n",
+ afs_printable_VolumeId_lu(singleVolumeNumber),
+ afs_printable_VolumeId_lu(q_res.rw));
#ifdef SALVSYNC_BUILD_CLIENT
if (SALVSYNC_LinkVolume(q_res.rw,
singleVolumeNumber,
}
salvinfo->volumeSummaryp = calloc(VOL_VG_MAX_VOLS, sizeof(struct VolumeSummary));
- osi_Assert(salvinfo->volumeSummaryp != NULL);
+ opr_Assert(salvinfo->volumeSummaryp != NULL);
salvinfo->nVolumes = 0;
vsp = salvinfo->volumeSummaryp;
DiskToVolumeHeader(&vsp->header, &diskHdr);
VolumeExternalName_r(q_res.children[i], name, sizeof(name));
- vsp->fileName = ToString(name);
+ vsp->unused = 1;
salvinfo->nVolumes++;
vsp++;
}
params = (struct SalvageScanParams *)rock;
+ memset(&summary, 0, sizeof(summary));
+
singleVolumeNumber = params->singleVolumeNumber;
salvinfo = params->salvinfo;
if (programType == salvageServer) {
#ifdef SALVSYNC_BUILD_CLIENT
- Log("fileserver requested salvage of clone %u; scheduling salvage of volume group %u...\n",
- summary.header.id, summary.header.parent);
+ Log("fileserver requested salvage of clone %" AFS_VOLID_FMT "; scheduling salvage of volume group %" AFS_VOLID_FMT "...\n",
+ afs_printable_VolumeId_lu(summary.header.id),
+ afs_printable_VolumeId_lu(summary.header.parent));
if (SALVSYNC_LinkVolume(summary.header.parent,
summary.header.id,
dp->name,
Exit(SALSRV_EXIT_VOLGROUP_LINK);
} else {
- Log("%u is a read-only volume; not salvaged\n",
- singleVolumeNumber);
+ Log("%" AFS_VOLID_FMT " is a read-only volume; not salvaged\n",
+ afs_printable_VolumeId_lu(singleVolumeNumber));
Exit(1);
}
}
base = name;
}
- (void)afs_snprintf(nameShouldBe, sizeof nameShouldBe,
- VFORMAT, afs_printable_uint32_lu(summary.header.id));
+ snprintf(nameShouldBe, sizeof nameShouldBe,
+ VFORMAT, afs_printable_VolumeId_lu(summary.header.id));
if (strcmp(nameShouldBe, base)) {
return 1;
}
- summary.fileName = ToString(base);
+ summary.unused = 1;
params->nVolumes++;
if (params->nVolumes > params->totalVolumes) {
}
salvinfo->volumeSummaryp = calloc(nvols, sizeof(struct VolumeSummary));
- osi_Assert(salvinfo->volumeSummaryp != NULL);
+ opr_Assert(salvinfo->volumeSummaryp != NULL);
params.singleVolumeNumber = singleVolumeNumber;
params.vsp = salvinfo->volumeSummaryp;
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 (!VALID_INO(ino))
ino =
- IH_CREATE(NULL, salvinfo->fileSysDevice, salvinfo->fileSysPath, 0, isp->volumeId,
+ IH_CREATE(NULL, salvinfo->fileSysDevice, salvinfo->fileSysPath, 0, isp->RWvolumeId,
INODESPECIAL, VI_LINKTABLE, isp->RWvolumeId);
if (!VALID_INO(ino))
Abort
- ("Unable to allocate link table inode for volume %u (error = %d)\n",
- isp->RWvolumeId, errno);
+ ("Unable to allocate link table inode for volume %" AFS_VOLID_FMT " (error = %d)\n",
+ afs_printable_VolumeId_lu(isp->RWvolumeId), errno);
IH_INIT(salvinfo->VGLinkH, salvinfo->fileSysDevice, isp->RWvolumeId, ino);
fdP = IH_OPEN(salvinfo->VGLinkH);
if (fdP == NULL)
- Abort("Can't open link table for volume %u (error = %d)\n",
- isp->RWvolumeId, errno);
+ Abort("Can't open link table for volume %" AFS_VOLID_FMT " (error = %d)\n",
+ afs_printable_VolumeId_lu(isp->RWvolumeId), errno);
if (FDH_TRUNC(fdP, sizeof(version) + sizeof(short)) < 0)
- Abort("Can't truncate link table for volume %u (error = %d)\n",
- isp->RWvolumeId, errno);
+ Abort("Can't truncate link table for volume %" AFS_VOLID_FMT " (error = %d)\n",
+ afs_printable_VolumeId_lu(isp->RWvolumeId), errno);
version.magic = LINKTABLEMAGIC;
version.version = LINKTABLEVERSION;
if (FDH_PWRITE(fdP, (char *)&version, sizeof(version), 0)
!= sizeof(version))
- Abort("Can't truncate link table for volume %u (error = %d)\n",
- isp->RWvolumeId, errno);
+ Abort("Can't truncate link table for volume %" AFS_VOLID_FMT " (error = %d)\n",
+ afs_printable_VolumeId_lu(isp->RWvolumeId), errno);
FDH_REALLYCLOSE(fdP);
}
void
-SalvageVolumeGroup(struct SalvInfo *salvinfo, struct InodeSummary *isp, int nVols)
+nt_SalvageVolumeGroup(struct SalvInfo *salvinfo, struct InodeSummary *isp, int nVols)
{
pthread_t tid;
pthread_attr_t tattr;
for (i = 0, totalInodes = 0; i < nVols; i++)
totalInodes += isp[i].nInodes;
size = totalInodes * sizeof(struct ViceInodeInfo);
- inodes = (struct ViceInodeInfo *)malloc(size);
+ inodes = malloc(size);
allInodes = inodes - isp->index; /* this would the base of all the inodes
* for the partition, if all the inodes
* had been read into memory */
- osi_Assert(OS_SEEK
+ opr_Verify(OS_SEEK
(salvinfo->inodeFd, isp->index * sizeof(struct ViceInodeInfo),
SEEK_SET) != -1);
- osi_Assert(OS_READ(salvinfo->inodeFd, inodes, size) == size);
+ opr_Verify(OS_READ(salvinfo->inodeFd, inodes, size) == size);
/* Don't try to salvage a read write volume if there isn't one on this
* partition */
IH_INIT(salvinfo->VGLinkH, salvinfo->fileSysDevice, isp->RWvolumeId, ino);
fdP = IH_OPEN(salvinfo->VGLinkH);
}
+ if (VALID_INO(ino) && fdP != NULL) {
+ struct versionStamp header;
+ afs_sfsize_t nBytes;
+
+ nBytes = FDH_PREAD(fdP, (char *)&header, sizeof(struct versionStamp), 0);
+ if (nBytes != sizeof(struct versionStamp)
+ || header.magic != LINKTABLEMAGIC) {
+ Log("Bad linktable header for volume %" AFS_VOLID_FMT ".\n", afs_printable_VolumeId_lu(isp->RWvolumeId));
+ FDH_REALLYCLOSE(fdP);
+ fdP = NULL;
+ }
+ }
if (!VALID_INO(ino) || fdP == NULL) {
- Log("%s link table for volume %u.\n",
- Testing ? "Would have recreated" : "Recreating", isp->RWvolumeId);
+ Log("%s link table for volume %" AFS_VOLID_FMT ".\n",
+ Testing ? "Would have recreated" : "Recreating", afs_printable_VolumeId_lu(isp->RWvolumeId));
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
if (!Showmode)
- Log("%s VOLUME %u%s.\n", rw ? "SALVAGING" : "CHECKING CLONED",
- lisp->volumeId, (Testing ? "(READONLY mode)" : ""));
+ Log("%s VOLUME %" AFS_VOLID_FMT "%s.\n", rw ? "SALVAGING" : "CHECKING CLONED",
+ afs_printable_VolumeId_lu(lisp->volumeId), (Testing ? "(READONLY mode)" : ""));
/* Check inodes twice. The second time do things seriously. This
* way the whole RO volume can be deleted, below, if anything goes wrong */
for (check = 1; check >= 0; check--) {
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]);
+ 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);
}
}
memset(goodspecial, 0, sizeof(goodspecial));
- skip = malloc(isp->nSpecialInodes * sizeof(*skip));
- if (skip) {
- memset(skip, 0, isp->nSpecialInodes * sizeof(*skip));
- } else {
+ skip = calloc(isp->nSpecialInodes, sizeof(*skip));
+ if (skip == NULL) {
Log("cannot allocate memory for inode skip array when salvaging "
"volume %lu; not performing duplicate special inode recovery\n",
afs_printable_uint32_lu(isp->volumeId));
continue;
}
if (!Showmode) {
- Log("Duplicate special %d inodes for volume %u found (%s, %s);\n",
- ip->u.special.type, isp->volumeId,
+ Log("Duplicate special %d inodes for volume %" AFS_VOLID_FMT " found (%s, %s);\n",
+ ip->u.special.type, afs_printable_VolumeId_lu(isp->volumeId),
PrintInode(stmp1, ip->inodeNumber),
PrintInode(stmp2, (ip+1)->inodeNumber));
}
}
} else {
if (!Showmode)
- Log("cannot determine which is correct; salvage of volume %u aborted\n", isp->volumeId);
+ Log("cannot determine which is correct; salvage of volume %" AFS_VOLID_FMT " aborted\n", afs_printable_VolumeId_lu(isp->volumeId));
if (skip) {
free(skip);
}
if (stuff[i].inodeType == VI_LINKTABLE) {
/* Gross hack: SalvageHeader does a bcmp on the volume header.
* And we may have recreated the link table earlier, so set the
- * RW header as well.
+ * RW header as well. The header magic was already checked.
*/
if (VALID_INO(salvinfo->VGLinkH->ih_ino)) {
*stuff[i].inode = salvinfo->VGLinkH->ih_ino;
if (isp->volSummary == NULL) {
char path[64];
char headerName[64];
- (void)afs_snprintf(headerName, sizeof headerName, VFORMAT, afs_printable_uint32_lu(isp->volumeId));
- (void)afs_snprintf(path, sizeof path, "%s" OS_DIRSEP "%s", salvinfo->fileSysPath, headerName);
+ snprintf(headerName, sizeof headerName, VFORMAT,
+ afs_printable_VolumeId_lu(isp->volumeId));
+ snprintf(path, sizeof path, "%s" OS_DIRSEP "%s",
+ salvinfo->fileSysPath, headerName);
if (check) {
- Log("No header file for volume %u\n", isp->volumeId);
+ Log("No header file for volume %" AFS_VOLID_FMT "\n", afs_printable_VolumeId_lu(isp->volumeId));
return -1;
}
if (!Showmode)
- Log("No header file for volume %u; %screating %s\n",
- isp->volumeId, (Testing ? "it would have been " : ""),
+ Log("No header file for volume %" AFS_VOLID_FMT "; %screating %s\n",
+ afs_printable_VolumeId_lu(isp->volumeId), (Testing ? "it would have been " : ""),
path);
isp->volSummary = calloc(1, sizeof(struct VolumeSummary));
- isp->volSummary->fileName = ToString(headerName);
writefunc = VCreateVolumeDiskHeader;
} else {
if (memcmp
(&isp->volSummary->header, &tempHeader,
sizeof(struct VolumeHeader))) {
- /* We often remove the name before calling us, so we make a fake one up */
- if (isp->volSummary->fileName) {
- strcpy(headerName, isp->volSummary->fileName);
- } else {
- (void)afs_snprintf(headerName, sizeof headerName, VFORMAT, afs_printable_uint32_lu(isp->volumeId));
- isp->volSummary->fileName = ToString(headerName);
- }
- (void)afs_snprintf(path, sizeof path, "%s" OS_DIRSEP "%s", salvinfo->fileSysPath, headerName);
+ VolumeExternalName_r(isp->volumeId, headerName, sizeof(headerName));
+ snprintf(path, sizeof path, "%s" OS_DIRSEP "%s",
+ salvinfo->fileSysPath, headerName);
Log("Header file %s is damaged or no longer valid%s\n", path,
(check ? "" : "; repairing"));
sizeof(struct VolumeHeader));
if (Testing) {
if (!Showmode)
- Log("It would have written a new header file for volume %u\n",
- isp->volumeId);
+ Log("It would have written a new header file for volume %" AFS_VOLID_FMT "\n",
+ afs_printable_VolumeId_lu(isp->volumeId));
} else {
afs_int32 code;
VolumeHeaderToDisk(&diskHeader, &tempHeader);
code = (*writefunc)(&diskHeader, salvinfo->fileSysPartition);
if (code) {
- Log("Error %ld writing volume header file for volume %lu\n",
+ Log("Error %ld writing volume header file for volume %" AFS_VOLID_FMT "\n",
afs_printable_int32_ld(code),
- afs_printable_uint32_lu(diskHeader.id));
+ afs_printable_VolumeId_lu(diskHeader.id));
return -1;
}
}
return 0;
#ifndef AFS_NAMEI_ENV
if (sp->inodeType == VI_LINKTABLE)
- return 0;
+ return 0; /* header magic was already checked */
#endif
if (*(sp->inode) == 0) {
if (check) {
* it below */
memset(&header, 0, sizeof(header));
}
+#ifdef AFS_NAMEI_ENV
+ if (namei_FixSpecialOGM(fdP, check)) {
+ Log("Error with namei header OGM data (%s)\n", sp->description);
+ FDH_REALLYCLOSE(fdP);
+ IH_RELEASE(specH);
+ return -1;
+ }
+#endif
if (sp->inodeType == VI_VOLINFO
&& header.volumeInfo.destroyMe == DESTROY_ME) {
if (deleteMe)
header.volumeInfo.stamp = sp->stamp;
header.volumeInfo.id = isp->volumeId;
header.volumeInfo.parentId = isp->RWvolumeId;
- sprintf(header.volumeInfo.name, "bogus.%u", isp->volumeId);
- Log("Warning: the name of volume %u is now \"bogus.%u\"\n",
- isp->volumeId, isp->volumeId);
+ sprintf(header.volumeInfo.name, "bogus.%" AFS_VOLID_FMT, afs_printable_VolumeId_lu(isp->volumeId));
+ Log("Warning: the name of volume %" AFS_VOLID_FMT " is now \"bogus.%" AFS_VOLID_FMT "\"\n",
+ afs_printable_VolumeId_lu(isp->volumeId), afs_printable_VolumeId_lu(isp->volumeId));
header.volumeInfo.inService = 0;
header.volumeInfo.blessed = 0;
/* The + 1000 is a hack in case there are any files out in venus caches */
header.volumeInfo.uniquifier = (isp->maxUniquifier + 1) + 1000;
header.volumeInfo.type = (isp->volumeId == isp->RWvolumeId ? readwriteVolume : readonlyVolume); /* XXXX */
header.volumeInfo.needsCallback = 0;
- gettimeofday(&tp, 0);
+ gettimeofday(&tp, NULL);
header.volumeInfo.creationDate = tp.tv_sec;
nBytes =
FDH_PWRITE(fdP, (char *)&header.volumeInfo,
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 (%u) %supdated %s\n", salvinfo->VolInfo.name,
- salvinfo->VolInfo.id,
+ 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 (%u) not updated (created %s)\n",
- salvinfo->VolInfo.name, salvinfo->VolInfo.id, update);
+ Log("%s (%" AFS_VOLID_FMT ") not updated (created %s)\n",
+ salvinfo->VolInfo.name, afs_printable_VolumeId_lu(salvinfo->VolInfo.id), update);
}
}
IH_INIT(handle, salvinfo->fileSysDevice, volSummary->header.parent, ino);
fdP = IH_OPEN(handle);
- osi_Assert(fdP != NULL);
+ opr_Assert(fdP != NULL);
file = FDH_FDOPEN(fdP, "r+");
- osi_Assert(file != NULL);
+ opr_Assert(file != NULL);
vcp = &VnodeClassInfo[class];
size = OS_SIZE(fdP->fd_fd);
- osi_Assert(size != -1);
+ opr_Assert(size != -1);
nVnodes = (size / vcp->diskSize) - 1;
if (nVnodes > 0) {
- osi_Assert((nVnodes + 1) * vcp->diskSize == size);
- osi_Assert(STREAM_ASEEK(file, vcp->diskSize) == 0);
+ opr_Assert((nVnodes + 1) * vcp->diskSize == size);
+ opr_Verify(STREAM_ASEEK(file, vcp->diskSize) == 0);
} else {
nVnodes = 0;
}
}
} /* VNDISK_GET_INO(vnode) != 0 */
vnodeDone:
- osi_Assert(!(vnodeChanged && check));
+ opr_Assert(!(vnodeChanged && check));
if (vnodeChanged && !Testing) {
- osi_Assert(IH_IWRITE
- (handle, vnodeIndexOffset(vcp, vnodeNumber),
- (char *)vnode, vcp->diskSize)
- == vcp->diskSize);
+ opr_Verify(IH_IWRITE(handle,
+ vnodeIndexOffset(vcp, vnodeNumber),
+ (char *)vnode, vcp->diskSize)
+ == vcp->diskSize);
salvinfo->VolumeChanged = 1; /* For break call back */
}
}
IH_IREAD(salvinfo->vnodeInfo[vLarge].handle,
vnodeIndexOffset(vcp, dir->vnodeNumber), (char *)&vnode,
sizeof(vnode));
- osi_Assert(code == sizeof(vnode));
+ opr_Assert(code == sizeof(vnode));
oldinode = VNDISK_GET_INO(&vnode);
/* Increment the version number by a whole lot to avoid problems with
* clients that were promised new version numbers--but the file server
IH_CREATE(dir->ds_linkH, salvinfo->fileSysDevice, salvinfo->fileSysPath, 0, dir->rwVid,
dir->vnodeNumber, vnode.uniquifier, vnode.dataVersion +=
200);
- osi_Assert(VALID_INO(newinode));
- osi_Assert(CopyInode(salvinfo->fileSysDevice, oldinode, newinode, dir->rwVid) == 0);
+ opr_Assert(VALID_INO(newinode));
+ opr_Verify(CopyInode(salvinfo->fileSysDevice, oldinode, newinode,
+ dir->rwVid) == 0);
vnode.cloned = 0;
VNDISK_SET_INO(&vnode, newinode);
code =
IH_IWRITE(salvinfo->vnodeInfo[vLarge].handle,
vnodeIndexOffset(vcp, dir->vnodeNumber), (char *)&vnode,
sizeof(vnode));
- osi_Assert(code == sizeof(vnode));
+ opr_Assert(code == sizeof(vnode));
SetSalvageDirHandle(&dir->dirHandle, dir->dirHandle.dirh_handle->ih_vid,
salvinfo->fileSysDevice, newinode,
IH_IREAD(salvinfo->vnodeInfo[vLarge].handle,
vnodeIndexOffset(vcp, dir->vnodeNumber), (char *)&vnode,
sizeof(vnode));
- osi_Assert(lcode == sizeof(vnode));
+ opr_Assert(lcode == sizeof(vnode));
oldinode = VNDISK_GET_INO(&vnode);
/* Increment the version number by a whole lot to avoid problems with
* clients that were promised new version numbers--but the file server
IH_CREATE(dir->ds_linkH, salvinfo->fileSysDevice, salvinfo->fileSysPath, 0, dir->rwVid,
dir->vnodeNumber, vnode.uniquifier, vnode.dataVersion +=
200);
- osi_Assert(VALID_INO(newinode));
+ opr_Assert(VALID_INO(newinode));
SetSalvageDirHandle(&newdir, dir->rwVid, salvinfo->fileSysDevice, newinode,
&salvinfo->VolumeChanged);
if (code) {
Log("also failed to decrement link count on new inode");
}
- osi_Assert(1 == 2);
+ opr_Assert(0);
}
Log("Checking the results of the directory salvage...\n");
if (!DirOK(&newdir)) {
Log("Directory salvage failed!!!; restoring old version of the directory.\n");
code = IH_DEC(dir->ds_linkH, newinode, dir->rwVid);
- osi_Assert(code == 0);
- osi_Assert(1 == 2);
+ opr_Assert(code == 0);
+ opr_Assert(0);
}
vnode.cloned = 0;
VNDISK_SET_INO(&vnode, newinode);
- length = Length(&newdir);
+ length = afs_dir_Length(&newdir);
VNDISK_SET_LEN(&vnode, length);
lcode =
IH_IWRITE(salvinfo->vnodeInfo[vLarge].handle,
vnodeIndexOffset(vcp, dir->vnodeNumber), (char *)&vnode,
sizeof(vnode));
- osi_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
+ opr_Assert(lcode == sizeof(vnode));
+ IH_CONDSYNC(salvinfo->vnodeInfo[vLarge].handle);
+
/* make sure old directory file is really closed */
fdP = IH_OPEN(dir->dirHandle.dirh_handle);
FDH_REALLYCLOSE(fdP);
code = IH_DEC(dir->ds_linkH, oldinode, dir->rwVid);
- osi_Assert(code == 0);
+ opr_Assert(code == 0);
dir->dirHandle = newdir;
}
}
if (!Testing) {
CopyOnWrite(salvinfo, dir);
- osi_Assert(Delete(&dir->dirHandle, name) == 0);
+ opr_Verify(afs_dir_Delete(&dir->dirHandle, name) == 0);
}
return 0;
}
Log("dir vnode %d: invalid entry: %s" OS_DIRSEP "%s has no inode (vnode %d, unique %d)%s\n", dir->vnodeNumber, (dir->name ? dir->name : "??"), name, vnodeNumber, unique, (Testing ? "-- would have deleted" : " -- deleted"));
if (!Testing) {
CopyOnWrite(salvinfo, dir);
- osi_Assert(Delete(&dir->dirHandle, name) == 0);
+ opr_Verify(afs_dir_Delete(&dir->dirHandle, name) == 0);
}
return 0;
}
if (!unique) {
if (!Testing) {
CopyOnWrite(salvinfo, dir);
- osi_Assert(Delete(&dir->dirHandle, name) == 0);
+ opr_Verify(afs_dir_Delete(&dir->dirHandle, name) == 0);
}
return 0;
}
* 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);
- osi_Assert(Delete(&dir->dirHandle, name) == 0);
- if (!todelete)
- osi_Assert(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) {
if (dir->vnodeNumber != vnodeNumber || (dir->unique != unique)) {
- AFSFid fid;
if (!Showmode)
Log("directory vnode %u.%u: bad '.' entry (was %u.%u); fixed\n", dir->vnodeNumber, dir->unique, vnodeNumber, unique);
if (!Testing) {
+ AFSFid fid;
CopyOnWrite(salvinfo, dir);
- osi_Assert(Delete(&dir->dirHandle, ".") == 0);
+ opr_Verify(afs_dir_Delete(&dir->dirHandle, ".") == 0);
fid.Vnode = dir->vnodeNumber;
fid.Unique = dir->unique;
- osi_Assert(Create(&dir->dirHandle, ".", &fid) == 0);
+ opr_Verify(afs_dir_Create(&dir->dirHandle, ".", &fid) == 0);
+ vnodeNumber = fid.Vnode; /* Get the new Essence */
+ unique = fid.Unique;
+ vnodeEssence = CheckVnodeNumber(salvinfo, vnodeNumber);
}
-
- vnodeNumber = fid.Vnode; /* Get the new Essence */
- unique = fid.Unique;
- vnodeEssence = CheckVnodeNumber(salvinfo, vnodeNumber);
}
dir->haveDot = 1;
} else if (strcmp(name, "..") == 0) {
struct VnodeEssence *dotdot;
pa.Vnode = dir->parent;
dotdot = CheckVnodeNumber(salvinfo, pa.Vnode);
- osi_Assert(dotdot != NULL); /* XXX Should not be assert */
+ opr_Assert(dotdot != NULL); /* XXX Should not be assert */
pa.Unique = dotdot->unique;
} else {
pa.Vnode = dir->vnodeNumber;
Log("directory vnode %u.%u: bad '..' entry (was %u.%u); fixed\n", dir->vnodeNumber, dir->unique, vnodeNumber, unique);
if (!Testing) {
CopyOnWrite(salvinfo, dir);
- osi_Assert(Delete(&dir->dirHandle, "..") == 0);
- osi_Assert(Create(&dir->dirHandle, "..", &pa) == 0);
+ opr_Verify(afs_dir_Delete(&dir->dirHandle, "..") == 0);
+ opr_Verify(afs_dir_Create(&dir->dirHandle, "..", &pa) == 0);
}
vnodeNumber = pa.Vnode; /* Get the new Essence */
}
if (!Testing) {
CopyOnWrite(salvinfo, dir);
- osi_Assert(Delete(&dir->dirHandle, name) == 0);
+ opr_Verify(afs_dir_Delete(&dir->dirHandle, name) == 0);
}
vnodeEssence->claimed = 0; /* Not claimed: Orphaned */
vnodeEssence->todelete = 1; /* Will later delete vnode and decr inode */
if (nBytes == size) {
buf[size] = '\0';
if ( (*buf != '#' && *buf != '%') || buf[strlen(buf)-1] != '.' ) {
- Log("Volume %u (%s) mount point %s" OS_DIRSEP "%s to '%s' invalid, %s to symbolic link\n",
- dir->dirHandle.dirh_handle->ih_vid, dir->vname, dir->name ? dir->name : "??", name, buf,
+ Log("Volume %" AFS_VOLID_FMT " (%s) mount point %s" OS_DIRSEP "%s to '%s' invalid, %s to symbolic link\n",
+ afs_printable_VolumeId_lu(dir->dirHandle.dirh_handle->ih_vid), dir->vname, dir->name ? dir->name : "??", name, buf,
Testing ? "would convert" : "converted");
vnodeEssence->modeBits |= 0111;
vnodeEssence->changed = 1;
- } else if (ShowMounts) Log("In volume %u (%s) found mountpoint %s" OS_DIRSEP "%s to '%s'\n",
- dir->dirHandle.dirh_handle->ih_vid, dir->vname,
- dir->name ? dir->name : "??", name, buf);
+ } else if (ShowMounts)
+ Log("In volume %" AFS_VOLID_FMT " (%s) found mountpoint %s" OS_DIRSEP "%s to '%s'\n",
+ afs_printable_VolumeId_lu(dir->dirHandle.dirh_handle->ih_vid),
+ dir->vname, dir->name ? dir->name : "??", name, buf);
} else {
Log("Volume %s cound not read mount point vnode %u size %d code %d\n",
dir->vname, vnodeNumber, (int)size, (int)nBytes);
Log("FOUND root file: %s" OS_DIRSEP "%s (%u.%u %05o) author %u (vnode %u dir %u)\n", dir->name ? dir->name : "??", name, vnodeEssence->owner, vnodeEssence->group, vnodeEssence->modeBits, vnodeEssence->author, vnodeNumber, dir->vnodeNumber);
if (vnodeIdToClass(vnodeNumber) == vLarge
&& vnodeEssence->name == NULL) {
- char *n;
- if ((n = (char *)malloc(strlen(name) + 1)))
- strcpy(n, name);
- vnodeEssence->name = n;
+ vnodeEssence->name = strdup(name);
}
/* The directory entry points to the vnode. Check to see if the
}
if (!Testing) {
CopyOnWrite(salvinfo, dir);
- osi_Assert(Delete(&dir->dirHandle, name) == 0);
+ opr_Verify(afs_dir_Delete(&dir->dirHandle, name) == 0);
}
return 0;
}
IH_INIT(vip->handle, salvinfo->fileSysDevice, rwVId, ino);
fdP = IH_OPEN(vip->handle);
- osi_Assert(fdP != NULL);
+ opr_Assert(fdP != NULL);
file = FDH_FDOPEN(fdP, "r+");
- osi_Assert(file != NULL);
+ opr_Assert(file != NULL);
size = OS_SIZE(fdP->fd_fd);
- osi_Assert(size != -1);
+ opr_Assert(size != -1);
vip->nVnodes = (size / vcp->diskSize) - 1;
if (vip->nVnodes > 0) {
- osi_Assert((vip->nVnodes + 1) * vcp->diskSize == size);
- osi_Assert(STREAM_ASEEK(file, vcp->diskSize) == 0);
- osi_Assert((vip->vnodes = (struct VnodeEssence *)
- calloc(vip->nVnodes, sizeof(struct VnodeEssence))) != NULL);
+ opr_Assert((vip->nVnodes + 1) * vcp->diskSize == size);
+ opr_Verify(STREAM_ASEEK(file, vcp->diskSize) == 0);
+ opr_Verify((vip->vnodes = calloc(vip->nVnodes,
+ sizeof(struct VnodeEssence)))
+ != NULL);
if (class == vLarge) {
- osi_Assert((vip->inodes = (Inode *)
- calloc(vip->nVnodes, sizeof(Inode))) != NULL);
+ opr_Verify((vip->inodes = calloc(vip->nVnodes, sizeof(Inode)))
+ != NULL);
} else {
vip->inodes = NULL;
}
if (class != vLarge) {
VnodeId vnodeNumber = bitNumberToVnodeNumber(vnodeIndex, class);
vip->nAllocatedVnodes--;
- memset(vnode, 0, sizeof(vnode));
+ memset(vnode, 0, sizeof(*vnode));
IH_IWRITE(salvinfo->vnodeInfo[vSmall].handle,
vnodeIndexOffset(vcp, vnodeNumber),
(char *)&vnode, sizeof(vnode));
judge_params.salvinfo = salvinfo;
judge_params.dir = &dir;
- osi_Assert(EnumerateDir(&dirHandle, JudgeEntry, &judge_params) == 0);
+ opr_Verify(afs_dir_EnumerateDir(&dirHandle, JudgeEntry,
+ &judge_params) == 0);
}
/* Delete the old directory if it was copied in order to salvage.
DFlush();
if (dir.copied && !Testing) {
code = IH_DEC(dir.ds_linkH, dirHandle.dirh_handle->ih_ino, rwVid);
- osi_Assert(code == 0);
+ opr_Assert(code == 0);
dirVnodeInfo->inodes[i] = dir.dirHandle.dirh_inode;
}
Inode *ip;
afs_sfsize_t bytes;
struct VnodeEssence *vep;
- Inode readmeinode;
+ Inode readmeinode = 0;
time_t now = time(NULL);
if (!salvinfo->vnodeInfo[vLarge].vnodes && !salvinfo->vnodeInfo[vSmall].vnodes) {
salvinfo->vnodeInfo[vLarge].vnodes = calloc(1, sizeof(struct VnodeEssence));
salvinfo->vnodeInfo[vLarge].inodes = calloc(1, sizeof(Inode));
- osi_Assert(salvinfo->vnodeInfo[vLarge].vnodes);
- osi_Assert(salvinfo->vnodeInfo[vLarge].inodes);
+ opr_Assert(salvinfo->vnodeInfo[vLarge].vnodes);
+ opr_Assert(salvinfo->vnodeInfo[vLarge].inodes);
}
vep = &salvinfo->vnodeInfo[vLarge].vnodes[vnodeIdToBitNumber(1)];
did.Volume = vid;
did.Vnode = 1;
did.Unique = 1;
- if (MakeDir(&rootdir->dirHandle, (afs_int32*)&did, (afs_int32*)&did)) {
+ if (afs_dir_MakeDir(&rootdir->dirHandle, (afs_int32*)&did, (afs_int32*)&did)) {
Log("CreateRootDir: MakeDir failed\n");
goto error;
}
- if (Create(&rootdir->dirHandle, "README.ROOTDIR", &readmeid)) {
+ if (afs_dir_Create(&rootdir->dirHandle, "README.ROOTDIR", &readmeid)) {
Log("CreateRootDir: Create failed\n");
goto error;
}
DFlush();
- length = Length(&rootdir->dirHandle);
- DZap((void *)&rootdir->dirHandle);
+ length = afs_dir_Length(&rootdir->dirHandle);
+ DZap(&rootdir->dirHandle);
/* create the new root dir vnode */
rootvnode = calloc(1, SIZEOF_LARGEDISKVNODE);
vid = rwIsp->volSummary->header.id;
IH_INIT(h, salvinfo->fileSysDevice, vid, rwIsp->volSummary->header.volumeInfo);
nBytes = IH_IREAD(h, 0, (char *)&volHeader, sizeof(volHeader));
- osi_Assert(nBytes == sizeof(volHeader));
- osi_Assert(volHeader.stamp.magic == VOLUMEINFOMAGIC);
- osi_Assert(volHeader.destroyMe != DESTROY_ME);
+ opr_Assert(nBytes == sizeof(volHeader));
+ opr_Assert(volHeader.stamp.magic == VOLUMEINFOMAGIC);
+ opr_Assert(volHeader.destroyMe != DESTROY_ME);
/* (should not have gotten this far with DESTROY_ME flag still set!) */
DistilVnodeEssence(salvinfo, vid, vLarge,
&salvinfo->VolumeChanged);
pa.Vnode = LFVnode;
pa.Unique = LFUnique;
- osi_Assert(Delete(&dh, "..") == 0);
- osi_Assert(Create(&dh, "..", &pa) == 0);
+ opr_Verify(afs_dir_Delete(&dh, "..") == 0);
+ opr_Verify(afs_dir_Create(&dh, "..", &pa) == 0);
/* The original parent's link count was decremented above.
* Here we increment the new parent's link count.
pa.Vnode = ThisVnode;
pa.Unique = ThisUnique;
- (void)afs_snprintf(npath, sizeof npath, "%s.%u.%u",
- ((class ==
- vLarge) ? "__ORPHANDIR__" :
- "__ORPHANFILE__"), ThisVnode,
- ThisUnique);
+ snprintf(npath, sizeof npath, "%s.%u.%u",
+ ((class == vLarge) ? "__ORPHANDIR__"
+ : "__ORPHANFILE__"),
+ ThisVnode, ThisUnique);
CopyOnWrite(salvinfo, &rootdir);
- code = Create(&rootdir.dirHandle, npath, &pa);
+ code = afs_dir_Create(&rootdir.dirHandle, npath, &pa);
if (!code)
break;
ThisUnique += 50; /* Try creating a different file */
}
- osi_Assert(code == 0);
+ opr_Assert(code == 0);
Log("Attaching orphaned %s to volume's root dir as %s\n",
((class == vLarge) ? "directory" : "file"), npath);
}
code =
IH_DEC(oldrootdir.ds_linkH, oldrootdir.dirHandle.dirh_inode,
oldrootdir.rwVid);
- osi_Assert(code == 0);
+ opr_Assert(code == 0);
/* dirVnodeInfo->inodes[?] is not updated with new inode number */
}
IH_IREAD(salvinfo->vnodeInfo[class].handle,
vnodeIndexOffset(vcp, vnodeNumber),
(char *)&vnode, sizeof(vnode));
- osi_Assert(nBytes == sizeof(vnode));
+ opr_Assert(nBytes == sizeof(vnode));
vnode.parent = vnp->parent;
oldCount = vnode.linkCount;
if (orphaned) {
if (!vnp->todelete) {
/* Orphans should have already been attached (if requested) */
- osi_Assert(orphans != ORPH_ATTACH);
+ opr_Assert(orphans != ORPH_ATTACH);
oblocks += vnp->blockCount;
ofiles++;
}
if (VNDISK_GET_INO(&vnode)) {
code =
IH_DEC(alinkH, VNDISK_GET_INO(&vnode), vid);
- osi_Assert(code == 0);
+ opr_Assert(code == 0);
}
memset(&vnode, 0, sizeof(vnode));
}
IH_IWRITE(salvinfo->vnodeInfo[class].handle,
vnodeIndexOffset(vcp, vnodeNumber),
(char *)&vnode, sizeof(vnode));
- osi_Assert(nBytes == sizeof(vnode));
+ opr_Assert(nBytes == sizeof(vnode));
}
salvinfo->VolumeChanged = 1;
}
/* 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
*/
afs_printable_uint32_lu(vid));
}
+ if (!Testing && salvinfo->VolumeChanged) {
#ifdef FSSYNC_BUILD_CLIENT
- if (!Testing && salvinfo->VolumeChanged && salvinfo->useFSYNC) {
- afs_int32 fsync_code;
-
- fsync_code = FSYNC_VolOp(vid, NULL, FSYNC_VOL_BREAKCBKS, FSYNC_SALVAGE, NULL);
- if (fsync_code) {
- Log("Error trying to tell the fileserver to break callbacks for "
- "changed volume %lu; error code %ld\n",
- afs_printable_uint32_lu(vid),
- afs_printable_int32_ld(fsync_code));
- } else {
- salvinfo->VolumeChanged = 0;
+ if (salvinfo->useFSYNC) {
+ afs_int32 fsync_code;
+
+ fsync_code = FSYNC_VolOp(vid, NULL, FSYNC_VOL_BREAKCBKS, FSYNC_SALVAGE, NULL);
+ if (fsync_code) {
+ Log("Error trying to tell the fileserver to break callbacks for "
+ "changed volume %lu; error code %ld\n",
+ afs_printable_uint32_lu(vid),
+ afs_printable_int32_ld(fsync_code));
+ } else {
+ salvinfo->VolumeChanged = 0;
+ }
}
- }
#endif /* FSSYNC_BUILD_CLIENT */
+#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
+ * header. So, to reduce the amount of time a client could have
+ * stale data, remove fsstate.dat, so the fileserver will init
+ * callback state with all clients. This is a very coarse hammer,
+ * and in the future we should just record which volumes have
+ * changed. */
+ code = unlink(AFSDIR_SERVER_FSSTATE_FILEPATH);
+ if (code && errno != ENOENT) {
+ Log("Error %d when trying to unlink FS state file %s\n", errno,
+ AFSDIR_SERVER_FSSTATE_FILEPATH);
+ }
+ }
+#endif
+ }
+
/* Turn off the inUse bit; the volume's been salvaged! */
volHeader.inUse = 0; /* clear flag indicating inUse@last crash */
volHeader.needsSalvaged = 0; /* clear 'damaged' flag */
salvinfo->VolumeChanged = 0;
if (!Testing) {
nBytes = IH_IWRITE(h, 0, (char *)&volHeader, sizeof(volHeader));
- osi_Assert(nBytes == sizeof(volHeader));
+ opr_Assert(nBytes == sizeof(volHeader));
}
if (!Showmode) {
- Log("%sSalvaged %s (%u): %d files, %d blocks\n",
- (Testing ? "It would have " : ""), volHeader.name, volHeader.id,
+ Log("%sSalvaged %s (%" AFS_VOLID_FMT "): %d files, %d blocks\n",
+ (Testing ? "It would have " : ""), volHeader.name, afs_printable_VolumeId_lu(volHeader.id),
FilesInVolume, BlocksInVolume);
}
VolumeDiskData volHeader;
nBytes = IH_IREAD(h, 0, (char *)&volHeader, sizeof(volHeader));
- osi_Assert(nBytes == sizeof(volHeader));
- osi_Assert(volHeader.stamp.magic == VOLUMEINFOMAGIC);
+ opr_Assert(nBytes == sizeof(volHeader));
+ opr_Assert(volHeader.stamp.magic == VOLUMEINFOMAGIC);
volHeader.inUse = 0;
volHeader.needsSalvaged = 0;
volHeader.inService = 1;
volHeader.dontSalvage = DONT_SALVAGE;
if (!Testing) {
nBytes = IH_IWRITE(h, 0, (char *)&volHeader, sizeof(volHeader));
- osi_Assert(nBytes == sizeof(volHeader));
+ opr_Assert(nBytes == sizeof(volHeader));
}
}
char *message, int deleteMe, int check)
{
if (readOnly(isp) || deleteMe) {
- if (isp->volSummary && isp->volSummary->fileName) {
+ if (isp->volSummary && !isp->volSummary->deleted) {
if (deleteMe) {
if (!Showmode)
- Log("Volume %u (is only a partial volume--probably an attempt was made to move/restore it when a machine crash occured.\n", isp->volumeId);
+ Log("Volume %" AFS_VOLID_FMT " (is only a partial volume--probably an attempt was made to move/restore it when a machine crash occured.\n", afs_printable_VolumeId_lu(isp->volumeId));
if (!Showmode)
Log("It will be deleted on this server (you may find it elsewhere)\n");
} else {
if (!Showmode)
- Log("Volume %u needs to be salvaged. Since it is read-only, however,\n", isp->volumeId);
+ Log("Volume %" AFS_VOLID_FMT " needs to be salvaged. Since it is read-only, however,\n", afs_printable_VolumeId_lu(isp->volumeId));
if (!Showmode)
Log("it will be deleted instead. It should be recloned.\n");
}
if (!Testing) {
afs_int32 code;
char path[64];
- sprintf(path, "%s" OS_DIRSEP "%s", salvinfo->fileSysPath, isp->volSummary->fileName);
+ char filename[VMAXPATHLEN];
+ VolumeExternalName_r(isp->volumeId, filename, sizeof(filename));
+ sprintf(path, "%s" OS_DIRSEP "%s", salvinfo->fileSysPath, filename);
code = VDestroyVolumeDiskHeader(salvinfo->fileSysPartition, isp->volumeId, isp->RWvolumeId);
if (code) {
- Log("Error %ld destroying volume disk header for volume %lu\n",
+ Log("Error %ld destroying volume disk header for volume %" AFS_VOLID_FMT "\n",
afs_printable_int32_ld(code),
- afs_printable_uint32_lu(isp->volumeId));
+ afs_printable_VolumeId_lu(isp->volumeId));
}
- /* make sure we actually delete the fileName file; ENOENT
+ /* make sure we actually delete the header file; ENOENT
* is fine, since VDestroyVolumeDiskHeader probably already
* unlinked it */
if (unlink(path) && errno != ENOENT) {
}
}
} else if (!check) {
- Log("%s salvage was unsuccessful: read-write volume %u\n", message,
- isp->volumeId);
- Abort("Salvage of volume %u aborted\n", isp->volumeId);
+ Log("%s salvage was unsuccessful: read-write volume %" AFS_VOLID_FMT "\n", message,
+ afs_printable_VolumeId_lu(isp->volumeId));
+ Abort("Salvage of volume %" AFS_VOLID_FMT " aborted\n", afs_printable_VolumeId_lu(isp->volumeId));
}
}
afs_printable_uint32_lu(volumeId));
}
- code = FSYNC_VerifyCheckout(volumeId, salvinfo->fileSysPathName, FSYNC_VOL_OFF, FSYNC_SALVAGE);
+ code = FSYNC_VerifyCheckout(volumeId, salvinfo->fileSysPartition->name, FSYNC_VOL_OFF, FSYNC_SALVAGE);
if (code == SYNC_DENIED) {
/* need to retry checking out volumes */
return -1;
* case). But if it's there enough that we can read it, but
* somehow we cannot write to it to signify we're salvaging it,
* we've got a big problem and we cannot continue. */
- osi_Assert(IH_IWRITE(h, 0, (char*)&volHeader, sizeof(volHeader)) == sizeof(volHeader));
+ opr_Verify(IH_IWRITE(h, 0, (char*)&volHeader, sizeof(volHeader))
+ == sizeof(volHeader));
IH_RELEASE(h);
}
}
#endif /* AFS_DEMAND_ATTACH_FS */
+static void
+AskError(struct SalvInfo *salvinfo, VolumeId volumeId)
+{
+#if defined(AFS_DEMAND_ATTACH_FS) || defined(AFS_DEMAND_ATTACH_UTIL)
+ afs_int32 code;
+ code = FSYNC_VolOp(volumeId, salvinfo->fileSysPartition->name,
+ FSYNC_VOL_FORCE_ERROR, FSYNC_WHATEVER, NULL);
+ if (code != SYNC_OK) {
+ Log("AskError: failed to force volume %lu into error state; "
+ "SYNC error code %ld (%s)\n", (long unsigned)volumeId,
+ (long)code, SYNC_res2string(code));
+ }
+#endif /* AFS_DEMAND_ATTACH_FS || AFS_DEMAND_ATTACH_UTIL */
+}
+
void
AskOffline(struct SalvInfo *salvinfo, VolumeId volumeId)
{
int
AskDAFS(void)
{
- afs_int32 code, i, ret = 0;
SYNC_response res;
+ afs_int32 code = 1, i;
/* we don't care if we race. the answer shouldn't change */
if (isDAFS != -1)
memset(&res, 0, sizeof(res));
- for (i = 0; i < 3; i++) {
- code = FSYNC_VolOp(1, NULL,
- FSYNC_VOL_QUERY_VOP, FSYNC_SALVAGE, &res);
-
- if (code == SYNC_OK) {
- ret = 1;
- break;
- } else if (code == SYNC_DENIED) {
- ret = 1;
- break;
- } else if (code == SYNC_BAD_COMMAND) {
- ret = 0;
- break;
- } else if (code == SYNC_FAILED) {
- if (res.hdr.reason == FSYNC_UNKNOWN_VOLID)
- ret = 1;
- else
- ret = 0;
- } else if (i < 2) {
- /* try it again */
- Log("AskDAFS: request to query fileserver failed; trying again...\n");
+ for (i = 0; code && i < 3; i++) {
+ code = FSYNC_VolOp(0, NULL, FSYNC_VOL_LISTVOLUMES, FSYNC_SALVAGE, &res);
+ if (code) {
+ Log("AskDAFS: FSYNC_VOL_LISTVOLUMES failed with code %ld reason "
+ "%ld (%s); trying again...\n", (long)code, (long)res.hdr.reason,
+ FSYNC_reason2string(res.hdr.reason));
FSYNC_clientFinis();
FSYNC_clientInit();
}
}
- isDAFS = ret;
- return ret;
+ if (code) {
+ Log("AskDAFS: could not determine DAFS-ness, assuming not DAFS\n");
+ res.hdr.flags = 0;
+ }
+
+ if ((res.hdr.flags & SYNC_FLAG_DAFS_EXTENSIONS)) {
+ isDAFS = 1;
+ } else {
+ isDAFS = 0;
+ }
+
+ return isDAFS;
+}
+
+static void
+MaybeAskOnline(struct SalvInfo *salvinfo, VolumeId volumeId)
+{
+ struct VolumeDiskHeader diskHdr;
+ int code;
+ code = VReadVolumeDiskHeader(volumeId, salvinfo->fileSysPartition, &diskHdr);
+ if (code) {
+ /* volume probably does not exist; no need to bring back online */
+ return;
+ }
+ AskOnline(salvinfo, volumeId);
}
void
if (code == SYNC_OK) {
break;
} else if (code == SYNC_DENIED) {
- Log("AskOnline: file server denied online request to volume %u partition %s; trying again...\n", volumeId, salvinfo->fileSysPartition->name);
+ Log("AskOnline: file server denied online request to volume %" AFS_VOLID_FMT " partition %s; trying again...\n", afs_printable_VolumeId_lu(volumeId), salvinfo->fileSysPartition->name);
} else if (code == SYNC_BAD_COMMAND) {
Log("AskOnline: fssync protocol mismatch (bad command word '%d')\n",
FSYNC_VOL_ON);
if (code == SYNC_OK) {
break;
} else if (code == SYNC_DENIED) {
- Log("AskOnline: file server denied DONE request to volume %u partition %s; trying again...\n", volumeId, salvinfo->fileSysPartition->name);
+ Log("AskOnline: file server denied DONE request to volume %" AFS_VOLID_FMT " partition %s; trying again...\n", afs_printable_VolumeId_lu(volumeId), salvinfo->fileSysPartition->name);
} else if (code == SYNC_BAD_COMMAND) {
Log("AskOnline: fssync protocol mismatch (bad command word '%d')\n",
FSYNC_VOL_DONE);
IH_INIT(srcH, device, rwvolume, inode1);
srcFdP = IH_OPEN(srcH);
- osi_Assert(srcFdP != NULL);
+ opr_Assert(srcFdP != NULL);
IH_INIT(destH, device, rwvolume, inode2);
destFdP = IH_OPEN(destH);
while ((nBytes = FDH_PREAD(srcFdP, buf, sizeof(buf), size)) > 0) {
- osi_Assert(FDH_PWRITE(destFdP, buf, nBytes, size) == nBytes);
+ opr_Verify(FDH_PWRITE(destFdP, buf, nBytes, size) == nBytes);
size += nBytes;
}
- osi_Assert(nBytes == 0);
+ opr_Assert(nBytes == 0);
FDH_REALLYCLOSE(srcFdP);
FDH_REALLYCLOSE(destFdP);
IH_RELEASE(srcH);
afs_sfsize_t st_size;
st_size = OS_SIZE(salvinfo->inodeFd);
- osi_Assert(st_size >= 0);
- buf = (struct ViceInodeInfo *)malloc(st_size);
- osi_Assert(buf != NULL);
+ opr_Assert(st_size >= 0);
+ buf = malloc(st_size);
+ opr_Assert(buf != NULL);
nInodes = st_size / sizeof(struct ViceInodeInfo);
- osi_Assert(OS_READ(salvinfo->inodeFd, buf, st_size) == st_size);
+ opr_Verify(OS_READ(salvinfo->inodeFd, buf, st_size) == st_size);
for (ip = buf; nInodes--; ip++) {
- Log("Inode:%s, linkCount=%d, size=%#llx, p=(%u,%u,%u,%u)\n",
+ Log("Inode:%s, linkCount=%d, size=%#llx, p=(%" AFS_VOLID_FMT ",%u,%u,%u)\n", /* VolumeId in param */
PrintInode(stmp, ip->inodeNumber), ip->linkCount,
- (afs_uintmax_t) ip->byteCount, ip->u.param[0], ip->u.param[1],
+ (afs_uintmax_t) ip->byteCount,
+ afs_printable_VolumeId_lu(ip->u.param[0]), ip->u.param[1],
ip->u.param[2], ip->u.param[3]);
}
free(buf);
for (i = 0; i < salvinfo->nVolumesInInodeFile; i++) {
isp = &salvinfo->inodeSummary[i];
- Log("VID:%u, RW:%u, index:%d, nInodes:%d, nSpecialInodes:%d, maxUniquifier:%u, volSummary\n", isp->volumeId, isp->RWvolumeId, isp->index, isp->nInodes, isp->nSpecialInodes, isp->maxUniquifier);
- }
-}
-
-void
-PrintVolumeSummary(struct SalvInfo *salvinfo)
-{
- int i;
- struct VolumeSummary *vsp;
-
- for (i = 0, vsp = salvinfo->volumeSummaryp; i < salvinfo->nVolumes; vsp++, i++) {
- Log("fileName:%s, header, wouldNeedCallback\n", vsp->fileName);
+ Log("VID:%" AFS_VOLID_FMT ", RW:%" AFS_VOLID_FMT ", index:%d, nInodes:%d, nSpecialInodes:%d, maxUniquifier:%u, volSummary\n", afs_printable_VolumeId_lu(isp->volumeId), afs_printable_VolumeId_lu(isp->RWvolumeId), isp->index, isp->nInodes, isp->nSpecialInodes, isp->maxUniquifier);
}
}
int f;
#ifdef AFS_NT40_ENV
f = 0;
- osi_Assert(0); /* Fork is never executed in the NT code path */
+ opr_Assert(0); /* Fork is never executed in the NT code path */
#else
f = fork();
- osi_Assert(f >= 0);
+ opr_Assert(f >= 0);
#ifdef AFS_DEMAND_ATTACH_FS
if ((f == 0) && (programType == salvageServer)) {
/* we are a salvageserver child */
return f;
}
-void
-Exit(int code)
+static void
+QuietExit(int code)
{
- if (ShowLog)
- showlog();
-
#ifdef AFS_DEMAND_ATTACH_FS
if (programType == salvageServer) {
-#ifdef SALVSYNC_BUILD_CLIENT
+ /* release all volume locks before closing down our SYNC channels.
+ * the fileserver may try to online volumes we have checked out when
+ * we close down FSSYNC, so we should make sure we don't have those
+ * volumes locked when it does */
+ struct DiskPartition64 *dp;
+ int i;
+ for (i = 0; i <= VOLMAXPARTS; i++) {
+ dp = VGetPartitionById(i, 0);
+ if (dp) {
+ VLockFileReinit(&dp->volLockFile);
+ }
+ }
+# ifdef SALVSYNC_BUILD_CLIENT
VDisconnectSALV();
-#endif
-#ifdef FSSYNC_BUILD_CLIENT
+# endif
+# ifdef FSSYNC_BUILD_CLIENT
VDisconnectFS();
-#endif
+# endif
}
#endif /* AFS_DEMAND_ATTACH_FS */
#endif
}
+void
+Exit(int code)
+{
+ SalvageShowLog();
+ QuietExit(code);
+}
+
+
int
Wait(char *prog)
{
int status;
int pid;
pid = wait(&status);
- osi_Assert(pid != -1);
+ opr_Assert(pid != -1);
if (WCOREDUMP(status))
Log("\"%s\" core dumped!\n", prog);
if (WIFSIGNALED(status) != 0 || WEXITSTATUS(status) != 0)
}
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;
-}
-
-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) {
- renamefile(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
- }
+ nbytes = strftime(buffer, size, "%m/%d/%Y %H:%M", lt);
+ if (nbytes == 0)
+ memset(buffer, 0, size);
+ return buffer;
}
-#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);
- (void)afs_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];
+ FILE *logFile;
-#ifndef AFS_NT40_ENV
- if (useSyslog) {
- printf("Can't show log since using syslog.\n");
- fflush(stdout);
+ if (ShowLog == 0 || ClientMode) {
return;
}
-#endif
- if (logFile) {
- rewind(logFile);
- fclose(logFile);
+ if (ShowLogFilename == NULL) {
+ ShowLogFilename = strdup(AFSDIR_SERVER_SLVGLOG_FILEPATH);
}
-
- logFile = afs_fopen(AFSDIR_SERVER_SLVGLOG_FILEPATH, "r");
-
+ CloseLog();
+ logFile = afs_fopen(ShowLogFilename, "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);
}
}
+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);
- (void)afs_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, 0);
- 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);
- (void)afs_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 *
ToString(const char *s)
{
char *p;
- p = (char *)malloc(strlen(s) + 1);
- osi_Assert(p != NULL);
- strcpy(p, s);
+ p = strdup(s);
+ opr_Assert(p != NULL);
return p;
}
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;
}