#include <afsconfig.h>
#include <afs/param.h>
+#include <afs/procmgmt.h>
+#include <roken.h>
#ifndef AFS_NT40_ENV
#include <sys/param.h>
#ifdef AFS_OSF_ENV
#include <ufs/inode.h>
#else /* AFS_OSF_ENV */
-#if !defined(AFS_LINUX20_ENV) && !defined(AFS_XBSD_ENV)
+#if !defined(AFS_LINUX20_ENV) && !defined(AFS_XBSD_ENV) && !defined(AFS_ARM_DARWIN_ENV)
#include <sys/inode.h>
#endif
#endif
* vnodes in the volume that
* we are currently looking
* at */
+ int useFSYNC; /**< 0 if the fileserver is unavailable; 1 if we should try
+ * to contact the fileserver over FSYNC */
};
char *tmpdir = NULL;
SameDisk(struct DiskPartition64 *p1, struct DiskPartition64 *p2)
{
#define RES_LEN 256
- char res[RES_LEN];
- int d1, d2;
+ char res1[RES_LEN];
+ char res2[RES_LEN];
+
static int dowarn = 1;
- if (!QueryDosDevice(p1->devName, res, RES_LEN - 1))
+ if (!QueryDosDevice(p1->devName, res1, RES_LEN - 1))
return 1;
- if (strncmp(res, HDSTR, HDLEN)) {
+ if (strncmp(res1, HDSTR, HDLEN)) {
if (dowarn) {
dowarn = 0;
Log("WARNING: QueryDosDevice is returning %s, not %s for %s\n",
- res, HDSTR, p1->devName);
+ res1, HDSTR, p1->devName);
}
- return 1;
}
- d1 = atoi(&res[HDLEN]);
-
- if (!QueryDosDevice(p2->devName, res, RES_LEN - 1))
+ if (!QueryDosDevice(p2->devName, res2, RES_LEN - 1))
return 1;
- if (strncmp(res, HDSTR, HDLEN)) {
+ if (strncmp(res2, HDSTR, HDLEN)) {
if (dowarn) {
dowarn = 0;
Log("WARNING: QueryDosDevice is returning %s, not %s for %s\n",
- res, HDSTR, p2->devName);
+ res2, HDSTR, p2->devName);
}
- return 1;
}
- d2 = atoi(&res[HDLEN]);
- return d1 == d2;
+ return (0 == _strnicmp(res1, res2, RES_LEN - 1));
}
#else
#define SameDisk(P1, P2) ((P1)->device/PartsPerDisk == (P2)->device/PartsPerDisk)
ShowLog = 0;
for (fd = 0; fd < 16; fd++)
close(fd);
- open("/", 0);
+ open(OS_DIRSEP, 0);
dup2(0, 1);
dup2(0, 2);
#ifndef AFS_NT40_ENV
{
char pbuf[128], *ptr;
strcpy(pbuf, pbuffer);
- ptr = (char *)strrchr(pbuf, '/');
+ ptr = (char *)strrchr(pbuf, OS_DIRSEPC);
if (ptr) {
*ptr = '\0';
strcpy(wpath, pbuf);
} else
return NULL;
- ptr = (char *)strrchr(pbuffer, '/');
+ ptr = (char *)strrchr(pbuffer, OS_DIRSEPC);
if (ptr) {
strcpy(pbuffer, ptr + 1);
return pbuffer;
#ifdef AFS_NT40_ENV
/* Opendir can fail on "C:" but not on "C:\" if C is empty! */
- (void)sprintf(salvinfo->fileSysPath, "%s\\", salvinfo->fileSysPathName);
+ (void)sprintf(salvinfo->fileSysPath, "%s" OS_DIRSEP, salvinfo->fileSysPathName);
name = partP->devName;
#else
strlcpy(salvinfo->fileSysPath, salvinfo->fileSysPathName, sizeof(salvinfo->fileSysPath));
Abort("Couldn't connect to file server\n");
}
+ salvinfo->useFSYNC = 1;
AskOffline(salvinfo, singleVolumeNumber);
#ifdef AFS_DEMAND_ATTACH_FS
if (LockVolume(salvinfo, singleVolumeNumber)) {
#endif /* AFS_DEMAND_ATTACH_FS */
} else {
+ salvinfo->useFSYNC = 0;
VLockPartition(partP->name);
if (ForceSalvage) {
ForceSalvage = 1;
char npath[1024];
Log("Removing old salvager temp files %s\n", dp->d_name);
strcpy(npath, salvinfo->fileSysPath);
- strcat(npath, "/");
+ strcat(npath, OS_DIRSEP);
strcat(npath, dp->d_name);
- unlink(npath);
+ OS_UNLINK(npath);
}
}
closedir(dirp);
(void)_putenv("TMP="); /* If "TMP" is set, then that overrides tdir. */
(void)strncpy(inodeListPath, _tempnam(tdir, "salvage.inodes."), 255);
#else
- snprintf(inodeListPath, 255, "%s/salvage.inodes.%s.%d", tdir, name,
+ snprintf(inodeListPath, 255, "%s" OS_DIRSEP "salvage.inodes.%s.%d", tdir, name,
getpid());
#endif
* semantics of unlink. In most places in the salvager, we really do
* mean to unlink the file at that point. Those places have been
* modified to actually do that so that the NT crt can be used there.
+ *
+ * jaltman - On NT delete on close cannot be applied to a file while the
+ * process has an open file handle that does not have DELETE file
+ * access and FILE_SHARE_DELETE. fopen() calls CreateFile() without
+ * delete privileges. As a result the nt_unlink() call will always
+ * fail.
*/
code = nt_unlink(inodeListPath);
#else
RemoveTheForce(salvinfo->fileSysPath);
if (!Testing && singleVolumeNumber) {
+ int foundSVN = 0;
#ifdef AFS_DEMAND_ATTACH_FS
/* unlock vol headers so the fs can attach them when we AskOnline */
VLockFileReinit(&salvinfo->fileSysPartition->volLockFile);
#endif /* AFS_DEMAND_ATTACH_FS */
- AskOnline(salvinfo, singleVolumeNumber);
-
/* Step through the volumeSummary list and set all volumes on-line.
- * The volumes were taken off-line in GetVolumeSummary.
+ * Most volumes were taken off-line in GetVolumeSummary.
+ * If a volume was deleted, don't tell the fileserver anything, since
+ * we already told the fileserver the volume was deleted back when we
+ * we destroyed the volume header.
+ * Also, make sure we bring the singleVolumeNumber back online first.
*/
+
+ for (j = 0; j < salvinfo->nVolumes; j++) {
+ if (salvinfo->volumeSummaryp[j].header.id == singleVolumeNumber) {
+ foundSVN = 1;
+ if (!salvinfo->volumeSummaryp[j].deleted) {
+ AskOnline(salvinfo, singleVolumeNumber);
+ }
+ }
+ }
+
+ if (!foundSVN) {
+ /* singleVolumeNumber generally should always be in the constructed
+ * volumeSummary, but just in case it's not... */
+ AskOnline(salvinfo, singleVolumeNumber);
+ }
+
for (j = 0; j < salvinfo->nVolumes; j++) {
- AskOnline(salvinfo, salvinfo->volumeSummaryp[j].header.id);
+ if (salvinfo->volumeSummaryp[j].header.id != singleVolumeNumber) {
+ if (!salvinfo->volumeSummaryp[j].deleted) {
+ AskOnline(salvinfo, salvinfo->volumeSummaryp[j].header.id);
+ }
+ }
}
} else {
if (!Showmode)
DeleteExtraVolumeHeaderFile(struct SalvInfo *salvinfo, struct VolumeSummary *vsp)
{
char path[64];
- sprintf(path, "%s/%s", salvinfo->fileSysPath, vsp->fileName);
+ sprintf(path, "%s" OS_DIRSEP "%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 (unlink(path) && errno != ENOENT) {
Log("Unable to unlink %s (errno = %d)\n", path, errno);
}
+ if (salvinfo->useFSYNC) {
+ AskDelete(salvinfo, vsp->header.id);
+ }
+ vsp->deleted = 1;
}
vsp->fileName = 0;
}
tdir = (tmpdir ? tmpdir : part);
#ifdef AFS_NT40_ENV
(void)_putenv("TMP="); /* If "TMP" is set, then that overrides tdir. */
- (void)strcpy(summaryFileName, _tempnam(tdir, "salvage.temp"));
+ (void)strcpy(summaryFileName, _tempnam(tdir, "salvage.temp."));
#else
(void)afs_snprintf(summaryFileName, sizeof summaryFileName,
- "%s/salvage.temp.%d", tdir, getpid());
+ "%s" OS_DIRSEP "salvage.temp.%d", tdir, getpid());
#endif
summaryFile = afs_fopen(summaryFileName, "a+");
if (summaryFile == NULL) {
* semantics of unlink. In most places in the salvager, we really do
* mean to unlink the file at that point. Those places have been
* modified to actually do that so that the NT crt can be used there.
+ *
+ * jaltman - As commented elsewhere, this cannot work because fopen()
+ * does not open files with DELETE and FILE_SHARE_DELETE.
*/
code = nt_unlink(summaryFileName);
#else
Exit(SALSRV_EXIT_VOLGROUP_LINK);
}
- salvinfo->volumeSummaryp = malloc(VOL_VG_MAX_VOLS * sizeof(struct VolumeSummary));
+ salvinfo->volumeSummaryp = calloc(VOL_VG_MAX_VOLS, sizeof(struct VolumeSummary));
osi_Assert(salvinfo->volumeSummaryp != NULL);
salvinfo->nVolumes = 0;
/* check if the header file is incorrectly named */
int badname = 0;
- const char *base = strrchr(name, '/');
+ const char *base = strrchr(name, OS_DIRSEPC);
if (base) {
base++;
} else {
nvols = VOL_VG_MAX_VOLS;
}
- salvinfo->volumeSummaryp = malloc(nvols * sizeof(struct VolumeSummary));
+ salvinfo->volumeSummaryp = calloc(nvols, sizeof(struct VolumeSummary));
osi_Assert(salvinfo->volumeSummaryp != NULL);
params.singleVolumeNumber = singleVolumeNumber;
for (i = 0; i < nVols; i++) {
ip = allInodes + isp[i].index;
for (j = isp[i].nSpecialInodes; j < isp[i].nInodes; j++) {
-#ifdef AFS_NT40_ENV
- nt_SetLinkCount(fdP, ip[j].inodeNumber, 1, 1);
-#else
namei_SetLinkCount(fdP, ip[j].inodeNumber, 1, 1);
-#endif
}
}
}
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", salvinfo->fileSysPath, headerName);
+ (void)afs_snprintf(path, sizeof path, "%s" OS_DIRSEP "%s", salvinfo->fileSysPath, headerName);
if (check) {
Log("No header file for volume %u\n", isp->volumeId);
return -1;
Log("No header file for volume %u; %screating %s\n",
isp->volumeId, (Testing ? "it would have been " : ""),
path);
- isp->volSummary = (struct VolumeSummary *)
- malloc(sizeof(struct VolumeSummary));
+ isp->volSummary = calloc(1, sizeof(struct VolumeSummary));
isp->volSummary->fileName = ToString(headerName);
writefunc = VCreateVolumeDiskHeader;
(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", salvinfo->fileSysPath, headerName);
+ (void)afs_snprintf(path, sizeof path, "%s" OS_DIRSEP "%s", salvinfo->fileSysPath, headerName);
Log("Header file %s is damaged or no longer valid%s\n", path,
(check ? "" : "; repairing"));
} else {
if (vcp->magic != vnode->vnodeMagic) {
/* bad magic #, probably partially created vnode */
+ if (check) {
+ Log("Partially allocated vnode %d: bad magic (is %lx should be %lx)\n",
+ vnodeNumber, afs_printable_uint32_lu(vnode->vnodeMagic),
+ afs_printable_uint32_lu(vcp->magic));
+ memset(vnode, 0, vcp->diskSize);
+ err = -1;
+ goto zooks;
+ }
Log("Partially allocated vnode %d deleted.\n",
vnodeNumber);
memset(vnode, 0, vcp->diskSize);
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);
+ Log("dir vnode %u: invalid entry deleted: %s" OS_DIRSEP "%s (vnode %u, unique %u)\n", dir->vnodeNumber, dir->name ? dir->name : "??", name, vnodeNumber, unique);
}
if (!Testing) {
CopyOnWrite(salvinfo, dir);
* 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"));
+ Log("dir vnode %d: invalid entry: %s" OS_DIRSEP "%s has no inode (vnode %d, unique %d)%s\n", dir->vnodeNumber, (dir->name ? dir->name : "??"), name, vnodeNumber, unique, (Testing ? "-- would have deleted" : " -- deleted"));
if (!Testing) {
CopyOnWrite(salvinfo, dir);
osi_Assert(Delete(&dir->dirHandle, name) == 0);
if (!(vnodeNumber & 1) && !Showmode
&& !(vnodeEssence->count || vnodeEssence->unique
|| vnodeEssence->modeBits)) {
- Log("dir vnode %u: invalid entry: %s/%s (vnode %u, unique %u)%s\n",
+ Log("dir vnode %u: invalid entry: %s" OS_DIRSEP "%s (vnode %u, unique %u)%s\n",
dir->vnodeNumber, (dir->name ? dir->name : "??"), name,
vnodeNumber, unique,
((!unique) ? (Testing ? "-- would have deleted" : " -- deleted") :
todelete = ((!vnodeEssence->unique || dirOrphaned) ? 1 : 0);
if (!Showmode) {
- Log("dir vnode %u: %s/%s (vnode %u): unique changed from %u to %u %s\n", dir->vnodeNumber, (dir->name ? dir->name : "??"), name, vnodeNumber, unique, vnodeEssence->unique, (!todelete ? "" : (Testing ? "-- would have deleted" : "-- deleted")));
+ Log("dir vnode %u: %s" OS_DIRSEP "%s (vnode %u): unique changed from %u to %u %s\n", dir->vnodeNumber, (dir->name ? dir->name : "??"), name, vnodeNumber, unique, vnodeEssence->unique, (!todelete ? "" : (Testing ? "-- would have deleted" : "-- deleted")));
}
if (!Testing) {
AFSFid fid;
return 0;
} else {
if (ShowSuid && (vnodeEssence->modeBits & 06000))
- Log("FOUND suid/sgid file: %s/%s (%u.%u %05o) author %u (vnode %u dir %u)\n", dir->name ? dir->name : "??", name, vnodeEssence->owner, vnodeEssence->group, vnodeEssence->modeBits, vnodeEssence->author, vnodeNumber, dir->vnodeNumber);
+ Log("FOUND suid/sgid file: %s" OS_DIRSEP "%s (%u.%u %05o) author %u (vnode %u dir %u)\n", dir->name ? dir->name : "??", name, vnodeEssence->owner, vnodeEssence->group, vnodeEssence->modeBits, vnodeEssence->author, vnodeNumber, dir->vnodeNumber);
if (/* ShowMounts && */ (vnodeEssence->type == vSymlink)
&& !(vnodeEssence->modeBits & 0111)) {
- ssize_t nBytes;
+ afs_sfsize_t nBytes;
afs_sfsize_t size;
char buf[1025];
IHandle_t *ihP;
if (nBytes == size) {
buf[size] = '\0';
if ( (*buf != '#' && *buf != '%') || buf[strlen(buf)-1] != '.' ) {
- Log("Volume %u (%s) mount point %s/%s to '%s' invalid, %s to symbolic link\n",
+ Log("Volume %u (%s) mount point %s" OS_DIRSEP "%s to '%s' invalid, %s to symbolic link\n",
dir->dirHandle.dirh_handle->ih_vid, dir->vname, dir->name ? dir->name : "??", name, buf,
Testing ? "would convert" : "converted");
vnodeEssence->modeBits |= 0111;
vnodeEssence->changed = 1;
- } else if (ShowMounts) Log("In volume %u (%s) found mountpoint %s/%s to '%s'\n",
+ } else if (ShowMounts) Log("In volume %u (%s) found mountpoint %s" OS_DIRSEP "%s to '%s'\n",
dir->dirHandle.dirh_handle->ih_vid, dir->vname,
dir->name ? dir->name : "??", name, buf);
} else {
IH_RELEASE(ihP);
}
if (ShowRootFiles && vnodeEssence->owner == 0 && vnodeNumber != 1)
- Log("FOUND root file: %s/%s (%u.%u %05o) author %u (vnode %u dir %u)\n", dir->name ? dir->name : "??", name, vnodeEssence->owner, vnodeEssence->group, vnodeEssence->modeBits, vnodeEssence->author, vnodeNumber, dir->vnodeNumber);
+ Log("FOUND root file: %s" OS_DIRSEP "%s (%u.%u %05o) author %u (vnode %u dir %u)\n", dir->name ? dir->name : "??", name, vnodeEssence->owner, vnodeEssence->group, vnodeEssence->modeBits, vnodeEssence->author, vnodeNumber, dir->vnodeNumber);
if (vnodeIdToClass(vnodeNumber) == vLarge
&& vnodeEssence->name == NULL) {
char *n;
* another non-orphaned dir).
*/
if (!Showmode) {
- Log("dir vnode %u: %s/%s (vnode %u, unique %u) -- parent vnode %schanged from %u to %u\n", dir->vnodeNumber, (dir->name ? dir->name : "??"), name, vnodeNumber, unique, (Testing ? "would have been " : ""), vnodeEssence->parent, dir->vnodeNumber);
+ Log("dir vnode %u: %s" OS_DIRSEP "%s (vnode %u, unique %u) -- parent vnode %schanged from %u to %u\n", dir->vnodeNumber, (dir->name ? dir->name : "??"), name, vnodeNumber, unique, (Testing ? "would have been " : ""), vnodeEssence->parent, dir->vnodeNumber);
}
vnodeEssence->parent = dir->vnodeNumber;
vnodeEssence->changed = 1;
/* Vnode was claimed by another directory */
if (!Showmode) {
if (dirOrphaned) {
- Log("dir vnode %u: %s/%s parent vnode is %u (vnode %u, unique %u) -- %sdeleted\n", dir->vnodeNumber, (dir->name ? dir->name : "??"), name, vnodeEssence->parent, vnodeNumber, unique, (Testing ? "would have been " : ""));
+ Log("dir vnode %u: %s" OS_DIRSEP "%s parent vnode is %u (vnode %u, unique %u) -- %sdeleted\n", dir->vnodeNumber, (dir->name ? dir->name : "??"), name, vnodeEssence->parent, vnodeNumber, unique, (Testing ? "would have been " : ""));
} else if (vnodeNumber == 1) {
- Log("dir vnode %d: %s/%s is invalid (vnode %d, unique %d) -- %sdeleted\n", dir->vnodeNumber, (dir->name ? dir->name : "??"), name, vnodeNumber, unique, (Testing ? "would have been " : ""));
+ Log("dir vnode %d: %s" OS_DIRSEP "%s is invalid (vnode %d, unique %d) -- %sdeleted\n", dir->vnodeNumber, (dir->name ? dir->name : "??"), name, vnodeNumber, unique, (Testing ? "would have been " : ""));
} else {
- Log("dir vnode %u: %s/%s already claimed by directory vnode %u (vnode %u, unique %u) -- %sdeleted\n", dir->vnodeNumber, (dir->name ? dir->name : "??"), name, vnodeEssence->parent, vnodeNumber, unique, (Testing ? "would have been " : ""));
+ Log("dir vnode %u: %s" OS_DIRSEP "%s already claimed by directory vnode %u (vnode %u, unique %u) -- %sdeleted\n", dir->vnodeNumber, (dir->name ? dir->name : "??"), name, vnodeEssence->parent, vnodeNumber, unique, (Testing ? "would have been " : ""));
}
}
if (!Testing) {
}
if (vp->parent && vp->name && (parentvp = CheckVnodeNumber(salvinfo, vp->parent))
&& GetDirName(salvinfo, vp->parent, parentvp, path)) {
- strcat(path, "/");
+ strcat(path, OS_DIRSEP);
strcat(path, vp->name);
return path;
}
* will get removed here also (if requested).
*/
for (class = 0; class < nVNODECLASSES; class++) {
- int nVnodes = salvinfo->vnodeInfo[class].nVnodes;
+ afs_sfsize_t nVnodes = salvinfo->vnodeInfo[class].nVnodes;
struct VnodeClassInfo *vcp = &VnodeClassInfo[class];
struct VnodeEssence *vnodes = salvinfo->vnodeInfo[class].vnodes;
FilesInVolume += salvinfo->vnodeInfo[class].nAllocatedVnodes;
}
#ifdef FSSYNC_BUILD_CLIENT
- if (!Testing && salvinfo->VolumeChanged) {
+ if (!Testing && salvinfo->VolumeChanged && salvinfo->useFSYNC) {
afs_int32 fsync_code;
fsync_code = FSYNC_VolOp(vid, NULL, FSYNC_VOL_BREAKCBKS, FSYNC_SALVAGE, NULL);
if (!Testing) {
afs_int32 code;
char path[64];
- sprintf(path, "%s/%s", salvinfo->fileSysPath, isp->volSummary->fileName);
+ sprintf(path, "%s" OS_DIRSEP "%s", salvinfo->fileSysPath, isp->volSummary->fileName);
code = VDestroyVolumeDiskHeader(salvinfo->fileSysPartition, isp->volumeId, isp->RWvolumeId);
if (code) {
if (unlink(path) && errno != ENOENT) {
Log("Unable to unlink %s (errno = %d)\n", path, errno);
}
+ if (salvinfo->useFSYNC) {
+ AskDelete(salvinfo, isp->volumeId);
+ }
+ isp->volSummary->deleted = 1;
}
}
} else if (!check) {
break;
} else if (i < 2) {
/* try it again */
- Log("AskOnline: request for fileserver to take volume offline failed; trying again...\n");
+ Log("AskOnline: request for fileserver to put volume online failed; trying again...\n");
+ FSYNC_clientFinis();
+ FSYNC_clientInit();
+ }
+ }
+}
+
+void
+AskDelete(struct SalvInfo *salvinfo, VolumeId volumeId)
+{
+ afs_int32 code, i;
+
+ for (i = 0; i < 3; i++) {
+ code = FSYNC_VolOp(volumeId, salvinfo->fileSysPartition->name,
+ FSYNC_VOL_DONE, FSYNC_SALVAGE, NULL);
+
+ if (code == SYNC_OK) {
+ break;
+ } else if (code == SYNC_DENIED) {
+ Log("AskOnline: file server denied DONE request to volume %u partition %s; trying again...\n", volumeId, salvinfo->fileSysPartition->name);
+ } else if (code == SYNC_BAD_COMMAND) {
+ Log("AskOnline: fssync protocol mismatch (bad command word '%d')\n",
+ FSYNC_VOL_DONE);
+#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
+ break;
+ } else if (i < 2) {
+ /* try it again */
+ Log("AskOnline: request for fileserver to delete volume failed; trying again...\n");
FSYNC_clientFinis();
FSYNC_clientInit();
}