]> Zhao Yanbai Git Server - minix.git/commitdiff
mkfs.mfs -I: insert fs at offset feature 25/1125/7
authorBen Gras <ben@minix3.org>
Thu, 7 Nov 2013 07:33:39 +0000 (08:33 +0100)
committerBen Gras <ben@minix3.org>
Fri, 8 Nov 2013 11:59:47 +0000 (11:59 +0000)
. use it in x86_hdimage.sh:
  avoid copying big FS images into iso & hd images each time

Change-Id: I0775f43cd1821ea7be2fec5b96d107a68afb96d6

releasetools/x86_hdimage.sh
usr.sbin/mkfs.mfs/mkfs.c
usr.sbin/mkfs.mfs/v3/mkfs.mfs.1

index 869bb06448cd830758d3ef6481a2dca2ea8ad031..4fb10a7a00f96501043e31a45fc7011535efea65 100755 (executable)
@@ -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" ]
index d732b4eac45c866b6e97df0d93c31e1f409e8f27..b5256cb9824167b5d6cbbae6c444980601049c2a 100644 (file)
@@ -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
 }
index 646c420f9e29649023ff27a5ea067e5ca2da7de2..f939708441620308c388d173bcd11f61b97df7f7 100644 (file)
@@ -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