📄 mkfs.c
字号:
/* * EFS version of mkfs. * * $Revision: 1.2 $ */#include "efs.h"#include <sys/stat.h>#include <sys/dkio.h>#include <diskinfo.h>#include <sys/ustat.h>#include <sys/major.h>#define HP_DISK_MODEL#ifdef HP_DISK_MODEL#include "diskmodel.param"#include "diskdevices.h"#endifextern char *malloc();extern char *calloc();void cgsizepick();void efs_newregfile();#define GOOD_INODE_TOTAL(b) (b / 10 + (b > 20000 ? 1000 : b / 20))char *progname; /* name of this program *//* user supplied information */char *special; /* name of special device */char *rawpath; /* equivalent raw device (may be the same) */long fs_blocks; /* total blocks in filesystem */long dev_blocks; /* total blocks on device */ino_t fs_isize = 0; /* total minimum inodes in partition */short fs_sectors; /* # of sectors per track */int user_inodes = 0;/* internally supplied information */long cg_align; /* alignment for cylinder groups */long i_align; /* alignment for inodes *//* random variables */long firstcg; /* block offset to first cg */long cg_fsize = 0; /* data size for a cylinder group */long cg_isize; /* inode size for a cylinder group */char is_ittybitty; /* non-zero for itty bitty filesystems */int fs_fd; /* fd to read/write on for special */long ncg; /* number of cylinder groups */struct efs *fs; /* pointer to sblock.fs */char *bitmap; /* base of incore copy of bitmap */long bitmap_blocks; /* number of bb's in bitmap */long bitmap_bytes; /* number of bytes in bitmap (exact) */char *proto; /* name of proto file */char *charp;FILE *fproto; /* FILE proto is open on during reading */char string[1000]; /* temp buffer for parsing proto */int end_blocks; /* blocks used by replsb at end */int start_blocks; /* blocks used by boot, superblock & bitmap * (rounded up to a cg_align boundary) */int cyl_align = 0; /* in auto mode, align inodes and data to * cylinder boundaries */int debug = 0;/* * This union declares a single BB, assuming that the minimum for raw i/o * is at least a BB. */union { struct efs fs; char block[BBTOB(BTOBB(sizeof(struct efs)))];} sblock;void getstr();void clear_other_sb();int quiet = 0;int interact = 0;int use_writeb = 0;int short_form = 1;int recover_option = 0;intgood_cg_size(blocks, iblocks, align)int blocks, iblocks, align;{ int size; size = (blocks / 100) + 20000; if (size < ((blocks + iblocks - 1) / iblocks) * align) size = ((blocks + iblocks - 1) / iblocks) * align; return size;}/* Given an (extended) dev_t, put it into the on-disk * union. If its components are within the range understood by earlier * kernels, use the old format; if not, put -1 in the old field & * store it in the new one. Duplicates logic in fs/efs/efs_inode.c * * XXXdh mkfs should really use the efs_putdev() in efs/cmd/nlib/libefs.a, * but that is missing several functions needed by the proto file stuff, * so until those are moved into nlib & tested, we have to use the old * lib/libefs.a */static voidefs_putdev(dev_t dev, union di_addr *di){major_t maj;minor_t min; if ( ((maj = (dev >> L_BITSMINOR)) > O_MAXMAJ) || ((min = (dev & L_MAXMIN)) > O_MAXMIN)) { di->di_dev.odev = -1; di->di_dev.ndev = dev; } else di->di_dev.odev = (maj << O_BITSMINOR) | min;}void main(argc, argv) int argc; char **argv;{ int cgblocks; int iblocks; int add_inodes = 0; int i, nargs; int fp; char **ap; progname = argv[0]; /* The (-q) option is not really intended to be documented or used by users. It is here for use of programs like the vadmin disk tool. Olson, 10/88 Another change (daveh 10/26/88): the default is now to just go ahead. If you want confirmation, give the -i flag. (Note: ALL - flags MUST come before any other arguments, for backward compatibility with any scripts which use the long forms). */ nargs = (argc > 4) ? 4 : argc; ap = argv; for (i = 1; i < nargs; i++) { if (ap[i][0] != '-') break; switch (ap[i][1]) { case 'd' : debug = 1; break; case 'q' : quiet++; break; case 'i' : interact++; break; case 'r' : recover_option++; break; case 'a' : cyl_align++; break; case 'n' : i++; user_inodes = atoi(ap[i]); argc--; argv++; break; default : userr(); } argc--; argv++; } /* If interactive use is specified, clobber 'quiet' so fs params get printed for the user. (-q -i is pretty stupid, but just in case...) */ if (interact) quiet = 0; if (argc != 3) { fprintf(stderr, "Usage: mkfs diskname protofile\n"); exit(-1); } proto = argv[2]; special = argv[1]; fproto = fopen(proto, "r"); if (!fproto) { fprintf(stderr, "%s: can't open proto file %s\n", progname, proto); exit(-1); } getstr(); /* ignore get boot image */ fs_blocks = getnum(); fs_isize = GOOD_INODE_TOTAL(fs_blocks); add_inodes = (fs_blocks - 0x8000) / 4; if (add_inodes < 0) add_inodes = 0; if (add_inodes > 4096) add_inodes = 4096; fs_isize += add_inodes; fs_sectors = getnum();#ifdef HP_DISK_MODEL fs_sectors = NSECTORS;#endif cg_align = 1; /* No alignment */ i_align = 1; /* No alignment */ /* protect user against himself. sigh... */ if ((fs_blocks == 0) || (fs_isize == 0) || (fs_sectors == 0) || (cg_align == 0) || (i_align == 0)) { fprintf(stderr,"%s: Illegal zero numeric parameter.\n", progname); exit(-1); } /* NOTE (daveh 12/13/89): if fs_blocks is greater than the 2 gig * limit, we must use the new writeb system call (and cannot * proceed if this is not present, ie on a 3.2 kernel). * This works only on a char device, so we need in that case to find * the equivalent char device even if invoked on block. * Also, the structure of efs extent descriptors imposes, for the * moment, an 8 gig absolute upper limit. (24 bit offsets). */ if (fs_blocks > 0xffffff) { fprintf(stderr,"%s: filesystems may not exceed 8 gigabytes!\n", progname); exit(-1); } if ((fs_fd = open(special, O_RDWR|O_CREAT, 0664)) < 0) { fprintf(stderr, "%s: can't open %s\n", progname, special); exit(-1); } /* * Now seek to the end of the file and then back. */ fp = lseek(fs_fd, (fs_blocks * 512) - 1, SEEK_SET); if (fp != (fs_blocks * 512 -1)) { perror(progname); exit(-1); } if (write(fs_fd, "\000", 1) != 1) { perror(progname); exit(-1); } /* * Compute the number of blocks used by the bootblock, superblock * & bitmap, rounded up to a cg_align boundary. The first cylinder * group starts there. * The replicated superblock at the end effectively consumes cg_align * blocks. */ bitmap_bytes = (fs_blocks + BITSPERBYTE - 1) / BITSPERBYTE; bitmap_blocks = BTOBB(bitmap_bytes); start_blocks = 2 + bitmap_blocks; if (i = (start_blocks % cg_align)) start_blocks += (cg_align - i); firstcg = start_blocks; end_blocks = cg_align; cgblocks = fs_blocks - (start_blocks + end_blocks); iblocks = (fs_isize + EFS_INOPBB - 1) / EFS_INOPBB; /* * If file system is itty bitty, handle it specially */ if (short_form && fs_blocks < 2 * good_cg_size(cgblocks, iblocks, cg_align)) { is_ittybitty = 1; ncg = 1; firstcg = start_blocks = 2 + bitmap_blocks; end_blocks = 1; cg_fsize = fs_blocks - (start_blocks + end_blocks); cg_align = i_align = 1; if (cg_fsize <= 0) { fprintf(stderr, "%s: not enough space to make filesystem\n", progname); exit(-1); } cg_isize = (fs_isize + EFS_INOPBB - 1) / EFS_INOPBB; if (cg_isize >= cg_fsize) { fprintf(stderr, "%s: invalid filesystem size - inodes larger than partition\n", progname); exit(-1); } buildfs(); exit(0); } /* * If size of cylinder groups not yet specified, compute a good * size to efficiently fit the available space. * Compute number of cylinder groups and blocks of inodes per cylinder * group. */ if (!cg_fsize) { if (cyl_align) cgsizepick(cgblocks, iblocks, cg_align, &ncg, &cg_fsize, &cg_isize); else { cg_fsize = good_cg_size(cgblocks, iblocks, cg_align); ncg = cgblocks / cg_fsize; cg_fsize = cgblocks / ncg; cg_isize = cg_fsize / (cgblocks / iblocks); } } else { /* round cg_fsize down to a cg_align multiple. Sanity check: * if given cg_fsize is < align, complain & exit */ if (cg_fsize < cg_align) { fprintf(stderr, "%s: invalid cgsize - smaller than specified alignment.\n", progname); exit(-1); } cg_fsize -= cg_fsize % cg_align; if (cg_fsize > cgblocks) { fprintf(stderr, "%s: invalid cgsize - larger than available space.\n", progname); exit(-1); } ncg = cgblocks / cg_fsize; /* Now the inode computations: * Adjust cg_isize to be a multiple of i_align. Round up or * down, whichever is closest, unless this would make it zero! */ cg_isize = (iblocks + ncg - 1) / ncg; if (i = (cg_isize % i_align)) { if (cg_isize < i_align) cg_isize = i_align; else if (i < (i_align / 2)) cg_isize -= i; else cg_isize += (i_align - i); } } if (cg_isize >= cg_fsize) { fprintf(stderr, "%s: Ridiculous number of inodes; no space for data.\n", progname); exit(-1); } fs_isize = cg_isize * ncg * EFS_INOPBB; buildfs(); fprintf(stderr, "%s: SUCCESSFUL COMPLETION\n", progname); exit(0);} /* * Get info about device size & geometry. */getdevinfo(){ int heads; int add_inodes = 0; if ((dev_blocks = findsize(special)) <= 0) { fprintf(stderr,"Can't determine size of %s\n", special); blather(); exit(-1); } fs_blocks = dev_blocks; /* by default, use whole device */ if ((fs_sectors = findtrksize(special)) <= 0) { fprintf(stderr,"Can't determine tracksize of %s\n", special); blather(); exit(-1); } if ((heads = findnumhead(special)) <= 0) { fprintf(stderr,"Can't get number of heads on %s\n", special); blather(); exit(-1); } fs_isize = GOOD_INODE_TOTAL(fs_blocks); /* * On root partitions > 16MB, add 512 inodes for each additional MB. */ if (is_rootpart(special)) { add_inodes = (fs_blocks - 0x8000) / 4; if (add_inodes < 0) add_inodes = 0; if (add_inodes > 4096) add_inodes = 4096; } fs_isize += add_inodes; if (user_inodes) { if (user_inodes < fs_isize) fprintf(stderr,"Warning: specified number of inodes %d is smaller than normal default %d\n", user_inodes, fs_isize); fs_isize = user_inodes; } if (cyl_align) { cg_align = fs_sectors * heads; i_align = fs_sectors * heads; } else { cg_align = 1; i_align = 1; }}blather(){ fprintf(stderr,"Check that device exists and is writeable.\n"); fprintf(stderr,"(Note that it is possible for a special file\n"); fprintf(stderr,"to exist and have writeable permissions, but\n"); fprintf(stderr,"for there to be no real device corresponding\n"); fprintf(stderr,"to it).\n");}/* * cgsizepick() chooses cylinder group size, inodes per cylinder group, * and number of cylinder groups for a filesystem. It holds inodes per * cylinder group to a constant and varies the data blocks per cylinder * group by up to 20 percent either way, looking for the least amount * of space wastage. This algorithm is optimized for large align values. */voidcgsizepick(blocks, iblocks, align, addr_ncg, addr_cg_fsize, addr_cg_isize)int blocks, iblocks, align;long *addr_ncg, *addr_cg_fsize, *addr_cg_isize;{ int cgs, cguess, i, waste; int savecgs, savecgsize, savecgisize; int prevwaste = blocks; int mincgsize, mult; mult = (blocks + iblocks - 1) / iblocks;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -