#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
#endif
#include <rx/xdr.h>
#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 "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
-/*@+fcnmacros +macrofcndecl@*/
-#ifdef O_LARGEFILE
-#ifdef S_SPLINT_S
-extern off64_t afs_lseek(int FD, off64_t O, int F);
-#endif /*S_SPLINT_S */
-#define afs_lseek(FD, O, F) lseek64(FD, (off64_t) (O), F)
-#define afs_stat stat64
-#define afs_fstat fstat64
-#define afs_open open64
-#define afs_fopen fopen64
-#else /* !O_LARGEFILE */
-#ifdef S_SPLINT_S
-extern off_t afs_lseek(int FD, off_t O, int F);
-#endif /*S_SPLINT_S */
-#define afs_lseek(FD, O, F) lseek(FD, (off_t) (O), F)
-#define afs_stat stat
-#define afs_fstat fstat
-#define afs_open open
-#define afs_fopen fopen
-#endif /* !O_LARGEFILE */
-/*@=fcnmacros =macrofcndecl@*/
-
#ifdef AFS_OSF_ENV
extern void *calloc();
#endif
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. */
* header dealt with */
int nVolumesInInodeFile; /**< Number of read-write volumes summarized */
- int inodeFd; /**< File descriptor for inode file */
+ FD_t inodeFd; /**< File descriptor for inode file */
struct VolumeSummary *volumeSummaryp; /**< Holds all the volumes in a part */
int nVolumes; /**< Number of volumes (read-write and read-only)
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
+#if defined(AFS_DEMAND_ATTACH_FS) || defined(AFS_DEMAND_ATTACH_UTIL)
static int LockVolume(struct SalvInfo *salvinfo, VolumeId volumeId);
-#endif /* AFS_DEMAND_ATTACH_FS */
+#endif /* AFS_DEMAND_ATTACH_FS || AFS_DEMAND_ATTACH_UTIL */
/* Uniquifier stored in the Inode */
static Unique
/* Check if the given inode is the root of the filesystem. */
#ifndef AFS_SGI_XFS_IOPS_ENV
int
-IsRootInode(struct afs_stat *status)
+IsRootInode(struct afs_stat_st *status)
{
/*
* The root inode is not a fixed value in XFS partitions. So we need to
} else
#endif
{
- (void)afs_snprintf(logFileName, sizeof logFileName,
- "%s.%d",
- AFSDIR_SERVER_SLVGLOG_FILEPATH,
- jobs[startjob]->jobnumb);
+ snprintf(logFileName, sizeof logFileName, "%s.%d",
+ AFSDIR_SERVER_SLVGLOG_FILEPATH,
+ jobs[startjob]->jobnumb);
logFile = afs_fopen(logFileName, "w");
}
if (!logFile)
#endif
if (!partP) {
for (i = 0; i < jobcount; i++) {
- (void)afs_snprintf(logFileName, sizeof logFileName, "%s.%d",
- AFSDIR_SERVER_SLVGLOG_FILEPATH, 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 *name, *tdir;
char inodeListPath[256];
- FILE *inodeFile = NULL;
+ FD_t inodeFile = INVALID_FD;
static char tmpDevName[100];
static char wpath[100];
struct VolumeSummary *vsp, *esp;
memset(salvinfo, 0, sizeof(*salvinfo));
tries++;
- if (inodeFile) {
- fclose(inodeFile);
- inodeFile = NULL;
+ if (inodeFile != INVALID_FD) {
+ OS_CLOSE(inodeFile);
+ inodeFile = INVALID_FD;
}
if (tries > VOL_MAX_CHECKOUT_RETRIES) {
Abort("Raced too many times with fileserver restarts while trying to "
"checkout/lock volumes; Aborted\n");
}
-#ifdef AFS_DEMAND_ATTACH_FS
+#if defined(AFS_DEMAND_ATTACH_FS) || defined(AFS_DEMAND_ATTACH_UTIL)
if (tries > 1) {
/* unlock all previous volume locks, since we're about to lock them
* again */
VLockFileReinit(&partP->volLockFile);
}
-#endif /* AFS_DEMAND_ATTACH_FS */
+#endif /* AFS_DEMAND_ATTACH_FS || AFS_DEMAND_ATTACH_UTIL */
salvinfo->fileSysPartition = partP;
salvinfo->fileSysDevice = salvinfo->fileSysPartition->device;
#endif
if (singleVolumeNumber) {
-#ifndef AFS_DEMAND_ATTACH_FS
+#if !(defined(AFS_DEMAND_ATTACH_FS) || defined(AFS_DEMAND_ATTACH_UTIL))
/* 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 */
+#endif /* !(AFS_DEMAND_ATTACH_FS || AFS_DEMAND_ATTACH_UTIL) */
ForceSalvage = 1;
salvinfo->useFSYNC = 1;
AskOffline(salvinfo, singleVolumeNumber);
-#ifdef AFS_DEMAND_ATTACH_FS
+#if defined(AFS_DEMAND_ATTACH_FS) || defined(AFS_DEMAND_ATTACH_UTIL)
if (LockVolume(salvinfo, singleVolumeNumber)) {
goto retry;
}
-#endif /* AFS_DEMAND_ATTACH_FS */
+#endif /* AFS_DEMAND_ATTACH_FS || AFS_DEMAND_ATTACH_UTIL */
} else {
salvinfo->useFSYNC = 0;
getpid());
#endif
- inodeFile = fopen(inodeListPath, "w+b");
- if (!inodeFile) {
+ inodeFile = OS_OPEN(inodeListPath, O_RDWR|O_TRUNC|O_CREAT, 0666);
+ if (inodeFile == INVALID_FD) {
Abort("Error %d when creating inode description file %s; not salvaged\n", errno, inodeListPath);
}
#ifdef AFS_NT40_ENV
}
if (GetInodeSummary(salvinfo, inodeFile, singleVolumeNumber) < 0) {
- fclose(inodeFile);
+ OS_CLOSE(inodeFile);
return;
}
- salvinfo->inodeFd = fileno(inodeFile);
- if (salvinfo->inodeFd == -1)
+ salvinfo->inodeFd = inodeFile;
+ if (salvinfo->inodeFd == INVALID_FD)
Abort("Temporary file %s is missing...\n", inodeListPath);
- afs_lseek(salvinfo->inodeFd, 0L, SEEK_SET);
+ 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);
}
RemoveTheForce(salvinfo->fileSysPath);
if (!Testing && singleVolumeNumber) {
-#ifdef AFS_DEMAND_ATTACH_FS
+ int foundSVN = 0;
+#if defined(AFS_DEMAND_ATTACH_FS) || defined(AFS_DEMAND_ATTACH_UTIL)
/* unlock vol headers so the fs can attach them when we AskOnline */
VLockFileReinit(&salvinfo->fileSysPartition->volLockFile);
-#endif /* AFS_DEMAND_ATTACH_FS */
-
- AskOnline(salvinfo, singleVolumeNumber);
+#endif /* AFS_DEMAND_ATTACH_FS || AFS_DEMAND_ATTACH_UTIL */
/* Step through the volumeSummary list and set all volumes on-line.
- * The volumes were taken off-line in GetVolumeSummary.
+ * Most volumes were taken off-line in GetVolumeSummary.
+ * If a volume was deleted, don't tell the fileserver anything, since
+ * we already told the fileserver the volume was deleted back when we
+ * we destroyed the volume header.
+ * Also, make sure we bring the singleVolumeNumber back online first.
*/
+
+ for (j = 0; j < salvinfo->nVolumes; j++) {
+ if (salvinfo->volumeSummaryp[j].header.id == singleVolumeNumber) {
+ foundSVN = 1;
+ if (!salvinfo->volumeSummaryp[j].deleted) {
+ AskOnline(salvinfo, singleVolumeNumber);
+ }
+ }
+ }
+
+ if (!foundSVN) {
+ /* If singleVolumeNumber is not in our volumeSummary, it means that
+ * at least one other volume in the VG is on the partition, but the
+ * RW volume is not. We've already AskOffline'd it by now, though,
+ * so make sure we don't still have the volume checked out. */
+ AskDelete(salvinfo, singleVolumeNumber);
+ }
+
for (j = 0; j < salvinfo->nVolumes; j++) {
- AskOnline(salvinfo, salvinfo->volumeSummaryp[j].header.id);
+ if (salvinfo->volumeSummaryp[j].header.id != singleVolumeNumber) {
+ if (!salvinfo->volumeSummaryp[j].deleted) {
+ AskOnline(salvinfo, salvinfo->volumeSummaryp[j].header.id);
+ }
+ }
}
} else {
if (!Showmode)
salvinfo->fileSysPartition->name, (Testing ? " (READONLY mode)" : ""));
}
- fclose(inodeFile); /* SalvageVolumeGroup was the last which needed it. */
+ OS_CLOSE(inodeFile); /* SalvageVolumeGroup was the last which needed it. */
}
void
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_printable_uint32_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) {
Log("Unable to unlink %s (errno = %d)\n", path, errno);
}
+ if (salvinfo->useFSYNC) {
+ AskDelete(salvinfo, vsp->header.id);
+ }
+ vsp->deleted = 1;
}
- vsp->fileName = 0;
}
int
* be unlinked by the caller.
*/
int
-GetInodeSummary(struct SalvInfo *salvinfo, FILE *inodeFile, VolumeId singleVolumeNumber)
+GetInodeSummary(struct SalvInfo *salvinfo, FD_t inodeFile, VolumeId singleVolumeNumber)
{
- struct afs_stat status;
int forceSal, err;
int code;
struct ViceInodeInfo *ip, *ip_save;
struct InodeSummary summary;
char summaryFileName[50];
- FILE *summaryFile;
+ FD_t summaryFile = INVALID_FD;
#ifdef AFS_NT40_ENV
char *dev = salvinfo->fileSysPath;
char *wpath = salvinfo->fileSysPath;
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... */
if ((err =
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);
}
Log("***Forced salvage of all volumes on this partition***\n");
ForceSalvage = 1;
}
- fseek(inodeFile, 0L, SEEK_SET);
- salvinfo->inodeFd = fileno(inodeFile);
- if (salvinfo->inodeFd == -1 || afs_fstat(salvinfo->inodeFd, &status) == -1) {
+ OS_SEEK(inodeFile, 0L, SEEK_SET);
+ salvinfo->inodeFd = inodeFile;
+ if (salvinfo->inodeFd == INVALID_FD ||
+ (st_size = OS_SIZE(salvinfo->inodeFd)) == -1) {
Abort("No inode description file for \"%s\"; not salvaged\n", dev);
}
tdir = (tmpdir ? tmpdir : part);
(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 = afs_fopen(summaryFileName, "a+");
- if (summaryFile == NULL) {
+ summaryFile = OS_OPEN(summaryFileName, O_RDWR|O_APPEND|O_CREAT, 0666);
+ if (summaryFile == INVALID_FD) {
Abort("Unable to create inode summary file\n");
}
}
if (!canfork || debug || Fork() == 0) {
- int nInodes;
- unsigned long st_size=(unsigned long) status.st_size;
- nInodes = st_size / sizeof(struct ViceInodeInfo);
+ int nInodes = st_size / sizeof(struct ViceInodeInfo);
if (nInodes == 0) {
- fclose(summaryFile);
+ OS_CLOSE(summaryFile);
if (!singleVolumeNumber) /* Remove the FORCESALVAGE file */
RemoveTheForce(salvinfo->fileSysPath);
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));
if (ip == NULL) {
- fclose(summaryFile);
+ OS_CLOSE(summaryFile);
Abort
("Unable to allocate enough space to read inode table; %s not salvaged\n",
dev);
}
- if (read(salvinfo->inodeFd, ip, st_size) != st_size) {
- fclose(summaryFile);
+ if (OS_READ(salvinfo->inodeFd, ip, st_size) != st_size) {
+ OS_CLOSE(summaryFile);
Abort("Unable to read inode table; %s not salvaged\n", dev);
}
qsort(ip, nInodes, sizeof(struct ViceInodeInfo), CompareInodes);
- if (afs_lseek(salvinfo->inodeFd, 0, SEEK_SET) == -1
- || write(salvinfo->inodeFd, ip, st_size) != st_size) {
- fclose(summaryFile);
+ if (OS_SEEK(salvinfo->inodeFd, 0, SEEK_SET) == -1
+ || OS_WRITE(salvinfo->inodeFd, ip, st_size) != st_size) {
+ OS_CLOSE(summaryFile);
Abort("Unable to rewrite inode table; %s not salvaged\n", dev);
}
summary.index = 0;
ip_save = ip;
while (nInodes) {
CountVolumeInodes(ip, nInodes, &summary);
- if (fwrite(&summary, sizeof(summary), 1, summaryFile) != 1) {
+ if (OS_WRITE(summaryFile, &summary, sizeof(summary)) != sizeof(summary)) {
Log("Difficulty writing summary file (errno = %d); %s not salvaged\n", errno, dev);
- fclose(summaryFile);
- return -1;
+ OS_CLOSE(summaryFile);
+ retcode = -1;
+ goto error;
}
summary.index += (summary.nInodes);
nInodes -= summary.nInodes;
free(ip_save);
ip = ip_save = NULL;
/* Following fflush is not fclose, because if it was debug mode would not work */
- if (fflush(summaryFile) == EOF || fsync(fileno(summaryFile)) == -1) {
+ if (OS_SYNC(summaryFile) == -1) {
Log("Unable to write summary file (errno = %d); %s not salvaged\n", errno, dev);
- fclose(summaryFile);
- return -1;
+ OS_CLOSE(summaryFile);
+ retcode = -1;
+ goto error;
}
if (canfork && !debug) {
ShowLog = 0;
}
} else {
if (Wait("Inode summary") == -1) {
- fclose(summaryFile);
+ OS_CLOSE(summaryFile);
Exit(1); /* salvage of this partition aborted */
}
}
- osi_Assert(afs_fstat(fileno(summaryFile), &status) != -1);
- if (status.st_size != 0) {
+
+ st_size = OS_SIZE(summaryFile);
+ osi_Assert(st_size >= 0);
+ if (st_size != 0) {
int ret;
- unsigned long st_status=(unsigned long)status.st_size;
- salvinfo->inodeSummary = (struct InodeSummary *)malloc(st_status);
+ salvinfo->inodeSummary = (struct InodeSummary *)malloc(st_size);
osi_Assert(salvinfo->inodeSummary != NULL);
/* For GNU we need to do lseek to get the file pointer moved. */
- osi_Assert(afs_lseek(fileno(summaryFile), 0, SEEK_SET) == 0);
- ret = read(fileno(summaryFile), salvinfo->inodeSummary, st_status);
- osi_Assert(ret == st_status);
+ osi_Assert(OS_SEEK(summaryFile, 0, SEEK_SET) == 0);
+ ret = OS_READ(summaryFile, salvinfo->inodeSummary, st_size);
+ osi_Assert(ret == st_size);
}
- salvinfo->nVolumesInInodeFile =(unsigned long)(status.st_size) / sizeof(struct InodeSummary);
+ salvinfo->nVolumesInInodeFile = st_size / sizeof(struct InodeSummary);
for (i = 0; i < salvinfo->nVolumesInInodeFile; i++) {
salvinfo->inodeSummary[i].volSummary = NULL;
}
- Log("%d nVolumesInInodeFile %lu \n",salvinfo->nVolumesInInodeFile,(unsigned long)(status.st_size));
- fclose(summaryFile);
- return 0;
+ Log("%d nVolumesInInodeFile %lu \n",salvinfo->nVolumesInInodeFile,(unsigned long)st_size);
+ OS_CLOSE(summaryFile);
+
+ error:
+ if (retcode && singleVolumeNumber && !deleted) {
+ AskError(salvinfo, singleVolumeNumber);
+ }
+
+ return retcode;
}
/* Comparison routine for volume sort.
Exit(SALSRV_EXIT_VOLGROUP_LINK);
}
- salvinfo->volumeSummaryp = malloc(VOL_VG_MAX_VOLS * sizeof(struct VolumeSummary));
+ salvinfo->volumeSummaryp = calloc(VOL_VG_MAX_VOLS, sizeof(struct VolumeSummary));
osi_Assert(salvinfo->volumeSummaryp != NULL);
salvinfo->nVolumes = 0;
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;
base = name;
}
- (void)afs_snprintf(nameShouldBe, sizeof nameShouldBe,
- VFORMAT, afs_printable_uint32_lu(summary.header.id));
+ snprintf(nameShouldBe, sizeof nameShouldBe,
+ VFORMAT, afs_printable_uint32_lu(summary.header.id));
if (strcmp(nameShouldBe, base)) {
AskOffline(salvinfo, summary.header.id);
-#ifdef AFS_DEMAND_ATTACH_FS
+#if defined(AFS_DEMAND_ATTACH_FS) || defined(AFS_DEMAND_ATTACH_UTIL)
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 */
+#endif /* AFS_DEMAND_ATTACH_FS || AFS_DEMAND_ATTACH_UTIL */
}
}
if (badname) {
return 1;
}
- summary.fileName = ToString(base);
+ summary.unused = 1;
params->nVolumes++;
if (params->nVolumes > params->totalVolumes) {
nvols = VOL_VG_MAX_VOLS;
}
- salvinfo->volumeSummaryp = malloc(nvols * sizeof(struct VolumeSummary));
+ salvinfo->volumeSummaryp = calloc(nvols, sizeof(struct VolumeSummary));
osi_Assert(salvinfo->volumeSummaryp != NULL);
params.singleVolumeNumber = singleVolumeNumber;
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
}
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;
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(afs_lseek
+ osi_Assert(OS_SEEK
(salvinfo->inodeFd, isp->index * sizeof(struct ViceInodeInfo),
SEEK_SET) != -1);
- osi_Assert(read(salvinfo->inodeFd, inodes, size) == size);
+ osi_Assert(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 %u.\n", 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);
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_uint32_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);
return -1;
Log("No header file for volume %u; %screating %s\n",
isp->volumeId, (Testing ? "it would have been " : ""),
path);
- isp->volSummary = (struct VolumeSummary *)
- malloc(sizeof(struct VolumeSummary));
- isp->volSummary->fileName = ToString(headerName);
+ isp->volSummary = calloc(1, sizeof(struct VolumeSummary));
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"));
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) {
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,
}
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,
}
if (!Testing) {
CopyOnWrite(salvinfo, dir);
- osi_Assert(Delete(&dir->dirHandle, name) == 0);
+ osi_Assert(afs_dir_Delete(&dir->dirHandle, name) == 0);
}
return 0;
}
if (!unique) {
if (!Testing) {
CopyOnWrite(salvinfo, dir);
- osi_Assert(Delete(&dir->dirHandle, name) == 0);
+ osi_Assert(afs_dir_Delete(&dir->dirHandle, name) == 0);
}
return 0;
}
fid.Vnode = vnodeNumber;
fid.Unique = vnodeEssence->unique;
CopyOnWrite(salvinfo, dir);
- osi_Assert(Delete(&dir->dirHandle, name) == 0);
+ osi_Assert(afs_dir_Delete(&dir->dirHandle, name) == 0);
if (!todelete)
- osi_Assert(Create(&dir->dirHandle, name, &fid) == 0);
+ osi_Assert(afs_dir_Create(&dir->dirHandle, name, &fid) == 0);
}
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);
+ osi_Assert(afs_dir_Delete(&dir->dirHandle, ".") == 0);
fid.Vnode = dir->vnodeNumber;
fid.Unique = dir->unique;
- osi_Assert(Create(&dir->dirHandle, ".", &fid) == 0);
+ osi_Assert(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) {
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);
+ osi_Assert(afs_dir_Delete(&dir->dirHandle, "..") == 0);
+ osi_Assert(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);
+ osi_Assert(afs_dir_Delete(&dir->dirHandle, name) == 0);
}
vnodeEssence->claimed = 0; /* Not claimed: Orphaned */
vnodeEssence->todelete = 1; /* Will later delete vnode and decr inode */
}
if (!Testing) {
CopyOnWrite(salvinfo, dir);
- osi_Assert(Delete(&dir->dirHandle, name) == 0);
+ osi_Assert(afs_dir_Delete(&dir->dirHandle, name) == 0);
}
return 0;
}
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);
+ osi_Assert(afs_dir_EnumerateDir(&dirHandle, JudgeEntry,
+ &judge_params) == 0);
}
/* Delete the old directory if it was copied in order to salvage.
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) {
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);
&salvinfo->VolumeChanged);
pa.Vnode = LFVnode;
pa.Unique = LFUnique;
- osi_Assert(Delete(&dh, "..") == 0);
- osi_Assert(Create(&dh, "..", &pa) == 0);
+ osi_Assert(afs_dir_Delete(&dh, "..") == 0);
+ osi_Assert(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;
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 */
+#if defined(AFS_DEMAND_ATTACH_FS) || defined(AFS_DEMAND_ATTACH_UTIL)
+ 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 */
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);
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) {
afs_printable_uint32_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) {
Log("Unable to unlink %s (errno = %d)\n", path, errno);
}
+ if (salvinfo->useFSYNC) {
+ AskDelete(salvinfo, isp->volumeId);
+ }
+ isp->volSummary->deleted = 1;
}
}
} else if (!check) {
}
}
-#ifdef AFS_DEMAND_ATTACH_FS
+#if defined(AFS_DEMAND_ATTACH_FS) || defined(AFS_DEMAND_ATTACH_UTIL)
/**
* Locks a volume on disk for salvaging.
*
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;
return 0;
}
-#endif /* AFS_DEMAND_ATTACH_FS */
+#endif /* AFS_DEMAND_ATTACH_FS || AFS_DEMAND_ATTACH_UTIL */
+
+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)
if (code == SYNC_OK) {
break;
} else if (code == SYNC_DENIED) {
-#ifdef DEMAND_ATTACH_ENABLE
- Log("AskOffline: file server denied offline request; a general salvage may be required.\n");
-#else
- Log("AskOffline: file server denied offline request; a general salvage is required.\n");
-#endif
+ if (AskDAFS())
+ Log("AskOffline: file server denied offline request; a general salvage may be required.\n");
+ else
+ Log("AskOffline: file server denied offline request; a general salvage is required.\n");
Abort("Salvage aborted\n");
} else if (code == SYNC_BAD_COMMAND) {
Log("AskOffline: fssync protocol mismatch (bad command word '%d'); salvage aborting.\n",
FSYNC_VOL_OFF);
-#ifdef DEMAND_ATTACH_ENABLE
- Log("AskOffline: please make sure fileserver, volserver, salvageserver and salvager binaries are same version.\n");
+ if (AskDAFS()) {
+#if defined(AFS_DEMAND_ATTACH_FS) || defined(AFS_DEMAND_ATTACH_UTIL)
+ 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)
+ 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("AskOffline: please make sure fileserver, volserver and salvager binaries are same version.\n");
#endif
+ }
Abort("Salvage aborted\n");
} else if (i < 2) {
/* try it again */
}
}
+/* don't want to pass around state; remember it here */
+static int isDAFS = -1;
+int
+AskDAFS(void)
+{
+ SYNC_response res;
+ afs_int32 code = 1, i;
+
+ /* we don't care if we race. the answer shouldn't change */
+ if (isDAFS != -1)
+ return isDAFS;
+
+ memset(&res, 0, sizeof(res));
+
+ 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();
+ }
+ }
+
+ 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
AskOnline(struct SalvInfo *salvinfo, VolumeId volumeId)
{
} else if (code == SYNC_BAD_COMMAND) {
Log("AskOnline: fssync protocol mismatch (bad command word '%d')\n",
FSYNC_VOL_ON);
-#ifdef DEMAND_ATTACH_ENABLE
- Log("AskOnline: please make sure fileserver, volserver, salvageserver and salvager binaries are same version.\n");
+ Log("AskOnline: please make sure file server binaries are same version.\n");
+ break;
+ } else if (i < 2) {
+ /* try it again */
+ Log("AskOnline: request for fileserver to put volume online failed; trying again...\n");
+ FSYNC_clientFinis();
+ FSYNC_clientInit();
+ }
+ }
+}
+
+void
+AskDelete(struct SalvInfo *salvinfo, VolumeId volumeId)
+{
+ afs_int32 code, i;
+ SYNC_response res;
+
+ for (i = 0; i < 3; i++) {
+ memset(&res, 0, sizeof(res));
+ code = FSYNC_VolOp(volumeId, salvinfo->fileSysPartition->name,
+ FSYNC_VOL_DONE, FSYNC_SALVAGE, &res);
+
+ 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);
+ } else if (code == SYNC_BAD_COMMAND) {
+ 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)
+ 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)
+ 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");
+ Log("AskOnline: please make sure fileserver, volserver and salvager binaries are same version.\n");
#endif
+ }
+ break;
+ } else if (code == SYNC_FAILED &&
+ (res.hdr.reason == FSYNC_UNKNOWN_VOLID ||
+ res.hdr.reason == FSYNC_WRONG_PART)) {
+ /* volume is already effectively 'deleted' */
break;
} else if (i < 2) {
/* try it again */
- Log("AskOnline: request for fileserver to take volume offline failed; trying again...\n");
+ Log("AskOnline: request for fileserver to delete volume failed; trying again...\n");
FSYNC_clientFinis();
FSYNC_clientInit();
}
{
struct ViceInodeInfo *ip;
struct ViceInodeInfo *buf;
- struct afs_stat status;
int nInodes;
afs_ino_str_t stmp;
+ afs_sfsize_t st_size;
- osi_Assert(afs_fstat(salvinfo->inodeFd, &status) == 0);
- buf = (struct ViceInodeInfo *)malloc(status.st_size);
+ st_size = OS_SIZE(salvinfo->inodeFd);
+ osi_Assert(st_size >= 0);
+ buf = (struct ViceInodeInfo *)malloc(st_size);
osi_Assert(buf != NULL);
- nInodes = status.st_size / sizeof(struct ViceInodeInfo);
- osi_Assert(read(salvinfo->inodeFd, buf, status.st_size) == status.st_size);
+ nInodes = st_size / sizeof(struct ViceInodeInfo);
+ osi_Assert(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",
PrintInode(stmp, ip->inodeNumber), ip->linkCount,
}
}
-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);
- }
-}
-
int
Fork(void)
{
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);
+ 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 */
va_list args;
va_start(args, format);
- (void)afs_vsnprintf(tmp, sizeof tmp, format, args);
+ vsnprintf(tmp, sizeof tmp, format, args);
va_end(args);
#ifndef AFS_NT40_ENV
if (useSyslog) {
} else
#endif
if (logFile) {
- gettimeofday(&now, 0);
+ gettimeofday(&now, NULL);
fprintf(logFile, "%s %s", TimeStamp(now.tv_sec, 1), tmp);
fflush(logFile);
}
char tmp[1024];
va_start(args, format);
- (void)afs_vsnprintf(tmp, sizeof tmp, format, args);
+ vsnprintf(tmp, sizeof tmp, format, args);
va_end(args);
#ifndef AFS_NT40_ENV
if (useSyslog) {
RemoveTheForce(char *path)
{
char target[1024];
- struct afs_stat force; /* so we can use afs_stat to find it */
+ struct afs_stat_st force; /* so we can use afs_stat to find it */
strcpy(target,path);
strcat(target,"/FORCESALVAGE");
if (!Testing && ForceSalvage) {
int
UseTheForceLuke(char *path)
{
- struct afs_stat force;
+ struct afs_stat_st force;
char target[1024];
strcpy(target,path);
strcat(target,"/FORCESALVAGE");