* 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);
-#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
{
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);
+ if (singleVolumeNumber) {
+ /* the volume group -- let alone the volume -- does not exist,
+ * but we checked it out, so give it back to the fileserver */
+ AskDelete(salvinfo, singleVolumeNumber);
+ }
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.
if (!Testing && singleVolumeNumber) {
int foundSVN = 0;
-#ifdef AFS_DEMAND_ATTACH_FS
+#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 */
+#endif /* AFS_DEMAND_ATTACH_FS || AFS_DEMAND_ATTACH_UTIL */
/* Step through the volumeSummary list and set all volumes on-line.
* Most volumes were taken off-line in GetVolumeSummary.
}
if (!foundSVN) {
- /* singleVolumeNumber generally should always be in the constructed
- * volumeSummary, but just in case it's not... */
- AskOnline(salvinfo, singleVolumeNumber);
+ /* 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++) {
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
* 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;
+ afs_sfsize_t st_size;
/* This file used to come from vfsck; cobble it up ourselves now... */
if ((err =
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)afs_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 {
}
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);
+ OS_CLOSE(summaryFile);
return -1;
}
summary.index += (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);
+ OS_CLOSE(summaryFile);
return -1;
}
if (canfork && !debug) {
}
} 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);
+ Log("%d nVolumesInInodeFile %lu \n",salvinfo->nVolumesInInodeFile,(unsigned long)st_size);
+ OS_CLOSE(summaryFile);
return 0;
}
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) {
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 */
}
}
-#ifdef AFS_DEMAND_ATTACH_FS
+#if defined(AFS_DEMAND_ATTACH_FS) || defined(AFS_DEMAND_ATTACH_UTIL)
/**
* Locks a volume on disk for salvaging.
*
return 0;
}
-#endif /* AFS_DEMAND_ATTACH_FS */
+#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)
+{
+ afs_int32 code, i, ret = 0;
+ SYNC_response res;
+
+ /* 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; 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");
+ FSYNC_clientFinis();
+ FSYNC_clientInit();
+ }
+ }
+
+ isDAFS = ret;
+ return ret;
+}
+
+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");
-#else
- Log("AskOnline: please make sure fileserver, volserver and salvager binaries are same version.\n");
-#endif
+ Log("AskOnline: please make sure file server binaries are same version.\n");
break;
} else if (i < 2) {
/* try it again */
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, NULL);
+ FSYNC_VOL_DONE, FSYNC_SALVAGE, &res);
if (code == SYNC_OK) {
break;
} else if (code == SYNC_BAD_COMMAND) {
Log("AskOnline: fssync protocol mismatch (bad command word '%d')\n",
FSYNC_VOL_DONE);
-#ifdef DEMAND_ATTACH_ENABLE
- Log("AskOnline: 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("AskOnline: please make sure dafileserver, davolserver, salvageserver and dasalvager binaries are same version.\n");
#else
- Log("AskOnline: please make sure fileserver, volserver and salvager binaries are same version.\n");
+ 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");
+#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 */
{
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,
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");