dafs-20060317

FIXES 26648

demand attach/fast restart fileserver
This commit is contained in:
Tom Keiser 2006-03-17 19:54:26 +00:00 committed by Derrick Brashear
parent cba4f12e17
commit 51ec267011
71 changed files with 18626 additions and 2350 deletions

View File

@ -213,6 +213,24 @@ sgiefs:
vol: cmd comerr dir afs sgiefs
${COMPILE_PART1} vol ${COMPILE_PART2}
tsalvaged: vol libafsrpc libafsauthent cmd util
set -x; \
if test "@DEMAND_ATTACH@" = "yes" ; then \
case ${SYS_NAME} in \
alpha_dux*|sgi_*|sun*_5*|rs_aix*|*linux*|hp_ux11*|ia64_hpux*|*fbsd*|*nbsd2*) \
${COMPILE_PART1} tsalvaged ${COMPILE_PART2} ;; \
*_darwin_[1-6][0-9]) \
echo Not building MT tsalvaged for ${SYS_NAME} ;; \
*_darwin_*) \
${COMPILE_PART1} tsalvaged ${COMPILE_PART2} ;; \
*) \
echo Not building MT tsalvaged for ${SYS_NAME} ;; \
esac \
else \
echo skipping tsalvaged ; \
fi
vlserver: cmd comerr vol audit vlserver_depinstall
${COMPILE_PART1} vlserver ${COMPILE_PART2}
@ -569,13 +587,13 @@ jafs: libjafs
jafsadm: libjafsadm
finale: project cmd comerr afsd butc tbutc @ENABLE_KERNEL_MODULE@ libuafs audit kauth log package \
ptserver scout bu_utils ubik uss bozo vfsck volser tvolser \
ptserver scout bu_utils ubik uss bozo vfsck volser tvolser tsalvaged \
venus update xstat afsmonitor dauth rxdebug libafsrpc \
libafsauthent shlibafsrpc shlibafsauthent libadmin login man-pages
${COMPILE_PART1} finale ${COMPILE_PART2}
finale_nolibafs: project cmd comerr afsd butc tbutc libuafs audit kauth log package \
ptserver scout bu_utils ubik uss bozo vfsck volser tvolser \
ptserver scout bu_utils ubik uss bozo vfsck volser tvolser tsalvaged \
venus update xstat afsmonitor dauth rxdebug libafsrpc \
libafsauthent shlibafsrpc shlibafsauthent libadmin login man-pages
${COMPILE_PART1} finale ${COMPILE_PART2}
@ -633,6 +651,7 @@ clean2:
-${COMPILE_PART1} tviced ${COMPILE_CLEAN}
-${COMPILE_PART1} volser ${COMPILE_CLEAN}
-${COMPILE_PART1} tvolser ${COMPILE_CLEAN}
-${COMPILE_PART1} tsalvaged ${COMPILE_CLEAN}
-${COMPILE_PART1} venus ${COMPILE_CLEAN}
-${COMPILE_PART1} venus/test ${COMPILE_CLEAN}
-${COMPILE_PART1} afsd ${COMPILE_CLEAN}
@ -791,6 +810,7 @@ distclean: clean
src/tests/Makefile \
src/tests/run-tests \
src/tests/OpenAFS/Dirpath.pm \
src/tsalvaged/Makefile \
src/tsm41/Makefile \
src/tviced/Makefile \
src/tvolser/Makefile \

View File

@ -33,6 +33,8 @@ AC_ARG_ENABLE( fast-restart,
[ --enable-fast-restart enable fast startup of file server without salvaging],, enable_fast_restart="no")
AC_ARG_ENABLE( bitmap-later,
[ --enable-bitmap-later enable fast startup of file server by not reading bitmap till needed],, enable_bitmap_later="no")
AC_ARG_ENABLE( demand-attach-fs,
[ --enable-demand-attach-fs enable Demand Attach Fileserver (please see documentation)],, enable_demand_attach_fs="no")
AC_ARG_ENABLE( full-vos-listvol-switch,
[ --disable-full-vos-listvol-switch disable vos full listvol switch for formatted output],, enable_full_vos_listvol_switch="yes")
AC_ARG_WITH(dux-kernel-headers,
@ -948,6 +950,20 @@ if test "$enable_bitmap_later" = "yes"; then
AC_DEFINE(BITMAP_LATER, 1, [define if you want to salvager to check bitmasks later])
fi
if test "$enable_demand_attach_fs" = "yes"; then
AC_DEFINE(DEMAND_ATTACH_ENABLE, 1, [define if you want the demand attach fileserver])
DEMAND_ATTACH="yes"
else
DEMAND_ATTACH="no"
fi
AC_SUBST(DEMAND_ATTACH)
if test "$enable_fast_restart" = "yes" &&
test "$enable_demand_attach_fs" = "yes" ; then
AC_MSG_ERROR([The Demand Attach and Fast Restart extensions are mutually exclusive. Demand Attach fileservers automatically salvage volumes in the background, thereby making Fast Restart pointless.])
exit 1
fi
if test "$enable_full_vos_listvol_switch" = "yes"; then
AC_DEFINE(FULL_LISTVOL_SWITCH, 1, [define if you want to want listvol switch])
fi

View File

@ -106,6 +106,7 @@ src/tbutc/Makefile \
src/tests/Makefile \
src/tests/run-tests \
src/tests/OpenAFS/Dirpath.pm \
src/tsalvaged/Makefile \
src/tsm41/Makefile \
src/tviced/Makefile \
src/tvolser/Makefile \

View File

@ -96,7 +96,7 @@ test:
cd test; $(MAKE)
clean:
$(RM) -f *.o *.a copyauth setkey auth.h cellconfig.h acfg_errors.c ktc_errors.c core\
$(RM) -f *.o *.a copyauth setkey auth.h cellconfig.h acfg_errors.c ktc_errors.c core \
AFS_component_version_number.c
include ../config/Makefile.version

View File

@ -52,10 +52,12 @@ static DoStat();
#include "bosint.h"
#define MRAFS_OFFSET 9
#define ADDPARMOFFSET 26
/* command offsets for bos salvage command */
#define MRAFS_OFFSET 10
#define ADDPARMOFFSET 27
static struct SalvageParms {
/* MR-AFS salvage parameters */
struct MRAFSSalvageParms {
afs_int32 Optdebug;
afs_int32 Optnowrite;
afs_int32 Optforce;
@ -74,7 +76,7 @@ static struct SalvageParms {
afs_int32 OptLogLevel;
afs_int32 OptRxDebug;
afs_uint32 OptResidencies;
} mrafsParm;
};
/* dummy routine for the audit work. It should do nothing since audits */
/* occur at the server level and bos is not a server. */
@ -1224,17 +1226,11 @@ StopServer(as)
#define PARMBUFFERSSIZE 32
static
DoSalvage(aconn, aparm1, aparm2, aoutName, showlog, parallel, atmpDir,
orphans)
struct rx_connection *aconn;
char *aoutName;
char *aparm1;
char *aparm2;
afs_int32 showlog;
char *parallel;
char *atmpDir;
char *orphans;
static afs_int32
DoSalvage(struct rx_connection * aconn, char * aparm1, char * aparm2,
char * aoutName, afs_int32 showlog, char * parallel,
char * atmpDir, char * orphans, int dafs,
struct MRAFSSalvageParms * mrafsParm)
{
register afs_int32 code;
char *parms[6];
@ -1285,19 +1281,43 @@ DoSalvage(aconn, aparm1, aparm2, aoutName, showlog, parallel, atmpDir,
parms[code] = "";
if (!aparm2)
aparm2 = "";
/* MUST pass canonical (wire-format) salvager path to bosserver */
strncpy(tbuffer, AFSDIR_CANONICAL_SERVER_SALVAGER_FILEPATH, BOZO_BSSIZE);
if (*aparm2 != 0) {
if ((strlen(tbuffer) + 1 + strlen(partName) + 1 + strlen(aparm2) +
1) > BOZO_BSSIZE) {
printf("bos: command line too big\n");
return (E2BIG);
/* single volume salvage */
if (dafs) {
/* for DAFS, we call the salvagserver binary with special options.
* in this mode, it simply uses SALVSYNC to tell the currently
* running salvageserver to offline and salvage the volume in question */
strncpy(tbuffer, AFSDIR_CANONICAL_SERVER_SALSRV_FILEPATH, BOZO_BSSIZE);
if ((strlen(tbuffer) + 9 + strlen(partName) + 1 + strlen(aparm2) +
1) > BOZO_BSSIZE) {
printf("bos: command line too big\n");
return (E2BIG);
}
strcat(tbuffer, " -client ");
strcat(tbuffer, partName);
strcat(tbuffer, " ");
strcat(tbuffer, aparm2);
} else {
strncpy(tbuffer, AFSDIR_CANONICAL_SERVER_SALVAGER_FILEPATH, BOZO_BSSIZE);
if ((strlen(tbuffer) + 1 + strlen(partName) + 1 + strlen(aparm2) +
1) > BOZO_BSSIZE) {
printf("bos: command line too big\n");
return (E2BIG);
}
strcat(tbuffer, " ");
strcat(tbuffer, partName);
strcat(tbuffer, " ");
strcat(tbuffer, aparm2);
}
strcat(tbuffer, " ");
strcat(tbuffer, partName);
strcat(tbuffer, " ");
strcat(tbuffer, aparm2);
} else {
/* partition salvage */
strncpy(tbuffer, AFSDIR_CANONICAL_SERVER_SALVAGER_FILEPATH, BOZO_BSSIZE);
if ((strlen(tbuffer) + 4 + strlen(partName) + 1) > BOZO_BSSIZE) {
printf("bos: command line too big\n");
return (E2BIG);
@ -1306,75 +1326,82 @@ DoSalvage(aconn, aparm1, aparm2, aoutName, showlog, parallel, atmpDir,
strcat(tbuffer, partName);
}
/* add the parallel option if given */
if (parallel != NULL) {
if ((strlen(tbuffer) + 11 + strlen(parallel) + 1) > BOZO_BSSIZE) {
printf("bos: command line too big\n");
return (E2BIG);
/* For DAFS, specifying a single volume does not result in a standard
* salvager call. Instead, it simply results in a SALVSYNC call to the
* online salvager daemon. This interface does not give us the same rich
* set of call flags. Thus, we skip these steps for DAFS single-volume
* calls */
if (!dafs || (*aparm2 == 0)) {
/* add the parallel option if given */
if (parallel != NULL) {
if ((strlen(tbuffer) + 11 + strlen(parallel) + 1) > BOZO_BSSIZE) {
printf("bos: command line too big\n");
return (E2BIG);
}
strcat(tbuffer, " -parallel ");
strcat(tbuffer, parallel);
}
strcat(tbuffer, " -parallel ");
strcat(tbuffer, parallel);
}
/* add the tmpdir option if given */
if (atmpDir != NULL) {
if ((strlen(tbuffer) + 9 + strlen(atmpDir) + 1) > BOZO_BSSIZE) {
printf("bos: command line too big\n");
return (E2BIG);
/* add the tmpdir option if given */
if (atmpDir != NULL) {
if ((strlen(tbuffer) + 9 + strlen(atmpDir) + 1) > BOZO_BSSIZE) {
printf("bos: command line too big\n");
return (E2BIG);
}
strcat(tbuffer, " -tmpdir ");
strcat(tbuffer, atmpDir);
}
strcat(tbuffer, " -tmpdir ");
strcat(tbuffer, atmpDir);
}
/* add the orphans option if given */
if (orphans != NULL) {
if ((strlen(tbuffer) + 10 + strlen(orphans) + 1) > BOZO_BSSIZE) {
printf("bos: command line too big\n");
return (E2BIG);
/* add the orphans option if given */
if (orphans != NULL) {
if ((strlen(tbuffer) + 10 + strlen(orphans) + 1) > BOZO_BSSIZE) {
printf("bos: command line too big\n");
return (E2BIG);
}
strcat(tbuffer, " -orphans ");
strcat(tbuffer, orphans);
}
strcat(tbuffer, " -orphans ");
strcat(tbuffer, orphans);
}
if (mrafsParm.Optdebug)
strcat(tbuffer, " -debug");
if (mrafsParm.Optnowrite)
strcat(tbuffer, " -nowrite");
if (mrafsParm.Optforce)
strcat(tbuffer, " -force");
if (mrafsParm.Optoktozap)
strcat(tbuffer, " -oktozap");
if (mrafsParm.Optrootfiles)
strcat(tbuffer, " -rootfiles");
if (mrafsParm.Optsalvagedirs)
strcat(tbuffer, " -salvagedirs");
if (mrafsParm.Optblockreads)
strcat(tbuffer, " -blockreads");
if (mrafsParm.OptListResidencies)
strcat(tbuffer, " -ListResidencies");
if (mrafsParm.OptSalvageRemote)
strcat(tbuffer, " -SalvageRemote");
if (mrafsParm.OptSalvageArchival)
strcat(tbuffer, " -SalvageArchival");
if (mrafsParm.OptIgnoreCheck)
strcat(tbuffer, " -IgnoreCheck");
if (mrafsParm.OptForceOnLine)
strcat(tbuffer, " -ForceOnLine");
if (mrafsParm.OptUseRootDirACL)
strcat(tbuffer, " -UseRootDirACL");
if (mrafsParm.OptTraceBadLinkCounts)
strcat(tbuffer, " -TraceBadLinkCounts");
if (mrafsParm.OptDontAskFS)
strcat(tbuffer, " -DontAskFS");
if (mrafsParm.OptLogLevel) {
sprintf(pbuffer, " -LogLevel %ld", mrafsParm.OptLogLevel);
strcat(tbuffer, pbuffer);
}
if (mrafsParm.OptRxDebug)
strcat(tbuffer, " -rxdebug");
if (mrafsParm.OptResidencies) {
sprintf(pbuffer, " -Residencies %lu", mrafsParm.OptResidencies);
strcat(tbuffer, pbuffer);
if (mrafsParm->Optdebug)
strcat(tbuffer, " -debug");
if (mrafsParm->Optnowrite)
strcat(tbuffer, " -nowrite");
if (mrafsParm->Optforce)
strcat(tbuffer, " -force");
if (mrafsParm->Optoktozap)
strcat(tbuffer, " -oktozap");
if (mrafsParm->Optrootfiles)
strcat(tbuffer, " -rootfiles");
if (mrafsParm->Optsalvagedirs)
strcat(tbuffer, " -salvagedirs");
if (mrafsParm->Optblockreads)
strcat(tbuffer, " -blockreads");
if (mrafsParm->OptListResidencies)
strcat(tbuffer, " -ListResidencies");
if (mrafsParm->OptSalvageRemote)
strcat(tbuffer, " -SalvageRemote");
if (mrafsParm->OptSalvageArchival)
strcat(tbuffer, " -SalvageArchival");
if (mrafsParm->OptIgnoreCheck)
strcat(tbuffer, " -IgnoreCheck");
if (mrafsParm->OptForceOnLine)
strcat(tbuffer, " -ForceOnLine");
if (mrafsParm->OptUseRootDirACL)
strcat(tbuffer, " -UseRootDirACL");
if (mrafsParm->OptTraceBadLinkCounts)
strcat(tbuffer, " -TraceBadLinkCounts");
if (mrafsParm->OptDontAskFS)
strcat(tbuffer, " -DontAskFS");
if (mrafsParm->OptLogLevel) {
sprintf(pbuffer, " -LogLevel %ld", mrafsParm->OptLogLevel);
strcat(tbuffer, pbuffer);
}
if (mrafsParm->OptRxDebug)
strcat(tbuffer, " -rxdebug");
if (mrafsParm->OptResidencies) {
sprintf(pbuffer, " -Residencies %lu", mrafsParm->OptResidencies);
strcat(tbuffer, pbuffer);
}
}
parms[0] = tbuffer;
@ -1481,22 +1508,36 @@ SalvageCmd(as)
char tname[BOZO_BSSIZE];
afs_int32 newID;
extern struct ubik_client *cstruct;
afs_int32 curGoal, showlog = 0, mrafs = 0;
afs_int32 curGoal, showlog = 0, dafs = 0, mrafs = 0;
char *parallel;
char *tmpDir;
char *orphans;
char *tp;
char * serviceName;
struct MRAFSSalvageParms mrafsParm;
memset(&mrafsParm, 0, sizeof(mrafsParm));
/* parm 0 is machine name, 1 is partition, 2 is volume, 3 is -all flag */
tconn = GetConn(as, 0);
/* Find out whether fileserver is running MR-AFS (has a scanner instance) */
/* XXX this should really be done some other way, potentially by RPC */
tp = &tname[0];
if (code = BOZO_GetInstanceParm(tconn, "fs", 3, &tp) == 0)
mrafs = 1;
/* find out whether fileserver is running demand attach fs */
if (code = BOZO_GetInstanceParm(tconn, "dafs", 0, &tp) == 0) {
dafs = 1;
serviceName = "dafs";
/* Find out whether fileserver is running MR-AFS (has a scanner instance) */
/* XXX this should really be done some other way, potentially by RPC */
if (code = BOZO_GetInstanceParm(tconn, serviceName, 4, &tp) == 0)
mrafs = 1;
} else {
serviceName = "fs";
/* Find out whether fileserver is running MR-AFS (has a scanner instance) */
/* XXX this should really be done some other way, potentially by RPC */
if (code = BOZO_GetInstanceParm(tconn, serviceName, 3, &tp) == 0)
mrafs = 1;
}
/* we can do a volume, a partition or the whole thing, but not mixtures
* thereof */
@ -1542,6 +1583,14 @@ SalvageCmd(as)
orphans = as->parms[8].items->data;
}
if (dafs) {
if (!as->parms[9].items) { /* -forceDAFS flag */
printf("This is a demand attach fileserver. Are you sure you want to proceed with a manual salvage?\n");
printf("must specify -forceDAFS flag in order to proceed.\n");
return EINVAL;
}
}
if (mrafs) {
if (as->parms[MRAFS_OFFSET].items)
mrafsParm.Optdebug = 1;
@ -1597,7 +1646,7 @@ SalvageCmd(as)
} else {
int stop = 0;
for (i = 9; i < ADDPARMOFFSET; i++) {
for (i = MRAFS_OFFSET; i < ADDPARMOFFSET; i++) {
if (as->parms[i].items) {
printf(" %s only possible for MR-AFS fileserver.\n",
as->parms[i].name);
@ -1610,12 +1659,12 @@ SalvageCmd(as)
if (as->parms[4].items) {
/* salvage whole enchilada */
curGoal = GetServerGoal(tconn, "fs");
curGoal = GetServerGoal(tconn, serviceName);
if (curGoal == BSTAT_NORMAL) {
printf("bos: shutting down fs.\n");
code = BOZO_SetTStatus(tconn, "fs", BSTAT_SHUTDOWN);
printf("bos: shutting down '%s'.\n", serviceName);
code = BOZO_SetTStatus(tconn, serviceName, BSTAT_SHUTDOWN);
if (code) {
printf("bos: failed to stop 'fs' (%s)\n", em(code));
printf("bos: failed to stop '%s' (%s)\n", serviceName, em(code));
return code;
}
code = BOZO_WaitAll(tconn); /* wait for shutdown to complete */
@ -1626,12 +1675,12 @@ SalvageCmd(as)
/* now do the salvage operation */
printf("Starting salvage.\n");
rc = DoSalvage(tconn, NULL, NULL, outName, showlog, parallel, tmpDir,
orphans);
orphans, dafs, &mrafsParm);
if (curGoal == BSTAT_NORMAL) {
printf("bos: restarting fs.\n");
code = BOZO_SetTStatus(tconn, "fs", BSTAT_NORMAL);
printf("bos: restarting %s.\n", serviceName);
code = BOZO_SetTStatus(tconn, serviceName, BSTAT_NORMAL);
if (code) {
printf("bos: failed to restart 'fs' (%s)\n", em(code));
printf("bos: failed to restart '%s' (%s)\n", serviceName, em(code));
return code;
}
}
@ -1651,13 +1700,13 @@ SalvageCmd(as)
as->parms[1].items->data);
return -1;
}
curGoal = GetServerGoal(tconn, "fs");
curGoal = GetServerGoal(tconn, serviceName);
/* salvage a whole partition (specified by parms[1]) */
if (curGoal == BSTAT_NORMAL) {
printf("bos: shutting down fs.\n");
code = BOZO_SetTStatus(tconn, "fs", BSTAT_SHUTDOWN);
printf("bos: shutting down '%s'.\n", serviceName);
code = BOZO_SetTStatus(tconn, serviceName, BSTAT_SHUTDOWN);
if (code) {
printf("bos: can't stop 'fs' (%s)\n", em(code));
printf("bos: can't stop '%s' (%s)\n", serviceName, em(code));
return code;
}
code = BOZO_WaitAll(tconn); /* wait for shutdown to complete */
@ -1668,12 +1717,12 @@ SalvageCmd(as)
/* now do the salvage operation */
printf("Starting salvage.\n");
rc = DoSalvage(tconn, as->parms[1].items->data, NULL, outName,
showlog, parallel, tmpDir, orphans);
showlog, parallel, tmpDir, orphans, dafs, &mrafsParm);
if (curGoal == BSTAT_NORMAL) {
printf("bos: restarting fs.\n");
code = BOZO_SetTStatus(tconn, "fs", BSTAT_NORMAL);
printf("bos: restarting '%s'.\n", serviceName);
code = BOZO_SetTStatus(tconn, serviceName, BSTAT_NORMAL);
if (code) {
printf("bos: failed to restart 'fs' (%s)\n", em(code));
printf("bos: failed to restart '%s' (%s)\n", serviceName, em(code));
return code;
}
}
@ -1723,7 +1772,7 @@ SalvageCmd(as)
}
printf("Starting salvage.\n");
rc = DoSalvage(tconn, as->parms[1].items->data, tname, outName,
showlog, parallel, tmpDir, orphans);
showlog, parallel, tmpDir, orphans, dafs, &mrafsParm);
if (rc)
return rc;
}
@ -2153,6 +2202,8 @@ main(argc, argv)
"directory to place tmp files");
cmd_AddParm(ts, "-orphans", CMD_SINGLE, CMD_OPTIONAL,
"ignore | remove | attach");
cmd_AddParm(ts, "-forceDAFS", CMD_FLAG, CMD_OPTIONAL,
"(DAFS) force salvage of demand attach fileserver");
cmd_AddParm(ts, "-debug", CMD_FLAG, CMD_OPTIONAL,
"(MR-AFS) Run in Debugging mode");
cmd_AddParm(ts, "-nowrite", CMD_FLAG, CMD_OPTIONAL,

View File

@ -51,7 +51,7 @@ RCSID
#define BOZO_LWP_STACKSIZE 16000
extern int BOZO_ExecuteRequest();
extern int RXSTATS_ExecuteRequest();
extern struct bnode_ops fsbnode_ops, ezbnode_ops, cronbnode_ops;
extern struct bnode_ops fsbnode_ops, dafsbnode_ops, ezbnode_ops, cronbnode_ops;
void bozo_Log();
@ -895,6 +895,7 @@ main(int argc, char **argv, char **envp)
}
bnode_Register("fs", &fsbnode_ops, 3);
bnode_Register("dafs", &dafsbnode_ops, 4);
bnode_Register("simple", &ezbnode_ops, 1);
bnode_Register("cron", &cronbnode_ops, 2);

View File

@ -41,13 +41,6 @@ RCSID
#include <afs/afsutil.h>
#include "bnode.h"
static int fs_timeout(), fs_getstat(), fs_setstat(), fs_delete();
static int fs_procexit(), fs_getstring(), fs_getparm(), fs_restartp();
static int fs_hascore();
struct bnode *fs_create();
static SetNeedsClock();
static NudgeProcs();
static int emergency = 0;
@ -76,6 +69,77 @@ static int emergency = 0;
The needsSalvage flag is cleared when the salvager exits.
*/
struct fsbnode {
struct bnode b;
afs_int32 timeSDStarted; /* time shutdown operation started */
char *filecmd; /* command to start primary file server */
char *volcmd; /* command to start secondary vol server */
char *salsrvcmd; /* command to start salvageserver (demand attach fs) */
char *salcmd; /* command to start salvager */
char *scancmd; /* command to start scanner (MR-AFS) */
struct bnode_proc *fileProc; /* process for file server */
struct bnode_proc *volProc; /* process for vol server */
struct bnode_proc *salsrvProc; /* process for salvageserver (demand attach fs) */
struct bnode_proc *salProc; /* process for salvager */
struct bnode_proc *scanProc; /* process for scanner (MR-AFS) */
afs_int32 lastFileStart; /* last start for file */
afs_int32 lastVolStart; /* last start for vol */
afs_int32 lastSalsrvStart; /* last start for salvageserver (demand attach fs) */
afs_int32 lastScanStart; /* last start for scanner (MR-AFS) */
char fileRunning; /* file process is running */
char volRunning; /* volser is running */
char salsrvRunning; /* salvageserver is running (demand attach fs) */
char salRunning; /* salvager is running */
char scanRunning; /* scanner is running (MR_AFS) */
char fileSDW; /* file shutdown wait */
char volSDW; /* vol shutdown wait */
char salsrvSDW; /* salvageserver shutdown wait (demand attach fs) */
char salSDW; /* waiting for the salvager to shutdown */
char scanSDW; /* scanner shutdown wait (MR_AFS) */
char fileKillSent; /* kill signal has been sent */
char volKillSent;
char salsrvKillSent; /* kill signal has been sent (demand attach fs) */
char salKillSent;
char scanKillSent; /* kill signal has been sent (MR_AFS) */
char needsSalvage; /* salvage before running */
char needsClock; /* do we need clock ticks */
};
struct bnode * fs_create(char *ainstance, char *afilecmd, char *avolcmd,
char *asalcmd, char *ascancmd);
struct bnode * dafs_create(char *ainstance, char *afilecmd, char *avolcmd,
char * asalsrvcmd, char *asalcmd, char *ascancmd);
static int fs_hascore(register struct ezbnode *abnode);
static int fs_restartp(register struct fsbnode *abnode);
static int SetSalFlag(register struct fsbnode *abnode, register int aflag);
static int RestoreSalFlag(register struct fsbnode *abnode);
static int fs_delete(struct fsbnode *abnode);
static int fs_timeout(struct fsbnode *abnode);
static int fs_getstat(struct fsbnode *abnode, afs_int32 * astatus);
static int fs_setstat(register struct fsbnode *abnode, afs_int32 astatus);
static int fs_procexit(struct fsbnode *abnode, struct bnode_proc *aproc);
static int fs_getstring(struct fsbnode *abnode, char *abuffer, afs_int32 alen);
static int fs_getparm(struct fsbnode *abnode, afs_int32 aindex,
char *abuffer, afs_int32 alen);
static int dafs_getparm(struct fsbnode *abnode, afs_int32 aindex,
char *abuffer, afs_int32 alen);
#ifdef AFS_NT40_ENV
static void AppendExecutableExtension(char *cmd)
#else
#define AppendExecutableExtension(x)
#endif
static void SetNeedsClock(register struct fsbnode *ab);
static int NudgeProcs(register struct fsbnode *abnode);
struct bnode_ops fsbnode_ops = {
fs_create,
fs_timeout,
@ -89,36 +153,21 @@ struct bnode_ops fsbnode_ops = {
fs_hascore,
};
struct fsbnode {
struct bnode b;
afs_int32 timeSDStarted; /* time shutdown operation started */
char *filecmd; /* command to start primary file server */
char *volcmd; /* command to start secondary vol server */
char *salcmd; /* command to start salvager */
char *scancmd; /* command to start scanner (MR-AFS) */
struct bnode_proc *fileProc; /* process for file server */
struct bnode_proc *volProc; /* process for vol server */
struct bnode_proc *salProc; /* process for salvager */
struct bnode_proc *scanProc; /* process for scanner (MR-AFS) */
afs_int32 lastFileStart; /* last start for file */
afs_int32 lastVolStart; /* last start for vol */
afs_int32 lastScanStart; /* last start for scanner (MR-AFS) */
char fileRunning; /* file process is running */
char volRunning; /* volser is running */
char salRunning; /* salvager is running */
char scanRunning; /* scanner is running (MR_AFS) */
char fileSDW; /* file shutdown wait */
char volSDW; /* vol shutdown wait */
char salSDW; /* waiting for the salvager to shutdown */
char scanSDW; /* scanner shutdown wait (MR_AFS) */
char fileKillSent; /* kill signal has been sent */
char volKillSent;
char salKillSent;
char scanKillSent; /* kill signal has been sent (MR_AFS) */
char needsSalvage; /* salvage before running */
char needsClock; /* do we need clock ticks */
/* demand attach fs bnode ops */
struct bnode_ops dafsbnode_ops = {
dafs_create,
fs_timeout,
fs_getstat,
fs_setstat,
fs_delete,
fs_procexit,
fs_getstring,
dafs_getparm,
fs_restartp,
fs_hascore,
};
/* Function to tell whether this bnode has a core file or not. You might
* think that this could be in bnode.c, and decide what core files to check
* for based on the bnode's coreName property, but that doesn't work because
@ -140,6 +189,11 @@ fs_hascore(register struct ezbnode *abnode)
if (access(tbuffer, 0) == 0)
return 1;
/* see if salvageserver left a core file */
bnode_CoreName(abnode, "salsrv", tbuffer);
if (access(tbuffer, 0) == 0)
return 1;
/* see if salvager left a core file */
bnode_CoreName(abnode, "salv", tbuffer);
if (access(tbuffer, 0) == 0)
@ -198,6 +252,25 @@ fs_restartp(register struct fsbnode *abnode)
if (code)
return code;
if (abnode->salsrvcmd) { /* only in demand attach fs */
/* now do same for salsrvcmd (demand attach fs) */
code = bnode_ParseLine(abnode->salsrvcmd, &tt);
if (code)
return 0;
if (!tt)
return 0;
code = stat(tt->key, &tstat);
if (code) {
bnode_FreeTokens(tt);
return 0;
}
if (tstat.st_ctime > abnode->lastScanStart)
code = 1;
else
code = 0;
bnode_FreeTokens(tt);
}
if (abnode->scancmd) { /* Only in MR-AFS */
/* now do same for scancmd (MR-AFS) */
code = bnode_ParseLine(abnode->scancmd, &tt);
@ -228,14 +301,17 @@ SetSalFlag(register struct fsbnode *abnode, register int aflag)
char tbuffer[AFSDIR_PATH_MAX];
int fd;
abnode->needsSalvage = aflag;
strcompose(tbuffer, AFSDIR_PATH_MAX, AFSDIR_SERVER_LOCAL_DIRPATH, "/",
SALFILE, abnode->b.name, NULL);
if (aflag) {
fd = open(tbuffer, O_CREAT | O_TRUNC | O_RDWR, 0666);
close(fd);
} else {
unlink(tbuffer);
/* don't use the salvage flag for demand attach fs */
if (abnode->salsrvcmd == NULL) {
abnode->needsSalvage = aflag;
strcompose(tbuffer, AFSDIR_PATH_MAX, AFSDIR_SERVER_LOCAL_DIRPATH, "/",
SALFILE, abnode->b.name, NULL);
if (aflag) {
fd = open(tbuffer, O_CREAT | O_TRUNC | O_RDWR, 0666);
close(fd);
} else {
unlink(tbuffer);
}
}
return 0;
}
@ -246,13 +322,18 @@ RestoreSalFlag(register struct fsbnode *abnode)
{
char tbuffer[AFSDIR_PATH_MAX];
strcompose(tbuffer, AFSDIR_PATH_MAX, AFSDIR_SERVER_LOCAL_DIRPATH, "/",
SALFILE, abnode->b.name, NULL);
if (access(tbuffer, 0) == 0) {
/* file exists, so need to salvage */
abnode->needsSalvage = 1;
} else {
/* never set needs salvage flag for demand attach fs */
if (abnode->salsrvcmd != NULL) {
abnode->needsSalvage = 0;
} else {
strcompose(tbuffer, AFSDIR_PATH_MAX, AFSDIR_SERVER_LOCAL_DIRPATH, "/",
SALFILE, abnode->b.name, NULL);
if (access(tbuffer, 0) == 0) {
/* file exists, so need to salvage */
abnode->needsSalvage = 1;
} else {
abnode->needsSalvage = 0;
}
}
return 0;
}
@ -272,6 +353,8 @@ fs_delete(struct fsbnode *abnode)
free(abnode->filecmd);
free(abnode->volcmd);
free(abnode->salcmd);
if (abnode->salsrvcmd)
free(abnode->salsrvcmd);
if (abnode->scancmd)
free(abnode->scancmd);
free(abnode);
@ -304,95 +387,235 @@ fs_create(char *ainstance, char *afilecmd, char *avolcmd, char *asalcmd,
char *fileCmdpath, *volCmdpath, *salCmdpath, *scanCmdpath;
int bailout = 0;
fileCmdpath = volCmdpath = salCmdpath = NULL;
te = fileCmdpath = volCmdpath = salCmdpath = scanCmdpath = NULL;
/* construct local paths from canonical (wire-format) paths */
if (ConstructLocalBinPath(afilecmd, &fileCmdpath)) {
bozo_Log("BNODE: command path invalid '%s'\n", afilecmd);
bailout = 1;
goto done;
}
if (ConstructLocalBinPath(avolcmd, &volCmdpath)) {
bozo_Log("BNODE: command path invalid '%s'\n", avolcmd);
bailout = 1;
goto done;
}
if (ConstructLocalBinPath(asalcmd, &salCmdpath)) {
bozo_Log("BNODE: command path invalid '%s'\n", asalcmd);
bailout = 1;
goto done;
}
if (ascancmd && strlen(ascancmd)) {
if (ConstructLocalBinPath(ascancmd, &scanCmdpath)) {
bozo_Log("BNODE: command path invalid '%s'\n", ascancmd);
bailout = 1;
goto done;
}
}
if (!bailout) {
sscanf(fileCmdpath, "%s", cmdname);
#ifdef AFS_NT40_ENV
AppendExecutableExtension(cmdname);
#endif
if (stat(cmdname, &tstat)) {
bozo_Log("BNODE: file server binary '%s' not found\n", cmdname);
bailout = 1;
goto done;
}
sscanf(volCmdpath, "%s", cmdname);
#ifdef AFS_NT40_ENV
AppendExecutableExtension(cmdname);
#endif
if (stat(cmdname, &tstat)) {
bozo_Log("BNODE: volume server binary '%s' not found\n", cmdname);
bailout = 1;
goto done;
}
sscanf(salCmdpath, "%s", cmdname);
#ifdef AFS_NT40_ENV
AppendExecutableExtension(cmdname);
#endif
if (stat(cmdname, &tstat)) {
bozo_Log("BNODE: salvager binary '%s' not found\n", cmdname);
bailout = 1;
goto done;
}
if (ascancmd && strlen(ascancmd)) {
sscanf(scanCmdpath, "%s", cmdname);
#ifdef AFS_NT40_ENV
AppendExecutableExtension(cmdname);
#endif
if (stat(cmdname, &tstat)) {
bozo_Log("BNODE: scanner binary '%s' not found\n", cmdname);
bailout = 1;
goto done;
}
}
}
if (bailout) {
free(fileCmdpath);
free(volCmdpath);
free(salCmdpath);
return NULL;
}
te = (struct fsbnode *)malloc(sizeof(struct fsbnode));
if (te == NULL) {
bailout = 1;
goto done;
}
memset(te, 0, sizeof(struct fsbnode));
te->filecmd = fileCmdpath;
te->volcmd = volCmdpath;
te->salsrvcmd = NULL;
te->salcmd = salCmdpath;
if (ascancmd && strlen(ascancmd))
te->scancmd = scanCmdpath;
else
te->scancmd = NULL;
if (bnode_InitBnode(te, &fsbnode_ops, ainstance) != 0) {
free(te);
free(fileCmdpath);
free(volCmdpath);
free(salCmdpath);
return NULL;
bailout = 1;
goto done;
}
bnode_SetTimeout(te, POLLTIME); /* ask for timeout activations every 10 seconds */
RestoreSalFlag(te); /* restore needsSalvage flag based on file's existence */
SetNeedsClock(te); /* compute needsClock field */
done:
if (bailout) {
if (te)
free(te);
if (fileCmdpath)
free(fileCmdpath);
if (volCmdpath)
free(volCmdpath);
if (salCmdpath)
free(salCmdpath);
if (scanCmdpath)
free(scanCmdpath);
return NULL;
}
return (struct bnode *)te;
}
/* create a demand attach fs bnode */
struct bnode *
dafs_create(char *ainstance, char *afilecmd, char *avolcmd,
char * asalsrvcmd, char *asalcmd, char *ascancmd)
{
struct stat tstat;
register struct fsbnode *te;
char cmdname[AFSDIR_PATH_MAX];
char *fileCmdpath, *volCmdpath, *salsrvCmdpath, *salCmdpath, *scanCmdpath;
int bailout = 0;
te = fileCmdpath = volCmdpath = salsrvCmdpath = salCmdpath = scanCmdpath = NULL;
/* construct local paths from canonical (wire-format) paths */
if (ConstructLocalBinPath(afilecmd, &fileCmdpath)) {
bozo_Log("BNODE: command path invalid '%s'\n", afilecmd);
bailout = 1;
goto done;
}
if (ConstructLocalBinPath(avolcmd, &volCmdpath)) {
bozo_Log("BNODE: command path invalid '%s'\n", avolcmd);
bailout = 1;
goto done;
}
if (ConstructLocalBinPath(asalsrvcmd, &salsrvCmdpath)) {
bozo_Log("BNODE: command path invalid '%s'\n", asalsrvcmd);
bailout = 1;
goto done;
}
if (ConstructLocalBinPath(asalcmd, &salCmdpath)) {
bozo_Log("BNODE: command path invalid '%s'\n", asalcmd);
bailout = 1;
goto done;
}
if (ascancmd && strlen(ascancmd)) {
if (ConstructLocalBinPath(ascancmd, &scanCmdpath)) {
bozo_Log("BNODE: command path invalid '%s'\n", ascancmd);
bailout = 1;
goto done;
}
}
if (!bailout) {
sscanf(fileCmdpath, "%s", cmdname);
AppendExecutableExtension(cmdname);
if (stat(cmdname, &tstat)) {
bozo_Log("BNODE: file server binary '%s' not found\n", cmdname);
bailout = 1;
goto done;
}
sscanf(volCmdpath, "%s", cmdname);
AppendExecutableExtension(cmdname);
if (stat(cmdname, &tstat)) {
bozo_Log("BNODE: volume server binary '%s' not found\n", cmdname);
bailout = 1;
goto done;
}
sscanf(salsrvCmdpath, "%s", cmdname);
AppendExecutableExtension(cmdname);
if (stat(cmdname, &tstat)) {
bozo_Log("BNODE: salvageserver binary '%s' not found\n", cmdname);
bailout = 1;
goto done;
}
sscanf(salCmdpath, "%s", cmdname);
AppendExecutableExtension(cmdname);
if (stat(cmdname, &tstat)) {
bozo_Log("BNODE: salvager binary '%s' not found\n", cmdname);
bailout = 1;
goto done;
}
if (ascancmd && strlen(ascancmd)) {
sscanf(scanCmdpath, "%s", cmdname);
AppendExecutableExtension(cmdname);
if (stat(cmdname, &tstat)) {
bozo_Log("BNODE: scanner binary '%s' not found\n", cmdname);
bailout = 1;
goto done;
}
}
}
te = (struct fsbnode *)malloc(sizeof(struct fsbnode));
if (te == NULL) {
bailout = 1;
goto done;
}
memset(te, 0, sizeof(struct fsbnode));
te->filecmd = fileCmdpath;
te->volcmd = volCmdpath;
te->salsrvcmd = salsrvCmdpath;
te->salcmd = salCmdpath;
if (ascancmd && strlen(ascancmd))
te->scancmd = scanCmdpath;
else
te->scancmd = NULL;
if (bnode_InitBnode(te, &dafsbnode_ops, ainstance) != 0) {
bailout = 1;
goto done;
}
bnode_SetTimeout(te, POLLTIME); /* ask for timeout activations every 10 seconds */
RestoreSalFlag(te); /* restore needsSalvage flag based on file's existence */
SetNeedsClock(te); /* compute needsClock field */
done:
if (bailout) {
if (te)
free(te);
if (fileCmdpath)
free(fileCmdpath);
if (volCmdpath)
free(volCmdpath);
if (salsrvCmdpath)
free(salsrvCmdpath);
if (salCmdpath)
free(salCmdpath);
if (scanCmdpath)
free(scanCmdpath);
return NULL;
}
return (struct bnode *)te;
}
@ -431,6 +654,15 @@ fs_timeout(struct fsbnode *abnode)
FSSDTIME);
}
}
if (abnode->salsrvSDW) {
if (!abnode->salsrvKillSent && now - abnode->timeSDStarted > SDTIME) {
bnode_StopProc(abnode->salsrvProc, SIGKILL);
abnode->salsrvKillSent = 1;
bozo_Log
("bos shutdown: salvageserver failed to shutdown within %d seconds\n",
SDTIME);
}
}
if (abnode->scanSDW) {
if (!abnode->scanKillSent && now - abnode->timeSDStarted > SDTIME) {
bnode_StopProc(abnode->scanProc, SIGKILL);
@ -449,15 +681,17 @@ fs_getstat(struct fsbnode *abnode, afs_int32 * astatus)
{
register afs_int32 temp;
if (abnode->volSDW || abnode->fileSDW || abnode->salSDW
|| abnode->scanSDW)
|| abnode->scanSDW || abnode->salsrvSDW)
temp = BSTAT_SHUTTINGDOWN;
else if (abnode->salRunning)
temp = BSTAT_NORMAL;
else if (abnode->volRunning && abnode->fileRunning
&& (!abnode->scancmd || abnode->scanRunning))
&& (!abnode->scancmd || abnode->scanRunning)
&& (!abnode->salsrvcmd || abnode->salsrvRunning))
temp = BSTAT_NORMAL;
else if (!abnode->salRunning && !abnode->volRunning
&& !abnode->fileRunning && !abnode->scanRunning)
&& !abnode->fileRunning && !abnode->scanRunning
&& !abnode->salsrvRunning)
temp = BSTAT_SHUTDOWN;
else
temp = BSTAT_STARTINGUP;
@ -508,6 +742,11 @@ fs_procexit(struct fsbnode *abnode, struct bnode_proc *aproc)
abnode->scanRunning = 0;
abnode->scanSDW = 0;
abnode->scanKillSent = 0;
} else if (aproc == abnode->salsrvProc) {
abnode->salsrvProc = 0;
abnode->salsrvRunning = 0;
abnode->salsrvSDW = 0;
abnode->salsrvKillSent = 0;
}
/* now restart anyone who needs to restart */
@ -515,14 +754,15 @@ fs_procexit(struct fsbnode *abnode, struct bnode_proc *aproc)
}
/* make sure we're periodically checking the state if we need to */
static int
static void
SetNeedsClock(register struct fsbnode *ab)
{
if (ab->b.goal == 1 && ab->fileRunning && ab->volRunning
&& (!ab->scancmd || ab->scanRunning))
&& (!ab->scancmd || ab->scanRunning)
&& (!ab->salsrvcmd || ab->salsrvRunning))
ab->needsClock = 0; /* running normally */
else if (ab->b.goal == 0 && !ab->fileRunning && !ab->volRunning
&& !ab->salRunning && !ab->scanRunning)
&& !ab->salRunning && !ab->scanRunning && !ab->salsrvRunning)
ab->needsClock = 0; /* halted normally */
else
ab->needsClock = 1; /* other */
@ -562,6 +802,18 @@ NudgeProcs(register struct fsbnode *abnode)
abnode->volRunning = 1;
}
}
if (abnode->salsrvcmd) {
if (!abnode->salsrvRunning) {
abnode->lastSalsrvStart = FT_ApproxTime();
code =
bnode_NewProc(abnode, abnode->salsrvcmd, "salsrv",
&tp);
if (code == 0) {
abnode->salsrvProc = tp;
abnode->salsrvRunning = 1;
}
}
}
if (abnode->scancmd) {
if (!abnode->scanRunning) {
abnode->lastScanStart = FT_ApproxTime();
@ -576,7 +828,8 @@ NudgeProcs(register struct fsbnode *abnode)
}
} else { /* file is not running */
/* see how to start */
if (!abnode->needsSalvage) {
/* for demand attach fs, needsSalvage flag is ignored */
if (!abnode->needsSalvage || abnode->salsrvcmd) {
/* no crash apparent, just start up normally */
if (!abnode->fileRunning) {
abnode->lastFileStart = FT_ApproxTime();
@ -596,6 +849,16 @@ NudgeProcs(register struct fsbnode *abnode)
abnode->volRunning = 1;
}
}
if (abnode->salsrvcmd && !abnode->salsrvRunning) {
abnode->lastSalsrvStart = FT_ApproxTime();
code =
bnode_NewProc(abnode, abnode->salsrvcmd, "salsrv",
&tp);
if (code == 0) {
abnode->salsrvProc = tp;
abnode->salsrvRunning = 1;
}
}
if (abnode->scancmd && !abnode->scanRunning) {
abnode->lastScanStart = FT_ApproxTime();
code =
@ -656,6 +919,11 @@ NudgeProcs(register struct fsbnode *abnode)
abnode->volSDW = 1;
abnode->timeSDStarted = now;
}
if (abnode->salsrvRunning && !abnode->salsrvSDW) {
bnode_StopProc(abnode->salsrvProc, SIGTERM);
abnode->salsrvSDW = 1;
abnode->timeSDStarted = now;
}
if (abnode->scanRunning && !abnode->scanSDW) {
bnode_StopProc(abnode->scanProc, SIGTERM);
abnode->scanSDW = 1;
@ -724,3 +992,22 @@ fs_getparm(struct fsbnode *abnode, afs_int32 aindex, char *abuffer,
return BZDOM;
return 0;
}
static int
dafs_getparm(struct fsbnode *abnode, afs_int32 aindex, char *abuffer,
afs_int32 alen)
{
if (aindex == 0)
strcpy(abuffer, abnode->filecmd);
else if (aindex == 1)
strcpy(abuffer, abnode->volcmd);
else if (aindex == 2)
strcpy(abuffer, abnode->salsrvcmd);
else if (aindex == 3)
strcpy(abuffer, abnode->salcmd);
else if (aindex == 4 && abnode->scancmd)
strcpy(abuffer, abnode->scancmd);
else
return BZDOM;
return 0;
}

View File

@ -971,6 +971,18 @@ case $AFS_SYSNAME in
;;
esac
dnl pthreads fixes
case $AFS_SYSNAME in
dnl we'll go ahead and turn on XOPEN2K and ISO_C99
dnl if this causes problems, we should scale back to _XOPEN_SOURCE=500
*linux*)
MT_CFLAGS="${MT_CFLAGS} -D_XOPEN_SOURCE=600 -D_BSD_SOURCE"
;;
esac
dnl Disable the default for debugging/optimization if not enabled
if test "x$enable_debug_kernel" = "xno"; then
KERN_DBG=

View File

@ -25,8 +25,6 @@
#ifdef AFS_NAMEI_ENV
#define AFS_64BIT_IOPS_ENV 1
#endif
#define BITMAP_LATER 1
#define FAST_RESTART 1
#define AFS_HAVE_FLOCK_SYSID 1

View File

@ -26,8 +26,6 @@
#ifdef AFS_NAMEI_ENV
#define AFS_64BIT_IOPS_ENV 1
#endif
#define BITMAP_LATER 1
#define FAST_RESTART 1
#define AFS_HAVE_FLOCK_SYSID 1

View File

@ -27,8 +27,6 @@
#ifdef AFS_NAMEI_ENV
#define AFS_64BIT_IOPS_ENV 1
#endif
#define BITMAP_LATER 1
#define FAST_RESTART 1
#define AFS_HAVE_FLOCK_SYSID 1

View File

@ -56,8 +56,16 @@ typedef unsigned __int64 afs_uint64;
typedef long long afs_int64;
typedef unsigned long long afs_uint64;
#endif
#define ZeroInt64(a) (a) = 0
#define ZeroInt64(a) (a = 0)
#define AssignInt64(a, b) *(b) = (a)
#define IncInt64(a) (*(a))++
#define IncUInt64(a) (*(a))++
#define DecInt64(a) (*(a))--
#define DecUInt64(a) (*(a))--
#define GTInt64(a,b) ((a) > (b))
#define GEInt64(a,b) ((a) >= (b))
#define LEInt64(a,b) ((a) <= (b))
#define LTInt64(a,b) ((a) < (b))
#define AddInt64(a,b,c) *(c) = (afs_int64)(a) + (afs_int64)(b)
#define AddUInt64(a,b,c) *(c) = (afs_uint64)(a) + (afs_uint64)(b)
#define SubtractInt64(a,b,c) *(c) = (afs_int64)(a) - (afs_int64)(b)
@ -83,8 +91,16 @@ struct u_Int64 {
afs_uint32 low;
};
typedef struct u_Int64 afs_uint64;
#define ZeroInt64(a) (a).high = (a).low = 0
#define ZeroInt64(a) ((a).high = (a).low = 0)
#define AssignInt64(a, b) (b)->high = (a).high; (b)->low = (a).low
#define IncInt64(a) ((++((a)->low)) ? 0 : (a)->high++ )
#define IncUInt64(a) ((++((a)->low)) ? 0 : (a)->high++ )
#define DecInt64(a) (((a)->low)-- ? 0 : (a)->high-- )
#define DecUInt64(a) (((a)->low)-- ? 0 : (a)->high-- )
#define GTInt64(a,b) (((a).high > (b).high) || (((a).high == (b).high) && ((a).low > (b).low)))
#define GEInt64(a,b) (((a).high > (b).high) || (((a).high == (b).high) && ((a).low >= (b).low)))
#define LEInt64(a,b) (((a).high < (b).high) || (((a).high == (b).high) && ((a).low <= (b).low)))
#define LTInt64(a,b) (((a).high < (b).high) || (((a).high == (b).high) && ((a).low < (b).low)))
#define CompareInt64(a,b) (((afs_int32)(a).high - (afs_int32)(b).high) || (((a).high == (b).high) && ((a).low - (b).low)))
#define AddInt64(a, b, c) { afs_int64 _a, _b; _a = a; _b = b; (c)->low = _a.low + _b.low; (c)->high = _a.high + _b.high + ((c)->low < _b.low); }
#define SubtractInt64(a, b, c) { afs_int64 _a, _b; _a = a; _b = b; (c)->low = _a.low - _b.low; (c)->high = _a.high - _b.high - (_a.low < _b.low); }
@ -246,4 +262,9 @@ struct afsUUID {
};
typedef struct afsUUID afsUUID;
/* for now, demand attach fileserver is only support on unix pthreads builds */
#if defined(DEMAND_ATTACH_ENABLE) && defined(AFS_PTHREAD_ENV) && !defined(AFS_NT40_ENV)
#define AFS_DEMAND_ATTACH_FS 1
#endif
#endif /* OPENAFS_CONFIG_AFS_STDS_H */

View File

@ -78,6 +78,13 @@ for (n=0, queue_Scan(&myqueue, qe, nqe, myelement), n++) {}
#define _RXQSP(q1,q2,i,a,b,c,d,x,y) if (!queue_IsEnd(q1,i->c)) \
(((y->b->a=q2->a)->b=y->b), ((x->a->b=q2)->a=x->a), ((i->c=q1)->d=i))
/* This one moves a chain of elements from (s) to (e) from its
* current position to either before or after element (i)
* if (a,b,x,y) is (prev,next,s,e) then chain is moved before (i)
* if (a,b,x,y) is (next,prev,e,s) then chain is moved after (i) */
#define _RXQMV(i, s, e, a, b, x, y) if (i->a != y) \
(((e->next->prev=s->prev)->next=e->next), ((i->a->b=x)->a=i->a), ((y->b=i)->a=y))
/* Basic remove operation. Doesn't update the queue item to indicate it's been removed */
#define _RXQR(i) ((_RXQ(i)->prev->next=_RXQ(i)->next)->prev=_RXQ(i)->prev)
@ -120,6 +127,12 @@ for (n=0, queue_Scan(&myqueue, qe, nqe, myelement), n++) {}
#define queue_Replace(q1,q2) if (queue_IsEmpty(q2)) queue_Init(q1); else \
(*_RXQ(q1) = *_RXQ(q2), _RXQ(q1)->next->prev = _RXQ(q1)->prev->next = _RXQ(q1), queue_Init(q2))
/* move a chain of elements beginning at (s) and ending at (e) before node (i) */
#define queue_MoveChainBefore(i, s, e) _RXQMV(_RXQ(i),_RXQ(s),_RXQ(e),prev,next,_RXQ(s),_RXQ(e))
/* move a chain of elements beginning at (s) and ending at (e) after node (i) */
#define queue_MoveChainAfter(i, s, e) _RXQMV(_RXQ(i),_RXQ(s),_RXQ(e),next,prev,_RXQ(e),_RXQ(s))
/* Remove a queue element (*i) from it's queue. The next field is 0'd, so that any further use of this q entry will hopefully cause a core dump. Multiple removes of the same queue item are not supported */
#define queue_Remove(i) (_RXQR(i), _RXQ(i)->next = 0)
@ -155,6 +168,10 @@ for (n=0, queue_Scan(&myqueue, qe, nqe, myelement), n++) {}
/* Returns false if the item was removed from a queue OR is uninitialized (zero) */
#define queue_IsOnQueue(i) (_RXQ(i)->next != 0)
/* Returns true if the item was removed from a queue OR is uninitialized (zero) */
/* Return false if the queue item is currently in a queue */
#define queue_IsNotOnQueue(i) (_RXQ(i)->next == 0)
/* Returns true if the queue item (i) is the first element of the queue (q) */
#define queue_IsFirst(q,i) (_RXQ(q)->first == _RXQ(i))
@ -164,6 +181,9 @@ for (n=0, queue_Scan(&myqueue, qe, nqe, myelement), n++) {}
/* Returns true if the queue item (i) is the end of the queue (q), that is, i is the head of the queue */
#define queue_IsEnd(q,i) (_RXQ(q) == _RXQ(i))
/* Returns false if the queue item (i) is the end of the queue (q), that is, i is the head of the queue */
#define queue_IsNotEnd(q,i) (_RXQ(q) != _RXQ(i))
/* Prototypical loop to scan an entire queue forwards. q is the queue
* head, qe is the loop variable, next is a variable used to store the
* queue entry for the next iteration of the loop, s is the user's
@ -180,12 +200,24 @@ for (n=0, queue_Scan(&myqueue, qe, nqe, myelement), n++) {}
!queue_IsEnd(q, qe); \
(qe) = (next), next = queue_Next(qe, s)
/* similar to queue_Scan except start at element 'start' instead of the beginning */
#define queue_ScanFrom(q, start, qe, next, s) \
(qe) = (struct s*)(start), next = queue_Next(qe, s); \
!queue_IsEnd(q, qe); \
(qe) = (next), next = queue_Next(qe, s)
/* This is similar to queue_Scan, but scans from the end of the queue to the beginning. Next is the previous queue entry. */
#define queue_ScanBackwards(q, qe, prev, s) \
(qe) = queue_Last(q, s), prev = queue_Prev(qe, s); \
!queue_IsEnd(q, qe); \
(qe) = prev, prev = queue_Prev(qe, s)
/* This is similar to queue_ScanBackwards, but start at element 'start' instead of the end. Next is the previous queue entry. */
#define queue_ScanBackwardsFrom(q, start, qe, prev, s) \
(qe) = (struct s*)(start), prev = queue_Prev(qe, s); \
!queue_IsEnd(q, qe); \
(qe) = prev, prev = queue_Prev(qe, s)
#define queue_Count(q, qe, nqe, s, n) \
for (n=0, queue_Scan(q, qe, nqe, s), n++) {}
#endif /* _RX_QUEUE_ */

200
src/tsalvaged/Makefile.in Normal file
View File

@ -0,0 +1,200 @@
# 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
#
# Portions Copyright (c) 2003 Apple Computer, Inc.
# Portions Copyright (c) 2006 Sine Nomine Associates
srcdir=@srcdir@
include @TOP_OBJDIR@/src/config/Makefile.config
CC=${MT_CC}
CFLAGS=${COMMON_CFLAGS} -I.. -DNINTERFACE ${MT_CFLAGS} -DRXDEBUG -DFSSYNC_BUILD_CLIENT \
-DSALVSYNC_BUILD_SERVER -DSALVSYNC_BUILD_CLIENT
CCRULE=${CC} ${CFLAGS} -c $?
VICED=../viced
VLSERVER=../vlserver
LWP=../lwp
LIBACL=../libacl
UTIL=../util
DIR=../dir
VOL=../vol
FSINT=../fsint
SALVAGEDOBJS=salvaged.o vol-salvage.o physio.o
DIROBJS=buffer.o dir.o salvage.o
LWPOBJS=lock.o threadname.o
UTILOBJS=assert.o uuid.o serverLog.o fileutil.o netutils.o dirpath.o volparse.o flipbase64.o softsig.o fstab.o
VLIBOBJS=vnode.o volume.o vutil.o partition.o fssync-client.o \
clone.o nuke.o devname.o listinodes.o ihandle.o \
namei_ops.o salvsync-server.o salvsync-client.o \
daemon_com.o
OBJECTS= ${SALVAGEDOBJS} ${UTILOBJS} ${VLIBOBJS} ${DIROBJS} ${LWPOBJS}
FSSDEBUG_OBJS = fssync-debug.o physio.o common.o ${UTILOBJS} ${VLIBOBJS} ${DIROBJS} ${LWPOBJS}
SSSDEBUG_OBJS = salvsync-debug.o physio.o common.o ${UTILOBJS} ${VLIBOBJS} ${DIROBJS} ${LWPOBJS}
LIBS=${TOP_LIBDIR}/libafsauthent.a ${TOP_LIBDIR}/libafsrpc.a ${TOP_LIBDIR}/util.a ${TOP_LIBDIR}/libcmd.a
INSTALL_TARGS = ${DESTDIR}${afssrvlibexecdir}/salvageserver \
${DESTDIR}${afssrvsbindir}/fssync-debug \
${DESTDIR}${afssrvsbindir}/salvsync-debug
DEST_TARGS = ${DEST}/root.server/usr/afs/bin/salvageserver \
${DEST}/root.server/usr/afs/bin/fssync-debug \
${DEST}/root.server/usr/afs/bin/salvsync-debug
all: salvageserver fssync-debug salvsync-debug
salvaged.o: ${VOL}/salvaged.c
${CCRULE}
vol-salvage.o: ${VOL}/vol-salvage.c
${CCRULE}
physio.o: ${VOL}/physio.c
${CCRULE}
fssync-debug.o: ${VOL}/fssync-debug.c
${CCRULE}
salvsync-debug.o: salvsync-debug.c
${CCRULE}
assert.o: ${UTIL}/assert.c
${CCRULE}
uuid.o: ${UTIL}/uuid.c
${CCRULE}
serverLog.o: ${UTIL}/serverLog.c
${CCRULE}
fileutil.o: ${UTIL}/fileutil.c
${CCRULE}
volparse.o: ${UTIL}/volparse.c
${CCRULE}
flipbase64.o: ${UTIL}/flipbase64.c
${CCRULE}
netutils.o: ${UTIL}/netutils.c
${CCRULE}
dirpath.o: ${UTIL}/dirpath.c
${CCRULE}
softsig.o: ${UTIL}/softsig.c
${CCRULE}
buffer.o: ${DIR}/buffer.c
${CCRULE}
dir.o: ${DIR}/dir.c
${CCRULE}
salvage.o: ${DIR}/salvage.c
${CCRULE}
lock.o: ${LWP}/lock.c
${CCRULE}
threadname.o: ${LWP}/threadname.c
${CCRULE}
vnode.o: ${VOL}/vnode.c
${CCRULE}
volume.o: ${VOL}/volume.c
${CCRULE}
vutil.o: ${VOL}/vutil.c
${CCRULE}
partition.o: ${VOL}/partition.c
${CCRULE}
fssync-client.o: ${VOL}/fssync-client.c
${CCRULE}
salvsync-server.o: ${VOL}/salvsync-server.c
${CCRULE}
salvsync-client.o: ${VOL}/salvsync-client.c
${CCRULE}
daemon_com.o: ${VOL}/daemon_com.c
${CCRULE}
clone.o: ${VOL}/clone.c
${CCRULE}
nuke.o: ${VOL}/nuke.c
${CCRULE}
devname.o: ${VOL}/devname.c
${CCRULE}
# only for darwin?
fstab.o: ${UTIL}/fstab.c
${CCRULE}
common.o: ${VOL}/common.c
${CCRULE}
listinodes.o: ${VOL}/listinodes.c
${CCRULE}
ihandle.o: ${VOL}/ihandle.c
${CCRULE}
namei_ops.o: ${VOL}/namei_ops.c
${CCRULE}
salvageserver: ${OBJECTS} ${LIBS}
${CC} ${LDFLAGS} -o salvageserver ${OBJECTS} ${LIBS} ${MT_LIBS} ${XLIBS}
fssync-debug: ${FSSDEBUG_OBJS} ${LIBS}
${CC} ${LDFLAGS} -o fssync-debug ${FSSDEBUG_OBJS} ${LIBS} ${MT_LIBS} ${XLIBS}
salvsync-debug: ${SSSDEBUG_OBJS} ${LIBS}
${CC} ${LDFLAGS} -o salvsync-debug ${SSSDEBUG_OBJS} ${LIBS} ${MT_LIBS} ${XLIBS}
${DEST}/root.server/usr/afs/bin/salvageserver: salvageserver
${INSTALL} -ns $? $@
${DEST}/root.server/usr/afs/bin/fssync-debug: fssync-debug
${INSTALL} -s $? $@
${DEST}/root.server/usr/afs/bin/salvsync-debug: salvsync-debug
${INSTALL} -s $? $@
install: ${INSTALL_TARGS}
clean:
$(RM) -f *.o salvageserver core AFS_component_version_number.c
include ../config/Makefile.version
${DESTDIR}${afssrvlibexecdir}/salvageserver: salvageserver
${INSTALL} -ns $? $@
${DESTDIR}${afssrvsbindir}/fssync-debug: fssync-debug
${INSTALL} -s $? $@
${DESTDIR}${afssrvsbindir}/salvsync-debug: salvsync-debug
${INSTALL} -s $? $@
dest: ${DEST_TARGS}

View File

@ -0,0 +1,475 @@
/*
* Copyright 2006, Sine Nomine Associates 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
*/
/* Main program file. Define globals. */
#define MAIN 1
/*
* salvsync debug tool
*/
#include <afsconfig.h>
#include <afs/param.h>
RCSID
("$Header$");
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <dirent.h>
#include <sys/stat.h>
#include <time.h>
#include <errno.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
#include <rx/xdr.h>
#include <afs/afsint.h>
#include <afs/assert.h>
#include <fcntl.h>
#ifndef AFS_NT40_ENV
#include <afs/osi_inode.h>
#endif
#include <afs/cmd.h>
#include <afs/afsutil.h>
#include <afs/fileutil.h>
#include "nfs.h"
#include "lwp.h"
#include "lock.h"
#include "ihandle.h"
#include "vnode.h"
#include "volume.h"
#include "partition.h"
#include "daemon_com.h"
#include "salvsync.h"
#ifdef AFS_NT40_ENV
#include <pthread.h>
#endif
int VolumeChanged; /* hack to make dir package happy */
#ifndef AFS_DEMAND_ATTACH_FS
int
main(int argc, char ** argv)
{
fprintf(stderr, "*** salvsync-debug is only supported for OpenAFS builds with the demand-attach fileserver extension\n");
return -1;
}
#else /* AFS_DEMAND_ATTACH_FS */
struct salv_state {
afs_uint32 prio;
afs_uint32 volume;
char partName[16];
};
struct state {
afs_int32 reason;
struct salv_state * sop;
};
static int common_prolog(struct cmd_syndesc *, struct state *);
static int common_salv_prolog(struct cmd_syndesc *, struct state *);
static int do_salvop(struct state *, afs_int32 command, SYNC_response * res);
static char * response_code_to_string(afs_int32);
static char * command_code_to_string(afs_int32);
static char * reason_code_to_string(afs_int32);
static char * program_type_to_string(afs_int32);
static char * state_code_to_string(afs_int32);
static int OpStats(struct cmd_syndesc * as, char * rock);
static int OpSalvage(struct cmd_syndesc * as, char * rock);
static int OpCancel(struct cmd_syndesc * as, char * rock);
static int OpCancelAll(struct cmd_syndesc * as, char * rock);
static int OpRaisePrio(struct cmd_syndesc * as, char * rock);
static int OpQuery(struct cmd_syndesc * as, char * rock);
#ifndef AFS_NT40_ENV
#include "AFS_component_version_number.c"
#endif
#define MAX_ARGS 128
#define COMMON_PARMS_OFFSET 13
#define COMMON_PARMS(ts) \
cmd_Seek(ts, COMMON_PARMS_OFFSET); \
cmd_AddParm(ts, "-reason", CMD_SINGLE, CMD_OPTIONAL, "sync protocol reason code"); \
cmd_AddParm(ts, "-programtype", CMD_SINGLE, CMD_OPTIONAL, "program type code")
#define COMMON_SALV_PARMS_OFFSET 10
#define COMMON_SALV_PARMS(ts) \
cmd_Seek(ts, COMMON_SALV_PARMS_OFFSET); \
cmd_AddParm(ts, "-volumeid", CMD_SINGLE, 0, "volume id"); \
cmd_AddParm(ts, "-partition", CMD_SINGLE, CMD_OPTIONAL, "partition name"); \
cmd_AddParm(ts, "-priority", CMD_SINGLE, CMD_OPTIONAL, "priority")
#define SALV_PARMS_DECL(ts) \
COMMON_SALV_PARMS(ts); \
COMMON_PARMS(ts)
#define COMMON_PARMS_DECL(ts) \
COMMON_PARMS(ts)
int
main(int argc, char **argv)
{
struct cmd_syndesc *ts;
int err = 0;
int i;
extern char cml_version_number[];
/* Initialize directory paths */
if (!(initAFSDirPath() & AFSDIR_SERVER_PATHS_OK)) {
#ifdef AFS_NT40_ENV
ReportErrorEventAlt(AFSEVT_SVR_NO_INSTALL_DIR, 0, argv[0], 0);
#endif
fprintf(stderr, "%s: Unable to obtain AFS server directory.\n",
argv[0]);
exit(2);
}
ts = cmd_CreateSyntax("stats", OpStats, 0, "get salvageserver statistics (SALVSYNC_NOP opcode)");
COMMON_PARMS_DECL(ts);
cmd_CreateAlias(ts, "nop");
ts = cmd_CreateSyntax("salvage", OpSalvage, 0, "schedule a salvage (SALVSYNC_SALVAGE opcode)");
SALV_PARMS_DECL(ts);
ts = cmd_CreateSyntax("cancel", OpCancel, 0, "cancel a salvage (SALVSYNC_CANCEL opcode)");
SALV_PARMS_DECL(ts);
ts = cmd_CreateSyntax("raiseprio", OpRaisePrio, 0, "raise a salvage priority (SALVSYNC_RAISEPRIO opcode)");
SALV_PARMS_DECL(ts);
cmd_CreateAlias(ts, "rp");
ts = cmd_CreateSyntax("query", OpQuery, 0, "query salvage status (SALVSYNC_QUERY opcode)");
SALV_PARMS_DECL(ts);
cmd_CreateAlias(ts, "qry");
ts = cmd_CreateSyntax("kill", OpCancelAll, 0, "cancel all scheduled salvages (SALVSYNC_CANCELALL opcode)");
COMMON_PARMS_DECL(ts);
err = cmd_Dispatch(argc, argv);
exit(err);
}
static int
common_prolog(struct cmd_syndesc * as, struct state * state)
{
register struct cmd_item *ti;
#ifdef AFS_NT40_ENV
if (afs_winsockInit() < 0) {
Exit(1);
}
#endif
VInitVolumePackage(debugUtility, 1, 1,
DONT_CONNECT_FS, 0);
DInit(1);
if ((ti = as->parms[COMMON_PARMS_OFFSET].items)) { /* -reason */
state->reason = atoi(ti->data);
}
if ((ti = as->parms[COMMON_PARMS_OFFSET+1].items)) { /* -programtype */
if (!strcmp(ti->data, "fileServer")) {
programType = fileServer;
} else if (!strcmp(ti->data, "volumeUtility")) {
programType = volumeUtility;
} else if (!strcmp(ti->data, "salvager")) {
programType = salvager;
} else if (!strcmp(ti->data, "salvageServer")) {
programType = salvageServer;
} else {
programType = (ProgramType) atoi(ti->data);
}
}
VConnectSALV();
return 0;
}
static int
common_salv_prolog(struct cmd_syndesc * as, struct state * state)
{
register struct cmd_item *ti;
char pname[100], *temp;
state->sop = (struct salv_state *) calloc(1, sizeof(struct salv_state));
assert(state->sop != NULL);
if ((ti = as->parms[COMMON_SALV_PARMS_OFFSET].items)) { /* -volumeid */
state->sop->volume = atoi(ti->data);
} else {
fprintf(stderr, "required argument -volumeid not given\n");
}
if ((ti = as->parms[COMMON_SALV_PARMS_OFFSET+1].items)) { /* -partition */
strlcpy(state->sop->partName, ti->data, sizeof(state->sop->partName));
} else {
memset(state->sop->partName, 0, sizeof(state->sop->partName));
}
if ((ti = as->parms[COMMON_SALV_PARMS_OFFSET+2].items)) { /* -prio */
state->sop->prio = atoi(ti->data);
} else {
state->sop->prio = 0;
}
return 0;
}
static int
do_salvop(struct state * state, afs_int32 command, SYNC_response * res)
{
afs_int32 code;
SALVSYNC_response_hdr hdr_l, *hdr;
SYNC_response res_l;
if (!res) {
res = &res_l;
res->payload.len = sizeof(hdr_l);
res->payload.buf = hdr = &hdr_l;
} else {
hdr = (SALVSYNC_response_hdr *) res->payload.buf;
}
fprintf(stderr, "calling SALVSYNC_SalvageVolume with command code %d (%s)\n",
command, command_code_to_string(command));
code = SALVSYNC_SalvageVolume(state->sop->volume,
state->sop->partName,
command,
state->reason,
state->sop->prio,
res);
switch (code) {
case SYNC_OK:
case SYNC_DENIED:
break;
default:
fprintf(stderr, "possible sync protocol error. return code was %d\n", code);
}
fprintf(stderr, "SALVSYNC_SalvageVolume returned %d (%s)\n", code, response_code_to_string(code));
fprintf(stderr, "protocol response code was %d (%s)\n",
res->hdr.response, response_code_to_string(res->hdr.response));
fprintf(stderr, "protocol reason code was %d (%s)\n",
res->hdr.reason, reason_code_to_string(res->hdr.reason));
printf("state = {\n");
if (res->hdr.flags & SALVSYNC_FLAG_VOL_STATS_VALID) {
printf("\tstate = %d (%s)\n",
hdr->state, state_code_to_string(hdr->state));
printf("\tprio = %d\n", hdr->prio);
}
printf("\tsq_len = %d\n", hdr->sq_len);
printf("\tpq_len = %d\n", hdr->pq_len);
printf("}\n");
VDisconnectSALV();
}
static char *
response_code_to_string(afs_int32 response)
{
switch (response) {
case SYNC_OK:
return "SYNC_OK";
case SYNC_DENIED:
return "SYNC_DENIED";
case SYNC_COM_ERROR:
return "SYNC_COM_ERROR";
case SYNC_BAD_COMMAND:
return "SYNC_BAD_COMMAND";
case SYNC_FAILED:
return "SYNC_FAILED";
default:
return "**UNKNOWN**";
}
}
static char *
command_code_to_string(afs_int32 command)
{
switch (command) {
case SYNC_COM_CHANNEL_CLOSE:
return "SYNC_COM_CHANNEL_CLOSE";
case SALVSYNC_NOP:
return "SALVSYNC_NOP";
case SALVSYNC_SALVAGE:
return "SALVSYNC_SALVAGE";
case SALVSYNC_CANCEL:
return "SALVSYNC_CANCEL";
case SALVSYNC_RAISEPRIO:
return "SALVSYNC_RAISEPRIO";
case SALVSYNC_QUERY:
return "SALVSYNC_QUERY";
case SALVSYNC_CANCELALL:
return "SALVSYNC_CANCELLALL";
default:
return "**UNKNOWN**";
}
}
static char *
reason_code_to_string(afs_int32 reason)
{
switch (reason) {
case SALVSYNC_WHATEVER:
return "SALVSYNC_WHATEVER";
case SALVSYNC_ERROR:
return "SALVSYNC_ERROR";
case SALVSYNC_OPERATOR:
return "SALVSYNC_OPERATOR";
case SALVSYNC_SHUTDOWN:
return "SALVSYNC_SHUTDOWN";
case SALVSYNC_NEEDED:
return "SALVSYNC_NEEDED";
default:
return "**UNKNOWN**";
}
}
static char *
program_type_to_string(afs_int32 type)
{
switch ((ProgramType)type) {
case fileServer:
return "fileServer";
case volumeUtility:
return "volumeUtility";
case salvager:
return "salvager";
case salvageServer:
return "salvageServer";
default:
return "**UNKNOWN**";
}
}
static char *
state_code_to_string(afs_int32 state)
{
switch (state) {
case SALVSYNC_STATE_UNKNOWN:
return "SALVSYNC_STATE_UNKNOWN";
case SALVSYNC_STATE_QUEUED:
return "SALVSYNC_STATE_QUEUED";
case SALVSYNC_STATE_SALVAGING:
return "SALVSYNC_STATE_SALVAGING";
case SALVSYNC_STATE_ERROR:
return "SALVSYNC_STATE_ERROR";
case SALVSYNC_STATE_DONE:
return "SALVSYNC_STATE_DONE";
default:
return "**UNKNOWN**";
}
}
static int
OpStats(struct cmd_syndesc * as, char * rock)
{
struct state state;
common_prolog(as, &state);
common_salv_prolog(as, &state);
do_salvop(&state, SALVSYNC_NOP, NULL);
return 0;
}
static int
OpSalvage(struct cmd_syndesc * as, char * rock)
{
struct state state;
common_prolog(as, &state);
common_salv_prolog(as, &state);
do_salvop(&state, SALVSYNC_SALVAGE, NULL);
return 0;
}
static int
OpCancel(struct cmd_syndesc * as, char * rock)
{
struct state state;
common_prolog(as, &state);
common_salv_prolog(as, &state);
do_salvop(&state, SALVSYNC_CANCEL, NULL);
return 0;
}
static int
OpCancelAll(struct cmd_syndesc * as, char * rock)
{
struct state state;
common_prolog(as, &state);
common_salv_prolog(as, &state);
do_salvop(&state, SALVSYNC_CANCELALL, NULL);
return 0;
}
static int
OpRaisePrio(struct cmd_syndesc * as, char * rock)
{
struct state state;
common_prolog(as, &state);
common_salv_prolog(as, &state);
do_salvop(&state, SALVSYNC_RAISEPRIO, NULL);
return 0;
}
static int
OpQuery(struct cmd_syndesc * as, char * rock)
{
struct state state;
common_prolog(as, &state);
common_salv_prolog(as, &state);
do_salvop(&state, SALVSYNC_QUERY, NULL);
return 0;
}
#endif /* AFS_DEMAND_ATTACH_FS */

View File

@ -11,7 +11,7 @@ srcdir=@srcdir@
include @TOP_OBJDIR@/src/config/Makefile.config
CC=${MT_CC}
CFLAGS=${COMMON_CFLAGS} -I.. -DNINTERFACE ${MT_CFLAGS} -DRXDEBUG
CFLAGS=${COMMON_CFLAGS} -I.. -DNINTERFACE ${MT_CFLAGS} -DRXDEBUG -DFSSYNC_BUILD_SERVER -DSALVSYNC_BUILD_CLIENT
CCRULE=${CC} ${CFLAGS} -c $?
@ -24,7 +24,7 @@ DIR=../dir
VOL=../vol
FSINT=../fsint
VICEDOBJS=viced.o afsfileprocs.o host.o physio.o callback.o
VICEDOBJS=viced.o afsfileprocs.o host.o physio.o callback.o serialize_state.o
VLSERVEROBJS=vldbint.cs.o vldbint.xdr.o
@ -36,18 +36,20 @@ UTILOBJS=assert.o uuid.o serverLog.o fileutil.o netutils.o dirpath.o volparse.o
DIROBJS=buffer.o dir.o salvage.o
VOLOBJS= vnode.o volume.o vutil.o partition.o fssync.o purge.o \
VOLOBJS= vnode.o volume.o vutil.o partition.o fssync-server.o \
clone.o devname.o common.o ihandle.o listinodes.o namei_ops.o \
fstab.o
fstab.o salvsync-client.o daemon_com.o
FSINTOBJS= afsaux.o afscbint.cs.o afsint.ss.o afsint.xdr.o
objects= ${VICEDOBJS} ${VLSERVEROBJS} ${LWPOBJS} ${LIBACLOBJS} \
${UTILOBJS} ${DIROBJS} ${VOLOBJS} ${FSINTOBJS}
SDBGOBJS = state_analyzer.o uuid.o dirpath.o fileutil.o ${TOP_LIBDIR}/util.a
LIBS=${TOP_LIBDIR}/libafsauthent.a ${TOP_LIBDIR}/libafsrpc.a ${TOP_LIBDIR}/util.a
all: fileserver
all: fileserver state_analyzer
viced.o: ${VICED}/viced.c
${CCRULE}
@ -64,6 +66,9 @@ physio.o: ${VICED}/physio.c
callback.o: ${VICED}/callback.c
${CCRULE}
serialize_state.o: ./serialize_state.c
${CCRULE}
assert.o: ${UTIL}/assert.c
${CCRULE}
@ -130,10 +135,16 @@ vutil.o: ${VOL}/vutil.c
partition.o: ${VOL}/partition.c
${CCRULE}
fssync.o: ${VOL}/fssync.c
fssync-server.o: ${VOL}/fssync-server.c
${CCRULE}
purge.o: ${VOL}/purge.c
fssync-client.o: ${VOL}/fssync-client.c
${CCRULE}
salvsync-client.o: ${VOL}/salvsync-client.c
${CCRULE}
daemon_com.o: ${VOL}/daemon_com.c
${CCRULE}
clone.o: ${VOL}/clone.c
@ -179,21 +190,33 @@ afsint.ss.o: ${FSINT}/afsint.ss.c
afsint.xdr.o: ${FSINT}/afsint.xdr.c
${CCRULE}
state_analyzer.o: state_analyzer.c
${CCRULE}
fileserver: ${objects} ${LIBS}
${CC} ${LDFLAGS} -o fileserver ${objects} ${LIBS} ${MT_LIBS} ${XLIBS}
state_analyzer: ${SDBGOBJS}
${CC} ${LDFLAGS} -o state_analyzer ${SDBGOBJS} ${MT_LIBS} ${XLIBS}
${DEST}/root.server/usr/afs/bin/fileserver: fileserver
${INSTALL} -ns $? $@
install: ${DESTDIR}${afssrvlibexecdir}/fileserver
${DEST}/root.server/usr/afs/bin/state_analyzer: state_analyzer
${INSTALL} $? $@
install: ${DESTDIR}${afssrvlibexecdir}/fileserver ${DESTDIR}${afssrvsbindir}/state_analyzer
clean:
$(RM) -f *.o fileserver core AFS_component_version_number.c
$(RM) -f *.o fileserver state_analyzer core AFS_component_version_number.c
include ../config/Makefile.version
${DESTDIR}${afssrvlibexecdir}/fileserver: fileserver
${INSTALL} -ns $? $@
dest: ${DEST}/root.server/usr/afs/bin/fileserver
${DESTDIR}${afssrvsbindir}/state_analyzer: state_analyzer
${INSTALL} $? $@
dest: ${DEST}/root.server/usr/afs/bin/fileserver ${DEST}/root.server/usr/afs/bin/state_analyzer

View File

@ -5,7 +5,7 @@
# License. For details, see the LICENSE file in the top-level source
# directory or online at http://www.openafs.org/dl/license10.html
AFSDEV_AUXCDEFINES = -DAFS_PTHREAD_ENV -DRXDEBUG
AFSDEV_AUXCDEFINES = -DAFS_PTHREAD_ENV -DRXDEBUG -DFSSYNC_BUILD_SERVER
RELDIR=tviced
!INCLUDE ..\config\NTMakefile.$(SYS_NAME)

1120
src/tviced/serialize_state.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,311 @@
/*
* Copyright 2006, Sine Nomine Associates 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
*/
/*
* demand attach fs
* fileserver state serialization
*/
#ifndef _AFS_TVICED_SERIALIZE_STATE_H
#define _AFS_TVICED_SERIALIZE_STATE_H
#ifdef AFS_DEMAND_ATTACH_FS
#define FS_STATE_MAGIC 0x62FA841C
#define FS_STATE_VERSION 2
#define HOST_STATE_MAGIC 0x7B8C9DAE
#define HOST_STATE_VERSION 2
#define HOST_STATE_ENTRY_MAGIC 0xA8B9CADB
#define CALLBACK_STATE_MAGIC 0x89DE67BC
#define CALLBACK_STATE_VERSION 1
#define CALLBACK_STATE_TIMEOUT_MAGIC 0x99DD5511
#define CALLBACK_STATE_FEHASH_MAGIC 0x77BB33FF
#define CALLBACK_STATE_ENTRY_MAGIC 0x54637281
#define ACTIVE_VOLUME_STATE_MAGIC 0xAC7557CA
#define ACTIVE_VOLUME_STATE_VERSION 1
#define ACTIVE_VOLUME_STATE_AVEHASH_MAGIC 0xBADDF00D
#define HOST_STATE_VALID_WINDOW 1800 /* 30 minutes */
/*
* on-disk structures
*/
struct disk_version_stamp {
afs_uint32 magic;
afs_uint32 version;
};
/* 1024 byte header structure */
struct fs_state_header {
struct disk_version_stamp stamp; /* version stamp */
afs_uint32 timestamp; /* timestamp of save */
afs_uint32 sys_name; /* sys name id for this machine */
afsUUID server_uuid; /* server's UUID */
byte valid; /* whether header contents are valid */
byte endianness; /* endianness sanity check (0 for LE, 1 for BE) */
byte stats_detailed; /* fs stats detailed sanity check */
byte padding1[1]; /* padding */
afs_uint32 reserved1[23]; /* for expansion */
afs_uint64 avol_offset; /* offset of active volumes structure */
afs_uint64 h_offset; /* offset of host_state_header structure */
afs_uint64 cb_offset; /* offset of callback_state_header structure */
afs_uint64 vlru_offset; /* offset of vlru state structure */
afs_uint32 reserved2[56]; /* for expansion */
char server_version_string[128]; /* version string from AFS_component_version_number.c */
afs_uint32 reserved3[128]; /* for expansion */
};
/*
* host package serialization
*/
/* 256 byte header for the host state data */
struct host_state_header {
struct disk_version_stamp stamp; /* host state version stamp */
afs_uint32 records; /* number of stored host records */
afs_uint32 index_max; /* max index value encountered */
afs_uint32 reserved[60]; /* for expansion */
};
/* 32 byte host entry header */
struct host_state_entry_header {
afs_uint32 magic; /* stamp */
afs_uint32 len; /* number of bytes in this record */
afs_uint32 interfaces; /* number of interfaces included in record */
afs_uint32 hcps; /* number of hcps entries in record */
afs_uint32 reserved[4];
};
/* 36 byte host entry structure */
struct hostDiskEntry {
afs_uint32 host; /* IP address of host interface that is
* currently being used, in network
* byte order */
afs_uint16 port; /* port address of host */
afs_uint16 hostFlags; /* bit map */
byte Console; /* XXXX This host is a console */
byte hcpsfailed; /* Retry the cps call next time */
byte hcps_valid; /* prlist_val not null */
#if FS_STATS_DETAILED
byte InSameNetwork; /*Is host's addr in the same network as
* the File Server's? */
#else
byte padding1[1]; /* for padding */
#endif /* FS_STATS_DETAILED */
afs_uint32 hcps_len; /* length of hcps */
afs_uint32 LastCall; /* time of last call from host */
afs_uint32 ActiveCall; /* time of any call but gettime */
afs_uint32 cpsCall; /* time of last cps call from this host */
afs_uint32 cblist; /* Call back list for this host */
afs_uint32 index; /* index for correlating w/ callback dumps */
};
/*
* callback package serialization
*/
/* 512 byte header */
struct callback_state_header {
struct disk_version_stamp stamp; /* callback state version stamp */
afs_uint32 nFEs; /* number of FileEntry records */
afs_uint32 nCBs; /* number of CallBack records */
afs_uint32 fe_max; /* max FileEntry index */
afs_uint32 cb_max; /* max CallBack index */
afs_int32 tfirst; /* first valid timeout */
afs_uint32 reserved[115]; /* for expansion */
afs_uint64 timeout_offset; /* offset of timeout queue heads */
afs_uint64 fehash_offset; /* offset of file entry hash buckets */
afs_uint64 fe_offset; /* offset of first file entry */
};
/* 32 byte header */
struct callback_state_timeout_header {
afs_uint32 magic; /* magic number for timeout header */
afs_uint32 len; /* total length of header and timeout records */
afs_uint32 records; /* number of timeout records */
afs_uint32 reserved[5];
};
/* 32 byte header */
struct callback_state_fehash_header {
afs_uint32 magic; /* magic number for fehash header */
afs_uint32 len; /* total length of header and fehash bucket heads */
afs_uint32 records; /* number of hash buckets */
afs_uint32 reserved[5];
};
/* 32 byte header */
struct callback_state_entry_header {
afs_uint32 magic; /* magic number for FE entry */
afs_uint32 len; /* number of bytes in this record */
afs_uint32 nCBs; /* number of callbacks for this FE */
afs_uint32 reserved[5];
};
struct FEDiskEntry {
struct FileEntry fe;
afs_uint32 index;
};
struct CBDiskEntry {
struct CallBack cb;
afs_uint32 index;
};
/*
* active volumes state serialization
*
* these structures are meant to support
* automated salvaging of active volumes
* in the event of a fileserver crash
*/
/* 512 byte header */
struct active_volume_state_header {
struct disk_version_stamp stamp; /* callback state version stamp */
afs_uint32 nAVEs; /* number of ActiveVolumeEntry records */
afs_uint32 init_timestamp; /* timestamp of AVE initialization */
afs_uint32 update_timetamp; /* timestamp of last AVE update */
afs_uint32 reserved[119]; /* for expansion */
afs_uint64 avehash_offset; /* offset of active volume entry hash buckets */
afs_uint64 ave_offset; /* offset of first active volume entry */
};
/* 32 byte header */
struct active_volume_state_avehash_header {
afs_uint32 magic; /* magic number for avehash header */
afs_uint32 len; /* total length of header and avehash bucket heads */
afs_uint32 records; /* number of hash buckets */
afs_uint32 reserved[5];
};
typedef afs_uint32 active_volume_state_avehash_entry;
/* active volume entry */
struct AVDiskEntry {
afs_uint32 volume;
afs_uint32 partition;
afs_uint32 hash_next;
};
/*
* dump runtime state
*/
struct idx_map_entry_t {
afs_uint32 old_idx; /* host hash id from last runtime */
afs_uint32 new_idx; /* host hash id for this runtime */
};
/* verification process sanity check constants
*
* make them fairly large so we don't get
* false positives
*/
#define FS_STATE_H_MAX_UUID_HASH_CHAIN_LEN 100000 /* max elements in a host uuid-hash chain */
#define FS_STATE_H_MAX_ADDR_HASH_CHAIN_LEN 2000000 /* max elements in a host ipv4-hash chain */
#define FS_STATE_FE_MAX_HASH_CHAIN_LEN 100000 /* max elements in a FE fid-hash chain */
#define FS_STATE_FCB_MAX_LIST_LEN 100000 /* max elements in a per-FE CB list */
#define FS_STATE_HCB_MAX_LIST_LEN 100000 /* max elements in a per-host CB list */
#define FS_STATE_TCB_MAX_LIST_LEN 100000 /* max elements in a per-timeout CB list */
/*
* main state serialization state structure
*/
struct fs_dump_state {
enum {
FS_STATE_DUMP_MODE,
FS_STATE_LOAD_MODE
} mode;
struct {
byte do_host_restore; /* whether host restore should be done */
byte some_steps_skipped; /* whether some steps were skipped */
byte warnings_generated; /* whether any warnings were generated during restore */
} flags;
afs_fsize_t file_len;
int fd; /* fd of the current dump file */
int bail; /* non-zero if something went wrong */
char * fn; /* name of the current dump file */
struct { /* memory map of dump file */
void * map;
void * cursor;
afs_foff_t offset;
afs_fsize_t size;
} mmap;
struct fs_state_header * hdr; /* main header */
struct host_state_header * h_hdr; /* header for host state data */
struct callback_state_header * cb_hdr; /* header for callback state data */
struct callback_state_timeout_header * cb_timeout_hdr;
struct callback_state_fehash_header * cb_fehash_hdr;
afs_uint64 eof_offset; /* current end of file offset */
struct {
int len; /* number of host entries in map */
struct idx_map_entry_t * entries;
} h_map;
struct {
int len;
struct idx_map_entry_t * entries;
} fe_map;
struct {
int len;
struct idx_map_entry_t * entries;
} cb_map;
};
/* prototypes */
/* serialize_state.c */
extern int fs_stateWrite(struct fs_dump_state * state,
void * buf, size_t len);
extern int fs_stateRead(struct fs_dump_state * state,
void * buf, size_t len);
extern int fs_stateWriteV(struct fs_dump_state * state,
struct iovec * iov, int niov);
extern int fs_stateReadV(struct fs_dump_state * state,
struct iovec * iov, int niov);
extern int fs_stateSync(struct fs_dump_state * state);
extern int fs_stateWriteHeader(struct fs_dump_state * state,
afs_uint64 * offset,
void * hdr, size_t len);
extern int fs_stateReadHeader(struct fs_dump_state * state,
afs_uint64 * offset,
void * hdr, size_t len);
extern int fs_stateIncEOF(struct fs_dump_state * state,
afs_int32 len);
extern int fs_stateSeek(struct fs_dump_state * state,
afs_uint64 * offset);
/* host.c */
extern int h_stateSave(struct fs_dump_state * state);
extern int h_stateRestore(struct fs_dump_state * state);
extern int h_stateRestoreIndices(struct fs_dump_state * state);
extern int h_stateVerify(struct fs_dump_state * state);
extern int h_OldToNew(struct fs_dump_state * state, afs_uint32 old, afs_uint32 * new);
/* callback.c */
extern int cb_stateSave(struct fs_dump_state * state);
extern int cb_stateRestore(struct fs_dump_state * state);
extern int cb_stateRestoreIndices(struct fs_dump_state * state);
extern int cb_stateVerify(struct fs_dump_state * state);
extern int cb_stateVerifyHCBList(struct fs_dump_state * state, struct host * host);
extern int fe_OldToNew(struct fs_dump_state * state, afs_uint32 old, afs_uint32 * new);
extern int cb_OldToNew(struct fs_dump_state * state, afs_uint32 old, afs_uint32 * new);
#endif /* AFS_DEMAND_ATTACH_FS */
#endif /* _AFS_TVICED_SERIALIZE_STATE_H */

2004
src/tviced/state_analyzer.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -10,7 +10,7 @@ include @TOP_OBJDIR@/src/config/Makefile.config
HELPER_SPLINT=@HELPER_SPLINT@
CC=${MT_CC}
CFLAGS=${COMMON_CFLAGS} -I.. -DNINTERFACE ${MT_CFLAGS} -DRXDEBUG
CFLAGS=${COMMON_CFLAGS} -I.. -DNINTERFACE ${MT_CFLAGS} -DRXDEBUG -DFSSYNC_BUILD_CLIENT
CCRULE=${CC} ${CFLAGS} -c $?
@ -36,8 +36,9 @@ UTILOBJS=assert.o uuid.o serverLog.o fileutil.o netutils.o dirpath.o volparse.o
DIROBJS=buffer.o dir.o salvage.o
VOLOBJS= vnode.o volume.o vutil.o partition.o fssync.o purge.o \
clone.o devname.o common.o ihandle.o listinodes.o namei_ops.o nuke.o
VOLOBJS= vnode.o volume.o vutil.o partition.o fssync-client.o purge.o \
clone.o devname.o common.o ihandle.o listinodes.o \
namei_ops.o nuke.o salvsync-client.o daemon_com.o
FSINTOBJS=# afsaux.o afscbint.cs.o afsint.ss.o afsint.xdr.o
@ -138,7 +139,13 @@ partition.o: ${VOL}/partition.c
nuke.o: ${VOL}/nuke.c
${COMPILE}
fssync.o: ${VOL}/fssync.c
fssync-client.o: ${VOL}/fssync-client.c
${COMPILE}
salvsync-client.o: ${VOL}/salvsync-client.c
${COMPILE}
daemon_com.o: ${VOL}/daemon_com.c
${COMPILE}
purge.o: ${VOL}/purge.c

View File

@ -13,7 +13,7 @@ HELPER_SPLINT=@HELPER_SPLINT@
objects = assert.o base64.o casestrcpy.o ktime.o volparse.o hostparse.o \
hputil.o kreltime.o isathing.o get_krbrlm.o uuid.o serverLog.o \
dirpath.o fileutil.o netutils.o flipbase64.o fstab.o \
afs_atomlist.o afs_lhash.o snprintf.o strlcat.o strlcpy.o \
afs_atomlist.o afs_lhash.o snprintf.o strlcat.o strlcpy.o strnlen.o \
daemon.o rxkstats.o ${REGEX_OBJ}
includes = \
@ -134,6 +134,9 @@ strlcat.o: ${srcdir}/strlcat.c ${includes}
strlcpy.o: ${srcdir}/strlcpy.c ${includes}
${CCOBJ} ${CFLAGS} -c ${srcdir}/strlcpy.c
strnlen.o: ${srcdir}/strnlen.c ${includes}
${CCOBJ} ${CFLAGS} -c ${srcdir}/strnlen.c
daemon.o: ${srcdir}/daemon.c ${includes}
${CCOBJ} ${CFLAGS} -c ${srcdir}/daemon.c

View File

@ -173,6 +173,9 @@ extern size_t strlcpy(char *dst, const char *src, size_t siz);
extern size_t strlcat(char *dst, const char *src, size_t siz);
#endif
/* strn */
extern size_t afs_strnlen(char * buf, size_t len);
/* sys.c */
@ -184,6 +187,10 @@ extern void afs_htonuuid(afsUUID * uuidp);
extern void afs_ntohuuid(afsUUID * uuidp);
extern afs_int32 afs_uuid_create(afsUUID * uuid);
extern u_short afs_uuid_hash(afsUUID * uuid);
#if !defined(KERNEL) && !defined(UKERNEL)
extern int afsUUID_from_string(const char *str, afsUUID * uuid);
extern int afsUUID_to_string(const afsUUID * uuid, char *str, size_t strsz);
#endif
/* volparse.c */
extern afs_int32 volutil_GetPartitionID(char *aname);

View File

@ -292,10 +292,17 @@ initDirPathArray(void)
pathp = dirPathArray[AFSDIR_SERVER_SLVGLOG_FILEPATH_ID];
AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOGS_DIR, AFSDIR_SLVGLOG_FILE);
pathp = dirPathArray[AFSDIR_SERVER_SALSRVLOG_FILEPATH_ID];
AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOGS_DIR, AFSDIR_SALSRVLOG_FILE);
pathp = dirPathArray[AFSDIR_SERVER_SALVAGER_FILEPATH_ID];
AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_SERVER_BIN_DIR,
AFSDIR_SALVAGER_FILE);
pathp = dirPathArray[AFSDIR_SERVER_SALSRV_FILEPATH_ID];
AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_SERVER_BIN_DIR,
AFSDIR_SALSRV_FILE);
pathp = dirPathArray[AFSDIR_SERVER_SLVGLOCK_FILEPATH_ID];
AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOCAL_DIR, AFSDIR_SLVGLOCK_FILE);
@ -368,6 +375,9 @@ initDirPathArray(void)
pathp = dirPathArray[AFSDIR_SERVER_KRB_EXCL_FILEPATH_ID];
AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_SERVER_ETC_DIR, AFSDIR_KRB_EXCL_FILE);
pathp = dirPathArray[AFSDIR_SERVER_FSSTATE_FILEPATH_ID];
AFSDIR_SERVER_FILEPATH(pathp, AFSDIR_LOCAL_DIR, AFSDIR_FSSTATE_FILE);
/* client file paths */
#ifdef AFS_NT40_ENV
strcpy(dirPathArray[AFSDIR_CLIENT_THISCELL_FILEPATH_ID],

View File

@ -135,7 +135,9 @@ ConstructLocalLogPath(const char *cpath,
#define AFSDIR_VLOG_FILE "VLLog"
#define AFSDIR_CORE_FILE "core"
#define AFSDIR_SLVGLOG_FILE "SalvageLog"
#define AFSDIR_SALSRVLOG_FILE "SalsrvLog"
#define AFSDIR_SALVAGER_FILE "salvager"
#define AFSDIR_SALSRV_FILE "salvageserver"
#define AFSDIR_SLVGLOCK_FILE "salvage.lock"
#define AFSDIR_BOZCONF_FILE "BosConfig"
#define AFSDIR_BOZCONFNEW_FILE "BosConfig.new"
@ -155,6 +157,8 @@ ConstructLocalLogPath(const char *cpath,
#define AFSDIR_FILELOG_FILE "FileLog"
#define AFSDIR_MIGRATE_LOGNAME "wtlog."
#define AFSDIR_FSSTATE_FILE "fsstate.dat"
#define AFSDIR_CELLSERVDB_FILE_NTCLIENT "afsdcell.ini"
#define AFSDIR_NETINFO_FILE "NetInfo"
@ -194,9 +198,15 @@ AFSDIR_CANONICAL_SERVER_AFS_DIRPATH "/local"
#define AFSDIR_CANONICAL_SERVER_SALVAGER_FILEPATH \
AFSDIR_CANONICAL_SERVER_BIN_DIRPATH "/" AFSDIR_SALVAGER_FILE
#define AFSDIR_CANONICAL_SERVER_SALSRV_FILEPATH \
AFSDIR_CANONICAL_SERVER_BIN_DIRPATH "/" AFSDIR_SALSRV_FILE
#define AFSDIR_CANONICAL_SERVER_SLVGLOG_FILEPATH \
AFSDIR_CANONICAL_SERVER_LOGS_DIRPATH "/" AFSDIR_SLVGLOG_FILE
#define AFSDIR_CANONICAL_SERVER_SALSRVLOG_FILEPATH \
AFSDIR_CANONICAL_SERVER_LOGS_DIRPATH "/" AFSDIR_SALSRVLOG_FILE
/* --------------------- Local path macros ---------------------- */
@ -264,6 +274,9 @@ typedef enum afsdir_id {
AFSDIR_SERVER_BIN_FILE_DIRPATH_ID,
AFSDIR_CLIENT_CELLALIAS_FILEPATH_ID,
AFSDIR_SERVER_KRB_EXCL_FILEPATH_ID,
AFSDIR_SERVER_SALSRV_FILEPATH_ID,
AFSDIR_SERVER_SALSRVLOG_FILEPATH_ID,
AFSDIR_SERVER_FSSTATE_FILEPATH_ID,
AFSDIR_PATHSTRING_MAX } afsdir_id_t;
/* getDirPath() returns a pointer to a string from an internal array of path strings
@ -310,7 +323,9 @@ const char *getDirPath(afsdir_id_t string_id);
#define AFSDIR_SERVER_VLOG_FILEPATH getDirPath(AFSDIR_SERVER_VLOG_FILEPATH_ID)
#define AFSDIR_SERVER_CORELOG_FILEPATH getDirPath(AFSDIR_SERVER_CORELOG_FILEPATH_ID)
#define AFSDIR_SERVER_SLVGLOG_FILEPATH getDirPath(AFSDIR_SERVER_SLVGLOG_FILEPATH_ID)
#define AFSDIR_SERVER_SALSRVLOG_FILEPATH getDirPath(AFSDIR_SERVER_SALSRVLOG_FILEPATH_ID)
#define AFSDIR_SERVER_SALVAGER_FILEPATH getDirPath(AFSDIR_SERVER_SALVAGER_FILEPATH_ID)
#define AFSDIR_SERVER_SALSRV_FILEPATH getDirPath(AFSDIR_SERVER_SALSRV_FILEPATH_ID)
#define AFSDIR_SERVER_BOZCONF_FILEPATH getDirPath(AFSDIR_SERVER_BOZCONF_FILEPATH_ID)
#define AFSDIR_SERVER_BOZCONFNEW_FILEPATH getDirPath(AFSDIR_SERVER_BOZCONFNEW_FILEPATH_ID)
#define AFSDIR_SERVER_BOZINIT_FILEPATH getDirPath(AFSDIR_SERVER_BOZINIT_FILEPATH_ID)
@ -332,6 +347,7 @@ const char *getDirPath(afsdir_id_t string_id);
#define AFSDIR_SERVER_THRESHOLD_CONSTANTS_FILEPATH getDirPath(AFSDIR_SERVER_THRESHOLD_CONSTANTS_FILEPATH_ID)
#define AFSDIR_SERVER_MIGRATELOG_FILEPATH getDirPath(AFSDIR_SERVER_MIGRATELOG_FILEPATH_ID)
#define AFSDIR_SERVER_KRB_EXCL_FILEPATH getDirPath(AFSDIR_SERVER_KRB_EXCL_FILEPATH_ID)
#define AFSDIR_SERVER_FSSTATE_FILEPATH getDirPath(AFSDIR_SERVER_FSSTATE_FILEPATH_ID)
/* client file paths */
#define AFSDIR_CLIENT_THISCELL_FILEPATH getDirPath(AFSDIR_CLIENT_THISCELL_FILEPATH_ID)

View File

@ -126,7 +126,9 @@ extern int
#define AFSDIR_VLOG_FILE "VLLog"
#define AFSDIR_CORE_FILE "core"
#define AFSDIR_SLVGLOG_FILE "SalvageLog"
#define AFSDIR_SALSRVLOG_FILE "SalsrvLog"
#define AFSDIR_SALVAGER_FILE "salvager"
#define AFSDIR_SALSRV_FILE "salvageserver"
#define AFSDIR_SLVGLOCK_FILE "salvage.lock"
#define AFSDIR_BOZCONF_FILE "BosConfig"
#define AFSDIR_BOZCONFNEW_FILE "BosConfig.new"
@ -146,6 +148,8 @@ extern int
#define AFSDIR_FILELOG_FILE "FileLog"
#define AFSDIR_MIGRATE_LOGNAME "wtlog."
#define AFSDIR_FSSTATE_FILE "fsstate.dat"
#ifdef COMMENT
#define AFSDIR_CELLSERVDB_FILE_NTCLIENT "afsdcell.ini"
#else
@ -189,9 +193,15 @@ AFSDIR_LOCAL_DIR
#define AFSDIR_CANONICAL_SERVER_SALVAGER_FILEPATH \
AFSDIR_CANONICAL_SERVER_BIN_DIRPATH "/" AFSDIR_SALVAGER_FILE
#define AFSDIR_CANONICAL_SERVER_SALSRV_FILEPATH \
AFSDIR_CANONICAL_SERVER_BIN_DIRPATH "/" AFSDIR_SALSRV_FILE
#define AFSDIR_CANONICAL_SERVER_SLVGLOG_FILEPATH \
AFSDIR_CANONICAL_SERVER_LOGS_DIRPATH "/" AFSDIR_SLVGLOG_FILE
#define AFSDIR_CANONICAL_SERVER_SALSRVLOG_FILEPATH \
AFSDIR_CANONICAL_SERVER_LOGS_DIRPATH "/" AFSDIR_SALSRVLOG_FILE
/* --------------------- Local path macros ---------------------- */
@ -259,6 +269,9 @@ typedef enum afsdir_id {
AFSDIR_SERVER_BIN_FILE_DIRPATH_ID,
AFSDIR_CLIENT_CELLALIAS_FILEPATH_ID,
AFSDIR_SERVER_KRB_EXCL_FILEPATH_ID,
AFSDIR_SERVER_SALSRV_FILEPATH_ID,
AFSDIR_SERVER_SALSRVLOG_FILEPATH_ID,
AFSDIR_SERVER_FSSTATE_FILEPATH_ID,
AFSDIR_PATHSTRING_MAX
} afsdir_id_t;
@ -306,7 +319,9 @@ const char *getDirPath(afsdir_id_t string_id);
#define AFSDIR_SERVER_VLOG_FILEPATH getDirPath(AFSDIR_SERVER_VLOG_FILEPATH_ID)
#define AFSDIR_SERVER_CORELOG_FILEPATH getDirPath(AFSDIR_SERVER_CORELOG_FILEPATH_ID)
#define AFSDIR_SERVER_SLVGLOG_FILEPATH getDirPath(AFSDIR_SERVER_SLVGLOG_FILEPATH_ID)
#define AFSDIR_SERVER_SALSRVLOG_FILEPATH getDirPath(AFSDIR_SERVER_SALSRVLOG_FILEPATH_ID)
#define AFSDIR_SERVER_SALVAGER_FILEPATH getDirPath(AFSDIR_SERVER_SALVAGER_FILEPATH_ID)
#define AFSDIR_SERVER_SALSRV_FILEPATH getDirPath(AFSDIR_SERVER_SALSRV_FILEPATH_ID)
#define AFSDIR_SERVER_BOZCONF_FILEPATH getDirPath(AFSDIR_SERVER_BOZCONF_FILEPATH_ID)
#define AFSDIR_SERVER_BOZCONFNEW_FILEPATH getDirPath(AFSDIR_SERVER_BOZCONFNEW_FILEPATH_ID)
#define AFSDIR_SERVER_BOZINIT_FILEPATH getDirPath(AFSDIR_SERVER_BOZINIT_FILEPATH_ID)
@ -328,6 +343,7 @@ const char *getDirPath(afsdir_id_t string_id);
#define AFSDIR_SERVER_THRESHOLD_CONSTANTS_FILEPATH getDirPath(AFSDIR_SERVER_THRESHOLD_CONSTANTS_FILEPATH_ID)
#define AFSDIR_SERVER_MIGRATELOG_FILEPATH getDirPath(AFSDIR_SERVER_MIGRATELOG_FILEPATH_ID)
#define AFSDIR_SERVER_KRB_EXCL_FILEPATH getDirPath(AFSDIR_SERVER_KRB_EXCL_FILEPATH_ID)
#define AFSDIR_SERVER_FSSTATE_FILEPATH getDirPath(AFSDIR_SERVER_FSSTATE_FILEPATH_ID)
/* client file paths */
#define AFSDIR_CLIENT_THISCELL_FILEPATH getDirPath(AFSDIR_CLIENT_THISCELL_FILEPATH_ID)

View File

@ -50,6 +50,7 @@
* to THIS server to find out where */
#define VIO 112 /* Vnode temporarily unaccessible, but not known
* to be permanently bad. */
#define VSALVAGING 113 /* Volume is being salvaged (demand attach fs) */
#define VRESTRICTED 120 /* Volume is restricted from using one or more
* of the given residencies; do a
* vos examine to find out the current

35
src/util/strnlen.c Normal file
View File

@ -0,0 +1,35 @@
/*
* Copyright 2006, Sine Nomine Associates 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
*/
/* strnlen.c - fixed length string length */
#include <afsconfig.h>
#include <afs/param.h>
RCSID
("$Header$");
#include <sys/types.h>
#include <stdarg.h>
#include <ctype.h>
size_t
afs_strnlen(char * buf, size_t len)
{
size_t i;
for (i = 0; i < len; i++) {
if (buf[i] == '\0')
break;
}
return i;
}

View File

@ -50,6 +50,7 @@ headers=${TOP_INCDIR}/lwp.h \
${TOP_INCDIR}/afs/afsint.h \
viced.h \
host.h \
callback.h \
fs_stats.h
objects=viced.o \

View File

@ -5,6 +5,8 @@
# License. For details, see the LICENSE file in the top-level source
# directory or online at http://www.openafs.org/dl/license10.html
AFSDEV_AUXCDEFINES = -DFSSYNC_BUILD_SERVER
RELDIR=viced
!INCLUDE ..\config\NTMakefile.$(SYS_NAME)
!INCLUDE ..\config\NTMakefile.version

View File

@ -112,6 +112,7 @@ RCSID
#include "viced_prototypes.h"
#include "viced.h"
#include "host.h"
#include "callback.h"
#include <afs/unified_afs.h>
#include <afs/audit.h>
#include <afs/afsutil.h>
@ -209,7 +210,7 @@ extern afs_int32 readonlyServer;
/*
* Externals used by the xstat code.
*/
extern int VolumeCacheSize, VolumeGets, VolumeReplacements;
extern VolPkgStats VStats;
extern int CEs, CEBlocks;
extern int HTs, HTBlocks;
@ -438,7 +439,7 @@ static afs_int32
CheckVnode(AFSFid * fid, Volume ** volptr, Vnode ** vptr, int lock)
{
int fileCode = 0;
int errorCode = -1;
afs_int32 local_errorCode, errorCode = -1;
static struct timeval restartedat = { 0, 0 };
if (fid->Volume == 0 || fid->Vnode == 0) /* not: || fid->Unique == 0) */
@ -448,7 +449,7 @@ CheckVnode(AFSFid * fid, Volume ** volptr, Vnode ** vptr, int lock)
while (1) {
errorCode = 0;
*volptr = VGetVolume(&errorCode, (afs_int32) fid->Volume);
*volptr = VGetVolume(&local_errorCode, &errorCode, (afs_int32) fid->Volume);
if (!errorCode) {
assert(*volptr);
break;
@ -525,8 +526,10 @@ CheckVnode(AFSFid * fid, Volume ** volptr, Vnode ** vptr, int lock)
}
}
}
/* allow read operations on busy volume */
else if (errorCode == VBUSY && lock == READ_LOCK) {
/* allow read operations on busy volume.
* must check local_errorCode because demand attach fs
* can have local_errorCode == VSALVAGING, errorCode == VBUSY */
else if (local_errorCode == VBUSY && lock == READ_LOCK) {
errorCode = 0;
break;
} else if (errorCode)
@ -1151,6 +1154,8 @@ CopyOnWrite(Vnode * targetptr, Volume * volptr)
wrlen, errno));
#ifdef FAST_RESTART /* if running in no-salvage, don't core the server */
ViceLog(0, ("CopyOnWrite failed: taking volume offline\n"));
#elif defined(AFS_DEMAND_ATTACH_FS)
ViceLog(0, ("CopyOnWrite failed: requesting salvage\n"));
#else /* Avoid further corruption and try to get a core. */
assert(0);
#endif
@ -5564,7 +5569,7 @@ SRXAFS_XStatsVersion(struct rx_call * a_call, afs_int32 * a_versionP)
static void
FillPerfValues(struct afs_PerfStats *a_perfP)
{ /*FillPerfValues */
afs_uint32 hi, lo;
int dir_Buffers; /*# buffers in use by dir package */
int dir_Calls; /*# read calls in dir package */
int dir_IOs; /*# I/O ops in dir package */
@ -5582,9 +5587,11 @@ FillPerfValues(struct afs_PerfStats *a_perfP)
a_perfP->vcache_S_Gets = VnodeClassInfo[vSmall].gets;
a_perfP->vcache_S_Reads = VnodeClassInfo[vSmall].reads;
a_perfP->vcache_S_Writes = VnodeClassInfo[vSmall].writes;
a_perfP->vcache_H_Entries = VolumeCacheSize;
a_perfP->vcache_H_Gets = VolumeGets;
a_perfP->vcache_H_Replacements = VolumeReplacements;
a_perfP->vcache_H_Entries = VStats.hdr_cache_size;
SplitInt64(VStats.hdr_gets, hi, lo);
a_perfP->vcache_H_Gets = lo;
SplitInt64(VStats.hdr_loads, hi, lo);
a_perfP->vcache_H_Replacements = lo;
/*
* Directory section.

File diff suppressed because it is too large Load Diff

158
src/viced/callback.h Normal file
View File

@ -0,0 +1,158 @@
/*
* 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
*
* Portions Copyright (c) 2006 Sine Nomine Associates
*/
#ifndef _AFS_VICED_CALLBACK_H
#define _AFS_VICED_CALLBACK_H
/* Maximum number of call backs to break at once, single fid
* There is some debate as to just how large this value should be
* Ideally, it would be very very large, but I am afraid that the
* cache managers will all send in their responses simultaneously,
* thereby swamping the file server. As a result, something like
* 10 or 15 might be a better bet.
*/
#define MAX_CB_HOSTS 10
/* max time to break a callback, otherwise client is dead or net is hosed */
#define MAXCBT 25
#define u_byte unsigned char
struct cbcounters {
afs_int32 DeleteFiles;
afs_int32 DeleteCallBacks;
afs_int32 BreakCallBacks;
afs_int32 AddCallBacks;
afs_int32 GotSomeSpaces;
afs_int32 DeleteAllCallBacks;
afs_int32 nFEs, nCBs, nblks;
afs_int32 CBsTimedOut;
afs_int32 nbreakers;
afs_int32 GSS1, GSS2, GSS3, GSS4, GSS5;
};
extern struct cbcounters cbstuff;
struct cbstruct {
struct host *hp;
afs_uint32 thead;
};
/* structure MUST be multiple of 8 bytes, otherwise the casts to
* struct object will have alignment issues on *P64 userspaces */
struct FileEntry {
afs_uint32 vnode;
afs_uint32 unique;
afs_uint32 volid;
afs_uint32 fnext; /* index of next FE in hash chain */
afs_uint32 ncbs; /* number of callbacks for this FE */
afs_uint32 firstcb; /* index of first cb in per-FE list */
afs_uint32 status; /* status bits for this FE */
afs_uint32 spare;
};
#define FE_LATER 0x1
/* structure MUST be multiple of 8 bytes, otherwise the casts to
* struct object will have alignment issues on *P64 userspaces */
struct CallBack {
afs_uint32 cnext; /* index of next cb in per-FE list */
afs_uint32 fhead; /* index of associated FE */
u_byte thead; /* Head of timeout chain */
u_byte status; /* Call back status; see definitions, below */
unsigned short spare; /* ensure proper alignment */
afs_uint32 hhead; /* Head of host table chain */
afs_uint32 tprev, tnext; /* per-timeout circular list of callbacks */
afs_uint32 hprev, hnext; /* per-host circular list of callbacks */
};
struct VCBParams {
struct cbstruct cba[MAX_CB_HOSTS]; /* re-entrant storage */
unsigned int ncbas;
afs_uint32 thead; /* head of timeout queue for youngest callback */
struct AFSFid *fid;
};
/* callback hash macros */
#define FEHASH_SIZE 512 /* Power of 2 */
#define FEHASH_MASK (FEHASH_SIZE-1)
#define FEHash(volume, unique) (((volume)+(unique))&(FEHASH_MASK))
#define CB_NUM_TIMEOUT_QUEUES 128
/* status values for status field of CallBack structure */
#define CB_NORMAL 1 /* Normal call back */
#define CB_DELAYED 2 /* Delayed call back due to rpc problems.
* The call back entry will be added back to the
* host list at the END of the list, so that
* searching backwards in the list will find all
* the (consecutive)host. delayed call back entries */
#define CB_VOLUME 3 /* Callback for a volume */
#define CB_BULK 4 /* Normal callbacks, handed out from FetchBulkStatus */
/* call back indices to pointers, and vice-versa */
#define itocb(i) ((i)?CB+(i):0)
#define cbtoi(cbp) (!(cbp)?0:(cbp)-CB)
/* file entry indices to pointers, and vice-versa */
#define itofe(i) ((i)?FE+(i):0)
#define fetoi(fep) (!(fep)?0:(fep)-FE)
/* Timeouts: there are 128 possible timeout values in effect at any
* given time. Each timeout represents timeouts in an interval of 128
* seconds. So the maximum timeout for a call back is 128*128=16384
* seconds, or 4 1/2 hours. The timeout cleanup stuff is called only
* if space runs out or by the file server every 5 minutes. This 5
* minute slack should be allowed for--so a maximum time of 4 hours
* is safer.
*
* Timeouts must be chosen to correspond to an exact multiple
* of 128, because all times are truncated to a 128 multiple, and
* timed out if the current truncated time is <= to the truncated time
* corresponding to the timeout queue.
*/
/* Unix time to Call Back time, and vice-versa. Call back time is
in units of 128 seconds, corresponding to time queues. */
#define CBtime(uxtime) ((uxtime)>>7)
#define UXtime(cbtime) ((cbtime)<<7)
/* Given a Unix time, compute the closest Unix time that corresponds to
a time queue, rounding up */
#define TimeCeiling(uxtime) (((uxtime)+127)&~127)
#define TimeOutCutoff ((sizeof(TimeOuts)/sizeof(TimeOuts[0]))*8)
#define TimeOut(nusers) ((nusers)>=TimeOutCutoff? MinTimeOut: TimeOuts[(nusers)>>3])
/* time out at server is 3 minutes more than ws */
#define ServerBias (3*60)
/* Convert cbtime to timeout queue index */
#define TIndex(cbtime) (((cbtime)&127)+1)
/* Convert cbtime to pointer to timeout queue head */
#define THead(cbtime) (&timeout[TIndex(cbtime)-1])
/* Normalize index into timeout array so that two such indices will be
ordered correctly, so that they can be compared to see which times
sooner, or so that the difference in time out times between them
can be computed. */
#define TNorm(index) ((index)<TIndex(tfirst)?(index)+128:(index))
/* This converts a timeout index into the actual time it will expire */
#define TIndexToTime(index) (UXtime(TNorm(index) - TIndex(tfirst) + tfirst))
/* Convert pointer to timeout queue head to index, and vice versa */
#define ttoi(t) ((t-timeout)+1)
#define itot(i) ((timeout)+(i-1))
#endif /* _AFS_VICED_CALLBACK_H */

View File

@ -5,6 +5,8 @@
* 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
*
* Portions Copyright (c) 2006 Sine Nomine Associates
*/
#include <afsconfig.h>
@ -59,7 +61,11 @@ RCSID
#include "viced_prototypes.h"
#include "viced.h"
#include "host.h"
#include "callback.h"
#ifdef AFS_DEMAND_ATTACH_FS
#include "../util/afsutil_prototypes.h"
#include "../tviced/serialize_state.h"
#endif /* AFS_DEMAND_ATTACH_FS */
#ifdef AFS_PTHREAD_ENV
pthread_mutex_t host_glock_mutex;
@ -83,6 +89,13 @@ int hostCount = 0; /* number of hosts in hostList */
int rxcon_ident_key;
int rxcon_client_key;
static struct rx_securityClass *sc = NULL;
static void h_SetupCallbackConn_r(struct host * host);
static void h_AddHostToHashTable_r(afs_uint32 addr, afs_uint16 port, struct host * host);
static void h_AddHostToUuidHashTable_r(afsUUID * uuid, struct host * host);
static int h_DeleteHostFromHashTableByAddr_r(afs_uint32 addr, afs_uint16 port, struct host *host);
#define CESPERBLOCK 73
struct CEBlock { /* block of CESPERBLOCK file entries */
struct client entry[CESPERBLOCK];
@ -232,9 +245,9 @@ GetHT()
{
register struct host *entry;
if (HTFree == 0)
if (HTFree == NULL)
GetHTBlock();
assert(HTFree != 0);
assert(HTFree != NULL);
entry = HTFree;
HTFree = entry->next;
HTs++;
@ -448,7 +461,7 @@ h_gethostcps_r(register struct host *host, register afs_int32 now)
free(host->hcps.prlist_val); /* this is for hostaclRefresh */
host->hcps.prlist_val = NULL;
host->hcps.prlist_len = 0;
slept ? (host->cpsCall = FT_ApproxTime()) : (host->cpsCall = now);
host->cpsCall = slept ? (FT_ApproxTime()) : (now);
H_UNLOCK;
code = pr_GetHostCPS(ntohl(host->host), &host->hcps);
@ -533,7 +546,6 @@ h_Alloc_r(register struct rx_connection *r_con)
{
struct servent *serverentry;
struct host *host;
static struct rx_securityClass *sc = 0;
afs_int32 now;
#if FS_STATS_DETAILED
afs_uint32 newHostAddr_HBO; /*New host IP addr, in host byte order */
@ -544,7 +556,7 @@ h_Alloc_r(register struct rx_connection *r_con)
host->host = rxr_HostOf(r_con);
host->port = rxr_PortOf(r_con);
hashInsert_r(host->host, host->port, host);
h_AddHostToHashTable_r(host->host, host->port, host);
if (consolePort == 0) { /* find the portal number for console */
#if defined(AFS_OSF_ENV)
@ -561,24 +573,17 @@ h_Alloc_r(register struct rx_connection *r_con)
host->Console = 1;
/* Make a callback channel even for the console, on the off chance that it
* makes a request that causes a break call back. It shouldn't. */
{
if (!sc)
sc = rxnull_NewClientSecurityObject();
host->callback_rxcon =
rx_NewConnection(host->host, host->port, 1, sc, 0);
rx_SetConnDeadTime(host->callback_rxcon, 50);
rx_SetConnHardDeadTime(host->callback_rxcon, AFS_HARDDEADTIME);
}
h_SetupCallbackConn_r(host);
now = host->LastCall = host->cpsCall = host->ActiveCall = FT_ApproxTime();
host->hostFlags = 0;
host->hcps.prlist_val = NULL;
host->hcps.prlist_len = 0;
host->interface = 0;
host->interface = NULL;
#ifdef undef
host->hcpsfailed = 0; /* save cycles */
h_gethostcps(host); /* do this under host hold/lock */
#endif
host->FirstClient = 0;
host->FirstClient = NULL;
h_Hold_r(host);
h_Lock_r(host);
h_InsertList_r(host); /* update global host List */
@ -596,6 +601,20 @@ h_Alloc_r(register struct rx_connection *r_con)
} /*h_Alloc_r */
/* Make a callback channel even for the console, on the off chance that it
* makes a request that causes a break call back. It shouldn't. */
static void
h_SetupCallbackConn_r(struct host * host)
{
if (!sc)
sc = rxnull_NewClientSecurityObject();
host->callback_rxcon =
rx_NewConnection(host->host, host->port, 1, sc, 0);
rx_SetConnDeadTime(host->callback_rxcon, 50);
rx_SetConnHardDeadTime(host->callback_rxcon, AFS_HARDDEADTIME);
}
/* Lookup a host given an IP address and UDP port number. */
/* hostaddr and hport are in network order */
/* Note: host should be released by caller if 0 == *heldp and non-null */
@ -833,7 +852,7 @@ h_FreeConnection(struct rx_connection *tcon)
if (client) {
H_LOCK;
if (client->tcon == tcon)
client->tcon = (struct rx_connection *)0;
client->tcon = NULL;
H_UNLOCK;
}
return 0;
@ -878,8 +897,11 @@ h_Enumerate(int (*proc) (), char *param)
H_UNLOCK;
for (i = 0; i < count; i++) {
held[i] = (*proc) (list[i], held[i], param);
if (!held[i])
if (!H_ENUMERATE_ISSET_HELD(held[i]))
h_Release(list[i]); /* this might free up the host */
/* bail out of the enumeration early */
if (H_ENUMERATE_ISSET_BAIL(held[i]))
break;
}
free((void *)list);
free((void *)held);
@ -908,17 +930,19 @@ h_Enumerate_r(int (*proc) (), struct host *enumstart, char *param)
h_Hold_r(enumstart);
for (host = enumstart; host; host = next, held = nheld) {
next = host->next;
if (next && !(nheld = h_Held_r(next)))
if (next && !(nheld = h_Held_r(next)) && !H_ENUMERATE_ISSET_BAIL(held))
h_Hold_r(next);
held = (*proc) (host, held, param);
if (!held)
if (!H_ENUMERATE_ISSET_HELD(held))
h_Release_r(host); /* this might free up the host */
if (H_ENUMERATE_ISSET_BAIL(held))
break;
}
} /*h_Enumerate_r */
/* inserts a new HashChain structure corresponding to this UUID */
void
hashInsertUuid_r(struct afsUUID *uuid, struct host *host)
static void
h_AddHostToUuidHashTable_r(struct afsUUID *uuid, struct host *host)
{
int index;
struct h_hashChain *chain;
@ -929,7 +953,7 @@ hashInsertUuid_r(struct afsUUID *uuid, struct host *host)
/* insert into beginning of list for this bucket */
chain = (struct h_hashChain *)malloc(sizeof(struct h_hashChain));
if (!chain) {
ViceLog(0, ("Failed malloc in hashInsertUuid_r\n"));
ViceLog(0, ("Failed malloc in h_AddHostToUuidHashTable_r\n"));
assert(0);
}
assert(chain);
@ -940,8 +964,8 @@ hashInsertUuid_r(struct afsUUID *uuid, struct host *host)
/* inserts a new HashChain structure corresponding to this address */
void
hashInsert_r(afs_uint32 addr, afs_uint16 port, struct host *host)
static void
h_AddHostToHashTable_r(afs_uint32 addr, afs_uint16 port, struct host *host)
{
int index;
struct h_hashChain *chain;
@ -952,7 +976,7 @@ hashInsert_r(afs_uint32 addr, afs_uint16 port, struct host *host)
/* insert into beginning of list for this bucket */
chain = (struct h_hashChain *)malloc(sizeof(struct h_hashChain));
if (!chain) {
ViceLog(0, ("Failed malloc in hashInsert_r\n"));
ViceLog(0, ("Failed malloc in h_AddHostToHashTable_r\n"));
assert(0);
}
chain->hostPtr = host;
@ -1017,7 +1041,7 @@ addInterfaceAddr_r(struct host *host, afs_uint32 addr, afs_uint16 port)
/*
* Create a hash table entry for this address
*/
hashInsert_r(addr, port, host);
h_AddHostToHashTable_r(addr, port, host);
return 0;
}
@ -1072,7 +1096,7 @@ removeInterfaceAddr_r(struct host *host, afs_uint32 addr, afs_uint16 port)
/*
* Remove the hash table entry for this address
*/
hashDelete_r(addr, port, host);
h_DeleteHostFromHashTableByAddr_r(addr, port, host);
return 0;
}
@ -1394,7 +1418,7 @@ h_GetHost_r(struct rx_connection *tcon)
/* the new host is held and locked */
} else {
/* This really is a new host */
hashInsertUuid_r(&identP->uuid, host);
h_AddHostToUuidHashTable_r(&identP->uuid, host);
cb_conn = host->callback_rxcon;
rx_GetConnection(cb_conn);
H_UNLOCK;
@ -1735,7 +1759,7 @@ h_FindClient_r(struct rx_connection *tcon)
client->authClass = authClass; /* rx only */
client->sid = rxr_CidOf(tcon);
client->VenusEpoch = rxr_GetEpoch(tcon);
client->CPS.prlist_val = 0;
client->CPS.prlist_val = NULL;
client->CPS.prlist_len = 0;
h_Unlock_r(host);
}
@ -2134,6 +2158,540 @@ h_DumpHosts()
} /*h_DumpHosts */
#ifdef AFS_DEMAND_ATTACH_FS
/*
* demand attach fs
* host state serialization
*/
static int h_stateFillHeader(struct host_state_header * hdr);
static int h_stateCheckHeader(struct host_state_header * hdr);
static int h_stateAllocMap(struct fs_dump_state * state);
static int h_stateSaveHost(register struct host * host, int held, struct fs_dump_state * state);
static int h_stateRestoreHost(struct fs_dump_state * state);
static int h_stateRestoreIndex(struct host * h, int held, struct fs_dump_state * state);
static int h_stateVerifyHost(struct host * h, int held, struct fs_dump_state * state);
static int h_stateVerifyAddrHash(struct fs_dump_state * state, struct host * h, afs_uint32 addr, afs_uint16 port);
static int h_stateVerifyUuidHash(struct fs_dump_state * state, struct host * h);
static void h_hostToDiskEntry_r(struct host * in, struct hostDiskEntry * out);
static void h_diskEntryToHost_r(struct hostDiskEntry * in, struct host * out);
/* this procedure saves all host state to disk for fast startup */
int
h_stateSave(struct fs_dump_state * state)
{
AssignInt64(state->eof_offset, &state->hdr->h_offset);
/* XXX debug */
ViceLog(0, ("h_stateSave: hostCount=%d\n", hostCount));
/* invalidate host state header */
memset(state->h_hdr, 0, sizeof(struct host_state_header));
if (fs_stateWriteHeader(state, &state->hdr->h_offset, state->h_hdr,
sizeof(struct host_state_header))) {
state->bail = 1;
goto done;
}
fs_stateIncEOF(state, sizeof(struct host_state_header));
h_Enumerate_r(h_stateSaveHost, hostList, (char *)state);
if (state->bail) {
goto done;
}
h_stateFillHeader(state->h_hdr);
/* write the real header to disk */
state->bail = fs_stateWriteHeader(state, &state->hdr->h_offset, state->h_hdr,
sizeof(struct host_state_header));
done:
return state->bail;
}
/* demand attach fs
* host state serialization
*
* this procedure restores all host state from a disk for fast startup
*/
int
h_stateRestore(struct fs_dump_state * state)
{
int i, records;
/* seek to the right position and read in the host state header */
if (fs_stateReadHeader(state, &state->hdr->h_offset, state->h_hdr,
sizeof(struct host_state_header))) {
state->bail = 1;
goto done;
}
/* check the validity of the header */
if (h_stateCheckHeader(state->h_hdr)) {
state->bail = 1;
goto done;
}
records = state->h_hdr->records;
if (h_stateAllocMap(state)) {
state->bail = 1;
goto done;
}
/* iterate over records restoring host state */
for (i=0; i < records; i++) {
if (h_stateRestoreHost(state) != 0) {
state->bail = 1;
break;
}
}
done:
return state->bail;
}
int
h_stateRestoreIndices(struct fs_dump_state * state)
{
h_Enumerate_r(h_stateRestoreIndex, hostList, (char *)state);
return state->bail;
}
static int
h_stateRestoreIndex(struct host * h, int held, struct fs_dump_state * state)
{
if (cb_OldToNew(state, h->cblist, &h->cblist)) {
return H_ENUMERATE_BAIL(held);
}
return held;
}
int
h_stateVerify(struct fs_dump_state * state)
{
h_Enumerate_r(h_stateVerifyHost, hostList, (char *)state);
return state->bail;
}
static int
h_stateVerifyHost(struct host * h, int held, struct fs_dump_state * state)
{
int i;
if (h == NULL) {
ViceLog(0, ("h_stateVerifyHost: error: NULL host pointer in linked list\n"));
return H_ENUMERATE_BAIL(held);
}
if (h->interface) {
for (i = h->interface->numberOfInterfaces-1; i >= 0; i--) {
if (h_stateVerifyAddrHash(state, h, h->interface->interface[i].addr,
h->interface->interface[i].port)) {
state->bail = 1;
}
}
if (h_stateVerifyUuidHash(state, h)) {
state->bail = 1;
}
} else if (h_stateVerifyAddrHash(state, h, h->host, h->port)) {
state->bail = 1;
}
if (cb_stateVerifyHCBList(state, h)) {
state->bail = 1;
}
done:
return held;
}
static int
h_stateVerifyAddrHash(struct fs_dump_state * state, struct host * h, afs_uint32 addr, afs_uint16 port)
{
int ret = 0, found = 0;
struct host *host = NULL;
struct h_hashChain *chain;
int index = h_HashIndex(addr);
char tmp[16];
int chain_len = 0;
for (chain = hostHashTable[index]; chain; chain = chain->next) {
host = chain->hostPtr;
if (host == NULL) {
afs_inet_ntoa_r(addr, tmp);
ViceLog(0, ("h_stateVerifyAddrHash: error: addr hash chain has NULL host ptr (lookup addr %s)\n", tmp));
ret = 1;
goto done;
}
if ((chain->addr == addr) && (chain->port == port)) {
if (host != h) {
ViceLog(0, ("h_stateVerifyAddrHash: warning: addr hash entry points to different host struct (%d, %d)\n",
h->index, host->index));
state->flags.warnings_generated = 1;
}
found = 1;
break;
}
if (chain_len > FS_STATE_H_MAX_ADDR_HASH_CHAIN_LEN) {
ViceLog(0, ("h_stateVerifyAddrHash: error: hash chain length exceeds %d; assuming there's a loop\n",
FS_STATE_H_MAX_ADDR_HASH_CHAIN_LEN));
ret = 1;
goto done;
}
chain_len++;
}
if (!found) {
afs_inet_ntoa_r(addr, tmp);
if (state->mode == FS_STATE_LOAD_MODE) {
ViceLog(0, ("h_stateVerifyAddrHash: error: addr %s not found in hash\n", tmp));
ret = 1;
goto done;
} else {
ViceLog(0, ("h_stateVerifyAddrHash: warning: addr %s not found in hash\n", tmp));
state->flags.warnings_generated = 1;
}
}
done:
return ret;
}
static int
h_stateVerifyUuidHash(struct fs_dump_state * state, struct host * h)
{
int ret = 0, found = 0;
struct host *host = NULL;
struct h_hashChain *chain;
afsUUID * uuidp = &h->interface->uuid;
int index = h_UuidHashIndex(uuidp);
char tmp[40];
int chain_len = 0;
for (chain = hostUuidHashTable[index]; chain; chain = chain->next) {
host = chain->hostPtr;
if (host == NULL) {
afsUUID_to_string(uuidp, tmp, sizeof(tmp));
ViceLog(0, ("h_stateVerifyUuidHash: error: uuid hash chain has NULL host ptr (lookup uuid %s)\n", tmp));
ret = 1;
goto done;
}
if (host->interface &&
afs_uuid_equal(&host->interface->uuid, uuidp)) {
if (host != h) {
ViceLog(0, ("h_stateVerifyUuidHash: warning: uuid hash entry points to different host struct (%d, %d)\n",
h->index, host->index));
state->flags.warnings_generated = 1;
}
found = 1;
goto done;
}
if (chain_len > FS_STATE_H_MAX_UUID_HASH_CHAIN_LEN) {
ViceLog(0, ("h_stateVerifyUuidHash: error: hash chain length exceeds %d; assuming there's a loop\n",
FS_STATE_H_MAX_UUID_HASH_CHAIN_LEN));
ret = 1;
goto done;
}
chain_len++;
}
if (!found) {
afsUUID_to_string(uuidp, tmp, sizeof(tmp));
if (state->mode == FS_STATE_LOAD_MODE) {
ViceLog(0, ("h_stateVerifyUuidHash: error: uuid %s not found in hash\n", tmp));
ret = 1;
goto done;
} else {
ViceLog(0, ("h_stateVerifyUuidHash: warning: uuid %s not found in hash\n", tmp));
state->flags.warnings_generated = 1;
}
}
done:
return ret;
}
/* create the host state header structure */
static int
h_stateFillHeader(struct host_state_header * hdr)
{
hdr->stamp.magic = HOST_STATE_MAGIC;
hdr->stamp.version = HOST_STATE_VERSION;
}
/* check the contents of the host state header structure */
static int
h_stateCheckHeader(struct host_state_header * hdr)
{
int ret=0;
if (hdr->stamp.magic != HOST_STATE_MAGIC) {
ViceLog(0, ("check_host_state_header: invalid state header\n"));
ret = 1;
}
else if (hdr->stamp.version != HOST_STATE_VERSION) {
ViceLog(0, ("check_host_state_header: unknown version number\n"));
ret = 1;
}
return ret;
}
/* allocate the host id mapping table */
static int
h_stateAllocMap(struct fs_dump_state * state)
{
state->h_map.len = state->h_hdr->index_max + 1;
state->h_map.entries = (struct idx_map_entry_t *)
calloc(state->h_map.len, sizeof(struct idx_map_entry_t));
return (state->h_map.entries != NULL) ? 0 : 1;
}
/* function called by h_Enumerate to save a host to disk */
static int
h_stateSaveHost(register struct host * host, int held, struct fs_dump_state * state)
{
int i, if_len=0, hcps_len=0;
struct hostDiskEntry hdsk;
struct host_state_entry_header hdr;
struct Interface * ifp = NULL;
afs_int32 * hcps = NULL;
struct iovec iov[4];
int iovcnt = 2;
memset(&hdr, 0, sizeof(hdr));
if (state->h_hdr->index_max < host->index) {
state->h_hdr->index_max = host->index;
}
h_hostToDiskEntry_r(host, &hdsk);
if (host->interface) {
if_len = sizeof(struct Interface) +
((host->interface->numberOfInterfaces-1) * sizeof(struct AddrPort));
ifp = (struct Interface *) malloc(if_len);
assert(ifp != NULL);
memcpy(ifp, host->interface, if_len);
hdr.interfaces = host->interface->numberOfInterfaces;
iov[iovcnt].iov_base = (char *) ifp;
iov[iovcnt].iov_len = if_len;
iovcnt++;
}
if (host->hcps.prlist_val) {
hdr.hcps = host->hcps.prlist_len;
hcps_len = hdr.hcps * sizeof(afs_int32);
hcps = (afs_int32 *) malloc(hcps_len);
assert(hcps != NULL);
memcpy(hcps, host->hcps.prlist_val, hcps_len);
iov[iovcnt].iov_base = (char *) hcps;
iov[iovcnt].iov_len = hcps_len;
iovcnt++;
}
if (hdsk.index > state->h_hdr->index_max)
state->h_hdr->index_max = hdsk.index;
hdr.len = sizeof(struct host_state_entry_header) +
sizeof(struct hostDiskEntry) + if_len + hcps_len;
hdr.magic = HOST_STATE_ENTRY_MAGIC;
iov[0].iov_base = (char *) &hdr;
iov[0].iov_len = sizeof(hdr);
iov[1].iov_base = (char *) &hdsk;
iov[1].iov_len = sizeof(struct hostDiskEntry);
if (fs_stateWriteV(state, iov, iovcnt)) {
ViceLog(0, ("h_stateSaveHost: failed to save host %d", host->index));
state->bail = 1;
}
fs_stateIncEOF(state, hdr.len);
state->h_hdr->records++;
done:
if (ifp)
free(ifp);
if (hcps)
free(hcps);
if (state->bail) {
return H_ENUMERATE_BAIL(held);
}
return held;
}
/* restores a host from disk */
static int
h_stateRestoreHost(struct fs_dump_state * state)
{
int ifp_len=0, hcps_len=0, bail=0;
struct host_state_entry_header hdr;
struct hostDiskEntry hdsk;
struct host *host = NULL;
struct Interface *ifp = NULL;
afs_int32 * hcps = NULL;
struct iovec iov[3];
int iovcnt = 1;
if (fs_stateRead(state, &hdr, sizeof(hdr))) {
ViceLog(0, ("h_stateRestoreHost: failed to read host entry header from dump file '%s'\n",
state->fn));
bail = 1;
goto done;
}
if (hdr.magic != HOST_STATE_ENTRY_MAGIC) {
ViceLog(0, ("h_stateRestoreHost: fileserver state dump file '%s' is corrupt.\n",
state->fn));
bail = 1;
goto done;
}
iov[0].iov_base = (char *) &hdsk;
iov[0].iov_len = sizeof(struct hostDiskEntry);
if (hdr.interfaces) {
ifp_len = sizeof(struct Interface) +
((hdr.interfaces-1) * sizeof(struct AddrPort));
ifp = (struct Interface *) malloc(ifp_len);
assert(ifp != NULL);
iov[iovcnt].iov_base = (char *) ifp;
iov[iovcnt].iov_len = ifp_len;
iovcnt++;
}
if (hdr.hcps) {
hcps_len = hdr.hcps * sizeof(afs_int32);
hcps = (afs_int32 *) malloc(hcps_len);
assert(hcps != NULL);
iov[iovcnt].iov_base = (char *) hcps;
iov[iovcnt].iov_len = hcps_len;
iovcnt++;
}
if ((ifp_len + hcps_len + sizeof(hdsk) + sizeof(hdr)) != hdr.len) {
ViceLog(0, ("h_stateRestoreHost: host entry header length fields are inconsistent\n"));
bail = 1;
goto done;
}
if (fs_stateReadV(state, iov, iovcnt)) {
ViceLog(0, ("h_stateRestoreHost: failed to read host entry\n"));
bail = 1;
goto done;
}
if (!hdr.hcps && hdsk.hcps_valid) {
/* valid, zero-length host cps ; does this ever happen? */
hcps = (afs_int32 *) malloc(sizeof(afs_int32));
assert(hcps != NULL);
}
host = GetHT();
assert(host != NULL);
if (ifp) {
host->interface = ifp;
}
if (hcps) {
host->hcps.prlist_val = hcps;
host->hcps.prlist_len = hdr.hcps;
}
h_diskEntryToHost_r(&hdsk, host);
h_SetupCallbackConn_r(host);
if (ifp) {
int i;
for (i = ifp->numberOfInterfaces-1; i >= 0; i--) {
h_AddHostToHashTable_r(ifp->interface[i].addr,
ifp->interface[i].port, host);
}
h_AddHostToUuidHashTable_r(&ifp->uuid, host);
} else {
h_AddHostToHashTable_r(host->host, host->port, host);
}
h_InsertList_r(host);
/* setup host id map entry */
state->h_map.entries[hdsk.index].old_idx = hdsk.index;
state->h_map.entries[hdsk.index].new_idx = host->index;
done:
if (bail) {
if (ifp)
free(ifp);
if (hcps)
free(hcps);
}
return bail;
}
/* serialize a host structure to disk */
static void
h_hostToDiskEntry_r(struct host * in, struct hostDiskEntry * out)
{
out->host = in->host;
out->port = in->port;
out->hostFlags = in->hostFlags;
out->Console = in->Console;
out->hcpsfailed = in->hcpsfailed;
out->LastCall = in->LastCall;
out->ActiveCall = in->ActiveCall;
out->cpsCall = in->cpsCall;
out->cblist = in->cblist;
#ifdef FS_STATS_DETAILED
out->InSameNetwork = in->InSameNetwork;
#endif
/* special fields we save, but are not memcpy'd back on restore */
out->index = in->index;
out->hcps_len = in->hcps.prlist_len;
out->hcps_valid = (in->hcps.prlist_val == NULL) ? 0 : 1;
}
/* restore a host structure from disk */
static void
h_diskEntryToHost_r(struct hostDiskEntry * in, struct host * out)
{
out->host = in->host;
out->port = in->port;
out->hostFlags = in->hostFlags;
out->Console = in->Console;
out->hcpsfailed = in->hcpsfailed;
out->LastCall = in->LastCall;
out->ActiveCall = in->ActiveCall;
out->cpsCall = in->cpsCall;
out->cblist = in->cblist;
#ifdef FS_STATS_DETAILED
out->InSameNetwork = in->InSameNetwork;
#endif
}
/* index translation routines */
int
h_OldToNew(struct fs_dump_state * state, afs_uint32 old, afs_uint32 * new)
{
int ret = 0;
/* hosts use a zero-based index, so old==0 is valid */
if (old >= state->h_map.len) {
ViceLog(0, ("h_OldToNew: index %d is out of range\n", old));
ret = 1;
} else if (state->h_map.entries[old].old_idx != old) { /* sanity check */
ViceLog(0, ("h_OldToNew: index %d points to an invalid host record\n", old));
ret = 1;
} else {
*new = state->h_map.entries[old].new_idx;
}
done:
return ret;
}
#endif /* AFS_DEMAND_ATTACH_FS */
/*
* This counts the number of workstations, the number of active workstations,
@ -2348,13 +2906,23 @@ static struct AFSFid zerofid;
* Since it can serialize them, and pile up, it should be a separate LWP
* from other events.
*/
int
static int
CheckHost(register struct host *host, int held)
{
register struct client *client;
struct rx_connection *cb_conn = NULL;
int code;
#ifdef AFS_DEMAND_ATTACH_FS
/* kill the checkhost lwp ASAP during shutdown */
FS_STATE_RDLOCK;
if (fs_state.mode == FS_MODE_SHUTDOWN) {
FS_STATE_UNLOCK;
return H_ENUMERATE_BAIL(held);
}
FS_STATE_UNLOCK;
#endif
/* Host is held by h_Enumerate */
H_LOCK;
for (client = host->FirstClient; client; client = client->next) {
@ -2455,7 +3023,7 @@ CheckHost(register struct host *host, int held)
* This routine is called roughly every 5 minutes.
*/
void
h_CheckHosts()
h_CheckHosts(void)
{
afs_uint32 now = FT_ApproxTime();
@ -2570,7 +3138,7 @@ initInterfaceAddr_r(struct host *host, struct interfaceAddr *interf)
/* deleted a HashChain structure for this address and host */
/* returns 1 on success */
static int
hashDelete_r(afs_uint32 addr, afs_uint16 port, struct host *host)
h_DeleteHostFromHashTableByAddr_r(afs_uint32 addr, afs_uint16 port, struct host *host)
{
int flag;
register struct h_hashChain **hp, *th;

View File

@ -5,8 +5,13 @@
* 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
*
* Portions Copyright (c) 2006 Sine Nomine Associates
*/
#ifndef _AFS_VICED_HOST_H
#define _AFS_VICED_HOST_H
#include "fs_stats.h" /*File Server stats package */
#ifdef AFS_PTHREAD_ENV
@ -59,6 +64,7 @@ struct Interface {
struct AddrPort interface[1];/* there are actually more than one here */
/* in network byte order */
};
struct host {
struct host *next, *prev; /* linked list of all hosts */
struct rx_connection *callback_rxcon; /* rx callback connection */
@ -85,7 +91,7 @@ struct host {
struct client *FirstClient; /* first connection from host */
afs_uint32 cpsCall; /* time of last cps call from this host */
struct Interface *interface; /* all alternate addr for client */
afs_uint32 cblist; /* Call back list for this host */
afs_uint32 cblist; /* index of a cb in the per-host circular CB list */
/*
* These don't get zeroed, keep them at the end. If index doesn't
* follow an unsigned short then we need to pad to ensure that
@ -142,6 +148,7 @@ struct client {
/* Don't zero the lock */
#define CLIENT_TO_ZERO(C) ((int)(((char *)(&((C)->lock))-(char *)(C))))
/*
* key for the client structure stored in connection specific data
*/
@ -245,6 +252,19 @@ extern void h_CheckHosts();
struct Interface *MultiVerifyInterface_r();
extern int initInterfaceAddr_r(struct host *host, struct interfaceAddr *interf);
#ifdef AFS_DEMAND_ATTACH_FS
/*
* demand attach fs
* state serialization
*/
extern int h_SaveState(void);
extern int h_RestoreState(void);
#endif
#define H_ENUMERATE_BAIL(held) ((held)|0x80000000)
#define H_ENUMERATE_ISSET_BAIL(held) ((held)&0x80000000)
#define H_ENUMERATE_ISSET_HELD(held) ((held)&0x7FFFFFFF)
struct host *(hosttableptrs[h_MAXHOSTTABLES]); /* Used by h_itoh */
#define h_htoi(host) ((host)->index) /* index isn't zeroed, no need to lock */
#define h_itoh(hostindex) (hosttableptrs[(hostindex)>>h_HTSHIFT]+((hostindex)&(h_HTSPERBLOCK-1)))
@ -269,4 +289,4 @@ struct host *(hosttableptrs[h_MAXHOSTTABLES]); /* Used by h_itoh */
#define HFE_LATER 0x80 /* host has FE_LATER callbacks */
#define HERRORTRANS 0x100 /* do error translation */
#endif /* _AFS_VICED_HOST_H */

View File

@ -5,6 +5,8 @@
* 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
*
* Portions Copyright (c) 2006 Sine Nomine Associates
*/
/* viced.c - File Server main loop */
@ -215,6 +217,27 @@ afsUUID FS_HostUUID;
static void FlagMsg();
#ifdef AFS_DEMAND_ATTACH_FS
/*
* demand attach fs
* fileserver mode support
*
* during fileserver shutdown, we have to track the graceful shutdown of
* certain background threads before we are allowed to dump state to
* disk
*/
struct fs_state fs_state =
{ FS_MODE_NORMAL,
0,
0,
0,
0,
{ 1,1,1,1 },
PTHREAD_COND_INITIALIZER,
PTHREAD_RWLOCK_INITIALIZER
};
#endif /* AFS_DEMAND_ATTACH_FS */
/*
* Home for the performance statistics.
*/
@ -420,13 +443,31 @@ FiveMinuteCheckLWP()
ViceLog(1, ("Starting five minute check process\n"));
setThreadId("FiveMinuteCheckLWP");
#ifdef AFS_DEMAND_ATTACH_FS
FS_STATE_WRLOCK;
while (fs_state.mode == FS_MODE_NORMAL) {
fs_state.FiveMinuteLWP_tranquil = 1;
FS_STATE_UNLOCK;
#else
while (1) {
#endif
#ifdef AFS_PTHREAD_ENV
sleep(fiveminutes);
#else /* AFS_PTHREAD_ENV */
IOMGR_Sleep(fiveminutes);
#endif /* AFS_PTHREAD_ENV */
#ifdef AFS_DEMAND_ATTACH_FS
FS_STATE_WRLOCK;
if (fs_state.mode != FS_MODE_NORMAL) {
break;
}
fs_state.FiveMinuteLWP_tranquil = 0;
FS_STATE_UNLOCK;
#endif
/* close the log so it can be removed */
ReOpenLog(AFSDIR_SERVER_FILELOG_FILEPATH); /* don't trunc, just append */
ViceLog(2, ("Cleaning up timed out callbacks\n"));
@ -452,7 +493,17 @@ FiveMinuteCheckLWP()
afs_ctime(&now, tbuffer, sizeof(tbuffer))));
}
}
#ifdef AFS_DEMAND_ATTACH_FS
FS_STATE_WRLOCK;
#endif
}
#ifdef AFS_DEMAND_ATTACH_FS
fs_state.FiveMinuteLWP_tranquil = 1;
FS_LOCK;
assert(pthread_cond_broadcast(&fs_state.worker_done_cv)==0);
FS_UNLOCK;
FS_STATE_UNLOCK;
#endif
} /*FiveMinuteCheckLWP */
@ -460,20 +511,50 @@ FiveMinuteCheckLWP()
* other 5 minute activities because it may be delayed by timeouts when
* it probes the workstations
*/
static void
HostCheckLWP()
{
ViceLog(1, ("Starting Host check process\n"));
setThreadId("HostCheckLWP");
while (1) {
#ifdef AFS_DEMAND_ATTACH_FS
FS_STATE_WRLOCK;
while (fs_state.mode == FS_MODE_NORMAL) {
fs_state.HostCheckLWP_tranquil = 1;
FS_STATE_UNLOCK;
#else
while(1) {
#endif
#ifdef AFS_PTHREAD_ENV
sleep(fiveminutes);
#else /* AFS_PTHREAD_ENV */
IOMGR_Sleep(fiveminutes);
#endif /* AFS_PTHREAD_ENV */
#ifdef AFS_DEMAND_ATTACH_FS
FS_STATE_WRLOCK;
if (fs_state.mode != FS_MODE_NORMAL) {
break;
}
fs_state.HostCheckLWP_tranquil = 0;
FS_STATE_UNLOCK;
#endif
ViceLog(2, ("Checking for dead venii & clients\n"));
h_CheckHosts();
#ifdef AFS_DEMAND_ATTACH_FS
FS_STATE_WRLOCK;
#endif
}
#ifdef AFS_DEMAND_ATTACH_FS
fs_state.HostCheckLWP_tranquil = 1;
FS_LOCK;
assert(pthread_cond_broadcast(&fs_state.worker_done_cv)==0);
FS_UNLOCK;
FS_STATE_UNLOCK;
#endif
} /*HostCheckLWP */
/* This LWP does fsync checks every 5 minutes: it should not be used for
@ -496,7 +577,14 @@ FsyncCheckLWP()
assert(pthread_mutex_init(&fsync_glock_mutex, NULL) == 0);
#endif
while (1) {
#ifdef AFS_DEMAND_ATTACH_FS
FS_STATE_WRLOCK;
while (fs_state.mode == FS_MODE_NORMAL) {
fs_state.FsyncCheckLWP_tranquil = 1;
FS_STATE_UNLOCK;
#else
while(1) {
#endif
FSYNC_LOCK;
#ifdef AFS_PTHREAD_ENV
/* rounding is fine */
@ -513,11 +601,31 @@ FsyncCheckLWP()
ViceLog(0, ("LWP_WaitProcess returned %d\n", code));
#endif /* AFS_PTHREAD_ENV */
FSYNC_UNLOCK;
#ifdef AFS_DEMAND_ATTACH_FS
FS_STATE_WRLOCK;
if (fs_state.mode != FS_MODE_NORMAL) {
break;
}
fs_state.FsyncCheckLWP_tranquil = 0;
FS_STATE_UNLOCK;
#endif /* AFS_DEMAND_ATTACH_FS */
ViceLog(2, ("Checking for fsync events\n"));
do {
code = BreakLaterCallBacks();
} while (code != 0);
#ifdef AFS_DEMAND_ATTACH_FS
FS_STATE_WRLOCK;
#endif
}
#ifdef AFS_DEMAND_ATTACH_FS
fs_state.FsyncCheckLWP_tranquil = 1;
FS_LOCK;
assert(pthread_cond_broadcast(&fs_state.worker_done_cv)==0);
FS_UNLOCK;
FS_STATE_UNLOCK;
#endif /* AFS_DEMAND_ATTACH_FS */
}
/*------------------------------------------------------------------------
@ -604,6 +712,11 @@ PrintCounters()
("Vice was last started at %s\n",
afs_ctime(&StartTime, tbuffer, sizeof(tbuffer))));
#ifdef AFS_DEMAND_ATTACH_FS
/* XXX perhaps set extended stats verbosity flags
* based upon LogLevel ?? */
VPrintExtendedCacheStats(VOL_STATS_PER_CHAIN2);
#endif
VPrintCacheStats();
VPrintDiskStats();
DStat(&dirbuff, &dircall, &dirio);
@ -656,6 +769,16 @@ ShutDownAndCore(int dopanic)
time_t now = time(0);
char tbuffer[32];
/* do not allows new reqests to be served from now on, all new requests
* are returned with an error code of RX_RESTARTING ( transient failure ) */
rx_SetRxTranquil(); /* dhruba */
#ifdef AFS_DEMAND_ATTACH_FS
FS_STATE_WRLOCK;
fs_state.mode = FS_MODE_SHUTDOWN;
FS_STATE_UNLOCK;
#endif
ViceLog(0,
("Shutting down file server at %s",
afs_ctime(&now, tbuffer, sizeof(tbuffer))));
@ -671,11 +794,34 @@ ShutDownAndCore(int dopanic)
if (!dopanic)
PrintCounters();
/* do not allows new reqests to be served from now on, all new requests
* are returned with an error code of RX_RESTARTING ( transient failure ) */
rx_SetRxTranquil(); /* dhruba */
/* shut down volume package */
VShutdown();
#ifdef AFS_DEMAND_ATTACH_FS
if (fs_state.options.fs_state_save) {
/*
* demand attach fs
* save fileserver state to disk */
/* make sure background threads have finished all of their asynchronous
* work on host and callback structures */
FS_STATE_RDLOCK;
while (!fs_state.FiveMinuteLWP_tranquil ||
!fs_state.HostCheckLWP_tranquil ||
!fs_state.FsyncCheckLWP_tranquil) {
FS_LOCK;
FS_STATE_UNLOCK;
ViceLog(0, ("waiting for background host/callback threads to quiesce before saving fileserver state...\n"));
assert(pthread_cond_wait(&fs_state.worker_done_cv, &fileproc_glock_mutex) == 0);
FS_UNLOCK;
FS_STATE_RDLOCK;
}
/* ok. it should now be fairly safe. let's do the state dump */
fs_stateSave();
}
#endif /* AFS_DEMAND_ATTACH_FS */
if (debugFile) {
rx_PrintStats(debugFile);
fflush(debugFile);
@ -715,7 +861,7 @@ ShutDown(void)
static void
FlagMsg()
{
char buffer[1024];
char buffer[2048];
/* default supports help flag */
@ -743,8 +889,18 @@ FlagMsg()
strcat(buffer, "[-rxdbg (enable rx debugging)] ");
strcat(buffer, "[-rxdbge (enable rxevent debugging)] ");
strcat(buffer, "[-rxmaxmtu <bytes>] ");
#if AFS_PTHREAD_ENV
strcat(buffer, "[-vattachpar <number of volume attach threads>] ");
#ifdef AFS_DEMAND_ATTACH_FS
strcat(buffer, "[-fs-state-dont-save (disable state save during shutdown)] ");
strcat(buffer, "[-fs-state-dont-restore (disable state restore during startup)] ");
strcat(buffer, "[-fs-state-verify <none|save|restore|both> (default is both)] ");
strcat(buffer, "[-vattachpar <max number of volume attach/shutdown threads> (default is 1)] ");
strcat(buffer, "[-vhashsize <log(2) of number of volume hash buckets> (default is 8)] ");
strcat(buffer, "[-vlrudisable (disable VLRU functionality)] ");
strcat(buffer, "[-vlruthresh <minutes before unused volumes become eligible for soft detach> (default is 2 hours)] ");
strcat(buffer, "[-vlruinterval <seconds between VLRU scans> (default is 2 minutes)] ");
strcat(buffer, "[-vlrumax <max volumes to soft detach in one VLRU scan> (default is 8)] ");
#elif AFS_PTHREAD_ENV
strcat(buffer, "[-vattachpar <number of volume attach threads> (default is 1)] ");
#endif
#ifdef AFS_AIX32_ENV
strcat(buffer, "[-m <min percentage spare in partition>] ");
@ -945,11 +1101,62 @@ ParseArgs(int argc, char *argv[])
#ifdef AFS_PTHREAD_ENV
} else if (!strcmp(argv[i], "-vattachpar")) {
if ((i + 1) >= argc) {
fprintf(stderr, "missing argument for -vattachpar\n");
fprintf(stderr, "missing argument for %s\n", argv[i]);
return -1;
}
vol_attach_threads = atoi(argv[++i]);
#endif /* AFS_PTHREAD_ENV */
#ifdef AFS_DEMAND_ATTACH_FS
} else if (!strcmp(argv[i], "-fs-state-dont-save")) {
fs_state.options.fs_state_save = 0;
} else if (!strcmp(argv[i], "-fs-state-dont-restore")) {
fs_state.options.fs_state_restore = 0;
} else if (!strcmp(argv[i], "-fs-state-verify")) {
if ((i + 1) >= argc) {
fprintf(stderr, "missing argument for %s\n", argv[i]);
return -1;
}
i++;
if (!strcmp(argv[i], "none")) {
fs_state.options.fs_state_verify_before_save = 0;
fs_state.options.fs_state_verify_after_restore = 0;
} else if (!strcmp(argv[i], "save")) {
fs_state.options.fs_state_verify_after_restore = 0;
} else if (!strcmp(argv[i], "restore")) {
fs_state.options.fs_state_verify_before_save = 0;
} else if (!strcmp(argv[i], "both")) {
/* default */
} else {
fprintf(stderr, "invalid argument for %s\n", argv[i-1]);
return -1;
}
} else if (!strcmp(argv[i], "-vhashsize")) {
if ((i + 1) >= argc) {
fprintf(stderr, "missing argument for %s\n", argv[i]);
return -1;
}
VSetVolHashSize(atoi(argv[++i]));
} else if (!strcmp(argv[i], "-vlrudisable")) {
VLRU_SetOptions(VLRU_SET_ENABLED, 0);
} else if (!strcmp(argv[i], "-vlruthresh")) {
if ((i + 1) >= argc) {
fprintf(stderr, "missing argument for %s\n", argv[i]);
return -1;
}
VLRU_SetOptions(VLRU_SET_THRESH, 60*atoi(argv[++i]));
} else if (!strcmp(argv[i], "-vlruinterval")) {
if ((i + 1) >= argc) {
fprintf(stderr, "missing argument for %s\n", argv[i]);
return -1;
}
VLRU_SetOptions(VLRU_SET_INTERVAL, atoi(argv[++i]));
} else if (!strcmp(argv[i], "-vlrumax")) {
if ((i + 1) >= argc) {
fprintf(stderr, "missing argument for %s\n", argv[i]);
return -1;
}
VLRU_SetOptions(VLRU_SET_MAX, atoi(argv[++i]));
#endif /* AFS_DEMAND_ATTACH_FS */
} else if (!strcmp(argv[i], "-s")) {
Sawsmall = 1;
if ((i + 1) >= argc) {
@ -1923,6 +2130,15 @@ main(int argc, char *argv[])
exit(1);
}
#ifdef AFS_DEMAND_ATTACH_FS
if (fs_state.options.fs_state_restore) {
/*
* demand attach fs
* restore fileserver state */
fs_stateRestore();
}
#endif /* AFS_DEMAND_ATTACH_FS */
/*
* We are done calling fopen/fdopen. It is safe to use a large
* of the file descriptor cache.

View File

@ -5,6 +5,8 @@
* 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
*
* Portions Copyright (c) 2006 Sine Nomine Associates
*/
/* file.h - include file for the File Server */
@ -20,6 +22,9 @@
* Start with clean version to sync test and dev trees.
* */
#ifndef _AFS_VICED_VICED_H
#define _AFS_VICED_VICED_H
#include <afs/afssyscalls.h>
#include <afs/afsutil.h>
#include "fs_stats.h" /*Defs for xstat-based statistics */
@ -46,18 +51,6 @@ typedef struct DirHandle {
} DirHandle;
struct cbcounters {
int DeleteFiles;
int DeleteCallBacks;
int BreakCallBacks;
int AddCallBacks;
int GotSomeSpaces;
int DeleteAllCallBacks;
int nFEs, nCBs, nblks;
int CBsTimedOut;
int nbreakers;
int GSS1, GSS2, GSS3, GSS4, GSS5;
};
#define MAXCNTRS (AFS_HIGHEST_OPCODE+1)
@ -219,3 +212,46 @@ extern pthread_mutex_t fsync_glock_mutex;
#define FSYNC_LOCK
#define FSYNC_UNLOCK
#endif /* AFS_PTHREAD_ENV */
#ifdef AFS_DEMAND_ATTACH_FS
/*
* demand attach fs
* fileserver mode support
*/
struct fs_state {
volatile int mode;
volatile byte FiveMinuteLWP_tranquil; /* five minute check thread is shutdown or sleeping */
volatile byte HostCheckLWP_tranquil; /* host check thread is shutdown or sleeping */
volatile byte FsyncCheckLWP_tranquil; /* fsync check thread is shutdown or sleeping */
volatile byte salvsync_fatal_error; /* fatal error with salvsync comm */
/* some command-line options we use in
* various places
*
* these fields are immutable once we
* go multithreaded */
struct {
byte fs_state_save;
byte fs_state_restore;
byte fs_state_verify_before_save;
byte fs_state_verify_after_restore;
} options;
pthread_cond_t worker_done_cv;
pthread_rwlock_t state_lock;
};
extern struct fs_state fs_state;
/* this lock is defined to be directly above FS_LOCK in the locking hierarchy */
#define FS_STATE_RDLOCK assert(pthread_rwlock_rdlock(&fs_state.state_lock) == 0)
#define FS_STATE_WRLOCK assert(pthread_rwlock_wrlock(&fs_state.state_lock) == 0)
#define FS_STATE_UNLOCK assert(pthread_rwlock_unlock(&fs_state.state_lock) == 0)
#define FS_MODE_NORMAL 0
#define FS_MODE_SHUTDOWN 1
#endif /* AFS_DEMAND_ATTACH_FS */
#endif /* _AFS_VICED_VICED_H */

View File

@ -1,4 +1,27 @@
/*
* 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
*/
#ifndef _AFS_VICED_VICED_PROTOTYPES_H
#define _AFS_VICED_VICED_PROTOTYPES_H
extern int sendBufSize;
afs_int32 sys_error_to_et(afs_int32 in);
void init_sys_error_to_et(void);
#ifdef AFS_DEMAND_ATTACH_FS
/*
* demand attach fs
* fileserver state serialization
*/
extern int fs_stateSave(void);
extern int fs_stateRestore(void);
#endif /* AFS_DEMAND_ATTACH_FS */
#endif /* _AFS_VICED_VICED_PROTOTYPES_H */

View File

@ -16,22 +16,23 @@ LIBS=${TOP_LIBDIR}/libcmd.a vlib.a ${TOP_LIBDIR}/util.a \
${TOP_LIBDIR}/libsys.a ${TOP_LIBDIR}/libdir.a \
${TOP_LIBDIR}/liblwp.a ${TOP_LIBDIR}/libacl.a
CFLAGS = ${COMMON_CFLAGS} -D${SYS_NAME} ${FSINCLUDES} ${XCFLAGS} ${ARCHFLAGS}
CFLAGS = ${COMMON_CFLAGS} -D${SYS_NAME} ${FSINCLUDES} ${XCFLAGS} ${ARCHFLAGS} -DFSSYNC_BUILD_SERVER -DFSSYNC_BUILD_CLIENT
PUBLICHEADERS=nfs.h vnode.h viceinode.h volume.h voldefs.h partition.h\
fssync.h ihandle.h namei_ops.h
PUBLICHEADERS=nfs.h vnode.h viceinode.h volume.h voldefs.h partition.h \
fssync.h ihandle.h namei_ops.h salvsync.h daemon_com.h
VLIBOBJS=vnode.o volume.o vutil.o partition.o fssync.o purge.o \
clone.o nuke.o devname.o listinodes.o common.o ihandle.o \
namei_ops.o
VLIBOBJS=vnode.o volume.o vutil.o partition.o fssync-server.o fssync-client.o \
clone.o nuke.o devname.o listinodes.o common.o ihandle.o purge.o \
namei_ops.o salvsync-server.o salvsync-client.o daemon_com.o
OBJECTS=${VLIBOBJS} physio.o vol-salvage.o vol-info.o vol-dump.o vol-bless.o
OBJECTS=${VLIBOBJS} physio.o vol-salvage.o vol-info.o vol-dump.o vol-bless.o fssync-debug.o
all: gi \
${TOP_LIBDIR}/vlib.a \
${TOP_LIBDIR}/libvlib.a \
salvager \
volinfo \
fssync-debug \
$(FS_CONV_OSF40D) \
$(XFS_SIZE_CHECK) \
$(FS_CONV_SOL26) \
@ -42,6 +43,8 @@ all: gi \
${TOP_INCDIR}/afs/voldefs.h \
${TOP_INCDIR}/afs/partition.h \
${TOP_INCDIR}/afs/fssync.h \
${TOP_INCDIR}/afs/salvsync.h \
${TOP_INCDIR}/afs/daemon_com.h \
${TOP_INCDIR}/afs/ihandle.h \
${TOP_INCDIR}/afs/namei_ops.h
@ -53,6 +56,7 @@ install: \
${DESTDIR}${libdir}/afs/libvlib.a \
${DESTDIR}${afssrvlibexecdir}/salvager \
${DESTDIR}${afssrvsbindir}/volinfo \
${DESTDIR}${afssrvsbindir}/fssync-debug \
$(install_FS_CONV_OSF40D) \
$(install_XFS_SIZE_CHECK) \
$(install_FS_CONV_SOL26) \
@ -63,6 +67,8 @@ install: \
${DESTDIR}${includedir}/afs/voldefs.h \
${DESTDIR}${includedir}/afs/partition.h \
${DESTDIR}${includedir}/afs/fssync.h \
${DESTDIR}${includedir}/afs/salvsync.h \
${DESTDIR}${includedir}/afs/daemon_com.h \
${DESTDIR}${includedir}/afs/ihandle.h \
${DESTDIR}${includedir}/afs/namei_ops.h
@ -72,6 +78,11 @@ ${DEST}/root.server/usr/afs/bin/salvager: salvager
${DEST}/root.server/usr/afs/bin/volinfo: volinfo
${INSTALL} -s $? $@
${DEST}/root.server/usr/afs/bin/fssync-debug: fssync-debug
if test "@DEMAND_ATTACH@" = "no"; then \
${INSTALL} -s $? $@ ; \
fi
${DEST}/lib/afs/vlib.a: vlib.a
${INSTALL} $? $@
@ -117,6 +128,12 @@ ${DEST}/include/afs/partition.h: partition.h
${DEST}/include/afs/fssync.h: fssync.h
${INSTALL} $? $@
${DEST}/include/afs/salvsync.h: salvsync.h
${INSTALL} $? $@
${DEST}/include/afs/daemon_com.h: daemon_com.h
${INSTALL} $? $@
${DEST}/include/afs/ihandle.h: ihandle.h
${INSTALL} $? $@
@ -129,6 +146,8 @@ ${DEST}/include/afs/namei_ops.h: namei_ops.h
${OBJECTS}: ${PUBLICHEADERS} ${TOP_INCDIR}/lwp.h ${TOP_INCDIR}/lock.h ${TOP_INCDIR}/afs/afsint.h vutils.h salvage.h AFS_component_version_number.c
vol-salvage.o vutil.o: volinodes.h
vol-salvage.o salvager.o: vol-salvage.h
vol-salvage.o: salvsync.h daemon_com.h
vlib.a: ${VLIBOBJS} AFS_component_version_number.o
$(RM) -f $@
@ -136,8 +155,8 @@ vlib.a: ${VLIBOBJS} AFS_component_version_number.o
$(RANLIB) $@
# new salvager: remove references to /vice by linking with novice.o
salvager: vol-salvage.o physio.o vlib.a
${CC} ${LDFLAGS} -o salvager vol-salvage.o physio.o ${LIBS} ${XLIBS}
salvager: vol-salvage.o physio.o vlib.a salvager.o ${LIBS}
${CC} ${LDFLAGS} -o salvager vol-salvage.o physio.o salvager.o ${LIBS} ${XLIBS}
vol-salvage: vol-salvage.o
vol-info: vol-info.o physio.o ihandle.o
@ -167,13 +186,16 @@ volinfo: vol-info.o physio.o ihandle.o ${LIBS}
${CC} ${CFLAGS} -o volinfo vol-info.o physio.o \
ihandle.o ${LIBS} ${XLIBS}
fssync-debug: fssync-debug.o physio.o AFS_component_version_number.c ${LIBS}
${CC} ${LDFLAGS} -o fssync-debug fssync-debug.o physio.o ${LIBS} ${XLIBS}
vol-bless: vol-bless.o physio.o ihandle.o ${LIBS}
${CC} ${CFLAGS} -o vol-bless vol-bless.o physio.o ${LIBS} ${XLIBS}
fs_conv_dux40D: fs_conv_411.o
fs_conv_dux40D: fs_conv_411.o ${LIBS}
${CC} ${CFLAGS} ${TOP_LIBDIR}/libcmd.a -o fs_conv_dux40D fs_conv_411.o ${LIBS} ${XLIBS}
fs_conv_sol26: fs_conv_411.o vlib.a
fs_conv_sol26: fs_conv_411.o ${LIBS}
${CC} ${CFLAGS} ${TOP_LIBDIR}/libcmd.a -o fs_conv_sol26 fs_conv_411.o ${LIBS} ${XLIBS}
fs_conv_411.o: fs_conv_411.c AFS_component_version_number.c
@ -211,6 +233,11 @@ ${DESTDIR}${afssrvlibexecdir}/salvager: salvager
${DESTDIR}${afssrvsbindir}/volinfo: volinfo
${INSTALL} -s $? $@
${DESTDIR}${afssrvsbindir}/fssync-debug: fssync-debug
if test "@DEMAND_ATTACH@" = "no" ; then \
${INSTALL} -s $? $@ ; \
fi
${DESTDIR}${includedir}/afs/nfs.h: nfs.h
${INSTALL} $? $@
@ -253,6 +280,18 @@ ${DESTDIR}${includedir}/afs/fssync.h: fssync.h
${TOP_INCDIR}/afs/fssync.h: fssync.h
${INSTALL} $? $@
${DESTDIR}${includedir}/afs/salvsync.h: salvsync.h
${INSTALL} $? $@
${TOP_INCDIR}/afs/salvsync.h: salvsync.h
${INSTALL} $? $@
${DESTDIR}${includedir}/afs/daemon_com.h: daemon_com.h
${INSTALL} $? $@
${TOP_INCDIR}/afs/daemon_com.h: daemon_com.h
${INSTALL} $? $@
${DESTDIR}${includedir}/afs/ihandle.h: ihandle.h
${INSTALL} $? $@
@ -265,11 +304,24 @@ ${DESTDIR}${includedir}/afs/namei_ops.h: namei_ops.h
${TOP_INCDIR}/afs/namei_ops.h: namei_ops.h
${INSTALL} $? $@
${DESTDIR}${includedir}/afs/salvage.h: salvage.h
${INSTALL} $? $@
${TOP_INCDIR}/afs/salvage.h: salvage.h
${INSTALL} $? $@
${DESTDIR}${includedir}/afs/vol-salvage.h: vol-salvage.h
${INSTALL} $? $@
${TOP_INCDIR}/afs/vol-salvage.h: vol-salvage.h
${INSTALL} $? $@
dest: \
${DEST}/lib/afs/vlib.a \
${DEST}/lib/afs/libvlib.a \
${DEST}/root.server/usr/afs/bin/salvager \
${DEST}/root.server/usr/afs/bin/volinfo \
${DEST}/root.server/usr/afs/bin/fssync-debug \
$(dest_FS_CONV_OSF40D) \
$(dest_XFS_SIZE_CHECK) \
$(dest_FS_CONV_SOL26) \
@ -280,12 +332,14 @@ dest: \
${DEST}/include/afs/voldefs.h \
${DEST}/include/afs/partition.h \
${DEST}/include/afs/fssync.h \
${DEST}/include/afs/salvsync.h \
${DEST}/include/afs/daemon_com.h \
${DEST}/include/afs/ihandle.h \
${DEST}/include/afs/namei_ops.h
check-splint::
sh $(HELPER_SPLINT) $(CFLAGS) \
vnode.c volume.c vutil.c partition.c fssync.c purge.c \
vnode.c volume.c vutil.c partition.c fssync-server.c fssync-client.c \
clone.c nuke.c devname.c listinodes.c common.c ihandle.c \
namei_ops.c \
physio.c vol-salvage.c vol-info.c vol-bless.c
namei_ops.c salvsync-server.c salvsync-client.c daemon_com.c purge.c \
physio.c vol-salvage.c vol-info.c vol-bless.c fssync-debug.c

View File

@ -5,6 +5,8 @@
# License. For details, see the LICENSE file in the top-level source
# directory or online at http://www.openafs.org/dl/license10.html
AFSDEV_AUXCDEFINES = -DFSSYNC_BUILD_SERVER -DFSSYNC_BUILD_CLIENT
RELDIR=vol
!INCLUDE ..\config\NTMakefile.$(SYS_NAME)
!INCLUDE ..\config\NTMakefile.version

473
src/vol/daemon_com.c Normal file
View File

@ -0,0 +1,473 @@
/*
* Copyright 2006, Sine Nomine Associates 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
*/
/*
* localhost interprocess communication for servers
*
* currently handled by a localhost socket
* (yes, this needs to be replaced someday)
*/
#ifndef _WIN32
#define FD_SETSIZE 65536
#endif
#include <afsconfig.h>
#include <afs/param.h>
RCSID
("$Header$");
#include <sys/types.h>
#include <stdio.h>
#ifdef AFS_NT40_ENV
#include <winsock2.h>
#include <time.h>
#else
#include <sys/param.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/time.h>
#endif
#include <errno.h>
#include <assert.h>
#include <signal.h>
#ifdef HAVE_STRING_H
#include <string.h>
#else
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif
#endif
#include <rx/xdr.h>
#include <afs/afsint.h>
#include "nfs.h"
#include <afs/errors.h>
#include "daemon_com.h"
#include "lwp.h"
#include "lock.h"
#include <afs/afssyscalls.h>
#include "ihandle.h"
#include "vnode.h"
#include "volume.h"
#include "partition.h"
#include <rx/rx_queue.h>
/*@printflike@*/ extern void Log(const char *format, ...);
#ifdef osi_Assert
#undef osi_Assert
#endif
#define osi_Assert(e) (void)(e)
int (*V_BreakVolumeCallbacks) ();
#define MAXHANDLERS 4 /* Up to 4 clients; must be at least 2, so that
* move = dump+restore can run on single server */
#define MAX_BIND_TRIES 5 /* Number of times to retry socket bind */
static int getport(SYNC_client_state * state, struct sockaddr_in *addr);
static int SYNC_ask_internal(SYNC_client_state * state, SYNC_command * com, SYNC_response * res);
/* daemon com SYNC client interface */
int
SYNC_connect(SYNC_client_state * state)
{
struct sockaddr_in addr;
/* I can't believe the following is needed for localhost connections!! */
static time_t backoff[] =
{ 3, 3, 3, 5, 5, 5, 7, 15, 16, 24, 32, 40, 48, 0 };
time_t *timeout = &backoff[0];
if (state->fd >= 0) {
return 1;
}
for (;;) {
state->fd = getport(state, &addr);
if (connect(state->fd, (struct sockaddr *)&addr, sizeof(addr)) >= 0)
return 1;
if (!*timeout)
break;
if (!(*timeout & 1))
Log("SYNC_connect temporary failure (will retry)\n");
SYNC_disconnect(state);
sleep(*timeout++);
}
perror("SYNC_connect failed (giving up!)");
return 0;
}
int
SYNC_disconnect(SYNC_client_state * state)
{
#ifdef AFS_NT40_ENV
closesocket(state->fd);
#else
close(state->fd);
#endif
state->fd = -1;
return 0;
}
afs_int32
SYNC_closeChannel(SYNC_client_state * state)
{
afs_int32 code;
SYNC_command com;
SYNC_response res;
SYNC_PROTO_BUF_DECL(ores);
if (state->fd == -1)
return SYNC_OK;
memset(&com, 0, sizeof(com));
memset(&res, 0, sizeof(res));
res.payload.len = SYNC_PROTO_MAX_LEN;
res.payload.buf = ores;
com.hdr.command = SYNC_COM_CHANNEL_CLOSE;
com.hdr.command_len = sizeof(SYNC_command_hdr);
/* in case the other end dropped, don't do any retries */
state->retry_limit = 0;
state->hard_timeout = 0;
code = SYNC_ask(state, &com, &res);
if (code == SYNC_OK) {
if (res.hdr.response != SYNC_OK) {
Log("SYNC_closeChannel: channel shutdown request denied; closing socket anyway\n");
} else if (!(res.hdr.flags & SYNC_FLAG_CHANNEL_SHUTDOWN)) {
Log("SYNC_closeChannel: channel shutdown request mishandled by server\n");
}
} else {
Log("SYNC_closeChannel: channel communications problem");
}
SYNC_disconnect(state);
return code;
}
int
SYNC_reconnect(SYNC_client_state * state)
{
SYNC_disconnect(state);
return SYNC_connect(state);
}
/* private function to fill in the sockaddr struct for us */
static int
getport(SYNC_client_state * state, struct sockaddr_in *addr)
{
int sd;
memset(addr, 0, sizeof(*addr));
assert((sd = socket(AF_INET, SOCK_STREAM, 0)) >= 0);
#ifdef STRUCT_SOCKADDR_HAS_SA_LEN
addr->sin_len = sizeof(struct sockaddr_in);
#endif
addr->sin_addr.s_addr = htonl(0x7f000001);
addr->sin_family = AF_INET; /* was localhost->h_addrtype */
addr->sin_port = htons(state->port); /* XXXX htons not _really_ neccessary */
return sd;
}
afs_int32
SYNC_ask(SYNC_client_state * state, SYNC_command * com, SYNC_response * res)
{
int tries;
afs_uint32 now, timeout, code=SYNC_OK;
if (state->fatal_error) {
return SYNC_COM_ERROR;
}
if (state->fd == -1) {
SYNC_connect(state);
}
if (state->fd == -1) {
state->fatal_error = 1;
return SYNC_COM_ERROR;
}
#ifdef AFS_DEMAND_ATTACH_FS
com->hdr.flags |= SYNC_FLAG_DAFS_EXTENSIONS;
#endif
now = FT_ApproxTime();
timeout = now + state->hard_timeout;
for (tries = 0;
(tries <= state->retry_limit) && (now <= timeout);
tries++, now = FT_ApproxTime()) {
code = SYNC_ask_internal(state, com, res);
if (code == SYNC_OK) {
break;
} else if (code == SYNC_BAD_COMMAND) {
Log("SYNC_ask: protocol mismatch; make sure fileserver, volserver, salvageserver and salvager are same version\n");
break;
} else if (code == SYNC_COM_ERROR) {
Log("SYNC_ask: protocol communications failure; attempting reconnect to server\n");
SYNC_reconnect(state);
/* try again */
} else {
/* unknown (probably protocol-specific) response code, pass it up to the caller, and let them deal with it */
break;
}
}
if (code == SYNC_COM_ERROR) {
Log("SYNC_ask: fatal protocol error; disabling sync protocol to server running on port %d until next server restart\n",
state->port);
state->fatal_error = 1;
}
return code;
}
static afs_int32
SYNC_ask_internal(SYNC_client_state * state, SYNC_command * com, SYNC_response * res)
{
int n;
SYNC_PROTO_BUF_DECL(buf);
#ifndef AFS_NT40_ENV
int iovcnt;
struct iovec iov[2];
#endif
if (state->fd == -1) {
Log("SYNC_ask: invalid sync file descriptor\n");
res->hdr.response = SYNC_COM_ERROR;
goto done;
}
if (com->hdr.command_len > SYNC_PROTO_MAX_LEN) {
Log("SYNC_ask: internal SYNC buffer too small; please file a bug\n");
res->hdr.response = SYNC_COM_ERROR;
goto done;
}
com->hdr.proto_version = state->proto_version;
memcpy(buf, &com->hdr, sizeof(com->hdr));
if (com->payload.len) {
memcpy(buf + sizeof(com->hdr), com->payload.buf,
com->hdr.command_len - sizeof(com->hdr));
}
#ifdef AFS_NT40_ENV
n = send(state->fd, buf, com->hdr.command_len, 0);
if (n != com->hdr.command_len) {
Log("SYNC_ask: write failed\n");
res->hdr.response = SYNC_COM_ERROR;
goto done;
}
n = recv(state->fd, buf, SYNC_PROTO_MAX_LEN, 0);
if (n == 0 || (n < 0 && WSAEINTR != WSAGetLastError())) {
Log("SYNC_ask: No response\n");
res->hdr.response = SYNC_COM_ERROR;
goto done;
}
#else /* !AFS_NT40_ENV */
n = write(state->fd, buf, com->hdr.command_len);
if (com->hdr.command_len != n) {
Log("SYNC_ask: write failed\n");
res->hdr.response = SYNC_COM_ERROR;
goto done;
}
/* receive the response */
iov[0].iov_base = (char *)&res->hdr;
iov[0].iov_len = sizeof(res->hdr);
if (res->payload.len) {
iov[1].iov_base = (char *)res->payload.buf;
iov[1].iov_len = res->payload.len;
iovcnt = 2;
} else {
iovcnt = 1;
}
n = readv(state->fd, iov, iovcnt);
if (n == 0 || (n < 0 && errno != EINTR)) {
Log("SYNC_ask: No response\n");
res->hdr.response = SYNC_COM_ERROR;
goto done;
}
#endif /* !AFS_NT40_ENV */
res->recv_len = n;
if (n < sizeof(res->hdr)) {
Log("SYNC_ask: response too short\n");
res->hdr.response = SYNC_COM_ERROR;
goto done;
}
#ifdef AFS_NT40_ENV
memcpy(&res->hdr, buf, sizeof(res->hdr));
#endif
if ((n - sizeof(res->hdr)) > res->payload.len) {
Log("SYNC_ask: response too long\n");
res->hdr.response = SYNC_COM_ERROR;
goto done;
}
#ifdef AFS_NT40_ENV
memcpy(res->payload.buf, buf + sizeof(res->hdr), n - sizeof(res->hdr));
#endif
if (res->hdr.response_len != n) {
Log("SYNC_ask: length field in response inconsistent\n");
res->hdr.response = SYNC_COM_ERROR;
goto done;
}
if (res->hdr.response == SYNC_DENIED) {
Log("SYNC_ask: negative response\n");
}
done:
return res->hdr.response;
}
/*
* daemon com SYNC server-side interfaces
*/
/* get a command */
afs_int32
SYNC_getCom(int fd, SYNC_command * com)
{
int n;
afs_int32 code = SYNC_OK;
#ifdef AFS_NT40_ENV
SYNC_PROTO_BUF_DECL(buf);
#else
struct iovec iov[2];
int iovcnt;
#endif
#ifdef AFS_NT40_ENV
n = recv(fd, buf, SYNC_PROTO_MAX_LEN, 0);
if (n == 0 || (n < 0 && WSAEINTR != WSAGetLastError())) {
Log("SYNC_getCom: error receiving command\n");
code = SYNC_COM_ERROR;
goto done;
}
#else /* !AFS_NT40_ENV */
iov[0].iov_base = (char *)&com->hdr;
iov[0].iov_len = sizeof(com->hdr);
if (com->payload.len) {
iov[1].iov_base = (char *)com->payload.buf;
iov[1].iov_len = com->payload.len;
iovcnt = 2;
} else {
iovcnt = 1;
}
n = readv(fd, iov, iovcnt);
if (n == 0 || (n < 0 && errno != EINTR)) {
Log("SYNC_getCom: error receiving command\n");
code = SYNC_COM_ERROR;
goto done;
}
#endif /* !AFS_NT40_ENV */
com->recv_len = n;
if (n < sizeof(com->hdr)) {
Log("SYNC_getCom: command too short\n");
code = SYNC_COM_ERROR;
goto done;
}
#ifdef AFS_NT40_ENV
memcpy(&com->hdr, buf, sizeof(com->hdr));
#endif
if ((n - sizeof(com->hdr)) > com->payload.len) {
Log("SYNC_getCom: command too long\n");
code = SYNC_COM_ERROR;
goto done;
}
#ifdef AFS_NT40_ENV
memcpy(com->payload.buf, buf + sizeof(com->hdr), n - sizeof(com->hdr));
#endif
done:
return code;
}
/* put a response */
afs_int32
SYNC_putRes(int fd, SYNC_response * res)
{
int n;
afs_int32 code = SYNC_OK;
SYNC_PROTO_BUF_DECL(buf);
if (res->hdr.response_len > (sizeof(res->hdr) + res->payload.len)) {
Log("SYNC_putRes: response_len field in response header inconsistent\n");
code = SYNC_COM_ERROR;
goto done;
}
if (res->hdr.response_len > SYNC_PROTO_MAX_LEN) {
Log("SYNC_putRes: internal SYNC buffer too small; please file a bug\n");
code = SYNC_COM_ERROR;
goto done;
}
#ifdef AFS_DEMAND_ATTACH_FS
res->hdr.flags |= SYNC_FLAG_DAFS_EXTENSIONS;
#endif
memcpy(buf, &res->hdr, sizeof(res->hdr));
if (res->payload.len) {
memcpy(buf + sizeof(res->hdr), res->payload.buf,
res->hdr.response_len - sizeof(res->hdr));
}
#ifdef AFS_NT40_ENV
n = send(fd, buf, res->hdr.response_len, 0);
#else /* !AFS_NT40_ENV */
n = write(fd, buf, res->hdr.response_len);
#endif /* !AFS_NT40_ENV */
if (res->hdr.response_len != n) {
Log("SYNC_putRes: write failed\n");
res->hdr.response = SYNC_COM_ERROR;
goto done;
}
done:
return code;
}
/* return 0 for legal (null-terminated) string,
* 1 for illegal (unterminated) string */
int
SYNC_verifyProtocolString(char * buf, size_t len)
{
int ret = 0;
size_t s_len;
s_len = afs_strnlen(buf, len);
return (s_len == len) ? 1 : 0;
}

141
src/vol/daemon_com.h Normal file
View File

@ -0,0 +1,141 @@
/*
* Copyright 2006, Sine Nomine Associates 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
*/
#ifndef _AFS_VOL_DAEMON_COM_H
#define _AFS_VOL_DAEMON_COM_H
/*
* SYNC protocol constants
*/
/* SYNC protocol command codes
*
* command codes 0-65535 are reserved for
* global SYNC package command codes
*/
#define SYNC_COM_CODE_USER_BASE 65536
#define SYNC_COM_CODE_DECL(code) (SYNC_COM_CODE_USER_BASE+(code))
/* general command codes */
#define SYNC_COM_CHANNEL_CLOSE 0
/* SYNC protocol response codes
*
* response codes 0-65535 are reserved for
* global SYNC package response codes
*/
#define SYNC_RES_CODE_USER_BASE 65536
#define SYNC_RES_CODE_DECL(code) (SYNC_RES_CODE_USER_BASE+(code))
/* general response codes */
#define SYNC_OK 0 /* sync call returned ok */
#define SYNC_DENIED 1 /* sync request denied by server */
#define SYNC_COM_ERROR 2 /* sync protocol communicaions error */
#define SYNC_BAD_COMMAND 3 /* sync command code not implemented by server */
#define SYNC_FAILED 4 /* sync server-side procedure failed */
/* SYNC protocol reason codes
*
* reason codes 0-65535 are reserved for
* global SYNC package reason codes
*/
#define SYNC_REASON_CODE_USER_BASE 65536
#define SYNC_REASON_CODE_DECL(code) (SYNC_REASON_CODE_USER_BASE+(code))
/* general reason codes */
#define SYNC_REASON_NONE 0
#define SYNC_REASON_MALFORMED_PACKET 1
/* SYNC protocol flags
*
* flag bits 0-7 are reserved for
* global SYNC package flags
*/
#define SYNC_FLAG_CODE_USER_BASE 8
#define SYNC_FLAG_CODE_DECL(code) (1 << (SYNC_FLAG_CODE_USER_BASE+(code)))
/* general flag codes */
#define SYNC_FLAG_CHANNEL_SHUTDOWN 0x1
#define SYNC_FLAG_DAFS_EXTENSIONS 0x2 /* signal that other end of socket is compiled
* with demand attach extensions */
/* SYNC protocol response buffers */
#define SYNC_PROTO_MAX_LEN 768 /* maximum size of sync protocol message */
/* use a large type to get proper buffer alignment so we can safely cast the pointer */
#define SYNC_PROTO_BUF_DECL(buf) \
afs_int64 _##buf##_l[SYNC_PROTO_MAX_LEN/sizeof(afs_int64)]; \
char * buf = (char *)(_##buf##_l)
/* client-side state object */
typedef struct SYNC_client_state {
int fd;
afs_uint16 port;
afs_uint32 proto_version;
int retry_limit; /* max number of times for SYNC_ask to retry */
afs_int32 hard_timeout; /* upper limit on time to keep trying */
byte fatal_error; /* fatal error on this client conn */
} SYNC_client_state;
/* wire types */
typedef struct SYNC_command_hdr {
afs_uint32 proto_version; /* sync protocol version */
afs_int32 programType; /* type of program issuing the request */
afs_int32 command; /* request type */
afs_int32 reason; /* reason for request */
afs_uint32 command_len; /* entire length of command */
afs_uint32 flags;
} SYNC_command_hdr;
typedef struct SYNC_response_hdr {
afs_uint32 proto_version; /* sync protocol version */
afs_uint32 response_len; /* entire length of response */
afs_int32 response; /* response code */
afs_int32 reason; /* reason for response */
afs_uint32 flags;
} SYNC_response_hdr;
/* user-visible types */
typedef struct SYNC_command {
SYNC_command_hdr hdr;
struct {
afs_uint32 len;
void * buf;
} payload;
afs_int32 recv_len;
} SYNC_command;
typedef struct SYNC_response {
SYNC_response_hdr hdr;
struct {
afs_uint32 len;
void * buf;
} payload;
afs_int32 recv_len;
} SYNC_response;
/* client-side prototypes */
extern afs_int32 SYNC_ask(SYNC_client_state *, SYNC_command * com, SYNC_response * res);
extern int SYNC_connect(SYNC_client_state *); /* setup the channel */
extern int SYNC_disconnect(SYNC_client_state *); /* just close the socket */
extern afs_int32 SYNC_closeChannel(SYNC_client_state *); /* do a graceful channel close */
extern int SYNC_reconnect(SYNC_client_state *); /* do a reconnect after a protocol error, or from a forked child */
/* server-side prototypes */
extern int SYNC_getCom(int fd, SYNC_command * com);
extern int SYNC_putRes(int fd, SYNC_response * res);
extern int SYNC_verifyProtocolString(char * buf, size_t len);
#endif /* _AFS_VOL_DAEMON_COM_H */

222
src/vol/fssync-client.c Normal file
View File

@ -0,0 +1,222 @@
/*
* 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
*
* Portions Copyright (c) 2006 Sine Nomine Associates
*/
/*
System: VICE-TWO
Module: fssync.c
Institution: The Information Technology Center, Carnegie-Mellon University
*/
#ifdef notdef
/* All this is going away in early 1989 */
int newVLDB; /* Compatibility flag */
#endif
static int newVLDB = 1;
#ifndef AFS_PTHREAD_ENV
#define USUAL_PRIORITY (LWP_MAX_PRIORITY - 2)
/*
* stack size increased from 8K because the HP machine seemed to have trouble
* with the smaller stack
*/
#define USUAL_STACK_SIZE (24 * 1024)
#endif /* !AFS_PTHREAD_ENV */
/*
fssync-client.c
File server synchronization with external volume utilities.
client-side implementation
*/
#include <afsconfig.h>
#include <afs/param.h>
RCSID
("$Header$");
#include <sys/types.h>
#include <stdio.h>
#ifdef AFS_NT40_ENV
#include <winsock2.h>
#include <time.h>
#else
#include <sys/param.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/time.h>
#endif
#include <errno.h>
#ifdef AFS_PTHREAD_ENV
#include <assert.h>
#else /* AFS_PTHREAD_ENV */
#include <afs/assert.h>
#endif /* AFS_PTHREAD_ENV */
#include <signal.h>
#ifdef HAVE_STRING_H
#include <string.h>
#else
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif
#endif
#include <rx/xdr.h>
#include <afs/afsint.h>
#include "nfs.h"
#include <afs/errors.h>
#include "daemon_com.h"
#include "fssync.h"
#include "lwp.h"
#include "lock.h"
#include <afs/afssyscalls.h>
#include "ihandle.h"
#include "vnode.h"
#include "volume.h"
#include "partition.h"
#ifdef FSSYNC_BUILD_CLIENT
/*@printflike@*/ extern void Log(const char *format, ...);
#ifdef osi_Assert
#undef osi_Assert
#endif
#define osi_Assert(e) (void)(e)
extern int LogLevel;
static SYNC_client_state fssync_state = { -1, 2040, FSYNC_PROTO_VERSION, 5, 120 };
#ifdef AFS_PTHREAD_ENV
static pthread_mutex_t vol_fsync_mutex;
static volatile vol_fsync_mutex_init = 0;
#define VFSYNC_LOCK \
assert(pthread_mutex_lock(&vol_fsync_mutex) == 0)
#define VFSYNC_UNLOCK \
assert(pthread_mutex_unlock(&vol_fsync_mutex) == 0)
#else
#define VFSYNC_LOCK
#define VFSYNC_UNLOCK
#endif
int
FSYNC_clientInit(void)
{
#ifdef AFS_PTHREAD_ENV
/* this is safe since it gets called with VOL_LOCK held, or before we go multithreaded */
if (!vol_fsync_mutex_init) {
assert(pthread_mutex_init(&vol_fsync_mutex, NULL) == 0);
vol_fsync_mutex_init = 1;
}
#endif
return SYNC_connect(&fssync_state);
}
void
FSYNC_clientFinis(void)
{
SYNC_closeChannel(&fssync_state);
}
int
FSYNC_clientChildProcReconnect(void)
{
return SYNC_reconnect(&fssync_state);
}
/* fsync client interface */
afs_int32
FSYNC_askfs(SYNC_command * com, SYNC_response * res)
{
afs_int32 code;
VFSYNC_LOCK;
code = SYNC_ask(&fssync_state, com, res);
VFSYNC_UNLOCK;
switch (code) {
case SYNC_OK:
case SYNC_FAILED:
break;
case SYNC_COM_ERROR:
case SYNC_BAD_COMMAND:
Log("FSYNC_askfs: fatal FSSYNC protocol error; volume management functionality disabled until next fileserver restart\n");
break;
case SYNC_DENIED:
Log("FSYNC_askfs: FSSYNC request denied for reason=%d\n", res->hdr.reason);
break;
default:
Log("FSYNC_askfs: unknown protocol response %d\n", code);
break;
}
return code;
}
afs_int32
FSYNC_GenericOp(void * ext_hdr, size_t ext_len,
int command, int reason,
SYNC_response * res_in)
{
SYNC_response res_l, *res;
SYNC_command com;
if (res_in) {
res = res_in;
} else {
res = &res_l;
res_l.payload.buf = NULL;
res_l.payload.len = 0;
}
memset(&com, 0, sizeof(com));
com.hdr.programType = programType;
com.hdr.command = command;
com.hdr.reason = reason;
com.hdr.command_len = sizeof(com.hdr) + ext_len;
com.payload.buf = ext_hdr;
com.payload.len = ext_len;
return FSYNC_askfs(&com, res);
}
afs_int32
FSYNC_VolOp(VolumeId volume, char * partition,
int command, int reason,
SYNC_response * res)
{
FSSYNC_VolOp_hdr vcom;
memset(&vcom, 0, sizeof(vcom));
vcom.volume = volume;
if (partition)
strlcpy(vcom.partName, partition, sizeof(vcom.partName));
return FSYNC_GenericOp(&vcom, sizeof(vcom), command, reason, res);
}
afs_int32
FSYNC_StatsOp(FSSYNC_StatsOp_hdr * scom, int command, int reason,
SYNC_response * res)
{
return FSYNC_GenericOp(scom, sizeof(*scom), command, reason, res);
}
#endif /* FSSYNC_BUILD_CLIENT */

1148
src/vol/fssync-debug.c Normal file

File diff suppressed because it is too large Load Diff

1179
src/vol/fssync-server.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,751 +0,0 @@
/*
* 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
*/
/*
System: VICE-TWO
Module: fssync.c
Institution: The Information Technology Center, Carnegie-Mellon University
*/
#ifdef notdef
/* All this is going away in early 1989 */
int newVLDB; /* Compatibility flag */
#endif
static int newVLDB = 1;
#ifndef AFS_PTHREAD_ENV
#define USUAL_PRIORITY (LWP_MAX_PRIORITY - 2)
/*
* stack size increased from 8K because the HP machine seemed to have trouble
* with the smaller stack
*/
#define USUAL_STACK_SIZE (24 * 1024)
#endif /* !AFS_PTHREAD_ENV */
/*
fsync.c
File server synchronization with external volume utilities.
*/
/* This controls the size of an fd_set; it must be defined early before
* the system headers define that type and the macros that operate on it.
* Its value should be as large as the maximum file descriptor limit we
* are likely to run into on any platform. Right now, that is 65536
* which is the default hard fd limit on Solaris 9 */
#ifndef _WIN32
#define FD_SETSIZE 65536
#endif
#include <afsconfig.h>
#include <afs/param.h>
RCSID
("$Header$");
#include <sys/types.h>
#include <stdio.h>
#ifdef AFS_NT40_ENV
#include <winsock2.h>
#include <time.h>
#else
#include <sys/param.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/time.h>
#endif
#include <errno.h>
#ifdef AFS_PTHREAD_ENV
#include <assert.h>
#else /* AFS_PTHREAD_ENV */
#include <afs/assert.h>
#endif /* AFS_PTHREAD_ENV */
#include <signal.h>
#ifdef HAVE_STRING_H
#include <string.h>
#else
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif
#endif
#include <rx/xdr.h>
#include <afs/afsint.h>
#include "nfs.h"
#include <afs/errors.h>
#include "fssync.h"
#include "lwp.h"
#include "lock.h"
#include <afs/afssyscalls.h>
#include "ihandle.h"
#include "vnode.h"
#include "volume.h"
#include "partition.h"
/*@printflike@*/ extern void Log(const char *format, ...);
#ifdef osi_Assert
#undef osi_Assert
#endif
#define osi_Assert(e) (void)(e)
int (*V_BreakVolumeCallbacks) ();
#define MAXHANDLERS 4 /* Up to 4 clients; must be at least 2, so that
* move = dump+restore can run on single server */
#define MAXOFFLINEVOLUMES 128 /* This needs to be as big as the maximum
* number that would be offline for 1 operation.
* Current winner is salvage, which needs all
* cloned read-only copies offline when salvaging
* a single read-write volume */
#define MAX_BIND_TRIES 5 /* Number of times to retry socket bind */
struct offlineInfo {
VolumeId volumeID;
char partName[16];
};
static struct offlineInfo OfflineVolumes[MAXHANDLERS][MAXOFFLINEVOLUMES];
static FS_sd = -1; /* Client socket for talking to file server */
static AcceptSd = -1; /* Socket used by server for accepting connections */
static int getport();
struct command {
bit32 command;
bit32 reason;
VolumeId volume;
char partName[16]; /* partition name, e.g. /vicepa */
};
/* Forward declarations */
static void FSYNC_sync();
static void FSYNC_newconnection();
static void FSYNC_com();
static void FSYNC_Drop();
static void AcceptOn();
static void AcceptOff();
static void InitHandler();
static void CallHandler(fd_set * fdsetp);
static int AddHandler();
static int FindHandler();
static int FindHandler_r();
static int RemoveHandler();
static void GetHandler(fd_set * fdsetp, int *maxfdp);
extern int LogLevel;
/*
* This lock controls access to the handler array. The overhead
* is minimal in non-preemptive environments.
*/
struct Lock FSYNC_handler_lock;
int
FSYNC_clientInit(void)
{
struct sockaddr_in addr;
/* I can't believe the following is needed for localhost connections!! */
static time_t backoff[] =
{ 3, 3, 3, 5, 5, 5, 7, 15, 16, 24, 32, 40, 48, 0 };
time_t *timeout = &backoff[0];
for (;;) {
FS_sd = getport(&addr);
if (connect(FS_sd, (struct sockaddr *)&addr, sizeof(addr)) >= 0)
return 1;
if (!*timeout)
break;
if (!(*timeout & 1))
Log("FSYNC_clientInit temporary failure (will retry)");
FSYNC_clientFinis();
sleep(*timeout++);
}
perror("FSYNC_clientInit failed (giving up!)");
return 0;
}
void
FSYNC_clientFinis(void)
{
#ifdef AFS_NT40_ENV
closesocket(FS_sd);
#else
close(FS_sd);
#endif
FS_sd = -1;
}
int
FSYNC_askfs(VolumeId volume, char *partName, int com, int reason)
{
byte response;
struct command command;
int n;
command.volume = volume;
command.command = com;
command.reason = reason;
if (partName)
strcpy(command.partName, partName);
else
command.partName[0] = 0;
assert(FS_sd != -1);
VFSYNC_LOCK;
#ifdef AFS_NT40_ENV
if (send(FS_sd, (char *)&command, sizeof(command), 0) != sizeof(command)) {
printf("FSYNC_askfs: write to file server failed\n");
response = FSYNC_DENIED;
goto done;
}
while ((n = recv(FS_sd, &response, 1, 0)) != 1) {
if (n == 0 || WSAEINTR != WSAGetLastError()) {
printf("FSYNC_askfs: No response from file server\n");
response = FSYNC_DENIED;
goto done;
}
}
#else
if (write(FS_sd, &command, sizeof(command)) != sizeof(command)) {
printf("FSYNC_askfs: write to file server failed\n");
response = FSYNC_DENIED;
goto done;
}
while ((n = read(FS_sd, &response, 1)) != 1) {
if (n == 0 || errno != EINTR) {
printf("FSYNC_askfs: No response from file server\n");
response = FSYNC_DENIED;
goto done;
}
}
#endif
if (response == 0) {
printf
("FSYNC_askfs: negative response from file server; volume %u, command %d\n",
command.volume, (int)command.command);
}
done:
VFSYNC_UNLOCK;
return response;
}
void
FSYNC_fsInit(void)
{
#ifdef AFS_PTHREAD_ENV
pthread_t tid;
pthread_attr_t tattr;
assert(pthread_attr_init(&tattr) == 0);
assert(pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED) == 0);
assert(pthread_create(&tid, &tattr, FSYNC_sync, NULL) == 0);
#else /* AFS_PTHREAD_ENV */
PROCESS pid;
assert(LWP_CreateProcess
(FSYNC_sync, USUAL_STACK_SIZE, USUAL_PRIORITY, (void *)0,
"FSYNC_sync", &pid) == LWP_SUCCESS);
#endif /* AFS_PTHREAD_ENV */
}
static int
getport(struct sockaddr_in *addr)
{
int sd;
memset(addr, 0, sizeof(*addr));
assert((sd = socket(AF_INET, SOCK_STREAM, 0)) >= 0);
#ifdef STRUCT_SOCKADDR_HAS_SA_LEN
addr->sin_len = sizeof(struct sockaddr_in);
#endif
addr->sin_addr.s_addr = htonl(0x7f000001);
addr->sin_family = AF_INET; /* was localhost->h_addrtype */
addr->sin_port = htons(2040); /* XXXX htons not _really_ neccessary */
return sd;
}
static fd_set FSYNC_readfds;
static void
FSYNC_sync()
{
struct sockaddr_in addr;
int on = 1;
extern VInit;
int code;
int numTries;
#ifdef AFS_PTHREAD_ENV
int tid;
#endif
#ifndef AFS_NT40_ENV
(void)signal(SIGPIPE, SIG_IGN);
#endif
#ifdef AFS_PTHREAD_ENV
/* set our 'thread-id' so that the host hold table works */
MUTEX_ENTER(&rx_stats_mutex); /* protects rxi_pthread_hinum */
tid = ++rxi_pthread_hinum;
MUTEX_EXIT(&rx_stats_mutex);
pthread_setspecific(rx_thread_id_key, (void *)tid);
Log("Set thread id %d for FSYNC_sync\n", tid);
#endif /* AFS_PTHREAD_ENV */
while (!VInit) {
/* Let somebody else run until level > 0. That doesn't mean that
* all volumes have been attached. */
#ifdef AFS_PTHREAD_ENV
pthread_yield();
#else /* AFS_PTHREAD_ENV */
LWP_DispatchProcess();
#endif /* AFS_PTHREAD_ENV */
}
AcceptSd = getport(&addr);
/* Reuseaddr needed because system inexplicably leaves crud lying around */
code =
setsockopt(AcceptSd, SOL_SOCKET, SO_REUSEADDR, (char *)&on,
sizeof(on));
if (code)
Log("FSYNC_sync: setsockopt failed with (%d)\n", errno);
for (numTries = 0; numTries < MAX_BIND_TRIES; numTries++) {
if ((code =
bind(AcceptSd, (struct sockaddr *)&addr, sizeof(addr))) == 0)
break;
Log("FSYNC_sync: bind failed with (%d), will sleep and retry\n",
errno);
sleep(5);
}
assert(!code);
listen(AcceptSd, 100);
InitHandler();
AcceptOn();
for (;;) {
int maxfd;
GetHandler(&FSYNC_readfds, &maxfd);
/* Note: check for >= 1 below is essential since IOMGR_select
* doesn't have exactly same semantics as select.
*/
#ifdef AFS_PTHREAD_ENV
if (select(maxfd + 1, &FSYNC_readfds, NULL, NULL, NULL) >= 1)
#else /* AFS_PTHREAD_ENV */
if (IOMGR_Select(maxfd + 1, &FSYNC_readfds, NULL, NULL, NULL) >= 1)
#endif /* AFS_PTHREAD_ENV */
CallHandler(&FSYNC_readfds);
}
}
static void
FSYNC_newconnection(int afd)
{
struct sockaddr_in other;
int junk, fd;
junk = sizeof(other);
fd = accept(afd, (struct sockaddr *)&other, &junk);
if (fd == -1) {
Log("FSYNC_newconnection: accept failed, errno==%d\n", errno);
assert(1 == 2);
} else if (!AddHandler(fd, FSYNC_com)) {
AcceptOff();
assert(AddHandler(fd, FSYNC_com));
}
}
/*
#define TEST2081
*/
afs_int32 FS_cnt = 0;
static void
FSYNC_com(int fd)
{
byte rc = FSYNC_OK;
int n, i;
Error error;
struct command command;
int leaveonline;
register struct offlineInfo *volumes, *v;
Volume *vp;
char tvolName[VMAXPATHLEN];
FS_cnt++;
#ifdef AFS_NT40_ENV
n = recv(fd, &command, sizeof(command), 0);
#else
n = read(fd, &command, sizeof(command));
#endif
if (n <= 0) {
FSYNC_Drop(fd);
return;
}
if (n < sizeof(command)) {
Log("FSYNC_com: partial read (%d instead of %d); dropping connection (cnt=%d)\n", n, sizeof(command), FS_cnt);
FSYNC_Drop(fd);
return;
}
VATTACH_LOCK;
VOL_LOCK;
volumes = OfflineVolumes[FindHandler(fd)];
for (v = 0, i = 0; i < MAXOFFLINEVOLUMES; i++) {
if (volumes[i].volumeID == command.volume
&& strcmp(volumes[i].partName, command.partName) == 0) {
v = &volumes[i];
break;
}
}
switch (command.command) {
case FSYNC_DONE:
/* don't try to put online, this call is made only after deleting
* a volume, in which case we want to remove the vol # from the
* OfflineVolumes array only */
if (v)
v->volumeID = 0;
break;
case FSYNC_ON:
/*
This is where a detatched volume gets reattached. However in the
special case where the volume is merely busy, it is already
attatched and it is only necessary to clear the busy flag. See
defect #2080 for details.
*/
/* is the volume already attatched? */
#ifdef notdef
/*
* XXX With the following enabled we had bizarre problems where the backup id would
* be reset to 0; that was due to the interaction between fileserver/volserver in that they
* both keep volumes in memory and the changes wouldn't be made to the fileserver. Some of
* the problems were due to refcnt changes as result of VGetVolume/VPutVolume which would call
* VOffline, etc. when we don't want to; someday the whole #2080 issue should be revisited to
* be done right XXX
*/
vp = VGetVolume_r(&error, command.volume);
if (vp) {
/* yep, is the BUSY flag set? */
if (vp->specialStatus == VBUSY) {
/* test harness for defect #2081 */
#ifdef TEST2081
/*
* test #2081 by releasing TEST.2081,
* so leave it alone here, zap it after
*/
if (strcmp(vp->header->diskstuff.name, "TEST.2081") == 0)
break;
#endif
/* yep, clear BUSY flag */
vp->specialStatus = 0;
/* make sure vol is online */
if (v) {
v->volumeID = 0;
V_inUse(vp) = 1; /* online */
}
VPutVolume_r(vp);
break;
}
VPutVolume_r(vp);
}
#endif
/* so, we need to attach the volume */
if (v)
v->volumeID = 0;
tvolName[0] = '/';
sprintf(&tvolName[1], VFORMAT, command.volume);
vp = VAttachVolumeByName_r(&error, command.partName, tvolName,
V_VOLUPD);
if (vp)
VPutVolume_r(vp);
break;
case FSYNC_OFF:
case FSYNC_NEEDVOLUME:{
leaveonline = 0;
/* not already offline, we need to find a slot for newly offline volume */
if (!v) {
for (i = 0; i < MAXOFFLINEVOLUMES; i++) {
if (volumes[i].volumeID == 0) {
v = &volumes[i];
break;
}
}
}
if (!v) {
rc = FSYNC_DENIED;
break;
}
vp = VGetVolume_r(&error, command.volume);
if (vp) {
if (command.partName[0] != 0
&& strcmp(command.partName, vp->partition->name) != 0) {
/* volume on desired partition is not online, so we
* should treat this as an offline volume.
*/
VPutVolume_r(vp);
vp = (Volume *) 0;
}
}
if (vp) {
leaveonline = (command.command == FSYNC_NEEDVOLUME
&& (command.reason == V_READONLY
|| (!VolumeWriteable(vp)
&& (command.reason == V_CLONE
|| command.reason == V_DUMP))
)
);
if (!leaveonline) {
if (command.command == FSYNC_NEEDVOLUME
&& (command.reason == V_CLONE
|| command.reason == V_DUMP)) {
vp->specialStatus = VBUSY;
}
/* remember what volume we got, so we can keep track of how
* many volumes the volserver or whatever is using. Note that
* vp is valid since leaveonline is only set when vp is valid.
*/
v->volumeID = command.volume;
strcpy(v->partName, vp->partition->name);
if (!V_inUse(vp)) {
/* in this case, VOffline just returns sans decrementing
* ref count. We could try to fix it, but it has lots of
* weird callers.
*/
VPutVolume_r(vp);
} else {
VOffline_r(vp, "A volume utility is running.");
}
vp = 0;
} else {
VUpdateVolume_r(&error, vp); /* At least get volume stats right */
if (LogLevel) {
Log("FSYNC: Volume %u (%s) was left on line for an external %s request\n", V_id(vp), V_name(vp), command.reason == V_CLONE ? "clone" : command.reason == V_READONLY ? "readonly" : command.reason == V_DUMP ? "dump" : "UNKNOWN");
}
}
if (vp)
VPutVolume_r(vp);
}
rc = FSYNC_OK;
break;
}
case FSYNC_MOVEVOLUME:
/* Yuch: the "reason" for the move is the site it got moved to... */
/* still set specialStatus so we stop sending back VBUSY.
* also should still break callbacks. Note that I don't know
* how to tell if we should break all or not, so we just do it
* since it doesn't matter much if we do an extra break
* volume callbacks on a volume move within the same server */
vp = VGetVolume_r(&error, command.volume);
if (vp) {
vp->specialStatus = VMOVED;
VPutVolume_r(vp);
}
if (V_BreakVolumeCallbacks) {
Log("fssync: volume %u moved to %x; breaking all call backs\n",
command.volume, command.reason);
VOL_UNLOCK;
VATTACH_UNLOCK;
(*V_BreakVolumeCallbacks) (command.volume);
VATTACH_LOCK;
VOL_LOCK;
}
break;
case FSYNC_RESTOREVOLUME:
/* if the volume is being restored, break all callbacks on it */
if (V_BreakVolumeCallbacks) {
Log("fssync: volume %u restored; breaking all call backs\n",
command.volume);
VOL_UNLOCK;
VATTACH_UNLOCK;
(*V_BreakVolumeCallbacks) (command.volume);
VATTACH_LOCK;
VOL_LOCK;
}
break;
default:
rc = FSYNC_DENIED;
break;
}
VOL_UNLOCK;
VATTACH_UNLOCK;
#ifdef AFS_NT40_ENV
(void)send(fd, &rc, 1, 0);
#else
(void)write(fd, &rc, 1);
#endif
}
static void
FSYNC_Drop(int fd)
{
struct offlineInfo *p;
register i;
Error error;
char tvolName[VMAXPATHLEN];
VATTACH_LOCK;
VOL_LOCK;
p = OfflineVolumes[FindHandler(fd)];
for (i = 0; i < MAXOFFLINEVOLUMES; i++) {
if (p[i].volumeID) {
Volume *vp;
tvolName[0] = '/';
sprintf(&tvolName[1], VFORMAT, p[i].volumeID);
vp = VAttachVolumeByName_r(&error, p[i].partName, tvolName,
V_VOLUPD);
if (vp)
VPutVolume_r(vp);
p[i].volumeID = 0;
}
}
VOL_UNLOCK;
VATTACH_UNLOCK;
RemoveHandler(fd);
#ifdef AFS_NT40_ENV
closesocket(fd);
#else
close(fd);
#endif
AcceptOn();
}
static int AcceptHandler = -1; /* handler id for accept, if turned on */
static void
AcceptOn()
{
if (AcceptHandler == -1) {
assert(AddHandler(AcceptSd, FSYNC_newconnection));
AcceptHandler = FindHandler(AcceptSd);
}
}
static void
AcceptOff()
{
if (AcceptHandler != -1) {
assert(RemoveHandler(AcceptSd));
AcceptHandler = -1;
}
}
/* The multiple FD handling code. */
static int HandlerFD[MAXHANDLERS];
static int (*HandlerProc[MAXHANDLERS]) ();
static void
InitHandler()
{
register int i;
ObtainWriteLock(&FSYNC_handler_lock);
for (i = 0; i < MAXHANDLERS; i++) {
HandlerFD[i] = -1;
HandlerProc[i] = 0;
}
ReleaseWriteLock(&FSYNC_handler_lock);
}
static void
CallHandler(fd_set * fdsetp)
{
register int i;
ObtainReadLock(&FSYNC_handler_lock);
for (i = 0; i < MAXHANDLERS; i++) {
if (HandlerFD[i] >= 0 && FD_ISSET(HandlerFD[i], fdsetp)) {
ReleaseReadLock(&FSYNC_handler_lock);
(*HandlerProc[i]) (HandlerFD[i]);
ObtainReadLock(&FSYNC_handler_lock);
}
}
ReleaseReadLock(&FSYNC_handler_lock);
}
static int
AddHandler(int afd, int (*aproc) ())
{
register int i;
ObtainWriteLock(&FSYNC_handler_lock);
for (i = 0; i < MAXHANDLERS; i++)
if (HandlerFD[i] == -1)
break;
if (i >= MAXHANDLERS) {
ReleaseWriteLock(&FSYNC_handler_lock);
return 0;
}
HandlerFD[i] = afd;
HandlerProc[i] = aproc;
ReleaseWriteLock(&FSYNC_handler_lock);
return 1;
}
static int
FindHandler(register int afd)
{
register int i;
ObtainReadLock(&FSYNC_handler_lock);
for (i = 0; i < MAXHANDLERS; i++)
if (HandlerFD[i] == afd) {
ReleaseReadLock(&FSYNC_handler_lock);
return i;
}
ReleaseReadLock(&FSYNC_handler_lock); /* just in case */
assert(1 == 2);
return -1; /* satisfy compiler */
}
static int
FindHandler_r(register int afd)
{
register int i;
for (i = 0; i < MAXHANDLERS; i++)
if (HandlerFD[i] == afd) {
return i;
}
assert(1 == 2);
return -1; /* satisfy compiler */
}
static int
RemoveHandler(register int afd)
{
ObtainWriteLock(&FSYNC_handler_lock);
HandlerFD[FindHandler_r(afd)] = -1;
ReleaseWriteLock(&FSYNC_handler_lock);
return 1;
}
static void
GetHandler(fd_set * fdsetp, int *maxfdp)
{
register int i;
register int maxfd = -1;
FD_ZERO(fdsetp);
ObtainReadLock(&FSYNC_handler_lock); /* just in case */
for (i = 0; i < MAXHANDLERS; i++)
if (HandlerFD[i] != -1) {
FD_SET(HandlerFD[i], fdsetp);
if (maxfd < HandlerFD[i])
maxfd = HandlerFD[i];
}
*maxfdp = maxfd;
ReleaseReadLock(&FSYNC_handler_lock); /* just in case */
}

View File

@ -5,6 +5,8 @@
* 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
*
* Portions Copyright (c) 2006 Sine Nomine Associates
*/
/*
@ -14,38 +16,117 @@
*/
/* FSYNC commands */
#define FSYNC_ON 1 /* Volume online */
#define FSYNC_OFF 2 /* Volume offline */
#define FSYNC_LISTVOLUMES 3 /* Update local volume list */
#define FSYNC_NEEDVOLUME 4 /* Put volume in whatever mode (offline, or whatever)
* best fits the attachment mode provided in reason */
#define FSYNC_MOVEVOLUME 5 /* Generate temporary relocation information
* for this volume to another site, to be used
* if this volume disappears */
#define FSYNC_RESTOREVOLUME 6 /* Break all the callbacks on this volume since it is being restored */
#define FSYNC_DONE 7 /* Done with this volume (used after a delete).
* Don't put online, but remove from list */
#ifndef __fssync_h_
#define __fssync_h_
/* Reasons (these could be communicated to venus or converted to messages) */
#define FSYNC_WHATEVER 0 /* XXXX */
#define FSYNC_SALVAGE 1 /* volume is being salvaged */
#define FSYNC_MOVE 2 /* volume is being moved */
#define FSYNC_OPERATOR 3 /* operator forced volume offline */
#define FSYNC_PROTO_VERSION 2
/* Replies (1 byte) */
/* FSYNC command codes */
#define FSYNC_VOL_ON SYNC_COM_CODE_DECL(0) /* Volume online */
#define FSYNC_VOL_OFF SYNC_COM_CODE_DECL(1) /* Volume offline */
#define FSYNC_VOL_LISTVOLUMES SYNC_COM_CODE_DECL(2) /* Update local volume list */
#define FSYNC_VOL_NEEDVOLUME SYNC_COM_CODE_DECL(3) /* Put volume in whatever mode (offline, or whatever)
* best fits the attachment mode provided in reason */
#define FSYNC_VOL_MOVE SYNC_COM_CODE_DECL(4) /* Generate temporary relocation information
* for this volume to another site, to be used
* if this volume disappears */
#define FSYNC_VOL_BREAKCBKS SYNC_COM_CODE_DECL(5) /* Break all the callbacks on this volume */
#define FSYNC_VOL_DONE SYNC_COM_CODE_DECL(6) /* Done with this volume (used after a delete).
* Don't put online, but remove from list */
#define FSYNC_VOL_QUERY SYNC_COM_CODE_DECL(7) /* query the volume state */
#define FSYNC_VOL_QUERY_HDR SYNC_COM_CODE_DECL(8) /* query the volume disk data structure */
#define FSYNC_VOL_QUERY_VOP SYNC_COM_CODE_DECL(9) /* query the volume for pending vol op info */
#define FSYNC_VOL_STATS_GENERAL SYNC_COM_CODE_DECL(10) /* query the general volume package statistics */
#define FSYNC_VOL_STATS_VICEP SYNC_COM_CODE_DECL(11) /* query the per-partition volume package stats */
#define FSYNC_VOL_STATS_HASH SYNC_COM_CODE_DECL(12) /* query the per hash-chain volume package stats */
#define FSYNC_VOL_STATS_HDR SYNC_COM_CODE_DECL(13) /* query the volume header cache statistics */
#define FSYNC_VOL_STATS_VLRU SYNC_COM_CODE_DECL(14) /* query the VLRU statistics */
#define FSYNC_DENIED 0
#define FSYNC_OK 1
/* FSYNC reason codes */
#define FSYNC_WHATEVER SYNC_REASON_CODE_DECL(0) /* XXXX */
#define FSYNC_SALVAGE SYNC_REASON_CODE_DECL(1) /* volume is being salvaged */
#define FSYNC_MOVE SYNC_REASON_CODE_DECL(2) /* volume is being moved */
#define FSYNC_OPERATOR SYNC_REASON_CODE_DECL(3) /* operator forced volume offline */
#define FSYNC_EXCLUSIVE SYNC_REASON_CODE_DECL(4) /* somebody else has the volume offline */
#define FSYNC_UNKNOWN_VOLID SYNC_REASON_CODE_DECL(5) /* volume id not known by fileserver */
#define FSYNC_HDR_NOT_ATTACHED SYNC_REASON_CODE_DECL(6) /* volume header not currently attached */
#define FSYNC_NO_PENDING_VOL_OP SYNC_REASON_CODE_DECL(7) /* no volume operation pending */
#define FSYNC_VOL_PKG_ERROR SYNC_REASON_CODE_DECL(8) /* error in the volume package */
/* FSYNC response codes */
/* FSYNC flag codes */
/* Prototypes from fssync.c */
void FSYNC_clientFinis(void);
int FSYNC_clientInit(void);
void FSYNC_fsInit(void);
int FSYNC_askfs(VolumeId volume, char *partName, int com, int reason);
struct offlineInfo {
afs_uint32 volumeID;
char partName[16];
};
typedef struct FSSYNC_VolOp_hdr {
afs_uint32 volume; /* volume id associated with request */
char partName[16]; /* partition name, e.g. /vicepa */
} FSSYNC_VolOp_hdr;
typedef struct FSSYNC_VolOp_command {
SYNC_command_hdr * hdr;
FSSYNC_VolOp_hdr * vop;
SYNC_command * com;
struct offlineInfo * v;
struct offlineInfo * volumes;
} FSSYNC_VolOp_command;
typedef struct FSSYNC_VolOp_info {
SYNC_command_hdr com;
FSSYNC_VolOp_hdr vop;
} FSSYNC_VolOp_info;
typedef struct FSSYNC_StatsOp_hdr {
union {
afs_uint32 vlru_generation;
afs_uint32 hash_bucket;
char partName[16];
} args;
} FSSYNC_StatsOp_hdr;
typedef struct FSSYNC_StatsOp_command {
SYNC_command_hdr * hdr;
FSSYNC_StatsOp_hdr * sop;
SYNC_command * com;
} FSSYNC_StatsOp_command;
/*
* common interfaces
*/
extern void FSYNC_Init(void);
/*
* fsync client interfaces
*/
extern void FSYNC_clientFinis(void);
extern int FSYNC_clientInit(void);
extern int FSYNC_clientChildProcReconnect(void);
/* generic low-level interface */
extern afs_int32 FSYNC_askfs(SYNC_command * com, SYNC_response * res);
/* generic higher-level interface */
extern afs_int32 FSYNC_GenericOp(void * ext_hdr, size_t ext_len,
int command, int reason,
SYNC_response * res);
/* volume operations interface */
extern afs_int32 FSYNC_VolOp(VolumeId volume, char *partName, int com, int reason,
SYNC_response * res);
/* statistics query interface */
extern afs_int32 FSYNC_StatsOp(FSSYNC_StatsOp_hdr * scom, int command, int reason,
SYNC_response * res_in);
#endif /* __fssync_h_ */

View File

@ -41,6 +41,7 @@ RCSID
#include "partition.h"
#include "viceinode.h"
#include "salvage.h"
#include "daemon_com.h"
#include "fssync.h"
#ifdef O_LARGEFILE

View File

@ -7,6 +7,7 @@
* directory or online at http://www.openafs.org/dl/license10.html
*
* Portions Copyright (c) 2003 Apple Computer, Inc.
* Portions Copyright (c) 2006 Sine Nomine Associates
*/
/*
@ -189,6 +190,14 @@ RCSID
int aixlow_water = 8; /* default 8% */
struct DiskPartition *DiskPartitionList;
#ifdef AFS_DEMAND_ATTACH_FS
static struct DiskPartition *DiskPartitionTable[VOLMAXPARTS+1];
static struct DiskPartition * VLookupPartition_r(char * path);
static void AddPartitionToTable_r(struct DiskPartition *);
static void DeletePartitionFromTable_r(struct DiskPartition *);
#endif /* AFS_DEMAND_ATTACH_FS */
#ifdef AFS_SGI_XFS_IOPS_ENV
/* Verify that the on disk XFS inodes on the partition are large enough to
* hold the AFS attribute. Returns -1 if the attribute can't be set or is
@ -225,8 +234,16 @@ VerifyXFSInodeSize(char *part, char *fstype)
}
return code;
}
#endif
#endif /* AFS_SGI_XFS_IOPS_ENV */
int
VInitPartitionPackage(void)
{
#ifdef AFS_DEMAND_ATTACH_ENV
memset(&DiskPartitionTable, 0, sizeof(DiskPartitionTable));
#endif /* AFS_DEMAND_ATTACH_ENV */
return 0;
}
static void
VInitPartition_r(char *path, char *devname, Device dev)
@ -245,6 +262,7 @@ VInitPartition_r(char *path, char *devname, Device dev)
dp->next = 0;
dp->name = (char *)malloc(strlen(path) + 1);
strncpy(dp->name, path, strlen(path) + 1);
dp->index = volutil_GetPartitionID(path);
#if defined(AFS_NAMEI_ENV) && !defined(AFS_NT40_ENV)
/* Create a lockfile for the partition, of the form /vicepa/Lock/vicepa */
dp->devName = (char *)malloc(2 * strlen(path) + 6);
@ -254,7 +272,7 @@ VInitPartition_r(char *path, char *devname, Device dev)
mkdir(dp->devName, 0700);
strcat(dp->devName, path);
close(afs_open(dp->devName, O_RDWR | O_CREAT, 0600));
dp->device = volutil_GetPartitionID(path);
dp->device = dp->index;
#else
dp->devName = (char *)malloc(strlen(devname) + 1);
strncpy(dp->devName, devname, strlen(devname) + 1);
@ -268,6 +286,11 @@ VInitPartition_r(char *path, char *devname, Device dev)
(void)namei_ViceREADME(VPartitionPath(dp));
#endif
VSetPartitionDiskUsage_r(dp);
#ifdef AFS_DEMAND_ATTACH_FS
AddPartitionToTable_r(dp);
queue_Init(&dp->vol_list);
assert(pthread_cond_init(&dp->vol_list.cv, NULL) == 0);
#endif /* AFS_DEMAND_ATTACH_FS */
}
static void
@ -352,7 +375,7 @@ VCheckPartition(char *part, char *devname)
return -1;
#endif
#endif /* AFS_NAMEI_ENV */
#endif
#endif /* !AFS_LINUX20_ENV && !AFS_NT40_ENV */
#if defined(AFS_DUX40_ENV) && !defined(AFS_NAMEI_ENV)
if (status.st_ino != ROOTINO) {
@ -825,10 +848,14 @@ struct DiskPartition *
VGetPartition_r(char *name, int abortp)
{
register struct DiskPartition *dp;
#ifdef AFS_DEMAND_ATTACH_FS
dp = VLookupPartition_r(name);
#else /* AFS_DEMAND_ATTACH_FS */
for (dp = DiskPartitionList; dp; dp = dp->next) {
if (strcmp(dp->name, name) == 0)
break;
}
#endif /* AFS_DEMAND_ATTACH_FS */
if (abortp)
assert(dp != NULL);
return dp;
@ -1234,3 +1261,60 @@ VUnlockPartition(char *name)
VUnlockPartition_r(name);
VOL_UNLOCK;
}
#ifdef AFS_DEMAND_ATTACH_FS
/* XXX not sure this will work on AFS_NT40_ENV
* needs to be tested!
*/
struct DiskPartition *
VGetPartitionById_r(afs_int32 id, int abortp)
{
struct DiskPartition * dp = NULL;
if ((id >= 0) && (id <= VOLMAXPARTS)) {
dp = DiskPartitionTable[id];
}
if (abortp) {
assert(dp != NULL);
}
return dp;
}
struct DiskPartition *
VGetPartitionById(afs_int32 id, int abortp)
{
struct Diskpartition * dp;
VOL_LOCK;
dp = VGetPartitionById_r(id, abortp);
VOL_UNLOCK;
return dp;
}
static struct DiskPartition *
VLookupPartition_r(char * path)
{
afs_int32 id = volutil_GetPartitionID(path);
if (id < 0 || id > VOLMAXPARTS)
return NULL;
return DiskPartitionTable[id];
}
static void
AddPartitionToTable_r(struct DiskPartition * dp)
{
assert(dp->index >= 0 && dp->index <= VOLMAXPARTS);
DiskPartitionTable[dp->index] = dp;
}
static void
DeletePartitionFromTable_r(struct DiskPartition * dp)
{
assert(dp->index >= 0 && dp->index <= VOLMAXPARTS);
DiskPartitionTable[dp->index] = NULL;
}
#endif /* AFS_DEMAND_ATTACH_FS */

View File

@ -5,6 +5,8 @@
* 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
*
* Portions Copyright (c) 2006 Sine Nomine Associates
*/
/*
@ -27,6 +29,7 @@
#define AFS_RDSKDEV "/dev/r"
#endif
/* All Vice partitions on a server will have the following name prefix */
#define VICE_PARTITION_PREFIX "/vicep"
#define VICE_PREFIX_SIZE (sizeof(VICE_PARTITION_PREFIX)-1)
@ -53,6 +56,7 @@ struct DiskPartition {
char *name; /* Mounted partition name */
char *devName; /* Device mounted on */
Device device; /* device number */
afs_int32 index; /* partition index (0<=x<=VOLMAXPARTS) */
int lock_fd; /* File descriptor of this partition if locked; otherwise -1;
* Not used by the file server */
int free; /* Total number of blocks (1K) presumed
@ -77,7 +81,26 @@ struct DiskPartition {
* from the superblock */
int flags;
int f_files; /* total number of files in this partition */
#ifdef AFS_DEMAND_ATTACH_FS
struct {
struct rx_queue head; /* list of volumes on this partition (VByPList) */
afs_uint32 len; /* length of volume list */
int busy; /* asynch vol list op in progress */
pthread_cond_t cv; /* vol_list.busy change cond var */
} vol_list;
#endif /* AFS_DEMAND_ATTACH_FS */
};
struct DiskPartitionStats {
afs_int32 free;
afs_int32 totalUsable;
afs_int32 minFree;
afs_int32 f_files;
#ifdef AFS_DEMAND_ATTACH_FS
afs_int32 vol_list_len;
#endif
};
#define PART_DONTUPDATE 1
#define PART_DUPLICATE 2 /* NT - used if we find more than one partition
* using the same drive. Will be dumped before
@ -93,7 +116,12 @@ extern int VValidVPTEntry(struct vptab *vptp);
struct Volume; /* Potentially forward definition */
extern struct DiskPartition *DiskPartitionList;
extern struct DiskPartition *VGetPartition();
extern struct DiskPartition *VGetPartition(char * name, int abortp);
extern struct DiskPartition *VGetPartition_r(char * name, int abortp);
#ifdef AFS_DEMAND_ATTACH_FS
extern struct DiskPartition *VGetPartitionById(afs_int32 index, int abortp);
extern struct DiskPartition *VGetPartitionById_r(afs_int32 index, int abortp);
#endif
extern int VAttachPartitions(void);
extern void VLockPartition(char *name);
extern void VLockPartition_r(char *name);
@ -108,3 +136,4 @@ extern void VAdjustDiskUsage(Error * ec, struct Volume *vp,
afs_sfsize_t blocks, afs_sfsize_t checkBlocks);
extern int VDiskUsage(struct Volume *vp, afs_sfsize_t blocks);
extern void VPrintDiskStats(void);
extern int VInitPartitionPackage(void);

View File

@ -52,11 +52,16 @@ RCSID
#include "volume.h"
#include "viceinode.h"
#include "partition.h"
#include "daemon_com.h"
#include "fssync.h"
/* forward declarations */
void PurgeIndex_r(Volume * vp, VnodeClass class);
void PurgeHeader_r(Volume * vp);
static int ObliterateRegion(Volume * avp, VnodeClass aclass, StreamHandle_t * afile,
afs_int32 * aoffset);
static void PurgeIndex(Volume * vp, VnodeClass class);
static void PurgeIndex_r(Volume * vp, VnodeClass class);
static void PurgeHeader_r(Volume * vp);
static void PurgeHeader(Volume * vp);
void
VPurgeVolume_r(Error * ec, Volume * vp)
@ -78,7 +83,7 @@ VPurgeVolume_r(Error * ec, Volume * vp)
/*
* Call the fileserver to break all call backs for that volume
*/
FSYNC_askfs(V_id(vp), tpartp->name, FSYNC_RESTOREVOLUME, 0);
FSYNC_VolOp(V_id(vp), tpartp->name, FSYNC_VOL_BREAKCBKS, 0, NULL);
}
void
@ -161,7 +166,7 @@ ObliterateRegion(Volume * avp, VnodeClass aclass, StreamHandle_t * afile,
return -1;
}
void
static void
PurgeIndex(Volume * vp, VnodeClass class)
{
VOL_LOCK;
@ -169,7 +174,7 @@ PurgeIndex(Volume * vp, VnodeClass class)
VOL_UNLOCK;
}
void
static void
PurgeIndex_r(Volume * vp, VnodeClass class)
{
StreamHandle_t *ifile;
@ -199,7 +204,7 @@ PurgeIndex_r(Volume * vp, VnodeClass class)
FDH_CLOSE(fdP);
}
void
static void
PurgeHeader(Volume * vp)
{
VOL_LOCK;
@ -207,7 +212,7 @@ PurgeHeader(Volume * vp)
VOL_UNLOCK;
}
void
static void
PurgeHeader_r(Volume * vp)
{
IH_REALLYCLOSE(V_diskDataHandle(vp));

View File

@ -14,6 +14,9 @@
*/
#ifndef __salvage_h_
#define __salvage_h_
#include <afs/afssyscalls.h>
/* Definition of DirHandle for salvager. Not the same as for the file server */
@ -24,3 +27,5 @@ typedef struct DirHandle {
IHandle_t *dirh_handle;
afs_int32 dirh_cacheCheck;
} DirHandle;
#endif /* __salvage_h_ */

738
src/vol/salvaged.c Normal file
View File

@ -0,0 +1,738 @@
/*
* Copyright 2006, Sine Nomine Associates 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
*/
/*
* demand attach fs
* online salvager daemon
*/
/* Main program file. Define globals. */
#define MAIN 1
#include <afsconfig.h>
#include <afs/param.h>
RCSID
("$Header$");
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <dirent.h>
#include <sys/stat.h>
#include <time.h>
#include <errno.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)
#endif
#include <rx/xdr.h>
#include <afs/afsint.h>
#include <afs/assert.h>
#if !defined(AFS_SGI_ENV) && !defined(AFS_NT40_ENV)
#if defined(AFS_VFSINCL_ENV)
#include <sys/vnode.h>
#ifdef AFS_SUN5_ENV
#include <sys/fs/ufs_inode.h>
#else
#if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
#include <ufs/ufs/dinode.h>
#include <ufs/ffs/fs.h>
#else
#include <ufs/inode.h>
#endif
#endif
#else /* AFS_VFSINCL_ENV */
#ifdef AFS_OSF_ENV
#include <ufs/inode.h>
#else /* AFS_OSF_ENV */
#if !defined(AFS_LINUX20_ENV) && !defined(AFS_XBSD_ENV)
#include <sys/inode.h>
#endif
#endif
#endif /* AFS_VFSINCL_ENV */
#endif /* AFS_SGI_ENV */
#ifdef AFS_AIX_ENV
#include <sys/vfs.h>
#include <sys/lockf.h>
#else
#ifdef AFS_HPUX_ENV
#include <unistd.h>
#include <checklist.h>
#else
#if defined(AFS_SGI_ENV)
#include <unistd.h>
#include <fcntl.h>
#include <mntent.h>
#else
#if defined(AFS_SUN_ENV) || defined(AFS_SUN5_ENV)
#ifdef AFS_SUN5_ENV
#include <unistd.h>
#include <sys/mnttab.h>
#include <sys/mntent.h>
#else
#include <mntent.h>
#endif
#else
#endif /* AFS_SGI_ENV */
#endif /* AFS_HPUX_ENV */
#endif
#endif
#include <fcntl.h>
#ifndef AFS_NT40_ENV
#include <afs/osi_inode.h>
#endif
#include <afs/cmd.h>
#include <afs/afsutil.h>
#include <afs/fileutil.h>
#include <afs/procmgmt.h> /* signal(), kill(), wait(), etc. */
#ifndef AFS_NT40_ENV
#include <syslog.h>
#endif
#include "nfs.h"
#include "lwp.h"
#include "lock.h"
#include <afs/afssyscalls.h>
#include "ihandle.h"
#include "vnode.h"
#include "volume.h"
#include "partition.h"
#include "daemon_com.h"
#include "fssync.h"
#include "salvsync.h"
#include "viceinode.h"
#include "salvage.h"
#include "volinodes.h" /* header magic number, etc. stuff */
#include "vol-salvage.h"
#ifdef AFS_NT40_ENV
#include <pthread.h>
#endif
#if !defined(AFS_DEMAND_ATTACH_FS)
#error "online salvager only supported for demand attach fileserver"
#endif /* AFS_DEMAND_ATTACH_FS */
#if defined(AFS_NT40_ENV)
#error "online salvager not supported on NT"
#endif /* AFS_NT40_ENV */
/* Forward declarations */
/*@printflike@*/ void Log(const char *format, ...);
/*@printflike@*/ void Abort(const char *format, ...);
/*@+fcnmacros +macrofcndecl@*/
#ifdef O_LARGEFILE
#define afs_fopen fopen64
#else /* !O_LARGEFILE */
#define afs_fopen fopen
#endif /* !O_LARGEFILE */
/*@=fcnmacros =macrofcndecl@*/
static volatile int current_workers = 0;
static volatile struct rx_queue pending_q;
static pthread_mutex_t worker_lock;
static pthread_cond_t worker_cv;
static void * SalvageChildReaperThread(void *);
static int DoSalvageVolume(struct SalvageQueueNode * node, int slot);
static void SalvageServer(void);
static void SalvageClient(VolumeId vid, char * pname);
static int Reap_Child(char * prog, int * pid, int * status);
static void * SalvageLogCleanupThread(void *);
static int SalvageLogCleanup(int pid);
struct log_cleanup_node {
struct rx_queue q;
int pid;
};
struct {
struct rx_queue queue_head;
pthread_cond_t queue_change_cv;
} log_cleanup_queue;
#define DEFAULT_PARALLELISM 4 /* allow 4 parallel salvage workers by default */
static int
handleit(struct cmd_syndesc *as)
{
register struct cmd_item *ti;
char pname[100], *temp;
afs_int32 seenpart = 0, seenvol = 0, vid = 0, seenany = 0;
struct DiskPartition *partP;
#ifdef AFS_SGI_VNODE_GLUE
if (afs_init_kernel_config(-1) < 0) {
printf
("Can't determine NUMA configuration, not starting salvager.\n");
exit(1);
}
#endif
if (as->parms[2].items) /* -debug */
debug = 1;
if (as->parms[3].items) /* -nowrite */
Testing = 1;
if (as->parms[4].items) /* -inodes */
ListInodeOption = 1;
if (as->parms[5].items) /* -oktozap */
OKToZap = 1;
if (as->parms[6].items) /* -rootinodes */
ShowRootFiles = 1;
if (as->parms[8].items) /* -ForceReads */
forceR = 1;
if ((ti = as->parms[9].items)) { /* -Parallel # */
temp = ti->data;
if (strncmp(temp, "all", 3) == 0) {
PartsPerDisk = 1;
temp += 3;
}
if (strlen(temp) != 0) {
Parallel = atoi(temp);
if (Parallel < 1)
Parallel = 1;
if (Parallel > MAXPARALLEL) {
printf("Setting parallel salvages to maximum of %d \n",
MAXPARALLEL);
Parallel = MAXPARALLEL;
}
}
} else {
Parallel = MIN(DEFAULT_PARALLELISM, MAXPARALLEL);
}
if ((ti = as->parms[10].items)) { /* -tmpdir */
DIR *dirp;
tmpdir = ti->data;
dirp = opendir(tmpdir);
if (!dirp) {
printf
("Can't open temporary placeholder dir %s; using current partition \n",
tmpdir);
tmpdir = NULL;
} else
closedir(dirp);
}
if ((ti = as->parms[11].items)) /* -showlog */
ShowLog = 1;
if ((ti = as->parms[12].items)) { /* -orphans */
if (Testing)
orphans = ORPH_IGNORE;
else if (strcmp(ti->data, "remove") == 0
|| strcmp(ti->data, "r") == 0)
orphans = ORPH_REMOVE;
else if (strcmp(ti->data, "attach") == 0
|| strcmp(ti->data, "a") == 0)
orphans = ORPH_ATTACH;
}
#ifndef AFS_NT40_ENV /* ignore options on NT */
if ((ti = as->parms[13].items)) { /* -syslog */
useSyslog = 1;
ShowLog = 0;
}
if ((ti = as->parms[14].items)) { /* -syslogfacility */
useSyslogFacility = atoi(ti->data);
}
if ((ti = as->parms[15].items)) { /* -datelogs */
TimeStampLogFile(AFSDIR_SERVER_SALSRVLOG_FILEPATH);
}
#endif
if ((ti = as->parms[16].items)) { /* -client */
if ((ti = as->parms[0].items)) { /* -partition */
seenpart = 1;
strlcpy(pname, ti->data, sizeof(pname));
}
if ((ti = as->parms[1].items)) { /* -volumeid */
seenvol = 1;
vid = atoi(ti->data);
}
if (!seenpart || !seenvol) {
printf("You must specify '-partition' and '-volumeid' with the '-client' option\n");
exit(-1);
}
SalvageClient(vid, pname);
} else { /* salvageserver mode */
SalvageServer();
}
return (0);
}
#ifndef AFS_NT40_ENV
#include "AFS_component_version_number.c"
#endif
#define MAX_ARGS 128
#ifdef AFS_NT40_ENV
char *save_args[MAX_ARGS];
int n_save_args = 0;
pthread_t main_thread;
#endif
static char commandLine[150];
int
main(int argc, char **argv)
{
struct cmd_syndesc *ts;
int err = 0;
int i;
extern char cml_version_number[];
#ifdef AFS_AIX32_ENV
/*
* The following signal action for AIX is necessary so that in case of a
* crash (i.e. core is generated) we can include the user's data section
* in the core dump. Unfortunately, by default, only a partial core is
* generated which, in many cases, isn't too useful.
*/
struct sigaction nsa;
sigemptyset(&nsa.sa_mask);
nsa.sa_handler = SIG_DFL;
nsa.sa_flags = SA_FULLDUMP;
sigaction(SIGABRT, &nsa, NULL);
sigaction(SIGSEGV, &nsa, NULL);
#endif
/* Initialize directory paths */
if (!(initAFSDirPath() & AFSDIR_SERVER_PATHS_OK)) {
#ifdef AFS_NT40_ENV
ReportErrorEventAlt(AFSEVT_SVR_NO_INSTALL_DIR, 0, argv[0], 0);
#endif
fprintf(stderr, "%s: Unable to obtain AFS server directory.\n",
argv[0]);
exit(2);
}
#ifdef AFS_NT40_ENV
main_thread = pthread_self();
if (spawnDatap && spawnDataLen) {
/* This is a child per partition salvager. Don't setup log or
* try to lock the salvager lock.
*/
if (nt_SetupPartitionSalvage(spawnDatap, spawnDataLen) < 0)
exit(3);
} else {
#endif
for (commandLine[0] = '\0', i = 0; i < argc; i++) {
if (i > 0)
strlcat(commandLine, " ", sizeof(commandLine));
strlcat(commandLine, argv[i], sizeof(commandLine));
}
#ifndef AFS_NT40_ENV
if (geteuid() != 0) {
printf("Salvager must be run as root.\n");
fflush(stdout);
Exit(0);
}
#endif
/* bad for normal help flag processing, but can do nada */
#ifdef AFS_NT40_ENV
}
#endif
ts = cmd_CreateSyntax("initcmd", handleit, 0, "initialize the program");
cmd_AddParm(ts, "-partition", CMD_SINGLE, CMD_OPTIONAL,
"Name of partition to salvage");
cmd_AddParm(ts, "-volumeid", CMD_SINGLE, CMD_OPTIONAL,
"Volume Id to salvage");
cmd_AddParm(ts, "-debug", CMD_FLAG, CMD_OPTIONAL,
"Run in Debugging mode");
cmd_AddParm(ts, "-nowrite", CMD_FLAG, CMD_OPTIONAL,
"Run readonly/test mode");
cmd_AddParm(ts, "-inodes", CMD_FLAG, CMD_OPTIONAL,
"Just list affected afs inodes - debugging flag");
cmd_AddParm(ts, "-oktozap", CMD_FLAG, CMD_OPTIONAL,
"Give permission to destroy bogus inodes/volumes - debugging flag");
cmd_AddParm(ts, "-rootinodes", CMD_FLAG, CMD_OPTIONAL,
"Show inodes owned by root - debugging flag");
cmd_AddParm(ts, "-salvagedirs", CMD_FLAG, CMD_OPTIONAL,
"Force rebuild/salvage of all directories");
cmd_AddParm(ts, "-blockreads", CMD_FLAG, CMD_OPTIONAL,
"Read smaller blocks to handle IO/bad blocks");
cmd_AddParm(ts, "-parallel", CMD_SINGLE, CMD_OPTIONAL,
"# of max parallel partition salvaging");
cmd_AddParm(ts, "-tmpdir", CMD_SINGLE, CMD_OPTIONAL,
"Name of dir to place tmp files ");
cmd_AddParm(ts, "-showlog", CMD_FLAG, CMD_OPTIONAL,
"Show log file upon completion");
cmd_AddParm(ts, "-orphans", CMD_SINGLE, CMD_OPTIONAL,
"ignore | remove | attach");
/* note - syslog isn't avail on NT, but if we make it conditional, have
* to deal with screwy offsets for cmd params */
cmd_AddParm(ts, "-syslog", CMD_FLAG, CMD_OPTIONAL,
"Write salvage log to syslogs");
cmd_AddParm(ts, "-syslogfacility", CMD_SINGLE, CMD_OPTIONAL,
"Syslog facility number to use");
cmd_AddParm(ts, "-datelogs", CMD_FLAG, CMD_OPTIONAL,
"Include timestamp in logfile filename");
cmd_AddParm(ts, "-client", CMD_FLAG, CMD_OPTIONAL,
"Use SALVSYNC to ask salvageserver to salvage a volume");
err = cmd_Dispatch(argc, argv);
Exit(err);
}
static void
SalvageClient(VolumeId vid, char * pname)
{
int done = 0;
afs_int32 code;
SYNC_response res;
SALVSYNC_response_hdr sres;
VInitVolumePackage(volumeUtility, 5, 5, DONT_CONNECT_FS, 0);
SALVSYNC_clientInit();
code = SALVSYNC_SalvageVolume(vid, pname, SALVSYNC_SALVAGE, SALVSYNC_OPERATOR, 0, NULL);
if (code != SYNC_OK) {
goto sync_error;
}
res.payload.buf = (void *) &sres;
res.payload.len = sizeof(sres);
while(!done) {
sleep(2);
code = SALVSYNC_SalvageVolume(vid, pname, SALVSYNC_QUERY, SALVSYNC_WHATEVER, 0, &res);
if (code != SYNC_OK) {
goto sync_error;
}
switch (sres.state) {
case SALVSYNC_STATE_ERROR:
printf("salvageserver reports salvage ended in an error; check log files for more details\n");
case SALVSYNC_STATE_DONE:
case SALVSYNC_STATE_UNKNOWN:
done = 1;
}
}
SALVSYNC_clientFinis();
return;
sync_error:
if (code == SYNC_DENIED) {
printf("salvageserver refused to salvage volume %u on partition %s\n",
vid, pname);
} else if (code == SYNC_BAD_COMMAND) {
printf("SALVSYNC protocol mismatch; please make sure fileserver, volserver, salvageserver and salvager are same version\n");
} else if (code == SYNC_COM_ERROR) {
printf("SALVSYNC communications error\n");
}
SALVSYNC_clientFinis();
exit(-1);
}
static int * child_slot;
static void
SalvageServer(void)
{
int pid, ret;
struct SalvageQueueNode * node;
pthread_t tid;
pthread_attr_t attrs;
int slot;
/* All entries to the log will be appended. Useful if there are
* multiple salvagers appending to the log.
*/
CheckLogFile(AFSDIR_SERVER_SALSRVLOG_FILEPATH);
#ifndef AFS_NT40_ENV
#ifdef AFS_LINUX20_ENV
fcntl(fileno(logFile), F_SETFL, O_APPEND); /* Isn't this redundant? */
#else
fcntl(fileno(logFile), F_SETFL, FAPPEND); /* Isn't this redundant? */
#endif
#endif
setlinebuf(logFile);
fprintf(logFile, "%s\n", cml_version_number);
Log("Starting OpenAFS Online Salvage Server %s (%s)\n", SalvageVersion, commandLine);
/* Get and hold a lock for the duration of the salvage to make sure
* that no other salvage runs at the same time. The routine
* VInitVolumePackage (called below) makes sure that a file server or
* other volume utilities don't interfere with the salvage.
*/
/* even demand attach online salvager
* still needs this because we don't want
* a stand-alone salvager to conflict with
* the salvager daemon */
ObtainSalvageLock();
child_slot = (int *) malloc(Parallel * sizeof(int));
assert(child_slot != NULL);
memset(child_slot, 0, Parallel * sizeof(int));
/* initialize things */
VInitVolumePackage(salvageServer, 5, 5,
1, 0);
DInit(10);
queue_Init(&pending_q);
queue_Init(&log_cleanup_queue);
assert(pthread_mutex_init(&worker_lock, NULL) == 0);
assert(pthread_cond_init(&worker_cv, NULL) == 0);
assert(pthread_cond_init(&log_cleanup_queue.queue_change_cv, NULL) == 0);
assert(pthread_attr_init(&attrs) == 0);
/* start up the reaper and log cleaner threads */
assert(pthread_attr_setdetachstate(&attrs, PTHREAD_CREATE_DETACHED) == 0);
assert(pthread_create(&tid,
&attrs,
&SalvageChildReaperThread,
NULL) == 0);
assert(pthread_create(&tid,
&attrs,
&SalvageLogCleanupThread,
NULL) == 0);
/* loop forever serving requests */
while (1) {
node = SALVSYNC_getWork();
assert(node != NULL);
VOL_LOCK;
/* find a slot */
for (slot = 0; slot < Parallel; slot++) {
if (!child_slot[slot])
break;
}
assert (slot < Parallel);
pid = Fork();
if (pid == 0) {
VOL_UNLOCK;
ret = DoSalvageVolume(node, slot);
Exit(ret);
} else if (pid < 0) {
VOL_UNLOCK;
SALVSYNC_doneWork(node, 1);
} else {
child_slot[slot] = pid;
node->pid = pid;
VOL_UNLOCK;
assert(pthread_mutex_lock(&worker_lock) == 0);
current_workers++;
/* let the reaper thread know another worker was spawned */
assert(pthread_cond_broadcast(&worker_cv) == 0);
/* if we're overquota, wait for the reaper */
while (current_workers >= Parallel) {
assert(pthread_cond_wait(&worker_cv, &worker_lock) == 0);
}
assert(pthread_mutex_unlock(&worker_lock) == 0);
}
}
}
static int
DoSalvageVolume(struct SalvageQueueNode * node, int slot)
{
char childLog[AFSDIR_PATH_MAX];
int ret;
struct DiskPartition * partP;
VChildProcReconnectFS();
/* do not attempt to close parent's logFile handle as
* another thread may have held the lock on the FILE
* structure when fork was called! */
afs_snprintf(childLog, sizeof(childLog), "%s.%d",
AFSDIR_SERVER_SLVGLOG_FILEPATH, getpid());
logFile = afs_fopen(childLog, "a");
if (!logFile) { /* still nothing, use stdout */
logFile = stdout;
ShowLog = 0;
}
if (node->command.sop.volume <= 0) {
Log("salvageServer: invalid volume id specified; salvage aborted\n");
return 1;
}
partP = VGetPartition(node->command.sop.partName, 0);
if (!partP) {
Log("salvageServer: Unknown or unmounted partition %s; salvage aborted\n",
node->command.sop.partName);
return 1;
}
/* Salvage individual volume; don't notify fs */
SalvageFileSys1(partP, node->command.sop.volume);
VDisconnectFS();
fclose(logFile);
return 0;
}
static void *
SalvageChildReaperThread(void * args)
{
int slot, pid, status, code, found;
struct SalvageQueueNode *qp, *nqp;
struct log_cleanup_node * cleanup;
assert(pthread_mutex_lock(&worker_lock) == 0);
/* loop reaping our children */
while (1) {
/* wait() won't block unless we have children, so
* block on the cond var if we're childless */
while (current_workers == 0) {
assert(pthread_cond_wait(&worker_cv, &worker_lock) == 0);
}
assert(pthread_mutex_unlock(&worker_lock) == 0);
cleanup = (struct log_cleanup_node *) malloc(sizeof(struct log_cleanup_node));
while (Reap_Child("salvageserver", &pid, &status) < 0) {
/* try to prevent livelock if something goes wrong */
sleep(1);
}
VOL_LOCK;
for (slot = 0; slot < Parallel; slot++) {
if (child_slot[slot] == pid)
break;
}
assert(slot < Parallel);
child_slot[slot] = 0;
VOL_UNLOCK;
assert(pthread_mutex_lock(&worker_lock) == 0);
if (cleanup) {
cleanup->pid = pid;
queue_Append(&log_cleanup_queue, cleanup);
assert(pthread_cond_signal(&log_cleanup_queue.queue_change_cv) == 0);
}
/* ok, we've reaped a child */
current_workers--;
SALVSYNC_doneWorkByPid(pid, 0);
assert(pthread_cond_broadcast(&worker_cv) == 0);
}
return NULL;
}
static int
Reap_Child(char *prog, int * pid, int * status)
{
int ret;
ret = wait(status);
if (ret >= 0) {
*pid = ret;
if (WCOREDUMP(*status))
Log("\"%s\" core dumped!\n", prog);
if (WIFSIGNALED(*status) != 0 || WEXITSTATUS(*status) != 0)
Log("\"%s\" (pid=%d) terminated abnormally!\n", prog, ret);
} else {
Log("wait returned -1\n");
}
return ret;
}
/*
* thread to combine salvager child logs
* back into the main salvageserver log
*/
static void *
SalvageLogCleanupThread(void * arg)
{
struct log_cleanup_node * cleanup;
assert(pthread_mutex_lock(&worker_lock) == 0);
while (1) {
while (queue_IsEmpty(&log_cleanup_queue)) {
assert(pthread_cond_wait(&log_cleanup_queue.queue_change_cv, &worker_lock) == 0);
}
while (queue_IsNotEmpty(&log_cleanup_queue)) {
cleanup = queue_First(&log_cleanup_queue, log_cleanup_node);
queue_Remove(cleanup);
assert(pthread_mutex_unlock(&worker_lock) == 0);
SalvageLogCleanup(cleanup->pid);
free(cleanup);
assert(pthread_mutex_lock(&worker_lock) == 0);
}
}
assert(pthread_mutex_unlock(&worker_lock) == 0);
return NULL;
}
#define LOG_XFER_BUF_SIZE 65536
static int
SalvageLogCleanup(int pid)
{
int pidlog, len;
char fn[AFSDIR_PATH_MAX];
static char buf[LOG_XFER_BUF_SIZE];
afs_snprintf(fn, sizeof(fn), "%s.%d",
AFSDIR_SERVER_SLVGLOG_FILEPATH, pid);
pidlog = open(fn, O_RDONLY);
unlink(fn);
if (pidlog < 0)
return 1;
len = read(pidlog, buf, LOG_XFER_BUF_SIZE);
while (len) {
fwrite(buf, len, 1, logFile);
len = read(pidlog, buf, LOG_XFER_BUF_SIZE);
}
close(pidlog);
return 0;
}

499
src/vol/salvager.c Normal file
View File

@ -0,0 +1,499 @@
/*
* 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
*/
/*
* System: VICE-TWO
* Module: salvager.c
* Institution: The Information Technology Center, Carnegie-Mellon University
*/
/* Main program file. Define globals. */
#define MAIN 1
#include <afsconfig.h>
#include <afs/param.h>
RCSID
("$Header$");
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <dirent.h>
#include <sys/stat.h>
#include <time.h>
#include <errno.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)
#endif
#include <rx/xdr.h>
#include <afs/afsint.h>
#include <afs/assert.h>
#if !defined(AFS_SGI_ENV) && !defined(AFS_NT40_ENV)
#if defined(AFS_VFSINCL_ENV)
#include <sys/vnode.h>
#ifdef AFS_SUN5_ENV
#include <sys/fs/ufs_inode.h>
#else
#if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
#include <ufs/ufs/dinode.h>
#include <ufs/ffs/fs.h>
#else
#include <ufs/inode.h>
#endif
#endif
#else /* AFS_VFSINCL_ENV */
#ifdef AFS_OSF_ENV
#include <ufs/inode.h>
#else /* AFS_OSF_ENV */
#if !defined(AFS_LINUX20_ENV) && !defined(AFS_XBSD_ENV)
#include <sys/inode.h>
#endif
#endif
#endif /* AFS_VFSINCL_ENV */
#endif /* AFS_SGI_ENV */
#ifdef AFS_AIX_ENV
#include <sys/vfs.h>
#include <sys/lockf.h>
#else
#ifdef AFS_HPUX_ENV
#include <unistd.h>
#include <checklist.h>
#else
#if defined(AFS_SGI_ENV)
#include <unistd.h>
#include <fcntl.h>
#include <mntent.h>
#else
#if defined(AFS_SUN_ENV) || defined(AFS_SUN5_ENV)
#ifdef AFS_SUN5_ENV
#include <unistd.h>
#include <sys/mnttab.h>
#include <sys/mntent.h>
#else
#include <mntent.h>
#endif
#else
#endif /* AFS_SGI_ENV */
#endif /* AFS_HPUX_ENV */
#endif
#endif
#include <fcntl.h>
#ifndef AFS_NT40_ENV
#include <afs/osi_inode.h>
#endif
#include <afs/cmd.h>
#include <afs/afsutil.h>
#include <afs/fileutil.h>
#include <afs/procmgmt.h> /* signal(), kill(), wait(), etc. */
#ifndef AFS_NT40_ENV
#include <syslog.h>
#endif
#include "nfs.h"
#include "lwp.h"
#include "lock.h"
#include <afs/afssyscalls.h>
#include "ihandle.h"
#include "vnode.h"
#include "volume.h"
#include "partition.h"
#include "daemon_com.h"
#include "fssync.h"
#include "salvsync.h"
#include "viceinode.h"
#include "salvage.h"
#include "volinodes.h" /* header magic number, etc. stuff */
#include "vol-salvage.h"
#ifdef AFS_NT40_ENV
#include <pthread.h>
#endif
static int get_salvage_lock = 0;
/* Forward declarations */
/*@printflike@*/ void Log(const char *format, ...);
/*@printflike@*/ void Abort(const char *format, ...);
static int
handleit(struct cmd_syndesc *as)
{
register struct cmd_item *ti;
char pname[100], *temp;
afs_int32 seenpart = 0, seenvol = 0, vid = 0, seenany = 0;
struct DiskPartition *partP;
#ifdef AFS_SGI_VNODE_GLUE
if (afs_init_kernel_config(-1) < 0) {
printf
("Can't determine NUMA configuration, not starting salvager.\n");
exit(1);
}
#endif
#ifdef FAST_RESTART
{
afs_int32 i;
for (i = 0; i < CMD_MAXPARMS; i++) {
if (as->parms[i].items) {
seenany = 1;
break;
}
}
}
if (!seenany) {
char *msg =
"Exiting immediately without salvage. Look into the FileLog to find volumes which really need to be salvaged!";
if (useSyslog)
Log(msg);
else
printf("%s\n", msg);
Exit(0);
}
#endif /* FAST_RESTART */
if ((ti = as->parms[0].items)) { /* -partition */
seenpart = 1;
strncpy(pname, ti->data, 100);
}
if ((ti = as->parms[1].items)) { /* -volumeid */
if (!seenpart) {
printf
("You must also specify '-partition' option with the '-volumeid' option\n");
exit(-1);
}
seenvol = 1;
vid = atoi(ti->data);
}
if (as->parms[2].items) /* -debug */
debug = 1;
if (as->parms[3].items) /* -nowrite */
Testing = 1;
if (as->parms[4].items) /* -inodes */
ListInodeOption = 1;
if (as->parms[5].items) /* -force */
ForceSalvage = 1;
if (as->parms[6].items) /* -oktozap */
OKToZap = 1;
if (as->parms[7].items) /* -rootinodes */
ShowRootFiles = 1;
if (as->parms[8].items) /* -RebuildDirs */
RebuildDirs = 1;
if (as->parms[9].items) /* -ForceReads */
forceR = 1;
if ((ti = as->parms[10].items)) { /* -Parallel # */
temp = ti->data;
if (strncmp(temp, "all", 3) == 0) {
PartsPerDisk = 1;
temp += 3;
}
if (strlen(temp) != 0) {
Parallel = atoi(temp);
if (Parallel < 1)
Parallel = 1;
if (Parallel > MAXPARALLEL) {
printf("Setting parallel salvages to maximum of %d \n",
MAXPARALLEL);
Parallel = MAXPARALLEL;
}
}
}
if ((ti = as->parms[11].items)) { /* -tmpdir */
DIR *dirp;
tmpdir = ti->data;
dirp = opendir(tmpdir);
if (!dirp) {
printf
("Can't open temporary placeholder dir %s; using current partition \n",
tmpdir);
tmpdir = NULL;
} else
closedir(dirp);
}
if ((ti = as->parms[12].items)) /* -showlog */
ShowLog = 1;
if ((ti = as->parms[13].items)) { /* -log */
Testing = 1;
ShowSuid = 1;
Showmode = 1;
}
if ((ti = as->parms[14].items)) { /* -showmounts */
Testing = 1;
Showmode = 1;
ShowMounts = 1;
}
if ((ti = as->parms[15].items)) { /* -orphans */
if (Testing)
orphans = ORPH_IGNORE;
else if (strcmp(ti->data, "remove") == 0
|| strcmp(ti->data, "r") == 0)
orphans = ORPH_REMOVE;
else if (strcmp(ti->data, "attach") == 0
|| strcmp(ti->data, "a") == 0)
orphans = ORPH_ATTACH;
}
#ifndef AFS_NT40_ENV /* ignore options on NT */
if ((ti = as->parms[16].items)) { /* -syslog */
useSyslog = 1;
ShowLog = 0;
}
if ((ti = as->parms[17].items)) { /* -syslogfacility */
useSyslogFacility = atoi(ti->data);
}
if ((ti = as->parms[18].items)) { /* -datelogs */
TimeStampLogFile(AFSDIR_SERVER_SLVGLOG_FILEPATH);
}
#endif
#ifdef FAST_RESTART
if (ti = as->parms[19].items) { /* -DontSalvage */
char *msg =
"Exiting immediately without salvage. Look into the FileLog to find volumes which really need to be salvaged!";
if (useSyslog)
Log(msg);
else
printf("%s\n", msg);
Exit(0);
}
#elif defined(DEMAND_ATTACH_ENABLE)
if (seenvol && !as->parms[19].items) {
char * msg =
"The standalone salvager cannot be run concurrently with a Demand Attach Fileserver. Please use 'salvageserver -client <partition> <volume id>' to manually schedule volume salvages with the salvageserver (new versions of 'bos salvage' automatically do this for you). Or, if you insist on using the standalone salvager, add the -forceDAFS flag to your salvager command line.";
if (useSyslog)
Log(msg);
else
printf("%s\n", msg);
Exit(1);
}
#endif
if (get_salvage_lock) {
ObtainSalvageLock();
}
/* Note: if seenvol we initialize this as a standard volume utility: this has the
* implication that the file server may be running; negotations have to be made with
* the file server in this case to take the read write volume and associated read-only
* volumes off line before salvaging */
#ifdef AFS_NT40_ENV
if (seenvol) {
if (afs_winsockInit() < 0) {
ReportErrorEventAlt(AFSEVT_SVR_WINSOCK_INIT_FAILED, 0,
AFSDIR_SALVAGER_FILE, 0);
Log("Failed to initailize winsock, exiting.\n");
Exit(1);
}
}
#endif
VInitVolumePackage(seenvol ? volumeUtility : salvager, 5, 5,
DONT_CONNECT_FS, 0);
DInit(10);
#ifdef AFS_NT40_ENV
if (myjob.cj_number != NOT_CHILD) {
if (!seenpart) {
seenpart = 1;
(void)strcpy(pname, myjob.cj_part);
}
}
#endif
if (seenpart == 0) {
for (partP = DiskPartitionList; partP; partP = partP->next) {
SalvageFileSysParallel(partP);
}
SalvageFileSysParallel(0);
} else {
partP = VGetPartition(pname, 0);
if (!partP) {
Log("salvage: Unknown or unmounted partition %s; salvage aborted\n", pname);
Exit(1);
}
if (!seenvol)
SalvageFileSys(partP, 0);
else {
/* Salvage individual volume */
if (vid <= 0) {
Log("salvage: invalid volume id specified; salvage aborted\n");
Exit(1);
}
SalvageFileSys(partP, vid);
}
}
return (0);
}
#ifndef AFS_NT40_ENV
#include "AFS_component_version_number.c"
#endif
#define MAX_ARGS 128
#ifdef AFS_NT40_ENV
char *save_args[MAX_ARGS];
int n_save_args = 0;
pthread_t main_thread;
#endif
int
main(int argc, char **argv)
{
struct cmd_syndesc *ts;
int err = 0;
char commandLine[150];
int i;
extern char cml_version_number[];
#ifdef AFS_AIX32_ENV
/*
* The following signal action for AIX is necessary so that in case of a
* crash (i.e. core is generated) we can include the user's data section
* in the core dump. Unfortunately, by default, only a partial core is
* generated which, in many cases, isn't too useful.
*/
struct sigaction nsa;
sigemptyset(&nsa.sa_mask);
nsa.sa_handler = SIG_DFL;
nsa.sa_flags = SA_FULLDUMP;
sigaction(SIGABRT, &nsa, NULL);
sigaction(SIGSEGV, &nsa, NULL);
#endif
/* Initialize directory paths */
if (!(initAFSDirPath() & AFSDIR_SERVER_PATHS_OK)) {
#ifdef AFS_NT40_ENV
ReportErrorEventAlt(AFSEVT_SVR_NO_INSTALL_DIR, 0, argv[0], 0);
#endif
fprintf(stderr, "%s: Unable to obtain AFS server directory.\n",
argv[0]);
exit(2);
}
#ifdef AFS_NT40_ENV
main_thread = pthread_self();
if (spawnDatap && spawnDataLen) {
/* This is a child per partition salvager. Don't setup log or
* try to lock the salvager lock.
*/
if (nt_SetupPartitionSalvage(spawnDatap, spawnDataLen) < 0)
exit(3);
} else {
#endif
for (commandLine[0] = '\0', i = 0; i < argc; i++) {
if (i > 0)
strcat(commandLine, " ");
strcat(commandLine, argv[i]);
}
/* All entries to the log will be appended. Useful if there are
* multiple salvagers appending to the log.
*/
CheckLogFile(AFSDIR_SERVER_SLVGLOG_FILEPATH);
#ifndef AFS_NT40_ENV
#ifdef AFS_LINUX20_ENV
fcntl(fileno(logFile), F_SETFL, O_APPEND); /* Isn't this redundant? */
#else
fcntl(fileno(logFile), F_SETFL, FAPPEND); /* Isn't this redundant? */
#endif
#endif
setlinebuf(logFile);
#ifndef AFS_NT40_ENV
if (geteuid() != 0) {
printf("Salvager must be run as root.\n");
fflush(stdout);
Exit(0);
}
#endif
/* bad for normal help flag processing, but can do nada */
fprintf(logFile, "%s\n", cml_version_number);
Log("STARTING AFS SALVAGER %s (%s)\n", SalvageVersion, commandLine);
/* Get and hold a lock for the duration of the salvage to make sure
* that no other salvage runs at the same time. The routine
* VInitVolumePackage (called below) makes sure that a file server or
* other volume utilities don't interfere with the salvage.
*/
get_salvage_lock = 1;
#ifdef AFS_NT40_ENV
}
#endif
ts = cmd_CreateSyntax("initcmd", handleit, 0, "initialize the program");
cmd_AddParm(ts, "-partition", CMD_SINGLE, CMD_OPTIONAL,
"Name of partition to salvage");
cmd_AddParm(ts, "-volumeid", CMD_SINGLE, CMD_OPTIONAL,
"Volume Id to salvage");
cmd_AddParm(ts, "-debug", CMD_FLAG, CMD_OPTIONAL,
"Run in Debugging mode");
cmd_AddParm(ts, "-nowrite", CMD_FLAG, CMD_OPTIONAL,
"Run readonly/test mode");
cmd_AddParm(ts, "-inodes", CMD_FLAG, CMD_OPTIONAL,
"Just list affected afs inodes - debugging flag");
cmd_AddParm(ts, "-force", CMD_FLAG, CMD_OPTIONAL, "Force full salvaging");
cmd_AddParm(ts, "-oktozap", CMD_FLAG, CMD_OPTIONAL,
"Give permission to destroy bogus inodes/volumes - debugging flag");
cmd_AddParm(ts, "-rootinodes", CMD_FLAG, CMD_OPTIONAL,
"Show inodes owned by root - debugging flag");
cmd_AddParm(ts, "-salvagedirs", CMD_FLAG, CMD_OPTIONAL,
"Force rebuild/salvage of all directories");
cmd_AddParm(ts, "-blockreads", CMD_FLAG, CMD_OPTIONAL,
"Read smaller blocks to handle IO/bad blocks");
cmd_AddParm(ts, "-parallel", CMD_SINGLE, CMD_OPTIONAL,
"# of max parallel partition salvaging");
cmd_AddParm(ts, "-tmpdir", CMD_SINGLE, CMD_OPTIONAL,
"Name of dir to place tmp files ");
cmd_AddParm(ts, "-showlog", CMD_FLAG, CMD_OPTIONAL,
"Show log file upon completion");
cmd_AddParm(ts, "-showsuid", CMD_FLAG, CMD_OPTIONAL,
"Report on suid/sgid files");
cmd_AddParm(ts, "-showmounts", CMD_FLAG, CMD_OPTIONAL,
"Report on mountpoints");
cmd_AddParm(ts, "-orphans", CMD_SINGLE, CMD_OPTIONAL,
"ignore | remove | attach");
/* note - syslog isn't avail on NT, but if we make it conditional, have
* to deal with screwy offsets for cmd params */
cmd_AddParm(ts, "-syslog", CMD_FLAG, CMD_OPTIONAL,
"Write salvage log to syslogs");
cmd_AddParm(ts, "-syslogfacility", CMD_SINGLE, CMD_OPTIONAL,
"Syslog facility number to use");
cmd_AddParm(ts, "-datelogs", CMD_FLAG, CMD_OPTIONAL,
"Include timestamp in logfile filename");
#ifdef FAST_RESTART
cmd_AddParm(ts, "-DontSalvage", CMD_FLAG, CMD_OPTIONAL,
"Don't salvage. This my be set in BosConfig to let the fileserver restart immediately after a crash. Bad volumes will be taken offline");
#elif defined(DEMAND_ATTACH_ENABLE)
cmd_AddParm(ts, "-forceDAFS", CMD_FLAG, CMD_OPTIONAL,
"For Demand Attach Fileserver, permit a manual volume salvage outside of the salvageserver");
#endif /* FAST_RESTART */
err = cmd_Dispatch(argc, argv);
Exit(err);
}

172
src/vol/salvsync-client.c Normal file
View File

@ -0,0 +1,172 @@
/*
* Copyright 2006, Sine Nomine Associates 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
*/
/*
* salvsync-client.c
*
* OpenAFS demand attach fileserver
* Salvage server synchronization with fileserver.
*/
#include <afsconfig.h>
#include <afs/param.h>
RCSID
("$Header$");
#include <sys/types.h>
#include <stdio.h>
#ifdef AFS_NT40_ENV
#include <winsock2.h>
#include <time.h>
#else
#include <sys/param.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/time.h>
#endif
#include <errno.h>
#include <assert.h>
#include <signal.h>
#ifdef HAVE_STRING_H
#include <string.h>
#else
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif
#endif
#include <rx/xdr.h>
#include <afs/afsint.h>
#include "nfs.h"
#include <afs/errors.h>
#include "salvsync.h"
#include "lwp.h"
#include "lock.h"
#include <afs/afssyscalls.h>
#include "ihandle.h"
#include "vnode.h"
#include "volume.h"
#include "partition.h"
#include <rx/rx_queue.h>
/*@printflike@*/ extern void Log(const char *format, ...);
#ifdef osi_Assert
#undef osi_Assert
#endif
#define osi_Assert(e) (void)(e)
#ifdef AFS_DEMAND_ATTACH_FS
/*
* SALVSYNC is a feature specific to the demand attach fileserver
*/
extern int LogLevel;
extern int VInit;
extern pthread_mutex_t vol_salvsync_mutex;
static SYNC_client_state salvsync_client_state = { -1, 2041, SALVSYNC_PROTO_VERSION, 5, 120 };
/*
* client-side routines
*/
int
SALVSYNC_clientInit(void)
{
return SYNC_connect(&salvsync_client_state);
}
int
SALVSYNC_clientFinis(void)
{
SYNC_closeChannel(&salvsync_client_state);
return 1;
}
int
SALVSYNC_clientReconnect(void)
{
return SYNC_reconnect(&salvsync_client_state);
}
afs_int32
SALVSYNC_askSalv(SYNC_command * com, SYNC_response * res)
{
afs_int32 code;
VSALVSYNC_LOCK;
code = SYNC_ask(&salvsync_client_state, com, res);
VSALVSYNC_UNLOCK;
switch (code) {
case SYNC_OK:
case SYNC_FAILED:
break;
case SYNC_COM_ERROR:
case SYNC_BAD_COMMAND:
Log("SALVSYNC_askSalv: fatal SALVSYNC protocol error; online salvager functionality disabled until next fileserver restart\n");
break;
case SYNC_DENIED:
Log("SALVSYNC_askSalv: SALVSYNC request denied for reason=%d\n", res->hdr.reason);
break;
default:
Log("SALVSYNC_askSalv: unknown protocol response %d\n", code);
break;
}
return code;
}
afs_int32
SALVSYNC_SalvageVolume(VolumeId volume, char *partName, int command, int reason,
afs_uint32 prio, SYNC_response * res_in)
{
SYNC_command com;
SYNC_response res_l, *res;
SALVSYNC_command_hdr scom;
SALVSYNC_response_hdr sres;
int n, tot;
memset(&com, 0, sizeof(com));
memset(&scom, 0, sizeof(scom));
if (res_in) {
res = res_in;
} else {
memset(&res_l, 0, sizeof(res_l));
memset(&sres, 0, sizeof(sres));
res_l.payload.buf = (void *) &sres;
res_l.payload.len = sizeof(sres);
res = &res_l;
}
com.payload.buf = (void *) &scom;
com.payload.len = sizeof(scom);
com.hdr.command = command;
com.hdr.reason = reason;
com.hdr.command_len = sizeof(com.hdr) + sizeof(scom);
scom.volume = volume;
scom.prio = prio;
if (partName) {
strlcpy(scom.partName, partName, sizeof(scom.partName));
} else {
scom.partName[0] = '\0';
}
return SALVSYNC_askSalv(&com, res);
}
#endif /* AFS_DEMAND_ATTACH_FS */

1009
src/vol/salvsync-server.c Normal file

File diff suppressed because it is too large Load Diff

111
src/vol/salvsync.h Normal file
View File

@ -0,0 +1,111 @@
/*
* Copyright 2006, Sine Nomine Associates 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
*/
/*
* demand attach fs
* salvage server interface
*/
#ifndef _AFS_VOL_SALVSYNC_H
#define _AFS_VOL_SALVSYNC_H
#ifdef AFS_DEMAND_ATTACH_FS
#include "daemon_com.h"
#define SALVSYNC_PROTO_VERSION 1
/* SALVSYNC command codes */
#define SALVSYNC_NOP SYNC_COM_CODE_DECL(0) /* just return stats */
#define SALVSYNC_SALVAGE SYNC_COM_CODE_DECL(1) /* schedule a salvage */
#define SALVSYNC_CANCEL SYNC_COM_CODE_DECL(2) /* Cancel a salvage */
#define SALVSYNC_RAISEPRIO SYNC_COM_CODE_DECL(3) /* move a salvage operation to
* the head of the work queue */
#define SALVSYNC_QUERY SYNC_COM_CODE_DECL(4) /* query the status of a salvage */
#define SALVSYNC_CANCELALL SYNC_COM_CODE_DECL(5) /* cancel all pending salvages */
/* SALVSYNC reason codes */
#define SALVSYNC_WHATEVER SYNC_REASON_CODE_DECL(0) /* XXXX */
#define SALVSYNC_ERROR SYNC_REASON_CODE_DECL(1) /* volume is in error state */
#define SALVSYNC_OPERATOR SYNC_REASON_CODE_DECL(2) /* operator forced salvage */
#define SALVSYNC_SHUTDOWN SYNC_REASON_CODE_DECL(3) /* cancel due to shutdown */
#define SALVSYNC_NEEDED SYNC_REASON_CODE_DECL(4) /* needsSalvaged flag set */
/* SALVSYNC response codes */
/* SALVSYNC flags */
#define SALVSYNC_FLAG_VOL_STATS_VALID SYNC_FLAG_CODE_DECL(0) /* volume stats in response are valid */
/* SALVSYNC command state fields */
#define SALVSYNC_STATE_UNKNOWN 0 /* unknown state */
#define SALVSYNC_STATE_QUEUED 1 /* salvage request on queue */
#define SALVSYNC_STATE_SALVAGING 2 /* salvage is happening now */
#define SALVSYNC_STATE_ERROR 3 /* salvage ended in an error */
#define SALVSYNC_STATE_DONE 4 /* last salvage ended successfully */
typedef struct SALVSYNC_command_hdr {
afs_uint32 prio;
afs_uint32 volume;
char partName[16]; /* partition name, e.g. /vicepa */
} SALVSYNC_command_hdr;
typedef struct SALVSYNC_response_hdr {
afs_int32 state;
afs_int32 prio;
afs_int32 sq_len;
afs_int32 pq_len;
} SALVSYNC_response_hdr;
typedef struct SALVSYNC_command {
SYNC_command_hdr * hdr;
SALVSYNC_command_hdr * sop;
SYNC_command * com;
} SALVSYNC_command;
typedef struct SALVSYNC_response {
SYNC_response_hdr * hdr;
SALVSYNC_response_hdr * sop;
SYNC_response * res;
} SALVSYNC_response;
typedef struct SALVSYNC_command_info {
SYNC_command_hdr com;
SALVSYNC_command_hdr sop;
} SALVSYNC_command_info;
struct SalvageQueueNode {
struct rx_queue q;
struct rx_queue hash_chain;
afs_uint32 state;
struct SALVSYNC_command_info command;
afs_int32 partition_id;
int pid;
};
/* Prototypes from salvsync.c */
/* online salvager client interfaces */
extern int SALVSYNC_clientFinis(void);
extern int SALVSYNC_clientInit(void);
extern int SALVSYNC_clientReconnect(void);
extern afs_int32 SALVSYNC_askSalv(SYNC_command * com, SYNC_response * res);
extern afs_int32 SALVSYNC_SalvageVolume(VolumeId volume, char *partName, int com, int reason,
afs_uint32 prio, SYNC_response * res);
/* salvage server interfaces */
extern void SALVSYNC_salvInit(void);
extern struct SalvageQueueNode * SALVSYNC_getWork(void);
extern void SALVSYNC_doneWork(struct SalvageQueueNode *, int result);
extern void SALVSYNC_doneWorkByPid(int pid, int result);
#endif /* AFS_DEMAND_ATTACH_FS */
#endif /* _AFS_VOL_SALVSYNC_H */

View File

@ -102,6 +102,7 @@ RCSID
#include "afs/assert.h"
#include "filesignal.h"
#include "vutils.h"
#include "daemon_com.h"
#include "fssync.h"
#include <afs/auxinode.h>
#include <afs/dir.h>

View File

@ -102,6 +102,7 @@ RCSID
#include "afs/assert.h"
#include "filesignal.h"
#include "vutils.h"
#include "daemon_com.h"
#include "fssync.h"
#include <afs/auxinode.h>
#include <afs/dir.h>

View File

@ -5,6 +5,8 @@
* 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
*
* Portions Copyright (c) 2006 Sine Nomine Associates
*/
/*
@ -46,6 +48,7 @@ RCSID
#include "vnode.h"
#include "volume.h"
#include "partition.h"
#include "salvsync.h"
#if defined(AFS_SGI_ENV)
#include "sys/types.h"
#include "fcntl.h"
@ -73,8 +76,8 @@ RCSID
struct VnodeClassInfo VnodeClassInfo[nVNODECLASSES];
private int moveHash(register Vnode * vnp, bit32 newHash);
void StickOnLruChain_r(register Vnode * vnp,
register struct VnodeClassInfo *vcp);
private void StickOnLruChain_r(register Vnode * vnp,
register struct VnodeClassInfo *vcp);
#define BAD_IGET -1000
@ -162,6 +165,83 @@ private Vnode *VnodeHashTable[VNODE_HASH_TABLE_SIZE];
#define VNODE_HASH(volumeptr,vnodenumber)\
((volumeptr->vnodeHashOffset + vnodenumber)&(VNODE_HASH_TABLE_SIZE-1))
/*
* new support to secondarily hash vnodes by volume id
*/
#define VNVOLUME_HASH(volumeId) (volumeId&(VolumeHashTable.Mask))
#include "rx/rx_queue.h"
typedef struct VnodeHashByVolumeChainHead {
struct rx_queue queue;
int len;
/* someday we could put a per-chain lock here... */
#ifdef AFS_DEMAND_ATTACH_FS
int busy;
pthread_cond_t chain_busy_cv;
#endif /* AFS_DEMAND_ATTACH_FS */
} VnodeHashByVolumeChainHead;
private VnodeHashByVolumeChainHead *VnodeHashByVolumeTable = NULL;
void
VInitVnHashByVolume(void)
{
register int i;
VnodeHashByVolumeTable = (VnodeHashByVolumeChainHead *) calloc(VolumeHashTable.Size,
sizeof(VnodeHashByVolumeChainHead));
assert(VnodeHashByVolumeTable != NULL);
for (i=0; i < VolumeHashTable.Size; i++) {
queue_Init(&VnodeHashByVolumeTable[i]);
#ifdef AFS_DEMAND_ATTACH_FS
assert(pthread_cond_init(&VnodeHashByVolumeTable[i].chain_busy_cv, NULL) == 0);
#endif /* AFS_DEMAND_ATTACH_FS */
}
}
static void
AddToVnHashByVolumeTable(register Vnode * vnp)
{
VnodeHashByVolumeChainHead * head;
if (queue_IsOnQueue(vnp))
return;
head = &VnodeHashByVolumeTable[VNVOLUME_HASH(vnp->volumePtr->hashid)];
#ifdef AFS_DEMAND_ATTACH_FS
while (head->busy) {
/* if the hash table is busy, wait */
assert(pthread_cond_wait(&head->chain_busy_cv, &vol_glock_mutex) == 0);
}
#endif /* AFS_DEMAND_ATTACH_FS */
head->len++;
queue_Append(head, vnp);
}
/* for demand-attach, caller MUST hold a ref count on vp */
static void
DeleteFromVnHashByVolumeTable(register Vnode * vnp)
{
VnodeHashByVolumeChainHead * head;
if (!queue_IsOnQueue(vnp))
return;
head = &VnodeHashByVolumeTable[VNVOLUME_HASH(vnp->volumePtr->hashid)];
#ifdef AFS_DEMAND_ATTACH_FS
while (head->busy) {
/* if the hash table is busy, wait */
assert(pthread_cond_wait(&head->chain_busy_cv, &vol_glock_mutex) == 0);
}
#endif /* AFS_DEMAND_ATTACH_FS */
head->len--;
queue_Remove(vnp);
}
/* Code to invalidate a vnode entry. Called when we've damaged a vnode, and want
to prevent future VGetVnode's from applying to it. Leaves it in the same hash bucket
but that shouldn't be important. */
@ -305,7 +385,7 @@ VAllocVnode_r(Error * ec, Volume * vp, VnodeType type)
unique = vp->nextVnodeUnique++;
if (vp->nextVnodeUnique > V_uniquifier(vp)) {
VUpdateVolume_r(ec, vp);
VUpdateVolume_r(ec, vp, VOL_UPDATE_WAIT);
if (*ec)
return NULL;
}
@ -317,7 +397,8 @@ VAllocVnode_r(Error * ec, Volume * vp, VnodeType type)
}
/* Find a slot in the bit map */
bitNumber = VAllocBitmapEntry_r(ec, vp, &vp->vnodeIndex[class]);
bitNumber = VAllocBitmapEntry_r(ec, vp, &vp->vnodeIndex[class],
VOL_ALLOC_BITMAP_WAIT);
if (*ec)
return NULL;
vnodeNumber = bitNumberToVnodeNumber(bitNumber, class);
@ -376,7 +457,6 @@ VAllocVnode_r(Error * ec, Volume * vp, VnodeType type)
vnp->volumePtr = vp;
vnp->cacheCheck = vp->cacheCheck;
vnp->nUsers = 1;
moveHash(vnp, newHash);
/* This will never block */
ObtainWriteLock(&vnp->lock);
#ifdef AFS_PTHREAD_ENV
@ -391,18 +471,33 @@ VAllocVnode_r(Error * ec, Volume * vp, VnodeType type)
FdHandle_t *fdP;
off_t off = vnodeIndexOffset(vcp, vnodeNumber);
/* XXX we have a potential race here if two threads
* allocate new vnodes at the same time, and they
* both decide it's time to extend the index
* file size... */
VOL_UNLOCK;
fdP = IH_OPEN(ihP);
if (fdP == NULL)
Abort("VAllocVnode: can't open index file!\n");
if ((size = FDH_SIZE(fdP)) < 0)
Abort("VAllocVnode: can't stat index file!\n");
if (FDH_SEEK(fdP, off, SEEK_SET) < 0)
Abort("VAllocVnode: can't seek on index file!\n");
if (off < size) {
if (FDH_READ(fdP, &vnp->disk, vcp->diskSize) == vcp->diskSize) {
if (vnp->disk.type != vNull)
Abort("VAllocVnode: addled bitmap or index!\n");
if (fdP == NULL) {
Log("VAllocVnode: can't open index file!\n");
goto error_encountered;
}
if ((size = FDH_SIZE(fdP)) < 0) {
Log("VAllocVnode: can't stat index file!\n");
goto error_encountered;
}
if (FDH_SEEK(fdP, off, SEEK_SET) < 0) {
Log("VAllocVnode: can't seek on index file!\n");
goto error_encountered;
}
if (off + vcp->diskSize <= size) {
if (FDH_READ(fdP, &vnp->disk, vcp->diskSize) != vcp->diskSize) {
Log("VAllocVnode: can't read index file!\n");
goto error_encountered;
}
if (vnp->disk.type != vNull) {
Log("VAllocVnode: addled bitmap or index!\n");
goto error_encountered;
}
} else {
/* growing file - grow in a reasonable increment */
@ -414,9 +509,28 @@ VAllocVnode_r(Error * ec, Volume * vp, VnodeType type)
free(buf);
}
FDH_CLOSE(fdP);
fdP = NULL;
VOL_LOCK;
goto sane;
error_encountered:
#ifdef AFS_DEMAND_ATTACH_FS
VOL_LOCK;
VRequestSalvage_r(vp, SALVSYNC_ERROR, 0);
if (fdP)
FDH_CLOSE(fdP);
VInvalidateVnode_r(vnp);
StickOnLruChain_r(vnp, vcp);
return NULL;
#else
assert(1 == 2);
#endif
}
sane:
VNLog(4, 2, vnodeNumber, (afs_int32) vnp);
AddToVnHashByVolumeTable(vnp);
moveHash(vnp, newHash);
}
VNLog(5, 1, (afs_int32) vnp);
@ -510,6 +624,8 @@ VGetVnode_r(Error * ec, Volume * vp, VnodeId vnodeNumber, int locktype)
vcp->reads++;
vnp = VGetFreeVnode_r(vcp);
/* Remove it from the old hash chain */
if (vnp->volumePtr)
DeleteFromVnHashByVolumeTable(vnp);
moveHash(vnp, newHash);
/* Remove it from the LRU chain */
if (vnp == vcp->lruHead)
@ -525,6 +641,7 @@ VGetVnode_r(Error * ec, Volume * vp, VnodeId vnodeNumber, int locktype)
vnp->volumePtr = vp;
vnp->cacheCheck = vp->cacheCheck;
vnp->nUsers = 1;
AddToVnHashByVolumeTable(vnp);
/* This will never block */
ObtainWriteLock(&vnp->lock);
@ -540,11 +657,21 @@ VGetVnode_r(Error * ec, Volume * vp, VnodeId vnodeNumber, int locktype)
if (fdP == NULL) {
Log("VGetVnode: can't open index dev=%u, i=%s\n", vp->device,
PrintInode(NULL, vp->vnodeIndex[class].handle->ih_ino));
#ifdef AFS_DEMAND_ATTACH_FS
VOL_LOCK;
VRequestSalvage_r(vp, SALVSYNC_ERROR, 0);
VOL_UNLOCK;
#endif
*ec = VIO;
mlkReason = 9;
} else if (FDH_SEEK(fdP, vnodeIndexOffset(vcp, vnodeNumber), SEEK_SET)
< 0) {
Log("VGetVnode: can't seek on index file vn=%u\n", vnodeNumber);
#ifdef AFS_DEMAND_ATTACH_FS
VOL_LOCK;
VRequestSalvage_r(vp, SALVSYNC_ERROR, 0);
VOL_UNLOCK;
#endif
*ec = VIO;
mlkReason = 10;
FDH_REALLYCLOSE(fdP);
@ -564,8 +691,18 @@ VGetVnode_r(Error * ec, Volume * vp, VnodeId vnodeNumber, int locktype)
* is not allocated */
if (n == -1 && errno == EIO) {
Log("VGetVnode: Couldn't read vnode %u, volume %u (%s); volume needs salvage\n", vnodeNumber, V_id(vp), V_name(vp));
VForceOffline_r(vp);
#ifdef AFS_DEMAND_ATTACH_FS
if (programType == fileServer) {
VRequestSalvage_r(vp, SALVSYNC_ERROR, 0);
*ec = VSALVAGING;
} else {
VForceOffline_r(vp, 0);
*ec = VSALVAGE;
}
#else
VForceOffline_r(vp, 0);
*ec = VSALVAGE;
#endif
mlkReason = 4;
} else {
mlkReason = 5;
@ -603,9 +740,19 @@ VGetVnode_r(Error * ec, Volume * vp, VnodeId vnodeNumber, int locktype)
*ec = VNOVNODE;
} else {
Log("VGetVnode: Bad magic number, vnode %u, volume %u (%s); volume needs salvage\n", vnodeNumber, V_id(vp), V_name(vp));
#ifdef AFS_DEMAND_ATTACH_FS
if (programType == fileServer) {
VRequestSalvage_r(vp, SALVSYNC_ERROR, 0);
*ec = VSALVAGING;
} else {
vp->goingOffline = 1;
*ec = VSALVAGE;
}
#else
vp->goingOffline = 1; /* used to call VOffline, but that would mess
* up the volume ref count if called here */
*ec = VSALVAGE;
#endif
mlkReason = 7;
}
VInvalidateVnode_r(vnp);
@ -728,20 +875,27 @@ VPutVnode_r(Error * ec, register Vnode * vnp)
/* The vnode has been changed. Write it out to disk */
if (!V_inUse(vp)) {
#ifdef AFS_DEMAND_ATTACH_FS
VRequestSalvage_r(vp, SALVSYNC_ERROR, 0);
*ec = VSALVAGING;
#else
assert(V_needsSalvaged(vp));
*ec = VSALVAGE;
#endif
} else {
IHandle_t *ihP = vp->vnodeIndex[class].handle;
FdHandle_t *fdP;
VOL_UNLOCK;
fdP = IH_OPEN(ihP);
if (fdP == NULL)
Abort("VPutVnode: can't open index file!\n");
if (fdP == NULL) {
Log("VPutVnode: can't open index file!\n");
goto error_encountered;
}
offset = vnodeIndexOffset(vcp, vnp->vnodeNumber);
if (FDH_SEEK(fdP, offset, SEEK_SET) < 0) {
Abort
("VPutVnode: can't seek on index file! fdp=0x%x offset=%d, errno=%d\n",
fdP, offset, errno);
Log("VPutVnode: can't seek on index file! fdp=0x%x offset=%d, errno=%d\n",
fdP, offset, errno);
goto error_encountered;
}
code = FDH_WRITE(fdP, &vnp->disk, vcp->diskSize);
if (code != vcp->diskSize) {
@ -756,8 +910,13 @@ VPutVnode_r(Error * ec, register Vnode * vnp)
*ec = VIO;
} else {
Log("VPutVnode: Couldn't write vnode %u, volume %u (%s) (error %d)\n", vnp->vnodeNumber, V_id(vnp->volumePtr), V_name(vnp->volumePtr), code);
VForceOffline_r(vp);
#ifdef AFS_DEMAND_ATTACH_FS
VRequestSalvage_r(vp, SALVSYNC_ERROR, 0);
*ec = VSALVAGING;
#else
VForceOffline_r(vp, 0);
*ec = VSALVAGE;
#endif
}
VOL_UNLOCK;
FDH_REALLYCLOSE(fdP);
@ -765,6 +924,23 @@ VPutVnode_r(Error * ec, register Vnode * vnp)
FDH_CLOSE(fdP);
}
VOL_LOCK;
goto sane;
error_encountered:
#ifdef AFS_DEMAND_ATTACH_FS
/* XXX instead of dumping core, let's try to request a salvage
* and just fail the putvnode */
if (fdP)
FDH_CLOSE(fdP);
VOL_LOCK;
VRequestSalvage_r(vp, SALVSYNC_ERROR, 0);
*ec = VSALVAGING;
goto done;
#else
assert(1 == 2);
#endif
sane:
/* If the vnode is to be deleted, and we wrote the vnode out,
* free its bitmap entry. Do after the vnode is written so we
* don't allocate from bitmap before the vnode is written
@ -787,6 +963,7 @@ VPutVnode_r(Error * ec, register Vnode * vnp)
vnp);
}
done:
/* Do not look at disk portion of vnode after this point; it may
* have been deleted above */
if (vnp->nUsers-- == 1)
@ -865,19 +1042,28 @@ VVnodeWriteToRead_r(Error * ec, register Vnode * vnp)
/* The inode has been changed. Write it out to disk */
if (!V_inUse(vp)) {
#ifdef AFS_DEMAND_ATTACH_FS
VRequestSalvage_r(vp, SALVSYNC_ERROR, 0);
*ec = VSALVAGING;
#else
assert(V_needsSalvaged(vp));
*ec = VSALVAGE;
#endif
} else {
IHandle_t *ihP = vp->vnodeIndex[class].handle;
FdHandle_t *fdP;
off_t off = vnodeIndexOffset(vcp, vnp->vnodeNumber);
VOL_UNLOCK;
fdP = IH_OPEN(ihP);
if (fdP == NULL)
Abort("VPutVnode: can't open index file!\n");
if (fdP == NULL) {
Log("VPutVnode: can't open index file!\n");
goto error_encountered;
}
code = FDH_SEEK(fdP, off, SEEK_SET);
if (code < 0)
Abort("VPutVnode: can't seek on index file!\n");
if (code < 0) {
Log("VPutVnode: can't seek on index file!\n");
goto error_encountered;
}
code = FDH_WRITE(fdP, &vnp->disk, vcp->diskSize);
if (code != vcp->diskSize) {
/*
@ -892,14 +1078,33 @@ VVnodeWriteToRead_r(Error * ec, register Vnode * vnp)
*ec = VIO;
} else {
Log("VPutVnode: Couldn't write vnode %u, volume %u (%s)\n", vnp->vnodeNumber, V_id(vnp->volumePtr), V_name(vnp->volumePtr));
VForceOffline_r(vp);
#ifdef AFS_DEMAND_ATTACH_FS
VRequestSalvage_r(vp, SALVSYNC_ERROR, 0);
*ec = VSALVAGING;
#else
VForceOffline_r(vp, 0);
*ec = VSALVAGE;
#endif
}
VOL_UNLOCK;
}
FDH_CLOSE(fdP);
VOL_LOCK;
goto sane;
error_encountered:
#ifdef AFS_DEMAND_ATTACH_FS
if (fdP)
FDH_CLOSE(fdP);
VOL_LOCK;
VRequestSalvage_r(vp, SALVSYNC_ERROR, 0);
*ec = VSALVAGING;
#else
assert(1 == 2);
#endif
}
sane:
vcp->writes++;
vnp->changed_newTime = vnp->changed_oldTime = 0;
}
@ -931,7 +1136,7 @@ moveHash(register Vnode * vnp, bit32 newHash)
return 0;
}
void
private void
StickOnLruChain_r(register Vnode * vnp, register struct VnodeClassInfo *vcp)
{
/* Add it to the circular LRU list */
@ -950,8 +1155,10 @@ StickOnLruChain_r(register Vnode * vnp, register struct VnodeClassInfo *vcp)
vcp->lruHead = vnp->lruNext;
/* If caching is turned off, set volumeptr to NULL to invalidate the
* entry */
if (!TrustVnodeCacheEntry)
if (!TrustVnodeCacheEntry) {
DeleteFromVnHashByVolumeTable(vnp);
vnp->volumePtr = NULL;
}
}
/* VCloseVnodeFiles - called when a volume is going off line. All open
@ -962,15 +1169,30 @@ void
VCloseVnodeFiles_r(Volume * vp)
{
int i;
Vnode *vnp;
Vnode *vnp, *nvnp;
VnodeHashByVolumeChainHead * head;
for (i = 0; i < VNODE_HASH_TABLE_SIZE; i++) {
for (vnp = VnodeHashTable[i]; vnp; vnp = vnp->hashNext) {
if (vnp->volumePtr == vp) {
IH_REALLYCLOSE(vnp->handle);
}
head = &VnodeHashByVolumeTable[VNVOLUME_HASH(vp->hashid)];
#ifdef AFS_DEMAND_ATTACH_FS
while (head->busy) {
assert(pthread_cond_wait(&head->chain_busy_cv, &vol_glock_mutex) == 0);
}
head->busy = 1;
VOL_UNLOCK;
#endif /* AFS_DEMAND_ATTACH_FS */
for (queue_Scan(head, vnp, nvnp, Vnode)) {
if (vnp->volumePtr == vp) {
IH_REALLYCLOSE(vnp->handle);
}
}
#ifdef AFS_DEMAND_ATTACH_FS
VOL_LOCK;
head->busy = 0;
assert(pthread_cond_broadcast(&head->chain_busy_cv) == 0);
#endif /* AFS_DEMAND_ATTACH_FS */
}
/* VReleaseVnodeFiles - called when a volume is going detached. All open
@ -981,13 +1203,29 @@ void
VReleaseVnodeFiles_r(Volume * vp)
{
int i;
Vnode *vnp;
Vnode *vnp, *nvnp;
VnodeHashByVolumeChainHead * head;
for (i = 0; i < VNODE_HASH_TABLE_SIZE; i++) {
for (vnp = VnodeHashTable[i]; vnp; vnp = vnp->hashNext) {
if (vnp->volumePtr == vp) {
IH_RELEASE(vnp->handle);
}
head = &VnodeHashByVolumeTable[VNVOLUME_HASH(vp->hashid)];
#ifdef AFS_DEMAND_ATTACH_FS
while (head->busy) {
assert(pthread_cond_wait(&head->chain_busy_cv, &vol_glock_mutex) == 0);
}
head->busy = 1;
VOL_UNLOCK;
#endif /* AFS_DEMAND_ATTACH_FS */
for (queue_Scan(head, vnp, nvnp, Vnode)) {
if (vnp->volumePtr == vp) {
IH_RELEASE(vnp->handle);
}
}
#ifdef AFS_DEMAND_ATTACH_FS
VOL_LOCK;
head->busy = 0;
assert(pthread_cond_broadcast(&head->chain_busy_cv) == 0);
#endif /* AFS_DEMAND_ATTACH_FS */
}

View File

@ -118,6 +118,7 @@ typedef struct VnodeDiskObject {
#define SIZEOF_LARGEDISKVNODE 256
typedef struct Vnode {
struct rx_queue vid_hash; /* for vnode by volume id hash */
struct Vnode *hashNext; /* Next vnode on hash conflict chain */
struct Vnode *lruNext; /* Less recently used vnode than this one */
struct Vnode *lruPrev; /* More recently used vnode than this one */
@ -216,3 +217,4 @@ extern Vnode *VAllocVnode(Error * ec, struct Volume *vp, VnodeType type);
extern Vnode *VAllocVnode_r(Error * ec, struct Volume *vp, VnodeType type);
/*extern VFreeVnode();*/
extern Vnode *VGetFreeVnode_r(struct VnodeClassInfo *vcp);
extern void VInitVnHashByVolume(void);

View File

@ -83,11 +83,6 @@ Vnodes with 0 inode pointers in RW volumes are now deleted.
*/
#define SalvageVersion "2.4"
/* Main program file. Define globals. */
#define MAIN 1
#include <afsconfig.h>
#include <afs/param.h>
@ -186,10 +181,13 @@ RCSID
#include "vnode.h"
#include "volume.h"
#include "partition.h"
#include "daemon_com.h"
#include "fssync.h"
#include "salvsync.h"
#include "viceinode.h"
#include "salvage.h"
#include "volinodes.h" /* header magic number, etc. stuff */
#include "vol-salvage.h"
#ifdef AFS_NT40_ENV
#include <pthread.h>
#endif
@ -221,10 +219,6 @@ extern void *calloc();
#endif
static char *TimeStamp(time_t clock, int precision);
#define ORPH_IGNORE 0
#define ORPH_REMOVE 1
#define ORPH_ATTACH 2
int debug; /* -d flag */
int Testing = 0; /* -n flag */
@ -251,7 +245,7 @@ int OKToZap; /* -o flag */
int ForceSalvage; /* If salvage should occur despite the DONT_SALVAGE flag
* in the volume header */
static FILE *logFile = 0; /* one of {/usr/afs/logs,/vice/file}/SalvageLog */
FILE *logFile = 0; /* one of {/usr/afs/logs,/vice/file}/SalvageLog */
#define ROOTINODE 2 /* Root inode of a 4.2 Unix file system
* partition */
@ -279,201 +273,30 @@ int VolumeChanged; /* Set by any routine which would change the volume in
VolumeDiskData VolInfo; /* A copy of the last good or salvaged volume header dealt with */
struct InodeSummary { /* Inode summary file--an entry for each
* volume in the inode file for a partition */
VolId volumeId; /* Volume id */
VolId RWvolumeId; /* RW volume associated */
int index; /* index into inode file (0, 1, 2 ...) */
int nInodes; /* Number of inodes for this volume */
int nSpecialInodes; /* Number of special inodes, i.e. volume
* header, index, etc. These are all
* marked (viceinode.h) and will all be sorted
* to the beginning of the information for
* this volume. Read-only volumes should
* ONLY have special inodes (all the other
* inodes look as if they belong to the
* original RW volume). */
Unique maxUniquifier; /* The maximum uniquifier found in all the inodes.
* This is only useful for RW volumes and is used
* to compute a new volume uniquifier in the event
* that the header needs to be recreated. The inode
* uniquifier may be a truncated version of vnode
* uniquifier (AFS_3DISPARES). The real maxUniquifer
* is from the vnodes and later calcuated from it */
struct VolumeSummary *volSummary;
/* Either a pointer to the original volume
* header summary, or constructed summary
* information */
} *inodeSummary;
#define readOnly(isp) ((isp)->volumeId != (isp)->RWvolumeId)
int nVolumesInInodeFile; /* Number of read-write volumes summarized */
int inodeFd; /* File descriptor for inode file */
struct VolumeSummary { /* Volume summary an entry for each
* volume in a volume directory.
* Assumption: one volume directory per
* partition */
char *fileName; /* File name on the partition for the volume
* header */
struct VolumeHeader header;
/* volume number, rw volume number, inode
* numbers of each major component of
* the volume */
IHandle_t *volumeInfoHandle;
byte wouldNeedCallback; /* set if the file server should issue
* call backs for all the files in this volume when
* the volume goes back on line */
};
struct VnodeInfo {
IHandle_t *handle; /* Inode containing this index */
int nVnodes; /* Total number of vnodes in index */
int nAllocatedVnodes; /* Total number actually used */
int volumeBlockCount; /* Total number of blocks used by volume */
Inode *inodes; /* Directory only */
struct VnodeEssence {
short count; /* Number of references to vnode; MUST BE SIGNED */
unsigned claimed:1; /* Set when a parent directory containing an entry
* referencing this vnode is found. The claim
* is that the parent in "parent" can point to
* this vnode, and no other */
unsigned changed:1; /* Set if any parameters (other than the count)
* in the vnode change. It is determined if the
* link count has changed by noting whether it is
* 0 after scanning all directories */
unsigned salvaged:1; /* Set if this directory vnode has already been salvaged. */
unsigned todelete:1; /* Set if this vnode is to be deleted (should not be claimed) */
afs_fsize_t blockCount;
/* Number of blocks (1K) used by this vnode,
* approximately */
VnodeId parent; /* parent in vnode */
Unique unique; /* Must match entry! */
char *name; /* Name of directory entry */
int modeBits; /* File mode bits */
Inode InodeNumber; /* file's inode */
int type; /* File type */
int author; /* File author */
int owner; /* File owner */
int group; /* File group */
} *vnodes;
} vnodeInfo[nVNODECLASSES];
struct DirSummary {
struct DirHandle dirHandle;
VnodeId vnodeNumber;
Unique unique;
unsigned haveDot, haveDotDot;
VolumeId rwVid;
int copied; /* If the copy-on-write stuff has been applied */
VnodeId parent;
char *name;
char *vname;
IHandle_t *ds_linkH;
};
struct VnodeInfo vnodeInfo[nVNODECLASSES];
struct VolumeSummary *volumeSummaryp; /* Holds all the volumes in a part */
int nVolumes; /* Number of volumes (read-write and read-only)
* in volume summary */
#ifdef AFS_NT40_ENV
/* For NT, we can fork the per partition salvagers to gain the required
* safety against Aborts. But there's too many complex data structures at
* the per volume salvager layer to easilty copy the data across.
* childJobNumber is resset from -1 to the job number if this is a
* per partition child of the main salvager. This information is passed
* out-of-band in the extra data area setup for the now unused parent/child
* data transfer.
*/
#define SALVAGER_MAGIC 0x00BBaaDD
#define NOT_CHILD -1 /* job numbers start at 0 */
/* If new options need to be passed to child, add them here. */
typedef struct {
int cj_magic;
int cj_number;
char cj_part[32];
} childJob_t;
extern char * tmpdir = 0;
#ifdef AFS_NT40_ENV
/* Child job this process is running. */
childJob_t myjob = { SALVAGER_MAGIC, NOT_CHILD, "" };
int nt_SalvagePartition(char *partName, int jobn);
int nt_SetupPartitionSalvage(void *datap, int len);
typedef struct {
struct InodeSummary *svgp_inodeSummaryp;
int svgp_count;
} SVGParms_t;
#define canfork 0
#else
#define canfork 1
#endif
#endif /* AFS_NT40_ENV */
/* Forward declarations */
/*@printflike@*/ void Log(const char *format, ...);
/*@printflike@*/ void Abort(const char *format, ...);
void Exit(int code);
int Fork(void);
int Wait(char *prog);
char *ToString(char *s);
void AskOffline(VolumeId volumeId);
void AskOnline(VolumeId volumeId, char *partition);
void CheckLogFile(void);
#ifndef AFS_NT40_ENV
void TimeStampLogFile(void);
#endif
void ClearROInUseBit(struct VolumeSummary *summary);
void CopyAndSalvage(register struct DirSummary *dir);
int CopyInode(Device device, Inode inode1, Inode inode2, int rwvolume);
void CopyOnWrite(register struct DirSummary *dir);
void CountVolumeInodes(register struct ViceInodeInfo *ip, int maxInodes,
register struct InodeSummary *summary);
void DeleteExtraVolumeHeaderFile(register struct VolumeSummary *vsp);
void DistilVnodeEssence(VolumeId vid, VnodeClass class, Inode ino,
Unique * maxu);
int GetInodeSummary(char *path, VolumeId singleVolumeNumber);
void GetVolumeSummary(VolumeId singleVolumeNumber);
void JudgeEntry(struct DirSummary *dir, char *name, VnodeId vnodeNumber,
Unique unique);
void MaybeZapVolume(register struct InodeSummary *isp, char *message,
int deleteMe, int check);
void ObtainSalvageLock(void);
void PrintInodeList(void);
void PrintInodeSummary(void);
void PrintVolumeSummary(void);
int QuickCheck(register struct InodeSummary *isp, int nVols);
void RemoveTheForce(char *path);
void SalvageDir(char *name, VolumeId rwVid, struct VnodeInfo *dirVnodeInfo,
IHandle_t * alinkH, int i, struct DirSummary *rootdir,
int *rootdirfound);
void SalvageFileSysParallel(struct DiskPartition *partP);
void SalvageFileSys(struct DiskPartition *partP, VolumeId singleVolumeNumber);
void SalvageFileSys1(struct DiskPartition *partP,
VolumeId singleVolumeNumber);
int SalvageHeader(register struct stuff *sp, struct InodeSummary *isp,
int check, int *deleteMe);
int SalvageIndex(Inode ino, VnodeClass class, int RW,
register struct ViceInodeInfo *ip, int nInodes,
struct VolumeSummary *volSummary, int check);
int SalvageVnodes(register struct InodeSummary *rwIsp,
register struct InodeSummary *thisIsp,
register struct ViceInodeInfo *inodes, int check);
int SalvageVolume(register struct InodeSummary *rwIsp, IHandle_t * alinkH);
void DoSalvageVolumeGroup(register struct InodeSummary *isp, int nVols);
#ifdef AFS_NT40_ENV
void SalvageVolumeGroup(register struct InodeSummary *isp, int nVols);
#else
#define SalvageVolumeGroup DoSalvageVolumeGroup
#endif
int SalvageVolumeHeaderFile(register struct InodeSummary *isp,
register struct ViceInodeInfo *inodes, int RW,
int check, int *deleteMe);
void showlog(void);
int UseTheForceLuke(char *path);
static int IsVnodeOrphaned(VnodeId vnode);
/* Uniquifier stored in the Inode */
@ -500,207 +323,6 @@ BadError(register int aerror)
}
char *tmpdir = 0;
static int
handleit(struct cmd_syndesc *as)
{
register struct cmd_item *ti;
char pname[100], *temp;
afs_int32 seenpart = 0, seenvol = 0, vid = 0, seenany = 0;
struct DiskPartition *partP;
#ifdef AFS_SGI_VNODE_GLUE
if (afs_init_kernel_config(-1) < 0) {
printf
("Can't determine NUMA configuration, not starting salvager.\n");
exit(1);
}
#endif
#ifdef FAST_RESTART
{
afs_int32 i;
for (i = 0; i < CMD_MAXPARMS; i++) {
if (as->parms[i].items) {
seenany = 1;
break;
}
}
}
if (!seenany) {
char *msg =
"Exiting immediately without salvage. Look into the FileLog to find volumes which really need to be salvaged!";
if (useSyslog)
Log(msg);
else
printf("%s\n", msg);
Exit(0);
}
#endif /* FAST_RESTART */
if ((ti = as->parms[0].items)) { /* -partition */
seenpart = 1;
strncpy(pname, ti->data, 100);
}
if ((ti = as->parms[1].items)) { /* -volumeid */
if (!seenpart) {
printf
("You must also specify '-partition' option with the '-volumeid' option\n");
exit(-1);
}
seenvol = 1;
vid = atoi(ti->data);
}
if (as->parms[2].items) /* -debug */
debug = 1;
if (as->parms[3].items) /* -nowrite */
Testing = 1;
if (as->parms[4].items) /* -inodes */
ListInodeOption = 1;
if (as->parms[5].items) /* -force */
ForceSalvage = 1;
if (as->parms[6].items) /* -oktozap */
OKToZap = 1;
if (as->parms[7].items) /* -rootinodes */
ShowRootFiles = 1;
if (as->parms[8].items) /* -RebuildDirs */
RebuildDirs = 1;
if (as->parms[9].items) /* -ForceReads */
forceR = 1;
if ((ti = as->parms[10].items)) { /* -Parallel # */
temp = ti->data;
if (strncmp(temp, "all", 3) == 0) {
PartsPerDisk = 1;
temp += 3;
}
if (strlen(temp) != 0) {
Parallel = atoi(temp);
if (Parallel < 1)
Parallel = 1;
if (Parallel > MAXPARALLEL) {
printf("Setting parallel salvages to maximum of %d \n",
MAXPARALLEL);
Parallel = MAXPARALLEL;
}
}
}
if ((ti = as->parms[11].items)) { /* -tmpdir */
DIR *dirp;
tmpdir = ti->data;
dirp = opendir(tmpdir);
if (!dirp) {
printf
("Can't open temporary placeholder dir %s; using current partition \n",
tmpdir);
tmpdir = NULL;
} else
closedir(dirp);
}
if ((ti = as->parms[12].items)) /* -showlog */
ShowLog = 1;
if ((ti = as->parms[13].items)) { /* -log */
Testing = 1;
ShowSuid = 1;
Showmode = 1;
}
if ((ti = as->parms[14].items)) { /* -showmounts */
Testing = 1;
Showmode = 1;
ShowMounts = 1;
}
if ((ti = as->parms[15].items)) { /* -orphans */
if (Testing)
orphans = ORPH_IGNORE;
else if (strcmp(ti->data, "remove") == 0
|| strcmp(ti->data, "r") == 0)
orphans = ORPH_REMOVE;
else if (strcmp(ti->data, "attach") == 0
|| strcmp(ti->data, "a") == 0)
orphans = ORPH_ATTACH;
}
#ifndef AFS_NT40_ENV /* ignore options on NT */
if ((ti = as->parms[16].items)) { /* -syslog */
useSyslog = 1;
ShowLog = 0;
}
if ((ti = as->parms[17].items)) { /* -syslogfacility */
useSyslogFacility = atoi(ti->data);
}
if ((ti = as->parms[18].items)) { /* -datelogs */
TimeStampLogFile();
}
#endif
#ifdef FAST_RESTART
if (ti = as->parms[19].items) { /* -DontSalvage */
char *msg =
"Exiting immediately without salvage. Look into the FileLog to find volumes which really need to be salvaged!";
if (useSyslog)
Log(msg);
else
printf("%s\n", msg);
Exit(0);
}
#endif /* FAST_RESTART */
/* Note: if seemvol we initialize this as a standard volume utility: this has the
* implication that the file server may be running; negotations have to be made with
* the file server in this case to take the read write volume and associated read-only
* volumes off line before salvaging */
#ifdef AFS_NT40_ENV
if (seenvol) {
if (afs_winsockInit() < 0) {
ReportErrorEventAlt(AFSEVT_SVR_WINSOCK_INIT_FAILED, 0,
AFSDIR_SALVAGER_FILE, 0);
Log("Failed to initailize winsock, exiting.\n");
Exit(1);
}
}
#endif
VInitVolumePackage(seenvol ? volumeUtility : salvager, 5, 5,
DONT_CONNECT_FS, 0);
DInit(10);
#ifdef AFS_NT40_ENV
if (myjob.cj_number != NOT_CHILD) {
if (!seenpart) {
seenpart = 1;
(void)strcpy(pname, myjob.cj_part);
}
}
#endif
if (seenpart == 0) {
for (partP = DiskPartitionList; partP; partP = partP->next) {
SalvageFileSysParallel(partP);
}
SalvageFileSysParallel(0);
} else {
partP = VGetPartition(pname, 0);
if (!partP) {
Log("salvage: Unknown or unmounted partition %s; salvage aborted\n", pname);
Exit(1);
}
if (!seenvol)
SalvageFileSys(partP, 0);
else {
/* Salvage individual volume */
if (vid <= 0) {
Log("salvage: invalid volume id specified; salvage aborted\n");
Exit(1);
}
SalvageFileSys(partP, vid);
}
}
return (0);
}
#ifndef AFS_NT40_ENV
#include "AFS_component_version_number.c"
#endif
#define MAX_ARGS 128
#ifdef AFS_NT40_ENV
char *save_args[MAX_ARGS];
@ -708,143 +330,6 @@ int n_save_args = 0;
pthread_t main_thread;
#endif
int
main(int argc, char **argv)
{
struct cmd_syndesc *ts;
int err = 0;
char commandLine[150];
int i;
extern char cml_version_number[];
#ifdef AFS_AIX32_ENV
/*
* The following signal action for AIX is necessary so that in case of a
* crash (i.e. core is generated) we can include the user's data section
* in the core dump. Unfortunately, by default, only a partial core is
* generated which, in many cases, isn't too useful.
*/
struct sigaction nsa;
sigemptyset(&nsa.sa_mask);
nsa.sa_handler = SIG_DFL;
nsa.sa_flags = SA_FULLDUMP;
sigaction(SIGABRT, &nsa, NULL);
sigaction(SIGSEGV, &nsa, NULL);
#endif
/* Initialize directory paths */
if (!(initAFSDirPath() & AFSDIR_SERVER_PATHS_OK)) {
#ifdef AFS_NT40_ENV
ReportErrorEventAlt(AFSEVT_SVR_NO_INSTALL_DIR, 0, argv[0], 0);
#endif
fprintf(stderr, "%s: Unable to obtain AFS server directory.\n",
argv[0]);
exit(2);
}
#ifdef AFS_NT40_ENV
main_thread = pthread_self();
if (spawnDatap && spawnDataLen) {
/* This is a child per partition salvager. Don't setup log or
* try to lock the salvager lock.
*/
if (nt_SetupPartitionSalvage(spawnDatap, spawnDataLen) < 0)
exit(3);
} else {
#endif
for (commandLine[0] = '\0', i = 0; i < argc; i++) {
if (i > 0)
strcat(commandLine, " ");
strcat(commandLine, argv[i]);
}
/* All entries to the log will be appended. Useful if there are
* multiple salvagers appending to the log.
*/
CheckLogFile();
#ifndef AFS_NT40_ENV
#ifdef AFS_LINUX20_ENV
fcntl(fileno(logFile), F_SETFL, O_APPEND); /* Isn't this redundant? */
#else
fcntl(fileno(logFile), F_SETFL, FAPPEND); /* Isn't this redundant? */
#endif
#endif
setlinebuf(logFile);
#ifndef AFS_NT40_ENV
if (geteuid() != 0) {
printf("Salvager must be run as root.\n");
fflush(stdout);
Exit(0);
}
#endif
/* bad for normal help flag processing, but can do nada */
fprintf(logFile, "%s\n", cml_version_number);
Log("STARTING AFS SALVAGER %s (%s)\n", SalvageVersion, commandLine);
/* Get and hold a lock for the duration of the salvage to make sure
* that no other salvage runs at the same time. The routine
* VInitVolumePackage (called below) makes sure that a file server or
* other volume utilities don't interfere with the salvage.
*/
ObtainSalvageLock();
#ifdef AFS_NT40_ENV
}
#endif
ts = cmd_CreateSyntax("initcmd", handleit, 0, "initialize the program");
cmd_AddParm(ts, "-partition", CMD_SINGLE, CMD_OPTIONAL,
"Name of partition to salvage");
cmd_AddParm(ts, "-volumeid", CMD_SINGLE, CMD_OPTIONAL,
"Volume Id to salvage");
cmd_AddParm(ts, "-debug", CMD_FLAG, CMD_OPTIONAL,
"Run in Debugging mode");
cmd_AddParm(ts, "-nowrite", CMD_FLAG, CMD_OPTIONAL,
"Run readonly/test mode");
cmd_AddParm(ts, "-inodes", CMD_FLAG, CMD_OPTIONAL,
"Just list affected afs inodes - debugging flag");
cmd_AddParm(ts, "-force", CMD_FLAG, CMD_OPTIONAL, "Force full salvaging");
cmd_AddParm(ts, "-oktozap", CMD_FLAG, CMD_OPTIONAL,
"Give permission to destroy bogus inodes/volumes - debugging flag");
cmd_AddParm(ts, "-rootinodes", CMD_FLAG, CMD_OPTIONAL,
"Show inodes owned by root - debugging flag");
cmd_AddParm(ts, "-salvagedirs", CMD_FLAG, CMD_OPTIONAL,
"Force rebuild/salvage of all directories");
cmd_AddParm(ts, "-blockreads", CMD_FLAG, CMD_OPTIONAL,
"Read smaller blocks to handle IO/bad blocks");
cmd_AddParm(ts, "-parallel", CMD_SINGLE, CMD_OPTIONAL,
"# of max parallel partition salvaging");
cmd_AddParm(ts, "-tmpdir", CMD_SINGLE, CMD_OPTIONAL,
"Name of dir to place tmp files ");
cmd_AddParm(ts, "-showlog", CMD_FLAG, CMD_OPTIONAL,
"Show log file upon completion");
cmd_AddParm(ts, "-showsuid", CMD_FLAG, CMD_OPTIONAL,
"Report on suid/sgid files");
cmd_AddParm(ts, "-showmounts", CMD_FLAG, CMD_OPTIONAL,
"Report on mountpoints");
cmd_AddParm(ts, "-orphans", CMD_SINGLE, CMD_OPTIONAL,
"ignore | remove | attach");
/* note - syslog isn't avail on NT, but if we make it conditional, have
* to deal with screwy offsets for cmd params */
cmd_AddParm(ts, "-syslog", CMD_FLAG, CMD_OPTIONAL,
"Write salvage log to syslogs");
cmd_AddParm(ts, "-syslogfacility", CMD_SINGLE, CMD_OPTIONAL,
"Syslog facility number to use");
cmd_AddParm(ts, "-datelogs", CMD_FLAG, CMD_OPTIONAL,
"Include timestamp in logfile filename");
#ifdef FAST_RESTART
cmd_AddParm(ts, "-DontSalvage", CMD_FLAG, CMD_OPTIONAL,
"Don't salvage. This my be set in BosConfig to let the fileserver restart immediately after a crash. Bad volumes will be taken offline");
#endif /* FAST_RESTART */
err = cmd_Dispatch(argc, argv);
Exit(err);
}
/* Get the salvage lock if not already held. Hold until process exits. */
void
@ -1249,7 +734,8 @@ SalvageFileSys1(struct DiskPartition *partP, VolumeId singleVolumeNumber)
ForceSalvage = UseTheForceLuke(fileSysPath);
if (singleVolumeNumber) {
if (!VConnectFS()) {
/* salvageserver already setup fssync conn for us */
if ((programType != salvageServer) && !VConnectFS()) {
Abort("Couldn't connect to file server\n");
}
AskOffline(singleVolumeNumber);
@ -2554,7 +2040,7 @@ SalvageIndex(Inode ino, VnodeClass class, int RW,
* if no such match, take the first determined by our sort
* order */
register struct ViceInodeInfo *lip = ip;
register lnInodes = nInodes;
register int lnInodes = nInodes;
while (lnInodes
&& lip->u.vnode.vnodeNumber == vnodeNumber) {
if (VNDISK_GET_INO(vnode) == lip->inodeNumber) {
@ -3628,8 +3114,38 @@ MaybeZapVolume(register struct InodeSummary *isp, char *message, int deleteMe,
void
AskOffline(VolumeId volumeId)
{
if (FSYNC_askfs(volumeId, NULL, FSYNC_OFF, FSYNC_SALVAGE) == FSYNC_DENIED) {
Log("AskOffline: file server denied offline request; a general salvage is required.\n");
afs_int32 code, i;
for (i = 0; i < 3; i++) {
code = FSYNC_VolOp(volumeId, NULL, FSYNC_VOL_OFF, FSYNC_SALVAGE, NULL);
if (code == SYNC_OK) {
break;
} else if (code == SYNC_DENIED) {
#ifdef DEMAND_ATTACH_ENABLE
Log("AskOffline: file server denied offline request; a general salvage may be required.\n");
#else
Log("AskOffline: file server denied offline request; a general salvage is required.\n");
#endif
Abort("Salvage aborted\n");
} else if (code == SYNC_BAD_COMMAND) {
Log("AskOffline: fssync protocol mismatch (bad command word '%d'); salvage aborting.\n",
FSYNC_VOL_OFF);
#ifdef DEMAND_ATTACH_ENABLE
Log("AskOffline: please make sure fileserver, volserver, salvageserver and salvager binaries are same version.\n");
#else
Log("AskOffline: please make sure fileserver, volserver and salvager binaries are same version.\n");
#endif
Abort("Salvage aborted\n");
} else if (i < 2) {
/* try it again */
Log("AskOffline: request for fileserver to take volume offline failed; trying again...\n");
FSYNC_clientFinis();
FSYNC_clientInit();
}
}
if (code != SYNC_OK) {
Log("AskOffline: request for fileserver to take volume offline failed; salvage aborting.\n");
Abort("Salvage aborted\n");
}
}
@ -3637,8 +3153,30 @@ AskOffline(VolumeId volumeId)
void
AskOnline(VolumeId volumeId, char *partition)
{
if (FSYNC_askfs(volumeId, partition, FSYNC_ON, 0) == FSYNC_DENIED) {
Log("AskOnline: file server denied online request to volume %u partition %s\n", volumeId, partition);
afs_int32 code, i;
for (i = 0; i < 3; i++) {
code = FSYNC_VolOp(volumeId, partition, 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);
} else if (code == SYNC_BAD_COMMAND) {
Log("AskOnline: fssync protocol mismatch (bad command word '%d')\n",
FSYNC_VOL_ON);
#ifdef DEMAND_ATTACH_ENABLE
Log("AskOnline: please make sure fileserver, volserver, salvageserver and salvager binaries are same version.\n");
#else
Log("AskOnline: please make sure fileserver, volserver and salvager binaries are same version.\n");
#endif
break;
} else if (i < 2) {
/* try it again */
Log("AskOnline: request for fileserver to take volume offline failed; trying again...\n");
FSYNC_clientFinis();
FSYNC_clientInit();
}
}
}
@ -3772,7 +3310,7 @@ TimeStamp(time_t clock, int precision)
}
void
CheckLogFile(void)
CheckLogFile(char * log_path)
{
char oldSlvgLog[AFSDIR_PATH_MAX];
@ -3783,11 +3321,11 @@ CheckLogFile(void)
}
#endif
strcpy(oldSlvgLog, AFSDIR_SERVER_SLVGLOG_FILEPATH);
strcpy(oldSlvgLog, log_path);
strcat(oldSlvgLog, ".old");
if (!logFile) {
renamefile(AFSDIR_SERVER_SLVGLOG_FILEPATH, oldSlvgLog);
logFile = afs_fopen(AFSDIR_SERVER_SLVGLOG_FILEPATH, "a");
renamefile(log_path, oldSlvgLog);
logFile = afs_fopen(log_path, "a");
if (!logFile) { /* still nothing, use stdout */
logFile = stdout;
@ -3801,7 +3339,7 @@ CheckLogFile(void)
#ifndef AFS_NT40_ENV
void
TimeStampLogFile(void)
TimeStampLogFile(char * log_path)
{
char stampSlvgLog[AFSDIR_PATH_MAX];
struct tm *lt;
@ -3811,13 +3349,13 @@ TimeStampLogFile(void)
lt = localtime(&now);
(void)afs_snprintf(stampSlvgLog, sizeof stampSlvgLog,
"%s.%04d-%02d-%02d.%02d:%02d:%02d",
AFSDIR_SERVER_SLVGLOG_FILEPATH, lt->tm_year + 1900,
log_path, lt->tm_year + 1900,
lt->tm_mon + 1, lt->tm_mday, lt->tm_hour, lt->tm_min,
lt->tm_sec);
/* try to link the logfile to a timestamped filename */
/* if it fails, oh well, nothing we can do */
link(AFSDIR_SERVER_SLVGLOG_FILEPATH, stampSlvgLog);
link(log_path, stampSlvgLog);
}
#endif
@ -3937,7 +3475,7 @@ UseTheForceLuke(char *path)
*
* NOTE:
* The VRMIX fsck will not muck with the filesystem it is supposedly
* fixing and create a "FORCESAVAGE" file (by design). Instead, we
* fixing and create a "FORCESALVAGE" file (by design). Instead, we
* muck directly with the root inode, which is within the normal
* domain of fsck.
* ListViceInodes() has a side effect of setting ForceSalvage if

282
src/vol/vol-salvage.h Normal file
View File

@ -0,0 +1,282 @@
/*
* 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
*/
/*
* Module: vol-salvage.h
*/
#ifndef __vol_salvage_h_
#define __vol_salvage_h_
#define SalvageVersion "2.4"
#include "salvage.h"
#include "volinodes.h"
/* salvager data structures */
struct InodeSummary { /* Inode summary file--an entry for each
* volume in the inode file for a partition */
VolId volumeId; /* Volume id */
VolId RWvolumeId; /* RW volume associated */
int index; /* index into inode file (0, 1, 2 ...) */
int nInodes; /* Number of inodes for this volume */
int nSpecialInodes; /* Number of special inodes, i.e. volume
* header, index, etc. These are all
* marked (viceinode.h) and will all be sorted
* to the beginning of the information for
* this volume. Read-only volumes should
* ONLY have special inodes (all the other
* inodes look as if they belong to the
* original RW volume). */
Unique maxUniquifier; /* The maximum uniquifier found in all the inodes.
* This is only useful for RW volumes and is used
* to compute a new volume uniquifier in the event
* that the header needs to be recreated. The inode
* uniquifier may be a truncated version of vnode
* uniquifier (AFS_3DISPARES). The real maxUniquifer
* is from the vnodes and later calcuated from it */
struct VolumeSummary *volSummary;
/* Either a pointer to the original volume
* header summary, or constructed summary
* information */
} *inodeSummary;
#define readOnly(isp) ((isp)->volumeId != (isp)->RWvolumeId)
struct VolumeSummary { /* Volume summary an entry for each
* volume in a volume directory.
* Assumption: one volume directory per
* partition */
char *fileName; /* File name on the partition for the volume
* header */
struct VolumeHeader header;
/* volume number, rw volume number, inode
* numbers of each major component of
* the volume */
IHandle_t *volumeInfoHandle;
byte wouldNeedCallback; /* set if the file server should issue
* call backs for all the files in this volume when
* the volume goes back on line */
};
struct VnodeInfo {
IHandle_t *handle; /* Inode containing this index */
int nVnodes; /* Total number of vnodes in index */
int nAllocatedVnodes; /* Total number actually used */
int volumeBlockCount; /* Total number of blocks used by volume */
Inode *inodes; /* Directory only */
struct VnodeEssence {
short count; /* Number of references to vnode; MUST BE SIGNED */
unsigned claimed:1; /* Set when a parent directory containing an entry
* referencing this vnode is found. The claim
* is that the parent in "parent" can point to
* this vnode, and no other */
unsigned changed:1; /* Set if any parameters (other than the count)
* in the vnode change. It is determined if the
* link count has changed by noting whether it is
* 0 after scanning all directories */
unsigned salvaged:1; /* Set if this directory vnode has already been salvaged. */
unsigned todelete:1; /* Set if this vnode is to be deleted (should not be claimed) */
afs_fsize_t blockCount;
/* Number of blocks (1K) used by this vnode,
* approximately */
VnodeId parent; /* parent in vnode */
Unique unique; /* Must match entry! */
char *name; /* Name of directory entry */
int modeBits; /* File mode bits */
Inode InodeNumber; /* file's inode */
int type; /* File type */
int author; /* File author */
int owner; /* File owner */
int group; /* File group */
} *vnodes;
};
struct DirSummary {
struct DirHandle dirHandle;
VnodeId vnodeNumber;
Unique unique;
unsigned haveDot, haveDotDot;
VolumeId rwVid;
int copied; /* If the copy-on-write stuff has been applied */
VnodeId parent;
char *name;
char *vname;
IHandle_t *ds_linkH;
};
#define ORPH_IGNORE 0
#define ORPH_REMOVE 1
#define ORPH_ATTACH 2
/* command line options */
extern int debug; /* -d flag */
extern int Testing; /* -n flag */
extern int ListInodeOption; /* -i flag */
extern int ShowRootFiles; /* -r flag */
extern int RebuildDirs; /* -sal flag */
extern int Parallel; /* -para X flag */
extern int PartsPerDisk; /* Salvage up to 8 partitions on same disk sequentially */
extern int forceR; /* -b flag */
extern int ShowLog; /* -showlog flag */
extern int ShowSuid; /* -showsuid flag */
extern int ShowMounts; /* -showmounts flag */
extern int orphans; /* -orphans option */
extern int Showmode;
#ifndef AFS_NT40_ENV
extern int useSyslog; /* -syslog flag */
extern int useSyslogFacility; /* -syslogfacility option */
#endif
#define MAXPARALLEL 32
extern int OKToZap; /* -o flag */
extern int ForceSalvage; /* If salvage should occur despite the DONT_SALVAGE flag
* in the volume header */
#define ROOTINODE 2 /* Root inode of a 4.2 Unix file system
* partition */
extern Device fileSysDevice; /* The device number of the current
* partition being salvaged */
#ifdef AFS_NT40_ENV
extern char fileSysPath[8];
#else
extern char *fileSysPath; /* The path of the mounted partition currently
* being salvaged, i.e. the directory
* containing the volume headers */
#endif /* AFS_NT40_ENV */
extern char *fileSysPathName; /* NT needs this to make name pretty in log. */
extern IHandle_t *VGLinkH; /* Link handle for current volume group. */
extern int VGLinkH_cnt; /* # of references to lnk handle. */
extern struct DiskPartition *fileSysPartition; /* Partition being salvaged */
#ifndef AFS_NT40_ENV
extern char *fileSysDeviceName; /* The block device where the file system
* being salvaged was mounted */
extern char *filesysfulldev;
#endif /* AFS_NT40_ENV */
extern 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 */
extern VolumeDiskData VolInfo; /* A copy of the last good or salvaged volume header dealt with */
extern int nVolumesInInodeFile; /* Number of read-write volumes summarized */
extern int inodeFd; /* File descriptor for inode file */
extern struct VnodeInfo vnodeInfo[nVNODECLASSES];
extern struct VolumeSummary *volumeSummaryp; /* Holds all the volumes in a part */
extern int nVolumes; /* Number of volumes (read-write and read-only)
* in volume summary */
extern char * tmpdir;
extern FILE *logFile; /* one of {/usr/afs/logs,/vice/file}/SalvageLog */
#ifdef AFS_NT40_ENV
/* For NT, we can fork the per partition salvagers to gain the required
* safety against Aborts. But there's too many complex data structures at
* the per volume salvager layer to easilty copy the data across.
* childJobNumber is resset from -1 to the job number if this is a
* per partition child of the main salvager. This information is passed
* out-of-band in the extra data area setup for the now unused parent/child
* data transfer.
*/
#define SALVAGER_MAGIC 0x00BBaaDD
#define NOT_CHILD -1 /* job numbers start at 0 */
/* If new options need to be passed to child, add them here. */
typedef struct {
int cj_magic;
int cj_number;
char cj_part[32];
} childJob_t;
/* Child job this process is running. */
extern childJob_t myjob = { SALVAGER_MAGIC, NOT_CHILD, "" };
extern int nt_SalvagePartition(char *partName, int jobn);
extern int nt_SetupPartitionSalvage(void *datap, int len);
typedef struct {
struct InodeSummary *svgp_inodeSummaryp;
int svgp_count;
} SVGParms_t;
#define canfork 0
#else /* AFS_NT40_ENV */
#define canfork 1
#endif /* AFS_NT40_ENV */
/* prototypes */
extern void Exit(int code);
extern int Fork(void);
extern int Wait(char *prog);
extern char *ToString(char *s);
extern void AskOffline(VolumeId volumeId);
extern void AskOnline(VolumeId volumeId, char *partition);
extern void CheckLogFile(char * log_path);
#ifndef AFS_NT40_ENV
extern void TimeStampLogFile(char * log_path);
#endif
extern void ClearROInUseBit(struct VolumeSummary *summary);
extern void CopyAndSalvage(register struct DirSummary *dir);
extern int CopyInode(Device device, Inode inode1, Inode inode2, int rwvolume);
extern void CopyOnWrite(register struct DirSummary *dir);
extern void CountVolumeInodes(register struct ViceInodeInfo *ip, int maxInodes,
register struct InodeSummary *summary);
extern void DeleteExtraVolumeHeaderFile(register struct VolumeSummary *vsp);
extern void DistilVnodeEssence(VolumeId vid, VnodeClass class, Inode ino,
Unique * maxu);
extern int GetInodeSummary(char *path, VolumeId singleVolumeNumber);
extern void GetVolumeSummary(VolumeId singleVolumeNumber);
extern void JudgeEntry(struct DirSummary *dir, char *name, VnodeId vnodeNumber,
Unique unique);
extern void MaybeZapVolume(register struct InodeSummary *isp, char *message,
int deleteMe, int check);
extern void ObtainSalvageLock(void);
extern void PrintInodeList(void);
extern void PrintInodeSummary(void);
extern void PrintVolumeSummary(void);
extern int QuickCheck(register struct InodeSummary *isp, int nVols);
extern void RemoveTheForce(char *path);
extern void SalvageDir(char *name, VolumeId rwVid, struct VnodeInfo *dirVnodeInfo,
IHandle_t * alinkH, int i, struct DirSummary *rootdir,
int *rootdirfound);
extern void SalvageFileSysParallel(struct DiskPartition *partP);
extern void SalvageFileSys(struct DiskPartition *partP, VolumeId singleVolumeNumber);
extern void SalvageFileSys1(struct DiskPartition *partP,
VolumeId singleVolumeNumber);
extern int SalvageHeader(register struct stuff *sp, struct InodeSummary *isp,
int check, int *deleteMe);
extern int SalvageIndex(Inode ino, VnodeClass class, int RW,
register struct ViceInodeInfo *ip, int nInodes,
struct VolumeSummary *volSummary, int check);
extern int SalvageVnodes(register struct InodeSummary *rwIsp,
register struct InodeSummary *thisIsp,
register struct ViceInodeInfo *inodes, int check);
extern int SalvageVolume(register struct InodeSummary *rwIsp, IHandle_t * alinkH);
extern void DoSalvageVolumeGroup(register struct InodeSummary *isp, int nVols);
#ifdef AFS_NT40_ENV
extern void SalvageVolumeGroup(register struct InodeSummary *isp, int nVols);
#else
#define SalvageVolumeGroup DoSalvageVolumeGroup
#endif
extern int SalvageVolumeHeaderFile(register struct InodeSummary *isp,
register struct ViceInodeInfo *inodes, int RW,
int check, int *deleteMe);
extern void showlog(void);
extern int UseTheForceLuke(char *path);
#endif /* __vol_salvage_h_ */

View File

@ -25,6 +25,9 @@
#define ROVOL 1
#define BACKVOL 2
/* maximum numbe of Vice partitions */
#define VOLMAXPARTS 255
/* All volumes will have a volume header name in this format */
#if defined(AFS_AIX_ENV) || defined(AFS_HPUX_ENV)
/* Note that <afs/param.h> must have been included before we get here... */

View File

@ -14,6 +14,9 @@
*/
#ifndef __volinodes_h_
#define __volinodes_h_
/* Used by vutil.c and salvager.c */
private struct VolumeHeader tempHeader;
@ -56,3 +59,5 @@ LINKTABLEMAGIC, LINKTABLEVERSION}, VI_LINKTABLE,
#define MAXINODETYPE VI_LINKTABLE
Volume *VWaitAttachVolume();
#endif /* __volinodes_h_ */

File diff suppressed because it is too large Load Diff

View File

@ -5,6 +5,8 @@
* 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
*
* Portions Copyright (c) 2006 Sine Nomine Associates
*/
/*
@ -24,44 +26,44 @@
#define VolumeWriteable2(vol) (vol.type == readwriteVolume)
typedef bit32 FileOffset; /* Offset in this file */
#define Date afs_uint32
#include "daemon_com.h"
#include "fssync.h"
#ifdef AFS_PTHREAD_ENV
#include <assert.h>
#include <pthread.h>
extern pthread_mutex_t vol_glock_mutex;
extern pthread_mutex_t vol_attach_mutex;
extern pthread_mutex_t vol_fsync_mutex;
extern pthread_mutex_t vol_trans_mutex;
extern pthread_cond_t vol_put_volume_cond;
extern pthread_cond_t vol_sleep_cond;
extern int vol_attach_threads;
/* this lock has been deprecated */
#define VATTACH_LOCK
#define VATTACH_UNLOCK
#define VOL_LOCK \
assert(pthread_mutex_lock(&vol_glock_mutex) == 0)
#define VOL_UNLOCK \
assert(pthread_mutex_unlock(&vol_glock_mutex) == 0)
#define VFSYNC_LOCK \
assert(pthread_mutex_lock(&vol_fsync_mutex) == 0)
#define VFSYNC_UNLOCK \
assert(pthread_mutex_unlock(&vol_fsync_mutex) == 0)
#define VSALVSYNC_LOCK \
assert(pthread_mutex_lock(&vol_salvsync_mutex) == 0)
#define VSALVSYNC_UNLOCK \
assert(pthread_mutex_unlock(&vol_salvsync_mutex) == 0)
#define VTRANS_LOCK \
assert(pthread_mutex_lock(&vol_trans_mutex) == 0)
#define VTRANS_UNLOCK \
assert(pthread_mutex_unlock(&vol_trans_mutex) == 0)
#else /* AFS_PTHREAD_ENV */
#define VATTACH_LOCK
#define VATTACH_UNLOCK
#define VOL_LOCK
#define VOL_UNLOCK
#define VFSYNC_LOCK
#define VFSYNC_UNLOCK
#define VSALVSYNC_LOCK
#define VSALVSYNC_UNLOCK
#define VTRANS_LOCK
#define VTRANS_UNLOCK
#endif /* AFS_PTHREAD_ENV */
typedef enum { fileServer, volumeUtility, salvager } ProgramType;
typedef enum { fileServer, /* the fileserver process */
volumeUtility, /* volserver, or a single volume salvager (non-dafs) */
salvager, /* standalone whole-partition salvager */
salvageServer, /* dafs online salvager */
debugUtility /* fssync-debug or similar utility */
} ProgramType;
extern ProgramType programType; /* The type of program using the package */
/* Some initialization parameters for the volume package */
@ -76,6 +78,70 @@ struct versionStamp { /* Version stamp for critical volume files */
* that created this file */
};
#ifdef AFS_DEMAND_ATTACH_FS
/*
* demand attach fs
* volume state machine
*
* these must be contiguous in order for IsValidState() to work correctly
*/
#define VOL_STATE_UNATTACHED 0 /* volume is unattached */
#define VOL_STATE_PREATTACHED 1 /* volume has been pre-attached */
#define VOL_STATE_ATTACHING 2 /* volume is transitioning to fully attached */
#define VOL_STATE_ATTACHED 3 /* volume has been fully attached */
#define VOL_STATE_UPDATING 4 /* volume is updating on-disk structures */
#define VOL_STATE_GET_BITMAP 5 /* volume is getting bitmap entries */
#define VOL_STATE_HDR_LOADING 6 /* volume is loading disk header */
#define VOL_STATE_HDR_ATTACHING 7 /* volume is getting a header from the LRU */
#define VOL_STATE_SHUTTING_DOWN 8 /* volume is shutting down */
#define VOL_STATE_GOING_OFFLINE 9 /* volume is going offline */
#define VOL_STATE_OFFLINING 10 /* volume is transitioning to offline */
#define VOL_STATE_DETACHING 11 /* volume is transitioning to detached */
#define VOL_STATE_SALVSYNC_REQ 12 /* volume is blocked on a salvsync request */
#define VOL_STATE_SALVAGING 13 /* volume is being salvaged */
#define VOL_STATE_ERROR 14 /* volume is in an error state */
#define VOL_STATE_FREED 15 /* debugging aid */
#define VOL_STATE_COUNT 16 /* total number of valid states */
/* V_attachFlags bits */
#define VOL_HDR_ATTACHED 0x1 /* volume header is attached to Volume struct */
#define VOL_HDR_LOADED 0x2 /* volume header contents are valid */
#define VOL_HDR_IN_LRU 0x4 /* volume header is in LRU */
#define VOL_IN_HASH 0x8 /* volume is in hash table */
#define VOL_ON_VBYP_LIST 0x10 /* volume is on VByP list */
#define VOL_IS_BUSY 0x20 /* volume is not to be free()d */
#define VOL_ON_VLRU 0x40 /* volume is on the VLRU */
#define VOL_HDR_DONTSALV 0x80 /* volume header DONTSALVAGE flag is set */
/* VPrintExtendedCacheStats flags */
#define VOL_STATS_PER_CHAIN 0x1 /* compute simple per-chain stats */
#define VOL_STATS_PER_CHAIN2 0x2 /* compute per-chain stats that require scanning
* every element of the chain */
/* VLRU_SetOptions options */
#define VLRU_SET_THRESH 1
#define VLRU_SET_INTERVAL 2
#define VLRU_SET_MAX 3
#define VLRU_SET_ENABLED 4
/* valid VLRU queue names */
#define VLRU_QUEUE_NEW 0 /* LRU queue for new volumes */
#define VLRU_QUEUE_MID 1 /* survivor generation */
#define VLRU_QUEUE_OLD 2 /* old generation */
#define VLRU_QUEUE_CANDIDATE 3 /* soft detach candidate pool */
#define VLRU_QUEUE_HELD 4 /* volumes which are not allowed
* to be soft detached */
#define VLRU_QUEUE_INVALID 5 /* invalid queue id */
/* default scanner timing parameters */
#define VLRU_DEFAULT_OFFLINE_THRESH (60*60*2) /* 2 hours */
#define VLRU_DEFAULT_OFFLINE_INTERVAL (60*2) /* 2 minutes */
#define VLRU_DEFAULT_OFFLINE_MAX 8 /* 8 volumes */
#endif /* AFS_DEMAND_ATTACH_FS */
/* Magic numbers and version stamps for each type of file */
#define VOLUMEHEADERMAGIC ((bit32)0x88a1bb3c)
#define VOLUMEINFOMAGIC ((bit32)0x78a1b2c5)
@ -297,8 +363,144 @@ typedef struct VolumeDiskData {
/**************************************/
/* Memory resident volume information */
/**************************************/
/* global volume package stats */
typedef struct VolPkgStats {
#ifdef AFS_DEMAND_ATTACH_FS
/*
* demand attach fs
* extended volume package statistics
*/
/* levels */
afs_uint32 state_levels[VOL_STATE_COUNT];
/* counters */
afs_uint64 hash_looks; /* number of hash chain element traversals */
afs_uint64 hash_reorders; /* number of hash chain reorders */
afs_uint64 salvages; /* online salvages since fileserver start */
afs_uint64 vol_ops; /* volume operations since fileserver start */
#endif /* AFS_DEMAND_ATTACH_FS */
afs_uint64 hdr_loads; /* header loads from disk */
afs_uint64 hdr_gets; /* header pulls out of LRU */
afs_uint64 attaches; /* volume attaches since fileserver start */
afs_uint64 soft_detaches; /* soft detach ops since fileserver start */
/* configuration parameters */
afs_uint32 hdr_cache_size; /* size of volume header cache */
} VolPkgStats;
extern VolPkgStats VStats;
/*
* volume header cache supporting structures
*/
#ifdef AFS_DEMAND_ATTACH_FS
struct volume_hdr_LRU_stats {
afs_uint32 free;
afs_uint32 used;
afs_uint32 attached;
};
#endif
struct volume_hdr_LRU_t {
struct rx_queue lru;
#ifdef AFS_DEMAND_ATTACH_FS
struct volume_hdr_LRU_stats stats;
#endif
};
extern struct volume_hdr_LRU_t volume_hdr_LRU;
/*
* volume hash chain supporting structures
*/
typedef struct VolumeHashChainHead {
struct rx_queue queue;
int len;
/* someday we could put a per-chain lock here... */
#ifdef AFS_DEMAND_ATTACH_FS
int busy;
int cacheCheck;
/* per-chain statistics */
afs_uint64 looks;
afs_uint64 gets;
afs_uint64 reorders;
pthread_cond_t chain_busy_cv;
#endif /* AFS_DEMAND_ATTACH_FS */
} VolumeHashChainHead;
typedef struct VolumeHashTable {
int Size;
int Mask;
VolumeHashChainHead * Table;
} VolumeHashTable_t;
extern VolumeHashTable_t VolumeHashTable;
struct VolumeHashChainStats {
afs_int32 table_size;
afs_int32 chain_len;
#ifdef AFS_DEMAND_ATTACH_FS
afs_int32 chain_cacheCheck;
afs_int32 chain_busy;
afs_uint64 chain_looks;
afs_uint64 chain_gets;
afs_uint64 chain_reorders;
#endif
};
#ifdef AFS_DEMAND_ATTACH_FS
/* demand attach fs
* extended per-volume statistics
*
* please note that this structure lives across the entire
* lifetime of the fileserver process
*/
typedef struct VolumeStats {
/* counters */
afs_uint64 hash_lookups; /* hash table lookups */
afs_uint64 hash_short_circuits; /* short circuited hash lookups (due to cacheCheck) */
afs_uint64 hdr_loads; /* header loads from disk */
afs_uint64 hdr_gets; /* header pulls out of LRU */
afs_uint16 attaches; /* attaches of this volume since fileserver start */
afs_uint16 soft_detaches; /* soft detaches of this volume */
afs_uint16 salvages; /* online salvages since fileserver start */
afs_uint16 vol_ops; /* volume operations since fileserver start */
/* timestamps */
afs_uint32 last_attach; /* unix timestamp of last VAttach */
afs_uint32 last_get; /* unix timestamp of last VGet/VHold */
afs_uint32 last_promote; /* unix timestamp of last VLRU promote/demote */
afs_uint32 last_hdr_get; /* unix timestamp of last GetVolumeHeader() */
afs_uint32 last_salvage; /* unix timestamp of last initiation of an online salvage */
afs_uint32 last_salvage_req; /* unix timestamp of last SALVSYNC request */
afs_uint32 last_vol_op; /* unix timestamp of last volume operation */
} VolumeStats;
/* demand attach fs
* online salvager state */
typedef struct VolumeOnlineSalvage {
afs_uint32 prio; /* number of VGetVolume's since salvage requested */
int reason; /* reason for requesting online salvage */
byte requested; /* flag specifying that salvage should be scheduled */
byte scheduled; /* flag specifying whether online salvage scheduled */
byte reserved[2]; /* padding */
} VolumeOnlineSalvage;
/* demand attach fs
* volume LRU state */
typedef struct VolumeVLRUState {
struct rx_queue lru; /* VLRU queue pointers */
int idx; /* VLRU generation index */
} VolumeVLRUState;
typedef afs_uint16 VolState; /* attachment state type */
#endif /* AFS_DEMAND_ATTACH_FS */
typedef struct Volume {
struct Volume *hashNext; /* Next in hash resolution table */
struct rx_queue q; /* Volume hash chain pointers */
VolumeId hashid; /* Volume number -- for hash table lookup */
struct volHeader *header; /* Cached disk data */
Device device; /* Unix device for the volume */
@ -339,10 +541,23 @@ typedef struct Volume {
afs_uint32 updateTime; /* Time that this volume was put on the updated
* volume list--the list of volumes that will be
* salvaged should the file server crash */
#ifdef AFS_DEMAND_ATTACH_FS
VolState attach_state; /* what stage of attachment has been completed */
afs_uint16 attach_flags; /* flags related to attachment state */
pthread_cond_t attach_cv; /* state change condition variable */
short nWaiters; /* volume package internal ref count */
int chainCacheCheck; /* Volume hash chain cache check */
struct rx_queue vol_list; /* per-partition volume list (VByPList) */
VolumeOnlineSalvage salvage; /* online salvager state */
VolumeStats stats; /* per-volume statistics */
VolumeVLRUState vlru; /* state specific to the VLRU */
FSSYNC_VolOp_info * pending_vol_op; /* fssync command info for any pending vol ops */
#endif /* AFS_DEMAND_ATTACH_FS */
} Volume;
struct volHeader {
struct volHeader *prev, *next; /* LRU pointers */
struct rx_queue lru;
VolumeDiskData diskstuff; /* General volume info read from disk */
Volume *back; /* back pointer to current volume structure */
};
@ -356,6 +571,11 @@ struct volHeader {
#define V_vnodeIndex(vp) ((vp)->vnodeIndex)
#define V_nextVnodeUnique(vp) ((vp)->nextVnodeUnique)
#define V_linkHandle(vp) ((vp)->linkHandle)
#ifdef AFS_DEMAND_ATTACH_FS
#define V_attachState(vp) ((vp)->attach_state)
#define V_attachFlags(vp) ((vp)->attach_flags)
#define V_attachCV(vp) ((vp)->attach_cv)
#endif /* AFS_DEMAND_ATTACH_FS */
/* N.B. V_id must be this, rather than vp->id, or some programs will break, probably */
#define V_stamp(vp) ((vp)->header->diskstuff.stamp)
@ -414,7 +634,7 @@ struct volHeader {
extern char *VSalvageMessage; /* Canonical message when a volume is forced
* offline */
extern Volume *VGetVolume(Error * ec, VolId volumeId);
extern Volume *VGetVolume(Error * ec, Error * client_ec, VolId volumeId);
extern Volume *VGetVolume_r(Error * ec, VolId volumeId);
extern void VPutVolume(Volume *);
extern void VPutVolume_r(Volume *);
@ -422,6 +642,9 @@ extern void VOffline(Volume * vp, char *message);
extern void VOffline_r(Volume * vp, char *message);
extern int VConnectFS(void);
extern int VConnectFS_r(void);
extern void VDisconnectFS(void);
extern void VDisconnectFS_r(void);
extern int VChildProcReconnectFS(void);
extern Volume *VAttachVolume(Error * ec, VolumeId volumeId, int mode);
extern Volume *VAttachVolume_r(Error * ec, VolumeId volumeId, int mode);
extern Volume *VCreateVolume(Error * ec, char *partname, VolId volumeId,
@ -431,7 +654,7 @@ extern Volume *VCreateVolume_r(Error * ec, char *partname, VolId volumeId,
extern VnodeId VAllocBitmapEntry(Error * ec, Volume * vp,
struct vnodeIndex *index);
extern VnodeId VAllocBitmapEntry_r(Error * ec, Volume * vp,
struct vnodeIndex *index);
struct vnodeIndex *index, int flags);
extern void VFreeBitMapEntry(Error * ec, register struct vnodeIndex *index,
unsigned bitNumber);
extern void VFreeBitMapEntry_r(Error * ec, register struct vnodeIndex *index,
@ -444,13 +667,13 @@ extern Volume *VAttachVolumeByName_r(Error * ec, char *partition, char *name,
int mode);
extern void VShutdown(void);
extern void VUpdateVolume(Error * ec, Volume * vp);
extern void VUpdateVolume_r(Error * ec, Volume * vp);
extern void VUpdateVolume_r(Error * ec, Volume * vp, int flags);
extern void VAddToVolumeUpdateList(Error * ec, Volume * vp);
extern void VAddToVolumeUpdateList_r(Error * ec, Volume * vp);
extern void VDetachVolume(Error * ec, Volume * vp);
extern void VDetachVolume_r(Error * ec, Volume * vp);
extern void VForceOffline(Volume * vp);
extern void VForceOffline_r(Volume * vp);
extern void VForceOffline_r(Volume * vp, int flags);
extern void VBumpVolumeUsage(register Volume * vp);
extern void VBumpVolumeUsage_r(register Volume * vp);
extern void VSetDiskUsage(void);
@ -459,12 +682,41 @@ extern void VReleaseVnodeFiles_r(Volume * vp);
extern void VCloseVnodeFiles_r(Volume * vp);
extern struct DiskPartition *VGetPartition(char *name, int abortp);
extern struct DiskPartition *VGetPartition_r(char *name, int abortp);
extern int VInitVolumePackage(ProgramType pt, int nLargeVnodes,
int nSmallVnodes, int connect, int volcache);
extern int VInitVolumePackage(ProgramType pt, afs_uint32 nLargeVnodes,
afs_uint32 nSmallVnodes, int connect, afs_uint32 volcache);
extern void DiskToVolumeHeader(VolumeHeader_t * h, VolumeDiskHeader_t * dh);
extern void VolumeHeaderToDisk(VolumeDiskHeader_t * dh, VolumeHeader_t * h);
extern void VTakeOffline_r(register Volume * vp);
extern void VTakeOffline(register Volume * vp);
extern Volume * VLookupVolume_r(Error * ec, VolId volumeId, Volume * hint);
#ifdef AFS_DEMAND_ATTACH_FS
extern Volume *VPreAttachVolumeByName(Error * ec, char *partition, char *name,
int mode);
extern Volume *VPreAttachVolumeByName_r(Error * ec, char *partition, char *name,
int mode);
extern Volume *VPreAttachVolumeById_r(Error * ec, struct DiskPartition * partp,
Volume * vp, int volume_id);
extern Volume *VGetVolumeByVp_r(Error * ec, Volume * vp);
extern int VShutdownByPartition_r(struct DiskPartition * dp);
extern int VShutdownVolume_r(Volume * vp);
extern int VConnectSALV(void);
extern int VConnectSALV_r(void);
extern int VReconnectSALV(void);
extern int VReconnectSALV_r(void);
extern int VDisconnectSALV(void);
extern int VDisconnectSALV_r(void);
extern void VPrintExtendedCacheStats(int flags);
extern void VPrintExtendedCacheStats_r(int flags);
extern VolState VChangeState_r(Volume * vp, VolState new_state);
extern void VLRU_SetOptions(int option, afs_uint32 val);
extern int VSetVolHashSize(int logsize);
extern int VRequestSalvage_r(Volume * vp, int reason, int flags);
extern int VRegisterVolOp_r(Volume * vp, FSSYNC_VolOp_info * vopinfo);
extern int VDeregisterVolOp_r(Volume * vp, FSSYNC_VolOp_info * vopinfo);
#endif /* AFS_DEMAND_ATTACH_FS */
extern int VVolOpLeaveOnline_r(Volume * vp, FSSYNC_VolOp_info * vopinfo);
extern int VVolOpSetVBusy_r(Volume * vp, FSSYNC_VolOp_info * vopinfo);
/* Naive formula relating number of file size to number of 1K blocks in file */
@ -500,6 +752,26 @@ extern void VTakeOffline(register Volume * vp);
* getting the most recent data. */
/* VUpdateVolume_r flags */
#define VOL_UPDATE_WAIT 0x1 /* for demand attach, wait for other exclusive ops to end */
#define VOL_UPDATE_NOFORCEOFF 0x2 /* don't force offline on failure. this is to prevent
* infinite recursion between vupdate and vforceoff */
/* VForceOffline_r flags */
#define VOL_FORCEOFF_NOUPDATE 0x1 /* don't force update on forceoff. this is to prevent
* infinite recursion between vupdate and vforceoff */
/* VSyncVolume_r flags */
#define VOL_SYNC_WAIT 0x1 /* for demand attach, wait for other exclusive ops to end */
/* VAllocBitmapEntry_r flags */
#define VOL_ALLOC_BITMAP_WAIT 0x1 /* for demand attach, wait for other exclusive ops to end */
/* VRequestSalvage_r flags */
#define VOL_SALVAGE_INVALIDATE_HEADER 0x1 /* for demand attach fs, invalidate volume header cache */
#if defined(NEARINODE_HINT)
#define V_pref(vp,nearInode) nearInodeHash(V_id(vp),(nearInode)); (nearInode) %= V_partition(vp)->f_files
#else

View File

@ -5,6 +5,8 @@
# License. For details, see the LICENSE file in the top-level source
# directory or online at http://www.openafs.org/dl/license10.html
AFSDEV_AUXCDEFINES = -DFSSYNC_BUILD_CLIENT
RELDIR=volser
!INCLUDE ..\config\NTMakefile.$(SYS_NAME)
!INCLUDE ..\config\NTMakefile.version

View File

@ -51,6 +51,7 @@ RCSID
#include <afs/volume.h>
#include <afs/partition.h>
#include "dump.h"
#include <afs/daemon_com.h>
#include <afs/fssync.h>
#include <afs/acl.h>
#include "volser.h"

View File

@ -61,6 +61,7 @@ RCSID
#include <afs/volume.h>
#include <afs/partition.h>
#include "vol.h"
#include <afs/daemon_com.h>
#include <afs/fssync.h>
#include <afs/acl.h>
#include "afs/audit.h"
@ -844,7 +845,7 @@ VolReClone(struct rx_call *acid, afs_int32 atrans, afs_int32 cloneId)
{
struct DiskPartition *tpartp = originalvp->partition;
FSYNC_askfs(cloneId, tpartp->name, FSYNC_RESTOREVOLUME, 0);
FSYNC_VolOp(cloneId, tpartp->name, FSYNC_VOL_BREAKCBKS, 0, NULL);
}
return 0;
@ -1355,8 +1356,7 @@ VolRestore(struct rx_call *acid, afs_int32 atrans, afs_int32 aflags,
DFlushVolume(V_parentId(tt->volume)); /* Ensure dir buffers get dropped */
code = RestoreVolume(acid, tt->volume, (aflags & 1), cookie); /* last is incrementalp */
FSYNC_askfs(tt->volid, NULL, FSYNC_RESTOREVOLUME, 0l); /*break call backs on the
* restored volume */
FSYNC_VolOp(tt->volid, NULL, FSYNC_VOL_BREAKCBKS, 0l, NULL);
tt->rxCallPtr = (struct rx_call *)0;
tcode = TRELE(tt);
@ -1422,7 +1422,7 @@ VolSetForwarding(struct rx_call *acid, afs_int32 atid, afs_int32 anewsite)
}
strcpy(tt->lastProcName, "SetForwarding");
tt->rxCallPtr = acid;
FSYNC_askfs(tt->volid, NULL, FSYNC_MOVEVOLUME, anewsite);
FSYNC_VolOp(tt->volid, NULL, FSYNC_VOL_MOVE, anewsite, NULL);
tt->rxCallPtr = (struct rx_call *)0;
if (TRELE(tt))
return VOLSERTRELE_ERROR;
@ -1672,6 +1672,9 @@ XVolListPartitions(struct rx_call *acid, struct partEntries *pEntries)
/* Only report attached partitions */
for (i = 0; i < VOLMAXPARTS; i++) {
#ifdef AFS_DEMAND_ATTACH_FS
dp = VGetPartitionById(i, 0);
#else
if (i < 26) {
namehead[6] = i + 'a';
namehead[7] = '\0';
@ -1682,6 +1685,7 @@ XVolListPartitions(struct rx_call *acid, struct partEntries *pEntries)
namehead[8] = '\0';
}
dp = VGetPartition(namehead, 0);
#endif
if (dp)
partList.partId[j++] = i;
}
@ -1792,7 +1796,7 @@ VolListOneVolume(struct rx_call *acid, afs_int32 partid, afs_int32
pntr->volid = volid;
goto drop;
}
tv = VAttachVolumeByName(&error, pname, volname, V_READONLY);
tv = VAttachVolumeByName(&error, pname, volname, V_PEEK);
if (error) {
pntr->status = 0; /*things are messed up */
strcpy(pntr->name, volname);
@ -2007,7 +2011,7 @@ VolXListOneVolume(struct rx_call *a_rxCidP, afs_int32 a_partID,
/*
* Attach the volume, give up on the volume if we can't.
*/
tv = VAttachVolumeByName(&error, pname, volname, V_READONLY);
tv = VAttachVolumeByName(&error, pname, volname, V_PEEK);
if (error) {
xInfoP->status = 0; /*things are messed up */
strcpy(xInfoP->name, volname);
@ -2819,7 +2823,7 @@ SAFSVolConvertROtoRWvolume(struct rx_call *acid, afs_int32 partId,
return EIO;
}
close(fd);
FSYNC_askfs(volumeId, pname, FSYNC_RESTOREVOLUME, 0);
FSYNC_VolOp(volumeId, pname, FSYNC_VOL_BREAKCBKS, 0, NULL);
for (dp = DiskPartitionList; dp && strcmp(dp->name, pname);
dp = dp->next);
@ -2854,8 +2858,8 @@ SAFSVolConvertROtoRWvolume(struct rx_call *acid, afs_int32 partId,
if (unlink(opath) < 0) {
Log("1 SAFS_VolConvertROtoRWvolume: Couldn't unlink RO header, error = %d\n", error);
}
FSYNC_askfs(volumeId, pname, FSYNC_DONE, 0);
FSYNC_askfs(h.id, pname, FSYNC_ON, 0);
FSYNC_VolOp(volumeId, pname, FSYNC_VOL_DONE, 0, NULL);
FSYNC_VolOp(h.id, pname, FSYNC_VOL_ON, 0, NULL);
return 0;
#else /* AFS_NAMEI_ENV */
return EINVAL;

View File

@ -15,6 +15,8 @@
#include <pthread.h>
#endif
#include <afs/voldefs.h>
/* vflags, representing state of the volume */
#define VTDeleteOnSalvage 1 /* delete on next salvage */
#define VTOutOfService 2 /* never put this volume online */
@ -110,7 +112,6 @@ extern struct volser_trans *QI_GlobalWriteTrans;
#define INVALID_BID 0
#define VOLSER_MAXVOLNAME 65
#define VOLSER_OLDMAXVOLNAME 32
#define VOLMAXPARTS 255
/*flags used for interfacing with the backup system */
struct volDescription { /*used for interfacing with the backup system */