【转载】minix mkfs.c 可在RedFlag 4.0 上编译运行

   1: /*
   2: * mkfs.c - make a linux (minix) file-system.
   3: *
   4: * (C) 1991 Linus Torvalds. This file may be redistributed as per
   5: * the Linux copyright.
   6: */
   7:  
   8: /*
   9: * 24.11.91 -    time began. Used the fsck sources to get started.
  10: *
  11: * 25.11.91 -    corrected some bugs. Added support for ".badblocks"
  12: *        The algorithm for ".badblocks" is a bit weird, but
  13: *        it should work. Oh, well.
  14: *
  15: * Usuage: mkfs [-c] device size-in-blocks
  16: *
  17: *    -c for readablility checking (SLOW!)
  18: *
  19: * The device may be a block device or a image of one, but this isn't
  20: * enforced (but it's not much fun on a character device :-). 
  21: */
  22: /*--hgl--该程序用于创建MINIX1.0文件系统(即通常所说的格式化)
  23: //--hgl--相当于fdisk
  24: //--hgl--主要功能:
  25: //--hgl--                1,建立超级块,位图区域,inode区域和数据区
  26: //--hgl--                2,检测磁盘的坏块
  27: --hgl--*/
  28:  
  29: #include <unistd.h>
  30: #include <fcntl.h>
  31: #include <ctype.h>
  32: #include <termios.h>
  33: #include <sys/stat.h>
  34:  
  35: #include <linux/fs.h>
  36:  
  37: #ifndef __GNUC__
  38: #error "needs gcc for the bitop-__asm__'s"
  39: #endif
  40:  
  41: #ifndef __linux__
  42: #define volatile
  43: #endif
  44:  
  45: #define ROOT_INO 1                            //--hgl--根inode号
  46: #define BAD_INO 2
  47:  
  48: #define TEST_BUFFER_BLOCKS 32                //--hgl--测试时的步进长度
  49: #define MAX_GOOD_BLOCKS 512                //--hgl--
  50:  
  51: #define UPPER(size,n) ((size+((n)-1))/(n))                    //--hgl--向上取整
  52: #define INODE_SIZE (sizeof(struct d_inode))                    //--hgl--
  53: #define INODE_BLOCKS UPPER(INODES,INODES_PER_BLOCK)
  54: #define INODE_BUFFER_SIZE (INODE_BLOCKS * BLOCK_SIZE)    //--hgl--inode区域的大小
  55:  
  56: #define BITS_PER_BLOCK (BLOCK_SIZE<<3)        //--hgl--每block的bit数目
  57:  
  58: static char * program_name = "mkfs";    //--hgl--默认的程序名称
  59: static char * device_name = NULL;
  60: static int DEV = -1;                    //--hgl--该块设备的文件句柄(其实就是current->filp[]中的下标)
  61: static long BLOCKS = 0;                    //--hgl--逻辑块数目
  62: static int check = 0;
  63: static int badblocks = 0;                //--hgl--坏块的数目
  64:  
  65: #define ROOT_INO_STRING "\001\000"    //--hgl--第一数据块位根节点
  66: #define BAD_INO_STRING "\002\000"    //--hgl--第二数据块位坏块的记录
  67:  
  68: //--hgl--根的目录项
  69: static char root_block[BLOCK_SIZE] =
  70: ROOT_INO_STRING ".\0\0\0\0\0\0\0\0\0\0\0\0\0"
  71: ROOT_INO_STRING "..\0\0\0\0\0\0\0\0\0\0\0\0"
  72: BAD_INO_STRING ".badblocks\0\0\0\0";
  73:  
  74: static char * inode_buffer = NULL;                    //--hgl--inode区域
  75:    //--hgl--这里减1,可能是因为inode是1为起始的,所以预先减1了
  76: #define Inode (((struct d_inode *) inode_buffer)-1)    
  77: static char super_block_buffer[BLOCK_SIZE];
  78: #define Super (*(struct super_block *)super_block_buffer)
  79: #define INODES ((unsigned long)Super.s_ninodes)        //--hgl--inode数目
  80: #define ZONES ((unsigned long)Super.s_nzones)        //--hgl--逻辑块总数
  81: #define IMAPS ((unsigned long)Super.s_imap_blocks)    //--hgl--inode位图的block数目
  82: #define ZMAPS ((unsigned long)Super.s_zmap_blocks)    //--hgl--逻辑块位图的blk数目
  83: #define FIRSTZONE ((unsigned long)Super.s_firstdatazone)    //--hgl--第一个数据块的逻辑块号
  84: #define ZONESIZE ((unsigned long)Super.s_log_zone_size)
  85: #define MAXSIZE ((unsigned long)Super.s_max_size)
  86: #define MAGIC (Super.s_magic)
  87: //--hgl--2=1+1,boot和sb
  88: #define NORM_FIRSTZONE (2+IMAPS+ZMAPS+INODE_BLOCKS)    //--hgl--数据区的起始逻辑块号
  89:  
  90: static char inode_map[BLOCK_SIZE * I_MAP_SLOTS];    //--hgl--inode位图
  91: static char zone_map[BLOCK_SIZE * Z_MAP_SLOTS];    //--hgl--逻辑块位图
  92: //--hgl--因为在格式化的时候,先检测磁盘,如果发现坏块
  93: //--hgl--则在blk位图中标记占用,所以正常的逻辑块的使用
  94: //--hgl--情况不能在blk位图中标记了,所以就引入good_blocks_table[]
  95: //--hgl--来保存正常逻辑块的占用情况
  96: static unsigned short good_blocks_table[MAX_GOOD_BLOCKS];        //--hgl--已经使用的逻辑块数组,
  97: static int used_good_blocks = 0;                    //--hgl--已经使用的好的逻辑块
  98:  
  99: #define bitop(name,op) \
 100: static inline int name(char * addr,unsigned int nr) \
 101: { \
 102: int __res; \
 103: __asm__ __volatile__("bt" op " %1,%2; adcl $0,%0" \
 104: :"=g" (__res) \
 105: :"r" (nr),"m" (*(addr)),"0" (0)); \
 106: return __res; \
 107: }
 108:  
 109: bitop(bit,"")
 110: bitop(setbit,"s")
 111: bitop(clrbit,"r")
 112:  
 113: #define inode_in_use(x) (bit(inode_map,(x)))
 114: #define zone_in_use(x) (bit(zone_map,(x)-FIRSTZONE+1))        //--hgl--询问该位的值
 115: //--hgl--标记inode号为x的位图为1
 116: #define mark_inode(x) (setbit(inode_map,(x)))    
 117: #define unmark_inode(x) (clrbit(inode_map,(x)))
 118:  
 119: #define mark_zone(x) (setbit(zone_map,(x)-FIRSTZONE+1))
 120: #define unmark_zone(x) (clrbit(zone_map,(x)-FIRSTZONE+1))
 121:  
 122: /*
 123: * Volatile to let gcc know that this doesn't return. When trying
 124: * to compile this under minix, volatile gives a warning, as
 125: * exit() isn't defined as volatile under minix.
 126: */
 127: volatile void fatal_error(const char * fmt_string)
 128: {
 129:    printf(fmt_string);
 130:    exit(1);
 131: }
 132:  
 133: #define usage() fatal_error("Usage: %s [-c] /dev/name blocks\n")
 134: #define die(str) fatal_error(": " str "\n")
 135:  
 136: void write_tables(void)
 137: //--hgl--P--将前面的几个过程中建立的buffer 回写到块设备
 138: {
 139: //--hgl--跳过boot块
 140:    if (BLOCK_SIZE != lseek(DEV, BLOCK_SIZE, SEEK_SET))
 141:        die("seek failed in write_tables");
 142: //--hgl--填写sb
 143:    if (BLOCK_SIZE != write(DEV, super_block_buffer, BLOCK_SIZE))
 144:        die("unable to write super-block");
 145: //--hgl--填写inode位图域
 146:    if (IMAPS*BLOCK_SIZE != write(DEV,inode_map,IMAPS*BLOCK_SIZE))
 147:        die("Unable to write inode map");
 148: //--hgl--填写blk位图域
 149:    if (ZMAPS*BLOCK_SIZE != write(DEV,zone_map,ZMAPS*BLOCK_SIZE))
 150:        die("Unable to write zone map");
 151: //--hgl--填写inode缓冲区
 152:    if (INODE_BUFFER_SIZE != write(DEV,inode_buffer,INODE_BUFFER_SIZE))
 153:        die("Unable to write inodes");
 154: }
 155: //--hgl--blk            目标逻辑块
 156: //--hgl--buffer        源缓冲区
 157: void write_block(int blk, char * buffer)
 158: //--hgl--P--填写逻辑块
 159: //--hgl--???????????????????
 160: {
 161: //--hgl--因为它是一个应用程序,所以不能
 162:    //--hgl--将该文件(其实是块设备)的文件指针指向blk
 163:    if (blk*BLOCK_SIZE != lseek(DEV, blk*BLOCK_SIZE, SEEK_SET))
 164:        die("seek failed in write_block");
 165:    //--hgl--
 166:    if (BLOCK_SIZE != write(DEV, buffer, BLOCK_SIZE))
 167:        die("write failed in write_block");
 168: }
 169:  
 170: int get_free_block(void)
 171: //--hgl--P--获得空闲的逻辑块,并在good_block_table中标记该blk已经被使用
 172: //--hgl--将正常的逻辑块(但被使用了,不直接标记在inode用,)而是保存在
 173: //--hgl--used_good_blocks[]中,因为这时只有坏块才在inode位图中标记,
 174: //--hgl--以免混淆
 175: {
 176:    int blk;
 177: //--hgl--??????????????好像和坏块的数目没有关系呀
 178:    if (used_good_blocks+1 >= MAX_GOOD_BLOCKS)
 179:        die("too many bad blocks");
 180:    //--hgl--获得查找的起始逻辑块号
 181:    if (used_good_blocks)
 182:        blk = good_blocks_table[used_good_blocks-1]+1;
 183:    else
 184:        blk = FIRSTZONE;
 185:    //--hgl--找到没有被占用的blk
 186:    while (blk < ZONES && zone_in_use(blk))
 187:        blk++;
 188:    
 189:    if (blk >= ZONES)
 190:        die("not enough good blocks");
 191: //--hgl--将该逻辑块号添加到
 192:    good_blocks_table[used_good_blocks] = blk;
 193:    used_good_blocks++;
 194:    return blk;
 195: }
 196:  
 197: void mark_good_blocks(void)
 198: //--hgl--P--标记已经使用的好的逻辑块(在blk位图中标记)
 199: {
 200:    int blk;
 201:  
 202:    for (blk=0 ; blk < used_good_blocks ; blk++)
 203:        mark_zone(good_blocks_table[blk]);
 204: }
 205: //--hgl--zone    逻辑块号
 206: inline int next(int zone)
 207: //--hgl--P--
 208: {
 209:    //--hgl--zone==0表示为第一次搜索
 210:    if (!zone)
 211:        zone = FIRSTZONE-1;    //--hgl--减1,因为后面是先++zone
 212:    //--hgl--搜索整个数据区,如果被占用了,则表示是坏块
 213:    while (++zone < ZONES)
 214:        if (zone_in_use(zone))
 215:            return zone;
 216:    return 0;
 217: }
 218:  
 219: void make_bad_inode(void)
 220: //--hgl--P--将坏的逻辑块都连接到第二ionde
 221: {
 222:    struct d_inode * inode = &Inode[BAD_INO];
 223:    int i,j,zone;
 224:    int ind=0,dind=0;
 225:    unsigned short ind_block[BLOCK_SIZE>>1];
 226:    unsigned short dind_block[BLOCK_SIZE>>1];
 227:  
 228: #define NEXT_BAD (zone = next(zone))
 229:    //--hgl--看是否有坏块
 230:    if (!badblocks)
 231:        return;
 232:    //--hgl--如果有,则占用坏块节点
 233:    mark_inode(BAD_INO);
 234:    inode->i_nlinks = 1;
 235:    inode->i_time = time(NULL);
 236:    inode->i_mode = S_IFREG + 0000;
 237:    inode->i_size = badblocks*BLOCK_SIZE;    //--hgl--确定坏块文件的大小
 238: //--hgl--填写直接块号
 239:    zone = next(0);
 240:    for (i=0 ; i<7 ; i++) {
 241:        inode->i_zone[i] = zone;
 242:        if (!NEXT_BAD)
 243:            goto end_bad;
 244:    }
 245: //--hgl--填写一次间接块的缓冲区
 246:    //--hgl--获得一次间接块
 247:    inode->i_zone[7] = ind = get_free_block();
 248:    //--hgl--清空该一次间接块
 249:    memset(ind_block,0,BLOCK_SIZE);
 250:    //--hgl--填写一次间接块缓冲区
 251:    for (i=0 ; i<512 ; i++) {
 252:        ind_block[i] = zone;
 253:        if (!NEXT_BAD)
 254:            goto end_bad;
 255:    }
 256: //--hgl--填写二次间接块
 257:    inode->i_zone[8] = dind = get_free_block();
 258:    memset(dind_block,0,BLOCK_SIZE);
 259:    for (i=0 ; i<512 ; i++) {
 260:        //--hgl--回写到快设备
 261:        write_block(ind,(char *) ind_block);
 262:        //--hgl--
 263:        dind_block[i] = ind = get_free_block();
 264:        memset(ind_block,0,BLOCK_SIZE);
 265:        for (j=0 ; j<512 ; j++) {
 266:            ind_block[j] = zone;
 267:            if (!NEXT_BAD)
 268:                goto end_bad;
 269:        }
 270:    }
 271:    die("too many bad blocks");
 272: end_bad:
 273:    //--hgl--回写到块设备
 274:    if (ind)
 275:        write_block(ind, (char *) ind_block);
 276:    if (dind)
 277:        write_block(dind, (char *) dind_block);
 278: }
 279:  
 280: void make_root_inode(void)
 281: //--hgl--P--创建根inode
 282: {
 283: //--hgl--获得第一个inode,
 284:    struct d_inode * inode = &Inode[ROOT_INO];
 285: //--hgl--标记根inode已经被占用
 286:    mark_inode(ROOT_INO);
 287: //--hgl--填写该inode
 288:    inode->i_zone[0] = get_free_block();
 289:    inode->i_nlinks = 2;
 290:    inode->i_time = time(NULL);
 291:    //--hgl--确定文件大小
 292:    if (badblocks)
 293:        inode->i_size = 48;
 294:    else
 295:        inode->i_size = 32;
 296:    inode->i_mode = S_IFDIR + 0755;
 297: //--hgl--填写根inode的目录项
 298:    write_block(inode->i_zone[0],root_block);
 299: }
 300:  
 301: void setup_tables(void)
 302: //--hgl--P--填写缓冲区
 303: {
 304:    int i;
 305: //--hgl--???????????为何填写0xff(表示都被占用???)
 306: //--hgl--它可能是将整个磁盘当成一个大文件,由根inode来控制
 307:    memset(inode_map,0xff,sizeof(inode_map));    
 308:    memset(zone_map,0xff,sizeof(zone_map));
 309:    memset(super_block_buffer,0,BLOCK_SIZE);
 310: //--hgl--填写超级块
 311:    MAGIC = SUPER_MAGIC;
 312:    ZONESIZE = 0;
 313:    MAXSIZE = (7+512+512*512)*1024;
 314:    ZONES = BLOCKS;
 315:                    /* some magic nrs: 1 inode / 3 blocks */
 316:    //--hgl--***block和inode不是1:1的比例*********
 317:    INODES = BLOCKS/3;                        //--hgl--inode的数目
 318:                    /* I don't want some off-by-one errors, so this hack... */
 319: //--hgl--????????干吗要减去5呢????
 320:    if ((INODES & 8191) > 8188)
 321:        INODES -= 5;
 322:    //--hgl--如果是n块还多几个(<10)个比特,则放弃最后几个比特位
 323:    if ((INODES & 8191) < 10)            
 324:        INODES -= 20;
 325:    //--hgl--确定inode位图区域的大小
 326:    IMAPS = UPPER(INODES,BITS_PER_BLOCK);    //--hgl--向上取整
 327:    //--hgl--确定数据区位图区域的大小
 328:    ZMAPS = 0;
 329:    while (ZMAPS != UPPER(BLOCKS - NORM_FIRSTZONE,BITS_PER_BLOCK))
 330:        ZMAPS = UPPER(BLOCKS - NORM_FIRSTZONE,BITS_PER_BLOCK);
 331:    FIRSTZONE = NORM_FIRSTZONE;
 332: //--hgl--清空位图
 333:    //--hgl--清空所有数据区位图
 334:    for (i = FIRSTZONE ; i<ZONES ; i++)
 335:        unmark_zone(i);
 336:    //--hgl--清空所有inode位图
 337:    for (i = ROOT_INO ; i<INODES ; i++)
 338:        unmark_inode(i);
 339: //--hgl--清空inode区域
 340:    inode_buffer = malloc(INODE_BUFFER_SIZE);
 341:    if (!inode_buffer)
 342:        die("Unable to allocate buffer for inodes");
 343:    memset(inode_buffer,0,INODE_BUFFER_SIZE);
 344: //--hgl--打印消息
 345:    printf("%d inodes\n",INODES);
 346:    printf("%d blocks\n",ZONES);
 347:    printf("Firstdatazone=%d (%d)\n",FIRSTZONE,NORM_FIRSTZONE);
 348:    printf("Zonesize=%d\n",BLOCK_SIZE<<ZONESIZE);
 349:    printf("Maxsize=%d\n\n",MAXSIZE);
 350: }
 351:  
 352: void check_blocks(void)
 353: //--hgl--P--统计磁盘的坏块数目,并标记
 354: {
 355:    unsigned int current_block=0;    //--hgl--当前的逻辑块号
 356:    int try,got;
 357:    static char buffer[BLOCK_SIZE * TEST_BUFFER_BLOCKS];
 358:  
 359:    while (current_block < ZONES) {
 360:        if (lseek(DEV,current_block*BLOCK_SIZE,SEEK_SET) !=
 361:        current_block*BLOCK_SIZE)
 362:            die("seek failed in check_blocks");
 363:        //--hgl--连续读取TEST_BUFFER_BLOCKS长的数据
 364:        try = TEST_BUFFER_BLOCKS;
 365:        if (current_block + try > ZONES)
 366:            try = ZONES-current_block;
 367:        got = read(DEV, buffer, try * BLOCK_SIZE);
 368:        //--hgl--看是否被正确的读取
 369:        if (got<0)
 370:            got = 0;
 371:        if (got & (BLOCK_SIZE-1))
 372:            printf("Weird values in check_blocks: probably bugs\n");
 373:        
 374:        got /= BLOCK_SIZE;
 375:        current_block += got;
 376:        //--hgl--
 377:        if (got == try)                //--hgl--正确,则终止本次循环
 378:            continue;
 379:        if (current_block < FIRSTZONE)
 380:            die("bad blocks before data-area: cannot make fs");
 381: //--hgl--出错,则标志当前块被占用,(以防止该块被使用)
 382: //--hgl--?????没有完全标记呀???因为每次测试的块数n(1<n<TEST_BUFFER_BLOCKS)
 383:  
 384:        mark_zone(current_block);
 385:        badblocks++;
 386:        current_block++;
 387:    }
 388:    //--hgl--打印坏块的数目
 389:    if (badblocks)
 390:        printf("%d bad block%s\n",badblocks,(badblocks>1)?"s":"");
 391: }
 392:  
 393: //--hgl--Usage: mkfs [-c] device size-in-blocks
 394: //--hgl--第一个参数为程序名称
 395: //--hgl--第二个为设备名
 396: //--hgl--第三个为块数目
 397: int main(int argc, char ** argv)
 398: {
 399:    char * tmp;
 400:    struct stat statbuf;        //--hgl--inode的状态
 401: //--hgl--?????????????
 402:    if (argc && *argv)
 403:        program_name = *argv;
 404:    //--hgl--验证
 405:    if (INODE_SIZE * INODES_PER_BLOCK != BLOCK_SIZE)
 406:        die("bad inode size");
 407: //--hgl--<>解析参数
 408:    while (argc-- > 1) {
 409:        argv++;
 410: //--hgl--?????????
 411:        if (argv[0][0] != '-')        
 412:            if (device_name) {
 413:                BLOCKS = strtol(argv[0],&tmp,0);
 414:                if (*tmp)
 415:                    usage();
 416:            } else
 417:                device_name = argv[0];
 418:        //--hgl--如果有参数"-c"
 419:        else 
 420:            while (*++argv[0])
 421:            switch (argv[0][0]) {
 422:                case 'c': check=1; break;
 423:                default: usage();
 424:            }
 425:    }
 426:    if (!device_name || BLOCKS<10 || BLOCKS > 65536)
 427:        usage();
 428: //--hgl--打开设备device_name ,
 429: //--hgl--因为在unix中设备也是当作文件来访问的
 430:    DEV = open(device_name,O_RDWR);
 431:    if (DEV<0)
 432:        die("unable to open %s");
 433:    //--hgl--获的该文件的inode状态
 434:    if (fstat(DEV,&statbuf)<0)                
 435:        die("unable to stat %s");
 436:    //--hgl--检测该设备是否为块设备
 437:    if (!S_ISBLK(statbuf.st_mode))            
 438:        check=0;
 439:    else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0305)
 440:        die("Will not try to make filesystem on '%s'");
 441: //--hgl--
 442:    setup_tables();
 443: //--hgl--统计快设备的坏块,并在blk位图中标记
 444:    if (check)
 445:        check_blocks();
 446: //--hgl--创建根节点(即第一inode)
 447:    make_root_inode();
 448: //--hgl--创建第二inode,将坏块都归为第二inode的数据块,以免被使用
 449:    make_bad_inode();
 450: //--hgl--标记已经被占用的正常的逻辑块
 451:    mark_good_blocks();
 452: //--hgl--回写到快设备
 453:    write_tables();
 454:    return 0;
 455: }
posted @ 2011-01-11 03:35  羽落无声  阅读(981)  评论(0编辑  收藏  举报