}
+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;
+}
+
+
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
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)