From 068233cf4ab90a173e04de94605490e651d2f686 Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Fri, 4 Jan 2008 07:56:45 +0000 Subject: [PATCH] windows-fs-test_volstat-20080103 LICENSE MIT Add a hidden command that can be used to test volume status handlers. fs test_volstat. --- src/WINNT/afsd/cm_ioctl.c | 102 ++++++++++++++++++++++++++++++++++++ src/WINNT/afsd/cm_ioctl.h | 2 + src/WINNT/afsd/cm_volstat.h | 14 +++++ src/WINNT/afsd/fs.c | 87 ++++++++++++++++++++++++++++++ src/WINNT/afsd/smb_iocons.h | 3 ++ src/WINNT/afsd/smb_ioctl.c | 1 + 6 files changed, 209 insertions(+) diff --git a/src/WINNT/afsd/cm_ioctl.c b/src/WINNT/afsd/cm_ioctl.c index c5ce570a9..664457403 100644 --- a/src/WINNT/afsd/cm_ioctl.c +++ b/src/WINNT/afsd/cm_ioctl.c @@ -2939,3 +2939,105 @@ long cm_IoctlPathAvailability(struct smb_ioctl *ioctlp, struct cm_user *userp) } +long cm_IoctlVolStatTest(struct smb_ioctl *ioctlp, struct cm_user *userp) +{ + long code; + cm_cell_t *cellp = NULL; + cm_volume_t *volp; + cm_vol_state_t *statep; + struct VolStatTest * testp; + cm_req_t req; + afs_uint32 n; + size_t len; + + cm_InitReq(&req); + + cm_SkipIoctlPath(ioctlp); /* we don't care about the path */ + testp = (struct VolStatTest *)ioctlp->inDatap; + +#ifdef AFS_FREELANCE_CLIENT + if (testp->fid.cell == -1) + return CM_ERROR_NOACCESS; +#endif + + if (testp->flags & VOLSTAT_TEST_CHECK_VOLUME) { + cm_CheckOfflineVolumes(); + return 0; + } + + if (testp->flags & VOLSTAT_TEST_NETWORK_UP) { + cm_VolStatus_Network_Started(cm_NetbiosName +#ifdef _WIN64 + , cm_NetbiosName +#endif + ); + return 0; + } + + if (testp->flags & VOLSTAT_TEST_NETWORK_DOWN) { + cm_VolStatus_Network_Stopped(cm_NetbiosName +#ifdef _WIN64 + , cm_NetbiosName +#endif + ); + return 0; + } + + if (testp->cellname[0]) { + n = atoi(testp->cellname); + if (n) + testp->fid.cell = n; + else + cellp = cm_GetCell(testp->cellname, 0); + } + + if (testp->fid.cell > 0) { + cellp = cm_FindCellByID(testp->fid.cell); + } + + if (!cellp) + return CM_ERROR_NOSUCHCELL; + + if (testp->volname[0]) { + n = atoi(testp->volname); + if (n) + testp->fid.volume = n; + else + code = cm_GetVolumeByName(cellp, testp->volname, userp, &req, CM_GETVOL_FLAG_NO_LRU_UPDATE, &volp); + } + + if (testp->fid.volume > 0) + code = cm_GetVolumeByID(cellp, testp->fid.volume, userp, &req, CM_GETVOL_FLAG_NO_LRU_UPDATE, &volp); + + if (code) + return code; + + if (testp->fid.volume) { + if (testp->fid.volume == volp->rw.ID) + statep = &volp->rw; + else if (testp->fid.volume == volp->ro.ID) + statep = &volp->ro; + else + statep = &volp->bk; + } else { + len = strlen(testp->volname); + + if (stricmp(".readonly", &testp->volname[len-9]) == 0) + statep = &volp->ro; + else if (stricmp(".backup", &testp->volname[len-7]) == 0) + statep = &volp->bk; + else + statep = &volp->rw; + } + + if (statep) { + statep->state = testp->state; + code = cm_VolStatus_Change_Notification(cellp->cellID, statep->ID, testp->state); + } + + cm_PutVolume(volp); + + return code; +} + + diff --git a/src/WINNT/afsd/cm_ioctl.h b/src/WINNT/afsd/cm_ioctl.h index bfc98ef4c..8f9890e92 100644 --- a/src/WINNT/afsd/cm_ioctl.h +++ b/src/WINNT/afsd/cm_ioctl.h @@ -171,6 +171,8 @@ extern long cm_IoctlUUIDControl(struct smb_ioctl * ioctlp, struct cm_user *userp extern long cm_IoctlPathAvailability(struct smb_ioctl * ioctlp, struct cm_user *userp); +extern long cm_IoctlVolStatTest(struct smb_ioctl *ioctlp, struct cm_user *userp); + #endif /* __CM_IOCTL_INTERFACES_ONLY__ */ #endif /* __CM_IOCTL_H_ENV__ */ diff --git a/src/WINNT/afsd/cm_volstat.h b/src/WINNT/afsd/cm_volstat.h index 8d20cad38..84016aa60 100644 --- a/src/WINNT/afsd/cm_volstat.h +++ b/src/WINNT/afsd/cm_volstat.h @@ -88,3 +88,17 @@ typedef struct cm_VolStatus_Funcs { long (__fastcall * cm_VolStatus_Path_To_DFSlink)(const char * share, const char * path, afs_uint32 *pBufSize, char *pBuffer); } cm_VolStatus_Funcs_t; +/* pioctl */ +struct VolStatTest { + afs_uint32 flags; + cm_fid_t fid; + char cellname[CELL_MAXNAMELEN]; + char volname[VL_MAXNAMELEN]; + enum volstatus state; +}; + +#define VOLSTAT_TEST_APPLY_TO_SERVER 1 +#define VOLSTAT_TEST_CHECK_VOLUME 2 +#define VOLSTAT_TEST_NETWORK_UP 4 +#define VOLSTAT_TEST_NETWORK_DOWN 8 + diff --git a/src/WINNT/afsd/fs.c b/src/WINNT/afsd/fs.c index 78e6722c3..205d6078a 100644 --- a/src/WINNT/afsd/fs.c +++ b/src/WINNT/afsd/fs.c @@ -4316,6 +4316,86 @@ RxStatPeerCmd(struct cmd_syndesc *as, void *arock) return 0; } +static int +TestVolStatCmd(struct cmd_syndesc *as, void *arock) +{ + afs_int32 code; + struct VolStatTest test; + struct ViceIoctl blob; + char * tp; + afs_uint32 n; + + memset(&test, 0, sizeof(test)); + + if (as->parms[0].items) { /* -network */ + tp = as->parms[0].items->data; + if (strcmp(tp, "up") == 0) + test.flags |= VOLSTAT_TEST_NETWORK_UP; + else if (strcmp(tp, "down") == 0) + test.flags |= VOLSTAT_TEST_NETWORK_DOWN; + else { + fprintf (stderr, "%s: %s must be \"up\" or \"down\".\n", pn, tp); + return EINVAL; + } + } + if (as->parms[1].items) { /* check */ + test.flags |= VOLSTAT_TEST_CHECK_VOLUME; + } + if (as->parms[2].items) { /* cell */ + tp = as->parms[2].items->data; + n = atoi(tp); + if (n != 0) + test.fid.cell = n; + else { + strncpy(test.cellname, tp, sizeof(test.cellname)); + test.cellname[sizeof(test.cellname)-1] = '\0'; + } + } + if (as->parms[3].items) { /* volume */ + tp = as->parms[3].items->data; + n = atoi(tp); + if (n != 0) + test.fid.volume = n; + else { + strncpy(test.volname, tp, sizeof(test.volname)); + test.volname[sizeof(test.volname)-1] = '\0'; + } + } + if (as->parms[4].items) { /* state */ + tp = as->parms[4].items->data; + if (strcmp(tp, "online") == 0) + test.state = vl_online; + else if (strcmp(tp, "busy") == 0) + test.state = vl_busy; + else if (strcmp(tp, "offline") == 0) + test.state = vl_offline; + else if (strcmp(tp, "down") == 0) + test.state = vl_alldown; + else { + fprintf (stderr, "%s: %s must be \"online\", \"busy\", \"offline\" or \"down\".\n", pn, tp); + return EINVAL; + } + } + + if ((test.fid.cell || test.cellname[0]) && !(test.fid.volume || test.volname[0]) || + !(test.fid.cell || test.cellname[0]) && (test.fid.volume || test.volname[0])) { + fprintf (stderr, "%s: both a cell and a volume must be specified.\n", pn, tp); + return EINVAL; + } + + blob.in = (char *)&test; + blob.in_size = sizeof(test); + blob.out_size = 0; + + code = pioctl(NULL, VIOC_VOLSTAT_TEST, &blob, 1); + if (code != 0) { + Die(errno, NULL); + return 1; + } + + return 0; +} + #ifndef WIN32 #include "AFS_component_version_number.c" #endif @@ -4608,6 +4688,13 @@ main(int argc, char **argv) ts = cmd_CreateSyntax("minidump", MiniDumpCmd, NULL, "Generate MiniDump of current service state"); + ts = cmd_CreateSyntax("test_volstat", TestVolStatCmd, NULL, (char *)CMD_HIDDEN); + cmd_AddParm(ts, "-network", CMD_SINGLE, CMD_OPTIONAL, "set network state up or down"); + cmd_AddParm(ts, "-check", CMD_FLAG, CMD_OPTIONAL, "check state of offline volumes"); + cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cell name or number"); + cmd_AddParm(ts, "-volume", CMD_SINGLE, CMD_OPTIONAL, "volume name or number"); + cmd_AddParm(ts, "-state", CMD_SINGLE, CMD_OPTIONAL, "new volume state: online, busy, offline, down"); + code = cmd_Dispatch(argc, argv); if (rxInitDone) diff --git a/src/WINNT/afsd/smb_iocons.h b/src/WINNT/afsd/smb_iocons.h index b40f0b46c..83b2b5724 100644 --- a/src/WINNT/afsd/smb_iocons.h +++ b/src/WINNT/afsd/smb_iocons.h @@ -93,4 +93,7 @@ struct sbstruct { #define VIOC_RXSTAT_PEER 0x2f #define VIOC_UUIDCTL 0x30 #define VIOC_PATH_AVAILABILITY 0x31 + +#define VIOC_VOLSTAT_TEST 0x3F +/* Not to exceed SMB_IOCTL_MAXPROCS from smb_ioctl.h */ #endif /* __SMB_IOCONS_H_ENV_ */ diff --git a/src/WINNT/afsd/smb_ioctl.c b/src/WINNT/afsd/smb_ioctl.c index 036571187..a66cfa799 100644 --- a/src/WINNT/afsd/smb_ioctl.c +++ b/src/WINNT/afsd/smb_ioctl.c @@ -80,6 +80,7 @@ void smb_InitIoctl(void) smb_ioctlProcsp[VIOC_RXSTAT_PEER] = cm_IoctlRxStatPeer; smb_ioctlProcsp[VIOC_UUIDCTL] = cm_IoctlUUIDControl; smb_ioctlProcsp[VIOC_PATH_AVAILABILITY] = cm_IoctlPathAvailability; + smb_ioctlProcsp[VIOC_VOLSTAT_TEST] = cm_IoctlVolStatTest; } /* called to make a fid structure into an IOCTL fid structure */ -- 2.39.5