RCSID
("$Header$");
+#ifndef AFS_NT40_ENV
+#include <sys/param.h>
+#include <sys/file.h>
+#ifndef ITIMER_REAL
+#include <sys/time.h>
+#endif /* ITIMER_REAL */
+#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifdef AFS_NT40_ENV
#include <io.h>
#include <WINNT/afsevent.h>
-#else
-#include <sys/param.h>
-#include <sys/file.h>
-#ifndef ITIMER_REAL
-#include <sys/time.h>
-#endif /* ITIMER_REAL */
#endif
#if defined(AFS_AIX_ENV) || defined(AFS_SUN4_ENV)
#define WCOREDUMP(x) (x & 0200)
int debug; /* -d flag */
-int Testing = 0; /* -n flag */
+extern int Testing; /* -n flag */
int ListInodeOption; /* -i flag */
int ShowRootFiles; /* -r flag */
int RebuildDirs; /* -sal flag */
int orphans = ORPH_IGNORE; /* -orphans option */
int Showmode = 0;
+
#ifndef AFS_NT40_ENV
int useSyslog = 0; /* -syslog flag */
int useSyslogFacility = LOG_DAEMON; /* -syslogfacility option */
#endif
+#ifdef AFS_NT40_ENV
+int canfork = 0;
+#else
+int canfork = 1;
+#endif
+
#define MAXPARALLEL 32
int OKToZap; /* -o flag */
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 DiskPartition *fileSysPartition; /* Partition being salvaged */
+struct DiskPartition64 *fileSysPartition; /* Partition being salvaged */
#ifndef AFS_NT40_ENV
char *fileSysDeviceName; /* The block device where the file system
* being salvaged was mounted */
int nVolumes; /* Number of volumes (read-write and read-only)
* in volume summary */
-extern char * tmpdir = 0;
+char *tmpdir = NULL;
return 0; /* otherwise may be transient, e.g. EMFILE */
}
-
#define MAX_ARGS 128
#ifdef AFS_NT40_ENV
char *save_args[MAX_ARGS];
int n_save_args = 0;
-pthread_t main_thread;
+extern pthread_t main_thread;
+childJob_t myjob = { SALVAGER_MAGIC, NOT_CHILD, "" };
#endif
-
/* Get the salvage lock if not already held. Hold until process exits. */
void
ObtainSalvageLock(void)
#define HDSTR "\\Device\\Harddisk"
#define HDLEN (sizeof(HDSTR)-1) /* Length of "\Device\Harddisk" */
int
-SameDisk(struct DiskPartition *p1, struct DiskPartition *p2)
+SameDisk(struct DiskPartition64 *p1, struct DiskPartition64 *p2)
{
#define RES_LEN 256
char res[RES_LEN];
* PartsPerDisk are on the same disk.
*/
void
-SalvageFileSysParallel(struct DiskPartition *partP)
+SalvageFileSysParallel(struct DiskPartition64 *partP)
{
struct job {
- struct DiskPartition *partP;
+ struct DiskPartition64 *partP;
int pid; /* Pid for this job */
int jobnumb; /* Log file job number */
struct job *nextjob; /* Next partition on disk to salvage */
void
-SalvageFileSys(struct DiskPartition *partP, VolumeId singleVolumeNumber)
+SalvageFileSys(struct DiskPartition64 *partP, VolumeId singleVolumeNumber)
{
if (!canfork || debug || Fork() == 0) {
SalvageFileSys1(partP, singleVolumeNumber);
}
void
-SalvageFileSys1(struct DiskPartition *partP, VolumeId singleVolumeNumber)
+SalvageFileSys1(struct DiskPartition64 *partP, VolumeId singleVolumeNumber)
{
char *name, *tdir;
char inodeListPath[256];
if ((programType != salvageServer) && !VConnectFS()) {
Abort("Couldn't connect to file server\n");
}
- AskOffline(singleVolumeNumber);
+ AskOffline(singleVolumeNumber, partP->name);
} else {
if (!Showmode)
Log("SALVAGING FILE SYSTEM PARTITION %s (device=%s%s)\n",
}
int
-OnlyOneVolume(struct ViceInodeInfo *inodeinfo, VolumeId singleVolumeNumber, void *rock)
+OnlyOneVolume(struct ViceInodeInfo *inodeinfo, int singleVolumeNumber, void *rock)
{
if (inodeinfo->u.vnode.vnodeNumber == INODESPECIAL)
return (inodeinfo->u.special.parentId == singleVolumeNumber);
void
GetVolumeSummary(VolumeId singleVolumeNumber)
{
- DIR *dirp;
+ DIR *dirp = NULL;
afs_int32 nvols = 0;
struct VolumeSummary *vsp, vs;
struct VolumeDiskHeader diskHeader;
struct dirent *dp;
/* Get headers from volume directory */
- if (chdir(fileSysPath) == -1 || (dirp = opendir(".")) == NULL)
+ dirp = opendir(fileSysPath);
+ if (dirp == NULL)
Abort("Can't read directory %s; not salvaged\n", fileSysPath);
if (!singleVolumeNumber) {
while ((dp = readdir(dirp))) {
DiskToVolumeHeader(&vsp->header, &diskHeader);
if (singleVolumeNumber && vsp->header.id == singleVolumeNumber
&& vsp->header.parent != singleVolumeNumber) {
- Log("%u is a read-only volume; not salvaged\n",
- singleVolumeNumber);
- Exit(1);
+ if (programType == salvageServer) {
+#ifdef SALVSYNC_BUILD_CLIENT
+ Log("fileserver requested salvage of clone %u; scheduling salvage of volume group %u...\n",
+ vsp->header.id, vsp->header.parent);
+ if (SALVSYNC_LinkVolume(vsp->header.parent,
+ vsp->header.id,
+ fileSysPartition->name,
+ NULL) != SYNC_OK) {
+ Log("schedule request failed\n");
+ }
+#endif
+ Exit(SALSRV_EXIT_VOLGROUP_LINK);
+ } else {
+ Log("%u is a read-only volume; not salvaged\n",
+ singleVolumeNumber);
+ Exit(1);
+ }
}
if (!singleVolumeNumber
|| (vsp->header.id == singleVolumeNumber
|| vsp->header.parent == singleVolumeNumber)) {
(void)afs_snprintf(nameShouldBe, sizeof nameShouldBe,
VFORMAT, vsp->header.id);
- if (singleVolumeNumber)
- AskOffline(vsp->header.id);
+ if (singleVolumeNumber
+ && vsp->header.id != singleVolumeNumber)
+ AskOffline(vsp->header.id, fileSysPartition->name);
if (strcmp(nameShouldBe, dp->d_name)) {
if (!Showmode)
Log("Volume header file %s is incorrectly named; %sdeleted (it will be recreated later, if necessary)\n", dp->d_name, (Testing ? "it would have been " : ""));
Abort("Can't open link table for volume %u (error = %d)\n",
isp->RWvolumeId, errno);
- if (FDH_TRUNC(fdP, 0) < 0)
+ if (FDH_TRUNC(fdP, sizeof(version) + sizeof(short)) < 0)
Abort("Can't truncate link table for volume %u (error = %d)\n",
isp->RWvolumeId, errno);
int check;
Inode ino;
int dec_VGLinkH = 0;
- int VGLinkH_p1;
+ int VGLinkH_p1 =0;
FdHandle_t *fdP = NULL;
VGLinkH_cnt = 0;
if (Testing) {
IH_INIT(VGLinkH, fileSysDevice, -1, -1);
} else {
+ int i, j;
+ struct ViceInodeInfo *ip;
CreateLinkTable(isp, ino);
+ fdP = IH_OPEN(VGLinkH);
+ /* Sync fake 1 link counts to the link table, now that it exists */
+ if (fdP) {
+ 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
+ }
+ }
+ }
}
}
if (fdP)
&& volHeader.stamp.magic == VOLUMEINFOMAGIC
&& volHeader.dontSalvage == DONT_SALVAGE
&& volHeader.needsSalvaged == 0 && volHeader.destroyMe == 0) {
- if (volHeader.inUse == 1) {
+ if (volHeader.inUse != 0) {
volHeader.inUse = 0;
volHeader.inService = 1;
if (!Testing) {
}
if (VNDISK_GET_INO(vnode)) {
if (!Showmode) {
- Log("Vnode %d (unique %u): corresponding inode %s is missing; vnode deleted, vnode mod time=%s", vnodeNumber, vnode->uniquifier, PrintInode(NULL, VNDISK_GET_INO(vnode)), ctime((time_t *) & (vnode->serverModifyTime)));
+ time_t serverModifyTime = vnode->serverModifyTime;
+ Log("Vnode %d (unique %u): corresponding inode %s is missing; vnode deleted, vnode mod time=%s", vnodeNumber, vnode->uniquifier, PrintInode(NULL, VNDISK_GET_INO(vnode)), ctime(&serverModifyTime));
}
} else {
- if (!Showmode)
- Log("Vnode %d (unique %u): bad directory vnode (no inode number listed); vnode deleted, vnode mod time=%s", vnodeNumber, vnode->uniquifier, ctime((time_t *) & (vnode->serverModifyTime)));
+ if (!Showmode) {
+ time_t serverModifyTime = vnode->serverModifyTime;
+ Log("Vnode %d (unique %u): bad directory vnode (no inode number listed); vnode deleted, vnode mod time=%s", vnodeNumber, vnode->uniquifier, ctime(&serverModifyTime));
+ }
}
memset(vnode, 0, vcp->diskSize);
vnodeChanged = 1;
struct VnodeDiskObject vnode;
struct VnodeClassInfo *vcp = &VnodeClassInfo[vLarge];
Inode oldinode, newinode;
- int code;
+ afs_sfsize_t code;
if (dir->copied || Testing)
return;
struct VnodeClassInfo *vcp = &VnodeClassInfo[vLarge];
Inode oldinode, newinode;
DirHandle newdir;
- register afs_int32 code;
+ FdHandle_t *fdP;
+ afs_int32 code;
+ afs_sfsize_t lcode;
afs_int32 parentUnique = 1;
struct VnodeEssence *vnodeEssence;
+ afs_fsize_t length;
if (Testing)
return;
Log("Salvaging directory %u...\n", dir->vnodeNumber);
- code =
+ lcode =
IH_IREAD(vnodeInfo[vLarge].handle,
vnodeIndexOffset(vcp, dir->vnodeNumber), (char *)&vnode,
sizeof(vnode));
- assert(code == sizeof(vnode));
+ assert(lcode == sizeof(vnode));
oldinode = VNDISK_GET_INO(&vnode);
/* Increment the version number by a whole lot to avoid problems with
* clients that were promised new version numbers--but the file server
if (code) {
/* didn't really build the new directory properly, let's just give up. */
code = IH_DEC(dir->ds_linkH, newinode, dir->rwVid);
- assert(code == 0);
Log("Directory salvage returned code %d, continuing.\n", code);
+ if (code) {
+ Log("also failed to decrement link count on new inode");
+ }
assert(1 == 2);
}
Log("Checking the results of the directory salvage...\n");
}
vnode.cloned = 0;
VNDISK_SET_INO(&vnode, newinode);
- VNDISK_SET_LEN(&vnode, Length(&newdir));
- code =
+ length = Length(&newdir);
+ VNDISK_SET_LEN(&vnode, length);
+ lcode =
IH_IWRITE(vnodeInfo[vLarge].handle,
vnodeIndexOffset(vcp, dir->vnodeNumber), (char *)&vnode,
sizeof(vnode));
- assert(code == sizeof(vnode));
+ assert(lcode == sizeof(vnode));
+#if 0
#ifdef AFS_NT40_ENV
nt_sync(fileSysDevice);
#else
* an open FD on the file itself to fsync.
*/
#endif
+#else
+ 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;
}
-void
+int
JudgeEntry(struct DirSummary *dir, char *name, VnodeId vnodeNumber,
Unique unique)
{
CopyOnWrite(dir);
assert(Delete(&dir->dirHandle, name) == 0);
}
- return;
+ return 0;
}
#ifdef AFS_AIX_ENV
#ifndef AFS_NAMEI_ENV
CopyOnWrite(dir);
assert(Delete(&dir->dirHandle, name) == 0);
}
- return;
+ return 0;
}
#endif
#endif
CopyOnWrite(dir);
assert(Delete(&dir->dirHandle, name) == 0);
}
- return;
+ return 0;
}
}
* entry. Otherwise, it will get created in the next
* salvage and deleted again here. So Just skip it.
*/
- return;
+ return 0;
}
todelete = ((!vnodeEssence->unique || dirOrphaned) ? 1 : 0);
assert(Create(&dir->dirHandle, name, &fid) == 0);
}
if (todelete)
- return; /* no need to continue */
+ return 0; /* no need to continue */
}
if (strcmp(name, ".") == 0) {
}
vnodeEssence->claimed = 0; /* Not claimed: Orphaned */
vnodeEssence->todelete = 1; /* Will later delete vnode and decr inode */
- return;
+ 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);
- if (ShowMounts && (vnodeEssence->type == vSymlink)
+ if (/* ShowMounts && */ (vnodeEssence->type == vSymlink)
&& !(vnodeEssence->modeBits & 0111)) {
int code, size;
- char buf[1024];
+ char buf[1025];
IHandle_t *ihP;
FdHandle_t *fdP;
IH_INIT(ihP, fileSysDevice, dir->dirHandle.dirh_handle->ih_vid,
vnodeEssence->InodeNumber);
fdP = IH_OPEN(ihP);
- assert(fdP != NULL);
+ if (fdP == NULL) {
+ Log("ERROR %s could not open mount point vnode %u\n", dir->vname, vnodeNumber);
+ IH_RELEASE(ihP);
+ return 0;
+ }
size = FDH_SIZE(fdP);
- assert(size != -1);
- memset(buf, 0, 1024);
+ if (size < 0) {
+ Log("ERROR %s mount point has invalid size %d, vnode %u\n", dir->vname, size, vnodeNumber);
+ FDH_REALLYCLOSE(fdP);
+ IH_RELEASE(ihP);
+ return 0;
+ }
+
if (size > 1024)
size = 1024;
code = FDH_READ(fdP, buf, size);
- assert(code == size);
- Log("In volume %u (%s) found mountpoint %s/%s to '%s'\n",
- dir->dirHandle.dirh_handle->ih_vid, dir->vname,
- dir->name ? dir->name : "??", name, buf);
+ if (code == 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",
+ 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",
+ dir->dirHandle.dirh_handle->ih_vid, dir->vname,
+ dir->name ? dir->name : "??", name, buf);
+ } else {
+ Log("Volume %s cound not read mount point vnode %u size %d code %d\n",
+ dir->vname, vnodeNumber, size, code);
+ }
FDH_REALLYCLOSE(fdP);
IH_RELEASE(ihP);
}
CopyOnWrite(dir);
assert(Delete(&dir->dirHandle, name) == 0);
}
- return;
+ return 0;
}
}
/* This directory claims the vnode */
vnodeEssence->claimed = 1;
}
vnodeEssence->count--;
+ return 0;
}
void
struct VnodeClassInfo *vcp = &VnodeClassInfo[class];
char buf[SIZEOF_LARGEDISKVNODE];
struct VnodeDiskObject *vnode = (struct VnodeDiskObject *)buf;
- int size;
+ afs_sfsize_t size;
StreamHandle_t *file;
int vnodeIndex;
int nVnodes;
struct VnodeEssence *vep;
afs_int32 v, pv;
IHandle_t *h;
- int nBytes;
+ afs_sfsize_t nBytes;
ViceFid pa;
VnodeId LFVnode, ThisVnode;
Unique LFUnique, ThisUnique;
SalvageDir(volHeader.name, vid, dirVnodeInfo, alinkH, i, &rootdir,
&rootdirfound);
}
+#ifdef AFS_NT40_ENV
+ nt_sync(fileSysDevice);
+#else
+ sync(); /* This used to be done lower level, for every dir */
+#endif
if (Showmode) {
IH_RELEASE(h);
return 0;
if (!Showmode) {
Log("Vnode %u: link count incorrect (was %d, %s %d)\n", vnodeNumber, oldCount, (Testing ? "would have changed to" : "now"), vnode.linkCount);
}
+ } else {
+ vnode.modeBits = vnp->modeBits;
}
vnode.dataVersion++;
ClearROInUseBit(struct VolumeSummary *summary)
{
IHandle_t *h = summary->volumeInfoHandle;
- int nBytes;
+ afs_sfsize_t nBytes;
VolumeDiskData volHeader;
volHeader.inService = 1;
volHeader.dontSalvage = DONT_SALVAGE;
if (!Testing) {
- nBytes = IH_IREAD(h, 0, (char *)&volHeader, sizeof(volHeader));
+ nBytes = IH_IWRITE(h, 0, (char *)&volHeader, sizeof(volHeader));
assert(nBytes == sizeof(volHeader));
}
}
void
-AskOffline(VolumeId volumeId)
+AskOffline(VolumeId volumeId, char * partition)
{
afs_int32 code, i;
for (i = 0; i < 3; i++) {
- code = FSYNC_VolOp(volumeId, NULL, FSYNC_VOL_OFF, FSYNC_SALVAGE, NULL);
+ code = FSYNC_VolOp(volumeId, partition, FSYNC_VOL_OFF, FSYNC_SALVAGE, NULL);
if (code == SYNC_OK) {
break;
#else
f = fork();
assert(f >= 0);
+#ifdef AFS_DEMAND_ATTACH_FS
+ if ((f == 0) && (programType == salvageServer)) {
+ /* we are a salvageserver child */
+#ifdef FSSYNC_BUILD_CLIENT
+ VChildProcReconnectFS_r();
+#endif
+#ifdef SALVSYNC_BUILD_CLIENT
+ VReconnectSALV_r();
#endif
+ }
+#endif /* AFS_DEMAND_ATTACH_FS */
+#endif /* !AFS_NT40_ENV */
return f;
}
{
if (ShowLog)
showlog();
+
+#ifdef AFS_DEMAND_ATTACH_FS
+ if (programType == salvageServer) {
+#ifdef SALVSYNC_BUILD_CLIENT
+ VDisconnectSALV();
+#endif
+#ifdef FSSYNC_BUILD_CLIENT
+ VDisconnectFS();
+#endif
+ }
+#endif /* AFS_DEMAND_ATTACH_FS */
+
#ifdef AFS_NT40_ENV
if (main_thread != pthread_self())
pthread_exit((void *)code);
static char timestamp[20];
lt = localtime(&clock);
if (precision)
- (void)strftime(timestamp, 20, "%m/%d/%Y %T", lt);
+ (void)strftime(timestamp, 20, "%m/%d/%Y %H:%M:%S", lt);
else
(void)strftime(timestamp, 20, "%m/%d/%Y %H:%M", lt);
return timestamp;
syslog(LOG_INFO, "%s", tmp);
} else
#endif
- {
- gettimeofday(&now, 0);
- fprintf(logFile, "%s %s", TimeStamp(now.tv_sec, 1), tmp);
- fflush(logFile);
- }
+ if (logFile) {
+ gettimeofday(&now, 0);
+ fprintf(logFile, "%s %s", TimeStamp(now.tv_sec, 1), tmp);
+ fflush(logFile);
+ }
}
void
syslog(LOG_INFO, "%s", tmp);
} else
#endif
- {
- fprintf(logFile, "%s", tmp);
- fflush(logFile);
- if (ShowLog)
- showlog();
- }
+ if (logFile) {
+ fprintf(logFile, "%s", tmp);
+ fflush(logFile);
+ if (ShowLog)
+ showlog();
+ }
if (debug)
abort();
assert(p != NULL);
strcpy(p, s);
return p;
-
}
/* Remove the FORCESALVAGE file */
void
RemoveTheForce(char *path)
{
+ char target[1024];
+ struct afs_stat force; // so we can use afs_stat to find it
+ strcpy(target,path);
+ strcat(target,"/FORCESALVAGE");
if (!Testing && ForceSalvage) {
- if (chdir(path) == 0)
- unlink("FORCESALVAGE");
+ if (afs_stat(target,&force) == 0) unlink(target);
}
}
UseTheForceLuke(char *path)
{
struct afs_stat force;
+ char target[1024];
+ strcpy(target,path);
+ strcat(target,"/FORCESALVAGE");
- assert(chdir(path) != -1);
-
- return (afs_stat("FORCESALVAGE", &force) == 0);
+ return (afs_stat(target, &force) == 0);
}
#else
/*