From owner-svn-src-user@FreeBSD.ORG Sun Sep 28 00:20:12 2014 Return-Path: <owner-svn-src-user@FreeBSD.ORG> Delivered-To: svn-src-user@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 91E91358; Sun, 28 Sep 2014 00:20:12 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 7D47061B; Sun, 28 Sep 2014 00:20:12 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id s8S0KCJc069055; Sun, 28 Sep 2014 00:20:12 GMT (envelope-from marcel@FreeBSD.org) Received: (from marcel@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id s8S0K8lH069033; Sun, 28 Sep 2014 00:20:08 GMT (envelope-from marcel@FreeBSD.org) Message-Id: <201409280020.s8S0K8lH069033@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: marcel set sender to marcel@FreeBSD.org using -f From: Marcel Moolenaar <marcel@FreeBSD.org> Date: Sun, 28 Sep 2014 00:20:08 +0000 (UTC) To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r272231 - in user/marcel/mkimg: . tests X-SVN-Group: user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-user@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: "SVN commit messages for the experimental " user" src tree" <svn-src-user.freebsd.org> List-Unsubscribe: <http://lists.freebsd.org/mailman/options/svn-src-user>, <mailto:svn-src-user-request@freebsd.org?subject=unsubscribe> List-Archive: <http://lists.freebsd.org/pipermail/svn-src-user/> List-Post: <mailto:svn-src-user@freebsd.org> List-Help: <mailto:svn-src-user-request@freebsd.org?subject=help> List-Subscribe: <http://lists.freebsd.org/mailman/listinfo/svn-src-user>, <mailto:svn-src-user-request@freebsd.org?subject=subscribe> X-List-Received-Date: Sun, 28 Sep 2014 00:20:12 -0000 Author: marcel Date: Sun Sep 28 00:20:08 2014 New Revision: 272231 URL: http://svnweb.freebsd.org/changeset/base/272231 Log: Sync with ^head/usr.bin/mkimg@272217 Added: user/marcel/mkimg/qcow.c - copied unchanged from r272230, head/usr.bin/mkimg/qcow.c user/marcel/mkimg/tests/ - copied from r272230, head/usr.bin/mkimg/tests/ Modified: user/marcel/mkimg/Makefile user/marcel/mkimg/apm.c user/marcel/mkimg/bsd.c user/marcel/mkimg/ebr.c user/marcel/mkimg/gpt.c user/marcel/mkimg/image.c user/marcel/mkimg/image.h user/marcel/mkimg/mbr.c user/marcel/mkimg/mkimg.1 user/marcel/mkimg/mkimg.c user/marcel/mkimg/mkimg.h user/marcel/mkimg/pc98.c user/marcel/mkimg/scheme.c user/marcel/mkimg/scheme.h user/marcel/mkimg/vhd.c user/marcel/mkimg/vmdk.c user/marcel/mkimg/vtoc8.c Directory Properties: user/marcel/mkimg/ (props changed) Modified: user/marcel/mkimg/Makefile ============================================================================== --- user/marcel/mkimg/Makefile Sat Sep 27 23:57:21 2014 (r272230) +++ user/marcel/mkimg/Makefile Sun Sep 28 00:20:08 2014 (r272231) @@ -1,13 +1,18 @@ # $FreeBSD$ +.include <src.opts.mk> + PROG= mkimg SRCS= format.c image.c mkimg.c scheme.c MAN= mkimg.1 +MKIMG_VERSION=20140927 +CFLAGS+=-DMKIMG_VERSION=${MKIMG_VERSION} CFLAGS+=-DSPARSE_WRITE # List of formats to support SRCS+= \ + qcow.c \ raw.c \ vhd.c \ vmdk.c @@ -29,4 +34,8 @@ LDADD= -lutil WARNS?= 6 +.if ${MK_TESTS} != "no" +SUBDIR+= tests +.endif + .include <bsd.prog.mk> Modified: user/marcel/mkimg/apm.c ============================================================================== --- user/marcel/mkimg/apm.c Sat Sep 27 23:57:21 2014 (r272230) +++ user/marcel/mkimg/apm.c Sun Sep 28 00:20:08 2014 (r272231) @@ -39,6 +39,9 @@ __FBSDID("$FreeBSD$"); #include "mkimg.h" #include "scheme.h" +#ifndef APM_ENT_TYPE_APPLE_BOOT +#define APM_ENT_TYPE_APPLE_BOOT "Apple_Bootstrap" +#endif #ifndef APM_ENT_TYPE_FREEBSD_NANDFS #define APM_ENT_TYPE_FREEBSD_NANDFS "FreeBSD-nandfs" #endif @@ -54,13 +57,12 @@ static struct mkimg_alias apm_aliases[] { ALIAS_NONE, 0 } }; -static u_int -apm_metadata(u_int where) +static lba_t +apm_metadata(u_int where, lba_t blk) { - u_int secs; - secs = (where == SCHEME_META_IMG_START) ? nparts + 2 : 0; - return (secs); + blk += (where == SCHEME_META_IMG_START) ? nparts + 2 : 0; + return (round_block(blk)); } static int Modified: user/marcel/mkimg/bsd.c ============================================================================== --- user/marcel/mkimg/bsd.c Sat Sep 27 23:57:21 2014 (r272230) +++ user/marcel/mkimg/bsd.c Sun Sep 28 00:20:08 2014 (r272231) @@ -52,13 +52,17 @@ static struct mkimg_alias bsd_aliases[] { ALIAS_NONE, 0 } }; -static u_int -bsd_metadata(u_int where) +static lba_t +bsd_metadata(u_int where, lba_t blk) { - u_int secs; - secs = BBSIZE / secsz; - return ((where == SCHEME_META_IMG_START) ? secs : 0); + if (where == SCHEME_META_IMG_START) + blk += BBSIZE / secsz; + else if (where == SCHEME_META_IMG_END) + blk = round_cylinder(blk); + else + blk = round_block(blk); + return (blk); } static int @@ -68,7 +72,7 @@ bsd_write(lba_t imgsz, void *bootcode) struct disklabel *d; struct partition *dp; struct part *part; - int error, n; + int bsdparts, error, n; uint16_t checksum; buf = malloc(BBSIZE); @@ -76,16 +80,13 @@ bsd_write(lba_t imgsz, void *bootcode) return (ENOMEM); if (bootcode != NULL) { memcpy(buf, bootcode, BBSIZE); - memset(buf + secsz, 0, secsz); + memset(buf + secsz, 0, sizeof(struct disklabel)); } else memset(buf, 0, BBSIZE); - imgsz = (lba_t)ncyls * nheads * nsecs; - error = image_set_size(imgsz); - if (error) { - free(buf); - return (error); - } + bsdparts = nparts + 1; /* Account for c partition */ + if (bsdparts < MAXPARTITIONS) + bsdparts = MAXPARTITIONS; d = (void *)(buf + secsz); le32enc(&d->d_magic, DISKMAGIC); @@ -97,7 +98,7 @@ bsd_write(lba_t imgsz, void *bootcode) le32enc(&d->d_secperunit, imgsz); le16enc(&d->d_rpm, 3600); le32enc(&d->d_magic2, DISKMAGIC); - le16enc(&d->d_npartitions, (8 > nparts + 1) ? 8 : nparts + 1); + le16enc(&d->d_npartitions, bsdparts); le32enc(&d->d_bbsize, BBSIZE); dp = &d->d_partitions[RAW_PART]; @@ -107,12 +108,15 @@ bsd_write(lba_t imgsz, void *bootcode) dp = &d->d_partitions[n]; le32enc(&dp->p_size, part->size); le32enc(&dp->p_offset, part->block); + le32enc(&dp->p_fsize, 0); dp->p_fstype = ALIAS_TYPE2INT(part->type); + dp->p_frag = 0; + le16enc(&dp->p_cpg, 0); } - dp = &d->d_partitions[nparts + 1]; + dp = &d->d_partitions[bsdparts]; checksum = 0; - for (p = buf; p < (u_char *)dp; p += 2) + for (p = (void *)d; p < (u_char *)dp; p += 2) checksum ^= le16dec(p); le16enc(&d->d_checksum, checksum); Modified: user/marcel/mkimg/ebr.c ============================================================================== --- user/marcel/mkimg/ebr.c Sat Sep 27 23:57:21 2014 (r272230) +++ user/marcel/mkimg/ebr.c Sun Sep 28 00:20:08 2014 (r272231) @@ -49,13 +49,12 @@ static struct mkimg_alias ebr_aliases[] { ALIAS_NONE, 0 } }; -static u_int -ebr_metadata(u_int where) +static lba_t +ebr_metadata(u_int where, lba_t blk) { - u_int secs; - secs = (where == SCHEME_META_PART_BEFORE) ? nsecs : 0; - return (secs); + blk += (where == SCHEME_META_PART_BEFORE) ? 1 : 0; + return (round_track(blk)); } static void Modified: user/marcel/mkimg/gpt.c ============================================================================== --- user/marcel/mkimg/gpt.c Sat Sep 27 23:57:21 2014 (r272230) +++ user/marcel/mkimg/gpt.c Sun Sep 28 00:20:08 2014 (r272231) @@ -153,17 +153,15 @@ gpt_tblsz(void) return ((nparts + ents - 1) / ents); } -static u_int -gpt_metadata(u_int where) +static lba_t +gpt_metadata(u_int where, lba_t blk) { - u_int secs; - if (where != SCHEME_META_IMG_START && where != SCHEME_META_IMG_END) - return (0); - - secs = gpt_tblsz(); - secs += (where == SCHEME_META_IMG_START) ? 2 : 1; - return (secs); + if (where == SCHEME_META_IMG_START || where == SCHEME_META_IMG_END) { + blk += gpt_tblsz(); + blk += (where == SCHEME_META_IMG_START) ? 2 : 1; + } + return (round_block(blk)); } static int Modified: user/marcel/mkimg/image.c ============================================================================== --- user/marcel/mkimg/image.c Sat Sep 27 23:57:21 2014 (r272230) +++ user/marcel/mkimg/image.c Sun Sep 28 00:20:08 2014 (r272231) @@ -94,12 +94,19 @@ image_copyin(lba_t blk, int fd, uint64_t int image_copyout(int fd) { - off_t ofs; int error; error = image_copyout_region(fd, 0, image_size); - if (error) - return (error); + if (!error) + error = image_copyout_done(fd); + return (error); +} + +int +image_copyout_done(int fd) +{ + off_t ofs; + int error; ofs = lseek(fd, 0L, SEEK_CUR); if (ofs == -1) @@ -148,6 +155,33 @@ image_copyout_region(int fd, lba_t blk, return (error); } +int +image_data(lba_t blk, lba_t size) +{ + char *buffer, *p; + + blk *= secsz; + if (lseek(image_fd, blk, SEEK_SET) != blk) + return (1); + + size *= secsz; + buffer = malloc(size); + if (buffer == NULL) + return (1); + + if (read(image_fd, buffer, size) != (ssize_t)size) { + free(buffer); + return (1); + } + + p = buffer; + while (size > 0 && *p == '\0') + size--, p++; + + free(buffer); + return ((size == 0) ? 0 : 1); +} + lba_t image_get_size(void) { Modified: user/marcel/mkimg/image.h ============================================================================== --- user/marcel/mkimg/image.h Sat Sep 27 23:57:21 2014 (r272230) +++ user/marcel/mkimg/image.h Sun Sep 28 00:20:08 2014 (r272231) @@ -33,7 +33,9 @@ typedef int64_t lba_t; int image_copyin(lba_t blk, int fd, uint64_t *sizep); int image_copyout(int fd); +int image_copyout_done(int fd); int image_copyout_region(int fd, lba_t blk, lba_t size); +int image_data(lba_t blk, lba_t size); lba_t image_get_size(void); int image_init(void); int image_set_size(lba_t blk); Modified: user/marcel/mkimg/mbr.c ============================================================================== --- user/marcel/mkimg/mbr.c Sat Sep 27 23:57:21 2014 (r272230) +++ user/marcel/mkimg/mbr.c Sun Sep 28 00:20:08 2014 (r272231) @@ -50,13 +50,12 @@ static struct mkimg_alias mbr_aliases[] { ALIAS_NONE, 0 } /* Keep last! */ }; -static u_int -mbr_metadata(u_int where) +static lba_t +mbr_metadata(u_int where, lba_t blk) { - u_int secs; - secs = (where == SCHEME_META_IMG_START) ? nsecs : 0; - return (secs); + blk += (where == SCHEME_META_IMG_START) ? 1 : 0; + return (round_track(blk)); } static void Modified: user/marcel/mkimg/mkimg.1 ============================================================================== --- user/marcel/mkimg/mkimg.1 Sat Sep 27 23:57:21 2014 (r272230) +++ user/marcel/mkimg/mkimg.1 Sun Sep 28 00:20:08 2014 (r272231) @@ -24,12 +24,12 @@ .\" .\" $FreeBSD$ .\" -.Dd July 2, 2014 +.Dd September 27, 2014 .Dt MKIMG 1 .Os .Sh NAME .Nm mkimg -.Nd "utility to make a disk image" +.Nd "utility to make disk images" .Sh SYNOPSIS .Nm .Op Fl H Ar heads @@ -40,9 +40,12 @@ .Op Fl f Ar format .Op Fl o Ar outfile .Op Fl v +.Op Fl y .Fl s Ar scheme .Fl p Ar partition .Op Fl p Ar partition ... +.Nm +.Ar --formats | --schemes | --version .Sh DESCRIPTION The .Nm @@ -111,10 +114,42 @@ option increases the level of output tha .Nm utility prints. .Pp -For a complete list of supported partitioning schemes or supported output -format, or for a detailed description of how to specify partitions, run the +The +.Op Fl y +option is used for testing purposes only and is not to be used in production. +When present, the +.Nm +utility will generate predictable values for Universally Unique Identifiers +(UUIDs) and time stamps so that consecutive runs of the +.Nm +utility will create images that are identical. +.Pp +A set of long options exist to query about the +.Nm +utilty itself. +Options in this set should be given by themselves because the +.Nm +utility exits immediately after providing the requested information. +The version of the +.Nm +utility is printed when the +.Ar --version +option is given. +The list of supported output formats is printed when the +.Ar --formats +option is given and the list of supported partitioning schemes is printed +when the +.Ar --schemes +option is given. +Both the format and scheme lists a space-separated lists for easy handling +in scripts. +.Pp +For a more descriptive list of supported partitioning schemes or supported +output format, or for a detailed description of how to specify partitions, +run the .Nm utility without any arguments. +This will print a usage message with all the necessary details. .Sh ENVIRONMENT .Bl -tag -width "TMPDIR" -compact .It Ev TMPDIR @@ -160,6 +195,25 @@ utility as follows: .Dl % mkimg -s mbr -b /boot/mbr -p freebsd:-'mkimg -s bsd -b /boot/boot \ -p freebsd-ufs:=root-file-system.ufs -p freebsd-swap::1G' -o mbr-bsd.img .Pp +To accomodate the need to have partitions named or numbered in a certain +way, the +.Nm +utility allows for the specification of empty partitions. +For example, to create an image that is compatible with partition layouts +found in +.Pa /etc/disktab , +the 'd' partition often needs to be skipped. +This is accomplished by inserting an unused partition after the first 2 +partition specifications. +It is worth noting at this time that the BSD scheme will automatically +skip the 'c' partition by virtue of it referring to the entire disk. +To create an image that is compatible with the qp120at disk, use the +.Nm +utility as follows: +.Dl % mkimg -s bsd -b /boot/boot -p freebsd-ufs:=root-file-system.ufs \ +-p freebsd-swap::20M -p- -p- -p- -p- -p freebsd-ufs:=usr-file-system.ufs \ +-o bsd.img +.Pp For partitioning schemes that feature partition labels, the .Nm utility supports assigning labels to the partitions specified. Modified: user/marcel/mkimg/mkimg.c ============================================================================== --- user/marcel/mkimg/mkimg.c Sat Sep 27 23:57:21 2014 (r272230) +++ user/marcel/mkimg/mkimg.c Sun Sep 28 00:20:08 2014 (r272231) @@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$"); #include <errno.h> #include <err.h> #include <fcntl.h> +#include <getopt.h> #include <libutil.h> #include <limits.h> #include <stdio.h> @@ -48,6 +49,17 @@ __FBSDID("$FreeBSD$"); #include "mkimg.h" #include "scheme.h" +#define LONGOPT_FORMATS 0x01000001 +#define LONGOPT_SCHEMES 0x01000002 +#define LONGOPT_VERSION 0x01000003 + +static struct option longopts[] = { + { "formats", no_argument, NULL, LONGOPT_FORMATS }, + { "schemes", no_argument, NULL, LONGOPT_SCHEMES }, + { "version", no_argument, NULL, LONGOPT_VERSION }, + { NULL, 0, NULL, 0 } +}; + struct partlisthead partlist = STAILQ_HEAD_INITIALIZER(partlist); u_int nparts = 0; @@ -61,44 +73,103 @@ u_int secsz = 512; u_int blksz = 0; static void -usage(const char *why) +print_formats(int usage) { struct mkimg_format *f, **f_iter; + const char *sep; + + if (usage) { + fprintf(stderr, " formats:\n"); + SET_FOREACH(f_iter, formats) { + f = *f_iter; + fprintf(stderr, "\t%s\t- %s\n", f->name, + f->description); + } + } else { + sep = ""; + SET_FOREACH(f_iter, formats) { + f = *f_iter; + printf("%s%s", sep, f->name); + sep = " "; + } + putchar('\n'); + } +} + +static void +print_schemes(int usage) +{ struct mkimg_scheme *s, **s_iter; + const char *sep; + + if (usage) { + fprintf(stderr, " schemes:\n"); + SET_FOREACH(s_iter, schemes) { + s = *s_iter; + fprintf(stderr, "\t%s\t- %s\n", s->name, + s->description); + } + } else { + sep = ""; + SET_FOREACH(s_iter, schemes) { + s = *s_iter; + printf("%s%s", sep, s->name); + sep = " "; + } + putchar('\n'); + } +} + +static void +print_version(void) +{ + u_int width; + +#ifdef __LP64__ + width = 64; +#else + width = 32; +#endif + printf("mkimg %u (%u-bit)\n", MKIMG_VERSION, width); +} + +static void +usage(const char *why) +{ warnx("error: %s", why); - fprintf(stderr, "\nusage: %s <options>\n", getprogname()); + fputc('\n', stderr); + fprintf(stderr, "usage: %s <options>\n", getprogname()); fprintf(stderr, " options:\n"); + fprintf(stderr, "\t--formats\t- list image formats\n"); + fprintf(stderr, "\t--schemes\t- list partition schemes\n"); + fprintf(stderr, "\t--version\t- show version information\n"); + fputc('\n', stderr); fprintf(stderr, "\t-b <file>\t- file containing boot code\n"); fprintf(stderr, "\t-f <format>\n"); fprintf(stderr, "\t-o <file>\t- file to write image into\n"); fprintf(stderr, "\t-p <partition>\n"); fprintf(stderr, "\t-s <scheme>\n"); + fprintf(stderr, "\t-v\t\t- increase verbosity\n"); + fprintf(stderr, "\t-y\t\t- [developers] enable unit test\n"); fprintf(stderr, "\t-H <num>\t- number of heads to simulate\n"); fprintf(stderr, "\t-P <num>\t- physical sector size\n"); fprintf(stderr, "\t-S <num>\t- logical sector size\n"); fprintf(stderr, "\t-T <num>\t- number of tracks to simulate\n"); - - fprintf(stderr, "\n formats:\n"); - SET_FOREACH(f_iter, formats) { - f = *f_iter; - fprintf(stderr, "\t%s\t- %s\n", f->name, f->description); - } - - fprintf(stderr, "\n schemes:\n"); - SET_FOREACH(s_iter, schemes) { - s = *s_iter; - fprintf(stderr, "\t%s\t- %s\n", s->name, s->description); - } - - fprintf(stderr, "\n partition specification:\n"); + fputc('\n', stderr); + print_formats(1); + fputc('\n', stderr); + print_schemes(1); + fputc('\n', stderr); + fprintf(stderr, " partition specification:\n"); fprintf(stderr, "\t<t>[/<l>]::<size>\t- empty partition of given " "size\n"); fprintf(stderr, "\t<t>[/<l>]:=<file>\t- partition content and size " "are determined\n\t\t\t\t by the named file\n"); fprintf(stderr, "\t<t>[/<l>]:-<cmd>\t- partition content and size " "are taken from\n\t\t\t\t the output of the command to run\n"); + fprintf(stderr, "\t-\t\t\t- unused partition entry\n"); fprintf(stderr, "\t where:\n"); fprintf(stderr, "\t\t<t>\t- scheme neutral partition type\n"); fprintf(stderr, "\t\t<l>\t- optional scheme-dependent partition " @@ -138,6 +209,9 @@ pwr_of_two(u_int nr) * '-' contents holds a command to run; the output of * which is the contents of the partition. * contents the specification of a partition's contents + * + * A specification that is a single dash indicates an unused partition + * entry. */ static int parse_part(const char *spec) @@ -147,6 +221,11 @@ parse_part(const char *spec) size_t len; int error; + if (strcmp(spec, "-") == 0) { + nparts++; + return (0); + } + part = calloc(1, sizeof(struct part)); if (part == NULL) return (ENOMEM); @@ -355,7 +434,8 @@ main(int argc, char *argv[]) bcfd = -1; outfd = 1; /* Write to stdout by default */ - while ((c = getopt(argc, argv, "b:f:o:p:s:vyH:P:S:T:")) != -1) { + while ((c = getopt_long(argc, argv, "b:f:o:p:s:vyH:P:S:T:", + longopts, NULL)) != -1) { switch (c) { case 'b': /* BOOT CODE */ if (bcfd != -1) @@ -421,6 +501,18 @@ main(int argc, char *argv[]) if (error) errc(EX_DATAERR, error, "track size"); break; + case LONGOPT_FORMATS: + print_formats(0); + exit(EX_OK); + /*NOTREACHED*/ + case LONGOPT_SCHEMES: + print_schemes(0); + exit(EX_OK); + /*NOTREACHED*/ + case LONGOPT_VERSION: + print_version(); + exit(EX_OK); + /*NOTREACHED*/ default: usage("unknown option"); } Modified: user/marcel/mkimg/mkimg.h ============================================================================== --- user/marcel/mkimg/mkimg.h Sat Sep 27 23:57:21 2014 (r272230) +++ user/marcel/mkimg/mkimg.h Sun Sep 28 00:20:08 2014 (r272231) @@ -66,6 +66,21 @@ round_block(lba_t n) return ((n + b - 1) & ~(b - 1)); } +static inline lba_t +round_cylinder(lba_t n) +{ + u_int cyl = nsecs * nheads; + u_int r = n % cyl; + return ((r == 0) ? n : n + cyl - r); +} + +static inline lba_t +round_track(lba_t n) +{ + u_int r = n % nsecs; + return ((r == 0) ? n : n + nsecs - r); +} + #if !defined(SPARSE_WRITE) #define sparse_write write #else Modified: user/marcel/mkimg/pc98.c ============================================================================== --- user/marcel/mkimg/pc98.c Sat Sep 27 23:57:21 2014 (r272230) +++ user/marcel/mkimg/pc98.c Sun Sep 28 00:20:08 2014 (r272231) @@ -59,13 +59,12 @@ static struct mkimg_alias pc98_aliases[] { ALIAS_NONE, 0 } }; -static u_int -pc98_metadata(u_int where) +static lba_t +pc98_metadata(u_int where, lba_t blk) { - u_int secs; - - secs = PC98_BOOTCODESZ / secsz; - return ((where == SCHEME_META_IMG_START) ? secs : 0); + if (where == SCHEME_META_IMG_START) + blk += PC98_BOOTCODESZ / secsz; + return (round_track(blk)); } static void Copied: user/marcel/mkimg/qcow.c (from r272230, head/usr.bin/mkimg/qcow.c) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ user/marcel/mkimg/qcow.c Sun Sep 28 00:20:08 2014 (r272231, copy of r272230, head/usr.bin/mkimg/qcow.c) @@ -0,0 +1,369 @@ +/*- + * Copyright (c) 2014 Marcel Moolenaar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/types.h> +#include <sys/endian.h> +#include <sys/errno.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "image.h" +#include "format.h" +#include "mkimg.h" + +/* Default cluster sizes. */ +#define QCOW1_CLSTR_LOG2SZ 12 /* 4KB */ +#define QCOW2_CLSTR_LOG2SZ 16 /* 64KB */ + +/* Flag bits in cluster offsets */ +#define QCOW_CLSTR_COMPRESSED (1ULL << 62) +#define QCOW_CLSTR_COPIED (1ULL << 63) + +struct qcow_header { + uint32_t magic; +#define QCOW_MAGIC 0x514649fb + uint32_t version; +#define QCOW_VERSION_1 1 +#define QCOW_VERSION_2 2 + uint64_t path_offset; + uint32_t path_length; + uint32_t clstr_log2sz; /* v2 only */ + uint64_t disk_size; + union { + struct { + uint8_t clstr_log2sz; + uint8_t l2_log2sz; + uint16_t _pad; + uint32_t encryption; + uint64_t l1_offset; + } v1; + struct { + uint32_t encryption; + uint32_t l1_entries; + uint64_t l1_offset; + uint64_t refcnt_offset; + uint32_t refcnt_entries; + uint32_t snapshot_count; + uint64_t snapshot_offset; + } v2; + } u; +}; + +static u_int clstr_log2sz; + +static uint64_t +round_clstr(uint64_t ofs) +{ + uint64_t clstrsz; + + clstrsz = 1UL << clstr_log2sz; + return ((ofs + clstrsz - 1) & ~(clstrsz - 1)); +} + +static int +qcow_resize(lba_t imgsz, u_int version) +{ + uint64_t imagesz; + + switch (version) { + case QCOW_VERSION_1: + clstr_log2sz = QCOW1_CLSTR_LOG2SZ; + break; + case QCOW_VERSION_2: + clstr_log2sz = QCOW2_CLSTR_LOG2SZ; + break; + default: + return (EDOOFUS); + } + + imagesz = round_clstr(imgsz * secsz); + + if (verbose) + fprintf(stderr, "QCOW: image size = %ju, cluster size = %u\n", + (uintmax_t)imagesz, (u_int)(1U << clstr_log2sz)); + + return (image_set_size(imagesz / secsz)); +} + +static int +qcow1_resize(lba_t imgsz) +{ + + return (qcow_resize(imgsz, QCOW_VERSION_1)); +} + +static int +qcow2_resize(lba_t imgsz) +{ + + return (qcow_resize(imgsz, QCOW_VERSION_2)); +} + +static int +qcow_write(int fd, u_int version) +{ + struct qcow_header *hdr; + uint64_t *l1tbl, *l2tbl, *rctbl; + uint16_t *rcblk; + uint64_t clstr_imgsz, clstr_l2tbls, clstr_l1tblsz; + uint64_t clstr_rcblks, clstr_rctblsz; + uint64_t n, imagesz, nclstrs, ofs, ofsflags; + lba_t blk, blkofs, blk_imgsz; + u_int l1clno, l2clno, rcclno; + u_int blk_clstrsz; + u_int clstrsz, l1idx, l2idx; + int error; + + if (clstr_log2sz == 0) + return (EDOOFUS); + + clstrsz = 1U << clstr_log2sz; + blk_clstrsz = clstrsz / secsz; + blk_imgsz = image_get_size(); + imagesz = blk_imgsz * secsz; + clstr_imgsz = imagesz >> clstr_log2sz; + clstr_l2tbls = round_clstr(clstr_imgsz * 8) >> clstr_log2sz; + clstr_l1tblsz = round_clstr(clstr_l2tbls * 8) >> clstr_log2sz; + nclstrs = clstr_imgsz + clstr_l2tbls + clstr_l1tblsz + 1; + clstr_rcblks = clstr_rctblsz = 0; + do { + n = clstr_rcblks + clstr_rctblsz; + clstr_rcblks = round_clstr((nclstrs + n) * 2) >> clstr_log2sz; + clstr_rctblsz = round_clstr(clstr_rcblks * 8) >> clstr_log2sz; + } while (n < (clstr_rcblks + clstr_rctblsz)); + + /* + * We got all the sizes in clusters. Start the layout. + * 0 - header + * 1 - L1 table + * 2 - RC table (v2 only) + * 3 - L2 tables + * 4 - RC block (v2 only) + * 5 - data + */ + + l1clno = 1; + rcclno = 0; + rctbl = l2tbl = l1tbl = NULL; + rcblk = NULL; + + hdr = calloc(1, clstrsz); + if (hdr == NULL) + return (errno); + + be32enc(&hdr->magic, QCOW_MAGIC); + be32enc(&hdr->version, version); + be64enc(&hdr->disk_size, imagesz); + switch (version) { + case QCOW_VERSION_1: + ofsflags = 0; + l2clno = l1clno + clstr_l1tblsz; + hdr->u.v1.clstr_log2sz = clstr_log2sz; + hdr->u.v1.l2_log2sz = clstr_log2sz - 3; + be64enc(&hdr->u.v1.l1_offset, clstrsz * l1clno); + break; + case QCOW_VERSION_2: + ofsflags = QCOW_CLSTR_COPIED; + rcclno = l1clno + clstr_l1tblsz; + l2clno = rcclno + clstr_rctblsz; + be32enc(&hdr->clstr_log2sz, clstr_log2sz); + be32enc(&hdr->u.v2.l1_entries, clstr_l2tbls); + be64enc(&hdr->u.v2.l1_offset, clstrsz * l1clno); + be64enc(&hdr->u.v2.refcnt_offset, clstrsz * rcclno); + be32enc(&hdr->u.v2.refcnt_entries, clstr_rcblks); + break; + default: + return (EDOOFUS); + } + + if (sparse_write(fd, hdr, clstrsz) < 0) { + error = errno; + goto out; + } + + free(hdr); + hdr = NULL; + + ofs = clstrsz * l2clno; + nclstrs = 1 + clstr_l1tblsz + clstr_rctblsz; + + l1tbl = calloc(1, clstrsz * clstr_l1tblsz); + if (l1tbl == NULL) { + error = ENOMEM; + goto out; + } + + for (n = 0; n < clstr_imgsz; n++) { + blk = n * blk_clstrsz; + if (image_data(blk, blk_clstrsz)) { + nclstrs++; + l1idx = n >> (clstr_log2sz - 3); + if (l1tbl[l1idx] == 0) { + be64enc(l1tbl + l1idx, ofs + ofsflags); + ofs += clstrsz; + nclstrs++; + } + } + } + + if (sparse_write(fd, l1tbl, clstrsz * clstr_l1tblsz) < 0) { + error = errno; + goto out; + } + + clstr_rcblks = 0; + do { + n = clstr_rcblks; + clstr_rcblks = round_clstr((nclstrs + n) * 2) >> clstr_log2sz; + } while (n < clstr_rcblks); + + if (rcclno > 0) { + rctbl = calloc(1, clstrsz * clstr_rctblsz); + if (rctbl == NULL) { + error = ENOMEM; + goto out; + } + for (n = 0; n < clstr_rcblks; n++) { + be64enc(rctbl + n, ofs); + ofs += clstrsz; + nclstrs++; + } + if (sparse_write(fd, rctbl, clstrsz * clstr_rctblsz) < 0) { + error = errno; + goto out; + } + free(rctbl); + rctbl = NULL; + } + + l2tbl = malloc(clstrsz); + if (l2tbl == NULL) { + error = ENOMEM; + goto out; + } + + for (l1idx = 0; l1idx < clstr_l2tbls; l1idx++) { + if (l1tbl[l1idx] == 0) + continue; + memset(l2tbl, 0, clstrsz); + blkofs = (lba_t)l1idx * blk_clstrsz * (clstrsz >> 3); + for (l2idx = 0; l2idx < (clstrsz >> 3); l2idx++) { + blk = blkofs + (lba_t)l2idx * blk_clstrsz; + if (blk >= blk_imgsz) + break; + if (image_data(blk, blk_clstrsz)) { + be64enc(l2tbl + l2idx, ofs + ofsflags); + ofs += clstrsz; + } + } + if (sparse_write(fd, l2tbl, clstrsz) < 0) { + error = errno; + goto out; + } + } + + free(l2tbl); + l2tbl = NULL; + free(l1tbl); + l1tbl = NULL; + + if (rcclno > 0) { + rcblk = calloc(1, clstrsz * clstr_rcblks); + if (rcblk == NULL) { + error = ENOMEM; + goto out; + } + for (n = 0; n < nclstrs; n++) + be16enc(rcblk + n, 1); + if (sparse_write(fd, rcblk, clstrsz * clstr_rcblks) < 0) { + error = errno; + goto out; + } + free(rcblk); + rcblk = NULL; + } + + error = 0; + for (n = 0; n < clstr_imgsz; n++) { + blk = n * blk_clstrsz; + if (image_data(blk, blk_clstrsz)) { + error = image_copyout_region(fd, blk, blk_clstrsz); + if (error) + break; + } + } + if (!error) + error = image_copyout_done(fd); + + out: + if (rcblk != NULL) + free(rcblk); + if (l2tbl != NULL) + free(l2tbl); + if (rctbl != NULL) + free(rctbl); + if (l1tbl != NULL) + free(l1tbl); + if (hdr != NULL) + free(hdr); + return (error); +} + +static int +qcow1_write(int fd) +{ + + return (qcow_write(fd, QCOW_VERSION_1)); +} + +static int +qcow2_write(int fd) +{ + + return (qcow_write(fd, QCOW_VERSION_2)); +} + +static struct mkimg_format qcow1_format = { + .name = "qcow", + .description = "QEMU Copy-On-Write, version 1", + .resize = qcow1_resize, + .write = qcow1_write, +}; +FORMAT_DEFINE(qcow1_format); + +static struct mkimg_format qcow2_format = { + .name = "qcow2", + .description = "QEMU Copy-On-Write, version 2", + .resize = qcow2_resize, + .write = qcow2_write, +}; +FORMAT_DEFINE(qcow2_format); Modified: user/marcel/mkimg/scheme.c ============================================================================== --- user/marcel/mkimg/scheme.c Sat Sep 27 23:57:21 2014 (r272230) +++ user/marcel/mkimg/scheme.c Sun Sep 28 00:20:08 2014 (r272231) @@ -171,10 +171,8 @@ scheme_max_secsz(void) *** DIFF OUTPUT TRUNCATED AT 1000 LINES *** From owner-svn-src-user@FreeBSD.ORG Sun Sep 28 00:24:02 2014 Return-Path: <owner-svn-src-user@FreeBSD.ORG> Delivered-To: svn-src-user@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 661BF485; Sun, 28 Sep 2014 00:24:02 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 537756CB; Sun, 28 Sep 2014 00:24:02 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id s8S0O2jL072884; Sun, 28 Sep 2014 00:24:02 GMT (envelope-from marcel@FreeBSD.org) Received: (from marcel@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id s8S0O26B072883; Sun, 28 Sep 2014 00:24:02 GMT (envelope-from marcel@FreeBSD.org) Message-Id: <201409280024.s8S0O26B072883@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: marcel set sender to marcel@FreeBSD.org using -f From: Marcel Moolenaar <marcel@FreeBSD.org> Date: Sun, 28 Sep 2014 00:24:02 +0000 (UTC) To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r272232 - user/marcel/mkimg X-SVN-Group: user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-user@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: "SVN commit messages for the experimental " user" src tree" <svn-src-user.freebsd.org> List-Unsubscribe: <http://lists.freebsd.org/mailman/options/svn-src-user>, <mailto:svn-src-user-request@freebsd.org?subject=unsubscribe> List-Archive: <http://lists.freebsd.org/pipermail/svn-src-user/> List-Post: <mailto:svn-src-user@freebsd.org> List-Help: <mailto:svn-src-user-request@freebsd.org?subject=help> List-Subscribe: <http://lists.freebsd.org/mailman/listinfo/svn-src-user>, <mailto:svn-src-user-request@freebsd.org?subject=subscribe> X-List-Received-Date: Sun, 28 Sep 2014 00:24:02 -0000 Author: marcel Date: Sun Sep 28 00:24:01 2014 New Revision: 272232 URL: http://svnweb.freebsd.org/changeset/base/272232 Log: Work around broken make infrastructure. Sigh... Modified: user/marcel/mkimg/Makefile Modified: user/marcel/mkimg/Makefile ============================================================================== --- user/marcel/mkimg/Makefile Sun Sep 28 00:20:08 2014 (r272231) +++ user/marcel/mkimg/Makefile Sun Sep 28 00:24:01 2014 (r272232) @@ -1,6 +1,6 @@ # $FreeBSD$ -.include <src.opts.mk> +!.include <src.opts.mk> PROG= mkimg SRCS= format.c image.c mkimg.c scheme.c @@ -34,7 +34,7 @@ LDADD= -lutil WARNS?= 6 -.if ${MK_TESTS} != "no" +.if ${MK_TESTS:Uno} != "no" SUBDIR+= tests .endif From owner-svn-src-user@FreeBSD.ORG Sun Sep 28 00:43:05 2014 Return-Path: <owner-svn-src-user@FreeBSD.ORG> Delivered-To: svn-src-user@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 2527869C; Sun, 28 Sep 2014 00:43:05 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 116D48AD; Sun, 28 Sep 2014 00:43:05 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id s8S0h4Ed081855; Sun, 28 Sep 2014 00:43:04 GMT (envelope-from marcel@FreeBSD.org) Received: (from marcel@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id s8S0h4Pu081854; Sun, 28 Sep 2014 00:43:04 GMT (envelope-from marcel@FreeBSD.org) Message-Id: <201409280043.s8S0h4Pu081854@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: marcel set sender to marcel@FreeBSD.org using -f From: Marcel Moolenaar <marcel@FreeBSD.org> Date: Sun, 28 Sep 2014 00:43:04 +0000 (UTC) To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r272233 - user/marcel/mkimg X-SVN-Group: user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-user@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: "SVN commit messages for the experimental " user" src tree" <svn-src-user.freebsd.org> List-Unsubscribe: <http://lists.freebsd.org/mailman/options/svn-src-user>, <mailto:svn-src-user-request@freebsd.org?subject=unsubscribe> List-Archive: <http://lists.freebsd.org/pipermail/svn-src-user/> List-Post: <mailto:svn-src-user@freebsd.org> List-Help: <mailto:svn-src-user-request@freebsd.org?subject=help> List-Subscribe: <http://lists.freebsd.org/mailman/listinfo/svn-src-user>, <mailto:svn-src-user-request@freebsd.org?subject=subscribe> X-List-Received-Date: Sun, 28 Sep 2014 00:43:05 -0000 Author: marcel Date: Sun Sep 28 00:43:04 2014 New Revision: 272233 URL: http://svnweb.freebsd.org/changeset/base/272233 Log: Start performance optimizations: Output formats typically need to know whether a sequence of blocks has data or not. They use this to determine whether to allocate disk space for them or not. The image_data() function provides that functionality, but is implemented by reading the amount of blocks from the temporary file and comparing that with zeroes. The QCOW format needs to go over the image 3 times and every time we read from the temporary file. We can speed this up by building a "chunk" list in memory while we read the partition data. Each chunk is a sequence of blocks that is either defined as a gap (i.e. all zeroes) or defined as containing data. For each chunk we keep track of the file and the offset in that file where the chunk's data comes from. This allows us handle regular files and in particular sparse files more optimally. For sparse files we can trivially build a chunk for each of the holes in the parse file by using SEEK_HOLE and SEEK_DATA. The data regions still need to be read to handle zeroe blocks for block sizes smaller that the underlying file system's block size. However, we don't have to copy the data into a temporary file anymore. For anything but regular files, we still use the temporary file. We call it a swap file now. With that all data can be mapped and unmapped as we need to access it. This commit implements the creation of the chunk list and the swap file usage for non-regular files (i.e. streams). Mappable files are now handled like streams, so that needs some work. The big part that is missing is the use of the chunk list for determining whether a sequence of blocks has data and all the handling of writing the image data to the output file. As such: this commit breaks mkimg and makes it useless. It's a good WIP to safe thogh -- hence doing it on my branch. Modified: user/marcel/mkimg/image.c Modified: user/marcel/mkimg/image.c ============================================================================== --- user/marcel/mkimg/image.c Sun Sep 28 00:24:01 2014 (r272232) +++ user/marcel/mkimg/image.c Sun Sep 28 00:43:04 2014 (r272233) @@ -27,67 +27,303 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); +#include <sys/mman.h> +#include <sys/queue.h> +#include <sys/stat.h> #include <sys/types.h> #include <assert.h> #include <errno.h> #include <limits.h> #include <paths.h> +#include <stdint.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <unistd.h> #include "image.h" #include "mkimg.h" -#define BUFFER_SIZE (1024*1024) +struct chunk { + lba_t ch_block; /* Block address in image. */ + off_t ch_ofs; /* Offset in backing file. */ + STAILQ_ENTRY(chunk) ch_list; + size_t ch_size; /* Size of chunk in bytes. */ + int ch_fd; /* FD of backing file. */ + u_int ch_flags; +#define CH_FLAGS_GAP 1 /* Chunk is a gap (no FD). */ +#define CH_FLAGS_DIRTY 2 /* Data modified/only in memory. */ +}; + +static STAILQ_HEAD(chunk_head, chunk) image_chunks; +static u_int image_nchunks; + +static char image_swap_file[PATH_MAX]; +static int image_swap_fd = -1; +static u_int image_swap_pgsz; +static off_t image_swap_size; -static char image_tmpfile[PATH_MAX]; -static int image_fd = -1; static lba_t image_size; +/* + * Swap file handlng. + */ + +static off_t +image_swap_alloc(size_t size) +{ + off_t ofs; + size_t unit; + + unit = (secsz > image_swap_pgsz) ? secsz : image_swap_pgsz; + assert((unit & (unit - 1)) == 0); + + size = (size + unit - 1) & ~(unit - 1); + + ofs = image_swap_size; + image_swap_size += size; + if (ftruncate(image_swap_fd, image_swap_size) == -1) { + image_swap_size = ofs; + ofs = -1LL; + } + fprintf(stderr, "SWAP: off=%jd, size=%zu\n", (intmax_t)ofs, size); + return (ofs); +} + +/* + * Image chunk handling. + */ + static void -cleanup(void) +image_chunk_dump(void) { + struct chunk *ch; - if (image_fd != -1) - close(image_fd); - unlink(image_tmpfile); + fprintf(stderr, "%u chunks:\n", image_nchunks); + STAILQ_FOREACH(ch, &image_chunks, ch_list) { + fprintf(stderr, "\tblk=%jd, ofs=%jd, fd=%d, sz=%zu, fl=%u\n", + (intmax_t)ch->ch_block, (intmax_t)ch->ch_ofs, ch->ch_fd, + ch->ch_size, ch->ch_flags); + } } -int -image_copyin(lba_t blk, int fd, uint64_t *sizep) +static size_t +image_chunk_grow(struct chunk *ch, size_t sz) +{ + size_t dsz, newsz; + + newsz = ch->ch_size + sz; + if (newsz > ch->ch_size) { + ch->ch_size = newsz; + return (0); + } + /* We would overflow -- create new chunk for remainder. */ + dsz = SIZE_MAX - ch->ch_size; + assert(dsz < sz); + ch->ch_size = SIZE_MAX; + return (sz - dsz); +} + +static int +image_chunk_skipto(lba_t to) +{ + struct chunk *ch; + lba_t from; + size_t sz; + + ch = STAILQ_LAST(&image_chunks, chunk, ch_list); + from = (ch != NULL) ? ch->ch_block + (ch->ch_size / secsz) : 0LL; + + assert(from <= to); + + /* Nothing to do? */ + if (from == to) + return (0); + /* Avoid bugs due to overflows. */ + if ((uintmax_t)(to - from) > (uintmax_t)(SIZE_MAX / secsz)) + return (EFBIG); + sz = (to - from) * secsz; + if (ch != NULL && (ch->ch_flags & CH_FLAGS_GAP)) { + sz = image_chunk_grow(ch, sz); + if (sz == 0) + return (0); + from = ch->ch_block + (ch->ch_size / secsz); + } + ch = malloc(sizeof(*ch)); + if (ch == NULL) + return (ENOMEM); + memset(ch, 0, sizeof(*ch)); + ch->ch_block = from; + ch->ch_size = sz; + ch->ch_fd = -1; + ch->ch_flags |= CH_FLAGS_GAP; + STAILQ_INSERT_TAIL(&image_chunks, ch, ch_list); + image_nchunks++; + return (0); +} + +static int +image_chunk_append(lba_t blk, size_t sz, off_t ofs, int fd) +{ + struct chunk *ch; + + ch = STAILQ_LAST(&image_chunks, chunk, ch_list); + if (ch != NULL && (ch->ch_flags & CH_FLAGS_GAP) == 0) { + if (fd == ch->ch_fd && + blk == (lba_t)(ch->ch_block + (ch->ch_size / secsz)) && + ofs == (off_t)(ch->ch_ofs + ch->ch_size)) { + sz = image_chunk_grow(ch, sz); + if (sz == 0) + return (0); + blk = ch->ch_block + (ch->ch_size / secsz); + ofs = ch->ch_ofs + ch->ch_size; + } + } + ch = malloc(sizeof(*ch)); + if (ch == NULL) + return (ENOMEM); + memset(ch, 0, sizeof(*ch)); + ch->ch_block = blk; + ch->ch_ofs = ofs; + ch->ch_size = sz; + ch->ch_fd = fd; + STAILQ_INSERT_TAIL(&image_chunks, ch, ch_list); + image_nchunks++; + return (0); +} + +static int +image_chunk_copyin(lba_t blk, void *buf, size_t sz, off_t ofs, int fd) +{ + uint64_t *p = buf; + size_t n; + int error; + + assert(((uintptr_t)p & 3) == 0); + + error = 0; + sz = (sz + secsz - 1) & ~(secsz - 1); + while (!error && sz > 0) { + n = 0; + while (n < (secsz >> 3) && p[n] == 0) + n++; + if (n == (secsz >> 3)) + error = image_chunk_skipto(blk + 1); + else + error = image_chunk_append(blk, secsz, ofs, fd); + blk++; + p += (secsz >> 3); + sz -= secsz; + ofs += secsz; + } + return (error); +} + +/* + * File mapping support. + */ + +static void * +image_file_map(int fd, off_t ofs, size_t sz) +{ + void *ptr; + size_t unit; + int flags, prot; + + unit = (secsz > image_swap_pgsz) ? secsz : image_swap_pgsz; + assert((unit & (unit - 1)) == 0); + + flags = MAP_NOCORE | MAP_NOSYNC | MAP_SHARED; + /* Allow writing to our swap file only. */ + prot = PROT_READ | ((fd == image_swap_fd) ? PROT_WRITE : 0); + sz = (sz + unit - 1) & ~(unit - 1); + ptr = mmap(NULL, sz, prot, flags, fd, ofs); + return ((ptr == MAP_FAILED) ? NULL : ptr); +} + +static int +image_file_unmap(void *buffer, size_t sz) +{ + size_t unit; + + unit = (secsz > image_swap_pgsz) ? secsz : image_swap_pgsz; + sz = (sz + unit - 1) & ~(unit - 1); + munmap(buffer, sz); + return (0); +} + +/* + * Input/source file handling. + */ + +static int +image_copyin_stream(lba_t blk, int fd, uint64_t *sizep) { char *buffer; uint64_t bytesize; - ssize_t bcnt, rdsz; - int error, partial; + off_t swofs; + size_t iosz; + ssize_t rdsz; + int error; - assert(BUFFER_SIZE % secsz == 0); + /* + * This makes sure we're doing I/O in multiples of the page + * size as well as of the sector size. 2MB is the minimum + * by virtue of secsz at least 512 bytes and the page size + * at least 4K bytes. + */ + iosz = secsz * image_swap_pgsz; - buffer = malloc(BUFFER_SIZE); - if (buffer == NULL) - return (ENOMEM); bytesize = 0; - partial = 0; - while (1) { - rdsz = read(fd, buffer, BUFFER_SIZE); - if (rdsz <= 0) { - error = (rdsz < 0) ? errno : 0; - break; - } - if (partial) - abort(); - bytesize += rdsz; - bcnt = (rdsz + secsz - 1) / secsz; - error = image_write(blk, buffer, bcnt); + do { + swofs = image_swap_alloc(iosz); + if (swofs == -1LL) + return (errno); + buffer = image_file_map(image_swap_fd, swofs, iosz); + if (buffer == NULL) + return (errno); + rdsz = read(fd, buffer, iosz); + if (rdsz > 0) + error = image_chunk_copyin(blk, buffer, rdsz, swofs, + image_swap_fd); + else if (rdsz < 0) + error = errno; + else + error = 0; + image_file_unmap(buffer, iosz); + /* XXX should we relinguish unused swap space? */ if (error) - break; - blk += bcnt; - partial = ((ssize_t)(bcnt * secsz) != rdsz) ? 1 : 0; - } - free(buffer); + return (error); + + bytesize += rdsz; + blk += (rdsz + secsz - 1) / secsz; + } while (rdsz > 0); + if (sizep != NULL) *sizep = bytesize; + return (0); +} + +static int +image_copyin_mapped(lba_t blk, int fd, uint64_t *sizep) +{ + + return (image_copyin_stream(blk, fd, sizep)); +} + +int +image_copyin(lba_t blk, int fd, uint64_t *sizep) +{ + struct stat sb; + int error; + + error = image_chunk_skipto(blk); + if (!error) { + if (fstat(fd, &sb) == -1 || !S_ISREG(sb.st_mode)) + error = image_copyin_stream(blk, fd, sizep); + else + error = image_copyin_mapped(blk, fd, sizep); + } return (error); } @@ -120,23 +356,25 @@ image_copyout_region(int fd, lba_t blk, { char *buffer; off_t ofs; - size_t sz; + size_t bufsz, sz; ssize_t rdsz, wrsz; int error; + bufsz = secsz * image_swap_pgsz; + ofs = lseek(fd, 0L, SEEK_CUR); blk *= secsz; - if (lseek(image_fd, blk, SEEK_SET) != blk) + if (lseek(image_swap_fd, blk, SEEK_SET) != blk) return (errno); - buffer = malloc(BUFFER_SIZE); + buffer = malloc(bufsz); if (buffer == NULL) return (errno); error = 0; size *= secsz; while (size > 0) { - sz = (BUFFER_SIZE < size) ? BUFFER_SIZE : size; - rdsz = read(image_fd, buffer, sz); + sz = ((ssize_t)bufsz < size) ? bufsz : (size_t)size; + rdsz = read(image_swap_fd, buffer, sz); if (rdsz <= 0) { error = (rdsz < 0) ? errno : 0; break; @@ -161,7 +399,7 @@ image_data(lba_t blk, lba_t size) char *buffer, *p; blk *= secsz; - if (lseek(image_fd, blk, SEEK_SET) != blk) + if (lseek(image_swap_fd, blk, SEEK_SET) != blk) return (1); size *= secsz; @@ -169,7 +407,7 @@ image_data(lba_t blk, lba_t size) if (buffer == NULL) return (1); - if (read(image_fd, buffer, size) != (ssize_t)size) { + if (read(image_swap_fd, buffer, size) != (ssize_t)size) { free(buffer); return (1); } @@ -185,7 +423,12 @@ image_data(lba_t blk, lba_t size) lba_t image_get_size(void) { + static int once = 0; + if (once == 0) { + once++; + image_chunk_dump(); + } return (image_size); } @@ -193,8 +436,10 @@ int image_set_size(lba_t blk) { + image_chunk_skipto(blk); + image_size = blk; - if (ftruncate(image_fd, blk * secsz) == -1) + if (ftruncate(image_swap_fd, blk * secsz) == -1) return (errno); return (0); } @@ -204,27 +449,42 @@ image_write(lba_t blk, void *buf, ssize_ { blk *= secsz; - if (lseek(image_fd, blk, SEEK_SET) != blk) + if (lseek(image_swap_fd, blk, SEEK_SET) != blk) return (errno); len *= secsz; - if (sparse_write(image_fd, buf, len) != len) + if (sparse_write(image_swap_fd, buf, len) != len) return (errno); return (0); } +static void +image_cleanup(void) +{ + + if (image_swap_fd != -1) + close(image_swap_fd); + unlink(image_swap_file); +} + int image_init(void) { const char *tmpdir; - if (atexit(cleanup) == -1) + STAILQ_INIT(&image_chunks); + image_nchunks = 0; + + image_swap_size = 0; + image_swap_pgsz = getpagesize(); + + if (atexit(image_cleanup) == -1) return (errno); if ((tmpdir = getenv("TMPDIR")) == NULL || *tmpdir == '\0') tmpdir = _PATH_TMP; - snprintf(image_tmpfile, sizeof(image_tmpfile), "%s/mkimg-XXXXXX", + snprintf(image_swap_file, sizeof(image_swap_file), "%s/mkimg-XXXXXX", tmpdir); - image_fd = mkstemp(image_tmpfile); - if (image_fd == -1) + image_swap_fd = mkstemp(image_swap_file); + if (image_swap_fd == -1) return (errno); return (0); } From owner-svn-src-user@FreeBSD.ORG Sun Sep 28 18:34:22 2014 Return-Path: <owner-svn-src-user@FreeBSD.ORG> Delivered-To: svn-src-user@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id EB3603E4; Sun, 28 Sep 2014 18:34:21 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id D7D24762; Sun, 28 Sep 2014 18:34:21 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id s8SIYLCh091092; Sun, 28 Sep 2014 18:34:21 GMT (envelope-from marcel@FreeBSD.org) Received: (from marcel@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id s8SIYLcm091090; Sun, 28 Sep 2014 18:34:21 GMT (envelope-from marcel@FreeBSD.org) Message-Id: <201409281834.s8SIYLcm091090@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: marcel set sender to marcel@FreeBSD.org using -f From: Marcel Moolenaar <marcel@FreeBSD.org> Date: Sun, 28 Sep 2014 18:34:21 +0000 (UTC) To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r272265 - user/marcel/mkimg X-SVN-Group: user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-user@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: "SVN commit messages for the experimental " user" src tree" <svn-src-user.freebsd.org> List-Unsubscribe: <http://lists.freebsd.org/mailman/options/svn-src-user>, <mailto:svn-src-user-request@freebsd.org?subject=unsubscribe> List-Archive: <http://lists.freebsd.org/pipermail/svn-src-user/> List-Post: <mailto:svn-src-user@freebsd.org> List-Help: <mailto:svn-src-user-request@freebsd.org?subject=help> List-Subscribe: <http://lists.freebsd.org/mailman/listinfo/svn-src-user>, <mailto:svn-src-user-request@freebsd.org?subject=subscribe> X-List-Received-Date: Sun, 28 Sep 2014 18:34:22 -0000 Author: marcel Date: Sun Sep 28 18:34:20 2014 New Revision: 272265 URL: http://svnweb.freebsd.org/changeset/base/272265 Log: Implement image_copyin_mapped(): 1. If we can't seek, then let image_copyin_stream() deal with it. 2. Use SEEK_HOLE and SEEK_DATA to iterate over the regions of a sparse file. 3. Round or truncate to the sector size based on whether it's a hold or data. We truncate for holes and round for data. This to make sure to handle sparse files correctly when the sector size is larger than the file system's block/fragment size. Since we detect runts of zeroes for mmap'd data (to handle streams), we correct ourselves if such is applicable. We never mishandle data, which is the most important. I need to check with a file system that doesn't support sparse files what SEEK_HOLE and SEEK_DATA return. I'm thinking -1, which is what I don't handle yet. It's easy to do, because everything should be treated as data and we'll find the holes the hard way. While here: set DEBUG_FLAGS unconditionally to make sure I can always debug a core. Modified: user/marcel/mkimg/Makefile user/marcel/mkimg/image.c Modified: user/marcel/mkimg/Makefile ============================================================================== --- user/marcel/mkimg/Makefile Sun Sep 28 17:53:10 2014 (r272264) +++ user/marcel/mkimg/Makefile Sun Sep 28 18:34:20 2014 (r272265) @@ -10,6 +10,8 @@ MKIMG_VERSION=20140927 CFLAGS+=-DMKIMG_VERSION=${MKIMG_VERSION} CFLAGS+=-DSPARSE_WRITE +DEBUG_FLAGS=-O0 -gdwarf-2 + # List of formats to support SRCS+= \ qcow.c \ Modified: user/marcel/mkimg/image.c ============================================================================== --- user/marcel/mkimg/image.c Sun Sep 28 17:53:10 2014 (r272264) +++ user/marcel/mkimg/image.c Sun Sep 28 18:34:20 2014 (r272265) @@ -307,8 +307,88 @@ image_copyin_stream(lba_t blk, int fd, u static int image_copyin_mapped(lba_t blk, int fd, uint64_t *sizep) { + off_t cur, data, end, hole, pos; + void *buf; + uint64_t bytesize; + size_t sz; + int error; + + /* + * We'd like to know the size of the file and we must + * be able to seek in order to mmap(2). If this isn't + * possible, then treat the file as a stream/pipe. + */ + end = lseek(fd, 0L, SEEK_END); + if (end == -1L) + return (image_copyin_stream(blk, fd, sizep)); + + /* + * We need the file opened for the duration and our + * caller is going to close the file. Make a dup(2) + * so that control the faith of the descriptor. + */ + fd = dup(fd); + if (fd == -1) + return (errno); - return (image_copyin_stream(blk, fd, sizep)); + bytesize = 0; + cur = pos = 0; + error = 0; + while (!error && cur < end) { + hole = lseek(fd, cur, SEEK_HOLE); + data = lseek(fd, cur, SEEK_DATA); + + fprintf(stderr, "XXX: %s: cur=%jd, pos=%jd, hole=%jd, " + "data=%jd\n", __func__, (intmax_t)cur, (intmax_t)pos, + (intmax_t)hole, (intmax_t)data); + + if (cur == hole && data > hole) { + hole = pos; + pos = data & ~(secsz - 1); + + fprintf(stderr, "GAP %jd-%jd\n", + (intmax_t)hole, (intmax_t)pos); + + blk += (pos - hole) / secsz; + error = image_chunk_skipto(blk); + + bytesize += pos - hole; + cur = data; + } else if (cur == data && hole > data) { + data = pos; + pos = (hole + secsz - 1) & ~(secsz - 1); + + fprintf(stderr, "DATA %jd-%jd data\n", + (intmax_t)data, (intmax_t)pos); + + /* Sloppy... */ + sz = pos - data; + assert((off_t)sz == pos - data); + + buf = image_file_map(fd, data, sz); + if (buf != NULL) { + error = image_chunk_copyin(blk, buf, sz, + data, fd); + image_file_unmap(buf, sz); + } else + error = errno; + blk += sz / secsz; + bytesize += sz; + cur = hole; + } else { + /* + * I don't know what this means or whether it + * can happen at all... + */ + error = EDOOFUS; + break; + } + } + if (error) + close(fd); + if (!error && sizep != NULL) + *sizep = bytesize; + return (error); } int From owner-svn-src-user@FreeBSD.ORG Sun Sep 28 19:55:22 2014 Return-Path: <owner-svn-src-user@FreeBSD.ORG> Delivered-To: svn-src-user@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id A47C9145; Sun, 28 Sep 2014 19:55:22 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 91311E4A; Sun, 28 Sep 2014 19:55:22 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id s8SJtM37029895; Sun, 28 Sep 2014 19:55:22 GMT (envelope-from marcel@FreeBSD.org) Received: (from marcel@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id s8SJtM2C029894; Sun, 28 Sep 2014 19:55:22 GMT (envelope-from marcel@FreeBSD.org) Message-Id: <201409281955.s8SJtM2C029894@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: marcel set sender to marcel@FreeBSD.org using -f From: Marcel Moolenaar <marcel@FreeBSD.org> Date: Sun, 28 Sep 2014 19:55:22 +0000 (UTC) To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r272268 - user/marcel/mkimg X-SVN-Group: user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-user@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: "SVN commit messages for the experimental " user" src tree" <svn-src-user.freebsd.org> List-Unsubscribe: <http://lists.freebsd.org/mailman/options/svn-src-user>, <mailto:svn-src-user-request@freebsd.org?subject=unsubscribe> List-Archive: <http://lists.freebsd.org/pipermail/svn-src-user/> List-Post: <mailto:svn-src-user@freebsd.org> List-Help: <mailto:svn-src-user-request@freebsd.org?subject=help> List-Subscribe: <http://lists.freebsd.org/mailman/listinfo/svn-src-user>, <mailto:svn-src-user-request@freebsd.org?subject=subscribe> X-List-Received-Date: Sun, 28 Sep 2014 19:55:22 -0000 Author: marcel Date: Sun Sep 28 19:55:21 2014 New Revision: 272268 URL: http://svnweb.freebsd.org/changeset/base/272268 Log: When SEEK_HOLE and SEEK_DATA return -1, then the entire file is data. Set hole and data accordingly and before acting on them. While here: remove some debugging printfs; we're good so far. Modified: user/marcel/mkimg/image.c Modified: user/marcel/mkimg/image.c ============================================================================== --- user/marcel/mkimg/image.c Sun Sep 28 19:17:33 2014 (r272267) +++ user/marcel/mkimg/image.c Sun Sep 28 19:55:21 2014 (r272268) @@ -86,7 +86,6 @@ image_swap_alloc(size_t size) image_swap_size = ofs; ofs = -1LL; } - fprintf(stderr, "SWAP: off=%jd, size=%zu\n", (intmax_t)ofs, size); return (ofs); } @@ -338,17 +337,19 @@ image_copyin_mapped(lba_t blk, int fd, u hole = lseek(fd, cur, SEEK_HOLE); data = lseek(fd, cur, SEEK_DATA); - fprintf(stderr, "XXX: %s: cur=%jd, pos=%jd, hole=%jd, " - "data=%jd\n", __func__, (intmax_t)cur, (intmax_t)pos, - (intmax_t)hole, (intmax_t)data); + /* + * Treat the entire file as data if sparse files + * are not supported by the underlying file system. + */ + if (hole == -1 && data == -1) { + data = cur; + hole = end; + } if (cur == hole && data > hole) { hole = pos; pos = data & ~(secsz - 1); - fprintf(stderr, "GAP %jd-%jd\n", - (intmax_t)hole, (intmax_t)pos); - blk += (pos - hole) / secsz; error = image_chunk_skipto(blk); @@ -358,9 +359,6 @@ image_copyin_mapped(lba_t blk, int fd, u data = pos; pos = (hole + secsz - 1) & ~(secsz - 1); - fprintf(stderr, "DATA %jd-%jd data\n", - (intmax_t)data, (intmax_t)pos); - /* Sloppy... */ sz = pos - data; assert((off_t)sz == pos - data); From owner-svn-src-user@FreeBSD.ORG Mon Sep 29 16:24:49 2014 Return-Path: <owner-svn-src-user@FreeBSD.ORG> Delivered-To: svn-src-user@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 8B6A22FC; Mon, 29 Sep 2014 16:24:49 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 6C9AA125; Mon, 29 Sep 2014 16:24:49 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id s8TGOnXB005122; Mon, 29 Sep 2014 16:24:49 GMT (envelope-from marcel@FreeBSD.org) Received: (from marcel@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id s8TGOnPJ005121; Mon, 29 Sep 2014 16:24:49 GMT (envelope-from marcel@FreeBSD.org) Message-Id: <201409291624.s8TGOnPJ005121@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: marcel set sender to marcel@FreeBSD.org using -f From: Marcel Moolenaar <marcel@FreeBSD.org> Date: Mon, 29 Sep 2014 16:24:49 +0000 (UTC) To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r272283 - user/marcel/mkimg X-SVN-Group: user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-user@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: "SVN commit messages for the experimental " user" src tree" <svn-src-user.freebsd.org> List-Unsubscribe: <http://lists.freebsd.org/mailman/options/svn-src-user>, <mailto:svn-src-user-request@freebsd.org?subject=unsubscribe> List-Archive: <http://lists.freebsd.org/pipermail/svn-src-user/> List-Post: <mailto:svn-src-user@freebsd.org> List-Help: <mailto:svn-src-user-request@freebsd.org?subject=help> List-Subscribe: <http://lists.freebsd.org/mailman/listinfo/svn-src-user>, <mailto:svn-src-user-request@freebsd.org?subject=subscribe> X-List-Received-Date: Mon, 29 Sep 2014 16:24:49 -0000 Author: marcel Date: Mon Sep 29 16:24:48 2014 New Revision: 272283 URL: http://svnweb.freebsd.org/changeset/base/272283 Log: o In image_set_size(), don't truncate the swap file. It isn't holding the entire image data anymore. o Prepare for changes to image_write(): partitioning schemes call image_write() to fill in the sectors they reserved from themselves. Since we're talking about a handful of sectors, there's no need to have them in the swap file. Change struct chunk to accomodate for that. A chunk now has a type. That type can be "zeroes", "file" or "memory". o Flesh out the cleanup function: iterate over the chunks and close or free the corresponding data container. Free the chunk as well. Modified: user/marcel/mkimg/image.c Modified: user/marcel/mkimg/image.c ============================================================================== --- user/marcel/mkimg/image.c Mon Sep 29 15:05:23 2014 (r272282) +++ user/marcel/mkimg/image.c Mon Sep 29 16:24:48 2014 (r272283) @@ -45,14 +45,22 @@ __FBSDID("$FreeBSD$"); #include "mkimg.h" struct chunk { - lba_t ch_block; /* Block address in image. */ - off_t ch_ofs; /* Offset in backing file. */ STAILQ_ENTRY(chunk) ch_list; size_t ch_size; /* Size of chunk in bytes. */ - int ch_fd; /* FD of backing file. */ - u_int ch_flags; -#define CH_FLAGS_GAP 1 /* Chunk is a gap (no FD). */ -#define CH_FLAGS_DIRTY 2 /* Data modified/only in memory. */ + lba_t ch_block; /* Block address in image. */ + union { + struct { + off_t ofs; /* Offset in backing file. */ + int fd; /* FD of backing file. */ + } file; + struct { + void *ptr; /* Pointer to data in memory */ + } mem; + } ch_u; + u_int ch_type; +#define CH_TYPE_ZEROES 0 /* Chunk is a gap (no data). */ +#define CH_TYPE_FILE 1 /* File-backed chunk. */ +#define CH_TYPE_MEMORY 2 /* Memory-backed chunk */ }; static STAILQ_HEAD(chunk_head, chunk) image_chunks; @@ -100,9 +108,22 @@ image_chunk_dump(void) fprintf(stderr, "%u chunks:\n", image_nchunks); STAILQ_FOREACH(ch, &image_chunks, ch_list) { - fprintf(stderr, "\tblk=%jd, ofs=%jd, fd=%d, sz=%zu, fl=%u\n", - (intmax_t)ch->ch_block, (intmax_t)ch->ch_ofs, ch->ch_fd, - ch->ch_size, ch->ch_flags); + fprintf(stderr, "\tblk=%jd, sz=%zu, type=%u", + (intmax_t)ch->ch_block, ch->ch_size, ch->ch_type); + switch (ch->ch_type) { + case CH_TYPE_ZEROES: + fputc('\n', stderr); + break; + case CH_TYPE_FILE: + fprintf(stderr, "; ofs=%jd, fd=%d\n", + (intmax_t)ch->ch_u.file.ofs, ch->ch_u.file.fd); + break; + case CH_TYPE_MEMORY: + fprintf(stderr, "; ptr=%p\n", ch->ch_u.mem.ptr); + break; + default: + abort(); + } } } @@ -142,7 +163,7 @@ image_chunk_skipto(lba_t to) if ((uintmax_t)(to - from) > (uintmax_t)(SIZE_MAX / secsz)) return (EFBIG); sz = (to - from) * secsz; - if (ch != NULL && (ch->ch_flags & CH_FLAGS_GAP)) { + if (ch != NULL && ch->ch_type == CH_TYPE_ZEROES) { sz = image_chunk_grow(ch, sz); if (sz == 0) return (0); @@ -154,8 +175,7 @@ image_chunk_skipto(lba_t to) memset(ch, 0, sizeof(*ch)); ch->ch_block = from; ch->ch_size = sz; - ch->ch_fd = -1; - ch->ch_flags |= CH_FLAGS_GAP; + ch->ch_type = CH_TYPE_ZEROES; STAILQ_INSERT_TAIL(&image_chunks, ch, ch_list); image_nchunks++; return (0); @@ -167,15 +187,15 @@ image_chunk_append(lba_t blk, size_t sz, struct chunk *ch; ch = STAILQ_LAST(&image_chunks, chunk, ch_list); - if (ch != NULL && (ch->ch_flags & CH_FLAGS_GAP) == 0) { - if (fd == ch->ch_fd && + if (ch != NULL && ch->ch_type == CH_TYPE_FILE) { + if (fd == ch->ch_u.file.fd && blk == (lba_t)(ch->ch_block + (ch->ch_size / secsz)) && - ofs == (off_t)(ch->ch_ofs + ch->ch_size)) { + ofs == (off_t)(ch->ch_u.file.ofs + ch->ch_size)) { sz = image_chunk_grow(ch, sz); if (sz == 0) return (0); blk = ch->ch_block + (ch->ch_size / secsz); - ofs = ch->ch_ofs + ch->ch_size; + ofs = ch->ch_u.file.ofs + ch->ch_size; } } ch = malloc(sizeof(*ch)); @@ -183,9 +203,10 @@ image_chunk_append(lba_t blk, size_t sz, return (ENOMEM); memset(ch, 0, sizeof(*ch)); ch->ch_block = blk; - ch->ch_ofs = ofs; ch->ch_size = sz; - ch->ch_fd = fd; + ch->ch_type = CH_TYPE_FILE; + ch->ch_u.file.ofs = ofs; + ch->ch_u.file.fd = fd; STAILQ_INSERT_TAIL(&image_chunks, ch, ch_list); image_nchunks++; return (0); @@ -513,13 +534,12 @@ image_get_size(void) int image_set_size(lba_t blk) { + int error; - image_chunk_skipto(blk); - - image_size = blk; - if (ftruncate(image_swap_fd, blk * secsz) == -1) - return (errno); - return (0); + error = image_chunk_skipto(blk); + if (!error) + image_size = blk; + return (error); } int @@ -538,7 +558,24 @@ image_write(lba_t blk, void *buf, ssize_ static void image_cleanup(void) { + struct chunk *ch; + while ((ch = STAILQ_FIRST(&image_chunks)) != NULL) { + switch (ch->ch_type) { + case CH_TYPE_FILE: + /* We may be closing the same file multiple times. */ + if (ch->ch_u.file.fd != -1) + close(ch->ch_u.file.fd); + break; + case CH_TYPE_MEMORY: + free(ch->ch_u.mem.ptr); + break; + default: + break; + } + STAILQ_REMOVE_HEAD(&image_chunks, ch_list); + free(ch); + } if (image_swap_fd != -1) close(image_swap_fd); unlink(image_swap_file); From owner-svn-src-user@FreeBSD.ORG Tue Sep 30 23:16:03 2014 Return-Path: <owner-svn-src-user@FreeBSD.ORG> Delivered-To: svn-src-user@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id CEB03803; Tue, 30 Sep 2014 23:16:03 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id AF90625A; Tue, 30 Sep 2014 23:16:03 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id s8UNG3Bp082312; Tue, 30 Sep 2014 23:16:03 GMT (envelope-from marcel@FreeBSD.org) Received: (from marcel@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id s8UNG3rb082311; Tue, 30 Sep 2014 23:16:03 GMT (envelope-from marcel@FreeBSD.org) Message-Id: <201409302316.s8UNG3rb082311@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: marcel set sender to marcel@FreeBSD.org using -f From: Marcel Moolenaar <marcel@FreeBSD.org> Date: Tue, 30 Sep 2014 23:16:03 +0000 (UTC) To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r272335 - user/marcel/mkimg X-SVN-Group: user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-user@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: "SVN commit messages for the experimental " user" src tree" <svn-src-user.freebsd.org> List-Unsubscribe: <http://lists.freebsd.org/mailman/options/svn-src-user>, <mailto:svn-src-user-request@freebsd.org?subject=unsubscribe> List-Archive: <http://lists.freebsd.org/pipermail/svn-src-user/> List-Post: <mailto:svn-src-user@freebsd.org> List-Help: <mailto:svn-src-user-request@freebsd.org?subject=help> List-Subscribe: <http://lists.freebsd.org/mailman/listinfo/svn-src-user>, <mailto:svn-src-user-request@freebsd.org?subject=subscribe> X-List-Received-Date: Tue, 30 Sep 2014 23:16:03 -0000 Author: marcel Date: Tue Sep 30 23:16:03 2014 New Revision: 272335 URL: http://svnweb.freebsd.org/changeset/base/272335 Log: Implement image_write(): For every sector in the buffer, find the chunk that contains it and break it up (if it's not already a memory chunk) so that we have have a new chunk for every sector being written. We don't write to chunks for type file, because we may not be able to write and we don't want to clobber partition data. We don't try to combine adjacent chunks of type memory into a single one. It doesn't seem to have any significant upsides other than reducing syscall overhead. The downsides includes "excessive" copying and memory fragmantation. Without any kind of benchmarking, simplicity wins. Modified: user/marcel/mkimg/image.c Modified: user/marcel/mkimg/image.c ============================================================================== --- user/marcel/mkimg/image.c Tue Sep 30 23:01:11 2014 (r272334) +++ user/marcel/mkimg/image.c Tue Sep 30 23:16:03 2014 (r272335) @@ -73,6 +73,22 @@ static off_t image_swap_size; static lba_t image_size; +static int +is_empty_sector(void *buf) +{ + uint64_t *p = buf; + size_t n, max; + + assert(((uintptr_t)p & 3) == 0); + + max = secsz / sizeof(uint64_t); + for (n = 0; n < max; n++) { + if (p[n] != 0UL) + return (0); + } + return (1); +} + /* * Swap file handlng. */ @@ -102,11 +118,11 @@ image_swap_alloc(size_t size) */ static void -image_chunk_dump(void) +image_chunk_dump(int count) { struct chunk *ch; - fprintf(stderr, "%u chunks:\n", image_nchunks); + fprintf(stderr, "Dump %d: %u chunks:\n", count, image_nchunks); STAILQ_FOREACH(ch, &image_chunks, ch_list) { fprintf(stderr, "\tblk=%jd, sz=%zu, type=%u", (intmax_t)ch->ch_block, ch->ch_size, ch->ch_type); @@ -127,6 +143,25 @@ image_chunk_dump(void) } } +static struct chunk * +image_chunk_find(lba_t blk) +{ + static struct chunk *last = NULL; + struct chunk *ch; + + ch = (last != NULL && last->ch_block <= blk) + ? last : STAILQ_FIRST(&image_chunks); + while (ch != NULL) { + if (ch->ch_block <= blk && + (lba_t)(ch->ch_block + (ch->ch_size / secsz)) > blk) { + last = ch; + break; + } + ch = STAILQ_NEXT(ch, ch_list); + } + return (ch); +} + static size_t image_chunk_grow(struct chunk *ch, size_t sz) { @@ -144,6 +179,50 @@ image_chunk_grow(struct chunk *ch, size_ return (sz - dsz); } +static struct chunk * +image_chunk_memory(struct chunk *ch, lba_t blk) +{ + struct chunk *new; + void *ptr; + + ptr = calloc(1, secsz); + if (ptr == NULL) + return (NULL); + + if (ch->ch_block < blk) { + new = malloc(sizeof(*new)); + if (new == NULL) { + free(ptr); + return (NULL); + } + memcpy(new, ch, sizeof(*new)); + ch->ch_size = (blk - ch->ch_block) * secsz; + new->ch_block = blk; + new->ch_size -= ch->ch_size; + STAILQ_INSERT_AFTER(&image_chunks, ch, new, ch_list); + image_nchunks++; + ch = new; + } + + if (ch->ch_size > secsz) { + new = malloc(sizeof(*new)); + if (new == NULL) { + free(ptr); + return (NULL); + } + memcpy(new, ch, sizeof(*new)); + ch->ch_size = secsz; + new->ch_block++; + new->ch_size -= secsz; + STAILQ_INSERT_AFTER(&image_chunks, ch, new, ch_list); + image_nchunks++; + } + + ch->ch_type = CH_TYPE_MEMORY; + ch->ch_u.mem.ptr = ptr; + return (ch); +} + static int image_chunk_skipto(lba_t to) { @@ -215,24 +294,18 @@ image_chunk_append(lba_t blk, size_t sz, static int image_chunk_copyin(lba_t blk, void *buf, size_t sz, off_t ofs, int fd) { - uint64_t *p = buf; - size_t n; + uint8_t *p = buf; int error; - assert(((uintptr_t)p & 3) == 0); - error = 0; sz = (sz + secsz - 1) & ~(secsz - 1); while (!error && sz > 0) { - n = 0; - while (n < (secsz >> 3) && p[n] == 0) - n++; - if (n == (secsz >> 3)) + if (is_empty_sector(p)) error = image_chunk_skipto(blk + 1); else error = image_chunk_append(blk, secsz, ofs, fd); blk++; - p += (secsz >> 3); + p += secsz; sz -= secsz; ofs += secsz; } @@ -522,12 +595,9 @@ image_data(lba_t blk, lba_t size) lba_t image_get_size(void) { - static int once = 0; + static int count = 0; - if (once == 0) { - once++; - image_chunk_dump(); - } + image_chunk_dump(count++); return (image_size); } @@ -545,13 +615,28 @@ image_set_size(lba_t blk) int image_write(lba_t blk, void *buf, ssize_t len) { + struct chunk *ch; - blk *= secsz; - if (lseek(image_swap_fd, blk, SEEK_SET) != blk) - return (errno); - len *= secsz; - if (sparse_write(image_swap_fd, buf, len) != len) - return (errno); + while (len > 0) { + if (!is_empty_sector(buf)) { + ch = image_chunk_find(blk); + if (ch == NULL) + return (ENXIO); + /* We may not be able to write to files. */ + if (ch->ch_type == CH_TYPE_FILE) + return (EINVAL); + if (ch->ch_type == CH_TYPE_ZEROES) { + ch = image_chunk_memory(ch, blk); + if (ch == NULL) + return (ENOMEM); + } + assert(ch->ch_type == CH_TYPE_MEMORY); + memcpy(ch->ch_u.mem.ptr, buf, secsz); + } + blk++; + buf = (char *)buf + secsz; + len--; + } return (0); } From owner-svn-src-user@FreeBSD.ORG Tue Sep 30 23:29:07 2014 Return-Path: <owner-svn-src-user@FreeBSD.ORG> Delivered-To: svn-src-user@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id A70FEB59; Tue, 30 Sep 2014 23:29:07 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 93CF33A1; Tue, 30 Sep 2014 23:29:07 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id s8UNT78O087312; Tue, 30 Sep 2014 23:29:07 GMT (envelope-from marcel@FreeBSD.org) Received: (from marcel@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id s8UNT7tn087311; Tue, 30 Sep 2014 23:29:07 GMT (envelope-from marcel@FreeBSD.org) Message-Id: <201409302329.s8UNT7tn087311@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: marcel set sender to marcel@FreeBSD.org using -f From: Marcel Moolenaar <marcel@FreeBSD.org> Date: Tue, 30 Sep 2014 23:29:07 +0000 (UTC) To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r272337 - user/marcel/mkimg X-SVN-Group: user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-user@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: "SVN commit messages for the experimental " user" src tree" <svn-src-user.freebsd.org> List-Unsubscribe: <http://lists.freebsd.org/mailman/options/svn-src-user>, <mailto:svn-src-user-request@freebsd.org?subject=unsubscribe> List-Archive: <http://lists.freebsd.org/pipermail/svn-src-user/> List-Post: <mailto:svn-src-user@freebsd.org> List-Help: <mailto:svn-src-user-request@freebsd.org?subject=help> List-Subscribe: <http://lists.freebsd.org/mailman/listinfo/svn-src-user>, <mailto:svn-src-user-request@freebsd.org?subject=subscribe> X-List-Received-Date: Tue, 30 Sep 2014 23:29:07 -0000 Author: marcel Date: Tue Sep 30 23:29:06 2014 New Revision: 272337 URL: http://svnweb.freebsd.org/changeset/base/272337 Log: Implement image_data(): we now simply call image_chunk_find() to get the chunk that contains the block and we effectively have the answer right away. Account for the as-of-yet non-existent case of having multiple chunks of type zeroes adjacent to each other and having to handle chunk-crossing -- hence the loop. Modified: user/marcel/mkimg/image.c Modified: user/marcel/mkimg/image.c ============================================================================== --- user/marcel/mkimg/image.c Tue Sep 30 23:16:26 2014 (r272336) +++ user/marcel/mkimg/image.c Tue Sep 30 23:29:06 2014 (r272337) @@ -568,28 +568,22 @@ image_copyout_region(int fd, lba_t blk, int image_data(lba_t blk, lba_t size) { - char *buffer, *p; + struct chunk *ch; + lba_t lim; - blk *= secsz; - if (lseek(image_swap_fd, blk, SEEK_SET) != blk) - return (1); - - size *= secsz; - buffer = malloc(size); - if (buffer == NULL) - return (1); - - if (read(image_swap_fd, buffer, size) != (ssize_t)size) { - free(buffer); - return (1); + while (1) { + ch = image_chunk_find(blk); + if (ch == NULL) + return (0); + if (ch->ch_type != CH_TYPE_ZEROES) + return (1); + lim = ch->ch_block + (ch->ch_size / secsz); + if (lim >= blk + size) + return (0); + size -= lim - blk; + blk = lim; } - - p = buffer; - while (size > 0 && *p == '\0') - size--, p++; - - free(buffer); - return ((size == 0) ? 0 : 1); + /*NOTREACHED*/ } lba_t From owner-svn-src-user@FreeBSD.ORG Wed Oct 1 01:18:26 2014 Return-Path: <owner-svn-src-user@FreeBSD.ORG> Delivered-To: svn-src-user@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 2087FD2F; Wed, 1 Oct 2014 01:18:26 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 0D883FFD; Wed, 1 Oct 2014 01:18:26 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id s911IPCn039777; Wed, 1 Oct 2014 01:18:25 GMT (envelope-from marcel@FreeBSD.org) Received: (from marcel@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id s911IPb0039776; Wed, 1 Oct 2014 01:18:25 GMT (envelope-from marcel@FreeBSD.org) Message-Id: <201410010118.s911IPb0039776@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: marcel set sender to marcel@FreeBSD.org using -f From: Marcel Moolenaar <marcel@FreeBSD.org> Date: Wed, 1 Oct 2014 01:18:25 +0000 (UTC) To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r272338 - user/marcel/mkimg X-SVN-Group: user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-user@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: "SVN commit messages for the experimental " user" src tree" <svn-src-user.freebsd.org> List-Unsubscribe: <http://lists.freebsd.org/mailman/options/svn-src-user>, <mailto:svn-src-user-request@freebsd.org?subject=unsubscribe> List-Archive: <http://lists.freebsd.org/pipermail/svn-src-user/> List-Post: <mailto:svn-src-user@freebsd.org> List-Help: <mailto:svn-src-user-request@freebsd.org?subject=help> List-Subscribe: <http://lists.freebsd.org/mailman/listinfo/svn-src-user>, <mailto:svn-src-user-request@freebsd.org?subject=subscribe> X-List-Received-Date: Wed, 01 Oct 2014 01:18:26 -0000 Author: marcel Date: Wed Oct 1 01:18:25 2014 New Revision: 272338 URL: http://svnweb.freebsd.org/changeset/base/272338 Log: Implement image_copyout_region(): This is the one function that is responsible for writing to the output file. For eack chunk that covers all or parts of the region to write, call a corresponding function that knows how to write a chunk of that type: image_copyout_memory(): Use write(2) to write the buffer. image_copyout_zeroes(): Try and seek forward to create a sparse file. If that fails, scribble zeroes to the output file to support writing to stdout. Use image_copyout_memoryIO for that. image_copyout_file(): Iteratively map bits of the input file and use image_copyout_memory() to write the bits to the output file. With this commit all unit tests pass again. Modified: user/marcel/mkimg/image.c Modified: user/marcel/mkimg/image.c ============================================================================== --- user/marcel/mkimg/image.c Tue Sep 30 23:29:06 2014 (r272337) +++ user/marcel/mkimg/image.c Wed Oct 1 01:18:25 2014 (r272338) @@ -499,6 +499,10 @@ image_copyin(lba_t blk, int fd, uint64_t return (error); } +/* + * Output/sink file handling. + */ + int image_copyout(int fd) { @@ -523,46 +527,103 @@ image_copyout_done(int fd) return (error); } -int -image_copyout_region(int fd, lba_t blk, lba_t size) +static int +image_copyout_memory(int fd, size_t size, void *ptr) { - char *buffer; - off_t ofs; - size_t bufsz, sz; - ssize_t rdsz, wrsz; + + if (write(fd, ptr, size) == -1) + return (errno); + return (0); +} + +static int +image_copyout_zeroes(int fd, size_t size) +{ + static uint8_t *zeroes = NULL; + size_t sz; int error; - bufsz = secsz * image_swap_pgsz; + if (lseek(fd, (off_t)size, SEEK_CUR) != -1) + return (0); - ofs = lseek(fd, 0L, SEEK_CUR); + /* + * If we can't seek, we must write. + */ + + if (zeroes == NULL) { + zeroes = calloc(1, secsz); + if (zeroes == NULL) + return (ENOMEM); + } + + while (size > 0) { + sz = (size > secsz) ? secsz : size; + error = image_copyout_memory(fd, sz, zeroes); + if (error) + return (error); + size -= sz; + } + return (0); +} + +static int +image_copyout_file(int fd, size_t size, int ifd, off_t iofs) +{ + void *buf; + size_t iosz, sz; + int error; + + iosz = secsz * image_swap_pgsz; + + while (size > 0) { + sz = (size > iosz) ? iosz : size; + buf = image_file_map(ifd, iofs, sz); + if (buf == NULL) + return (errno); + error = image_copyout_memory(fd, sz, buf); + image_file_unmap(buf, sz); + if (error) + return (error); + size -= sz; + iofs += sz; + } + return (0); +} + +int +image_copyout_region(int fd, lba_t blk, lba_t size) +{ + struct chunk *ch; + size_t ofs, sz; + int error; - blk *= secsz; - if (lseek(image_swap_fd, blk, SEEK_SET) != blk) - return (errno); - buffer = malloc(bufsz); - if (buffer == NULL) - return (errno); - error = 0; size *= secsz; + while (size > 0) { - sz = ((ssize_t)bufsz < size) ? bufsz : (size_t)size; - rdsz = read(image_swap_fd, buffer, sz); - if (rdsz <= 0) { - error = (rdsz < 0) ? errno : 0; + ch = image_chunk_find(blk); + if (ch == NULL) + return (EINVAL); + ofs = (blk - ch->ch_block) * secsz; + sz = ch->ch_size - ofs; + sz = ((lba_t)sz < size) ? sz : (size_t)size; + switch (ch->ch_type) { + case CH_TYPE_ZEROES: + error = image_copyout_zeroes(fd, sz); break; - } - wrsz = (ofs == -1) ? - write(fd, buffer, rdsz) : - sparse_write(fd, buffer, rdsz); - if (wrsz < 0) { - error = errno; + case CH_TYPE_FILE: + error = image_copyout_file(fd, sz, ch->ch_u.file.fd, + ch->ch_u.file.ofs + ofs); break; + case CH_TYPE_MEMORY: + error = image_copyout_memory(fd, sz, ch->ch_u.mem.ptr); + break; + default: + return (EDOOFUS); } - assert(wrsz == rdsz); - size -= rdsz; + size -= sz; + blk += sz / secsz; } - free(buffer); - return (error); + return (0); } int From owner-svn-src-user@FreeBSD.ORG Wed Oct 1 01:50:24 2014 Return-Path: <owner-svn-src-user@FreeBSD.ORG> Delivered-To: svn-src-user@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 9385C528; Wed, 1 Oct 2014 01:50:24 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 8033E3EC; Wed, 1 Oct 2014 01:50:24 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id s911oOK8056243; Wed, 1 Oct 2014 01:50:24 GMT (envelope-from marcel@FreeBSD.org) Received: (from marcel@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id s911oO1g056242; Wed, 1 Oct 2014 01:50:24 GMT (envelope-from marcel@FreeBSD.org) Message-Id: <201410010150.s911oO1g056242@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: marcel set sender to marcel@FreeBSD.org using -f From: Marcel Moolenaar <marcel@FreeBSD.org> Date: Wed, 1 Oct 2014 01:50:24 +0000 (UTC) To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r272339 - user/marcel/mkimg X-SVN-Group: user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-user@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: "SVN commit messages for the experimental " user" src tree" <svn-src-user.freebsd.org> List-Unsubscribe: <http://lists.freebsd.org/mailman/options/svn-src-user>, <mailto:svn-src-user-request@freebsd.org?subject=unsubscribe> List-Archive: <http://lists.freebsd.org/pipermail/svn-src-user/> List-Post: <mailto:svn-src-user@freebsd.org> List-Help: <mailto:svn-src-user-request@freebsd.org?subject=help> List-Subscribe: <http://lists.freebsd.org/mailman/listinfo/svn-src-user>, <mailto:svn-src-user-request@freebsd.org?subject=subscribe> X-List-Received-Date: Wed, 01 Oct 2014 01:50:24 -0000 Author: marcel Date: Wed Oct 1 01:50:23 2014 New Revision: 272339 URL: http://svnweb.freebsd.org/changeset/base/272339 Log: Remove image_chunk_dump() and its call-site. I used it for debugging in the beginning, but not at the end. So, its value is marginal. Below a performance comparison while running the unit test: x old + new N Min Max Median Avg Stddev x 5 57.48 58.28 57.58 57.736 0.33886576 + 5 46.82 47.61 46.93 47.034 0.32791767 Difference at 95.0% confidence -10.702 +/- 0.486298 -18.5361% +/- 0.842279% (Student's t, pooled s = 0.333437) Modified: user/marcel/mkimg/image.c Modified: user/marcel/mkimg/image.c ============================================================================== --- user/marcel/mkimg/image.c Wed Oct 1 01:18:25 2014 (r272338) +++ user/marcel/mkimg/image.c Wed Oct 1 01:50:23 2014 (r272339) @@ -117,32 +117,6 @@ image_swap_alloc(size_t size) * Image chunk handling. */ -static void -image_chunk_dump(int count) -{ - struct chunk *ch; - - fprintf(stderr, "Dump %d: %u chunks:\n", count, image_nchunks); - STAILQ_FOREACH(ch, &image_chunks, ch_list) { - fprintf(stderr, "\tblk=%jd, sz=%zu, type=%u", - (intmax_t)ch->ch_block, ch->ch_size, ch->ch_type); - switch (ch->ch_type) { - case CH_TYPE_ZEROES: - fputc('\n', stderr); - break; - case CH_TYPE_FILE: - fprintf(stderr, "; ofs=%jd, fd=%d\n", - (intmax_t)ch->ch_u.file.ofs, ch->ch_u.file.fd); - break; - case CH_TYPE_MEMORY: - fprintf(stderr, "; ptr=%p\n", ch->ch_u.mem.ptr); - break; - default: - abort(); - } - } -} - static struct chunk * image_chunk_find(lba_t blk) { @@ -650,9 +624,7 @@ image_data(lba_t blk, lba_t size) lba_t image_get_size(void) { - static int count = 0; - image_chunk_dump(count++); return (image_size); } From owner-svn-src-user@FreeBSD.ORG Wed Oct 1 15:22:12 2014 Return-Path: <owner-svn-src-user@FreeBSD.ORG> Delivered-To: svn-src-user@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 66BE3667; Wed, 1 Oct 2014 15:22:12 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 5406A7A9; Wed, 1 Oct 2014 15:22:12 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id s91FMCBp046079; Wed, 1 Oct 2014 15:22:12 GMT (envelope-from marcel@FreeBSD.org) Received: (from marcel@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id s91FMCmG046078; Wed, 1 Oct 2014 15:22:12 GMT (envelope-from marcel@FreeBSD.org) Message-Id: <201410011522.s91FMCmG046078@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: marcel set sender to marcel@FreeBSD.org using -f From: Marcel Moolenaar <marcel@FreeBSD.org> Date: Wed, 1 Oct 2014 15:22:12 +0000 (UTC) To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r272364 - user/marcel/mkimg X-SVN-Group: user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-user@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: "SVN commit messages for the experimental " user" src tree" <svn-src-user.freebsd.org> List-Unsubscribe: <http://lists.freebsd.org/mailman/options/svn-src-user>, <mailto:svn-src-user-request@freebsd.org?subject=unsubscribe> List-Archive: <http://lists.freebsd.org/pipermail/svn-src-user/> List-Post: <mailto:svn-src-user@freebsd.org> List-Help: <mailto:svn-src-user-request@freebsd.org?subject=help> List-Subscribe: <http://lists.freebsd.org/mailman/listinfo/svn-src-user>, <mailto:svn-src-user-request@freebsd.org?subject=subscribe> X-List-Received-Date: Wed, 01 Oct 2014 15:22:12 -0000 Author: marcel Date: Wed Oct 1 15:22:11 2014 New Revision: 272364 URL: https://svnweb.freebsd.org/changeset/base/272364 Log: Remove DEBUG_FLAGS again. Modified: user/marcel/mkimg/Makefile Modified: user/marcel/mkimg/Makefile ============================================================================== --- user/marcel/mkimg/Makefile Wed Oct 1 15:02:37 2014 (r272363) +++ user/marcel/mkimg/Makefile Wed Oct 1 15:22:11 2014 (r272364) @@ -10,8 +10,6 @@ MKIMG_VERSION=20140927 CFLAGS+=-DMKIMG_VERSION=${MKIMG_VERSION} CFLAGS+=-DSPARSE_WRITE -DEBUG_FLAGS=-O0 -gdwarf-2 - # List of formats to support SRCS+= \ qcow.c \ From owner-svn-src-user@FreeBSD.ORG Wed Oct 1 15:23:23 2014 Return-Path: <owner-svn-src-user@FreeBSD.ORG> Delivered-To: svn-src-user@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id EEC3A7FF; Wed, 1 Oct 2014 15:23:23 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id DC46B7C0; Wed, 1 Oct 2014 15:23:23 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id s91FNNdO046286; Wed, 1 Oct 2014 15:23:23 GMT (envelope-from marcel@FreeBSD.org) Received: (from marcel@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id s91FNNDl046285; Wed, 1 Oct 2014 15:23:23 GMT (envelope-from marcel@FreeBSD.org) Message-Id: <201410011523.s91FNNDl046285@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: marcel set sender to marcel@FreeBSD.org using -f From: Marcel Moolenaar <marcel@FreeBSD.org> Date: Wed, 1 Oct 2014 15:23:23 +0000 (UTC) To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r272365 - user/marcel/mkimg X-SVN-Group: user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-user@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: "SVN commit messages for the experimental " user" src tree" <svn-src-user.freebsd.org> List-Unsubscribe: <http://lists.freebsd.org/mailman/options/svn-src-user>, <mailto:svn-src-user-request@freebsd.org?subject=unsubscribe> List-Archive: <http://lists.freebsd.org/pipermail/svn-src-user/> List-Post: <mailto:svn-src-user@freebsd.org> List-Help: <mailto:svn-src-user-request@freebsd.org?subject=help> List-Subscribe: <http://lists.freebsd.org/mailman/listinfo/svn-src-user>, <mailto:svn-src-user-request@freebsd.org?subject=subscribe> X-List-Received-Date: Wed, 01 Oct 2014 15:23:24 -0000 Author: marcel Date: Wed Oct 1 15:23:23 2014 New Revision: 272365 URL: https://svnweb.freebsd.org/changeset/base/272365 Log: Bump the version to 20141001. Modified: user/marcel/mkimg/Makefile Modified: user/marcel/mkimg/Makefile ============================================================================== --- user/marcel/mkimg/Makefile Wed Oct 1 15:22:11 2014 (r272364) +++ user/marcel/mkimg/Makefile Wed Oct 1 15:23:23 2014 (r272365) @@ -6,7 +6,7 @@ PROG= mkimg SRCS= format.c image.c mkimg.c scheme.c MAN= mkimg.1 -MKIMG_VERSION=20140927 +MKIMG_VERSION=20141001 CFLAGS+=-DMKIMG_VERSION=${MKIMG_VERSION} CFLAGS+=-DSPARSE_WRITE From owner-svn-src-user@FreeBSD.ORG Wed Oct 1 16:09:12 2014 Return-Path: <owner-svn-src-user@FreeBSD.ORG> Delivered-To: svn-src-user@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 69A3EB3; Wed, 1 Oct 2014 16:09:12 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 568EFDEE; Wed, 1 Oct 2014 16:09:12 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id s91G9CW9066527; Wed, 1 Oct 2014 16:09:12 GMT (envelope-from marcel@FreeBSD.org) Received: (from marcel@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id s91G9CkA066526; Wed, 1 Oct 2014 16:09:12 GMT (envelope-from marcel@FreeBSD.org) Message-Id: <201410011609.s91G9CkA066526@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: marcel set sender to marcel@FreeBSD.org using -f From: Marcel Moolenaar <marcel@FreeBSD.org> Date: Wed, 1 Oct 2014 16:09:12 +0000 (UTC) To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r272370 - user/marcel/mkimg X-SVN-Group: user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-user@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: "SVN commit messages for the experimental " user" src tree" <svn-src-user.freebsd.org> List-Unsubscribe: <http://lists.freebsd.org/mailman/options/svn-src-user>, <mailto:svn-src-user-request@freebsd.org?subject=unsubscribe> List-Archive: <http://lists.freebsd.org/pipermail/svn-src-user/> List-Post: <mailto:svn-src-user@freebsd.org> List-Help: <mailto:svn-src-user-request@freebsd.org?subject=help> List-Subscribe: <http://lists.freebsd.org/mailman/listinfo/svn-src-user>, <mailto:svn-src-user-request@freebsd.org?subject=subscribe> X-List-Received-Date: Wed, 01 Oct 2014 16:09:12 -0000 Author: marcel Date: Wed Oct 1 16:09:11 2014 New Revision: 272370 URL: https://svnweb.freebsd.org/changeset/base/272370 Log: Fix sloppy code (that was commented as such): Map the file with partition data using smaller pieces at at time. It's rather hard to map a 10G partition in memory on a 32-bit machine... Modified: user/marcel/mkimg/image.c Modified: user/marcel/mkimg/image.c ============================================================================== --- user/marcel/mkimg/image.c Wed Oct 1 16:08:19 2014 (r272369) +++ user/marcel/mkimg/image.c Wed Oct 1 16:09:11 2014 (r272370) @@ -377,7 +377,7 @@ image_copyin_mapped(lba_t blk, int fd, u off_t cur, data, end, hole, pos; void *buf; uint64_t bytesize; - size_t sz; + size_t iosz, sz; int error; /* @@ -398,6 +398,8 @@ image_copyin_mapped(lba_t blk, int fd, u if (fd == -1) return (errno); + iosz = secsz * image_swap_pgsz; + bytesize = 0; cur = pos = 0; error = 0; @@ -427,19 +429,22 @@ image_copyin_mapped(lba_t blk, int fd, u data = pos; pos = (hole + secsz - 1) & ~(secsz - 1); - /* Sloppy... */ - sz = pos - data; - assert((off_t)sz == pos - data); - - buf = image_file_map(fd, data, sz); - if (buf != NULL) { - error = image_chunk_copyin(blk, buf, sz, - data, fd); - image_file_unmap(buf, sz); - } else - error = errno; - blk += sz / secsz; - bytesize += sz; + while (data < pos) { + sz = (pos - data > (off_t)iosz) + ? iosz : (size_t)(pos - data); + + buf = image_file_map(fd, data, sz); + if (buf != NULL) { + error = image_chunk_copyin(blk, buf, + sz, data, fd); + image_file_unmap(buf, sz); + } else + error = errno; + + blk += sz / secsz; + bytesize += sz; + data += sz; + } cur = hole; } else { /* From owner-svn-src-user@FreeBSD.ORG Wed Oct 1 16:47:14 2014 Return-Path: <owner-svn-src-user@FreeBSD.ORG> Delivered-To: svn-src-user@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id D92C6F72; Wed, 1 Oct 2014 16:47:14 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id C66202C9; Wed, 1 Oct 2014 16:47:14 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id s91GlECg085124; Wed, 1 Oct 2014 16:47:14 GMT (envelope-from marcel@FreeBSD.org) Received: (from marcel@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id s91GlE1C085123; Wed, 1 Oct 2014 16:47:14 GMT (envelope-from marcel@FreeBSD.org) Message-Id: <201410011647.s91GlE1C085123@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: marcel set sender to marcel@FreeBSD.org using -f From: Marcel Moolenaar <marcel@FreeBSD.org> Date: Wed, 1 Oct 2014 16:47:14 +0000 (UTC) To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r272374 - user/marcel/mkimg X-SVN-Group: user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-user@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: "SVN commit messages for the experimental " user" src tree" <svn-src-user.freebsd.org> List-Unsubscribe: <http://lists.freebsd.org/mailman/options/svn-src-user>, <mailto:svn-src-user-request@freebsd.org?subject=unsubscribe> List-Archive: <http://lists.freebsd.org/pipermail/svn-src-user/> List-Post: <mailto:svn-src-user@freebsd.org> List-Help: <mailto:svn-src-user-request@freebsd.org?subject=help> List-Subscribe: <http://lists.freebsd.org/mailman/listinfo/svn-src-user>, <mailto:svn-src-user-request@freebsd.org?subject=subscribe> X-List-Received-Date: Wed, 01 Oct 2014 16:47:14 -0000 Author: marcel Date: Wed Oct 1 16:47:14 2014 New Revision: 272374 URL: https://svnweb.freebsd.org/changeset/base/272374 Log: Make sure to widen secsz from size_t to off_t when using it as a mask. On 32-bit machines this would other wise mask off the upper 32-bits of the 64-bit file offset. Modified: user/marcel/mkimg/image.c Modified: user/marcel/mkimg/image.c ============================================================================== --- user/marcel/mkimg/image.c Wed Oct 1 16:18:59 2014 (r272373) +++ user/marcel/mkimg/image.c Wed Oct 1 16:47:14 2014 (r272374) @@ -418,7 +418,7 @@ image_copyin_mapped(lba_t blk, int fd, u if (cur == hole && data > hole) { hole = pos; - pos = data & ~(secsz - 1); + pos = data & ~((uint64_t)secsz - 1); blk += (pos - hole) / secsz; error = image_chunk_skipto(blk); @@ -427,7 +427,7 @@ image_copyin_mapped(lba_t blk, int fd, u cur = data; } else if (cur == data && hole > data) { data = pos; - pos = (hole + secsz - 1) & ~(secsz - 1); + pos = (hole + secsz - 1) & ~((uint64_t)secsz - 1); while (data < pos) { sz = (pos - data > (off_t)iosz) From owner-svn-src-user@FreeBSD.ORG Wed Oct 1 16:48:55 2014 Return-Path: <owner-svn-src-user@FreeBSD.ORG> Delivered-To: svn-src-user@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 94E2E102; Wed, 1 Oct 2014 16:48:55 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 820312E1; Wed, 1 Oct 2014 16:48:55 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id s91GmtGa085372; Wed, 1 Oct 2014 16:48:55 GMT (envelope-from marcel@FreeBSD.org) Received: (from marcel@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id s91Gmtsj085371; Wed, 1 Oct 2014 16:48:55 GMT (envelope-from marcel@FreeBSD.org) Message-Id: <201410011648.s91Gmtsj085371@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: marcel set sender to marcel@FreeBSD.org using -f From: Marcel Moolenaar <marcel@FreeBSD.org> Date: Wed, 1 Oct 2014 16:48:55 +0000 (UTC) To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r272375 - user/marcel/mkimg X-SVN-Group: user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-user@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: "SVN commit messages for the experimental " user" src tree" <svn-src-user.freebsd.org> List-Unsubscribe: <http://lists.freebsd.org/mailman/options/svn-src-user>, <mailto:svn-src-user-request@freebsd.org?subject=unsubscribe> List-Archive: <http://lists.freebsd.org/pipermail/svn-src-user/> List-Post: <mailto:svn-src-user@freebsd.org> List-Help: <mailto:svn-src-user-request@freebsd.org?subject=help> List-Subscribe: <http://lists.freebsd.org/mailman/listinfo/svn-src-user>, <mailto:svn-src-user-request@freebsd.org?subject=subscribe> X-List-Received-Date: Wed, 01 Oct 2014 16:48:55 -0000 Author: marcel Date: Wed Oct 1 16:48:54 2014 New Revision: 272375 URL: https://svnweb.freebsd.org/changeset/base/272375 Log: Make sure the cookies are constants of appropriate width. Modified: user/marcel/mkimg/vhd.c Modified: user/marcel/mkimg/vhd.c ============================================================================== --- user/marcel/mkimg/vhd.c Wed Oct 1 16:47:14 2014 (r272374) +++ user/marcel/mkimg/vhd.c Wed Oct 1 16:48:54 2014 (r272375) @@ -64,7 +64,7 @@ __FBSDID("$FreeBSD$"); struct vhd_footer { uint64_t cookie; -#define VHD_FOOTER_COOKIE 0x636f6e6563746978 +#define VHD_FOOTER_COOKIE 0x636f6e6563746978ULL uint32_t features; #define VHD_FEATURES_TEMPORARY 0x01 #define VHD_FEATURES_RESERVED 0x02 @@ -236,7 +236,7 @@ vhd_resize(lba_t imgsz) struct vhd_dyn_header { uint64_t cookie; -#define VHD_HEADER_COOKIE 0x6378737061727365 +#define VHD_HEADER_COOKIE 0x6378737061727365ULL uint64_t data_offset; uint64_t table_offset; uint32_t version;