?? arytst.c
字號:
/* * Array Test * * Regression test utility for raidreconf * (C) 2000, by Jakob Oestergaard * * This software is licensed under the GNU Public License. * * Usage: * arytst {-w|-r} -l <raid level, {0,1,4,5,20,30}> -c <chunksize (blocks)> -s <array size (blocks)> <dev0> <dev1> ... * A block is 1024 bytes * Array level 20 : linear * Array level 30 : single disk * * arrays are filled with 64-bit words holding * [gblock number : 32 bit] * [origin level : 8 bit] * [origin disk-chunk : 16 bit] * [padding : 8 bit] */#define BLOCK_SIZE 1024#include "common.h"#include <popt.h>#include <stdio.h>#include <errno.h>#include <string.h>long array_size = 0;long chunk_size = 0;int array_level = -1;char opt_write = 0, opt_read = 0;char ** args = 0;struct fillword { unsigned int block_num; char org_level; unsigned short org_dchunk; char padding;};#define GBLK_SIZE 1024#define PADNUM 42void print_fillword(const struct fillword*);void init_fillword(struct fillword*, unsigned gblock, unsigned dchunk);void init_block_buf(char*, unsigned gblock, unsigned dchunk);int check_fillword(const struct fillword*, unsigned gblock, unsigned dchunk);int check_block_buf(const char*, unsigned gblock, unsigned dchunk);static void ary_progress(const char*, unsigned now, unsigned total);static void endary_progress(const char*);int write_single(void);int read_single(void);int write_raid0(void);int read_raid0(void);int main(int argc, const char** argv){ poptContext optCon; int i; struct poptOption optionsTable[] = { {"write", 'w', POPT_ARG_NONE, &opt_write, 0}, {"read", 'r', POPT_ARG_NONE, &opt_read, 0}, {"level", 'l', POPT_ARG_INT, &array_level, 0}, {"chunksize", 'c', POPT_ARG_LONG, &chunk_size, 0}, {"arraysize", 's', POPT_ARG_LONG, &array_size, 0}, {0, 0, 0, 0, 0} } ; /* * Parse options */ optCon = poptGetContext("arytst", argc, argv, optionsTable, 0); if ((i = poptGetNextOpt(optCon)) < -1) { fprintf(stderr, "%s: %s\n", poptBadOption(optCon, POPT_BADOPTION_NOALIAS), poptStrerror(i)); return -1; } args = (char **)poptGetArgs(optCon); if(!args) { fprintf(stderr, "No devices given\n"); return -1; } /* * Make sure mandatory arguments are given */ if(!opt_read && !opt_write) { fprintf(stderr, "Must either read or write\n"); return -1; } if(opt_read && opt_write) { fprintf(stderr, "Cannot both read and write\n"); return -1; } if(array_level != 0 && array_level != 30) { fprintf(stderr, "We only know raid level 0 and 30 (single disk) for now\n"); return -1; } if(chunk_size <= 0) { fprintf(stderr, "Chunk size must be specified\n"); return -1; } if(array_size <= 0) { fprintf(stderr, "Array size must be specified\n"); return -1; } /* * Choose action */ if(opt_write) { switch(array_level) { case 0: return write_raid0(); case 30: return write_single(); default: fprintf(stderr, "Unknown level\n"); return -1; } } if(opt_read) { switch(array_level) { case 0: return read_raid0(); case 30: return read_single(); default: fprintf(stderr, "Unknown level\n"); return -1; } } return 0;}void print_fillword(const struct fillword* fw){ fprintf(stderr, "block_num = %u\n" "org_level = %i\n" "org_dchunk = %u\n" "padding = %i\n", fw->block_num, fw->org_level, fw->org_dchunk, fw->padding);}void init_fillword(struct fillword* fw, unsigned gblock, unsigned dchunk){ fw->block_num = gblock; fw->org_level = array_level; fw->org_dchunk = dchunk; fw->padding = PADNUM;}void init_block_buf(char* buf, unsigned gblock, unsigned dchunk){ int pos; for(pos = 0; pos != GBLK_SIZE / sizeof(struct fillword); pos++) init_fillword((struct fillword*)(buf + sizeof(struct fillword) * pos), gblock, dchunk);}int check_fillword(const struct fillword* fw, unsigned gblock, unsigned dchunk){ if(fw->block_num != gblock) { fprintf(stderr, "\n*** Mismatch at gblock = %u, dchunk = %u\n", gblock, dchunk); print_fillword(fw); return 1; } else if(fw->padding != PADNUM) { fprintf(stderr, "\n*** Bad padding at gblock = %u, dchunk = %u\n", gblock, dchunk); print_fillword(fw); return 1; } return 0;}int check_block_buf(const char* buf, unsigned gblock, unsigned dchunk){ int pos; int rc; for(pos = 0; pos != GBLK_SIZE / sizeof(struct fillword); pos++) if((rc = check_fillword((const struct fillword*)(buf + sizeof(struct fillword) * pos), gblock, dchunk))) return rc; return 0;}void ary_progress(const char* dev, unsigned now, unsigned total){ fprintf(stderr, "\r%s: %9u/%-9u ~%3i%%", dev, now, total, now * 100 / total); fflush(stderr);}void endary_progress(const char* dev){ fprintf(stderr, "\r%s: all done. \n", dev);}int write_single(void){ FILE * fp = 0; unsigned blocks; if(!args[0] || args[1]) { fprintf(stderr, "Must have precisely one device\n"); return -1; } if(!(fp = fopen(args[0], "w"))) { fprintf(stderr, "Cannot open %s for writing\n", args[0]); return -1; } for(blocks = 0; blocks != array_size; blocks++) { char buf[GBLK_SIZE]; init_block_buf(buf, blocks, blocks / chunk_size); fwrite(buf, GBLK_SIZE, 1, fp); ary_progress(args[0], blocks, array_size); } endary_progress(args[0]); fclose(fp); return 0;}int read_single(void){ FILE * fp = 0; unsigned blocks; if(!args[0] || args[1]) { fprintf(stderr, "Must have precisely one device\n"); return -1; } if(!(fp = fopen(args[0], "r"))) { fprintf(stderr, "Cannot open %s for writing\n", args[0]); return -1; } for(blocks = 0; blocks != array_size; blocks++) { char buf[GBLK_SIZE]; int rc; if(1 != fread(buf, GBLK_SIZE, 1, fp)) { fprintf(stderr, "\nCannot read\n"); return -1; } if((rc = check_block_buf(buf, blocks, blocks / chunk_size))) return rc; ary_progress(args[0], blocks, array_size); } endary_progress(args[0]); fclose(fp); return 0;}int write_raid0(void){ FILE * fp = 0; unsigned blocks; char ** cur_dev; mdp_super_t sb; int ndisks = 0; int curdisk = 0; if(!args[0]) { fprintf(stderr, "Must have one or more devices\n"); return -1; } for(cur_dev = args; *cur_dev; cur_dev++) ndisks ++; for(cur_dev = args; *cur_dev; cur_dev++,curdisk++) { if(!(fp = fopen(*cur_dev, "w"))) { fprintf(stderr, "Cannot open %s for writing\n", *cur_dev); return -1; } for(blocks = curdisk; blocks-curdisk < array_size; blocks += ndisks) { char buf[GBLK_SIZE]; init_block_buf(buf, blocks, (blocks-curdisk) / chunk_size); fwrite(buf, GBLK_SIZE, 1, fp); ary_progress(*cur_dev, blocks, array_size); } endary_progress(*cur_dev); /* Put a superblock in there too */ if(fseek(fp, 1024 * MD_NEW_SIZE_BLOCKS(array_size/ndisks), SEEK_SET)) { fprintf(stderr, "Cannot seek to superblock position: %s\n", strerror(errno)); return -1; } else fprintf(stderr, "Pos: %lu\n", MD_NEW_SIZE_BLOCKS(array_size/ndisks)); memset(&sb, 0, sizeof(sb)); sb.md_magic = MD_SB_MAGIC; sb.state = (1 << MD_SB_CLEAN); fwrite(&sb, sizeof(sb), 1, fp); fclose(fp); } return 0;}int read_raid0(void){ FILE * fp = 0; unsigned blocks; char ** cur_dev; int ndisks = 0; int curdisk = 0; if(!args[0]) { fprintf(stderr, "Must have one or more devices\n"); return -1; } for(cur_dev = args; *cur_dev; cur_dev++) ndisks ++; for(cur_dev = args; *cur_dev; cur_dev++,curdisk++) { unsigned dblocks_read = 0; if(!(fp = fopen(*cur_dev, "r"))) { fprintf(stderr, "Cannot open %s for writing\n", *cur_dev); return -1; } for(blocks = curdisk; blocks-curdisk < array_size; blocks += ndisks) { char buf[GBLK_SIZE]; int rc; fread(buf, GBLK_SIZE, 1, fp); dblocks_read ++; if(dblocks_read == MD_NEW_SIZE_BLOCKS(array_size/ndisks)) break; if((rc = check_block_buf(buf, blocks, (blocks-curdisk) / chunk_size))) return rc; ary_progress(*cur_dev, blocks, array_size); } endary_progress(*cur_dev); fclose(fp); } return 0;}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -