📄 rf_ctrl.c
字号:
/* * Copyright (c) 1995 Carnegie-Mellon University. * All rights reserved. * * Author: Mark Holland * * Permission to use, copy, modify and distribute this software and * its documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. * * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. * * Carnegie Mellon requests users of this software to return to * * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU * School of Computer Science * Carnegie Mellon University * Pittsburgh PA 15213-3890 * * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. *//* $Locker: $ * $Log: rf_ctrl.c,v $ * Revision 1.7 1996/07/19 16:11:05 jimz * fix typing problems with access test * * Revision 1.6 1996/06/14 14:21:24 jimz * dfstrace stuff only compiled in if RF_DFSTRACE > 0 * * Revision 1.5 1996/06/05 18:06:02 jimz * Major code cleanup. The Great Renaming is now done. * Better modularity. Better typing. Fixed a bunch of * synchronization bugs. Made a lot of global stuff * per-desc or per-array. Removed dead code. * * Revision 1.4 1996/05/24 01:59:45 jimz * another checkpoint in code cleanup for release * time to sync kernel tree * * Revision 1.3 1996/05/23 21:46:35 jimz * checkpoint in code cleanup (release prep) * lots of types, function names have been fixed * * Revision 1.2 1995/12/01 15:15:03 root * added copyright info * * Revision 1.1 1995/11/29 21:55:22 wvcii * Initial revision * *//* rf_ctrl.c * * controls the kernelized raidframe by poking at it with ioctls. */#include <stdio.h>#include <stdlib.h>#include <fcntl.h>#include <string.h>#include <sys/stat.h>#include <sys/types.h>#include <sys/ioctl.h>#if RF_DFSTRACE > 0#include <sys/dfstracebuf.h>#endif /* RF_DFSTRACE > 0 */#include "rf_raidframe.h"static void DoIoctl(int fd, unsigned long which, void *arg, char *cmdstring);static void DoConfigure(int fd, char *configfile);static void bad_line(char *s);static void usage(void);static int raidID;#define RF_DEV2RAIDID(_dev) (minor(_dev)>>6) /* convert dev_t to raid id */#define SECTOR_SHIFT 9main(argc,argv) int argc; char **argv;{ int fd, nscanned, pctg, nomenu, nbytes; char *devfile = "/dev/raidframe_c"; char filen[100], cmdbuf[200], hostname[256]; struct stat buf; dev_t dev; unsigned long devno_long; struct rf_test_acc testacc; struct rf_recon_req fdisk_desc; nomenu = 0; argc--; argv++; while (argc && argv[0][0] == '-') { switch(argv[0][1]) { case 'M': nomenu = 1; break; default: fprintf(stderr,"Unknown option '%s'\n",argv[0]); usage(); exit(1); } argc--; argv++; } if (argc == 1) devfile = argv[0]; if (stat(devfile, &buf) < 0) {fprintf(stderr,"stat failure on %s\n",devfile); exit(1);} dev = buf.st_rdev; raidID = RF_DEV2RAIDID(dev); printf("Working with raid device number %d\n\n",raidID); fd = open(devfile, O_RDWR, 0644); if (fd < 0) { fprintf(stderr,"Unable to open raidframe device file\n"); perror("open"); exit(1); } while (1) { if (!nomenu) { printf("c [cfgfile]-- Configure from cfgfile (/dev/.rfconfigN if none)\n"); printf("s -- Shutdown\n"); printf("r -- Rewrite (initialize) parity\n"); printf("t dev -- TUR through raidframe on devno 'd'\n"); printf("a r/w s n -- Do a test read/write to sector s, numsector n\n"); printf("f r c flag -- Fail the disk at row r col c, init recon if flag non-zero\n"); printf("C -- Do a copyback after a reconstruction\n"); printf("R r -- Check reconstruction status on row r (default 0)\n"); printf("S d -- Fork a sparemap daemon using sparemap directory d\n"); printf("A -- Cause the sparemap daemon to wake up and exit\n");#if RF_DFSTRACE > 0 printf("d -- Start the dfstrace agent and collector\n"); printf("K -- Shutdown the dfstrace agent and collector\n"); printf("F -- Do a dfstrace flush operation\n"); printf("n -- Do a dfstrace newFile operation\n"); printf("T 1/0 -- Start/Stop DFS tracing of accesses\n");#endif /* RF_DFSTRACE > 0 */ printf("o -- Reset acc_totals\n"); printf("O 1/0 -- Toggle acc_total capture\n"); printf("q -- quit\n"); printf("\nCommand? "); } if (!gets(cmdbuf)) break; switch (*cmdbuf) { case 'o': DoIoctl(fd, RAIDFRAME_RESET_ACCTOTALS, NULL, "reset_acctotals"); break; case 'O': { char *str; int keep; str = strtok(cmdbuf, " \t"); str = strtok(NULL, " \t"); if (str == NULL) { fprintf(stderr, "Must specify 1 or 0 (on or off)\n"); fflush(stderr); break; } if (sscanf(str, "%d", &keep) != 1) { fprintf(stderr, "Cannot parse \"%s\" to an integer\n", str); fflush(stderr); break; } DoIoctl(fd, RAIDFRAME_KEEP_ACCTOTALS, &keep, "keep_acctotals"); } break; case 'T': nscanned = sscanf(cmdbuf,"T %d",&pctg); if (nscanned != 1) {bad_line(cmdbuf); break;} DoIoctl(fd, (unsigned long) ((pctg == 1) ? RAIDFRAME_START_ATRACE : RAIDFRAME_STOP_ATRACE), NULL, "atrace"); break; case 'c': nscanned = sscanf(cmdbuf,"c %s",filen); /* sscanf returns EOF "if the input ends before the first conflict or conversion" */ if (nscanned == EOF) sprintf(filen,"/dev/.rfconfig%d",raidID); else if (nscanned != 1) {bad_line(cmdbuf); break;} DoConfigure(fd, filen); break; case 's': DoIoctl(fd, (unsigned long) RAIDFRAME_SHUTDOWN, NULL, "shutdown"); break; case 'r': DoIoctl(fd, (unsigned long) RAIDFRAME_REWRITEPARITY, NULL, "rewrite"); break; case 't': if (sscanf(cmdbuf, "t 0x%lx",&devno_long) != 1) { if (sscanf(cmdbuf, "t %ld",&devno_long) != 1) {bad_line(cmdbuf); break;} } DoIoctl(fd, (unsigned long) RAIDFRAME_TUR, (void *) devno_long, "TUR"); break; case 'a': { if (sscanf(cmdbuf, "a %c 0x%lx 0x%x",&testacc.type, &testacc.startSector, &testacc.numSector) != 3) { if (sscanf(cmdbuf, "a %c %ld 0x%x",&testacc.type, &testacc.startSector, &testacc.numSector) != 3) { if (sscanf(cmdbuf, "a %c 0x%lx %d",&testacc.type, &testacc.startSector, &testacc.numSector) != 3) { if (sscanf(cmdbuf, "a %c %ld %d",&testacc.type, &testacc.startSector, &testacc.numSector) != 3) { bad_line(cmdbuf); break; } } } } nbytes = testacc.numSector<<SECTOR_SHIFT; testacc.buf = malloc(nbytes); if (testacc.buf == NULL) { printf("Unable to malloc %d bytes\n", nbytes); break; } DoIoctl(fd, (unsigned long) RAIDFRAME_TEST_ACC, (void *) &testacc, "testacc"); free(testacc.buf); } break; case 'f': nscanned = sscanf(cmdbuf, "f %d %d %d",&fdisk_desc.row,&fdisk_desc.col,&fdisk_desc.flags); if (nscanned != 2 && nscanned != 3) {bad_line(cmdbuf); break;} if (nscanned == 3 && fdisk_desc.flags) fdisk_desc.flags = RF_FDFLAGS_RECON; else fdisk_desc.flags = RF_FDFLAGS_NONE; DoIoctl(fd, (unsigned long) RAIDFRAME_FAIL_DISK, (void *) &fdisk_desc, "fail disk"); break; case 'R': nscanned = sscanf(cmdbuf, "R %d", &pctg); if (nscanned != 1 && nscanned != -1 && nscanned != 0) {bad_line(cmdbuf); break;} if (nscanned == 0 || nscanned == -1) pctg = 0; DoIoctl(fd, (unsigned long) RAIDFRAME_CHECKRECON, (void *) &pctg, "checkrecon"); printf("Reconstruction is %d %% complete\n",pctg); break; case 'C': DoIoctl(fd, (unsigned long) RAIDFRAME_COPYBACK, NULL, "copyback"); break; case 'S': nscanned = sscanf(cmdbuf,"S %s",filen); if (nscanned <= 0) sprintf(filen,"/afs/cs/project/pdl-1/Mark/Reconstruction/lib/sparemaps"); nscanned = fork(); if (nscanned < 0) { perror("rfctrl: fork failed\n"); } else if (nscanned == 0) { if (execl("smd", "smd", filen, NULL)) { perror("rfctrl child process: exec failed"); exit(1); } } break; case 'A': DoIoctl(fd, (unsigned long) RAIDFRAME_ABORT_SPARET_WAIT, NULL, "spare wait abort"); break; #if RF_DFSTRACE > 0 /* we first check the user's path for agent & collector, and if not found, * we default to /usr/dfstrace/bin */#define STRINGIFY(string) "string"#define DFSDIR /usr16/jimz/rfcfgs/#define DFSCONCAT(file) DFSDIR/**/file case 'd': printf("starting agent and collector\n"); nscanned = fork(); if (nscanned < 0) { perror("rfctrl: fork failed\n"); } else if (nscanned == 0) { if (execlp("collector", "collector", "-d", ".", "-g", "/dev/null", "-n", "-c", "0", NULL)) { if (execlp("DFSCONCAT(collector)", "collector", "-d", ".", "-g", "/dev/null", "-n", "-c", "0", NULL)) { perror("rfctrl child process: exec failed for collector"); exit(1); } printf("started collector from %s\n", STRINGIFY(DFSDIR)); } else { printf("started collector\n"); } } else { printf("collector is pid %d\n", nscanned); } sleep(3); /* give the collector a chance to get started */ nscanned = fork(); if (nscanned < 0) { perror("rfctrl: fork failed\n"); } else if (nscanned == 0) { char dfs_traceon_val[256]; if (gethostname(hostname, 256)) { perror("Unable to get host name for agent fork"); exit(1); } sprintf(dfs_traceon_val, "%ld", (DFS_TRACE_RAIDFRAME|DFS_TRACE_SCSI|DFS_TRACE_IO|DFS_TRACE_BASIC)); if (execlp("agent", "agent", "-l", "256", "-b3", "-h", hostname, "-c", "0", "-g", "/dev/null", NULL)) { if (execlp("DFSCONCAT(agent)", "agent", "-l", dfs_traceon_val, "-b3", "-h", hostname, "-c", "0", "-g", "/dev/null", NULL)) { perror("rfctrl child process: exec failed for agent"); exit(1); } printf("started agent from %s\n", STRINGIFY(DFSDIR)); } else { printf("started agent\n"); } } else { printf("agent is pid %d\n", nscanned); } printf("done starting agent and collector\n"); break; case 'K': nscanned = fork(); if (nscanned < 0) { perror("rfctrl: fork failed\n"); } else if (nscanned == 0) { if (execlp("shutAgent", "shutAgent", NULL)) { if (execlp("DFSCONCAT(shutAgent)", "shutAgent", NULL)) { perror("rfctrl child process: exec failed for agent shutdown"); exit(1); } } } sleep(3); /* give the agent a chance to shut down */ nscanned = fork(); if (nscanned < 0) { perror("rfctrl: fork failed\n"); } else if (nscanned == 0) { if (gethostname(hostname, 256)) { perror("Unable to get host name for agent fork"); exit(1); } if (execlp("shutCollector", "shutCollector", NULL)) { if (execlp("DFSCONCAT(shutCollector)", "shutCollector", NULL)) { perror("rfctrl child process: exec failed for collector shutdown"); exit(1); } } } break; case 'n': nscanned = fork(); if (nscanned < 0) { perror("rfctrl: fork failed\n"); } else if (nscanned == 0) { if (execlp("newFile", "newFile", NULL)) { if (execlp("DFSCONCAT(newFile)", "newFile", NULL)) { perror("rfctrl child process: exec failed for newFile"); exit(1); } } } break; case 'F': nscanned = fork(); if (nscanned < 0) { perror("rfctrl: fork failed\n"); } else if (nscanned == 0) { if (execlp("trflush", "trflush", NULL)) { if (execlp("DFSCONCAT(trflush)", "trflush", NULL)) { perror("rfctrl child process: exec failed for dfsflush"); exit(1); } } } break;#endif /* RF_DFSTRACE > 0 */ case 'q': exit(0); default: bad_line(cmdbuf); break; } } }static void usage(){ fprintf(stderr,"Usage: rfctrl [device_file]\n");}static void bad_line(char *s){ printf("Unparse-able line: %s\n",s);}static void DoConfigure(int fd, char *configfile){ void *p; char cmdbuf[256], namebuf[256]; int status; RF_Config_t cfg; if (rf_MakeConfig(configfile, &cfg) < 0) { fprintf(stderr,"Unable to create configuration structure\n"); return; } /* the argument to ioctl is a pointer to the data to be copied in. * I want only the pointer to the configuration info to be copied in, * so I use p as an extra level of indirection */ p = (void *) &cfg; if (ioctl(fd, (unsigned long) RAIDFRAME_CONFIGURE, (void *) &p) < 0) { perror("config ioctl"); } else { sprintf(namebuf, "/dev/.rfconfig%d",raidID); if (strcmp(configfile, namebuf)) { /* don't try to copy if the input file is /dev/.rfconfigX */ sprintf(cmdbuf, "cp %s /dev/.rfconfig%d",configfile,raidID); if (system(cmdbuf)) printf("Copy to /dev/.rfconfig%d failed\n",raidID); else printf("File %s copied to /dev/.rfconfig%d\n",configfile,raidID); } }}static void DoIoctl(int fd, unsigned long which, void *arg, char *cmdstring){ char errbuf[100]; if (ioctl(fd, which, arg) < 0) { sprintf(errbuf,"%s ioctl",cmdstring); perror(errbuf); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -