windows-fs-test_volstat-20080103
authorJeffrey Altman <jaltman@secure-endpoints.com>
Fri, 4 Jan 2008 07:56:45 +0000 (07:56 +0000)
committerJeffrey Altman <jaltman@secure-endpoints.com>
Fri, 4 Jan 2008 07:56:45 +0000 (07:56 +0000)
LICENSE MIT

Add a hidden command that can be used to test volume status handlers.
fs test_volstat.

src/WINNT/afsd/cm_ioctl.c
src/WINNT/afsd/cm_ioctl.h
src/WINNT/afsd/cm_volstat.h
src/WINNT/afsd/fs.c
src/WINNT/afsd/smb_iocons.h
src/WINNT/afsd/smb_ioctl.c

index c5ce570..6644574 100644 (file)
@@ -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;
+}       
+
+
index bfc98ef..8f9890e 100644 (file)
@@ -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__ */
index 8d20cad..84016aa 100644 (file)
@@ -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
+
index 78e6722..205d607 100644 (file)
@@ -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) 
index b40f0b4..83b2b57 100644 (file)
@@ -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_ */
index 0365711..a66cfa7 100644 (file)
@@ -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 */