From 8dbe32610b61afe7da53a09627e7e1d99e8d21df Mon Sep 17 00:00:00 2001 From: Ben Gras Date: Thu, 7 Nov 2013 08:33:39 +0100 Subject: [PATCH] mkfs.mfs -I: insert fs at offset feature . use it in x86_hdimage.sh: avoid copying big FS images into iso & hd images each time Change-Id: I0775f43cd1821ea7be2fec5b96d107a68afb96d6 --- releasetools/x86_hdimage.sh | 98 ++++++++++--------------- usr.sbin/mkfs.mfs/mkfs.c | 122 +++++++++++++++++++++----------- usr.sbin/mkfs.mfs/v3/mkfs.mfs.1 | 5 +- 3 files changed, 121 insertions(+), 104 deletions(-) diff --git a/releasetools/x86_hdimage.sh b/releasetools/x86_hdimage.sh index 869bb0644..4fb10a7a0 100755 --- a/releasetools/x86_hdimage.sh +++ b/releasetools/x86_hdimage.sh @@ -28,12 +28,6 @@ fi export PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:$PATH -# -# Artifacts from this script are stored in the IMG_DIR -# -rm -rf $IMG_DIR $IMG -mkdir -p $IMG_DIR $CDFILES - while getopts "i" c do case "$c" in @@ -45,6 +39,12 @@ done : ${IMG=minix_x86.img} +# +# Artifacts from this script are stored in the IMG_DIR +# +rm -rf $IMG_DIR $IMG +mkdir -p $IMG_DIR $CDFILES + # # Call build.sh using a sloppy file list so we don't need to remove the installed /etc/fstag # @@ -56,24 +56,13 @@ then cp ${DESTDIR}/usr/mdec/boot_monitor $CDFILES/boot cp ${MODDIR}/* $CDFILES/ . ./releasetools/release.functions cd_root_changes # uses $CDFILES and writes $CDFILES/boot.cfg - ${CROSS_TOOLS}/nbwriteisofs -s0x0 -l MINIX -B ${DESTDIR}/usr/mdec/bootxx_cd9660 -n $CDFILES ${IMG_DIR}/iso.img - ISO_SIZE=$((`stat -c %s ${IMG_DIR}/iso.img` / 512)) + # start the image off with the iso image; reduce root size to reserve + ${CROSS_TOOLS}/nbwriteisofs -s0x0 -l MINIX -B ${DESTDIR}/usr/mdec/bootxx_cd9660 -n $CDFILES $IMG + ISO_SIZE=$((`stat -c %s $IMG` / 512)) else # just make an empty iso partition ISO_SIZE=8 fi -# This script creates a bootable image and should at some point in the future -# be replaced by makefs. -# -# All sized are written in 512 byte blocks -# -# we create a disk image of about 2 gig's -# for alignment reasons, prefer sizes which are multiples of 4096 bytes -# -: ${ROOT_SIZE=$(( 64*(2**20) / 512))} -: ${HOME_SIZE=$(( 128*(2**20) / 512))} -: ${USR_SIZE=$((1536*(2**20) / 512))} - # # create a fstab entry in /etc this is normally done during the # setup phase on x86 @@ -87,15 +76,6 @@ rm -f ${DESTDIR}/SETS.* ${CROSS_TOOLS}/nbpwd_mkdb -V 0 -p -d ${DESTDIR} ${DESTDIR}/etc/master.passwd -# -# Now given the sizes above use DD to create separate files representing -# the partitions we are going to use. -# -dd if=/dev/zero of=${IMG_DIR}/iso.img bs=512 count=1 seek=$(($ISO_SIZE -1)) 2>/dev/null -dd if=/dev/zero of=${IMG_DIR}/root.img bs=512 count=1 seek=$(($ROOT_SIZE -1)) 2>/dev/null -dd if=/dev/zero of=${IMG_DIR}/home.img bs=512 count=1 seek=$(($HOME_SIZE -1)) 2>/dev/null -dd if=/dev/zero of=${IMG_DIR}/usr.img bs=512 count=1 seek=$(($USR_SIZE -1)) 2>/dev/null - # make the different file system. this part is *also* hacky. We first convert # the METALOG.sanitised using mtree into a input METALOG containing uids and # gids. @@ -133,54 +113,48 @@ rm ${IMG_DIR}/root.in cat ${IMG_DIR}/input | grep "^\./usr/\|^. " | sed "s,\./usr,\.,g" | ${CROSS_TOOLS}/nbtoproto -b ${DESTDIR}/usr -o ${IMG_DIR}/usr.proto cat ${IMG_DIR}/input | grep "^\./home/\|^. " | sed "s,\./home,\.,g" | ${CROSS_TOOLS}/nbtoproto -b ${DESTDIR}/home -o ${IMG_DIR}/home.proto -# If in ISO mode, fit the FSes +# This script creates a bootable image and should at some point in the future +# be replaced by makefs. +# +# All sized are written in 512 byte blocks +# +# we create a disk image of about 2 gig's +# for alignment reasons, prefer sizes which are multiples of 4096 bytes +# +: ${ROOT_SIZE=$(( 64*(2**20) / 512))} +: ${HOME_SIZE=$(( 128*(2**20) / 512))} +: ${USR_SIZE=$(( 1536*(2**20) / 512))} + if [ "$ISOMODE" ] -then ROOTSIZEARG="-x 5" # give root fs a little breathing room on the CD -else # give args with the right sizes +then + # In iso mode, make all FSes fit (i.e. as small as possible), but + # leave some space on / + ROOTSIZEARG="-x 5" +else + # In hd image mode, FSes have fixed sizes ROOTSIZEARG="-b $((${ROOT_SIZE} / 8))" USRSIZEARG="-b $((${USR_SIZE} / 8))" HOMESIZEARG="-b $((${HOME_SIZE} / 8))" fi -# -# Generate /root, /usr and /home partition images. -# echo "Writing Minix filesystem images" -echo " - ROOT" -${CROSS_TOOLS}/nbmkfs.mfs $ROOTSIZEARG ${IMG_DIR}/root.img ${IMG_DIR}/root.proto -echo " - USR" -${CROSS_TOOLS}/nbmkfs.mfs $USRSIZEARG ${IMG_DIR}/usr.img ${IMG_DIR}/usr.proto -echo " - HOME" -${CROSS_TOOLS}/nbmkfs.mfs $HOMESIZEARG ${IMG_DIR}/home.img ${IMG_DIR}/home.proto - -# Set the sizes based on what was just generated - should change nothing if sizes -# were specified -echo "$ROOT_SIZE $USR_SIZE $HOME_SIZE" -ROOT_SIZE=$((`stat -c %s ${IMG_DIR}/root.img` / 512)) -USR_SIZE=$((`stat -c %s ${IMG_DIR}/usr.img` / 512)) -HOME_SIZE=$((`stat -c %s ${IMG_DIR}/home.img` / 512)) -echo "$ROOT_SIZE $USR_SIZE $HOME_SIZE" # Do some math to determine the start addresses of the partitions. # Ensure the start of the partitions are always aligned, the end will # always be as we assume the sizes are multiples of 4096 bytes, which # is always true as soon as you have an integer multiple of 1MB. -# -ISO_START=0 -ROOT_START=$(($ISO_START + $ISO_SIZE)) +ROOT_START=$ISO_SIZE + +echo " - ROOT" +ROOT_SIZE=$((`${CROSS_TOOLS}/nbmkfs.mfs -d $ROOTSIZEARG -I $(($ROOT_START*512)) $IMG ${IMG_DIR}/root.proto`/512)) USR_START=$(($ROOT_START + $ROOT_SIZE)) +echo " - USR" +USR_SIZE=$((`${CROSS_TOOLS}/nbmkfs.mfs -d $USRSIZEARG -I $(($USR_START*512)) $IMG ${IMG_DIR}/usr.proto`/512)) HOME_START=$(($USR_START + $USR_SIZE)) +echo " - HOME" +HOME_SIZE=$((`${CROSS_TOOLS}/nbmkfs.mfs -d $HOMESIZEARG -I $(($HOME_START*512)) $IMG ${IMG_DIR}/home.proto`/512)) -# -# Merge the partitions into a single image. -# -echo "Merging file systems" -dd if=${IMG_DIR}/iso.img of=${IMG} seek=$ISO_START conv=notrunc -dd if=${IMG_DIR}/root.img of=${IMG} seek=$ROOT_START conv=notrunc -dd if=${IMG_DIR}/usr.img of=${IMG} seek=$USR_START conv=notrunc -dd if=${IMG_DIR}/home.img of=${IMG} seek=$HOME_START conv=notrunc - -${CROSS_TOOLS}/nbpartition -m ${IMG} ${ISO_START} 81:${ISO_SIZE} 81:${ROOT_SIZE} 81:${USR_SIZE} 81:${HOME_SIZE} +${CROSS_TOOLS}/nbpartition -m ${IMG} 0 81:${ISO_SIZE} 81:${ROOT_SIZE} 81:${USR_SIZE} 81:${HOME_SIZE} mods="`( cd $MODDIR; echo mod* | tr ' ' ',' )`" if [ "$ISOMODE" ] diff --git a/usr.sbin/mkfs.mfs/mkfs.c b/usr.sbin/mkfs.mfs/mkfs.c index d732b4eac..b5256cb98 100644 --- a/usr.sbin/mkfs.mfs/mkfs.c +++ b/usr.sbin/mkfs.mfs/mkfs.c @@ -52,7 +52,6 @@ #if !defined(__minix) #define mul64u(a,b) ((uint64_t)(a) * (b)) -#define lseek64(a,b,c,d) lseek(a,b,c) #endif /* some Minix specific types that do not conflict with Posix */ @@ -88,6 +87,7 @@ int lct = 0, fd, print = 0; int simple = 0, dflag = 0, verbose = 0; int donttest; /* skip test if it fits on medium */ char *progname; +uint64_t fs_offset_bytes, fs_offset_blocks, written_fs_size = 0; time_t current_time; char *zero; @@ -128,11 +128,13 @@ __dead void pexit(char const *s, ...) __printflike(1,2); void *alloc_block(void); void print_fs(void); int read_and_set(block_t n); -void special(char *string); +void special(char *string, int insertmode); __dead void usage(void); void get_block(block_t n, void *buf); void get_super_block(void *buf); void put_block(block_t n, void *buf); +static uint64_t mkfs_seek(uint64_t pos, int whence); +static ssize_t mkfs_write(void * buf, size_t count); /*================================================================ * mkfs - make filesystem @@ -145,6 +147,7 @@ main(int argc, char *argv[]) ino_t inodes, root_inum; char *token[MAX_TOKENS], line[LINE_LEN], *sfx; struct fs_size fssize; + int insertmode = 0; progname = argv[0]; @@ -157,7 +160,7 @@ main(int argc, char *argv[]) #endif zone_shift = 0; extra_space_percent = 0; - while ((ch = getopt(argc, argv, "B:b:di:ltvx:z:")) != EOF) + while ((ch = getopt(argc, argv, "B:b:di:ltvx:z:I:")) != EOF) switch (ch) { #ifndef MFS_STATIC_BLOCK_SIZE case 'B': @@ -179,6 +182,10 @@ main(int argc, char *argv[]) break; (void)sfx; /* shut up warnings about unused variable...*/ #endif + case 'I': + fs_offset_bytes = strtoul(optarg, (char **) NULL, 0); + insertmode = 1; + break; case 'b': blocks = bblocks = strtoul(optarg, (char **) NULL, 0); break; @@ -253,9 +260,11 @@ main(int argc, char *argv[]) */ zero = alloc_block(); + fs_offset_blocks = roundup(fs_offset_bytes, block_size) / block_size; + /* Determine the size of the device if not specified as -b or proto. */ maxblocks = sizeup(argv[optind]); - if (bblocks != 0 && bblocks > maxblocks){ + if (bblocks != 0 && bblocks + fs_offset_blocks > maxblocks && !insertmode) { errx(4, "Given size -b %d exeeds device capacity(%d)\n", bblocks, maxblocks); } @@ -274,7 +283,7 @@ main(int argc, char *argv[]) */ if (argc - optind != 2 && (argc - optind != 1 || blocks == 0)) usage(); - if (maxblocks && blocks > maxblocks) { + if (maxblocks && blocks > maxblocks && !insertmode) { errx(1, "%s: number of blocks too large for device.", argv[optind]); } @@ -315,7 +324,7 @@ main(int argc, char *argv[]) blocks += blocks*extra_space_percent/100; inodes += inodes*extra_space_percent/100; /* XXX is it OK to write on stdout? Use warn() instead? Also consider using verbose */ - printf("dynamically sized filesystem: %u blocks, %u inodes\n", + fprintf(stderr, "dynamically sized filesystem: %u blocks, %u inodes\n", (unsigned int) blocks, (unsigned int) inodes); } } else { @@ -362,7 +371,7 @@ main(int argc, char *argv[]) (unsigned)umap_array_elements); /* Open special. */ - special(argv[--optind]); + special(argv[--optind], insertmode); if (!donttest) { uint16_t *testb; @@ -371,19 +380,13 @@ main(int argc, char *argv[]) testb = alloc_block(); /* Try writing the last block of partition or diskette. */ - if(lseek64(fd, mul64u(blocks - 1, block_size), SEEK_SET, NULL) < 0) { - err(1, "couldn't seek to last block to test size (1)"); - } + mkfs_seek(mul64u(blocks - 1, block_size), SEEK_SET); testb[0] = 0x3245; testb[1] = 0x11FF; testb[block_size/2-1] = 0x1F2F; - if ((w=write(fd, testb, block_size)) != block_size) - err(1, "File system is too big for minor device (write1 %d/%u)", - w, block_size); + w=mkfs_write(testb, block_size); sync(); /* flush write, so if error next read fails */ - if(lseek64(fd, mul64u(blocks - 1, block_size), SEEK_SET, NULL) < 0) { - err(1, "couldn't seek to last block to test size (2)"); - } + mkfs_seek(mul64u(blocks - 1, block_size), SEEK_SET); testb[0] = 0; testb[1] = 0; testb[block_size/2-1] = 0; @@ -395,13 +398,12 @@ main(int argc, char *argv[]) testb[0], testb[1], testb[block_size-1]); errx(1, "File system is too big for minor device (read)"); } - lseek64(fd, mul64u(blocks - 1, block_size), SEEK_SET, NULL); + mkfs_seek(mul64u(blocks - 1, block_size), SEEK_SET); testb[0] = 0; testb[1] = 0; testb[block_size/2-1] = 0; - if (write(fd, testb, block_size) != block_size) - err(1, "File system is too big for minor device (write2)"); - lseek(fd, 0L, SEEK_SET); + mkfs_write(testb, block_size); + mkfs_seek(0L, SEEK_SET); free(testb); } @@ -426,6 +428,8 @@ main(int argc, char *argv[]) (int)next_inode-1, next_zone); } + if(insertmode) printf("%ld\n", written_fs_size); + return(0); /* NOTREACHED */ @@ -560,9 +564,7 @@ sizeup(char * device) progname, (unsigned long)d); } #else - size = lseek(fd, 0, SEEK_END); - if (size == (off_t) -1) - err(1, "cannot get device size fd=%d: %s", fd, device); + size = mkfs_seek(0, SEEK_END); /* Assume block_t is unsigned */ if (size / block_size > (block_t)(-1ul)) { d = (block_t)(-1ul); @@ -691,10 +693,8 @@ super(zone_t zones, ino_t inodes) #endif } - if (lseek(fd, (off_t) SUPER_BLOCK_BYTES, SEEK_SET) == (off_t) -1) - err(1, "super() couldn't seek"); - if (write(fd, buf, SUPER_BLOCK_BYTES) != SUPER_BLOCK_BYTES) - err(1, "super() couldn't write"); + mkfs_seek((off_t) SUPER_BLOCK_BYTES, SEEK_SET); + mkfs_write(buf, SUPER_BLOCK_BYTES); /* Clear maps and inodes. */ for (i = START_BLOCK; i < initblks; i++) put_block((block_t) i, zero); @@ -1541,19 +1541,20 @@ read_and_set(block_t n) __dead void usage(void) { - fprintf(stderr, "Usage: %s [-dltv] [-b blocks] [-i inodes] [-z zone_shift]\n" - "\t[-x extra] [-B blocksize] special [proto]\n", + fprintf(stderr, "Usage: %s [-dltv] [-b blocks] [-i inodes]\n" + "\t[-z zone_shift] [-I offset] [-x extra] [-B blocksize] special [proto]\n", progname); exit(4); } void -special(char * string) +special(char * string, int insertmode) { - fd = creat(string, 0777); - close(fd); - fd = open(string, O_RDWR); + int openmode = O_RDWR; + if(!insertmode) openmode |= O_TRUNC; + fd = open(string, O_RDWR | O_CREAT, 0644); if (fd < 0) err(1, "Can't open special file %s", string); + mkfs_seek(0, SEEK_SET); } @@ -1569,8 +1570,7 @@ get_block(block_t n, void *buf) memcpy(buf, zero, block_size); return; } - if (lseek64(fd, mul64u(n, block_size), SEEK_SET, NULL) == (off_t)(-1)) - pexit("get_block couldn't seek"); + mkfs_seek(mul64u(n, block_size), SEEK_SET); k = read(fd, buf, block_size); if (k != block_size) pexit("get_block couldn't read block #%u", (unsigned)n); @@ -1582,8 +1582,7 @@ get_super_block(void *buf) { ssize_t k; - if(lseek(fd, (off_t) SUPER_BLOCK_BYTES, SEEK_SET) == (off_t) -1) - err(1, "seek for superblock failed"); + mkfs_seek((off_t) SUPER_BLOCK_BYTES, SEEK_SET); k = read(fd, buf, SUPER_BLOCK_BYTES); if (k != SUPER_BLOCK_BYTES) err(1, "get_super_block couldn't read super block"); @@ -1596,8 +1595,49 @@ put_block(block_t n, void *buf) (void) read_and_set(n); - if (lseek64(fd, mul64u(n, block_size), SEEK_SET, NULL) == (off_t) -1) - pexit("put_block couldn't seek"); - if (write(fd, buf, block_size)!= block_size) - pexit("put_block couldn't write block #%u", (unsigned)n); + mkfs_seek(mul64u(n, block_size), SEEK_SET); + mkfs_write(buf, block_size); +} + +static ssize_t +mkfs_write(void * buf, size_t count) +{ + uint64_t fssize; + ssize_t w; + + /* Perform & check write */ + w = write(fd, buf, count); + if(w < 0) + err(1, "mkfs_write: write failed"); + if(w != count) + errx(1, "mkfs_write: short write: %ld != %ld", w, count); + + /* Check if this has made the FS any bigger; count bytes after offset */ + fssize = mkfs_seek(0, SEEK_CUR); + + assert(fssize >= fs_offset_bytes); + fssize -= fs_offset_bytes; + fssize = roundup(fssize, block_size); + if(fssize > written_fs_size) + written_fs_size = fssize; + + return w; +} + +/* Seek to position in FS we're creating. */ +static uint64_t +mkfs_seek(uint64_t pos, int whence) +{ + if(whence == SEEK_SET) pos += fs_offset_bytes; +#ifdef __minix + uint64_t newpos; + if((lseek64(fd, pos, whence, &newpos)) < 0) + err(1, "mkfs_seek: lseek64 failed"); + return newpos; +#else + off_t newpos; + if((newpos=lseek(fd, pos, whence)) == (off_t) -1) + err(1, "mkfs_seek: lseek failed"); + return newpos; +#endif } diff --git a/usr.sbin/mkfs.mfs/v3/mkfs.mfs.1 b/usr.sbin/mkfs.mfs/v3/mkfs.mfs.1 index 646c420f9..f93970844 100644 --- a/usr.sbin/mkfs.mfs/v3/mkfs.mfs.1 +++ b/usr.sbin/mkfs.mfs/v3/mkfs.mfs.1 @@ -12,6 +12,7 @@ .Op Fl b Ar blocks .Op Fl z Ar zone_shift .Op Fl x Ar extra_space +.Op Fl I Ar fs_offset .Ar special .Op Ar prototype .Sh OPTIONS @@ -35,6 +36,8 @@ Number of i-nodes (files) Filesystem block size (in bytes) .It Fl b Ar blocks Filesystem size (in blocks) +.It Fl I Ar fs_offset +Write filesystem starting at offset (in bytes) .It Fl x Ar extra_space Extra space after dynamic sizing (blocks and inodes) .It Fl z Ar zone_shift @@ -118,4 +121,4 @@ For special files, the major and minor devices are needed. The .Nm utility was written by -.An Andy Tanenbaum, Paul Ogilvie, Frans Meulenbroeks, Bruce Evans \ No newline at end of file +.An Andy Tanenbaum, Paul Ogilvie, Frans Meulenbroeks, Bruce Evans -- 2.44.0