mirror of
https://git.openafs.org/openafs.git
synced 2025-01-18 06:50:12 +00:00
dafs-20060317
FIXES 26648 demand attach/fast restart fileserver
This commit is contained in:
parent
cba4f12e17
commit
51ec267011
24
Makefile.in
24
Makefile.in
@ -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 \
|
||||
|
16
acinclude.m4
16
acinclude.m4
@ -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
|
||||
|
@ -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 \
|
||||
|
@ -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
|
||||
|
271
src/bozo/bos.c
271
src/bozo/bos.c
@ -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,
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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=
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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
200
src/tsalvaged/Makefile.in
Normal 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}
|
475
src/tsalvaged/salvsync-debug.c
Normal file
475
src/tsalvaged/salvsync-debug.c
Normal 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 */
|
@ -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
|
||||
|
||||
|
@ -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
1120
src/tviced/serialize_state.c
Normal file
File diff suppressed because it is too large
Load Diff
311
src/tviced/serialize_state.h
Normal file
311
src/tviced/serialize_state.h
Normal 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
2004
src/tviced/state_analyzer.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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],
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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
35
src/util/strnlen.c
Normal 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;
|
||||
}
|
||||
|
@ -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 \
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
1149
src/viced/callback.c
1149
src/viced/callback.c
File diff suppressed because it is too large
Load Diff
158
src/viced/callback.h
Normal file
158
src/viced/callback.h
Normal 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 */
|
634
src/viced/host.c
634
src/viced/host.c
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -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.
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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
473
src/vol/daemon_com.c
Normal 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
141
src/vol/daemon_com.h
Normal 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
222
src/vol/fssync-client.c
Normal 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
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
1179
src/vol/fssync-server.c
Normal file
File diff suppressed because it is too large
Load Diff
751
src/vol/fssync.c
751
src/vol/fssync.c
@ -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 */
|
||||
}
|
137
src/vol/fssync.h
137
src/vol/fssync.h
@ -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_ */
|
||||
|
@ -41,6 +41,7 @@ RCSID
|
||||
#include "partition.h"
|
||||
#include "viceinode.h"
|
||||
#include "salvage.h"
|
||||
#include "daemon_com.h"
|
||||
#include "fssync.h"
|
||||
|
||||
#ifdef O_LARGEFILE
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
|
@ -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
738
src/vol/salvaged.c
Normal 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
499
src/vol/salvager.c
Normal 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
172
src/vol/salvsync-client.c
Normal 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
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
111
src/vol/salvsync.h
Normal 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 */
|
@ -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>
|
||||
|
@ -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>
|
||||
|
320
src/vol/vnode.c
320
src/vol/vnode.c
@ -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 */
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
282
src/vol/vol-salvage.h
Normal 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_ */
|
@ -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... */
|
||||
|
@ -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_ */
|
||||
|
5191
src/vol/volume.c
5191
src/vol/volume.c
File diff suppressed because it is too large
Load Diff
316
src/vol/volume.h
316
src/vol/volume.h
@ -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
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user