/*
* Copyright 2000, International Business Machines Corporation and others.
* All Rights Reserved.
- *
+ *
* This software has been released under the terms of the IBM Public
* License. For details, see the LICENSE file in the top-level source
* directory or online at http://www.openafs.org/dl/license10.html
Logs missing inode numbers.
2.3 features:
- Increments directory version number by 200 (rather than by 1) when it is salvaged, in order to prevent problems due to the fact that a version number can be promised to a workstation before it is written to disk. If the server crashes, it may have an older version. Salvaging it could bring the version number up to the same version the workstation believed it already had a call back on.
+ Increments directory version number by 200 (rather than by 1) when it is salvaged, in order to prevent problems due to the fact that a version number can be promised to a workstation before it is written to disk. If the server crashes, it may have an older version. Salvaging it could bring the version number up to the same version the workstation believed it already had a call back on.
2.4 features:
Locks the file /vice/vol/salvage.lock before starting. Aborts if it can't acquire the lock.
#define ROOTINODE 2 /* Root inode of a 4.2 Unix file system
* partition */
-Device fileSysDevice; /* The device number of the current
- * partition being salvaged */
-#ifdef AFS_NT40_ENV
-char fileSysPath[8];
-#else
-char *fileSysPath; /* The path of the mounted partition currently
- * being salvaged, i.e. the directory
- * containing the volume headers */
-#endif
-char *fileSysPathName; /* NT needs this to make name pretty in log. */
-IHandle_t *VGLinkH; /* Link handle for current volume group. */
-int VGLinkH_cnt; /* # of references to lnk handle. */
-struct DiskPartition64 *fileSysPartition; /* Partition being salvaged */
+/**
+ * information that is 'global' to a particular salvage job.
+ */
+struct SalvInfo {
+ Device fileSysDevice; /**< The device number of the current partition
+ * being salvaged */
+ char fileSysPath[8]; /**< 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. */
+ IHandle_t *VGLinkH; /**< Link handle for current volume group. */
+ int VGLinkH_cnt; /**< # of references to lnk handle. */
+ struct DiskPartition64 *fileSysPartition; /**< Partition being salvaged */
+
#ifndef AFS_NT40_ENV
-char *fileSysDeviceName; /* The block device where the file system
- * being salvaged was mounted */
-char *filesysfulldev;
+ char *fileSysDeviceName; /**< The block device where the file system being
+ * salvaged was mounted */
+ char *filesysfulldev;
#endif
-int VolumeChanged; /* Set by any routine which would change the volume in
- * a way which would require callback is to be broken if the
- * volume was put back on line by an active file server */
-
-VolumeDiskData VolInfo; /* A copy of the last good or salvaged volume header dealt with */
-
-int nVolumesInInodeFile; /* Number of read-write volumes summarized */
-int inodeFd; /* File descriptor for inode file */
-
-
-struct VnodeInfo vnodeInfo[nVNODECLASSES];
-
-
-struct VolumeSummary *volumeSummaryp = NULL; /* Holds all the volumes in a part */
-int nVolumes; /* Number of volumes (read-write and read-only)
- * in volume summary */
+ int VolumeChanged; /**< Set by any routine which would change the
+ * volume in a way which would require callbacks
+ * to be broken if the volume was put back on
+ * on line by an active file server */
+
+ VolumeDiskData VolInfo; /**< A copy of the last good or salvaged volume
+ * header dealt with */
+
+ int nVolumesInInodeFile; /**< Number of read-write volumes summarized */
+ int 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)
+ * in volume summary */
+ struct InodeSummary *inodeSummary; /**< contains info on all the relevant
+ * inodes */
+
+ struct VnodeInfo vnodeInfo[nVNODECLASSES]; /**< contains info on all of the
+ * vnodes in the volume that
+ * we are currently looking
+ * at */
+};
char *tmpdir = NULL;
/* Forward declarations */
-static int IsVnodeOrphaned(VnodeId vnode);
-static int AskVolumeSummary(VolumeId singleVolumeNumber);
+static int IsVnodeOrphaned(struct SalvInfo *salvinfo, VnodeId vnode);
+static int AskVolumeSummary(struct SalvInfo *salvinfo,
+ VolumeId singleVolumeNumber);
#ifdef AFS_DEMAND_ATTACH_FS
-static int LockVolume(VolumeId volumeId);
+static int LockVolume(struct SalvInfo *salvinfo, VolumeId volumeId);
#endif /* AFS_DEMAND_ATTACH_FS */
/* Uniquifier stored in the Inode */
}
static int
-BadError(register int aerror)
+BadError(int aerror)
{
if (aerror == EPERM || aerror == ENXIO || aerror == ENOENT)
return 1;
{
/*
* The root inode is not a fixed value in XFS partitions. So we need to
- * see if the partition is in the list of mounted partitions. This only
+ * see if the partition is in the list of mounted partitions. This only
* affects the SalvageFileSys path, so we check there.
*/
return (status->st_ino == ROOTINODE);
}
if (thisjob) {
- /* Check to see if thisjob is for a disk that we are already
+ /* Check to see if thisjob is for a disk that we are already
* salvaging. If it is, link it in as the next job to do. The
- * jobs array has 1 entry per disk being salvages. numjobs is
- * the total number of disks currently being salvaged. In
+ * jobs array has 1 entry per disk being salvages. numjobs is
+ * the total number of disks currently being salvaged. In
* order to keep thejobs array compact, when a disk is
- * completed, the hightest element in the jobs array is moved
+ * completed, the hightest element in the jobs array is moved
* down to now open slot.
*/
for (j = 0; j < numjobs; j++) {
jobs[j] = jobs[j]->nextjob; /* Step to next part on same disk */
free(oldjob); /* free the old job */
- /* If there is another partition on the disk to salvage, then
+ /* If there is another partition on the disk to salvage, then
* say we will start it (startjob). If not, then put thisjob there
* and say we will start it.
*/
int i, j;
int code;
int tries = 0;
+ struct SalvInfo l_salvinfo;
+ struct SalvInfo *salvinfo = &l_salvinfo;
retry:
+ memset(salvinfo, 0, sizeof(*salvinfo));
+
tries++;
if (inodeFile) {
fclose(inodeFile);
}
#endif /* AFS_DEMAND_ATTACH_FS */
- fileSysPartition = partP;
- fileSysDevice = fileSysPartition->device;
- fileSysPathName = VPartitionPath(fileSysPartition);
+ salvinfo->fileSysPartition = partP;
+ salvinfo->fileSysDevice = salvinfo->fileSysPartition->device;
+ salvinfo->fileSysPathName = VPartitionPath(salvinfo->fileSysPartition);
#ifdef AFS_NT40_ENV
/* Opendir can fail on "C:" but not on "C:\" if C is empty! */
- (void)sprintf(fileSysPath, "%s\\", fileSysPathName);
+ (void)sprintf(salvinfo->fileSysPath, "%s\\", salvinfo->fileSysPathName);
name = partP->devName;
#else
- fileSysPath = fileSysPathName;
+ strlcpy(salvinfo->fileSysPath, salvinfo->fileSysPathName, sizeof(salvinfo->fileSysPath));
strcpy(tmpDevName, partP->devName);
name = get_DevName(tmpDevName, wpath);
- fileSysDeviceName = name;
- filesysfulldev = wpath;
+ salvinfo->fileSysDeviceName = name;
+ salvinfo->filesysfulldev = wpath;
#endif
if (singleVolumeNumber) {
Abort("Couldn't connect to file server\n");
}
- AskOffline(singleVolumeNumber, partP->name);
+ AskOffline(salvinfo, singleVolumeNumber);
#ifdef AFS_DEMAND_ATTACH_FS
- if (LockVolume(singleVolumeNumber)) {
+ if (LockVolume(salvinfo, singleVolumeNumber)) {
goto retry;
}
#endif /* AFS_DEMAND_ATTACH_FS */
if (ForceSalvage) {
ForceSalvage = 1;
} else {
- ForceSalvage = UseTheForceLuke(fileSysPath);
+ ForceSalvage = UseTheForceLuke(salvinfo->fileSysPath);
}
if (!Showmode)
Log("SALVAGING FILE SYSTEM PARTITION %s (device=%s%s)\n",
/*
- * Remove any leftover /vicepa/salvage.inodes.* or /vicepa/salvage.temp.*
- * files
+ * Remove any leftover /vicepa/salvage.inodes.* or /vicepa/salvage.temp.*
+ * files
*/
{
DIR *dirp;
struct dirent *dp;
- assert((dirp = opendir(fileSysPath)) != NULL);
+ assert((dirp = opendir(salvinfo->fileSysPath)) != NULL);
while ((dp = readdir(dirp))) {
if (!strncmp(dp->d_name, "salvage.inodes.", 15)
|| !strncmp(dp->d_name, "salvage.temp.", 13)) {
char npath[1024];
Log("Removing old salvager temp files %s\n", dp->d_name);
- strcpy(npath, fileSysPath);
+ strcpy(npath, salvinfo->fileSysPath);
strcat(npath, "/");
strcat(npath, dp->d_name);
unlink(npath);
}
closedir(dirp);
}
- tdir = (tmpdir ? tmpdir : fileSysPath);
+ tdir = (tmpdir ? tmpdir : salvinfo->fileSysPath);
#ifdef AFS_NT40_ENV
(void)_putenv("TMP="); /* If "TMP" is set, then that overrides tdir. */
(void)strncpy(inodeListPath, _tempnam(tdir, "salvage.inodes."), 255);
Log("Error %d when trying to unlink %s\n", errno, inodeListPath);
}
- if (GetInodeSummary(inodeFile, singleVolumeNumber) < 0) {
+ if (GetInodeSummary(salvinfo, inodeFile, singleVolumeNumber) < 0) {
fclose(inodeFile);
return;
}
- inodeFd = fileno(inodeFile);
- if (inodeFd == -1)
+ salvinfo->inodeFd = fileno(inodeFile);
+ if (salvinfo->inodeFd == -1)
Abort("Temporary file %s is missing...\n", inodeListPath);
- afs_lseek(inodeFd, 0L, SEEK_SET);
+ afs_lseek(salvinfo->inodeFd, 0L, SEEK_SET);
if (ListInodeOption) {
- PrintInodeList();
+ PrintInodeList(salvinfo);
return;
}
/* enumerate volumes in the partition.
* Fix up inodes on last volume in set (whether it is read-write
* or read-only).
*/
- if (GetVolumeSummary(singleVolumeNumber)) {
+ if (GetVolumeSummary(salvinfo, singleVolumeNumber)) {
goto retry;
}
- for (i = j = 0, vsp = volumeSummaryp, esp = vsp + nVolumes;
- i < nVolumesInInodeFile; i = j) {
- VolumeId rwvid = inodeSummary[i].RWvolumeId;
+ for (i = j = 0, vsp = salvinfo->volumeSummaryp, esp = vsp + salvinfo->nVolumes;
+ i < salvinfo->nVolumesInInodeFile; i = j) {
+ VolumeId rwvid = salvinfo->inodeSummary[i].RWvolumeId;
for (j = i;
- j < nVolumesInInodeFile && inodeSummary[j].RWvolumeId == rwvid;
+ j < salvinfo->nVolumesInInodeFile && salvinfo->inodeSummary[j].RWvolumeId == rwvid;
j++) {
- VolumeId vid = inodeSummary[j].volumeId;
+ VolumeId vid = salvinfo->inodeSummary[j].volumeId;
struct VolumeSummary *tsp;
/* Scan volume list (from partition root directory) looking for the
* current rw volume number in the volume list from the inode scan.
* delete it now. */
for (; vsp < esp && (vsp->header.parent < rwvid); vsp++) {
if (vsp->fileName)
- DeleteExtraVolumeHeaderFile(vsp);
+ DeleteExtraVolumeHeaderFile(salvinfo, vsp);
}
/* Now match up the volume summary info from the root directory with the
* entry in the volume list obtained from scanning inodes */
- inodeSummary[j].volSummary = NULL;
+ salvinfo->inodeSummary[j].volSummary = NULL;
for (tsp = vsp; tsp < esp && (tsp->header.parent == rwvid); tsp++) {
if (tsp->header.id == vid) {
- inodeSummary[j].volSummary = tsp;
+ salvinfo->inodeSummary[j].volSummary = tsp;
tsp->fileName = 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(&inodeSummary[i], j - i);
+ SalvageVolumeGroup(salvinfo, &salvinfo->inodeSummary[i], j - i);
}
/* 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)
- DeleteExtraVolumeHeaderFile(vsp);
+ DeleteExtraVolumeHeaderFile(salvinfo, vsp);
}
if (!singleVolumeNumber) /* Remove the FORCESALVAGE file */
- RemoveTheForce(fileSysPath);
+ RemoveTheForce(salvinfo->fileSysPath);
if (!Testing && singleVolumeNumber) {
#ifdef AFS_DEMAND_ATTACH_FS
/* unlock vol headers so the fs can attach them when we AskOnline */
- VLockFileReinit(&fileSysPartition->volLockFile);
+ VLockFileReinit(&salvinfo->fileSysPartition->volLockFile);
#endif /* AFS_DEMAND_ATTACH_FS */
- AskOnline(singleVolumeNumber, fileSysPartition->name);
+ AskOnline(salvinfo, singleVolumeNumber);
/* Step through the volumeSummary list and set all volumes on-line.
* The volumes were taken off-line in GetVolumeSummary.
*/
- for (j = 0; j < nVolumes; j++) {
- AskOnline(volumeSummaryp[j].header.id, fileSysPartition->name);
+ for (j = 0; j < salvinfo->nVolumes; j++) {
+ AskOnline(salvinfo, salvinfo->volumeSummaryp[j].header.id);
}
} else {
if (!Showmode)
Log("SALVAGING OF PARTITION %s%s COMPLETED\n",
- fileSysPartition->name, (Testing ? " (READONLY mode)" : ""));
+ salvinfo->fileSysPartition->name, (Testing ? " (READONLY mode)" : ""));
}
fclose(inodeFile); /* SalvageVolumeGroup was the last which needed it. */
}
void
-DeleteExtraVolumeHeaderFile(register struct VolumeSummary *vsp)
+DeleteExtraVolumeHeaderFile(struct SalvInfo *salvinfo, struct VolumeSummary *vsp)
{
char path[64];
- sprintf(path, "%s/%s", fileSysPath, vsp->fileName);
+ sprintf(path, "%s/%s", salvinfo->fileSysPath, vsp->fileName);
if (!Showmode)
Log("The volume header file %s is not associated with any actual data (%sdeleted)\n", path, (Testing ? "would have been " : ""));
if (!Testing) {
afs_int32 code;
- code = VDestroyVolumeDiskHeader(fileSysPartition, vsp->header.id, vsp->header.parent);
+ code = VDestroyVolumeDiskHeader(salvinfo->fileSysPartition, vsp->header.id, vsp->header.parent);
if (code) {
Log("Error %ld destroying volume disk header for volume %lu\n",
afs_printable_int32_ld(code),
int
CompareInodes(const void *_p1, const void *_p2)
{
- register const struct ViceInodeInfo *p1 = _p1;
- register const struct ViceInodeInfo *p2 = _p2;
+ const struct ViceInodeInfo *p1 = _p1;
+ const struct ViceInodeInfo *p2 = _p2;
if (p1->u.vnode.vnodeNumber == INODESPECIAL
|| p2->u.vnode.vnodeNumber == INODESPECIAL) {
VolumeId p1rwid, p2rwid;
}
void
-CountVolumeInodes(register struct ViceInodeInfo *ip, int maxInodes,
- register struct InodeSummary *summary)
+CountVolumeInodes(struct ViceInodeInfo *ip, int maxInodes,
+ struct InodeSummary *summary)
{
VolumeId volume = ip->u.vnode.volumeId;
VolumeId rwvolume = volume;
- register int n, nSpecial;
- register Unique maxunique;
+ int n, nSpecial;
+ Unique maxunique;
n = nSpecial = 0;
maxunique = 0;
while (maxInodes-- && volume == ip->u.vnode.volumeId) {
* be unlinked by the caller.
*/
int
-GetInodeSummary(FILE *inodeFile, VolumeId singleVolumeNumber)
+GetInodeSummary(struct SalvInfo *salvinfo, FILE *inodeFile, VolumeId singleVolumeNumber)
{
struct afs_stat status;
int forceSal, err;
char summaryFileName[50];
FILE *summaryFile;
#ifdef AFS_NT40_ENV
- char *dev = fileSysPath;
- char *wpath = fileSysPath;
+ char *dev = salvinfo->fileSysPath;
+ char *wpath = salvinfo->fileSysPath;
#else
- char *dev = fileSysDeviceName;
- char *wpath = filesysfulldev;
+ char *dev = salvinfo->fileSysDeviceName;
+ char *wpath = salvinfo->filesysfulldev;
#endif
- char *part = fileSysPath;
+ char *part = salvinfo->fileSysPath;
char *tdir;
+ int i;
/* This file used to come from vfsck; cobble it up ourselves now... */
if ((err =
- ListViceInodes(dev, fileSysPath, inodeFile,
+ ListViceInodes(dev, salvinfo->fileSysPath, inodeFile,
singleVolumeNumber ? OnlyOneVolume : 0,
singleVolumeNumber, &forceSal, forceR, wpath, NULL)) < 0) {
if (err == -2) {
ForceSalvage = 1;
}
fseek(inodeFile, 0L, SEEK_SET);
- inodeFd = fileno(inodeFile);
- if (inodeFd == -1 || afs_fstat(inodeFd, &status) == -1) {
+ salvinfo->inodeFd = fileno(inodeFile);
+ if (salvinfo->inodeFd == -1 || afs_fstat(salvinfo->inodeFd, &status) == -1) {
Abort("No inode description file for \"%s\"; not salvaged\n", dev);
}
tdir = (tmpdir ? tmpdir : part);
if (nInodes == 0) {
fclose(summaryFile);
if (!singleVolumeNumber) /* Remove the FORCESALVAGE file */
- RemoveTheForce(fileSysPath);
+ RemoveTheForce(salvinfo->fileSysPath);
else {
struct VolumeSummary *vsp;
int i;
- GetVolumeSummary(singleVolumeNumber);
+ GetVolumeSummary(salvinfo, singleVolumeNumber);
- for (i = 0, vsp = volumeSummaryp; i < nVolumes; i++) {
+ for (i = 0, vsp = salvinfo->volumeSummaryp; i < salvinfo->nVolumes; i++) {
if (vsp->fileName)
- DeleteExtraVolumeHeaderFile(vsp);
+ DeleteExtraVolumeHeaderFile(salvinfo, vsp);
}
}
Log("%s vice inodes on %s; not salvaged\n",
("Unable to allocate enough space to read inode table; %s not salvaged\n",
dev);
}
- if (read(inodeFd, ip, st_size) != st_size) {
+ if (read(salvinfo->inodeFd, ip, st_size) != st_size) {
fclose(summaryFile);
Abort("Unable to read inode table; %s not salvaged\n", dev);
}
qsort(ip, nInodes, sizeof(struct ViceInodeInfo), CompareInodes);
- if (afs_lseek(inodeFd, 0, SEEK_SET) == -1
- || write(inodeFd, ip, st_size) != st_size) {
+ if (afs_lseek(salvinfo->inodeFd, 0, SEEK_SET) == -1
+ || write(salvinfo->inodeFd, ip, st_size) != st_size) {
fclose(summaryFile);
Abort("Unable to rewrite inode table; %s not salvaged\n", dev);
}
if (status.st_size != 0) {
int ret;
unsigned long st_status=(unsigned long)status.st_size;
- inodeSummary = (struct InodeSummary *)malloc(st_status);
- assert(inodeSummary != NULL);
+ salvinfo->inodeSummary = (struct InodeSummary *)malloc(st_status);
+ assert(salvinfo->inodeSummary != NULL);
/* For GNU we need to do lseek to get the file pointer moved. */
assert(afs_lseek(fileno(summaryFile), 0, SEEK_SET) == 0);
- ret = read(fileno(summaryFile), inodeSummary, st_status);
+ ret = read(fileno(summaryFile), salvinfo->inodeSummary, st_status);
assert(ret == st_status);
}
- nVolumesInInodeFile =(unsigned long)(status.st_size) / sizeof(struct InodeSummary);
- Log("%d nVolumesInInodeFile %lu \n",nVolumesInInodeFile,(unsigned long)(status.st_size));
+ salvinfo->nVolumesInInodeFile =(unsigned long)(status.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;
}
int
CompareVolumes(const void *_p1, const void *_p2)
{
- register const struct VolumeSummary *p1 = _p1;
- register const struct VolumeSummary *p2 = _p2;
+ const struct VolumeSummary *p1 = _p1;
+ const struct VolumeSummary *p2 = _p2;
if (p1->header.parent != p2->header.parent)
return p1->header.parent < p2->header.parent ? -1 : 1;
if (p1->header.id == p1->header.parent) /* p1 is rw volume */
* @note for non-DAFS, always returns 1
*/
static int
-AskVolumeSummary(VolumeId singleVolumeNumber)
+AskVolumeSummary(struct SalvInfo *salvinfo, VolumeId singleVolumeNumber)
{
afs_int32 code = 1;
#if defined(FSSYNC_BUILD_CLIENT) && defined(AFS_DEMAND_ATTACH_FS)
memset(&res, 0, sizeof(res));
- code = FSYNC_VGCQuery(fileSysPartition->name, singleVolumeNumber, &q_res, &res);
+ code = FSYNC_VGCQuery(salvinfo->fileSysPartition->name, singleVolumeNumber, &q_res, &res);
/*
* We must wait for the partition to finish scanning before
*/
if (code == SYNC_FAILED && res.hdr.reason == FSYNC_PART_SCANNING) {
Log("waiting for fileserver to finish scanning partition %s...\n",
- fileSysPartition->name);
+ salvinfo->fileSysPartition->name);
for (i = 1; code == SYNC_FAILED && res.hdr.reason == FSYNC_PART_SCANNING; i++) {
/* linearly ramp up from 1 to 10 seconds; nothing fancy,
* polled only once every ten seconds. */
sleep((i > 10) ? (i = 10) : i);
- code = FSYNC_VGCQuery(fileSysPartition->name, singleVolumeNumber, &q_res, &res);
+ code = FSYNC_VGCQuery(salvinfo->fileSysPartition->name, singleVolumeNumber, &q_res, &res);
}
}
Log("fileserver refused VGCQuery request for volume %lu on "
"partition %s, code %ld reason %ld\n",
afs_printable_uint32_lu(singleVolumeNumber),
- fileSysPartition->name,
+ salvinfo->fileSysPartition->name,
afs_printable_int32_ld(code),
afs_printable_int32_ld(res.hdr.reason));
goto done;
#ifdef SALVSYNC_BUILD_CLIENT
if (SALVSYNC_LinkVolume(q_res.rw,
singleVolumeNumber,
- fileSysPartition->name,
+ salvinfo->fileSysPartition->name,
NULL) != SYNC_OK) {
Log("schedule request failed\n");
}
Exit(SALSRV_EXIT_VOLGROUP_LINK);
}
- volumeSummaryp = malloc(VOL_VG_MAX_VOLS * sizeof(struct VolumeSummary));
- assert(volumeSummaryp != NULL);
+ salvinfo->volumeSummaryp = malloc(VOL_VG_MAX_VOLS * sizeof(struct VolumeSummary));
+ assert(salvinfo->volumeSummaryp != NULL);
- nVolumes = 0;
- vsp = volumeSummaryp;
+ salvinfo->nVolumes = 0;
+ vsp = salvinfo->volumeSummaryp;
for (i = 0; i < VOL_VG_MAX_VOLS; i++) {
char name[VMAXPATHLEN];
/* AskOffline for singleVolumeNumber was called much earlier */
if (q_res.children[i] != singleVolumeNumber) {
- AskOffline(q_res.children[i], fileSysPartition->name);
- if (LockVolume(q_res.children[i])) {
+ AskOffline(salvinfo, q_res.children[i]);
+ if (LockVolume(salvinfo, q_res.children[i])) {
/* need to retry */
return -1;
}
}
- code = VReadVolumeDiskHeader(q_res.children[i], fileSysPartition, &diskHdr);
+ code = VReadVolumeDiskHeader(q_res.children[i], salvinfo->fileSysPartition, &diskHdr);
if (code) {
Log("Cannot read header for %lu; trying to salvage group anyway\n",
afs_printable_uint32_lu(q_res.children[i]));
DiskToVolumeHeader(&vsp->header, &diskHdr);
VolumeExternalName_r(q_res.children[i], name, sizeof(name));
vsp->fileName = ToString(name);
- nVolumes++;
+ salvinfo->nVolumes++;
vsp++;
}
- qsort(volumeSummaryp, nVolumes, sizeof(struct VolumeSummary),
+ qsort(salvinfo->volumeSummaryp, salvinfo->nVolumes, sizeof(struct VolumeSummary),
CompareVolumes);
}
done:
afs_int32 totalVolumes; /**< max # of vols we should encounter (the
* # of vols we've alloc'd memory for) */
int retry; /**< do we need to retry vol lock/checkout? */
+ struct SalvInfo *salvinfo; /**< salvage job info */
};
/**
struct SalvageScanParams *params;
struct VolumeSummary summary;
VolumeId singleVolumeNumber;
+ struct SalvInfo *salvinfo;
params = (struct SalvageScanParams *)rock;
singleVolumeNumber = params->singleVolumeNumber;
+ salvinfo = params->salvinfo;
DiskToVolumeHeader(&summary.header, hdr);
* the last try looking at it; avoid AskOffline'ing the same vol
* multiple times */
- if (singleVolumeNumber
+ if (singleVolumeNumber
&& summary.header.id != singleVolumeNumber) {
/* don't offline singleVolumeNumber; we already did that
* earlier */
- AskOffline(summary.header.id, fileSysPartition->name);
+ AskOffline(salvinfo, summary.header.id);
#ifdef AFS_DEMAND_ATTACH_FS
if (!badname) {
/* don't lock the volume if the header is bad, since we're
* about to delete it anyway. */
- if (LockVolume(summary.header.id)) {
+ if (LockVolume(salvinfo, summary.header.id)) {
params->retry = 1;
return -1;
}
}
/**
- * Populates volumeSummaryp with volume summary information, either by asking
+ * Populates salvinfo->volumeSummaryp with volume summary information, either by asking
* the fileserver for VG information, or by scanning the /vicepX partition.
*
* @param[in] singleVolumeNumber the volume ID of the single volume group we
* volumes must be retried
*/
int
-GetVolumeSummary(VolumeId singleVolumeNumber)
+GetVolumeSummary(struct SalvInfo *salvinfo, VolumeId singleVolumeNumber)
{
afs_int32 nvols = 0;
struct SalvageScanParams params;
int code;
- code = AskVolumeSummary(singleVolumeNumber);
+ code = AskVolumeSummary(salvinfo, singleVolumeNumber);
if (code == 0) {
/* we successfully got the vol information from the fileserver; no
* need to scan the partition */
if (!singleVolumeNumber) {
/* Count how many volumes we have in /vicepX */
- code = VWalkVolumeHeaders(fileSysPartition, fileSysPath, CountHeader,
+ code = VWalkVolumeHeaders(salvinfo->fileSysPartition, salvinfo->fileSysPath, CountHeader,
NULL, &nvols);
if (code < 0) {
- Abort("Can't read directory %s; not salvaged\n", fileSysPath);
+ Abort("Can't read directory %s; not salvaged\n", salvinfo->fileSysPath);
}
if (!nvols)
nvols = 1;
nvols = VOL_VG_MAX_VOLS;
}
- volumeSummaryp = malloc(nvols * sizeof(struct VolumeSummary));
- assert(volumeSummaryp != NULL);
+ salvinfo->volumeSummaryp = malloc(nvols * sizeof(struct VolumeSummary));
+ assert(salvinfo->volumeSummaryp != NULL);
params.singleVolumeNumber = singleVolumeNumber;
- params.vsp = volumeSummaryp;
+ params.vsp = salvinfo->volumeSummaryp;
params.nVolumes = 0;
params.totalVolumes = nvols;
params.retry = 0;
+ params.salvinfo = salvinfo;
/* walk the partition directory of volume headers and record the info
* about them; unlinking invalid headers */
- code = VWalkVolumeHeaders(fileSysPartition, fileSysPath, RecordHeader,
+ code = VWalkVolumeHeaders(salvinfo->fileSysPartition, salvinfo->fileSysPath, RecordHeader,
UnlinkHeader, ¶ms);
if (params.retry) {
/* we apparently need to retry checking-out/locking volumes */
if (code < 0) {
Abort("Failed to get volume header summary\n");
}
- nVolumes = params.nVolumes;
+ salvinfo->nVolumes = params.nVolumes;
- qsort(volumeSummaryp, nVolumes, sizeof(struct VolumeSummary),
+ qsort(salvinfo->volumeSummaryp, salvinfo->nVolumes, sizeof(struct VolumeSummary),
CompareVolumes);
return 0;
* a RO only site, then the RO volume. For now, be cautious and hunt carefully.
*/
Inode
-FindLinkHandle(register struct InodeSummary *isp, int nVols,
+FindLinkHandle(struct InodeSummary *isp, int nVols,
struct ViceInodeInfo *allInodes)
{
int i, j;
}
int
-CreateLinkTable(register struct InodeSummary *isp, Inode ino)
+CreateLinkTable(struct SalvInfo *salvinfo, struct InodeSummary *isp, Inode ino)
{
struct versionStamp version;
FdHandle_t *fdP;
if (!VALID_INO(ino))
ino =
- IH_CREATE(NULL, fileSysDevice, fileSysPath, 0, isp->volumeId,
+ IH_CREATE(NULL, salvinfo->fileSysDevice, salvinfo->fileSysPath, 0, isp->volumeId,
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);
- IH_INIT(VGLinkH, fileSysDevice, isp->RWvolumeId, ino);
- fdP = IH_OPEN(VGLinkH);
+ 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);
nt_SVG(void *arg)
{
SVGParms_t *parms = (SVGParms_t *) arg;
- DoSalvageVolumeGroup(parms->svgp_inodeSummaryp, parms->svgp_count);
+ DoSalvageVolumeGroup(parms->svgp_salvinfo, parms->svgp_inodeSummaryp, parms->svgp_count);
return NULL;
}
void
-SalvageVolumeGroup(register struct InodeSummary *isp, int nVols)
+SalvageVolumeGroup(struct SalvInfo *salvinfo, struct InodeSummary *isp, int nVols)
{
pthread_t tid;
pthread_attr_t tattr;
SVGParms_t parms;
/* Initialize per volume global variables, even if later code does so */
- VolumeChanged = 0;
- VGLinkH = NULL;
- VGLinkH_cnt = 0;
- memset(&VolInfo, 0, sizeof(VolInfo));
+ salvinfo->VolumeChanged = 0;
+ salvinfo->VGLinkH = NULL;
+ salvinfo->VGLinkH_cnt = 0;
+ memset(&salvinfo->VolInfo, 0, sizeof(salvinfo->VolInfo));
parms.svgp_inodeSummaryp = isp;
parms.svgp_count = nVols;
+ parms.svgp_salvinfo = salvinfo;
code = pthread_attr_init(&tattr);
if (code) {
Log("Failed to salvage volume group %u: pthread_attr_init()\n",
#endif /* AFS_NT40_ENV */
void
-DoSalvageVolumeGroup(register struct InodeSummary *isp, int nVols)
+DoSalvageVolumeGroup(struct SalvInfo *salvinfo, struct InodeSummary *isp, int nVols)
{
struct ViceInodeInfo *inodes, *allInodes, *ip;
int i, totalInodes, size, salvageTo;
int VGLinkH_p1 =0;
FdHandle_t *fdP = NULL;
- VGLinkH_cnt = 0;
+ salvinfo->VGLinkH_cnt = 0;
haveRWvolume = (isp->volumeId == isp->RWvolumeId
&& isp->nSpecialInodes > 0);
if ((!ShowMounts) || (ShowMounts && !haveRWvolume)) {
- if (!ForceSalvage && QuickCheck(isp, nVols))
+ if (!ForceSalvage && QuickCheck(salvinfo, isp, nVols))
return;
}
if (ShowMounts && !haveRWvolume)
* for the partition, if all the inodes
* had been read into memory */
assert(afs_lseek
- (inodeFd, isp->index * sizeof(struct ViceInodeInfo),
+ (salvinfo->inodeFd, isp->index * sizeof(struct ViceInodeInfo),
SEEK_SET) != -1);
- assert(read(inodeFd, inodes, size) == size);
+ assert(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_NAMEI_ENV
ino = FindLinkHandle(isp, nVols, allInodes);
if (VALID_INO(ino)) {
- IH_INIT(VGLinkH, fileSysDevice, isp->RWvolumeId, ino);
- fdP = IH_OPEN(VGLinkH);
+ IH_INIT(salvinfo->VGLinkH, salvinfo->fileSysDevice, isp->RWvolumeId, ino);
+ fdP = IH_OPEN(salvinfo->VGLinkH);
}
if (!VALID_INO(ino) || fdP == NULL) {
Log("%s link table for volume %u.\n",
Testing ? "Would have recreated" : "Recreating", isp->RWvolumeId);
if (Testing) {
- IH_INIT(VGLinkH, fileSysDevice, -1, -1);
+ IH_INIT(salvinfo->VGLinkH, salvinfo->fileSysDevice, -1, -1);
} else {
int i, j;
struct ViceInodeInfo *ip;
- CreateLinkTable(isp, ino);
- fdP = IH_OPEN(VGLinkH);
+ 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++) {
if (fdP)
FDH_REALLYCLOSE(fdP);
#else
- IH_INIT(VGLinkH, fileSysDevice, -1, -1);
+ IH_INIT(salvinfo->VGLinkH, salvinfo->fileSysDevice, -1, -1);
#endif
/* Salvage in reverse order--read/write volume last; this way any
* way the whole RO volume can be deleted, below, if anything goes wrong */
for (check = 1; check >= 0; check--) {
int deleteMe;
- if (SalvageVolumeHeaderFile(lisp, allInodes, rw, check, &deleteMe)
+ if (SalvageVolumeHeaderFile(salvinfo, lisp, allInodes, rw, check, &deleteMe)
== -1) {
- MaybeZapVolume(lisp, "Volume header", deleteMe, check);
+ MaybeZapVolume(salvinfo, lisp, "Volume header", deleteMe, check);
if (rw && deleteMe) {
haveRWvolume = 0; /* This will cause its inodes to be deleted--since salvage
* volume won't be called */
}
if (rw && check == 1)
continue;
- if (SalvageVnodes(isp, lisp, allInodes, check) == -1) {
- MaybeZapVolume(lisp, "Vnode index", 0, check);
+ if (SalvageVnodes(salvinfo, isp, lisp, allInodes, check) == -1) {
+ MaybeZapVolume(salvinfo, lisp, "Vnode index", 0, check);
break;
}
}
for (ip = inodes; totalInodes; ip++, totalInodes--) {
static int TraceBadLinkCounts = 0;
#ifdef AFS_NAMEI_ENV
- if (VGLinkH->ih_ino == ip->inodeNumber) {
- dec_VGLinkH = ip->linkCount - VGLinkH_cnt;
+ if (salvinfo->VGLinkH->ih_ino == ip->inodeNumber) {
+ dec_VGLinkH = ip->linkCount - salvinfo->VGLinkH_cnt;
VGLinkH_p1 = ip->u.param[0];
continue; /* Deal with this last. */
}
while (ip->linkCount > 0) {
/* below used to assert, not break */
if (!Testing) {
- if (IH_DEC(VGLinkH, ip->inodeNumber, ip->u.param[0])) {
+ if (IH_DEC(salvinfo->VGLinkH, ip->inodeNumber, ip->u.param[0])) {
Log("idec failed. inode %s errno %d\n",
PrintInode(NULL, ip->inodeNumber), errno);
break;
while (ip->linkCount < 0) {
/* these used to be asserts */
if (!Testing) {
- if (IH_INC(VGLinkH, ip->inodeNumber, ip->u.param[0])) {
+ if (IH_INC(salvinfo->VGLinkH, ip->inodeNumber, ip->u.param[0])) {
Log("iinc failed. inode %s errno %d\n",
PrintInode(NULL, ip->inodeNumber), errno);
break;
}
#ifdef AFS_NAMEI_ENV
while (dec_VGLinkH > 0) {
- if (IH_DEC(VGLinkH, VGLinkH->ih_ino, VGLinkH_p1) < 0) {
+ if (IH_DEC(salvinfo->VGLinkH, salvinfo->VGLinkH->ih_ino, VGLinkH_p1) < 0) {
Log("idec failed on link table, errno = %d\n", errno);
}
dec_VGLinkH--;
}
while (dec_VGLinkH < 0) {
- if (IH_INC(VGLinkH, VGLinkH->ih_ino, VGLinkH_p1) < 0) {
+ if (IH_INC(salvinfo->VGLinkH, salvinfo->VGLinkH->ih_ino, VGLinkH_p1) < 0) {
Log("iinc failed on link table, errno = %d\n", errno);
}
dec_VGLinkH++;
free(inodes);
/* Directory consistency checks on the rw volume */
if (haveRWvolume)
- SalvageVolume(isp, VGLinkH);
- IH_RELEASE(VGLinkH);
+ SalvageVolume(salvinfo, isp, salvinfo->VGLinkH);
+ IH_RELEASE(salvinfo->VGLinkH);
if (canfork && !debug) {
ShowLog = 0;
}
int
-QuickCheck(register struct InodeSummary *isp, int nVols)
+QuickCheck(struct SalvInfo *salvinfo, struct InodeSummary *isp, int nVols)
{
/* Check headers BEFORE forking */
- register int i;
+ int i;
IHandle_t *h;
for (i = 0; i < nVols; i++) {
continue;
return 0;
}
- IH_INIT(h, fileSysDevice, vs->header.parent, vs->header.volumeInfo);
+ IH_INIT(h, salvinfo->fileSysDevice, vs->header.parent, vs->header.volumeInfo);
if (IH_IREAD(h, 0, (char *)&volHeader, sizeof(volHeader))
== sizeof(volHeader)
&& volHeader.stamp.magic == VOLUMEINFOMAGIC
*/
int
-SalvageVolumeHeaderFile(register struct InodeSummary *isp,
- register struct ViceInodeInfo *inodes, int RW,
+SalvageVolumeHeaderFile(struct SalvInfo *salvinfo, struct InodeSummary *isp,
+ struct ViceInodeInfo *inodes, int RW,
int check, int *deleteMe)
{
int i;
- register struct ViceInodeInfo *ip;
+ struct ViceInodeInfo *ip;
int allinodesobsolete = 1;
struct VolumeDiskHeader diskHeader;
afs_int32 (*writefunc)(VolumeDiskHeader_t *, struct DiskPartition64 *) = NULL;
int *skip;
+ struct VolumeHeader tempHeader;
+ struct afs_inode_info stuff[MAXINODETYPE];
/* keeps track of special inodes that are probably 'good'; they are
* referenced in the vol header, and are included in the given inodes
* if we detect duplicate special inodes */
}
+ init_inode_info(&tempHeader, stuff);
+
/*
* First, look at the special inodes and see if any are referenced by
* the existing volume header. If we find duplicate special inodes, we
}
if (!check)
- VGLinkH_cnt++; /* one for every header. */
+ salvinfo->VGLinkH_cnt++; /* one for every header. */
if (!RW && !check && isp->volSummary) {
ClearROInUseBit(isp->volSummary);
* And we may have recreated the link table earlier, so set the
* RW header as well.
*/
- if (VALID_INO(VGLinkH->ih_ino)) {
- *stuff[i].inode = VGLinkH->ih_ino;
+ if (VALID_INO(salvinfo->VGLinkH->ih_ino)) {
+ *stuff[i].inode = salvinfo->VGLinkH->ih_ino;
}
continue;
}
- if (SalvageHeader(&stuff[i], isp, check, deleteMe) == -1 && check)
+ if (SalvageHeader(salvinfo, &stuff[i], isp, check, deleteMe) == -1 && check)
return -1;
}
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/%s", fileSysPath, headerName);
+ (void)afs_snprintf(path, sizeof path, "%s/%s", salvinfo->fileSysPath, headerName);
if (check) {
Log("No header file for volume %u\n", isp->volumeId);
return -1;
(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/%s", fileSysPath, headerName);
+ (void)afs_snprintf(path, sizeof path, "%s/%s", salvinfo->fileSysPath, headerName);
Log("Header file %s is damaged or no longer valid%s\n", path,
(check ? "" : "; repairing"));
} else {
afs_int32 code;
VolumeHeaderToDisk(&diskHeader, &tempHeader);
- code = (*writefunc)(&diskHeader, fileSysPartition);
+ code = (*writefunc)(&diskHeader, salvinfo->fileSysPartition);
if (code) {
Log("Error %ld writing volume header file for volume %lu\n",
afs_printable_int32_ld(code),
}
}
}
- IH_INIT(isp->volSummary->volumeInfoHandle, fileSysDevice, isp->RWvolumeId,
+ IH_INIT(isp->volSummary->volumeInfoHandle, salvinfo->fileSysDevice, isp->RWvolumeId,
isp->volSummary->header.volumeInfo);
return 0;
}
int
-SalvageHeader(register struct stuff *sp, struct InodeSummary *isp, int check,
- int *deleteMe)
+SalvageHeader(struct SalvInfo *salvinfo, struct afs_inode_info *sp,
+ struct InodeSummary *isp, int check, int *deleteMe)
{
union {
VolumeDiskData volumeInfo;
(Testing ? "it would have recreated it" : "recreating"));
if (!Testing) {
*(sp->inode) =
- IH_CREATE(NULL, fileSysDevice, fileSysPath, 0, isp->volumeId,
+ IH_CREATE(NULL, salvinfo->fileSysDevice, salvinfo->fileSysPath, 0, isp->volumeId,
INODESPECIAL, sp->inodeType, isp->RWvolumeId);
if (!VALID_INO(*(sp->inode)))
Abort
recreate = 1;
}
- IH_INIT(specH, fileSysDevice, isp->RWvolumeId, *(sp->inode));
+ IH_INIT(specH, salvinfo->fileSysDevice, isp->RWvolumeId, *(sp->inode));
fdP = IH_OPEN(specH);
if (OKToZap && (fdP == NULL) && BadError(errno)) {
/* bail out early and destroy the volume */
Log("Part of the header (%s) is corrupted; recreating\n",
sp->description);
recreate = 1;
+ /* header can be garbage; make sure we don't read garbage data from
+ * it below */
+ memset(&header, 0, sizeof(header));
}
if (sp->inodeType == VI_VOLINFO
&& header.volumeInfo.destroyMe == DESTROY_ME) {
FDH_REALLYCLOSE(fdP);
IH_RELEASE(specH);
if (sp->inodeType == VI_VOLINFO) {
- VolInfo = header.volumeInfo;
+ salvinfo->VolInfo = header.volumeInfo;
if (check) {
char update[25];
- if (VolInfo.updateDate) {
- strcpy(update, TimeStamp(VolInfo.updateDate, 0));
+
+ if (salvinfo->VolInfo.updateDate) {
+ strcpy(update, TimeStamp(salvinfo->VolInfo.updateDate, 0));
if (!Showmode)
- Log("%s (%u) %supdated %s\n", VolInfo.name, VolInfo.id,
+ Log("%s (%u) %supdated %s\n", salvinfo->VolInfo.name,
+ salvinfo->VolInfo.id,
(Testing ? "it would have been " : ""), update);
} else {
- strcpy(update, TimeStamp(VolInfo.creationDate, 0));
+ strcpy(update, TimeStamp(salvinfo->VolInfo.creationDate, 0));
if (!Showmode)
- Log("%s (%u) not updated (created %s)\n", VolInfo.name,
- VolInfo.id, update);
+ Log("%s (%u) not updated (created %s)\n",
+ salvinfo->VolInfo.name, salvinfo->VolInfo.id, update);
}
}
}
int
-SalvageVnodes(register struct InodeSummary *rwIsp,
- register struct InodeSummary *thisIsp,
- register struct ViceInodeInfo *inodes, int check)
+SalvageVnodes(struct SalvInfo *salvinfo,
+ struct InodeSummary *rwIsp,
+ struct InodeSummary *thisIsp,
+ struct ViceInodeInfo *inodes, int check)
{
int ilarge, ismall, ioffset, RW, nInodes;
ioffset = rwIsp->index + rwIsp->nSpecialInodes; /* first inode */
RW = (rwIsp == thisIsp);
nInodes = (rwIsp->nInodes - rwIsp->nSpecialInodes);
ismall =
- SalvageIndex(thisIsp->volSummary->header.smallVnodeIndex, vSmall, RW,
+ SalvageIndex(salvinfo, thisIsp->volSummary->header.smallVnodeIndex, vSmall, RW,
&inodes[ioffset], nInodes, thisIsp->volSummary, check);
if (check && ismall == -1)
return -1;
ilarge =
- SalvageIndex(thisIsp->volSummary->header.largeVnodeIndex, vLarge, RW,
+ SalvageIndex(salvinfo, thisIsp->volSummary->header.largeVnodeIndex, vLarge, RW,
&inodes[ioffset], nInodes, thisIsp->volSummary, check);
return (ilarge == 0 && ismall == 0 ? 0 : -1);
}
int
-SalvageIndex(Inode ino, VnodeClass class, int RW,
- register struct ViceInodeInfo *ip, int nInodes,
- struct VolumeSummary *volSummary, int check)
+SalvageIndex(struct SalvInfo *salvinfo, Inode ino, VnodeClass class, int RW,
+ struct ViceInodeInfo *ip, int nInodes,
+ struct VolumeSummary *volSummary, int check)
{
VolumeId volumeNumber;
char buf[SIZEOF_LARGEDISKVNODE];
FdHandle_t *fdP;
volumeNumber = volSummary->header.id;
- IH_INIT(handle, fileSysDevice, volSummary->header.parent, ino);
+ IH_INIT(handle, salvinfo->fileSysDevice, volSummary->header.parent, ino);
fdP = IH_OPEN(handle);
assert(fdP != NULL);
file = FDH_FDOPEN(fdP, "r+");
* don't bother for read-only or backup volumes */
#ifdef notdef /* This is done elsewhere */
if (ShowRootFiles && RW && vnode->owner == 0 && vnodeNumber != 1)
- Log("OWNER IS ROOT %s %u dir %u vnode %u author %u owner %u mode %o\n", VolInfo.name, volumeNumber, vnode->parent, vnodeNumber, vnode->author, vnode->owner, vnode->modeBits);
+ Log("OWNER IS ROOT %s %u dir %u vnode %u author %u owner %u mode %o\n", salvinfo->VolInfo.name, volumeNumber, vnode->parent, vnodeNumber, vnode->author, vnode->owner, vnode->modeBits);
#endif
if (VNDISK_GET_INO(vnode) == 0) {
if (RW) {
/* For RW volume, look for vnode with matching inode number;
* if no such match, take the first determined by our sort
* order */
- register struct ViceInodeInfo *lip = ip;
- register int lnInodes = nInodes;
+ struct ViceInodeInfo *lip = ip;
+ int lnInodes = nInodes;
while (lnInodes
&& lip->u.vnode.vnodeNumber == vnodeNumber) {
if (VNDISK_GET_INO(vnode) == lip->inodeNumber) {
/*
* Because of the possibility of the uniquifier overflows (> 4M)
* we compare them modulo the low 22-bits; we shouldn't worry
- * about mismatching since they shouldn't to many old
+ * about mismatching since they shouldn't to many old
* uniquifiers of the same vnode...
*/
if (IUnique(vu) != IUnique(iu)) {
memset(vnode, 0, vcp->diskSize);
vnodeChanged = 1;
} else {
- /* Should not reach here becuase we checked for
+ /* Should not reach here becuase we checked for
* (inodeNumber == 0) above. And where we zero the vnode,
* we also goto vnodeDone.
*/
(handle, vnodeIndexOffset(vcp, vnodeNumber),
(char *)vnode, vcp->diskSize)
== vcp->diskSize);
- VolumeChanged = 1; /* For break call back */
+ salvinfo->VolumeChanged = 1; /* For break call back */
}
}
}
}
struct VnodeEssence *
-CheckVnodeNumber(VnodeId vnodeNumber)
+CheckVnodeNumber(struct SalvInfo *salvinfo, VnodeId vnodeNumber)
{
VnodeClass class;
struct VnodeInfo *vip;
int offset;
class = vnodeIdToClass(vnodeNumber);
- vip = &vnodeInfo[class];
+ vip = &salvinfo->vnodeInfo[class];
offset = vnodeIdToBitNumber(vnodeNumber);
return (offset >= vip->nVnodes ? NULL : &vip->vnodes[offset]);
}
void
-CopyOnWrite(register struct DirSummary *dir)
+CopyOnWrite(struct SalvInfo *salvinfo, struct DirSummary *dir)
{
/* Copy the directory unconditionally if we are going to change it:
* not just if was cloned.
DFlush(); /* Well justified paranoia... */
code =
- IH_IREAD(vnodeInfo[vLarge].handle,
+ IH_IREAD(salvinfo->vnodeInfo[vLarge].handle,
vnodeIndexOffset(vcp, dir->vnodeNumber), (char *)&vnode,
sizeof(vnode));
assert(code == sizeof(vnode));
* crashed before the versions were written to disk.
*/
newinode =
- IH_CREATE(dir->ds_linkH, fileSysDevice, fileSysPath, 0, dir->rwVid,
+ IH_CREATE(dir->ds_linkH, salvinfo->fileSysDevice, salvinfo->fileSysPath, 0, dir->rwVid,
dir->vnodeNumber, vnode.uniquifier, vnode.dataVersion +=
200);
assert(VALID_INO(newinode));
- assert(CopyInode(fileSysDevice, oldinode, newinode, dir->rwVid) == 0);
+ assert(CopyInode(salvinfo->fileSysDevice, oldinode, newinode, dir->rwVid) == 0);
vnode.cloned = 0;
VNDISK_SET_INO(&vnode, newinode);
code =
- IH_IWRITE(vnodeInfo[vLarge].handle,
+ IH_IWRITE(salvinfo->vnodeInfo[vLarge].handle,
vnodeIndexOffset(vcp, dir->vnodeNumber), (char *)&vnode,
sizeof(vnode));
assert(code == sizeof(vnode));
SetSalvageDirHandle(&dir->dirHandle, dir->dirHandle.dirh_handle->ih_vid,
- fileSysDevice, newinode);
+ salvinfo->fileSysDevice, newinode,
+ &salvinfo->VolumeChanged);
/* Don't delete the original inode right away, because the directory is
* still being scanned.
*/
}
/*
- * This function should either successfully create a new dir, or give up
- * and leave things the way they were. In particular, if it fails to write
- * the new dir properly, it should return w/o changing the reference to the
+ * This function should either successfully create a new dir, or give up
+ * and leave things the way they were. In particular, if it fails to write
+ * the new dir properly, it should return w/o changing the reference to the
* old dir.
*/
void
-CopyAndSalvage(register struct DirSummary *dir)
+CopyAndSalvage(struct SalvInfo *salvinfo, struct DirSummary *dir)
{
struct VnodeDiskObject vnode;
struct VnodeClassInfo *vcp = &VnodeClassInfo[vLarge];
return;
Log("Salvaging directory %u...\n", dir->vnodeNumber);
lcode =
- IH_IREAD(vnodeInfo[vLarge].handle,
+ IH_IREAD(salvinfo->vnodeInfo[vLarge].handle,
vnodeIndexOffset(vcp, dir->vnodeNumber), (char *)&vnode,
sizeof(vnode));
assert(lcode == sizeof(vnode));
* crashed before the versions were written to disk.
*/
newinode =
- IH_CREATE(dir->ds_linkH, fileSysDevice, fileSysPath, 0, dir->rwVid,
+ IH_CREATE(dir->ds_linkH, salvinfo->fileSysDevice, salvinfo->fileSysPath, 0, dir->rwVid,
dir->vnodeNumber, vnode.uniquifier, vnode.dataVersion +=
200);
assert(VALID_INO(newinode));
- SetSalvageDirHandle(&newdir, dir->rwVid, fileSysDevice, newinode);
+ SetSalvageDirHandle(&newdir, dir->rwVid, salvinfo->fileSysDevice, newinode,
+ &salvinfo->VolumeChanged);
- /* Assign . and .. vnode numbers from dir and vnode.parent.
+ /* Assign . and .. vnode numbers from dir and vnode.parent.
* The uniquifier for . is in the vnode.
- * The uniquifier for .. might be set to a bogus value of 1 and
+ * The uniquifier for .. might be set to a bogus value of 1 and
* the salvager will later clean it up.
*/
- if (vnode.parent && (vnodeEssence = CheckVnodeNumber(vnode.parent))) {
+ if (vnode.parent && (vnodeEssence = CheckVnodeNumber(salvinfo, vnode.parent))) {
parentUnique = (vnodeEssence->unique ? vnodeEssence->unique : 1);
}
code =
length = Length(&newdir);
VNDISK_SET_LEN(&vnode, length);
lcode =
- IH_IWRITE(vnodeInfo[vLarge].handle,
+ IH_IWRITE(salvinfo->vnodeInfo[vLarge].handle,
vnodeIndexOffset(vcp, dir->vnodeNumber), (char *)&vnode,
sizeof(vnode));
assert(lcode == sizeof(vnode));
#if 0
#ifdef AFS_NT40_ENV
- nt_sync(fileSysDevice);
+ 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
- vnodeInfo[vLarge].handle->ih_synced = 1;
+ salvinfo->vnodeInfo[vLarge].handle->ih_synced = 1;
#endif
/* 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);
assert(code == 0);
dir->dirHandle = newdir;
}
+/**
+ * arguments for JudgeEntry.
+ */
+struct judgeEntry_params {
+ struct DirSummary *dir; /**< directory we're examining entries in */
+ struct SalvInfo *salvinfo; /**< SalvInfo for the current salvage job */
+};
+
int
-JudgeEntry(void *dirVal, char *name, afs_int32 vnodeNumber,
+JudgeEntry(void *arock, char *name, afs_int32 vnodeNumber,
afs_int32 unique)
{
- struct DirSummary *dir = (struct DirSummary *)dirVal;
+ struct judgeEntry_params *params = arock;
+ struct DirSummary *dir = params->dir;
+ struct SalvInfo *salvinfo = params->salvinfo;
struct VnodeEssence *vnodeEssence;
afs_int32 dirOrphaned, todelete;
- dirOrphaned = IsVnodeOrphaned(dir->vnodeNumber);
+ dirOrphaned = IsVnodeOrphaned(salvinfo, dir->vnodeNumber);
- vnodeEssence = CheckVnodeNumber(vnodeNumber);
+ vnodeEssence = CheckVnodeNumber(salvinfo, vnodeNumber);
if (vnodeEssence == NULL) {
if (!Showmode) {
Log("dir vnode %u: invalid entry deleted: %s/%s (vnode %u, unique %u)\n", dir->vnodeNumber, dir->name ? dir->name : "??", name, vnodeNumber, unique);
}
if (!Testing) {
- CopyOnWrite(dir);
+ CopyOnWrite(salvinfo, dir);
assert(Delete(&dir->dirHandle, name) == 0);
}
return 0;
}
#ifdef AFS_AIX_ENV
#ifndef AFS_NAMEI_ENV
- /* On AIX machines, don't allow entries to point to inode 0. That is a special
+ /* On AIX machines, don't allow entries to point to inode 0. That is a special
* mount inode for the partition. If this inode were deleted, it would crash
* the machine.
*/
if (vnodeEssence->InodeNumber == 0) {
Log("dir vnode %d: invalid entry: %s/%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(dir);
+ CopyOnWrite(salvinfo, dir);
assert(Delete(&dir->dirHandle, name) == 0);
}
return 0;
""));
if (!unique) {
if (!Testing) {
- CopyOnWrite(dir);
+ CopyOnWrite(salvinfo, dir);
assert(Delete(&dir->dirHandle, name) == 0);
}
return 0;
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
+ * entry. Otherwise, it will get created in the next
* salvage and deleted again here. So Just skip it.
*/
return 0;
AFSFid fid;
fid.Vnode = vnodeNumber;
fid.Unique = vnodeEssence->unique;
- CopyOnWrite(dir);
+ CopyOnWrite(salvinfo, dir);
assert(Delete(&dir->dirHandle, name) == 0);
if (!todelete)
assert(Create(&dir->dirHandle, name, &fid) == 0);
if (!Showmode)
Log("directory vnode %u.%u: bad '.' entry (was %u.%u); fixed\n", dir->vnodeNumber, dir->unique, vnodeNumber, unique);
if (!Testing) {
- CopyOnWrite(dir);
+ CopyOnWrite(salvinfo, dir);
assert(Delete(&dir->dirHandle, ".") == 0);
fid.Vnode = dir->vnodeNumber;
fid.Unique = dir->unique;
vnodeNumber = fid.Vnode; /* Get the new Essence */
unique = fid.Unique;
- vnodeEssence = CheckVnodeNumber(vnodeNumber);
+ vnodeEssence = CheckVnodeNumber(salvinfo, vnodeNumber);
}
dir->haveDot = 1;
} else if (strcmp(name, "..") == 0) {
if (dir->parent) {
struct VnodeEssence *dotdot;
pa.Vnode = dir->parent;
- dotdot = CheckVnodeNumber(pa.Vnode);
+ dotdot = CheckVnodeNumber(salvinfo, pa.Vnode);
assert(dotdot != NULL); /* XXX Should not be assert */
pa.Unique = dotdot->unique;
} else {
if (!Showmode)
Log("directory vnode %u.%u: bad '..' entry (was %u.%u); fixed\n", dir->vnodeNumber, dir->unique, vnodeNumber, unique);
if (!Testing) {
- CopyOnWrite(dir);
+ CopyOnWrite(salvinfo, dir);
assert(Delete(&dir->dirHandle, "..") == 0);
assert(Create(&dir->dirHandle, "..", &pa) == 0);
}
vnodeNumber = pa.Vnode; /* Get the new Essence */
unique = pa.Unique;
- vnodeEssence = CheckVnodeNumber(vnodeNumber);
+ vnodeEssence = CheckVnodeNumber(salvinfo, vnodeNumber);
}
dir->haveDotDot = 1;
} else if (strncmp(name, ".__afs", 6) == 0) {
Log("dir vnode %u: special old unlink-while-referenced file %s %s deleted (vnode %u)\n", dir->vnodeNumber, name, (Testing ? "would have been" : "is"), vnodeNumber);
}
if (!Testing) {
- CopyOnWrite(dir);
+ CopyOnWrite(salvinfo, dir);
assert(Delete(&dir->dirHandle, name) == 0);
}
vnodeEssence->claimed = 0; /* Not claimed: Orphaned */
IHandle_t *ihP;
FdHandle_t *fdP;
- IH_INIT(ihP, fileSysDevice, dir->dirHandle.dirh_handle->ih_vid,
+ IH_INIT(ihP, salvinfo->fileSysDevice, dir->dirHandle.dirh_handle->ih_vid,
vnodeEssence->InodeNumber);
fdP = IH_OPEN(ihP);
if (fdP == NULL) {
IH_RELEASE(ihP);
return 0;
}
-
+
if (size > 1024)
size = 1024;
nBytes = FDH_READ(fdP, buf, size);
}
/* The directory entry points to the vnode. Check to see if the
- * vnode points back to the directory. If not, then let the
- * directory claim it (else it might end up orphaned). Vnodes
+ * vnode points back to the directory. If not, then let the
+ * directory claim it (else it might end up orphaned). Vnodes
* already claimed by another directory are deleted from this
* directory: hardlinks to the same vnode are not allowed
* from different directories.
}
}
if (!Testing) {
- CopyOnWrite(dir);
+ CopyOnWrite(salvinfo, dir);
assert(Delete(&dir->dirHandle, name) == 0);
}
return 0;
}
void
-DistilVnodeEssence(VolumeId rwVId, VnodeClass class, Inode ino, Unique * maxu)
+DistilVnodeEssence(struct SalvInfo *salvinfo, VolumeId rwVId,
+ VnodeClass class, Inode ino, Unique * maxu)
{
- register struct VnodeInfo *vip = &vnodeInfo[class];
+ struct VnodeInfo *vip = &salvinfo->vnodeInfo[class];
struct VnodeClassInfo *vcp = &VnodeClassInfo[class];
char buf[SIZEOF_LARGEDISKVNODE];
struct VnodeDiskObject *vnode = (struct VnodeDiskObject *)buf;
int nVnodes;
FdHandle_t *fdP;
- IH_INIT(vip->handle, fileSysDevice, rwVId, ino);
+ IH_INIT(vip->handle, salvinfo->fileSysDevice, rwVId, ino);
fdP = IH_OPEN(vip->handle);
assert(fdP != NULL);
file = FDH_FDOPEN(fdP, "r+");
nVnodes && STREAM_READ(vnode, vcp->diskSize, 1, file) == 1;
nVnodes--, vnodeIndex++) {
if (vnode->type != vNull) {
- register struct VnodeEssence *vep = &vip->vnodes[vnodeIndex];
+ struct VnodeEssence *vep = &vip->vnodes[vnodeIndex];
afs_fsize_t vnodeLength;
vip->nAllocatedVnodes++;
vep->count = vnode->linkCount;
VnodeId vnodeNumber = bitNumberToVnodeNumber(vnodeIndex, class);
vip->nAllocatedVnodes--;
memset(vnode, 0, sizeof(vnode));
- IH_IWRITE(vnodeInfo[vSmall].handle,
+ IH_IWRITE(salvinfo->vnodeInfo[vSmall].handle,
vnodeIndexOffset(vcp, vnodeNumber),
(char *)&vnode, sizeof(vnode));
- VolumeChanged = 1;
+ salvinfo->VolumeChanged = 1;
} else
vip->inodes[vnodeIndex] = VNDISK_GET_INO(vnode);
}
}
static char *
-GetDirName(VnodeId vnode, struct VnodeEssence *vp, char *path)
+GetDirName(struct SalvInfo *salvinfo, VnodeId vnode, struct VnodeEssence *vp,
+ char *path)
{
struct VnodeEssence *parentvp;
strcpy(path, ".");
return path;
}
- if (vp->parent && vp->name && (parentvp = CheckVnodeNumber(vp->parent))
- && GetDirName(vp->parent, parentvp, path)) {
+ if (vp->parent && vp->name && (parentvp = CheckVnodeNumber(salvinfo, vp->parent))
+ && GetDirName(salvinfo, vp->parent, parentvp, path)) {
strcat(path, "/");
strcat(path, vp->name);
return path;
* vnodes must be "claimed". The vep->claimed flag is set in JudgeEntry().
*/
static int
-IsVnodeOrphaned(VnodeId vnode)
+IsVnodeOrphaned(struct SalvInfo *salvinfo, VnodeId vnode)
{
struct VnodeEssence *vep;
return (1); /* Vnode zero does not exist */
if (vnode == 1)
return (0); /* The root dir vnode is always claimed */
- vep = CheckVnodeNumber(vnode); /* Get the vnode essence */
+ vep = CheckVnodeNumber(salvinfo, vnode); /* Get the vnode essence */
if (!vep || !vep->claimed)
return (1); /* Vnode is not claimed - it is orphaned */
- return (IsVnodeOrphaned(vep->parent));
+ return (IsVnodeOrphaned(salvinfo, vep->parent));
}
void
-SalvageDir(char *name, VolumeId rwVid, struct VnodeInfo *dirVnodeInfo,
- IHandle_t * alinkH, int i, struct DirSummary *rootdir,
- int *rootdirfound)
+SalvageDir(struct SalvInfo *salvinfo, char *name, VolumeId rwVid,
+ struct VnodeInfo *dirVnodeInfo, IHandle_t * alinkH, int i,
+ struct DirSummary *rootdir, int *rootdirfound)
{
static struct DirSummary dir;
static struct DirHandle dirHandle;
dirVnodeInfo->vnodes[i].changed = 1;
}
} else {
- parent = CheckVnodeNumber(dirVnodeInfo->vnodes[i].parent);
+ parent = CheckVnodeNumber(salvinfo, dirVnodeInfo->vnodes[i].parent);
if (parent && parent->salvaged == 0)
- SalvageDir(name, rwVid, dirVnodeInfo, alinkH,
+ SalvageDir(salvinfo, name, rwVid, dirVnodeInfo, alinkH,
vnodeIdToBitNumber(dirVnodeInfo->vnodes[i].parent),
rootdir, rootdirfound);
}
dir.parent = dirVnodeInfo->vnodes[i].parent;
dir.haveDot = dir.haveDotDot = 0;
dir.ds_linkH = alinkH;
- SetSalvageDirHandle(&dir.dirHandle, dir.rwVid, fileSysDevice,
- dirVnodeInfo->inodes[i]);
+ SetSalvageDirHandle(&dir.dirHandle, dir.rwVid, salvinfo->fileSysDevice,
+ dirVnodeInfo->inodes[i], &salvinfo->VolumeChanged);
dirok = ((RebuildDirs && !Testing) ? 0 : DirOK(&dir.dirHandle));
if (!dirok) {
(Testing ? "skipping" : "salvaging"));
}
if (!Testing) {
- CopyAndSalvage(&dir);
+ CopyAndSalvage(salvinfo, &dir);
dirok = 1;
+ dirVnodeInfo->inodes[i] = dir.dirHandle.dirh_inode;
}
}
dirHandle = dir.dirHandle;
dir.name =
- GetDirName(bitNumberToVnodeNumber(i, vLarge),
+ GetDirName(salvinfo, bitNumberToVnodeNumber(i, vLarge),
&dirVnodeInfo->vnodes[i], path);
if (dirok) {
/* If enumeration failed for random reasons, we will probably delete
* too much stuff, so we guard against this instead.
*/
- assert(EnumerateDir(&dirHandle, JudgeEntry, &dir) == 0);
+ struct judgeEntry_params judge_params;
+ judge_params.salvinfo = salvinfo;
+ judge_params.dir = &dir;
+
+ assert(EnumerateDir(&dirHandle, JudgeEntry, &judge_params) == 0);
}
/* Delete the old directory if it was copied in order to salvage.
* vnode
*/
static void
-GetNewFID(VolumeDiskData *volHeader, VnodeClass class, AFSFid *afid,
- Unique *maxunique)
+GetNewFID(struct SalvInfo *salvinfo, VolumeDiskData *volHeader,
+ VnodeClass class, AFSFid *afid, Unique *maxunique)
{
int i;
- for (i = 0; i < vnodeInfo[class].nVnodes; i++) {
- if (vnodeInfo[class].vnodes[i].type == vNull) {
+ for (i = 0; i < salvinfo->vnodeInfo[class].nVnodes; i++) {
+ if (salvinfo->vnodeInfo[class].vnodes[i].type == vNull) {
break;
}
}
- if (i == vnodeInfo[class].nVnodes) {
+ if (i == salvinfo->vnodeInfo[class].nVnodes) {
/* no free vnodes; make a new one */
- vnodeInfo[class].nVnodes++;
- vnodeInfo[class].vnodes = realloc(vnodeInfo[class].vnodes,
- sizeof(struct VnodeEssence) * (i+1));
- vnodeInfo[class].vnodes[i].type = vNull;
+ salvinfo->vnodeInfo[class].nVnodes++;
+ salvinfo->vnodeInfo[class].vnodes =
+ realloc(salvinfo->vnodeInfo[class].vnodes,
+ sizeof(struct VnodeEssence) * (i+1));
+
+ salvinfo->vnodeInfo[class].vnodes[i].type = vNull;
}
afid->Vnode = bitNumberToVnodeNumber(i, class);
* @retval -1 error
*/
static int
-CreateReadme(VolumeDiskData *volHeader, IHandle_t *alinkH,
- VolumeId vid, Unique *maxunique, AFSFid *afid, Inode *ainode)
+CreateReadme(struct SalvInfo *salvinfo, VolumeDiskData *volHeader,
+ IHandle_t *alinkH, VolumeId vid, Unique *maxunique, AFSFid *afid,
+ Inode *ainode)
{
Inode readmeinode;
struct VnodeDiskObject *rvnode = NULL;
/* -1 for the trailing NUL */
length = sizeof(readme) - 1;
- GetNewFID(volHeader, vSmall, afid, maxunique);
+ GetNewFID(salvinfo, volHeader, vSmall, afid, maxunique);
- vep = &vnodeInfo[vSmall].vnodes[vnodeIdToBitNumber(afid->Vnode)];
+ vep = &salvinfo->vnodeInfo[vSmall].vnodes[vnodeIdToBitNumber(afid->Vnode)];
/* create the inode and write the contents */
- readmeinode = IH_CREATE(alinkH, fileSysDevice, fileSysPath, 0, vid,
+ readmeinode = IH_CREATE(alinkH, salvinfo->fileSysDevice,
+ salvinfo->fileSysPath, 0, vid,
afid->Vnode, afid->Unique, 1);
if (!VALID_INO(readmeinode)) {
Log("CreateReadme: readme IH_CREATE failed\n");
goto error;
}
- IH_INIT(readmeH, fileSysDevice, vid, readmeinode);
+ IH_INIT(readmeH, salvinfo->fileSysDevice, vid, readmeinode);
bytes = IH_IWRITE(readmeH, 0, readme, length);
IH_RELEASE(readmeH);
}
/* create the vnode and write it out */
- rvnode = malloc(SIZEOF_SMALLDISKVNODE);
+ rvnode = calloc(1, SIZEOF_SMALLDISKVNODE);
if (!rvnode) {
Log("CreateRootDir: error alloc'ing memory\n");
goto error;
rvnode->group = 0;
rvnode->vnodeMagic = VnodeClassInfo[vSmall].magic;
- bytes = IH_IWRITE(vnodeInfo[vSmall].handle,
+ bytes = IH_IWRITE(salvinfo->vnodeInfo[vSmall].handle,
vnodeIndexOffset(&VnodeClassInfo[vSmall], afid->Vnode),
(char*)rvnode, SIZEOF_SMALLDISKVNODE);
}
/* update VnodeEssence for new readme vnode */
- vnodeInfo[vSmall].nAllocatedVnodes++;
+ salvinfo->vnodeInfo[vSmall].nAllocatedVnodes++;
vep->count = 0;
vep->blockCount = nBlocks(length);
- vnodeInfo[vSmall].volumeBlockCount += vep->blockCount;
+ salvinfo->vnodeInfo[vSmall].volumeBlockCount += vep->blockCount;
vep->parent = rvnode->parent;
vep->unique = rvnode->uniquifier;
vep->modeBits = rvnode->modeBits;
* @retval -1 error
*/
static int
-CreateRootDir(VolumeDiskData *volHeader, IHandle_t *alinkH, VolumeId vid,
- struct DirSummary *rootdir, Unique *maxunique)
+CreateRootDir(struct SalvInfo *salvinfo, VolumeDiskData *volHeader,
+ IHandle_t *alinkH, VolumeId vid, struct DirSummary *rootdir,
+ Unique *maxunique)
{
FileVersion dv;
int decroot = 0, decreadme = 0;
Inode readmeinode;
time_t now = time(NULL);
- if (!vnodeInfo[vLarge].vnodes && !vnodeInfo[vSmall].vnodes) {
+ if (!salvinfo->vnodeInfo[vLarge].vnodes && !salvinfo->vnodeInfo[vSmall].vnodes) {
Log("Not creating new root dir; volume appears to lack any vnodes\n");
goto error;
}
- if (!vnodeInfo[vLarge].vnodes) {
+ if (!salvinfo->vnodeInfo[vLarge].vnodes) {
/* We don't have any large vnodes in the volume; allocate room
* for one so we can recreate the root dir */
- vnodeInfo[vLarge].nVnodes = 1;
- vnodeInfo[vLarge].vnodes = calloc(1, sizeof(struct VnodeEssence));
- vnodeInfo[vLarge].inodes = calloc(1, sizeof(Inode));
+ salvinfo->vnodeInfo[vLarge].nVnodes = 1;
+ salvinfo->vnodeInfo[vLarge].vnodes = calloc(1, sizeof(struct VnodeEssence));
+ salvinfo->vnodeInfo[vLarge].inodes = calloc(1, sizeof(Inode));
- assert(vnodeInfo[vLarge].vnodes);
- assert(vnodeInfo[vLarge].inodes);
+ assert(salvinfo->vnodeInfo[vLarge].vnodes);
+ assert(salvinfo->vnodeInfo[vLarge].inodes);
}
- vep = &vnodeInfo[vLarge].vnodes[vnodeIdToBitNumber(1)];
- ip = &vnodeInfo[vLarge].inodes[vnodeIdToBitNumber(1)];
+ vep = &salvinfo->vnodeInfo[vLarge].vnodes[vnodeIdToBitNumber(1)];
+ ip = &salvinfo->vnodeInfo[vLarge].inodes[vnodeIdToBitNumber(1)];
if (vep->type != vNull) {
Log("Not creating new root dir; existing vnode 1 is non-null\n");
goto error;
}
- if (CreateReadme(volHeader, alinkH, vid, maxunique, &readmeid, &readmeinode)) {
+ if (CreateReadme(salvinfo, volHeader, alinkH, vid, maxunique, &readmeid,
+ &readmeinode) != 0) {
goto error;
}
decreadme = 1;
* with a cached DV */
dv = 1 << 30;
- rootinode = IH_CREATE(alinkH, fileSysDevice, fileSysPath, 0, vid, 1, 1, dv);
+ rootinode = IH_CREATE(alinkH, salvinfo->fileSysDevice, salvinfo->fileSysPath,
+ 0, vid, 1, 1, dv);
if (!VALID_INO(rootinode)) {
Log("CreateRootDir: IH_CREATE failed\n");
goto error;
}
decroot = 1;
- SetSalvageDirHandle(&rootdir->dirHandle, vid, fileSysDevice, rootinode);
+ SetSalvageDirHandle(&rootdir->dirHandle, vid, salvinfo->fileSysDevice,
+ rootinode, &salvinfo->VolumeChanged);
did.Volume = vid;
did.Vnode = 1;
did.Unique = 1;
DZap((void *)&rootdir->dirHandle);
/* create the new root dir vnode */
- rootvnode = malloc(SIZEOF_LARGEDISKVNODE);
+ rootvnode = calloc(1, SIZEOF_LARGEDISKVNODE);
if (!rootvnode) {
Log("CreateRootDir: malloc failed\n");
goto error;
rootvnode->vnodeMagic = VnodeClassInfo[vLarge].magic;
/* write it out to disk */
- bytes = IH_IWRITE(vnodeInfo[vLarge].handle,
+ bytes = IH_IWRITE(salvinfo->vnodeInfo[vLarge].handle,
vnodeIndexOffset(&VnodeClassInfo[vLarge], 1),
(char*)rootvnode, SIZEOF_LARGEDISKVNODE);
}
/* update VnodeEssence for the new root vnode */
- vnodeInfo[vLarge].nAllocatedVnodes++;
+ salvinfo->vnodeInfo[vLarge].nAllocatedVnodes++;
vep->count = 0;
vep->blockCount = nBlocks(length);
- vnodeInfo[vLarge].volumeBlockCount += vep->blockCount;
+ salvinfo->vnodeInfo[vLarge].volumeBlockCount += vep->blockCount;
vep->parent = rootvnode->parent;
vep->unique = rootvnode->uniquifier;
vep->modeBits = rootvnode->modeBits;
return -1;
}
+/**
+ * salvage a volume group.
+ *
+ * @param[in] salvinfo information for the curent salvage job
+ * @param[in] rwIsp inode summary for rw volume
+ * @param[in] alinkH link table inode handle
+ *
+ * @return operation status
+ * @retval 0 success
+ */
int
-SalvageVolume(register struct InodeSummary *rwIsp, IHandle_t * alinkH)
+SalvageVolume(struct SalvInfo *salvinfo, struct InodeSummary *rwIsp, IHandle_t * alinkH)
{
/* This routine, for now, will only be called for read-write volumes */
int i, j, code;
int BlocksInVolume = 0, FilesInVolume = 0;
- register VnodeClass class;
+ VnodeClass class;
struct DirSummary rootdir, oldrootdir;
struct VnodeInfo *dirVnodeInfo;
struct VnodeDiskObject vnode;
int newrootdir = 0;
vid = rwIsp->volSummary->header.id;
- IH_INIT(h, fileSysDevice, vid, rwIsp->volSummary->header.volumeInfo);
+ IH_INIT(h, salvinfo->fileSysDevice, vid, rwIsp->volSummary->header.volumeInfo);
nBytes = IH_IREAD(h, 0, (char *)&volHeader, sizeof(volHeader));
assert(nBytes == sizeof(volHeader));
assert(volHeader.stamp.magic == VOLUMEINFOMAGIC);
assert(volHeader.destroyMe != DESTROY_ME);
/* (should not have gotten this far with DESTROY_ME flag still set!) */
- DistilVnodeEssence(vid, vLarge, rwIsp->volSummary->header.largeVnodeIndex,
- &maxunique);
- DistilVnodeEssence(vid, vSmall, rwIsp->volSummary->header.smallVnodeIndex,
- &maxunique);
+ DistilVnodeEssence(salvinfo, vid, vLarge,
+ rwIsp->volSummary->header.largeVnodeIndex, &maxunique);
+ DistilVnodeEssence(salvinfo, vid, vSmall,
+ rwIsp->volSummary->header.smallVnodeIndex, &maxunique);
- dirVnodeInfo = &vnodeInfo[vLarge];
+ dirVnodeInfo = &salvinfo->vnodeInfo[vLarge];
for (i = 0; i < dirVnodeInfo->nVnodes; i++) {
- SalvageDir(volHeader.name, vid, dirVnodeInfo, alinkH, i, &rootdir,
- &rootdirfound);
+ SalvageDir(salvinfo, volHeader.name, vid, dirVnodeInfo, alinkH, i,
+ &rootdir, &rootdirfound);
}
#ifdef AFS_NT40_ENV
- nt_sync(fileSysDevice);
+ nt_sync(salvinfo->fileSysDevice);
#else
sync(); /* This used to be done lower level, for every dir */
#endif
Log("Cannot find root directory for volume %lu; attempting to create "
"a new one\n", afs_printable_uint32_lu(vid));
- code = CreateRootDir(&volHeader, alinkH, vid, &rootdir, &maxunique);
+ code = CreateRootDir(salvinfo, &volHeader, alinkH, vid, &rootdir,
+ &maxunique);
if (code == 0) {
rootdirfound = 1;
newrootdir = 1;
- VolumeChanged = 1;
+ salvinfo->VolumeChanged = 1;
}
}
*/
oldrootdir = rootdir;
for (class = 0; class < nVNODECLASSES; class++) {
- for (v = 0; v < vnodeInfo[class].nVnodes; v++) {
- vep = &(vnodeInfo[class].vnodes[v]);
+ for (v = 0; v < salvinfo->vnodeInfo[class].nVnodes; v++) {
+ vep = &(salvinfo->vnodeInfo[class].vnodes[v]);
ThisVnode = bitNumberToVnodeNumber(v, class);
ThisUnique = vep->unique;
*/
if (class == vLarge) { /* directory vnode */
pv = vnodeIdToBitNumber(vep->parent);
- if (vnodeInfo[vLarge].vnodes[pv].unique != 0) {
+ if (salvinfo->vnodeInfo[vLarge].vnodes[pv].unique != 0) {
if (vep->parent == 1 && newrootdir) {
/* this vnode's parent was the volume root, and
* we just created the volume root. So, the parent
/* noop */
} else {
- vnodeInfo[vLarge].vnodes[pv].count++;
+ salvinfo->vnodeInfo[vLarge].vnodes[pv].count++;
}
}
}
LFVnode = rootdir.vnodeNumber; /* Lost+Found vnode number */
LFUnique = rootdir.unique; /* Lost+Found uniquifier */
- /* Update this orphaned vnode's info. Its parent info and
+ /* Update this orphaned vnode's info. Its parent info and
* link count (do for orphaned directories and files).
*/
vep->parent = LFVnode; /* Parent is the root dir */
vep->claimed = 1;
vep->count--; /* Inc link count (root dir will pt to it) */
- /* If this orphaned vnode is a directory, change '..'.
+ /* If this orphaned vnode is a directory, change '..'.
* The name of the orphaned dir/file is unknown, so we
* build a unique name. No need to CopyOnWrite the directory
* since it is not connected to tree in BK or RO volume and
DirHandle dh;
/* Remove and recreate the ".." entry in this orphaned directory */
- SetSalvageDirHandle(&dh, vid, fileSysDevice,
- vnodeInfo[class].inodes[v]);
+ SetSalvageDirHandle(&dh, vid, salvinfo->fileSysDevice,
+ salvinfo->vnodeInfo[class].inodes[v],
+ &salvinfo->VolumeChanged);
pa.Vnode = LFVnode;
pa.Unique = LFUnique;
assert(Delete(&dh, "..") == 0);
* Here we increment the new parent's link count.
*/
pv = vnodeIdToBitNumber(LFVnode);
- vnodeInfo[vLarge].vnodes[pv].count--;
+ salvinfo->vnodeInfo[vLarge].vnodes[pv].count--;
}
"__ORPHANFILE__"), ThisVnode,
ThisUnique);
- CopyOnWrite(&rootdir);
+ CopyOnWrite(salvinfo, &rootdir);
code = Create(&rootdir.dirHandle, npath, &pa);
if (!code)
break;
/* Delete the old rootinode directory if the rootdir was CopyOnWrite */
DFlush();
- if (!oldrootdir.copied && rootdir.copied) {
+ if (rootdirfound && !oldrootdir.copied && rootdir.copied) {
code =
IH_DEC(oldrootdir.ds_linkH, oldrootdir.dirHandle.dirh_inode,
oldrootdir.rwVid);
* will get removed here also (if requested).
*/
for (class = 0; class < nVNODECLASSES; class++) {
- int nVnodes = vnodeInfo[class].nVnodes;
+ int nVnodes = salvinfo->vnodeInfo[class].nVnodes;
struct VnodeClassInfo *vcp = &VnodeClassInfo[class];
- struct VnodeEssence *vnodes = vnodeInfo[class].vnodes;
- FilesInVolume += vnodeInfo[class].nAllocatedVnodes;
- BlocksInVolume += vnodeInfo[class].volumeBlockCount;
+ struct VnodeEssence *vnodes = salvinfo->vnodeInfo[class].vnodes;
+ FilesInVolume += salvinfo->vnodeInfo[class].nAllocatedVnodes;
+ BlocksInVolume += salvinfo->vnodeInfo[class].volumeBlockCount;
for (i = 0; i < nVnodes; i++) {
- register struct VnodeEssence *vnp = &vnodes[i];
+ struct VnodeEssence *vnp = &vnodes[i];
VnodeId vnodeNumber = bitNumberToVnodeNumber(i, class);
/* If the vnode is good but is unclaimed (not listed in
* any directory entries), then it is orphaned.
*/
orphaned = -1;
- if ((vnp->type != 0) && (orphaned = IsVnodeOrphaned(vnodeNumber))) {
+ if ((vnp->type != 0) && (orphaned = IsVnodeOrphaned(salvinfo, vnodeNumber))) {
vnp->claimed = 0; /* Makes IsVnodeOrphaned calls faster */
vnp->changed = 1;
}
if (vnp->changed || vnp->count) {
int oldCount;
- int code;
nBytes =
- IH_IREAD(vnodeInfo[class].handle,
+ IH_IREAD(salvinfo->vnodeInfo[class].handle,
vnodeIndexOffset(vcp, vnodeNumber),
(char *)&vnode, sizeof(vnode));
assert(nBytes == sizeof(vnode));
vnode.linkCount = vnode.linkCount - vnp->count;
if (orphaned == -1)
- orphaned = IsVnodeOrphaned(vnodeNumber);
+ orphaned = IsVnodeOrphaned(salvinfo, vnodeNumber);
if (orphaned) {
if (!vnp->todelete) {
/* Orphans should have already been attached (if requested) */
vnode.dataVersion++;
if (!Testing) {
nBytes =
- IH_IWRITE(vnodeInfo[class].handle,
+ IH_IWRITE(salvinfo->vnodeInfo[class].handle,
vnodeIndexOffset(vcp, vnodeNumber),
(char *)&vnode, sizeof(vnode));
assert(nBytes == sizeof(vnode));
}
- VolumeChanged = 1;
+ salvinfo->VolumeChanged = 1;
}
}
}
}
for (class = 0; class < nVNODECLASSES; class++) {
- register struct VnodeInfo *vip = &vnodeInfo[class];
+ struct VnodeInfo *vip = &salvinfo->vnodeInfo[class];
for (i = 0; i < vip->nVnodes; i++)
if (vip->vnodes[i].name)
free(vip->vnodes[i].name);
}
#ifdef FSSYNC_BUILD_CLIENT
- if (!Testing && VolumeChanged) {
+ if (!Testing && salvinfo->VolumeChanged) {
afs_int32 fsync_code;
fsync_code = FSYNC_VolOp(vid, NULL, FSYNC_VOL_BREAKCBKS, FSYNC_SALVAGE, NULL);
afs_printable_uint32_lu(vid),
afs_printable_int32_ld(fsync_code));
} else {
- VolumeChanged = 0;
+ salvinfo->VolumeChanged = 0;
}
}
#endif /* FSSYNC_BUILD_CLIENT */
volHeader.inUse = 0; /* clear flag indicating inUse@last crash */
volHeader.needsSalvaged = 0; /* clear 'damaged' flag */
volHeader.inService = 1; /* allow service again */
- volHeader.needsCallback = (VolumeChanged != 0);
+ volHeader.needsCallback = (salvinfo->VolumeChanged != 0);
volHeader.dontSalvage = DONT_SALVAGE;
- VolumeChanged = 0;
+ salvinfo->VolumeChanged = 0;
if (!Testing) {
nBytes = IH_IWRITE(h, 0, (char *)&volHeader, sizeof(volHeader));
assert(nBytes == sizeof(volHeader));
(Testing ? "It would have " : ""), volHeader.name, volHeader.id,
FilesInVolume, BlocksInVolume);
}
- IH_RELEASE(vnodeInfo[vSmall].handle);
- IH_RELEASE(vnodeInfo[vLarge].handle);
+
+ IH_RELEASE(salvinfo->vnodeInfo[vSmall].handle);
+ IH_RELEASE(salvinfo->vnodeInfo[vLarge].handle);
IH_RELEASE(h);
return 0;
}
* deleteMe - Always do so, only a partial volume.
*/
void
-MaybeZapVolume(register struct InodeSummary *isp, char *message, int deleteMe,
- int check)
+MaybeZapVolume(struct SalvInfo *salvinfo, struct InodeSummary *isp,
+ char *message, int deleteMe, int check)
{
if (readOnly(isp) || deleteMe) {
if (isp->volSummary && isp->volSummary->fileName) {
if (!Testing) {
afs_int32 code;
char path[64];
- sprintf(path, "%s/%s", fileSysPath, isp->volSummary->fileName);
+ sprintf(path, "%s/%s", salvinfo->fileSysPath, isp->volSummary->fileName);
- code = VDestroyVolumeDiskHeader(fileSysPartition, isp->volumeId, isp->RWvolumeId);
+ code = VDestroyVolumeDiskHeader(salvinfo->fileSysPartition, isp->volumeId, isp->RWvolumeId);
if (code) {
Log("Error %ld destroying volume disk header for volume %lu\n",
afs_printable_int32_ld(code),
* @note DAFS only
*/
static int
-LockVolume(VolumeId volumeId)
+LockVolume(struct SalvInfo *salvinfo, VolumeId volumeId)
{
afs_int32 code;
int locktype;
* try to provide what we're logically doing. */
locktype = VVolLockType(V_VOLUPD, 1);
- code = VLockVolumeByIdNB(volumeId, fileSysPartition, locktype);
+ code = VLockVolumeByIdNB(volumeId, salvinfo->fileSysPartition, locktype);
if (code) {
if (code == EBUSY) {
Abort("Someone else appears to be using volume %lu; Aborted\n",
afs_printable_uint32_lu(volumeId));
}
- code = FSYNC_VerifyCheckout(volumeId, fileSysPathName, FSYNC_VOL_OFF, FSYNC_SALVAGE);
+ code = FSYNC_VerifyCheckout(volumeId, salvinfo->fileSysPathName, FSYNC_VOL_OFF, FSYNC_SALVAGE);
if (code == SYNC_DENIED) {
/* need to retry checking out volumes */
return -1;
struct VolumeDiskHeader diskHeader;
struct VolumeDiskData volHeader;
- code = VReadVolumeDiskHeader(volumeId, fileSysPartition, &diskHeader);
+ code = VReadVolumeDiskHeader(volumeId, salvinfo->fileSysPartition, &diskHeader);
if (code) {
return 0;
}
DiskToVolumeHeader(&header, &diskHeader);
- IH_INIT(h, fileSysDevice, header.parent, header.volumeInfo);
+ IH_INIT(h, salvinfo->fileSysDevice, header.parent, header.volumeInfo);
if (IH_IREAD(h, 0, (char*)&volHeader, sizeof(volHeader)) != sizeof(volHeader) ||
volHeader.stamp.magic != VOLUMEINFOMAGIC) {
#endif /* AFS_DEMAND_ATTACH_FS */
void
-AskOffline(VolumeId volumeId, char * partition)
+AskOffline(struct SalvInfo *salvinfo, VolumeId volumeId)
{
afs_int32 code, i;
SYNC_response res;
memset(&res, 0, sizeof(res));
for (i = 0; i < 3; i++) {
- code = FSYNC_VolOp(volumeId, partition, FSYNC_VOL_OFF, FSYNC_SALVAGE, &res);
+ code = FSYNC_VolOp(volumeId, salvinfo->fileSysPartition->name,
+ FSYNC_VOL_OFF, FSYNC_SALVAGE, &res);
if (code == SYNC_OK) {
break;
}
void
-AskOnline(VolumeId volumeId, char *partition)
+AskOnline(struct SalvInfo *salvinfo, VolumeId volumeId)
{
afs_int32 code, i;
for (i = 0; i < 3; i++) {
- code = FSYNC_VolOp(volumeId, partition, FSYNC_VOL_ON, FSYNC_WHATEVER, NULL);
+ code = FSYNC_VolOp(volumeId, salvinfo->fileSysPartition->name,
+ FSYNC_VOL_ON, FSYNC_WHATEVER, NULL);
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, partition);
+ Log("AskOnline: file server denied online 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_ON);
}
void
-PrintInodeList(void)
+PrintInodeList(struct SalvInfo *salvinfo)
{
- register struct ViceInodeInfo *ip;
+ struct ViceInodeInfo *ip;
struct ViceInodeInfo *buf;
struct afs_stat status;
- register int nInodes;
+ int nInodes;
- assert(afs_fstat(inodeFd, &status) == 0);
+ assert(afs_fstat(salvinfo->inodeFd, &status) == 0);
buf = (struct ViceInodeInfo *)malloc(status.st_size);
assert(buf != NULL);
nInodes = status.st_size / sizeof(struct ViceInodeInfo);
- assert(read(inodeFd, buf, status.st_size) == status.st_size);
+ assert(read(salvinfo->inodeFd, buf, status.st_size) == status.st_size);
for (ip = buf; nInodes--; ip++) {
Log("Inode:%s, linkCount=%d, size=%#llx, p=(%u,%u,%u,%u)\n",
PrintInode(NULL, ip->inodeNumber), ip->linkCount,
}
void
-PrintInodeSummary(void)
+PrintInodeSummary(struct SalvInfo *salvinfo)
{
int i;
struct InodeSummary *isp;
- for (i = 0; i < nVolumesInInodeFile; i++) {
- isp = &inodeSummary[i];
+ 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(void)
+PrintVolumeSummary(struct SalvInfo *salvinfo)
{
int i;
struct VolumeSummary *vsp;
- for (i = 0, vsp = volumeSummaryp; i < nVolumes; vsp++, i++) {
+ for (i = 0, vsp = salvinfo->volumeSummaryp; i < salvinfo->nVolumes; vsp++, i++) {
Log("fileName:%s, header, wouldNeedCallback\n", vsp->fileName);
}
}
char *
ToString(const char *s)
{
- register char *p;
+ char *p;
p = (char *)malloc(strlen(s) + 1);
assert(p != NULL);
strcpy(p, s);