#endif
#include <rx/xdr.h>
#include <afs/afsint.h>
-#include <afs/afs_assert.h>
#if !defined(AFS_SGI_ENV) && !defined(AFS_NT40_ENV)
#if defined(AFS_VFSINCL_ENV)
#include <sys/vnode.h>
#include "daemon_com.h"
#include "daemon_com_inline.h"
#include "fssync.h"
+#include "fssync_inline.h"
#include "volume_inline.h"
#include "salvsync.h"
#include "viceinode.h"
struct SalvInfo {
Device fileSysDevice; /**< The device number of the current partition
* being salvaged */
- char fileSysPath[8]; /**< The path of the mounted partition currently
+ char fileSysPath[9]; /**< The path of the mounted partition currently
* being salvaged, i.e. the directory containing
* the volume headers */
char *fileSysPathName; /**< NT needs this to make name pretty log. */
goto retry;
}
+ if (singleVolumeNumber) {
+ /* If we delete a volume during the salvage, we indicate as such by
+ * setting the volsummary->deleted field. We need to know if we
+ * deleted a volume or not in order to know which volumes to bring
+ * back online after the salvage. If we fork, we will lose this
+ * information, since volsummary->deleted will not get set in the
+ * parent. So, don't fork. */
+ canfork = 0;
+ }
+
for (i = j = 0, vsp = salvinfo->volumeSummaryp, esp = vsp + salvinfo->nVolumes;
i < salvinfo->nVolumesInInodeFile; i = j) {
VolumeId rwvid = salvinfo->inodeSummary[i].RWvolumeId;
* If there is one here that is not in the inode volume list,
* delete it now. */
for (; vsp < esp && (vsp->header.parent < rwvid); vsp++) {
- if (vsp->fileName)
+ if (vsp->unused)
DeleteExtraVolumeHeaderFile(salvinfo, vsp);
}
/* Now match up the volume summary info from the root directory with the
for (tsp = vsp; tsp < esp && (tsp->header.parent == rwvid); tsp++) {
if (tsp->header.id == vid) {
salvinfo->inodeSummary[j].volSummary = tsp;
- tsp->fileName = 0;
+ tsp->unused = 0;
break;
}
}
/* Salvage the group of volumes (several read-only + 1 read/write)
* starting with the current read-only volume we're looking at.
*/
- SalvageVolumeGroup(salvinfo, &salvinfo->inodeSummary[i], j - i);
+#ifdef AFS_NT40_ENV
+ nt_SalvageVolumeGroup(salvinfo, &salvinfo->inodeSummary[i], j - i);
+#else
+ DoSalvageVolumeGroup(salvinfo, &salvinfo->inodeSummary[i], j - i);
+#endif /* AFS_NT40_ENV */
+
}
/* Delete any additional volumes that were listed in the partition but which didn't have any corresponding inodes */
for (; vsp < esp; vsp++) {
- if (vsp->fileName)
+ if (vsp->unused)
DeleteExtraVolumeHeaderFile(salvinfo, vsp);
}
DeleteExtraVolumeHeaderFile(struct SalvInfo *salvinfo, struct VolumeSummary *vsp)
{
char path[64];
- sprintf(path, "%s" OS_DIRSEP "%s", salvinfo->fileSysPath, vsp->fileName);
+ char filename[VMAXPATHLEN];
+
+ if (vsp->deleted) {
+ return;
+ }
+
+ VolumeExternalName_r(vsp->header.id, filename, sizeof(filename));
+ sprintf(path, "%s" OS_DIRSEP "%s", salvinfo->fileSysPath, filename);
if (!Showmode)
Log("The volume header file %s is not associated with any actual data (%sdeleted)\n", path, (Testing ? "would have been " : ""));
afs_printable_uint32_lu(vsp->header.id));
}
- /* make sure we actually delete the fileName file; ENOENT
+ /* make sure we actually delete the header file; ENOENT
* is fine, since VDestroyVolumeDiskHeader probably already
* unlinked it */
if (unlink(path) && errno != ENOENT) {
}
vsp->deleted = 1;
}
- vsp->fileName = 0;
}
int
GetVolumeSummary(salvinfo, singleVolumeNumber);
for (i = 0, vsp = salvinfo->volumeSummaryp; i < salvinfo->nVolumes; i++) {
- if (vsp->fileName) {
+ if (vsp->unused) {
if (vsp->header.id == singleVolumeNumber) {
foundSVN = 1;
}
DiskToVolumeHeader(&vsp->header, &diskHdr);
VolumeExternalName_r(q_res.children[i], name, sizeof(name));
- vsp->fileName = ToString(name);
+ vsp->unused = 1;
salvinfo->nVolumes++;
vsp++;
}
return 1;
}
- summary.fileName = ToString(base);
+ summary.unused = 1;
params->nVolumes++;
if (params->nVolumes > params->totalVolumes) {
if (!VALID_INO(ino))
ino =
- IH_CREATE(NULL, salvinfo->fileSysDevice, salvinfo->fileSysPath, 0, isp->volumeId,
+ IH_CREATE(NULL, salvinfo->fileSysDevice, salvinfo->fileSysPath, 0, isp->RWvolumeId,
INODESPECIAL, VI_LINKTABLE, isp->RWvolumeId);
if (!VALID_INO(ino))
Abort
}
void
-SalvageVolumeGroup(struct SalvInfo *salvinfo, struct InodeSummary *isp, int nVols)
+nt_SalvageVolumeGroup(struct SalvInfo *salvinfo, struct InodeSummary *isp, int nVols)
{
pthread_t tid;
pthread_attr_t tattr;
isp->volumeId, (Testing ? "it would have been " : ""),
path);
isp->volSummary = calloc(1, sizeof(struct VolumeSummary));
- isp->volSummary->fileName = ToString(headerName);
writefunc = VCreateVolumeDiskHeader;
} else {
if (memcmp
(&isp->volSummary->header, &tempHeader,
sizeof(struct VolumeHeader))) {
- /* We often remove the name before calling us, so we make a fake one up */
- if (isp->volSummary->fileName) {
- strcpy(headerName, isp->volSummary->fileName);
- } else {
- snprintf(headerName, sizeof headerName, VFORMAT,
- afs_printable_uint32_lu(isp->volumeId));
- isp->volSummary->fileName = ToString(headerName);
- }
+ VolumeExternalName_r(isp->volumeId, headerName, sizeof(headerName));
snprintf(path, sizeof path, "%s" OS_DIRSEP "%s",
salvinfo->fileSysPath, headerName);
if (strcmp(name, ".") == 0) {
if (dir->vnodeNumber != vnodeNumber || (dir->unique != unique)) {
- AFSFid fid;
if (!Showmode)
Log("directory vnode %u.%u: bad '.' entry (was %u.%u); fixed\n", dir->vnodeNumber, dir->unique, vnodeNumber, unique);
if (!Testing) {
+ AFSFid fid;
CopyOnWrite(salvinfo, dir);
osi_Assert(afs_dir_Delete(&dir->dirHandle, ".") == 0);
fid.Vnode = dir->vnodeNumber;
fid.Unique = dir->unique;
osi_Assert(afs_dir_Create(&dir->dirHandle, ".", &fid) == 0);
+ vnodeNumber = fid.Vnode; /* Get the new Essence */
+ unique = fid.Unique;
+ vnodeEssence = CheckVnodeNumber(salvinfo, vnodeNumber);
}
-
- vnodeNumber = fid.Vnode; /* Get the new Essence */
- unique = fid.Unique;
- vnodeEssence = CheckVnodeNumber(salvinfo, vnodeNumber);
}
dir->haveDot = 1;
} else if (strcmp(name, "..") == 0) {
if (class != vLarge) {
VnodeId vnodeNumber = bitNumberToVnodeNumber(vnodeIndex, class);
vip->nAllocatedVnodes--;
- memset(vnode, 0, sizeof(vnode));
+ memset(vnode, 0, sizeof(*vnode));
IH_IWRITE(salvinfo->vnodeInfo[vSmall].handle,
vnodeIndexOffset(vcp, vnodeNumber),
(char *)&vnode, sizeof(vnode));
Inode *ip;
afs_sfsize_t bytes;
struct VnodeEssence *vep;
- Inode readmeinode;
+ Inode readmeinode = 0;
time_t now = time(NULL);
if (!salvinfo->vnodeInfo[vLarge].vnodes && !salvinfo->vnodeInfo[vSmall].vnodes) {
char *message, int deleteMe, int check)
{
if (readOnly(isp) || deleteMe) {
- if (isp->volSummary && isp->volSummary->fileName) {
+ if (isp->volSummary && !isp->volSummary->deleted) {
if (deleteMe) {
if (!Showmode)
Log("Volume %u (is only a partial volume--probably an attempt was made to move/restore it when a machine crash occured.\n", isp->volumeId);
if (!Testing) {
afs_int32 code;
char path[64];
- sprintf(path, "%s" OS_DIRSEP "%s", salvinfo->fileSysPath, isp->volSummary->fileName);
+ char filename[VMAXPATHLEN];
+ VolumeExternalName_r(isp->volumeId, filename, sizeof(filename));
+ sprintf(path, "%s" OS_DIRSEP "%s", salvinfo->fileSysPath, filename);
code = VDestroyVolumeDiskHeader(salvinfo->fileSysPartition, isp->volumeId, isp->RWvolumeId);
if (code) {
afs_printable_uint32_lu(isp->volumeId));
}
- /* make sure we actually delete the fileName file; ENOENT
+ /* make sure we actually delete the header file; ENOENT
* is fine, since VDestroyVolumeDiskHeader probably already
* unlinked it */
if (unlink(path) && errno != ENOENT) {
afs_printable_uint32_lu(volumeId));
}
- code = FSYNC_VerifyCheckout(volumeId, salvinfo->fileSysPathName, FSYNC_VOL_OFF, FSYNC_SALVAGE);
+ code = FSYNC_VerifyCheckout(volumeId, salvinfo->fileSysPartition->name, FSYNC_VOL_OFF, FSYNC_SALVAGE);
if (code == SYNC_DENIED) {
/* need to retry checking out volumes */
return -1;
int
AskDAFS(void)
{
- afs_int32 code, i, ret = 0;
SYNC_response res;
+ afs_int32 code = 1, i;
/* we don't care if we race. the answer shouldn't change */
if (isDAFS != -1)
memset(&res, 0, sizeof(res));
- for (i = 0; i < 3; i++) {
- code = FSYNC_VolOp(1, NULL,
- FSYNC_VOL_QUERY_VOP, FSYNC_SALVAGE, &res);
-
- if (code == SYNC_OK) {
- ret = 1;
- break;
- } else if (code == SYNC_DENIED) {
- ret = 1;
- break;
- } else if (code == SYNC_BAD_COMMAND) {
- ret = 0;
- break;
- } else if (code == SYNC_FAILED) {
- if (res.hdr.reason == FSYNC_UNKNOWN_VOLID)
- ret = 1;
- else
- ret = 0;
- break;
- } else if (i < 2) {
- /* try it again */
- Log("AskDAFS: request to query fileserver failed; trying again...\n");
+ for (i = 0; code && i < 3; i++) {
+ code = FSYNC_VolOp(0, NULL, FSYNC_VOL_LISTVOLUMES, FSYNC_SALVAGE, &res);
+ if (code) {
+ Log("AskDAFS: FSYNC_VOL_LISTVOLUMES failed with code %ld reason "
+ "%ld (%s); trying again...\n", (long)code, (long)res.hdr.reason,
+ FSYNC_reason2string(res.hdr.reason));
FSYNC_clientFinis();
FSYNC_clientInit();
}
}
- isDAFS = ret;
- return ret;
+ if (code) {
+ Log("AskDAFS: could not determine DAFS-ness, assuming not DAFS\n");
+ res.hdr.flags = 0;
+ }
+
+ if ((res.hdr.flags & SYNC_FLAG_DAFS_EXTENSIONS)) {
+ isDAFS = 1;
+ } else {
+ isDAFS = 0;
+ }
+
+ return isDAFS;
}
static void
}
}
-void
-PrintVolumeSummary(struct SalvInfo *salvinfo)
-{
- int i;
- struct VolumeSummary *vsp;
-
- for (i = 0, vsp = salvinfo->volumeSummaryp; i < salvinfo->nVolumes; vsp++, i++) {
- Log("fileName:%s, header, wouldNeedCallback\n", vsp->fileName);
- }
-}
-
int
Fork(void)
{