From owner-svn-src-all@FreeBSD.ORG Wed Sep 24 22:45:03 2014 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id D1B51F11; Wed, 24 Sep 2014 22:45: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 B250B884; Wed, 24 Sep 2014 22:45: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 s8OMj3eZ052504; Wed, 24 Sep 2014 22:45:03 GMT (envelope-from marcel@FreeBSD.org) Received: (from marcel@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id s8OMj3p3052503; Wed, 24 Sep 2014 22:45:03 GMT (envelope-from marcel@FreeBSD.org) Message-Id: <201409242245.s8OMj3p3052503@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: marcel set sender to marcel@FreeBSD.org using -f From: Marcel Moolenaar Date: Wed, 24 Sep 2014 22:45:03 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r272086 - head/usr.bin/mkimg X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 24 Sep 2014 22:45:04 -0000 Author: marcel Date: Wed Sep 24 22:45:03 2014 New Revision: 272086 URL: http://svnweb.freebsd.org/changeset/base/272086 Log: Finish QCOW version 2 and stop making it conditional. We have a different ordering for the RC block(s) and L2 tables. This is expected to be a non-issue, because everything is found through file offsets in the corresponding RC table and L1 table. Files that grow organically have RC blocks and L2 tables scattered all over the place anyway. The reason for the difference is that mkimg needs to be able to write to a pipe. We can't seek forward and backward to fill in the bits in non-sequential order. Modified: head/usr.bin/mkimg/qcow.c Modified: head/usr.bin/mkimg/qcow.c ============================================================================== --- head/usr.bin/mkimg/qcow.c Wed Sep 24 22:31:40 2014 (r272085) +++ head/usr.bin/mkimg/qcow.c Wed Sep 24 22:45:03 2014 (r272086) @@ -40,8 +40,6 @@ __FBSDID("$FreeBSD$"); #include "format.h" #include "mkimg.h" -#undef QCOW_SUPPORT_QCOW2 - /* Default cluster sizes. */ #define QCOW1_CLSTR_LOG2SZ 12 /* 4KB */ #define QCOW2_CLSTR_LOG2SZ 16 /* 64KB */ @@ -123,21 +121,19 @@ qcow1_resize(lba_t imgsz) return (qcow_resize(imgsz, QCOW_VERSION_1)); } -#ifdef QCOW_SUPPORT_QCOW2 static int qcow2_resize(lba_t imgsz) { return (qcow_resize(imgsz, QCOW_VERSION_2)); } -#endif static int qcow_write(int fd, u_int version) { struct qcow_header *hdr; - uint64_t *l1tbl, *l2tbl; - uint16_t *rctbl; + 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; @@ -170,13 +166,15 @@ qcow_write(int fd, u_int version) * 0 - header * 1 - L1 table * 2 - RC table (v2 only) - * 3 - First RC block (v2 only) - * 4 - L2 tables - * n - data + * 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) @@ -196,7 +194,7 @@ qcow_write(int fd, u_int version) case QCOW_VERSION_2: ofsflags = QCOW_CLSTR_COPIED; rcclno = l1clno + clstr_l1tblsz; - l2clno = rcclno + clstr_rctblsz + 1; + 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); @@ -207,52 +205,62 @@ qcow_write(int fd, u_int version) return (EDOOFUS); } - l2tbl = l1tbl = NULL; - rctbl = NULL; + 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; } - if (rcclno > 0) { - rctbl = calloc(1, clstrsz * clstr_rctblsz); - if (rctbl == NULL) { - error = ENOMEM; - goto out; - } - } - ofs = clstrsz * l2clno; for (n = 0; n < clstr_imgsz; n++) { - l1idx = n >> (clstr_log2sz - 3); - if (l1tbl[l1idx] != 0UL) - continue; blk = n * blk_clstrsz; if (image_data(blk, blk_clstrsz)) { - be64enc(l1tbl + l1idx, ofs + ofsflags); - ofs += clstrsz; + nclstrs++; + l1idx = n >> (clstr_log2sz - 3); + if (l1tbl[l1idx] == 0) { + be64enc(l1tbl + l1idx, ofs + ofsflags); + ofs += clstrsz; + nclstrs++; + } } } - error = 0; - if (!error && sparse_write(fd, hdr, clstrsz) < 0) - error = errno; - if (!error && sparse_write(fd, l1tbl, clstrsz * clstr_l1tblsz) < 0) + if (sparse_write(fd, l1tbl, clstrsz * clstr_l1tblsz) < 0) { error = errno; - if (rcclno > 0) { - if (!error && - sparse_write(fd, rctbl, clstrsz * clstr_rctblsz) < 0) - error = errno; - if (!error && sparse_write(fd, rctbl, clstrsz) < 0) - error = errno; - } - if (error) goto out; + } - free(hdr); - hdr = NULL; - if (rctbl != NULL) { + 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; } @@ -288,6 +296,22 @@ qcow_write(int fd, u_int version) 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; @@ -301,6 +325,8 @@ qcow_write(int fd, u_int version) error = image_copyout_done(fd); out: + if (rcblk != NULL) + free(rcblk); if (l2tbl != NULL) free(l2tbl); if (rctbl != NULL) @@ -319,14 +345,12 @@ qcow1_write(int fd) return (qcow_write(fd, QCOW_VERSION_1)); } -#ifdef QCOW_SUPPORT_QCOW2 static int qcow2_write(int fd) { return (qcow_write(fd, QCOW_VERSION_2)); } -#endif static struct mkimg_format qcow1_format = { .name = "qcow", @@ -336,7 +360,6 @@ static struct mkimg_format qcow1_format }; FORMAT_DEFINE(qcow1_format); -#ifdef QCOW_SUPPORT_QCOW2 static struct mkimg_format qcow2_format = { .name = "qcow2", .description = "QEMU Copy-On-Write, version 2", @@ -344,4 +367,3 @@ static struct mkimg_format qcow2_format .write = qcow2_write, }; FORMAT_DEFINE(qcow2_format); -#endif