From f6bcc035084ab11fde5eaec95fecaca5891d2385 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Tue, 4 Nov 2014 10:41:25 +0000 Subject: [PATCH] tools: remove blktap1 Now that it is unhooked we can just remove it. Signed-off-by: Ian Campbell Acked-by: Ian Jackson --- .gitignore | 5 - .hgignore | 5 - tools/blktap/Makefile | 13 - tools/blktap/README | 122 -- tools/blktap/drivers/Makefile | 73 - tools/blktap/drivers/aes.c | 1319 -------------- tools/blktap/drivers/aes.h | 28 - tools/blktap/drivers/blk.h | 3 - tools/blktap/drivers/blk_linux.c | 42 - tools/blktap/drivers/blktapctrl.c | 937 ---------- tools/blktap/drivers/blktapctrl.h | 36 - tools/blktap/drivers/blktapctrl_linux.c | 89 - tools/blktap/drivers/block-aio.c | 259 --- tools/blktap/drivers/block-qcow.c | 1434 ---------------- tools/blktap/drivers/block-qcow2.c | 2098 ----------------------- tools/blktap/drivers/block-ram.c | 295 ---- tools/blktap/drivers/block-sync.c | 242 --- tools/blktap/drivers/block-vmdk.c | 428 ----- tools/blktap/drivers/bswap.h | 178 -- tools/blktap/drivers/img2qcow.c | 282 --- tools/blktap/drivers/qcow-create.c | 130 -- tools/blktap/drivers/qcow2raw.c | 348 ---- tools/blktap/drivers/tapaio.c | 357 ---- tools/blktap/drivers/tapaio.h | 108 -- tools/blktap/drivers/tapdisk.c | 872 ---------- tools/blktap/drivers/tapdisk.h | 259 --- tools/blktap/lib/Makefile | 60 - tools/blktap/lib/blkif.c | 185 -- tools/blktap/lib/blktaplib.h | 240 --- tools/blktap/lib/list.h | 59 - tools/blktap/lib/xenbus.c | 617 ------- tools/blktap/lib/xs_api.c | 360 ---- tools/blktap/lib/xs_api.h | 50 - 33 files changed, 11533 deletions(-) delete mode 100644 tools/blktap/Makefile delete mode 100644 tools/blktap/README delete mode 100644 tools/blktap/drivers/Makefile delete mode 100644 tools/blktap/drivers/aes.c delete mode 100644 tools/blktap/drivers/aes.h delete mode 100644 tools/blktap/drivers/blk.h delete mode 100644 tools/blktap/drivers/blk_linux.c delete mode 100644 tools/blktap/drivers/blktapctrl.c delete mode 100644 tools/blktap/drivers/blktapctrl.h delete mode 100644 tools/blktap/drivers/blktapctrl_linux.c delete mode 100644 tools/blktap/drivers/block-aio.c delete mode 100644 tools/blktap/drivers/block-qcow.c delete mode 100644 tools/blktap/drivers/block-qcow2.c delete mode 100644 tools/blktap/drivers/block-ram.c delete mode 100644 tools/blktap/drivers/block-sync.c delete mode 100644 tools/blktap/drivers/block-vmdk.c delete mode 100644 tools/blktap/drivers/bswap.h delete mode 100644 tools/blktap/drivers/img2qcow.c delete mode 100644 tools/blktap/drivers/qcow-create.c delete mode 100644 tools/blktap/drivers/qcow2raw.c delete mode 100644 tools/blktap/drivers/tapaio.c delete mode 100644 tools/blktap/drivers/tapaio.h delete mode 100644 tools/blktap/drivers/tapdisk.c delete mode 100644 tools/blktap/drivers/tapdisk.h delete mode 100644 tools/blktap/lib/Makefile delete mode 100644 tools/blktap/lib/blkif.c delete mode 100644 tools/blktap/lib/blktaplib.h delete mode 100644 tools/blktap/lib/list.h delete mode 100644 tools/blktap/lib/xenbus.c delete mode 100644 tools/blktap/lib/xs_api.c delete mode 100644 tools/blktap/lib/xs_api.h diff --git a/.gitignore b/.gitignore index 8c8c06fc5a..a8f15d571e 100644 --- a/.gitignore +++ b/.gitignore @@ -101,11 +101,6 @@ tools/blktap2/drivers/tapdisk2 tools/blktap2/drivers/td-util tools/blktap2/vhd/vhd-update tools/blktap2/vhd/vhd-util -tools/blktap/drivers/blktapctrl -tools/blktap/drivers/img2qcow -tools/blktap/drivers/qcow-create -tools/blktap/drivers/qcow2raw -tools/blktap/drivers/tapdisk tools/console/xenconsole tools/console/xenconsoled tools/debugger/gdb/gdb-6.2.1-linux-i386-xen/* diff --git a/.hgignore b/.hgignore index da27f808db..0bd29a1061 100644 --- a/.hgignore +++ b/.hgignore @@ -140,11 +140,6 @@ ^tools/blktap2/drivers/td-util$ ^tools/blktap2/vhd/vhd-update$ ^tools/blktap2/vhd/vhd-util$ -^tools/blktap/drivers/blktapctrl$ -^tools/blktap/drivers/img2qcow$ -^tools/blktap/drivers/qcow-create$ -^tools/blktap/drivers/qcow2raw$ -^tools/blktap/drivers/tapdisk$ ^tools/check/\..*$ ^tools/console/xenconsole$ ^tools/console/xenconsoled$ diff --git a/tools/blktap/Makefile b/tools/blktap/Makefile deleted file mode 100644 index 40205660e8..0000000000 --- a/tools/blktap/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -XEN_ROOT = $(CURDIR)/../.. -include $(XEN_ROOT)/tools/Rules.mk - -SUBDIRS-y := -SUBDIRS-y += lib -SUBDIRS-y += drivers - -.PHONY: all clean install -all clean install: %: subdirs-% - -install: - $(INSTALL_DIR) $(DESTDIR)$(DOCDIR) - $(INSTALL_DATA) README $(DESTDIR)$(DOCDIR)/README.blktap diff --git a/tools/blktap/README b/tools/blktap/README deleted file mode 100644 index 5e4108030e..0000000000 --- a/tools/blktap/README +++ /dev/null @@ -1,122 +0,0 @@ -Blktap Userspace Tools + Library -================================ - -Andrew Warfield and Julian Chesterfield -16th June 2006 - -{firstname.lastname}@cl.cam.ac.uk - -The blktap userspace toolkit provides a user-level disk I/O -interface. The blktap mechanism involves a kernel driver that acts -similarly to the existing Xen/Linux blkback driver, and a set of -associated user-level libraries. Using these tools, blktap allows -virtual block devices presented to VMs to be implemented in userspace -and to be backed by raw partitions, files, network, etc. - -The key benefit of blktap is that it makes it easy and fast to write -arbitrary block backends, and that these user-level backends actually -perform very well. Specifically: - -- Metadata disk formats such as Copy-on-Write, encrypted disks, sparse - formats and other compression features can be easily implemented. - -- Accessing file-based images from userspace avoids problems related - to flushing dirty pages which are present in the Linux loopback - driver. (Specifically, doing a large number of writes to an - NFS-backed image don't result in the OOM killer going berserk.) - -- Per-disk handler processes enable easier userspace policing of block - resources, and process-granularity QoS techniques (disk scheduling - and related tools) may be trivially applied to block devices. - -- It's very easy to take advantage of userspace facilities such as - networking libraries, compression utilities, peer-to-peer - file-sharing systems and so on to build more complex block backends. - -- Crashes are contained -- incremental development/debugging is very - fast. - -How it works (in one paragraph): - -Working in conjunction with the kernel blktap driver, all disk I/O -requests from VMs are passed to the userspace deamon (using a shared -memory interface) through a character device. Each active disk is -mapped to an individual device node, allowing per-disk processes to -implement individual block devices where desired. The userspace -drivers are implemented using asynchronous (Linux libaio), -O_DIRECT-based calls to preserve the unbuffered, batched and -asynchronous request dispatch achieved with the existing blkback -code. We provide a simple, asynchronous virtual disk interface that -makes it quite easy to add new disk implementations. - -As of June 2006 the current supported disk formats are: - - - Raw Images (both on partitions and in image files) - - File-backed Qcow disks - - Standalone sparse Qcow disks - - Fast shareable RAM disk between VMs (requires some form of cluster-based - filesystem support e.g. OCFS2 in the guest kernel) - - Some VMDK images - your mileage may vary - -Raw and QCow images have asynchronous backends and so should perform -fairly well. VMDK is based directly on the qemu vmdk driver, which is -synchronous (a.k.a. slow). - -Build and Installation Instructions -=================================== - -Make to configure the blktap backend driver in your dom0 kernel. It -will cooperate fine with the existing backend driver, so you can -experiment with tap disks without breaking existing VM configs. - -To build the tools separately, "make && make install" in -tools/blktap. - - -Using the Tools -=============== - -Prepare the image for booting. For qcow files use the qcow utilities -installed earlier. e.g. qcow-create generates a blank standalone image -or a file-backed CoW image. img2qcow takes an existing image or -partition and creates a sparse, standalone qcow-based file. - -The userspace disk agent is configured to start automatically via xend -(alternatively you can start it manually => 'blktapctrl') - -Customise the VM config file to use the 'tap' handler, followed by the -driver type. e.g. for a raw image such as a file or partition: - -disk = ['tap:aio:,sda1,w'] - -e.g. for a qcow image: - -disk = ['tap:qcow:,sda1,w'] - - -Mounting images in Dom0 using the blktap driver -=============================================== -Tap (and blkback) disks are also mountable in Dom0 without requiring an -active VM to attach. You will need to build a xenlinux Dom0 kernel that -includes the blkfront driver (e.g. the default 'make world' or -'make kernels' build. Simply use the xm command-line tool to activate -the backend disks, and blkfront will generate a virtual block device that -can be accessed in the same way as a loop device or partition: - -e.g. for a raw image file that would normally be mounted using -the loopback driver (such as 'mount -o loop /mnt/disk'), do the -following: - -xm block-attach 0 tap:aio: /dev/xvda1 w 0 -mount /dev/xvda1 /mnt/disk <--- don't use loop driver - -In this way, you can use any of the userspace device-type drivers built -with the blktap userspace toolkit to open and mount disks such as qcow -or vmdk images: - -xm block-attach 0 tap:qcow: /dev/xvda1 w 0 -mount /dev/xvda1 /mnt/disk - - - - diff --git a/tools/blktap/drivers/Makefile b/tools/blktap/drivers/Makefile deleted file mode 100644 index cea8b3b468..0000000000 --- a/tools/blktap/drivers/Makefile +++ /dev/null @@ -1,73 +0,0 @@ -XEN_ROOT = $(CURDIR)/../../.. -include $(XEN_ROOT)/tools/Rules.mk - -IBIN = blktapctrl tapdisk -QCOW_UTIL = img2qcow qcow2raw qcow-create - -CFLAGS += -Werror -CFLAGS += -Wno-unused -CFLAGS += -I../lib -CFLAGS += $(CFLAGS_libxenctrl) -CFLAGS += $(CFLAGS_libxenstore) -CFLAGS += -D_GNU_SOURCE - -ifeq ($(CONFIG_GCRYPT),y) -CFLAGS += -DUSE_GCRYPT -CRYPT_LIB := -lgcrypt -else -CRYPT_LIB := -lcrypto -$(warning === libgcrypt not installed: falling back to libcrypto ===) -endif - -MEMSHRLIBS := -ifeq ($(CONFIG_Linux), y) -MEMSHR_DIR = ../../memshr -CFLAGS += -DMEMSHR -CFLAGS += -I $(MEMSHR_DIR) -MEMSHRLIBS += $(MEMSHR_DIR)/libmemshr.a -endif - -AIOLIBS := -laio - -CFLAGS += $(PTHREAD_CFLAGS) -LDFLAGS += $(PTHREAD_LDFLAGS) - -LDLIBS_blktapctrl := $(MEMSHRLIBS) $(LDLIBS_libxenctrl) $(LDLIBS_libxenstore) -L../lib -lblktap -lrt -lm $(PTHREAD_LIBS) -LDLIBS_img := $(AIOLIBS) $(CRYPT_LIB) $(PTHREAD_LIBS) -lz - -BLK-OBJS-y := block-aio.o -BLK-OBJS-y += block-sync.o -BLK-OBJS-y += block-vmdk.o -BLK-OBJS-y += block-ram.o -BLK-OBJS-y += block-qcow.o -BLK-OBJS-y += block-qcow2.o -BLK-OBJS-y += aes.o -BLK-OBJS-y += tapaio.o -BLK-OBJS-$(CONFIG_Linux) += blk_linux.o - -BLKTAB-OBJS-y := blktapctrl.o -BLKTAB-OBJS-$(CONFIG_Linux) += blktapctrl_linux.o - -all: $(IBIN) qcow-util - -blktapctrl: $(BLKTAB-OBJS-y) - $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS_blktapctrl) - -tapdisk: tapdisk.o $(BLK-OBJS-y) - $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS_img) - -.PHONY: qcow-util -qcow-util: img2qcow qcow2raw qcow-create - -img2qcow qcow2raw qcow-create: %: %.o $(BLK-OBJS-y) - $(CC) $(LDFLAGS) -o $* $^ $(LDLIBS_img) - -install: all - $(INSTALL_PROG) $(IBIN) $(QCOW_UTIL) $(VHD_UTIL) $(DESTDIR)$(SBINDIR) - -clean: - rm -rf *.o *~ $(DEPS) xen TAGS $(IBIN) $(LIB) $(QCOW_UTIL) $(VHD_UTIL) - -.PHONY: clean install - --include $(DEPS) diff --git a/tools/blktap/drivers/aes.c b/tools/blktap/drivers/aes.c deleted file mode 100644 index 4d83fac957..0000000000 --- a/tools/blktap/drivers/aes.c +++ /dev/null @@ -1,1319 +0,0 @@ -/** - * - * aes.c - integrated in QEMU by Fabrice Bellard from the OpenSSL project. - */ -/* - * rijndael-alg-fst.c - * - * @version 3.0 (December 2000) - * - * Optimised ANSI C code for the Rijndael cipher (now AES) - * - * @author Vincent Rijmen - * @author Antoon Bosselaers - * @author Paulo Barreto - * - * This code is hereby placed in the public domain. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''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 AUTHORS 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 "vl.h" -#include -#include -#include "aes.h" - -//#define NDEBUG -#include - -typedef uint32_t u32; -typedef uint16_t u16; -typedef uint8_t u8; - -#define MAXKC (256/32) -#define MAXKB (256/8) -#define MAXNR 14 - -/* This controls loop-unrolling in aes_core.c */ -#undef FULL_UNROLL -# define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ ((u32)(pt)[2] << 8) ^ ((u32)(pt)[3])) -# define PUTU32(ct, st) { (ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); (ct)[2] = (u8)((st) >> 8); (ct)[3] = (u8)(st); } - -/* -Te0[x] = S [x].[02, 01, 01, 03]; -Te1[x] = S [x].[03, 02, 01, 01]; -Te2[x] = S [x].[01, 03, 02, 01]; -Te3[x] = S [x].[01, 01, 03, 02]; -Te4[x] = S [x].[01, 01, 01, 01]; - -Td0[x] = Si[x].[0e, 09, 0d, 0b]; -Td1[x] = Si[x].[0b, 0e, 09, 0d]; -Td2[x] = Si[x].[0d, 0b, 0e, 09]; -Td3[x] = Si[x].[09, 0d, 0b, 0e]; -Td4[x] = Si[x].[01, 01, 01, 01]; -*/ - -static const u32 Te0[256] = { - 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU, - 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U, - 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU, - 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU, - 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U, - 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU, - 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU, - 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU, - 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU, - 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU, - 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U, - 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU, - 0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU, - 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U, - 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU, - 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU, - 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU, - 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU, - 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU, - 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U, - 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU, - 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU, - 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU, - 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU, - 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U, - 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U, - 0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U, - 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U, - 0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU, - 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U, - 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U, - 0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU, - 0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU, - 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U, - 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U, - 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U, - 0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU, - 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U, - 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU, - 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U, - 0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU, - 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U, - 0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U, - 0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU, - 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U, - 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U, - 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U, - 0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U, - 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U, - 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U, - 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U, - 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U, - 0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU, - 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U, - 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U, - 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U, - 0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U, - 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U, - 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U, - 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU, - 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U, - 0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U, - 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U, - 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU, -}; -static const u32 Te1[256] = { - 0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU, - 0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U, - 0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU, - 0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U, - 0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU, - 0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U, - 0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU, - 0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U, - 0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U, - 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU, - 0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U, - 0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U, - 0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U, - 0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU, - 0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U, - 0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U, - 0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU, - 0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U, - 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U, - 0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U, - 0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU, - 0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU, - 0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U, - 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU, - 0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU, - 0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U, - 0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU, - 0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U, - 0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU, - 0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U, - 0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U, - 0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U, - 0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU, - 0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U, - 0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU, - 0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U, - 0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU, - 0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U, - 0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U, - 0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU, - 0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU, - 0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU, - 0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U, - 0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U, - 0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU, - 0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U, - 0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU, - 0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U, - 0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU, - 0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U, - 0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU, - 0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU, - 0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U, - 0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU, - 0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U, - 0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU, - 0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U, - 0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U, - 0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U, - 0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU, - 0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU, - 0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U, - 0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU, - 0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U, -}; -static const u32 Te2[256] = { - 0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU, - 0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U, - 0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU, - 0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U, - 0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU, - 0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U, - 0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU, - 0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U, - 0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U, - 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU, - 0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U, - 0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U, - 0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U, - 0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU, - 0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U, - 0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U, - 0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU, - 0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U, - 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U, - 0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U, - 0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU, - 0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU, - 0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U, - 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU, - 0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU, - 0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U, - 0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU, - 0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U, - 0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU, - 0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U, - 0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U, - 0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U, - 0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU, - 0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U, - 0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU, - 0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U, - 0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU, - 0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U, - 0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U, - 0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU, - 0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU, - 0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU, - 0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U, - 0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U, - 0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU, - 0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U, - 0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU, - 0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U, - 0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU, - 0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U, - 0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU, - 0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU, - 0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U, - 0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU, - 0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U, - 0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU, - 0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U, - 0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U, - 0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U, - 0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU, - 0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU, - 0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U, - 0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU, - 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U, -}; -static const u32 Te3[256] = { - - 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U, - 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U, - 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U, - 0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU, - 0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU, - 0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU, - 0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U, - 0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU, - 0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU, - 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U, - 0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U, - 0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU, - 0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU, - 0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU, - 0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU, - 0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU, - 0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U, - 0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU, - 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU, - 0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U, - 0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U, - 0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U, - 0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U, - 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U, - 0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU, - 0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U, - 0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU, - 0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU, - 0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U, - 0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U, - 0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U, - 0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU, - 0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U, - 0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU, - 0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU, - 0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U, - 0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U, - 0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU, - 0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U, - 0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU, - 0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U, - 0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U, - 0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U, - 0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U, - 0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU, - 0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U, - 0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU, - 0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U, - 0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU, - 0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U, - 0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU, - 0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU, - 0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU, - 0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU, - 0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U, - 0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U, - 0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U, - 0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U, - 0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U, - 0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U, - 0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU, - 0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U, - 0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU, - 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU, -}; -static const u32 Te4[256] = { - 0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU, - 0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U, - 0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU, - 0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U, - 0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU, - 0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U, - 0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU, - 0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U, - 0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U, - 0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU, - 0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U, - 0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U, - 0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U, - 0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU, - 0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U, - 0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U, - 0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU, - 0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U, - 0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U, - 0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U, - 0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU, - 0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU, - 0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U, - 0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU, - 0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU, - 0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U, - 0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU, - 0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U, - 0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU, - 0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U, - 0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U, - 0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U, - 0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU, - 0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U, - 0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU, - 0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U, - 0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU, - 0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U, - 0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U, - 0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU, - 0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU, - 0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU, - 0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U, - 0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U, - 0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU, - 0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U, - 0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU, - 0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U, - 0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU, - 0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U, - 0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU, - 0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU, - 0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U, - 0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU, - 0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U, - 0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU, - 0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U, - 0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U, - 0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U, - 0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU, - 0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU, - 0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U, - 0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU, - 0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U, -}; -static const u32 Td0[256] = { - 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U, - 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U, - 0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U, - 0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU, - 0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U, - 0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U, - 0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU, - 0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U, - 0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU, - 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U, - 0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U, - 0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U, - 0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U, - 0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU, - 0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U, - 0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU, - 0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U, - 0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU, - 0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U, - 0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U, - 0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U, - 0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU, - 0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U, - 0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU, - 0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U, - 0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU, - 0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U, - 0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU, - 0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU, - 0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U, - 0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU, - 0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U, - 0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU, - 0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U, - 0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U, - 0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U, - 0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU, - 0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U, - 0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U, - 0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU, - 0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U, - 0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U, - 0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U, - 0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U, - 0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U, - 0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU, - 0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U, - 0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U, - 0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U, - 0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U, - 0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U, - 0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU, - 0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU, - 0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU, - 0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU, - 0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U, - 0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U, - 0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU, - 0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU, - 0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U, - 0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU, - 0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U, - 0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U, - 0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U, -}; -static const u32 Td1[256] = { - 0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU, - 0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U, - 0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU, - 0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U, - 0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U, - 0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U, - 0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U, - 0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U, - 0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U, - 0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU, - 0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU, - 0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU, - 0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U, - 0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU, - 0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U, - 0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U, - 0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U, - 0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU, - 0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU, - 0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U, - 0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU, - 0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U, - 0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU, - 0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU, - 0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U, - 0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U, - 0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U, - 0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU, - 0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U, - 0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU, - 0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U, - 0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U, - 0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U, - 0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU, - 0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U, - 0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U, - 0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U, - 0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U, - 0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U, - 0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U, - 0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU, - 0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU, - 0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U, - 0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU, - 0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U, - 0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU, - 0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU, - 0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U, - 0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU, - 0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U, - 0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U, - 0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U, - 0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U, - 0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U, - 0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U, - 0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U, - 0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU, - 0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U, - 0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U, - 0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU, - 0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U, - 0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U, - 0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U, - 0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U, -}; -static const u32 Td2[256] = { - 0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U, - 0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U, - 0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U, - 0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U, - 0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU, - 0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U, - 0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U, - 0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U, - 0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U, - 0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU, - 0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U, - 0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U, - 0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU, - 0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U, - 0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U, - 0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U, - 0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U, - 0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U, - 0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U, - 0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU, - - 0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U, - 0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U, - 0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U, - 0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U, - 0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U, - 0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU, - 0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU, - 0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U, - 0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU, - 0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U, - 0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU, - 0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU, - 0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU, - 0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU, - 0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U, - 0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U, - 0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U, - 0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U, - 0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U, - 0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U, - 0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U, - 0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU, - 0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU, - 0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U, - 0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U, - 0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU, - 0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU, - 0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U, - 0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U, - 0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U, - 0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U, - 0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U, - 0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U, - 0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U, - 0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU, - 0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U, - 0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U, - 0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U, - 0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U, - 0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U, - 0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U, - 0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU, - 0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U, - 0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U, -}; -static const u32 Td3[256] = { - 0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU, - 0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU, - 0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U, - 0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U, - 0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU, - 0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU, - 0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U, - 0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU, - 0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U, - 0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU, - 0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U, - 0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U, - 0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U, - 0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U, - 0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U, - 0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU, - 0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU, - 0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U, - 0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U, - 0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU, - 0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU, - 0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U, - 0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U, - 0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U, - 0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U, - 0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU, - 0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U, - 0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U, - 0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU, - 0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU, - 0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U, - 0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U, - 0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U, - 0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU, - 0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U, - 0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U, - 0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U, - 0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U, - 0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U, - 0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U, - 0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U, - 0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU, - 0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U, - 0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U, - 0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU, - 0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU, - 0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U, - 0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU, - 0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U, - 0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U, - 0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U, - 0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U, - 0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U, - 0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U, - 0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU, - 0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU, - 0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU, - 0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU, - 0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U, - 0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U, - 0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U, - 0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU, - 0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U, - 0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U, -}; -static const u32 Td4[256] = { - 0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U, - 0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U, - 0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU, - 0x81818181U, 0xf3f3f3f3U, 0xd7d7d7d7U, 0xfbfbfbfbU, - 0x7c7c7c7cU, 0xe3e3e3e3U, 0x39393939U, 0x82828282U, - 0x9b9b9b9bU, 0x2f2f2f2fU, 0xffffffffU, 0x87878787U, - 0x34343434U, 0x8e8e8e8eU, 0x43434343U, 0x44444444U, - 0xc4c4c4c4U, 0xdedededeU, 0xe9e9e9e9U, 0xcbcbcbcbU, - 0x54545454U, 0x7b7b7b7bU, 0x94949494U, 0x32323232U, - 0xa6a6a6a6U, 0xc2c2c2c2U, 0x23232323U, 0x3d3d3d3dU, - 0xeeeeeeeeU, 0x4c4c4c4cU, 0x95959595U, 0x0b0b0b0bU, - 0x42424242U, 0xfafafafaU, 0xc3c3c3c3U, 0x4e4e4e4eU, - 0x08080808U, 0x2e2e2e2eU, 0xa1a1a1a1U, 0x66666666U, - 0x28282828U, 0xd9d9d9d9U, 0x24242424U, 0xb2b2b2b2U, - 0x76767676U, 0x5b5b5b5bU, 0xa2a2a2a2U, 0x49494949U, - 0x6d6d6d6dU, 0x8b8b8b8bU, 0xd1d1d1d1U, 0x25252525U, - 0x72727272U, 0xf8f8f8f8U, 0xf6f6f6f6U, 0x64646464U, - 0x86868686U, 0x68686868U, 0x98989898U, 0x16161616U, - 0xd4d4d4d4U, 0xa4a4a4a4U, 0x5c5c5c5cU, 0xccccccccU, - 0x5d5d5d5dU, 0x65656565U, 0xb6b6b6b6U, 0x92929292U, - 0x6c6c6c6cU, 0x70707070U, 0x48484848U, 0x50505050U, - 0xfdfdfdfdU, 0xededededU, 0xb9b9b9b9U, 0xdadadadaU, - 0x5e5e5e5eU, 0x15151515U, 0x46464646U, 0x57575757U, - 0xa7a7a7a7U, 0x8d8d8d8dU, 0x9d9d9d9dU, 0x84848484U, - 0x90909090U, 0xd8d8d8d8U, 0xababababU, 0x00000000U, - 0x8c8c8c8cU, 0xbcbcbcbcU, 0xd3d3d3d3U, 0x0a0a0a0aU, - 0xf7f7f7f7U, 0xe4e4e4e4U, 0x58585858U, 0x05050505U, - 0xb8b8b8b8U, 0xb3b3b3b3U, 0x45454545U, 0x06060606U, - 0xd0d0d0d0U, 0x2c2c2c2cU, 0x1e1e1e1eU, 0x8f8f8f8fU, - 0xcacacacaU, 0x3f3f3f3fU, 0x0f0f0f0fU, 0x02020202U, - 0xc1c1c1c1U, 0xafafafafU, 0xbdbdbdbdU, 0x03030303U, - 0x01010101U, 0x13131313U, 0x8a8a8a8aU, 0x6b6b6b6bU, - 0x3a3a3a3aU, 0x91919191U, 0x11111111U, 0x41414141U, - 0x4f4f4f4fU, 0x67676767U, 0xdcdcdcdcU, 0xeaeaeaeaU, - 0x97979797U, 0xf2f2f2f2U, 0xcfcfcfcfU, 0xcecececeU, - 0xf0f0f0f0U, 0xb4b4b4b4U, 0xe6e6e6e6U, 0x73737373U, - 0x96969696U, 0xacacacacU, 0x74747474U, 0x22222222U, - 0xe7e7e7e7U, 0xadadadadU, 0x35353535U, 0x85858585U, - 0xe2e2e2e2U, 0xf9f9f9f9U, 0x37373737U, 0xe8e8e8e8U, - 0x1c1c1c1cU, 0x75757575U, 0xdfdfdfdfU, 0x6e6e6e6eU, - 0x47474747U, 0xf1f1f1f1U, 0x1a1a1a1aU, 0x71717171U, - 0x1d1d1d1dU, 0x29292929U, 0xc5c5c5c5U, 0x89898989U, - 0x6f6f6f6fU, 0xb7b7b7b7U, 0x62626262U, 0x0e0e0e0eU, - 0xaaaaaaaaU, 0x18181818U, 0xbebebebeU, 0x1b1b1b1bU, - 0xfcfcfcfcU, 0x56565656U, 0x3e3e3e3eU, 0x4b4b4b4bU, - 0xc6c6c6c6U, 0xd2d2d2d2U, 0x79797979U, 0x20202020U, - 0x9a9a9a9aU, 0xdbdbdbdbU, 0xc0c0c0c0U, 0xfefefefeU, - 0x78787878U, 0xcdcdcdcdU, 0x5a5a5a5aU, 0xf4f4f4f4U, - 0x1f1f1f1fU, 0xddddddddU, 0xa8a8a8a8U, 0x33333333U, - 0x88888888U, 0x07070707U, 0xc7c7c7c7U, 0x31313131U, - 0xb1b1b1b1U, 0x12121212U, 0x10101010U, 0x59595959U, - 0x27272727U, 0x80808080U, 0xececececU, 0x5f5f5f5fU, - 0x60606060U, 0x51515151U, 0x7f7f7f7fU, 0xa9a9a9a9U, - 0x19191919U, 0xb5b5b5b5U, 0x4a4a4a4aU, 0x0d0d0d0dU, - 0x2d2d2d2dU, 0xe5e5e5e5U, 0x7a7a7a7aU, 0x9f9f9f9fU, - 0x93939393U, 0xc9c9c9c9U, 0x9c9c9c9cU, 0xefefefefU, - 0xa0a0a0a0U, 0xe0e0e0e0U, 0x3b3b3b3bU, 0x4d4d4d4dU, - 0xaeaeaeaeU, 0x2a2a2a2aU, 0xf5f5f5f5U, 0xb0b0b0b0U, - 0xc8c8c8c8U, 0xebebebebU, 0xbbbbbbbbU, 0x3c3c3c3cU, - 0x83838383U, 0x53535353U, 0x99999999U, 0x61616161U, - 0x17171717U, 0x2b2b2b2bU, 0x04040404U, 0x7e7e7e7eU, - 0xbabababaU, 0x77777777U, 0xd6d6d6d6U, 0x26262626U, - 0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U, - 0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU, -}; -static const u32 rcon[] = { - 0x01000000, 0x02000000, 0x04000000, 0x08000000, - 0x10000000, 0x20000000, 0x40000000, 0x80000000, - 0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ -}; - -/** - * Expand the cipher key into the encryption key schedule. - */ -int AES_set_encrypt_key(const unsigned char *userKey, const int bits, - AES_KEY *key) { - - u32 *rk; - int i = 0; - u32 temp; - - if (!userKey || !key) - return -1; - if (bits != 128 && bits != 192 && bits != 256) - return -2; - - rk = key->rd_key; - - if (bits==128) - key->rounds = 10; - else if (bits==192) - key->rounds = 12; - else - key->rounds = 14; - - rk[0] = GETU32(userKey ); - rk[1] = GETU32(userKey + 4); - rk[2] = GETU32(userKey + 8); - rk[3] = GETU32(userKey + 12); - if (bits == 128) { - while (1) { - temp = rk[3]; - rk[4] = rk[0] ^ - (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ - (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ - (Te4[(temp ) & 0xff] & 0x0000ff00) ^ - (Te4[(temp >> 24) ] & 0x000000ff) ^ - rcon[i]; - rk[5] = rk[1] ^ rk[4]; - rk[6] = rk[2] ^ rk[5]; - rk[7] = rk[3] ^ rk[6]; - if (++i == 10) { - return 0; - } - rk += 4; - } - } - rk[4] = GETU32(userKey + 16); - rk[5] = GETU32(userKey + 20); - if (bits == 192) { - while (1) { - temp = rk[ 5]; - rk[ 6] = rk[ 0] ^ - (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ - (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ - (Te4[(temp ) & 0xff] & 0x0000ff00) ^ - (Te4[(temp >> 24) ] & 0x000000ff) ^ - rcon[i]; - rk[ 7] = rk[ 1] ^ rk[ 6]; - rk[ 8] = rk[ 2] ^ rk[ 7]; - rk[ 9] = rk[ 3] ^ rk[ 8]; - if (++i == 8) { - return 0; - } - rk[10] = rk[ 4] ^ rk[ 9]; - rk[11] = rk[ 5] ^ rk[10]; - rk += 6; - } - } - rk[6] = GETU32(userKey + 24); - rk[7] = GETU32(userKey + 28); - if (bits == 256) { - while (1) { - temp = rk[ 7]; - rk[ 8] = rk[ 0] ^ - (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ - (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ - (Te4[(temp ) & 0xff] & 0x0000ff00) ^ - (Te4[(temp >> 24) ] & 0x000000ff) ^ - rcon[i]; - rk[ 9] = rk[ 1] ^ rk[ 8]; - rk[10] = rk[ 2] ^ rk[ 9]; - rk[11] = rk[ 3] ^ rk[10]; - if (++i == 7) { - return 0; - } - temp = rk[11]; - rk[12] = rk[ 4] ^ - (Te4[(temp >> 24) ] & 0xff000000) ^ - (Te4[(temp >> 16) & 0xff] & 0x00ff0000) ^ - (Te4[(temp >> 8) & 0xff] & 0x0000ff00) ^ - (Te4[(temp ) & 0xff] & 0x000000ff); - rk[13] = rk[ 5] ^ rk[12]; - rk[14] = rk[ 6] ^ rk[13]; - rk[15] = rk[ 7] ^ rk[14]; - - rk += 8; - } - } - return 0; -} - -/** - * Expand the cipher key into the decryption key schedule. - */ -int AES_set_decrypt_key(const unsigned char *userKey, const int bits, - AES_KEY *key) { - - u32 *rk; - int i, j, status; - u32 temp; - - /* first, start with an encryption schedule */ - status = AES_set_encrypt_key(userKey, bits, key); - if (status < 0) - return status; - - rk = key->rd_key; - - /* invert the order of the round keys: */ - for (i = 0, j = 4*(key->rounds); i < j; i += 4, j -= 4) { - temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp; - temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp; - temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp; - temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp; - } - /* apply the inverse MixColumn transform to all round keys but the first and the last: */ - for (i = 1; i < (key->rounds); i++) { - rk += 4; - rk[0] = - Td0[Te4[(rk[0] >> 24) ] & 0xff] ^ - Td1[Te4[(rk[0] >> 16) & 0xff] & 0xff] ^ - Td2[Te4[(rk[0] >> 8) & 0xff] & 0xff] ^ - Td3[Te4[(rk[0] ) & 0xff] & 0xff]; - rk[1] = - Td0[Te4[(rk[1] >> 24) ] & 0xff] ^ - Td1[Te4[(rk[1] >> 16) & 0xff] & 0xff] ^ - Td2[Te4[(rk[1] >> 8) & 0xff] & 0xff] ^ - Td3[Te4[(rk[1] ) & 0xff] & 0xff]; - rk[2] = - Td0[Te4[(rk[2] >> 24) ] & 0xff] ^ - Td1[Te4[(rk[2] >> 16) & 0xff] & 0xff] ^ - Td2[Te4[(rk[2] >> 8) & 0xff] & 0xff] ^ - Td3[Te4[(rk[2] ) & 0xff] & 0xff]; - rk[3] = - Td0[Te4[(rk[3] >> 24) ] & 0xff] ^ - Td1[Te4[(rk[3] >> 16) & 0xff] & 0xff] ^ - Td2[Te4[(rk[3] >> 8) & 0xff] & 0xff] ^ - Td3[Te4[(rk[3] ) & 0xff] & 0xff]; - } - return 0; -} - -#ifndef AES_ASM -/* - * Encrypt a single block - * in and out can overlap - */ -void AES_encrypt(const unsigned char *in, unsigned char *out, - const AES_KEY *key) { - - const u32 *rk; - u32 s0, s1, s2, s3, t0, t1, t2, t3; -#ifndef FULL_UNROLL - int r; -#endif /* ?FULL_UNROLL */ - - assert(in && out && key); - rk = key->rd_key; - - /* - * map byte array block to cipher state - * and add initial round key: - */ - s0 = GETU32(in ) ^ rk[0]; - s1 = GETU32(in + 4) ^ rk[1]; - s2 = GETU32(in + 8) ^ rk[2]; - s3 = GETU32(in + 12) ^ rk[3]; -#ifdef FULL_UNROLL - /* round 1: */ - t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[ 4]; - t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[ 5]; - t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[ 6]; - t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[ 7]; - /* round 2: */ - s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[ 8]; - s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[ 9]; - s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[10]; - s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[11]; - /* round 3: */ - t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[12]; - t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[13]; - t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[14]; - t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[15]; - /* round 4: */ - s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[16]; - s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[17]; - s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[18]; - s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[19]; - /* round 5: */ - t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[20]; - t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[21]; - t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[22]; - t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[23]; - /* round 6: */ - s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[24]; - s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[25]; - s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[26]; - s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[27]; - /* round 7: */ - t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[28]; - t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[29]; - t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[30]; - t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[31]; - /* round 8: */ - s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[32]; - s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[33]; - s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[34]; - s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[35]; - /* round 9: */ - t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[36]; - t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[37]; - t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[38]; - t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[39]; - if (key->rounds > 10) { - /* round 10: */ - s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[40]; - s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[41]; - s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[42]; - s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[43]; - /* round 11: */ - t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[44]; - t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[45]; - t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[46]; - t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[47]; - if (key->rounds > 12) { - /* round 12: */ - s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[48]; - s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[49]; - s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[50]; - s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[51]; - /* round 13: */ - t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[52]; - t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[53]; - t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[54]; - t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[55]; - } - } - rk += key->rounds << 2; -#else /* !FULL_UNROLL */ - /* - * Nr - 1 full rounds: - */ - r = key->rounds >> 1; - for (;;) { - t0 = - Te0[(s0 >> 24) ] ^ - Te1[(s1 >> 16) & 0xff] ^ - Te2[(s2 >> 8) & 0xff] ^ - Te3[(s3 ) & 0xff] ^ - rk[4]; - t1 = - Te0[(s1 >> 24) ] ^ - Te1[(s2 >> 16) & 0xff] ^ - Te2[(s3 >> 8) & 0xff] ^ - Te3[(s0 ) & 0xff] ^ - rk[5]; - t2 = - Te0[(s2 >> 24) ] ^ - Te1[(s3 >> 16) & 0xff] ^ - Te2[(s0 >> 8) & 0xff] ^ - Te3[(s1 ) & 0xff] ^ - rk[6]; - t3 = - Te0[(s3 >> 24) ] ^ - Te1[(s0 >> 16) & 0xff] ^ - Te2[(s1 >> 8) & 0xff] ^ - Te3[(s2 ) & 0xff] ^ - rk[7]; - - rk += 8; - if (--r == 0) { - break; - } - - s0 = - Te0[(t0 >> 24) ] ^ - Te1[(t1 >> 16) & 0xff] ^ - Te2[(t2 >> 8) & 0xff] ^ - Te3[(t3 ) & 0xff] ^ - rk[0]; - s1 = - Te0[(t1 >> 24) ] ^ - Te1[(t2 >> 16) & 0xff] ^ - Te2[(t3 >> 8) & 0xff] ^ - Te3[(t0 ) & 0xff] ^ - rk[1]; - s2 = - Te0[(t2 >> 24) ] ^ - Te1[(t3 >> 16) & 0xff] ^ - Te2[(t0 >> 8) & 0xff] ^ - Te3[(t1 ) & 0xff] ^ - rk[2]; - s3 = - Te0[(t3 >> 24) ] ^ - Te1[(t0 >> 16) & 0xff] ^ - Te2[(t1 >> 8) & 0xff] ^ - Te3[(t2 ) & 0xff] ^ - rk[3]; - } -#endif /* ?FULL_UNROLL */ - /* - * apply last round and - * map cipher state to byte array block: - */ - s0 = - (Te4[(t0 >> 24) ] & 0xff000000) ^ - (Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ - (Te4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ - (Te4[(t3 ) & 0xff] & 0x000000ff) ^ - rk[0]; - PUTU32(out , s0); - s1 = - (Te4[(t1 >> 24) ] & 0xff000000) ^ - (Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ - (Te4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ - (Te4[(t0 ) & 0xff] & 0x000000ff) ^ - rk[1]; - PUTU32(out + 4, s1); - s2 = - (Te4[(t2 >> 24) ] & 0xff000000) ^ - (Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ - (Te4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ - (Te4[(t1 ) & 0xff] & 0x000000ff) ^ - rk[2]; - PUTU32(out + 8, s2); - s3 = - (Te4[(t3 >> 24) ] & 0xff000000) ^ - (Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ - (Te4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ - (Te4[(t2 ) & 0xff] & 0x000000ff) ^ - rk[3]; - PUTU32(out + 12, s3); -} - -/* - * Decrypt a single block - * in and out can overlap - */ -void AES_decrypt(const unsigned char *in, unsigned char *out, - const AES_KEY *key) { - - const u32 *rk; - u32 s0, s1, s2, s3, t0, t1, t2, t3; -#ifndef FULL_UNROLL - int r; -#endif /* ?FULL_UNROLL */ - - assert(in && out && key); - rk = key->rd_key; - - /* - * map byte array block to cipher state - * and add initial round key: - */ - s0 = GETU32(in ) ^ rk[0]; - s1 = GETU32(in + 4) ^ rk[1]; - s2 = GETU32(in + 8) ^ rk[2]; - s3 = GETU32(in + 12) ^ rk[3]; -#ifdef FULL_UNROLL - /* round 1: */ - t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[ 4]; - t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[ 5]; - t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[ 6]; - t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[ 7]; - /* round 2: */ - s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[ 8]; - s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[ 9]; - s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[10]; - s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[11]; - /* round 3: */ - t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[12]; - t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[13]; - t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[14]; - t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[15]; - /* round 4: */ - s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[16]; - s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[17]; - s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[18]; - s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[19]; - /* round 5: */ - t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[20]; - t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[21]; - t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[22]; - t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[23]; - /* round 6: */ - s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[24]; - s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[25]; - s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[26]; - s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[27]; - /* round 7: */ - t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[28]; - t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[29]; - t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[30]; - t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[31]; - /* round 8: */ - s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[32]; - s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[33]; - s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[34]; - s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[35]; - /* round 9: */ - t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[36]; - t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[37]; - t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[38]; - t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[39]; - if (key->rounds > 10) { - /* round 10: */ - s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[40]; - s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[41]; - s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[42]; - s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[43]; - /* round 11: */ - t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[44]; - t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[45]; - t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[46]; - t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[47]; - if (key->rounds > 12) { - /* round 12: */ - s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[48]; - s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[49]; - s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[50]; - s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[51]; - /* round 13: */ - t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[52]; - t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[53]; - t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[54]; - t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[55]; - } - } - rk += key->rounds << 2; -#else /* !FULL_UNROLL */ - /* - * Nr - 1 full rounds: - */ - r = key->rounds >> 1; - for (;;) { - t0 = - Td0[(s0 >> 24) ] ^ - Td1[(s3 >> 16) & 0xff] ^ - Td2[(s2 >> 8) & 0xff] ^ - Td3[(s1 ) & 0xff] ^ - rk[4]; - t1 = - Td0[(s1 >> 24) ] ^ - Td1[(s0 >> 16) & 0xff] ^ - Td2[(s3 >> 8) & 0xff] ^ - Td3[(s2 ) & 0xff] ^ - rk[5]; - t2 = - Td0[(s2 >> 24) ] ^ - Td1[(s1 >> 16) & 0xff] ^ - Td2[(s0 >> 8) & 0xff] ^ - Td3[(s3 ) & 0xff] ^ - rk[6]; - t3 = - Td0[(s3 >> 24) ] ^ - Td1[(s2 >> 16) & 0xff] ^ - Td2[(s1 >> 8) & 0xff] ^ - Td3[(s0 ) & 0xff] ^ - rk[7]; - - rk += 8; - if (--r == 0) { - break; - } - - s0 = - Td0[(t0 >> 24) ] ^ - Td1[(t3 >> 16) & 0xff] ^ - Td2[(t2 >> 8) & 0xff] ^ - Td3[(t1 ) & 0xff] ^ - rk[0]; - s1 = - Td0[(t1 >> 24) ] ^ - Td1[(t0 >> 16) & 0xff] ^ - Td2[(t3 >> 8) & 0xff] ^ - Td3[(t2 ) & 0xff] ^ - rk[1]; - s2 = - Td0[(t2 >> 24) ] ^ - Td1[(t1 >> 16) & 0xff] ^ - Td2[(t0 >> 8) & 0xff] ^ - Td3[(t3 ) & 0xff] ^ - rk[2]; - s3 = - Td0[(t3 >> 24) ] ^ - Td1[(t2 >> 16) & 0xff] ^ - Td2[(t1 >> 8) & 0xff] ^ - Td3[(t0 ) & 0xff] ^ - rk[3]; - } -#endif /* ?FULL_UNROLL */ - /* - * apply last round and - * map cipher state to byte array block: - */ - s0 = - (Td4[(t0 >> 24) ] & 0xff000000) ^ - (Td4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ - (Td4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ - (Td4[(t1 ) & 0xff] & 0x000000ff) ^ - rk[0]; - PUTU32(out , s0); - s1 = - (Td4[(t1 >> 24) ] & 0xff000000) ^ - (Td4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ - (Td4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ - (Td4[(t2 ) & 0xff] & 0x000000ff) ^ - rk[1]; - PUTU32(out + 4, s1); - s2 = - (Td4[(t2 >> 24) ] & 0xff000000) ^ - (Td4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ - (Td4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ - (Td4[(t3 ) & 0xff] & 0x000000ff) ^ - rk[2]; - PUTU32(out + 8, s2); - s3 = - (Td4[(t3 >> 24) ] & 0xff000000) ^ - (Td4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ - (Td4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ - (Td4[(t0 ) & 0xff] & 0x000000ff) ^ - rk[3]; - PUTU32(out + 12, s3); -} - -#endif /* AES_ASM */ - -void AES_cbc_encrypt(const unsigned char *in, unsigned char *out, - const unsigned long length, const AES_KEY *key, - unsigned char *ivec, const int enc) -{ - - unsigned long n; - unsigned long len = length; - unsigned char tmp[AES_BLOCK_SIZE]; - - assert(in && out && key && ivec); - - if (enc) { - while (len >= AES_BLOCK_SIZE) { - for(n=0; n < AES_BLOCK_SIZE; ++n) - tmp[n] = in[n] ^ ivec[n]; - AES_encrypt(tmp, out, key); - memcpy(ivec, out, AES_BLOCK_SIZE); - len -= AES_BLOCK_SIZE; - in += AES_BLOCK_SIZE; - out += AES_BLOCK_SIZE; - } - if (len) { - for(n=0; n < len; ++n) - tmp[n] = in[n] ^ ivec[n]; - for(n=len; n < AES_BLOCK_SIZE; ++n) - tmp[n] = ivec[n]; - AES_encrypt(tmp, tmp, key); - memcpy(out, tmp, AES_BLOCK_SIZE); - memcpy(ivec, tmp, AES_BLOCK_SIZE); - } - } else { - while (len >= AES_BLOCK_SIZE) { - memcpy(tmp, in, AES_BLOCK_SIZE); - AES_decrypt(in, out, key); - for(n=0; n < AES_BLOCK_SIZE; ++n) - out[n] ^= ivec[n]; - memcpy(ivec, tmp, AES_BLOCK_SIZE); - len -= AES_BLOCK_SIZE; - in += AES_BLOCK_SIZE; - out += AES_BLOCK_SIZE; - } - if (len) { - memcpy(tmp, in, AES_BLOCK_SIZE); - AES_decrypt(tmp, tmp, key); - for(n=0; n < len; ++n) - out[n] = tmp[n] ^ ivec[n]; - memcpy(ivec, tmp, AES_BLOCK_SIZE); - } - } -} diff --git a/tools/blktap/drivers/aes.h b/tools/blktap/drivers/aes.h deleted file mode 100644 index 9fb54a900d..0000000000 --- a/tools/blktap/drivers/aes.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef QEMU_AES_H -#define QEMU_AES_H - -#include - -#define AES_MAXNR 14 -#define AES_BLOCK_SIZE 16 - -struct aes_key_st { - uint32_t rd_key[4 *(AES_MAXNR + 1)]; - int rounds; -}; -typedef struct aes_key_st AES_KEY; - -int AES_set_encrypt_key(const unsigned char *userKey, const int bits, - AES_KEY *key); -int AES_set_decrypt_key(const unsigned char *userKey, const int bits, - AES_KEY *key); - -void AES_encrypt(const unsigned char *in, unsigned char *out, - const AES_KEY *key); -void AES_decrypt(const unsigned char *in, unsigned char *out, - const AES_KEY *key); -void AES_cbc_encrypt(const unsigned char *in, unsigned char *out, - const unsigned long length, const AES_KEY *key, - unsigned char *ivec, const int enc); - -#endif diff --git a/tools/blktap/drivers/blk.h b/tools/blktap/drivers/blk.h deleted file mode 100644 index 1cdc98098c..0000000000 --- a/tools/blktap/drivers/blk.h +++ /dev/null @@ -1,3 +0,0 @@ - -int blk_getimagesize(int fd, uint64_t *size); -int blk_getsectorsize(int fd, uint64_t *sector_size); diff --git a/tools/blktap/drivers/blk_linux.c b/tools/blktap/drivers/blk_linux.c deleted file mode 100644 index bb52717050..0000000000 --- a/tools/blktap/drivers/blk_linux.c +++ /dev/null @@ -1,42 +0,0 @@ -#include -#include -#include -#include "tapdisk.h" -#include "blk.h" - -int blk_getimagesize(int fd, uint64_t *size) -{ - int rc; - - *size = 0; - rc = ioctl(fd, BLKGETSIZE, size); - if (rc) { - DPRINTF("ERR: BLKGETSIZE failed, couldn't stat image"); - return -EINVAL; - } - - return 0; -} - -int blk_getsectorsize(int fd, uint64_t *sector_size) -{ -#if defined(BLKSSZGET) - int rc; - - *sector_size = DEFAULT_SECTOR_SIZE; - rc = ioctl(fd, BLKSSZGET, sector_size); - if (rc) { - DPRINTF("ERR: BLKSSZGET failed. Falling back to use default sector size"); - *sector_size = DEFAULT_SECTOR_SIZE; - } - - if (*sector_size != DEFAULT_SECTOR_SIZE) - DPRINTF("Note: sector size is %"PRIu64" (not %u)\n", - *sector_size, DEFAULT_SECTOR_SIZE); -#else - *sector_size = DEFAULT_SECTOR_SIZE; -#endif - - return 0; -} - diff --git a/tools/blktap/drivers/blktapctrl.c b/tools/blktap/drivers/blktapctrl.c deleted file mode 100644 index 0a8b8800e8..0000000000 --- a/tools/blktap/drivers/blktapctrl.c +++ /dev/null @@ -1,937 +0,0 @@ -/* - * blktapctrl.c - * - * userspace controller for the blktap disks. - * As requests for new block devices arrive, - * the controller spawns off a separate process - * per-disk. - * - * - * Copyright (c) 2005 Julian Chesterfield and Andrew Warfield. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation; or, when distributed - * separately from the Linux kernel or incorporated into other - * software packages, subject to the following license: - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this source file (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, modify, - * merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef MEMSHR -#include -#endif -#include - -#include "blktaplib.h" -#include "blktapctrl.h" -#include "tapdisk.h" -#include "list.h" -#include "xs_api.h" /* for xs_fire_next_watch() */ - -#define PIDFILE "/var/run/blktapctrl.pid" - -#define NUM_POLL_FDS 2 -#define MSG_SIZE 4096 -#define MAX_TIMEOUT 10 -#define MAX_RAND_VAL 0xFFFF -#define MAX_ATTEMPTS 10 - -int run = 1; -int max_timeout = MAX_TIMEOUT; -int ctlfd = 0; - -int blktap_major; - -static int open_ctrl_socket(char *devname); -static int write_msg(int fd, int msgtype, void *ptr, void *ptr2); -static int read_msg(int fd, int msgtype, void *ptr); -static driver_list_entry_t *active_disks[MAX_DISK_TYPES]; - - -static unsigned long long tapdisk_get_size(blkif_t *blkif) -{ - image_t *img = (image_t *)blkif->prv; - return img->size; -} - -static unsigned long tapdisk_get_secsize(blkif_t *blkif) -{ - image_t *img = (image_t *)blkif->prv; - return img->secsize; -} - -static unsigned int tapdisk_get_info(blkif_t *blkif) -{ - image_t *img = (image_t *)blkif->prv; - return img->info; -} - -struct blkif_ops tapdisk_ops = { - .get_size = tapdisk_get_size, - .get_secsize = tapdisk_get_secsize, - .get_info = tapdisk_get_info, -}; - - -static void init_driver_list(void) -{ - int i; - - for (i = 0; i < MAX_DISK_TYPES; i++) - active_disks[i] = NULL; - return; -} - -static void init_rng(void) -{ - static uint32_t seed; - struct timeval tv; - - gettimeofday(&tv, NULL); - seed = tv.tv_usec; - srand48(seed); - return; -} - -static int get_tapdisk_pid(blkif_t *blkif) -{ - int ret; - - if ((ret = write_msg(blkif->fds[WRITE], CTLMSG_PID, blkif, NULL)) - <= 0) { - DPRINTF("Write_msg failed - CTLMSG_PID(%d)\n", ret); - return -EINVAL; - } - - if ((ret = read_msg(blkif->fds[READ], CTLMSG_PID_RSP, blkif)) - <= 0) { - DPRINTF("Read_msg failure - CTLMSG_PID(%d)\n", ret); - return -EINVAL; - } - return 1; -} - -/* Look up the disk specified by path: - * if found, dev points to the device string in the path - * type is the tapdisk driver type id - * blkif is the existing interface if this is a shared driver - * and NULL otherwise. - * return 0 on success, -1 on error. - */ - -static int test_path(char *path, char **dev, int *type, blkif_t **blkif, - int* use_ioemu) -{ - char *ptr, handle[10]; - int i, size, found = 0; - size_t handle_len; - - size = sizeof(dtypes)/sizeof(disk_info_t *); - *type = MAX_DISK_TYPES + 1; - *blkif = NULL; - - if (!strncmp(path, "tapdisk:", strlen("tapdisk:"))) { - *use_ioemu = 0; - path += strlen("tapdisk:"); - } else if (!strncmp(path, "ioemu:", strlen("ioemu:"))) { - *use_ioemu = 1; - path += strlen("ioemu:"); - } else { - // Use the default for the image type - *use_ioemu = -1; - } - - if ( (ptr = strstr(path, ":"))!=NULL) { - handle_len = (ptr - path); - memcpy(handle, path, handle_len); - *dev = ptr + 1; - ptr = handle + handle_len; - *ptr = '\0'; - DPRINTF("Detected handle: [%s]\n",handle); - - for (i = 0; i < size; i++) { - if ((strlen(dtypes[i]->handle) == handle_len) && - strncmp(handle, dtypes[i]->handle, - handle_len) == 0) { - found = 1; - } - - if (found) { - if (*use_ioemu == -1) - *use_ioemu = dtypes[i]->use_ioemu; - *type = dtypes[i]->idnum; - - if (dtypes[i]->single_handler == 1) { - /* Check whether tapdisk process - already exists */ - if (active_disks[dtypes[i]->idnum] == NULL) - *blkif = NULL; - else - *blkif = active_disks[dtypes[i] - ->idnum]->blkif; - } - - return 0; - } - } - } - - /* Fall-through case, we didn't find a disk driver. */ - DPRINTF("Unknown blktap disk type [%s]!\n",handle); - *dev = NULL; - return -1; -} - - -static void add_disktype(blkif_t *blkif, int type) -{ - driver_list_entry_t *entry, **pprev; - - if (type > MAX_DISK_TYPES) - return; - - entry = malloc(sizeof(driver_list_entry_t)); - entry->blkif = blkif; - entry->next = NULL; - - pprev = &active_disks[type]; - while (*pprev != NULL) - pprev = &(*pprev)->next; - - *pprev = entry; - entry->pprev = pprev; -} - -static int qemu_instance_has_disks(pid_t pid) -{ - int i; - int count = 0; - driver_list_entry_t *entry; - - for (i = 0; i < MAX_DISK_TYPES; i++) { - entry = active_disks[i]; - while (entry) { - if ((entry->blkif->tappid == pid) && dtypes[i]->use_ioemu) - count++; - entry = entry->next; - } - } - - return (count != 0); -} - -static int del_disktype(blkif_t *blkif) -{ - driver_list_entry_t *entry, **pprev; - int type = blkif->drivertype, count = 0, close = 0; - - if (type > MAX_DISK_TYPES) - return 1; - - pprev = &active_disks[type]; - while ((*pprev != NULL) && ((*pprev)->blkif != blkif)) - pprev = &(*pprev)->next; - - if ((entry = *pprev) == NULL) { - DPRINTF("DEL_DISKTYPE: No match\n"); - return 1; - } - - *pprev = entry->next; - if (entry->next) - entry->next->pprev = pprev; - - DPRINTF("DEL_DISKTYPE: Freeing entry\n"); - free(entry); - - /* - * When using ioemu, all disks of one VM are connected to the same - * qemu-dm instance. We may close the file handle only if there is - * no other disk left for this domain. - */ - if (dtypes[type]->use_ioemu) - return !qemu_instance_has_disks(blkif->tappid); - - /* Caller should close() if no single controller, or list is empty. */ - return (!dtypes[type]->single_handler || (active_disks[type] == NULL)); -} - -static int write_msg(int fd, int msgtype, void *ptr, void *ptr2) -{ - blkif_t *blkif; - blkif_info_t *blk; - msg_hdr_t *msg; - msg_newdev_t *msg_dev; - char *p, *buf, *path; - int msglen, len, ret; - fd_set writefds; - struct timeval timeout; - image_t *image, *img; - uint32_t seed; - - blkif = (blkif_t *)ptr; - blk = blkif->info; - image = blkif->prv; - len = 0; - - switch (msgtype) - { - case CTLMSG_PARAMS: - path = (char *)ptr2; - DPRINTF("Write_msg called: CTLMSG_PARAMS, sending [%s, %s]\n", - blk->params, path); - - msglen = sizeof(msg_hdr_t) + strlen(path) + 1; - buf = malloc(msglen); - - /*Assign header fields*/ - msg = (msg_hdr_t *)buf; - msg->type = CTLMSG_PARAMS; - msg->len = msglen; - msg->drivertype = blkif->drivertype; - msg->readonly = blkif->readonly; - - gettimeofday(&timeout, NULL); - msg->cookie = blkif->cookie; - DPRINTF("Generated cookie, %d\n",blkif->cookie); - - /*Copy blk->params to msg*/ - p = buf + sizeof(msg_hdr_t); - memcpy(p, path, strlen(path) + 1); - - break; - - case CTLMSG_NEWDEV: - DPRINTF("Write_msg called: CTLMSG_NEWDEV\n"); - - msglen = sizeof(msg_hdr_t) + sizeof(msg_newdev_t); - buf = malloc(msglen); - - /*Assign header fields*/ - msg = (msg_hdr_t *)buf; - msg->type = CTLMSG_NEWDEV; - msg->len = msglen; - msg->drivertype = blkif->drivertype; - msg->cookie = blkif->cookie; - - msg_dev = (msg_newdev_t *)(buf + sizeof(msg_hdr_t)); - msg_dev->devnum = blkif->minor; - msg_dev->domid = blkif->domid; - - break; - - case CTLMSG_CLOSE: - DPRINTF("Write_msg called: CTLMSG_CLOSE\n"); - - msglen = sizeof(msg_hdr_t); - buf = malloc(msglen); - - /*Assign header fields*/ - msg = (msg_hdr_t *)buf; - msg->type = CTLMSG_CLOSE; - msg->len = msglen; - msg->drivertype = blkif->drivertype; - msg->cookie = blkif->cookie; - - break; - - case CTLMSG_PID: - DPRINTF("Write_msg called: CTLMSG_PID\n"); - - msglen = sizeof(msg_hdr_t); - buf = malloc(msglen); - - /*Assign header fields*/ - msg = (msg_hdr_t *)buf; - msg->type = CTLMSG_PID; - msg->len = msglen; - msg->drivertype = blkif->drivertype; - msg->cookie = blkif->cookie; - - break; - - default: - return -1; - } - - /*Now send the message*/ - ret = 0; - FD_ZERO(&writefds); - FD_SET(fd,&writefds); - timeout.tv_sec = max_timeout; /*Wait for up to max_timeout seconds*/ - timeout.tv_usec = 0; - if (select(fd+1, (fd_set *) 0, &writefds, - (fd_set *) 0, &timeout) > 0) { - len = write(fd, buf, msglen); - if (len == -1) DPRINTF("Write failed: (%d)\n",errno); - } - free(buf); - - return len; -} - -static int read_msg(int fd, int msgtype, void *ptr) -{ - blkif_t *blkif; - blkif_info_t *blk; - msg_hdr_t *msg; - msg_pid_t *msg_pid; - char *p, *buf; - int msglen = MSG_SIZE, len, ret; - fd_set readfds; - struct timeval timeout; - image_t *image, *img; - - - blkif = (blkif_t *)ptr; - blk = blkif->info; - image = blkif->prv; - - buf = malloc(MSG_SIZE); - - ret = 0; - FD_ZERO(&readfds); - FD_SET(fd,&readfds); - timeout.tv_sec = max_timeout; /*Wait for up to max_timeout seconds*/ - timeout.tv_usec = 0; - if (select(fd+1, &readfds, (fd_set *) 0, - (fd_set *) 0, &timeout) > 0) { - ret = read(fd, buf, msglen); - } - if (ret > 0) { - msg = (msg_hdr_t *)buf; - switch (msg->type) - { - case CTLMSG_IMG: - img = (image_t *)(buf + sizeof(msg_hdr_t)); - image->size = img->size; - image->secsize = img->secsize; - image->info = img->info; - - DPRINTF("Received CTLMSG_IMG: %llu, %lu, %u\n", - image->size, image->secsize, image->info); - if(msgtype != CTLMSG_IMG) ret = 0; - break; - - case CTLMSG_IMG_FAIL: - DPRINTF("Received CTLMSG_IMG_FAIL, " - "unable to open image\n"); - ret = 0; - break; - - case CTLMSG_NEWDEV_RSP: - DPRINTF("Received CTLMSG_NEWDEV_RSP\n"); - if(msgtype != CTLMSG_NEWDEV_RSP) ret = 0; - break; - - case CTLMSG_NEWDEV_FAIL: - DPRINTF("Received CTLMSG_NEWDEV_FAIL\n"); - ret = 0; - break; - - case CTLMSG_CLOSE_RSP: - DPRINTF("Received CTLMSG_CLOSE_RSP\n"); - if (msgtype != CTLMSG_CLOSE_RSP) ret = 0; - break; - - case CTLMSG_PID_RSP: - DPRINTF("Received CTLMSG_PID_RSP\n"); - if (msgtype != CTLMSG_PID_RSP) ret = 0; - else { - msg_pid = (msg_pid_t *) - (buf + sizeof(msg_hdr_t)); - blkif->tappid = msg_pid->pid; - DPRINTF("\tPID: [%d]\n",blkif->tappid); - } - break; - default: - DPRINTF("UNKNOWN MESSAGE TYPE RECEIVED\n"); - ret = 0; - break; - } - } - - free(buf); - - return ret; - -} - -static int launch_tapdisk_provider(char **argv) -{ - pid_t child; - - if ((child = fork()) < 0) - return -1; - - if (!child) { - int i; - for (i = 0 ; i < sysconf(_SC_OPEN_MAX) ; i++) - if (i != STDIN_FILENO && - i != STDOUT_FILENO && - i != STDERR_FILENO) - close(i); - - execvp(argv[0], argv); - DPRINTF("execvp failed: %d (%s)\n", errno, strerror(errno)); - DPRINTF("PATH = %s\n", getenv("PATH")); - _exit(1); - } else { - pid_t got; - do { - got = waitpid(child, NULL, 0); - } while (got != child); - } - return child; -} - -static int launch_tapdisk(char *wrctldev, char *rdctldev) -{ - char *argv[] = { "tapdisk", wrctldev, rdctldev, NULL }; - - if (launch_tapdisk_provider(argv) < 0) - return -1; - - return 0; -} - -static int launch_tapdisk_ioemu(void) -{ - char *argv[] = { "tapdisk-ioemu", NULL }; - return launch_tapdisk_provider(argv); -} - -/* - * Connect to an ioemu based disk provider (qemu-dm or tapdisk-ioemu) - * - * If the domain has a device model, connect to qemu-dm through the - * domain specific pipe. Otherwise use a single tapdisk-ioemu instance - * which is represented by domid 0 and provides access for Dom0 and - * all DomUs without device model. - */ -static int connect_qemu(blkif_t *blkif, int domid) -{ - char *rdctldev, *wrctldev; - - static int tapdisk_ioemu_pid = 0; - static int dom0_readfd = 0; - static int dom0_writefd = 0; - int refresh_pid = 0; - - if (asprintf(&rdctldev, BLKTAP_CTRL_DIR "/qemu-read-%d", domid) < 0) - return -1; - - if (asprintf(&wrctldev, BLKTAP_CTRL_DIR "/qemu-write-%d", domid) < 0) { - free(rdctldev); - return -1; - } - - DPRINTF("Using qemu blktap pipe: %s\n", rdctldev); - - if (domid == 0) { - /* - * tapdisk-ioemu exits as soon as the last image is - * disconnected. Check if it is still running. - */ - if (tapdisk_ioemu_pid == 0 || kill(tapdisk_ioemu_pid, 0)) { - /* No device model and tapdisk-ioemu doesn't run yet */ - DPRINTF("Launching tapdisk-ioemu\n"); - launch_tapdisk_ioemu(); - - dom0_readfd = open_ctrl_socket(wrctldev); - dom0_writefd = open_ctrl_socket(rdctldev); - - refresh_pid = 1; - } - - DPRINTF("Using tapdisk-ioemu connection\n"); - blkif->fds[READ] = dom0_readfd; - blkif->fds[WRITE] = dom0_writefd; - - if (refresh_pid) { - get_tapdisk_pid(blkif); - tapdisk_ioemu_pid = blkif->tappid; - } - - } else if (access(rdctldev, R_OK | W_OK) == 0) { - /* Use existing pipe to the device model */ - DPRINTF("Using qemu-dm connection\n"); - blkif->fds[READ] = open_ctrl_socket(wrctldev); - blkif->fds[WRITE] = open_ctrl_socket(rdctldev); - } else { - /* No device model => try with tapdisk-ioemu */ - DPRINTF("No device model\n"); - connect_qemu(blkif, 0); - } - - free(rdctldev); - free(wrctldev); - - if (blkif->fds[READ] == -1 || blkif->fds[WRITE] == -1) - return -1; - - DPRINTF("Attached to qemu blktap pipes\n"); - return 0; -} - -/* Launch tapdisk instance */ -static int connect_tapdisk(blkif_t *blkif, int minor) -{ - char *rdctldev = NULL, *wrctldev = NULL; - int ret = -1; - - DPRINTF("tapdisk process does not exist:\n"); - - if (asprintf(&rdctldev, - "%s/tapctrlread%d", BLKTAP_CTRL_DIR, minor) == -1) - goto fail; - - if (asprintf(&wrctldev, - "%s/tapctrlwrite%d", BLKTAP_CTRL_DIR, minor) == -1) - goto fail; - - blkif->fds[READ] = open_ctrl_socket(rdctldev); - blkif->fds[WRITE] = open_ctrl_socket(wrctldev); - - if (blkif->fds[READ] == -1 || blkif->fds[WRITE] == -1) - goto fail; - - /*launch the new process*/ - DPRINTF("Launching process, CMDLINE [tapdisk %s %s]\n", - wrctldev, rdctldev); - - if (launch_tapdisk(wrctldev, rdctldev) == -1) { - DPRINTF("Unable to fork, cmdline: [tapdisk %s %s]\n", - wrctldev, rdctldev); - goto fail; - } - - ret = 0; - -fail: - if (rdctldev) - free(rdctldev); - - if (wrctldev) - free(wrctldev); - - return ret; -} - -static int blktapctrl_new_blkif(blkif_t *blkif) -{ - blkif_info_t *blk; - int major, minor, fd_read, fd_write, type, new; - char *rdctldev, *wrctldev, *ptr; - image_t *image; - blkif_t *exist = NULL; - static uint16_t next_cookie = 0; - int use_ioemu; - - DPRINTF("Received a poll for a new vbd\n"); - if ( ((blk=blkif->info) != NULL) && (blk->params != NULL) ) { - if (blktap_interface_create(ctlfd, &major, &minor, blkif) < 0) - return -1; - - if (test_path(blk->params, &ptr, &type, &exist, &use_ioemu) != 0) { - DPRINTF("Error in blktap device string(%s).\n", - blk->params); - goto fail; - } - blkif->drivertype = type; - blkif->cookie = next_cookie++; - - if (!exist) { - if (use_ioemu) { - if (connect_qemu(blkif, blkif->domid)) - goto fail; - } else { - if (connect_tapdisk(blkif, minor)) - goto fail; - } - - } else { - DPRINTF("Process exists!\n"); - blkif->fds[READ] = exist->fds[READ]; - blkif->fds[WRITE] = exist->fds[WRITE]; - } - - add_disktype(blkif, type); - blkif->major = major; - blkif->minor = minor; - - image = (image_t *)malloc(sizeof(image_t)); - blkif->prv = (void *)image; - blkif->ops = &tapdisk_ops; - - /*Retrieve the PID of the new process*/ - if (get_tapdisk_pid(blkif) <= 0) { - DPRINTF("Unable to contact disk process\n"); - goto fail; - } - - /* Both of the following read and write calls will block up to - * max_timeout val*/ - if (write_msg(blkif->fds[WRITE], CTLMSG_PARAMS, blkif, ptr) - <= 0) { - DPRINTF("Write_msg failed - CTLMSG_PARAMS\n"); - goto fail; - } - - if (read_msg(blkif->fds[READ], CTLMSG_IMG, blkif) <= 0) { - DPRINTF("Read_msg failure - CTLMSG_IMG\n"); - goto fail; - } - - } else return -1; - - return 0; -fail: - ioctl(ctlfd, BLKTAP_IOCTL_FREEINTF, minor); - return -EINVAL; -} - -static int map_new_blktapctrl(blkif_t *blkif) -{ - DPRINTF("Received a poll for a new devmap\n"); - if (write_msg(blkif->fds[WRITE], CTLMSG_NEWDEV, blkif, NULL) <= 0) { - DPRINTF("Write_msg failed - CTLMSG_NEWDEV\n"); - return -EINVAL; - } - - if (read_msg(blkif->fds[READ], CTLMSG_NEWDEV_RSP, blkif) <= 0) { - DPRINTF("Read_msg failed - CTLMSG_NEWDEV_RSP\n"); - return -EINVAL; - } - DPRINTF("Exiting map_new_blktapctrl\n"); - - return blkif->minor - 1; -} - -static int unmap_blktapctrl(blkif_t *blkif) -{ - DPRINTF("Unmapping vbd\n"); - - if (write_msg(blkif->fds[WRITE], CTLMSG_CLOSE, blkif, NULL) <= 0) { - DPRINTF("Write_msg failed - CTLMSG_CLOSE\n"); - return -EINVAL; - } - - if (del_disktype(blkif)) { - DPRINTF("Closing communication pipe to pid %d\n", blkif->tappid); - close(blkif->fds[WRITE]); - close(blkif->fds[READ]); - } - - return 0; -} - -int open_ctrl_socket(char *devname) -{ - int ret; - int ipc_fd; - fd_set socks; - struct timeval timeout; - - if (mkdir(BLKTAP_CTRL_DIR, 0755) == 0) - DPRINTF("Created %s directory\n", BLKTAP_CTRL_DIR); - ret = mkfifo(devname,S_IRWXU|S_IRWXG|S_IRWXO); - if ( (ret != 0) && (errno != EEXIST) ) { - DPRINTF("ERROR: pipe failed (%d)\n", errno); - exit(0); - } - - ipc_fd = open(devname,O_RDWR|O_NONBLOCK); - - if (ipc_fd < 0) { - DPRINTF("FD open failed\n"); - return -1; - } - - return ipc_fd; -} - -static void print_drivers(void) -{ - int i, size; - - size = sizeof(dtypes)/sizeof(disk_info_t *); - DPRINTF("blktapctrl: v1.0.0\n"); - for (i = 0; i < size; i++) - DPRINTF("Found driver: [%s]\n",dtypes[i]->name); -} - -static void write_pidfile(long pid) -{ - char buf[100]; - int len; - int fd; - int flags; - - fd = open(PIDFILE, O_RDWR | O_CREAT, 0600); - if (fd == -1) { - DPRINTF("Opening pid file failed (%d)\n", errno); - exit(1); - } - - /* We exit silently if daemon already running. */ - if (lockf(fd, F_TLOCK, 0) == -1) - exit(0); - - /* Set FD_CLOEXEC, so that tapdisk doesn't get this file - descriptor. */ - if ((flags = fcntl(fd, F_GETFD)) == -1) { - DPRINTF("F_GETFD failed (%d)\n", errno); - exit(1); - } - flags |= FD_CLOEXEC; - if (fcntl(fd, F_SETFD, flags) == -1) { - DPRINTF("F_SETFD failed (%d)\n", errno); - exit(1); - } - - len = snprintf(buf, sizeof(buf), "%ld\n", pid); - if (write(fd, buf, len) != len) { - DPRINTF("Writing pid file failed (%d)\n", errno); - exit(1); - } -} - -int main(int argc, char *argv[]) -{ - char *devname; - tapdev_info_t *ctlinfo; - int tap_pfd, store_pfd, xs_fd, ret, timeout, pfd_count, count=0; - struct xs_handle *h; - struct pollfd pfd[NUM_POLL_FDS]; - pid_t process; - char buf[128]; - - __init_blkif(); - snprintf(buf, sizeof(buf), "BLKTAPCTRL[%d]", getpid()); - openlog(buf, LOG_CONS|LOG_ODELAY, LOG_DAEMON); - if (daemon(0,0)) { - DPRINTF("daemon failed (%d)\n", errno); - goto open_failed; - } - - print_drivers(); - init_driver_list(); - init_rng(); - - register_new_blkif_hook(blktapctrl_new_blkif); - register_new_devmap_hook(map_new_blktapctrl); - register_new_unmap_hook(unmap_blktapctrl); - - ctlfd = blktap_interface_open(); - if (ctlfd < 0) { - DPRINTF("couldn't open blktap interface\n"); - goto open_failed; - } - -#ifdef MEMSHR - memshr_daemon_initialize(); -#endif - - retry: - /* Set up store connection and watch. */ - h = xs_daemon_open(); - if (h == NULL) { - DPRINTF("xs_daemon_open failed -- " - "is xenstore running?\n"); - if (count < MAX_ATTEMPTS) { - count++; - sleep(2); - goto retry; - } else goto open_failed; - } - - ret = setup_probe_watch(h); - if (ret != 0) { - DPRINTF("Failed adding device probewatch\n"); - xs_daemon_close(h); - goto open_failed; - } - - ioctl(ctlfd, BLKTAP_IOCTL_SETMODE, BLKTAP_MODE_INTERPOSE ); - - process = getpid(); - write_pidfile(process); - ret = ioctl(ctlfd, BLKTAP_IOCTL_SENDPID, process ); - - /*Static pollhooks*/ - pfd_count = 0; - tap_pfd = pfd_count++; - pfd[tap_pfd].fd = ctlfd; - pfd[tap_pfd].events = POLLIN; - - store_pfd = pfd_count++; - pfd[store_pfd].fd = xs_fileno(h); - pfd[store_pfd].events = POLLIN; - - while (run) { - timeout = 1000; /*Milliseconds*/ - ret = poll(pfd, pfd_count, timeout); - - if (ret > 0) { - if (pfd[store_pfd].revents) { - ret = xs_fire_next_watch(h); - } - } - } - - xs_daemon_close(h); - ioctl(ctlfd, BLKTAP_IOCTL_SETMODE, BLKTAP_MODE_PASSTHROUGH ); - close(ctlfd); - closelog(); - - return 0; - - open_failed: - DPRINTF("Unable to start blktapctrl\n"); - closelog(); - return -1; -} - -/* - * Local variables: - * c-file-style: "linux" - * indent-tabs-mode: t - * c-indent-level: 8 - * c-basic-offset: 8 - * tab-width: 8 - * End: - */ diff --git a/tools/blktap/drivers/blktapctrl.h b/tools/blktap/drivers/blktapctrl.h deleted file mode 100644 index 4512807c70..0000000000 --- a/tools/blktap/drivers/blktapctrl.h +++ /dev/null @@ -1,36 +0,0 @@ -/* blktapctrl.h - * - * controller image utils. - * - * (c) 2004-6 Andrew Warfield and Julian Chesterfield - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation; or, when distributed - * separately from the Linux kernel or incorporated into other - * software packages, subject to the following license: - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this source file (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, modify, - * merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - - -int blktap_interface_open(void); - -int blktap_interface_create(int ctlfd, int *major, int *minor, blkif_t *blkif); - diff --git a/tools/blktap/drivers/blktapctrl_linux.c b/tools/blktap/drivers/blktapctrl_linux.c deleted file mode 100644 index 6282fa681a..0000000000 --- a/tools/blktap/drivers/blktapctrl_linux.c +++ /dev/null @@ -1,89 +0,0 @@ - -#include -#include -#include -#include - -#include "tapdisk.h" -#include "blktaplib.h" -#include "blktapctrl.h" - -static void make_blktap_dev(char *devname, int major, int minor) -{ - struct stat st; - - if (lstat(devname, &st) != 0) { - /*Need to create device*/ - if (mkdir(BLKTAP_DEV_DIR, 0755) == 0) - DPRINTF("Created %s directory\n",BLKTAP_DEV_DIR); - if (mknod(devname, S_IFCHR|0600, - makedev(major, minor)) == 0) - DPRINTF("Created %s device\n",devname); - } else { - DPRINTF("%s device already exists\n",devname); - /* it already exists, but is it the same major number */ - if (((st.st_rdev>>8) & 0xff) != major) { - DPRINTF("%s has old major %d\n", - devname, - (unsigned int)((st.st_rdev >> 8) & 0xff)); - /* only try again if we succed in deleting it */ - if (!unlink(devname)) - make_blktap_dev(devname, major, minor); - } - } -} - -int blktap_interface_create(int ctlfd, int *major, int *minor, blkif_t *blkif) -{ - domid_translate_t tr; - domid_translate_ext_t tr_ext; - int ret; - char *devname; - - if (blkif->be_id >= (1<<28)) { - /* new-style backend-id, so use the extended structure */ - tr_ext.domid = blkif->domid; - tr_ext.busid = blkif->be_id; - ret = ioctl(ctlfd, BLKTAP_IOCTL_NEWINTF_EXT, &tr_ext); - DPRINTF("Sent domid %d and be_id %d\n", tr_ext.domid, - tr_ext.busid); - } - else { - /* old-style backend-id; use the old structure */ - tr.domid = blkif->domid; - tr.busid = (unsigned short)blkif->be_id; - ret = ioctl(ctlfd, BLKTAP_IOCTL_NEWINTF, tr); - DPRINTF("Sent domid %d and be_id %d\n", tr.domid, tr.busid); - } - - if ( (ret <= 0)||(ret > MAX_TAP_DEV) ) { - DPRINTF("Incorrect Dev ID [%d]\n",ret); - return -1; - } - - *minor = ret; - *major = ioctl(ctlfd, BLKTAP_IOCTL_MAJOR, ret ); - if (*major < 0) { - DPRINTF("Incorrect Major ID [%d]\n",*major); - return -1; - } - - if (asprintf(&devname,"%s/%s%d",BLKTAP_DEV_DIR, BLKTAP_DEV_NAME, *minor) == -1) - return -1; - make_blktap_dev(devname,*major,*minor); - DPRINTF("Received device id %d and major %d\n", - *minor, *major); - return 0; -} - - -int blktap_interface_open(void) -{ - int ctlfd; - - ctlfd = open(BLKTAP_DEV_DIR "/" BLKTAP_DEV_NAME "0", O_RDWR); - if (ctlfd == -1) - DPRINTF("blktap0 open failed\n"); - - return ctlfd; -} diff --git a/tools/blktap/drivers/block-aio.c b/tools/blktap/drivers/block-aio.c deleted file mode 100644 index 98727f4ac9..0000000000 --- a/tools/blktap/drivers/block-aio.c +++ /dev/null @@ -1,259 +0,0 @@ -/* block-aio.c - * - * libaio-based raw disk implementation. - * - * (c) 2006 Andrew Warfield and Julian Chesterfield - * - * NB: This code is not thread-safe. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation; or, when distributed - * separately from the Linux kernel or incorporated into other - * software packages, subject to the following license: - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this source file (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, modify, - * merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "tapdisk.h" -#include "tapaio.h" -#include "blk.h" - -#define MAX_AIO_REQS (MAX_REQUESTS * MAX_SEGMENTS_PER_REQ) - -/* *BSD has no O_LARGEFILE */ -#ifndef O_LARGEFILE -#define O_LARGEFILE 0 -#endif - -struct tdaio_state { - int fd; - tap_aio_context_t aio; -}; - - -/*Get Image size, secsize*/ -static int get_image_info(struct td_state *s, int fd) -{ - int ret; - long size; - unsigned long total_size; - struct statvfs statBuf; - struct stat stat; - - ret = fstat(fd, &stat); - if (ret != 0) { - DPRINTF("ERROR: fstat failed, Couldn't stat image"); - return -EINVAL; - } - - if (S_ISBLK(stat.st_mode)) { - /*Accessing block device directly*/ - if (blk_getimagesize(fd, &s->size) != 0) - return -EINVAL; - - DPRINTF("Image size: \n\tpre sector_shift [%llu]\n\tpost " - "sector_shift [%llu]\n", - (long long unsigned)(s->size << SECTOR_SHIFT), - (long long unsigned)s->size); - - /*Get the sector size*/ - if (blk_getsectorsize(fd, &s->sector_size) != 0) - s->sector_size = DEFAULT_SECTOR_SIZE; - - } else { - /*Local file? try fstat instead*/ - s->size = (stat.st_size >> SECTOR_SHIFT); - s->sector_size = DEFAULT_SECTOR_SIZE; - DPRINTF("Image size: \n\tpre sector_shift [%llu]\n\tpost " - "sector_shift [%llu]\n", - (long long unsigned)(s->size << SECTOR_SHIFT), - (long long unsigned)s->size); - } - - if (s->size == 0) { - s->size =((uint64_t) 16836057); - s->sector_size = DEFAULT_SECTOR_SIZE; - } - s->info = 0; - - return 0; -} - -static inline void init_fds(struct disk_driver *dd) -{ - int i; - struct tdaio_state *prv = (struct tdaio_state *)dd->private; - - for(i = 0; i < MAX_IOFD; i++) - dd->io_fd[i] = 0; - - dd->io_fd[0] = prv->aio.aio_ctx.pollfd; -} - -/* Open the disk file and initialize aio state. */ -static int tdaio_open (struct disk_driver *dd, const char *name, td_flag_t flags) -{ - int i, fd, ret = 0, o_flags; - struct td_state *s = dd->td_state; - struct tdaio_state *prv = (struct tdaio_state *)dd->private; - - DPRINTF("block-aio open('%s')", name); - - /* Initialize AIO */ - ret = tap_aio_init(&prv->aio, 0, MAX_AIO_REQS); - if (ret != 0) - return ret; - - /* Open the file */ - o_flags = O_DIRECT | O_LARGEFILE | - ((flags == TD_RDONLY) ? O_RDONLY : O_RDWR); - fd = open(name, o_flags); - - if ( (fd == -1) && (errno == EINVAL) ) { - - /* Maybe O_DIRECT isn't supported. */ - o_flags &= ~O_DIRECT; - fd = open(name, o_flags); - if (fd != -1) DPRINTF("WARNING: Accessing image without" - "O_DIRECT! (%s)\n", name); - - } else if (fd != -1) DPRINTF("open(%s) with O_DIRECT\n", name); - - if (fd == -1) { - DPRINTF("Unable to open [%s] (%d)!\n", name, 0 - errno); - ret = 0 - errno; - goto done; - } - - prv->fd = fd; - - init_fds(dd); - ret = get_image_info(s, fd); - -done: - return ret; -} - -static int tdaio_queue_read(struct disk_driver *dd, uint64_t sector, - int nb_sectors, char *buf, td_callback_t cb, - int id, void *private) -{ - struct td_state *s = dd->td_state; - struct tdaio_state *prv = (struct tdaio_state *)dd->private; - int size = nb_sectors * s->sector_size; - uint64_t offset = sector * (uint64_t)s->sector_size; - - return tap_aio_read(&prv->aio, prv->fd, size, offset, buf, - cb, id, sector, private); -} - -static int tdaio_queue_write(struct disk_driver *dd, uint64_t sector, - int nb_sectors, char *buf, td_callback_t cb, - int id, void *private) -{ - struct td_state *s = dd->td_state; - struct tdaio_state *prv = (struct tdaio_state *)dd->private; - int size = nb_sectors * s->sector_size; - uint64_t offset = sector * (uint64_t)s->sector_size; - - return tap_aio_write(&prv->aio, prv->fd, size, offset, buf, - cb, id, sector, private); -} - -static int tdaio_submit(struct disk_driver *dd) -{ - struct tdaio_state *prv = (struct tdaio_state *)dd->private; - - return tap_aio_submit(&prv->aio); -} - -static int tdaio_close(struct disk_driver *dd) -{ - struct tdaio_state *prv = (struct tdaio_state *)dd->private; - - io_destroy(prv->aio.aio_ctx.aio_ctx); - close(prv->fd); - - return 0; -} - -static int tdaio_do_callbacks(struct disk_driver *dd, int sid) -{ - int i, nr_events, rsp = 0; - struct io_event *ep; - struct tdaio_state *prv = (struct tdaio_state *)dd->private; - - nr_events = tap_aio_get_events(&prv->aio.aio_ctx); -repeat: - for (ep = prv->aio.aio_events, i = nr_events; i-- > 0; ep++) { - struct iocb *io = ep->obj; - struct pending_aio *pio; - - pio = &prv->aio.pending_aio[(long)io->data]; - rsp += pio->cb(dd, ep->res == io->u.c.nbytes ? 0 : 1, - pio->sector, io->u.c.nbytes >> 9, - pio->id, pio->private); - - prv->aio.iocb_free[prv->aio.iocb_free_count++] = io; - } - - if (nr_events) { - nr_events = tap_aio_more_events(&prv->aio.aio_ctx); - goto repeat; - } - - tap_aio_continue(&prv->aio.aio_ctx); - - return rsp; -} - -static int tdaio_get_parent_id(struct disk_driver *dd, struct disk_id *id) -{ - return TD_NO_PARENT; -} - -static int tdaio_validate_parent(struct disk_driver *dd, - struct disk_driver *parent, td_flag_t flags) -{ - return -EINVAL; -} - -struct tap_disk tapdisk_aio = { - .disk_type = "tapdisk_aio", - .private_data_size = sizeof(struct tdaio_state), - .td_open = tdaio_open, - .td_queue_read = tdaio_queue_read, - .td_queue_write = tdaio_queue_write, - .td_submit = tdaio_submit, - .td_close = tdaio_close, - .td_do_callbacks = tdaio_do_callbacks, - .td_get_parent_id = tdaio_get_parent_id, - .td_validate_parent = tdaio_validate_parent -}; diff --git a/tools/blktap/drivers/block-qcow.c b/tools/blktap/drivers/block-qcow.c deleted file mode 100644 index 0e4e9cfe0a..0000000000 --- a/tools/blktap/drivers/block-qcow.c +++ /dev/null @@ -1,1434 +0,0 @@ -/* block-qcow.c - * - * Asynchronous Qemu copy-on-write disk implementation. - * Code based on the Qemu implementation - * (see copyright notice below) - * - * (c) 2006 Andrew Warfield and Julian Chesterfield - * - */ - -/* - * Block driver for the QCOW format - * - * Copyright (c) 2004 Fabrice Bellard - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files(the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "bswap.h" -#include "aes.h" -#include "tapdisk.h" -#include "tapaio.h" -#include "blk.h" - -/* *BSD has no O_LARGEFILE */ -#ifndef O_LARGEFILE -#define O_LARGEFILE 0 -#endif - -#if 1 -#define ASSERT(_p) \ - if ( !(_p) ) { DPRINTF("Assertion '%s' failed, line %d, file %s", #_p , \ - __LINE__, __FILE__); *(int*)0=0; } -#else -#define ASSERT(_p) ((void)0) -#endif - -#define ROUNDUP(l, s) \ -({ \ - (uint64_t)( \ - ((l) + ((s) - 1)) - (((l) + ((s) - 1)) % (s))); \ -}) - -#undef IOCB_IDX -#define IOCB_IDX(_s, _io) ((_io) - (_s)->iocb_list) - -#define ZERO_TEST(_b) (_b | 0x00) - -/**************************************************************/ -/* QEMU COW block driver with compression and encryption support */ - -#define QCOW_MAGIC (('Q' << 24) | ('F' << 16) | ('I' << 8) | 0xfb) -#define XEN_MAGIC (('X' << 24) | ('E' << 16) | ('N' << 8) | 0xfb) -#define QCOW_VERSION 1 - -#define QCOW_CRYPT_NONE 0x00 -#define QCOW_CRYPT_AES 0x01 - -#define QCOW_OFLAG_COMPRESSED (1LL << 63) -#define SPARSE_FILE 0x01 -#define EXTHDR_L1_BIG_ENDIAN 0x02 - -#ifndef O_BINARY -#define O_BINARY 0 -#endif - -typedef struct QCowHeader { - uint32_t magic; - uint32_t version; - uint64_t backing_file_offset; - uint32_t backing_file_size; - uint32_t mtime; - uint64_t size; /* in bytes */ - uint8_t cluster_bits; - uint8_t l2_bits; - uint32_t crypt_method; - uint64_t l1_table_offset; -} QCowHeader; - -/*Extended header for Xen enhancements*/ -typedef struct QCowHeader_ext { - uint32_t xmagic; - uint32_t cksum; - uint32_t min_cluster_alloc; - uint32_t flags; -} QCowHeader_ext; - -#define L2_CACHE_SIZE 16 /*Fixed allocation in Qemu*/ - -struct tdqcow_state { - int fd; /*Main Qcow file descriptor */ - uint64_t fd_end; /*Store a local record of file length */ - char *name; /*Record of the filename*/ - uint32_t backing_file_size; - uint64_t backing_file_offset; - int encrypted; /*File contents are encrypted or plain*/ - int cluster_bits; /*Determines length of cluster as - *indicated by file hdr*/ - int cluster_size; /*Length of cluster*/ - int cluster_sectors; /*Number of sectors per cluster*/ - int cluster_alloc; /*Blktap fix for allocating full - *extents*/ - int min_cluster_alloc; /*Blktap historical extent alloc*/ - int sparse; /*Indicates whether to preserve sparseness*/ - int l2_bits; /*Size of L2 table entry*/ - int l2_size; /*Full table size*/ - int l1_size; /*L1 table size*/ - uint64_t cluster_offset_mask; - uint64_t l1_table_offset; /*L1 table offset from beginning of - *file*/ - uint64_t *l1_table; /*L1 table entries*/ - uint64_t *l2_cache; /*We maintain a cache of size - *L2_CACHE_SIZE of most read entries*/ - uint64_t l2_cache_offsets[L2_CACHE_SIZE]; /*L2 cache entries*/ - uint32_t l2_cache_counts[L2_CACHE_SIZE]; /*Cache access record*/ - uint8_t *cluster_cache; - uint8_t *cluster_data; - uint64_t cluster_cache_offset; /**/ - uint32_t crypt_method; /*current crypt method, 0 if no - *key yet */ - uint32_t crypt_method_header; /**/ - AES_KEY aes_encrypt_key; /*AES key*/ - AES_KEY aes_decrypt_key; /*AES key*/ - - /* libaio state */ - tap_aio_context_t aio; -}; - -static int decompress_cluster(struct tdqcow_state *s, uint64_t cluster_offset); - -#ifdef USE_GCRYPT - -#include - -static uint32_t gen_cksum(char *ptr, int len) -{ - int i; - uint32_t md[4]; - - /* Convert L1 table to big endian */ - for(i = 0; i < len / sizeof(uint64_t); i++) { - cpu_to_be64s(&((uint64_t*) ptr)[i]); - } - - /* Generate checksum */ - gcry_md_hash_buffer(GCRY_MD_MD5, md, ptr, len); - - /* Convert L1 table back to native endianess */ - for(i = 0; i < len / sizeof(uint64_t); i++) { - be64_to_cpus(&((uint64_t*) ptr)[i]); - } - - return md[0]; -} - -#else /* use libcrypto */ - -#include - -static uint32_t gen_cksum(char *ptr, int len) -{ - int i; - unsigned char *md; - uint32_t ret; - - md = malloc(MD5_DIGEST_LENGTH); - if(!md) return 0; - - /* Convert L1 table to big endian */ - for(i = 0; i < len / sizeof(uint64_t); i++) { - cpu_to_be64s(&((uint64_t*) ptr)[i]); - } - - /* Generate checksum */ - if (MD5((unsigned char *)ptr, len, md) != md) - ret = 0; - else - memcpy(&ret, md, sizeof(uint32_t)); - - /* Convert L1 table back to native endianess */ - for(i = 0; i < len / sizeof(uint64_t); i++) { - be64_to_cpus(&((uint64_t*) ptr)[i]); - } - - free(md); - return ret; -} - -#endif - -static int get_filesize(char *filename, uint64_t *size, struct stat *st) -{ - int fd; - QCowHeader header; - - /*Set to the backing file size*/ - fd = open(filename, O_RDONLY); - if (fd < 0) - return -1; - if (read(fd, &header, sizeof(header)) < sizeof(header)) { - close(fd); - return -1; - } - close(fd); - - be32_to_cpus(&header.magic); - be64_to_cpus(&header.size); - if (header.magic == QCOW_MAGIC) { - *size = header.size >> SECTOR_SHIFT; - return 0; - } - - if(S_ISBLK(st->st_mode)) { - fd = open(filename, O_RDONLY); - if (fd < 0) - return -1; - if (blk_getimagesize(fd, size) != 0) { - close(fd); - return -1; - } - close(fd); - } else *size = (st->st_size >> SECTOR_SHIFT); - return 0; -} - -static int qcow_set_key(struct tdqcow_state *s, const char *key) -{ - uint8_t keybuf[16]; - int len, i; - - memset(keybuf, 0, 16); - len = strlen(key); - if (len > 16) - len = 16; - /* XXX: we could compress the chars to 7 bits to increase - entropy */ - for (i = 0; i < len; i++) { - keybuf[i] = key[i]; - } - s->crypt_method = s->crypt_method_header; - - if (AES_set_encrypt_key(keybuf, 128, &s->aes_encrypt_key) != 0) - return -1; - if (AES_set_decrypt_key(keybuf, 128, &s->aes_decrypt_key) != 0) - return -1; -#if 0 - /* test */ - { - uint8_t in[16]; - uint8_t out[16]; - uint8_t tmp[16]; - for (i=0; i<16; i++) - in[i] = i; - AES_encrypt(in, tmp, &s->aes_encrypt_key); - AES_decrypt(tmp, out, &s->aes_decrypt_key); - for (i = 0; i < 16; i++) - DPRINTF(" %02x", tmp[i]); - DPRINTF("\n"); - for (i = 0; i < 16; i++) - DPRINTF(" %02x", out[i]); - DPRINTF("\n"); - } -#endif - return 0; -} - -/* - * The crypt function is compatible with the linux cryptoloop - * algorithm for < 4 GB images. NOTE: out_buf == in_buf is - * supported . - */ -static void encrypt_sectors(struct tdqcow_state *s, int64_t sector_num, - uint8_t *out_buf, const uint8_t *in_buf, - int nb_sectors, int enc, - const AES_KEY *key) -{ - union { - uint64_t ll[2]; - uint8_t b[16]; - } ivec; - int i; - - for (i = 0; i < nb_sectors; i++) { - ivec.ll[0] = cpu_to_le64(sector_num); - ivec.ll[1] = 0; - AES_cbc_encrypt(in_buf, out_buf, 512, key, - ivec.b, enc); - sector_num++; - in_buf += 512; - out_buf += 512; - } -} - -static int qtruncate(int fd, off_t length, int sparse) -{ - int ret, i; - int current = 0, rem = 0; - uint64_t sectors; - struct stat st; - char *buf; - - /* If length is greater than the current file len - * we synchronously write zeroes to the end of the - * file, otherwise we truncate the length down - */ - ret = fstat(fd, &st); - if (ret == -1) - return -1; - if (S_ISBLK(st.st_mode)) - return 0; - - sectors = (length + DEFAULT_SECTOR_SIZE - 1)/DEFAULT_SECTOR_SIZE; - current = (st.st_size + DEFAULT_SECTOR_SIZE - 1)/DEFAULT_SECTOR_SIZE; - rem = st.st_size % DEFAULT_SECTOR_SIZE; - - /* If we are extending this file, we write zeros to the end -- - * this tries to ensure that the extents allocated wind up being - * contiguous on disk. - */ - if(st.st_size < sectors * DEFAULT_SECTOR_SIZE) { - /*We are extending the file*/ - if ((ret = posix_memalign((void **)&buf, - 512, DEFAULT_SECTOR_SIZE))) { - DPRINTF("posix_memalign failed: %d\n", ret); - return -1; - } - memset(buf, 0x00, DEFAULT_SECTOR_SIZE); - if (lseek(fd, 0, SEEK_END)==-1) { - DPRINTF("Lseek EOF failed (%d), internal error\n", - errno); - free(buf); - return -1; - } - if (rem) { - ret = write(fd, buf, rem); - if (ret != rem) { - DPRINTF("write failed: ret = %d, err = %s\n", - ret, strerror(errno)); - free(buf); - return -1; - } - } - for (i = current; i < sectors; i++ ) { - ret = write(fd, buf, DEFAULT_SECTOR_SIZE); - if (ret != DEFAULT_SECTOR_SIZE) { - DPRINTF("write failed: ret = %d, err = %s\n", - ret, strerror(errno)); - free(buf); - return -1; - } - } - free(buf); - } else if(sparse && (st.st_size > sectors * DEFAULT_SECTOR_SIZE)) - if (ftruncate(fd, (off_t)sectors * DEFAULT_SECTOR_SIZE)==-1) { - DPRINTF("Ftruncate failed (%s)\n", strerror(errno)); - return -1; - } - return 0; -} - - -/* 'allocate' is: - * - * 0 to not allocate. - * - * 1 to allocate a normal cluster (for sector indexes 'n_start' to - * 'n_end') - * - * 2 to allocate a compressed cluster of size - * 'compressed_size'. 'compressed_size' must be > 0 and < - * cluster_size - * - * return 0 if not allocated. - */ -static uint64_t get_cluster_offset(struct tdqcow_state *s, - uint64_t offset, int allocate, - int compressed_size, - int n_start, int n_end) -{ - int min_index, i, j, l1_index, l2_index, l2_sector, l1_sector; - char *tmp_ptr2, *l2_ptr, *l1_ptr; - uint64_t *tmp_ptr; - uint64_t l2_offset, *l2_table, cluster_offset, tmp; - uint32_t min_count; - int new_l2_table; - - /*Check L1 table for the extent offset*/ - l1_index = offset >> (s->l2_bits + s->cluster_bits); - l2_offset = s->l1_table[l1_index]; - new_l2_table = 0; - if (!l2_offset) { - if (!allocate) - return 0; - /* - * allocating a new l2 entry + extent - * at the end of the file, we must also - * update the L1 entry safely. - */ - l2_offset = s->fd_end; - - /* round to cluster size */ - l2_offset = (l2_offset + s->cluster_size - 1) - & ~(s->cluster_size - 1); - - /* update the L1 entry */ - s->l1_table[l1_index] = l2_offset; - tmp = cpu_to_be64(l2_offset); - - /*Truncate file for L2 table - *(initialised to zero in case we crash)*/ - if (qtruncate(s->fd, - l2_offset + (s->l2_size * sizeof(uint64_t)), - s->sparse) != 0) { - DPRINTF("ERROR truncating file\n"); - return 0; - } - s->fd_end = l2_offset + (s->l2_size * sizeof(uint64_t)); - - /*Update the L1 table entry on disk - * (for O_DIRECT we write 4KByte blocks)*/ - l1_sector = (l1_index * sizeof(uint64_t)) >> 12; - l1_ptr = (char *)s->l1_table + (l1_sector << 12); - - if (posix_memalign((void **)&tmp_ptr, 4096, 4096) != 0) { - DPRINTF("ERROR allocating memory for L1 table\n"); - } - memcpy(tmp_ptr, l1_ptr, 4096); - - /* Convert block to write to big endian */ - for(i = 0; i < 4096 / sizeof(uint64_t); i++) { - cpu_to_be64s(&tmp_ptr[i]); - } - - /* - * Issue non-asynchronous L1 write. - * For safety, we must ensure that - * entry is written before blocks. - */ - lseek(s->fd, s->l1_table_offset + (l1_sector << 12), SEEK_SET); - if (write(s->fd, tmp_ptr, 4096) != 4096) { - free(tmp_ptr); - return 0; - } - free(tmp_ptr); - - new_l2_table = 1; - goto cache_miss; - } else if (s->min_cluster_alloc == s->l2_size) { - /*Fast-track the request*/ - cluster_offset = l2_offset + (s->l2_size * sizeof(uint64_t)); - l2_index = (offset >> s->cluster_bits) & (s->l2_size - 1); - return cluster_offset + (l2_index * s->cluster_size); - } - - /*Check to see if L2 entry is already cached*/ - for (i = 0; i < L2_CACHE_SIZE; i++) { - if (l2_offset == s->l2_cache_offsets[i]) { - /* increment the hit count */ - if (++s->l2_cache_counts[i] == 0xffffffff) { - for (j = 0; j < L2_CACHE_SIZE; j++) { - s->l2_cache_counts[j] >>= 1; - } - } - l2_table = s->l2_cache + (i << s->l2_bits); - goto found; - } - } - -cache_miss: - /* not found: load a new entry in the least used one */ - min_index = 0; - min_count = 0xffffffff; - for (i = 0; i < L2_CACHE_SIZE; i++) { - if (s->l2_cache_counts[i] < min_count) { - min_count = s->l2_cache_counts[i]; - min_index = i; - } - } - l2_table = s->l2_cache + (min_index << s->l2_bits); - - /*If extent pre-allocated, read table from disk, - *otherwise write new table to disk*/ - if (new_l2_table) { - /*Should we allocate the whole extent? Adjustable parameter.*/ - if (s->cluster_alloc == s->l2_size) { - cluster_offset = l2_offset + - (s->l2_size * sizeof(uint64_t)); - cluster_offset = (cluster_offset + s->cluster_size - 1) - & ~(s->cluster_size - 1); - if (qtruncate(s->fd, cluster_offset + - (s->cluster_size * s->l2_size), - s->sparse) != 0) { - DPRINTF("ERROR truncating file\n"); - return 0; - } - s->fd_end = cluster_offset + - (s->cluster_size * s->l2_size); - for (i = 0; i < s->l2_size; i++) { - l2_table[i] = cpu_to_be64(cluster_offset + - (i*s->cluster_size)); - } - } else memset(l2_table, 0, s->l2_size * sizeof(uint64_t)); - - lseek(s->fd, l2_offset, SEEK_SET); - if (write(s->fd, l2_table, s->l2_size * sizeof(uint64_t)) != - s->l2_size * sizeof(uint64_t)) - return 0; - } else { - lseek(s->fd, l2_offset, SEEK_SET); - if (read(s->fd, l2_table, s->l2_size * sizeof(uint64_t)) != - s->l2_size * sizeof(uint64_t)) - return 0; - } - - /*Update the cache entries*/ - s->l2_cache_offsets[min_index] = l2_offset; - s->l2_cache_counts[min_index] = 1; - -found: - /*The extent is split into 's->l2_size' blocks of - *size 's->cluster_size'*/ - l2_index = (offset >> s->cluster_bits) & (s->l2_size - 1); - cluster_offset = be64_to_cpu(l2_table[l2_index]); - - if (!cluster_offset || - ((cluster_offset & QCOW_OFLAG_COMPRESSED) && allocate == 1) ) { - if (!allocate) - return 0; - - if ((cluster_offset & QCOW_OFLAG_COMPRESSED) && - (n_end - n_start) < s->cluster_sectors) { - /* cluster is already allocated but compressed, we must - decompress it in the case it is not completely - overwritten */ - if (decompress_cluster(s, cluster_offset) < 0) - return 0; - cluster_offset = lseek(s->fd, s->fd_end, SEEK_SET); - cluster_offset = (cluster_offset + s->cluster_size - 1) - & ~(s->cluster_size - 1); - /* write the cluster content - not asynchronous */ - lseek(s->fd, cluster_offset, SEEK_SET); - if (write(s->fd, s->cluster_cache, s->cluster_size) != - s->cluster_size) - return -1; - } else { - /* allocate a new cluster */ - cluster_offset = lseek(s->fd, s->fd_end, SEEK_SET); - if (allocate == 1) { - /* round to cluster size */ - cluster_offset = - (cluster_offset + s->cluster_size - 1) - & ~(s->cluster_size - 1); - if (qtruncate(s->fd, cluster_offset + - s->cluster_size, s->sparse)!=0) { - DPRINTF("ERROR truncating file\n"); - return 0; - } - s->fd_end = (cluster_offset + s->cluster_size); - /* if encrypted, we must initialize the cluster - content which won't be written */ - if (s->crypt_method && - (n_end - n_start) < s->cluster_sectors) { - uint64_t start_sect; - start_sect = (offset & - ~(s->cluster_size - 1)) - >> 9; - memset(s->cluster_data + 512, - 0xaa, 512); - for (i = 0; i < s->cluster_sectors;i++) - { - if (i < n_start || i >= n_end) - { - encrypt_sectors(s, start_sect + i, - s->cluster_data, - s->cluster_data + 512, 1, 1, - &s->aes_encrypt_key); - lseek(s->fd, cluster_offset + i * 512, SEEK_SET); - if (write(s->fd, s->cluster_data, 512) != 512) - return -1; - } - } - } - } else { - cluster_offset |= QCOW_OFLAG_COMPRESSED | - (uint64_t)compressed_size - << (63 - s->cluster_bits); - } - } - /* update L2 table */ - tmp = cpu_to_be64(cluster_offset); - l2_table[l2_index] = tmp; - - /*For IO_DIRECT we write 4KByte blocks*/ - l2_sector = (l2_index * sizeof(uint64_t)) >> 12; - l2_ptr = (char *)l2_table + (l2_sector << 12); - - if (posix_memalign((void **)&tmp_ptr2, 4096, 4096) != 0) { - DPRINTF("ERROR allocating memory for L1 table\n"); - } - memcpy(tmp_ptr2, l2_ptr, 4096); - lseek(s->fd, l2_offset + (l2_sector << 12), SEEK_SET); - if (write(s->fd, tmp_ptr2, 4096) != 4096) { - free(tmp_ptr2); - return -1; - } - free(tmp_ptr2); - } - return cluster_offset; -} - -static void init_cluster_cache(struct disk_driver *dd) -{ - struct td_state *bs = dd->td_state; - struct tdqcow_state *s = (struct tdqcow_state *)dd->private; - uint32_t count = 0; - int i, cluster_entries; - - cluster_entries = s->cluster_size / 512; - DPRINTF("Initialising Cluster cache, %d sectors per cluster (%d cluster size)\n", - cluster_entries, s->cluster_size); - - for (i = 0; i < bs->size; i += cluster_entries) { - if (get_cluster_offset(s, i << 9, 0, 0, 0, 1)) count++; - if (count >= L2_CACHE_SIZE) return; - } - DPRINTF("Finished cluster initialisation, added %d entries\n", count); - return; -} - -static int qcow_is_allocated(struct tdqcow_state *s, int64_t sector_num, - int nb_sectors, int *pnum) -{ - int index_in_cluster, n; - uint64_t cluster_offset; - - cluster_offset = get_cluster_offset(s, sector_num << 9, 0, 0, 0, 0); - index_in_cluster = sector_num & (s->cluster_sectors - 1); - n = s->cluster_sectors - index_in_cluster; - if (n > nb_sectors) - n = nb_sectors; - *pnum = n; - return (cluster_offset != 0); -} - -static int decompress_buffer(uint8_t *out_buf, int out_buf_size, - const uint8_t *buf, int buf_size) -{ - z_stream strm1, *strm = &strm1; - int ret, out_len; - - memset(strm, 0, sizeof(*strm)); - - strm->next_in = (uint8_t *)buf; - strm->avail_in = buf_size; - strm->next_out = out_buf; - strm->avail_out = out_buf_size; - - ret = inflateInit2(strm, -12); - if (ret != Z_OK) - return -1; - ret = inflate(strm, Z_FINISH); - out_len = strm->next_out - out_buf; - if ( (ret != Z_STREAM_END && ret != Z_BUF_ERROR) || - (out_len != out_buf_size) ) { - inflateEnd(strm); - return -1; - } - inflateEnd(strm); - return 0; -} - -static int decompress_cluster(struct tdqcow_state *s, uint64_t cluster_offset) -{ - int ret, csize; - uint64_t coffset; - - coffset = cluster_offset & s->cluster_offset_mask; - if (s->cluster_cache_offset != coffset) { - csize = cluster_offset >> (63 - s->cluster_bits); - csize &= (s->cluster_size - 1); - lseek(s->fd, coffset, SEEK_SET); - ret = read(s->fd, s->cluster_data, csize); - if (ret != csize) - return -1; - if (decompress_buffer(s->cluster_cache, s->cluster_size, - s->cluster_data, csize) < 0) { - return -1; - } - s->cluster_cache_offset = coffset; - } - return 0; -} - -static inline void init_fds(struct disk_driver *dd) -{ - int i; - struct tdqcow_state *s = (struct tdqcow_state *)dd->private; - - for(i = 0; i < MAX_IOFD; i++) - dd->io_fd[i] = 0; - - dd->io_fd[0] = s->aio.aio_ctx.pollfd; -} - -/* Open the disk file and initialize qcow state. */ -static int tdqcow_open (struct disk_driver *dd, const char *name, td_flag_t flags) -{ - int fd, len, i, shift, ret, size, l1_table_size, o_flags, l1_table_block; - int max_aio_reqs; - struct td_state *bs = dd->td_state; - struct tdqcow_state *s = (struct tdqcow_state *)dd->private; - char *buf, *buf2; - QCowHeader *header; - QCowHeader_ext *exthdr; - uint32_t cksum; - uint64_t final_cluster = 0; - - DPRINTF("QCOW: Opening %s\n",name); - - o_flags = O_DIRECT | O_LARGEFILE | - ((flags == TD_RDONLY) ? O_RDONLY : O_RDWR); - fd = open(name, o_flags); - if (fd < 0) { - DPRINTF("Unable to open %s (%d)\n",name,0 - errno); - return -1; - } - - s->fd = fd; - if (asprintf(&s->name,"%s", name) == -1) { - close(fd); - return -1; - } - - ASSERT(sizeof(QCowHeader) + sizeof(QCowHeader_ext) < 512); - - ret = posix_memalign((void **)&buf, 512, 512); - if (ret != 0) goto fail; - - if (read(fd, buf, 512) != 512) - goto fail; - - header = (QCowHeader *)buf; - be32_to_cpus(&header->magic); - be32_to_cpus(&header->version); - be64_to_cpus(&header->backing_file_offset); - be32_to_cpus(&header->backing_file_size); - be32_to_cpus(&header->mtime); - be64_to_cpus(&header->size); - be32_to_cpus(&header->crypt_method); - be64_to_cpus(&header->l1_table_offset); - - if (header->magic != QCOW_MAGIC) - goto fail; - - switch (header->version) { - case QCOW_VERSION: - break; - case 2: - close(fd); - dd->drv = &tapdisk_qcow2; - return dd->drv->td_open(dd, name, flags); - default: - goto fail; - } - - if (header->size <= 1 || header->cluster_bits < 9) - goto fail; - if (header->crypt_method > QCOW_CRYPT_AES) - goto fail; - s->crypt_method_header = header->crypt_method; - if (s->crypt_method_header) - s->encrypted = 1; - s->cluster_bits = header->cluster_bits; - s->cluster_size = 1 << s->cluster_bits; - s->cluster_sectors = 1 << (s->cluster_bits - 9); - s->l2_bits = header->l2_bits; - s->l2_size = 1 << s->l2_bits; - s->cluster_alloc = s->l2_size; - bs->size = header->size / 512; - s->cluster_offset_mask = (1LL << (63 - s->cluster_bits)) - 1; - s->backing_file_offset = header->backing_file_offset; - s->backing_file_size = header->backing_file_size; - - /* read the level 1 table */ - shift = s->cluster_bits + s->l2_bits; - s->l1_size = ROUNDUP(header->size, 1LL << shift); - - s->l1_table_offset = header->l1_table_offset; - - /*allocate a 4Kbyte multiple of memory*/ - l1_table_size = s->l1_size * sizeof(uint64_t); - if (l1_table_size % 4096 > 0) { - l1_table_size = ROUNDUP(l1_table_size, 4096); - } - ret = posix_memalign((void **)&s->l1_table, 4096, l1_table_size); - if (ret != 0) goto fail; - - memset(s->l1_table, 0x00, l1_table_size); - - DPRINTF("L1 Table offset detected: %llu, size %d (%d)\n", - (long long)s->l1_table_offset, - (int) (s->l1_size * sizeof(uint64_t)), - l1_table_size); - - lseek(fd, 0, SEEK_SET); - l1_table_block = l1_table_size + s->l1_table_offset; - l1_table_block = ROUNDUP(l1_table_block, 512); - ret = posix_memalign((void **)&buf2, 4096, l1_table_block); - if (ret != 0) goto fail; - if (read(fd, buf2, l1_table_block) < l1_table_size + s->l1_table_offset) - goto fail; - memcpy(s->l1_table, buf2 + s->l1_table_offset, l1_table_size); - - for(i = 0; i < s->l1_size; i++) { - be64_to_cpus(&s->l1_table[i]); - //DPRINTF("L1[%d] => %llu\n", i, s->l1_table[i]); - if (s->l1_table[i] > final_cluster) - final_cluster = s->l1_table[i]; - } - - /* alloc L2 cache */ - size = s->l2_size * L2_CACHE_SIZE * sizeof(uint64_t); - ret = posix_memalign((void **)&s->l2_cache, 4096, size); - if(ret != 0) goto fail; - - size = s->cluster_size; - ret = posix_memalign((void **)&s->cluster_cache, 4096, size); - if(ret != 0) goto fail; - - ret = posix_memalign((void **)&s->cluster_data, 4096, size); - if(ret != 0) goto fail; - s->cluster_cache_offset = -1; - - if (s->backing_file_offset != 0) - s->cluster_alloc = 1; /*Cannot use pre-alloc*/ - - bs->sector_size = 512; - bs->info = 0; - - /*Detect min_cluster_alloc*/ - s->min_cluster_alloc = 1; /*Default*/ - if (s->backing_file_offset == 0 && s->l1_table_offset % 4096 == 0) { - /*We test to see if the xen magic # exists*/ - exthdr = (QCowHeader_ext *)(buf + sizeof(QCowHeader)); - be32_to_cpus(&exthdr->xmagic); - if(exthdr->xmagic != XEN_MAGIC) - goto end_xenhdr; - - be32_to_cpus(&exthdr->flags); - /* Try to detect old tapdisk images. They have to be fixed because - * they don't use big endian but native endianess for the L1 table */ - if ((exthdr->flags & EXTHDR_L1_BIG_ENDIAN) == 0) { - QCowHeader_ext *tmphdr = (QCowHeader_ext *)(buf2 + sizeof(QCowHeader)); - /* - The image is broken. Fix it. The L1 table has already been - byte-swapped, so we can write it to the image file as it is - currently in memory. Then swap it back to native endianess - for operation. - */ - - /* Change ENDIAN flag and copy it to store buffer */ - exthdr->flags |= EXTHDR_L1_BIG_ENDIAN; - tmphdr->flags = cpu_to_be32(exthdr->flags); - - - DPRINTF("qcow: Converting image to big endian L1 table\n"); - - memcpy(buf2 + s->l1_table_offset, s->l1_table, l1_table_size); - lseek(fd, 0, SEEK_SET); - if (write(fd, buf2, l1_table_block) < - l1_table_size + s->l1_table_offset) { - DPRINTF("qcow: Failed to write new L1 table\n"); - goto fail; - } - - for(i = 0;i < s->l1_size; i++) { - cpu_to_be64s(&s->l1_table[i]); - } - - } - - /*Finally check the L1 table cksum*/ - be32_to_cpus(&exthdr->cksum); - cksum = gen_cksum((char *)s->l1_table, - s->l1_size * sizeof(uint64_t)); - if(exthdr->cksum != cksum) - goto end_xenhdr; - - be32_to_cpus(&exthdr->min_cluster_alloc); - s->sparse = (exthdr->flags & SPARSE_FILE); - s->min_cluster_alloc = exthdr->min_cluster_alloc; - } - - end_xenhdr: - - /* A segment (i.e. a page) can span multiple clusters */ - max_aio_reqs = ((getpagesize() / s->cluster_size) + 1) * - MAX_SEGMENTS_PER_REQ * MAX_REQUESTS; - - if (tap_aio_init(&s->aio, bs->size, max_aio_reqs)!=0) { - DPRINTF("Unable to initialise AIO state\n"); - tap_aio_free(&s->aio); - goto fail; - } - init_fds(dd); - - if (!final_cluster) - s->fd_end = l1_table_block; - else { - s->fd_end = lseek(fd, 0, SEEK_END); - if (s->fd_end == (off_t)-1) - goto fail; - } - - return 0; - -fail: - DPRINTF("QCOW Open failed\n"); - tap_aio_free(&s->aio); - free(s->l1_table); - free(s->l2_cache); - free(s->cluster_cache); - free(s->cluster_data); - close(fd); - return -1; -} - -static int tdqcow_queue_read(struct disk_driver *dd, uint64_t sector, - int nb_sectors, char *buf, td_callback_t cb, - int id, void *private) -{ - struct tdqcow_state *s = (struct tdqcow_state *)dd->private; - int ret = 0, index_in_cluster, n, i, rsp = 0; - uint64_t cluster_offset, sec, nr_secs; - - sec = sector; - nr_secs = nb_sectors; - - /*Check we can get a lock*/ - for (i = 0; i < nb_sectors; i++) - if (!tap_aio_can_lock(&s->aio, sector + i)) - return cb(dd, -EBUSY, sector, nb_sectors, id, private); - - /*We store a local record of the request*/ - while (nb_sectors > 0) { - cluster_offset = - get_cluster_offset(s, sector << 9, 0, 0, 0, 0); - index_in_cluster = sector & (s->cluster_sectors - 1); - n = s->cluster_sectors - index_in_cluster; - if (n > nb_sectors) - n = nb_sectors; - - if (s->aio.iocb_free_count == 0 || !tap_aio_lock(&s->aio, sector)) - return cb(dd, -EBUSY, sector, nb_sectors, id, private); - - if(!cluster_offset) { - tap_aio_unlock(&s->aio, sector); - ret = cb(dd, BLK_NOT_ALLOCATED, - sector, n, id, private); - if (ret == -EBUSY) { - /* mark remainder of request - * as busy and try again later */ - return cb(dd, -EBUSY, sector + n, - nb_sectors - n, id, private); - } else - rsp += ret; - } else if (cluster_offset & QCOW_OFLAG_COMPRESSED) { - tap_aio_unlock(&s->aio, sector); - if (decompress_cluster(s, cluster_offset) < 0) { - rsp += cb(dd, -EIO, sector, - nb_sectors, id, private); - goto done; - } - memcpy(buf, s->cluster_cache + index_in_cluster * 512, - 512 * n); - rsp += cb(dd, 0, sector, n, id, private); - } else { - tap_aio_read(&s->aio, s->fd, n * 512, - (cluster_offset + index_in_cluster * 512), - buf, cb, id, sector, private); - } - nb_sectors -= n; - sector += n; - buf += n * 512; - } -done: - return rsp; -} - -static int tdqcow_queue_write(struct disk_driver *dd, uint64_t sector, - int nb_sectors, char *buf, td_callback_t cb, - int id, void *private) -{ - struct tdqcow_state *s = (struct tdqcow_state *)dd->private; - int ret = 0, index_in_cluster, n, i; - uint64_t cluster_offset, sec, nr_secs; - - sec = sector; - nr_secs = nb_sectors; - - /*Check we can get a lock*/ - for (i = 0; i < nb_sectors; i++) - if (!tap_aio_can_lock(&s->aio, sector + i)) - return cb(dd, -EBUSY, sector, nb_sectors, id, private); - - /*We store a local record of the request*/ - while (nb_sectors > 0) { - index_in_cluster = sector & (s->cluster_sectors - 1); - n = s->cluster_sectors - index_in_cluster; - if (n > nb_sectors) - n = nb_sectors; - - if (s->aio.iocb_free_count == 0 || !tap_aio_lock(&s->aio, sector)) - return cb(dd, -EBUSY, sector, nb_sectors, id, private); - - cluster_offset = get_cluster_offset(s, sector << 9, 1, 0, - index_in_cluster, - index_in_cluster+n); - if (!cluster_offset) { - DPRINTF("Ooops, no write cluster offset!\n"); - tap_aio_unlock(&s->aio, sector); - return cb(dd, -EIO, sector, nb_sectors, id, private); - } - - if (s->crypt_method) { - encrypt_sectors(s, sector, s->cluster_data, - (unsigned char *)buf, n, 1, - &s->aes_encrypt_key); - tap_aio_write(&s->aio, s->fd, n * 512, - (cluster_offset + index_in_cluster*512), - (char *)s->cluster_data, cb, id, sector, - private); - } else { - tap_aio_write(&s->aio, s->fd, n * 512, - (cluster_offset + index_in_cluster*512), - buf, cb, id, sector, private); - } - - nb_sectors -= n; - sector += n; - buf += n * 512; - } - s->cluster_cache_offset = -1; /* disable compressed cache */ - - return 0; -} - -static int tdqcow_submit(struct disk_driver *dd) -{ - struct tdqcow_state *prv = (struct tdqcow_state *)dd->private; - - return tap_aio_submit(&prv->aio); -} - -static int tdqcow_close(struct disk_driver *dd) -{ - struct tdqcow_state *s = (struct tdqcow_state *)dd->private; - uint32_t cksum, out; - int fd, offset; - - /*Update the hdr cksum*/ - if(s->min_cluster_alloc == s->l2_size) { - cksum = gen_cksum((char *)s->l1_table, s->l1_size * sizeof(uint64_t)); - printf("Writing cksum: %d",cksum); - fd = open(s->name, O_WRONLY | O_LARGEFILE); /*Open without O_DIRECT*/ - offset = sizeof(QCowHeader) + sizeof(uint32_t); - lseek(fd, offset, SEEK_SET); - out = cpu_to_be32(cksum); - if (write(fd, &out, sizeof(uint32_t))) ; - close(fd); - } - - io_destroy(s->aio.aio_ctx.aio_ctx); - free(s->name); - free(s->l1_table); - free(s->l2_cache); - free(s->cluster_cache); - free(s->cluster_data); - close(s->fd); - return 0; -} - -static int tdqcow_do_callbacks(struct disk_driver *dd, int sid) -{ - int ret, i, nr_events, rsp = 0,*ptr; - struct io_event *ep; - struct tdqcow_state *prv = (struct tdqcow_state *)dd->private; - - if (sid > MAX_IOFD) return 1; - - nr_events = tap_aio_get_events(&prv->aio.aio_ctx); -repeat: - for (ep = prv->aio.aio_events, i = nr_events; i-- > 0; ep++) { - struct iocb *io = ep->obj; - struct pending_aio *pio; - - pio = &prv->aio.pending_aio[(long)io->data]; - - tap_aio_unlock(&prv->aio, pio->sector); - - if (prv->crypt_method) - encrypt_sectors(prv, pio->sector, - (unsigned char *)pio->buf, - (unsigned char *)pio->buf, - pio->nb_sectors, 0, - &prv->aes_decrypt_key); - - rsp += pio->cb(dd, ep->res == io->u.c.nbytes ? 0 : 1, - pio->sector, pio->nb_sectors, - pio->id, pio->private); - - prv->aio.iocb_free[prv->aio.iocb_free_count++] = io; - } - - if (nr_events) { - nr_events = tap_aio_more_events(&prv->aio.aio_ctx); - goto repeat; - } - - tap_aio_continue(&prv->aio.aio_ctx); - - return rsp; -} - -int qcow_create(const char *filename, uint64_t total_size, - const char *backing_file, int sparse) -{ - int fd, header_size, backing_filename_len, l1_size, i; - int shift, length, adjust, flags = 0, ret = 0; - QCowHeader header; - QCowHeader_ext exthdr; - char backing_filename[PATH_MAX], *ptr; - uint64_t tmp, size, total_length; - struct stat st; - - DPRINTF("Qcow_create: size %llu\n",(long long unsigned)total_size); - - fd = open(filename, - O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE, - 0644); - if (fd < 0) - return -1; - - memset(&header, 0, sizeof(header)); - header.magic = cpu_to_be32(QCOW_MAGIC); - header.version = cpu_to_be32(QCOW_VERSION); - - /*Create extended header fields*/ - exthdr.xmagic = cpu_to_be32(XEN_MAGIC); - - header_size = sizeof(header) + sizeof(QCowHeader_ext); - backing_filename_len = 0; - size = (total_size >> SECTOR_SHIFT); - if (backing_file) { - if (strcmp(backing_file, "fat:")) { - const char *p; - /* XXX: this is a hack: we do not attempt to - *check for URL like syntax */ - p = strchr(backing_file, ':'); - if (p && (p - backing_file) >= 2) { - /* URL like but exclude "c:" like filenames */ - strncpy(backing_filename, backing_file, - sizeof(backing_filename)); - } else { - if (realpath(backing_file, backing_filename) == NULL || - stat(backing_filename, &st) != 0) { - return -1; - } - } - header.backing_file_offset = cpu_to_be64(header_size); - backing_filename_len = strlen(backing_filename); - header.backing_file_size = cpu_to_be32( - backing_filename_len); - header_size += backing_filename_len; - - /*Set to the backing file size*/ - if(get_filesize(backing_filename, &size, &st)) { - return -1; - } - DPRINTF("Backing file size detected: %lld sectors" - "(total %lld [%lld MB])\n", - (long long)size, - (long long)(size << SECTOR_SHIFT), - (long long)(size >> 11)); - } else { - backing_file = NULL; - DPRINTF("Setting file size: %lld (total %lld)\n", - (long long) total_size, - (long long) (total_size << SECTOR_SHIFT)); - } - header.mtime = cpu_to_be32(st.st_mtime); - header.cluster_bits = 9; /* 512 byte cluster to avoid copying - unmodifyed sectors */ - header.l2_bits = 12; /* 32 KB L2 tables */ - exthdr.min_cluster_alloc = cpu_to_be32(1); - } else { - DPRINTF("Setting file size: %lld sectors" - "(total %lld [%lld MB])\n", - (long long) size, - (long long) (size << SECTOR_SHIFT), - (long long) (size >> 11)); - header.cluster_bits = 12; /* 4 KB clusters */ - header.l2_bits = 9; /* 4 KB L2 tables */ - exthdr.min_cluster_alloc = cpu_to_be32(1 << 9); - } - /*Set the header size value*/ - header.size = cpu_to_be64(size * 512); - - header_size = (header_size + 7) & ~7; - if (header_size % 4096 > 0) { - header_size = ROUNDUP(header_size, 4096); - } - - shift = header.cluster_bits + header.l2_bits; - l1_size = ROUNDUP(size * 512, 1LL << shift); - - header.l1_table_offset = cpu_to_be64(header_size); - DPRINTF("L1 Table offset: %d, size %d\n", - header_size, - (int)(l1_size * sizeof(uint64_t))); - header.crypt_method = cpu_to_be32(QCOW_CRYPT_NONE); - - ptr = calloc(1, l1_size * sizeof(uint64_t)); - exthdr.cksum = cpu_to_be32(gen_cksum(ptr, l1_size * sizeof(uint64_t))); - printf("Created cksum: %d\n",exthdr.cksum); - free(ptr); - - /*adjust file length to system page size boundary*/ - length = ROUNDUP(header_size + (l1_size * sizeof(uint64_t)), - getpagesize()); - if (qtruncate(fd, length, 0)!=0) { - DPRINTF("ERROR truncating file\n"); - return -1; - } - - if (sparse == 0) { - /*Filesize is length+l1_size*(1 << s->l2_bits)+(size*512)*/ - total_length = length + (l1_size * (1 << 9)) + (size * 512); - if (qtruncate(fd, total_length, 0)!=0) { - DPRINTF("ERROR truncating file\n"); - return -1; - } - printf("File truncated to length %"PRIu64"\n",total_length); - } else - flags = SPARSE_FILE; - - flags |= EXTHDR_L1_BIG_ENDIAN; - exthdr.flags = cpu_to_be32(flags); - - /* write all the data */ - lseek(fd, 0, SEEK_SET); - ret += write(fd, &header, sizeof(header)); - ret += write(fd, &exthdr, sizeof(exthdr)); - if (backing_file) - ret += write(fd, backing_filename, backing_filename_len); - - lseek(fd, header_size, SEEK_SET); - tmp = 0; - for (i = 0;i < l1_size; i++) { - ret += write(fd, &tmp, sizeof(tmp)); - } - - close(fd); - - return 0; -} - -static int qcow_make_empty(struct tdqcow_state *s) -{ - uint32_t l1_length = s->l1_size * sizeof(uint64_t); - - memset(s->l1_table, 0, l1_length); - lseek(s->fd, s->l1_table_offset, SEEK_SET); - if (write(s->fd, s->l1_table, l1_length) < 0) - return -1; - if (qtruncate(s->fd, s->l1_table_offset + l1_length, s->sparse)!=0) { - DPRINTF("ERROR truncating file\n"); - return -1; - } - - memset(s->l2_cache, 0, s->l2_size * L2_CACHE_SIZE * sizeof(uint64_t)); - memset(s->l2_cache_offsets, 0, L2_CACHE_SIZE * sizeof(uint64_t)); - memset(s->l2_cache_counts, 0, L2_CACHE_SIZE * sizeof(uint32_t)); - - return 0; -} - -static int qcow_get_cluster_size(struct tdqcow_state *s) -{ - return s->cluster_size; -} - -/* XXX: put compressed sectors first, then all the cluster aligned - tables to avoid losing bytes in alignment */ -static int qcow_compress_cluster(struct tdqcow_state *s, int64_t sector_num, - const uint8_t *buf) -{ - z_stream strm; - int ret, out_len; - uint8_t *out_buf; - uint64_t cluster_offset; - - out_buf = malloc(s->cluster_size + (s->cluster_size / 1000) + 128); - if (!out_buf) - return -1; - - /* best compression, small window, no zlib header */ - memset(&strm, 0, sizeof(strm)); - ret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION, - Z_DEFLATED, -12, - 9, Z_DEFAULT_STRATEGY); - if (ret != 0) { - free(out_buf); - return -1; - } - - strm.avail_in = s->cluster_size; - strm.next_in = (uint8_t *)buf; - strm.avail_out = s->cluster_size; - strm.next_out = out_buf; - - ret = deflate(&strm, Z_FINISH); - if (ret != Z_STREAM_END && ret != Z_OK) { - free(out_buf); - deflateEnd(&strm); - return -1; - } - out_len = strm.next_out - out_buf; - - deflateEnd(&strm); - - if (ret != Z_STREAM_END || out_len >= s->cluster_size) { - /* could not compress: write normal cluster */ - //tdqcow_queue_write(bs, sector_num, buf, s->cluster_sectors); - } else { - cluster_offset = get_cluster_offset(s, sector_num << 9, 2, - out_len, 0, 0); - cluster_offset &= s->cluster_offset_mask; - lseek(s->fd, cluster_offset, SEEK_SET); - if (write(s->fd, out_buf, out_len) != out_len) { - free(out_buf); - return -1; - } - } - - free(out_buf); - return 0; -} - -static int tdqcow_get_parent_id(struct disk_driver *dd, struct disk_id *id) -{ - off_t off; - char *buf, *filename; - int len, secs, err = -EINVAL; - struct tdqcow_state *child = (struct tdqcow_state *)dd->private; - - if (!child->backing_file_offset) - return TD_NO_PARENT; - - /* read the backing file name */ - len = child->backing_file_size; - off = child->backing_file_offset - (child->backing_file_offset % 512); - secs = (len + (child->backing_file_offset - off) + 511) >> 9; - - if (posix_memalign((void **)&buf, 512, secs << 9)) - return -1; - - if (lseek(child->fd, off, SEEK_SET) == (off_t)-1) - goto out; - - if (read(child->fd, buf, secs << 9) != secs << 9) - goto out; - filename = buf + (child->backing_file_offset - off); - filename[len] = '\0'; - - id->name = strdup(filename); - id->drivertype = DISK_TYPE_AIO; - err = 0; - out: - free(buf); - return err; -} - -static int tdqcow_validate_parent(struct disk_driver *child, - struct disk_driver *parent, td_flag_t flags) -{ - struct stat stats; - uint64_t psize, csize; - - if (stat(parent->name, &stats)) - return -EINVAL; - if (get_filesize(parent->name, &psize, &stats)) - return -EINVAL; - - if (stat(child->name, &stats)) - return -EINVAL; - if (get_filesize(child->name, &csize, &stats)) - return -EINVAL; - - if (csize != psize) - return -EINVAL; - - return 0; -} - -struct tap_disk tapdisk_qcow = { - .disk_type = "tapdisk_qcow", - .private_data_size = sizeof(struct tdqcow_state), - .td_open = tdqcow_open, - .td_queue_read = tdqcow_queue_read, - .td_queue_write = tdqcow_queue_write, - .td_submit = tdqcow_submit, - .td_close = tdqcow_close, - .td_do_callbacks = tdqcow_do_callbacks, - .td_get_parent_id = tdqcow_get_parent_id, - .td_validate_parent = tdqcow_validate_parent -}; diff --git a/tools/blktap/drivers/block-qcow2.c b/tools/blktap/drivers/block-qcow2.c deleted file mode 100644 index ceda4f0124..0000000000 --- a/tools/blktap/drivers/block-qcow2.c +++ /dev/null @@ -1,2098 +0,0 @@ -/* - * Block driver for the QCOW version 2 format - * - * Copyright (c) 2004-2006 Fabrice Bellard - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include "aes.h" -#include -#include -#include -#include -#include -#include -#include - -#include "tapdisk.h" -#include "tapaio.h" -#include "bswap.h" -#include "blk.h" - -#define USE_AIO - -#define qemu_malloc malloc -#define qemu_mallocz(size) calloc(1, size) -#define qemu_free free - -#ifndef O_BINARY -#define O_BINARY 0 -#endif - -/* *BSD has no O_LARGEFILE */ -#ifndef O_LARGEFILE -#define O_LARGEFILE 0 -#endif - -#define BLOCK_FLAG_ENCRYPT 1 - -/* - Differences with QCOW: - - - Support for multiple incremental snapshots. - - Memory management by reference counts. - - Clusters which have a reference count of one have the bit - QCOW_OFLAG_COPIED to optimize write performance. - - Size of compressed clusters is stored in sectors to reduce bit usage - in the cluster offsets. - - Support for storing additional data (such as the VM state) in the - snapshots. - - If a backing store is used, the cluster size is not constrained - (could be backported to QCOW). - - L2 tables have always a size of one cluster. -*/ - -//#define DEBUG_ALLOC -//#define DEBUG_ALLOC2 - -#define QCOW_MAGIC (('Q' << 24) | ('F' << 16) | ('I' << 8) | 0xfb) -#define QCOW_VERSION 2 - -#define QCOW_CRYPT_NONE 0 -#define QCOW_CRYPT_AES 1 - -/* indicate that the refcount of the referenced cluster is exactly one. */ -#define QCOW_OFLAG_COPIED (1LL << 63) -/* indicate that the cluster is compressed (they never have the copied flag) */ -#define QCOW_OFLAG_COMPRESSED (1LL << 62) - -#define REFCOUNT_SHIFT 1 /* refcount size is 2 bytes */ - -#ifndef offsetof -#define offsetof(type, field) ((size_t) &((type *)0)->field) -#endif - -typedef struct QCowHeader { - uint32_t magic; - uint32_t version; - uint64_t backing_file_offset; - uint32_t backing_file_size; - uint32_t cluster_bits; - uint64_t size; /* in bytes */ - - uint32_t crypt_method; - uint32_t l1_size; /* XXX: save number of clusters instead ? */ - uint64_t l1_table_offset; - uint64_t refcount_table_offset; - uint32_t refcount_table_clusters; - uint32_t nb_snapshots; - uint64_t snapshots_offset; -} QCowHeader; - -typedef struct __attribute__((packed)) QCowSnapshotHeader { - /* header is 8 byte aligned */ - uint64_t l1_table_offset; - - uint32_t l1_size; - uint16_t id_str_size; - uint16_t name_size; - - uint32_t date_sec; - uint32_t date_nsec; - - uint64_t vm_clock_nsec; - - uint32_t vm_state_size; - uint32_t extra_data_size; /* for extension */ - /* extra data follows */ - /* id_str follows */ - /* name follows */ -} QCowSnapshotHeader; - -#define L2_CACHE_SIZE 16 - -typedef struct QCowSnapshot { - uint64_t l1_table_offset; - uint32_t l1_size; - char *id_str; - char *name; - uint32_t vm_state_size; - uint32_t date_sec; - uint32_t date_nsec; - uint64_t vm_clock_nsec; -} QCowSnapshot; - -typedef struct BDRVQcowState { - - /* blktap additions */ - int fd; - int poll_pipe[2]; /* dummy fd for polling on */ - char* name; - int encrypted; - char backing_file[1024]; - struct disk_driver* backing_hd; - - int64_t total_sectors; - - tap_aio_context_t async; - - /* Original qemu variables */ - int cluster_bits; - int cluster_size; - int cluster_sectors; - int l2_bits; - int l2_size; - int l1_size; - int l1_vm_state_index; - int csize_shift; - int csize_mask; - uint64_t cluster_offset_mask; - uint64_t l1_table_offset; - uint64_t *l1_table; - uint64_t *l2_cache; - uint64_t l2_cache_offsets[L2_CACHE_SIZE]; - uint32_t l2_cache_counts[L2_CACHE_SIZE]; - uint8_t *cluster_cache; - uint8_t *cluster_data; - uint64_t cluster_cache_offset; - - uint64_t *refcount_table; - uint64_t refcount_table_offset; - uint32_t refcount_table_size; - uint64_t refcount_block_cache_offset; - uint16_t *refcount_block_cache; - int64_t free_cluster_index; - int64_t free_byte_offset; - - uint32_t crypt_method; /* current crypt method, 0 if no key yet */ - uint32_t crypt_method_header; - AES_KEY aes_encrypt_key; - AES_KEY aes_decrypt_key; - uint64_t snapshots_offset; - int snapshots_size; - int nb_snapshots; - QCowSnapshot *snapshots; -} BDRVQcowState; - -static int decompress_cluster(BDRVQcowState *s, uint64_t cluster_offset); -static int qcow_read(struct disk_driver *bs, uint64_t sector_num, - uint8_t *buf, int nb_sectors); - -static int qcow_read_snapshots(struct disk_driver *bs); -static void qcow_free_snapshots(struct disk_driver *bs); - -static int refcount_init(struct disk_driver *bs); -static void refcount_close(struct disk_driver *bs); -static int get_refcount(struct disk_driver *bs, int64_t cluster_index); -static int update_cluster_refcount(struct disk_driver *bs, - int64_t cluster_index, - int addend); -static void update_refcount(struct disk_driver *bs, - int64_t offset, int64_t length, - int addend); -static int64_t alloc_clusters(struct disk_driver *bs, int64_t size); -static int64_t alloc_bytes(struct disk_driver *bs, int size); -static void free_clusters(struct disk_driver *bs, - int64_t offset, int64_t size); -#ifdef DEBUG_ALLOC -static void check_refcounts(struct disk_driver *bs); -#endif - -static int qcow_sync_read(struct disk_driver *dd, uint64_t sector, - int nb_sectors, char *buf, td_callback_t cb, - int id, void *prv); - -/** - * Read with byte offsets - */ -static int bdrv_pread(int fd, int64_t offset, void *buf, int count) -{ - int ret; - - if (lseek(fd, offset, SEEK_SET) == -1) { - DPRINTF("bdrv_pread failed seek (%#"PRIx64").\n", offset); - return -1; - } - - ret = read(fd, buf, count); - if (ret < 0) { - if (lseek(fd, 0, SEEK_END) >= offset) { - DPRINTF("bdrv_pread read failed (%#"PRIx64", END = %#"PRIx64").\n", - offset, lseek(fd, 0, SEEK_END)); - return -1; - } - - /* Read beyond end of file. Reading zeros. */ - memset(buf, 0, count); - ret = count; - } else if (ret < count) { - /* Read beyond end of file. Filling up with zeros. */ - memset(buf + ret, 0, count - ret); - ret = count; - } - return ret; -} - -/** - * Write with byte offsets - */ -static int bdrv_pwrite(int fd, int64_t offset, const void *buf, int count) -{ - if (lseek(fd, offset, SEEK_SET) == -1) { - DPRINTF("bdrv_pwrite failed seek (%#"PRIx64").\n", offset); - return -1; - } - - return write(fd, buf, count); -} - - -/** - * Read with sector offsets - */ -static int bdrv_read(int fd, int64_t offset, void *buf, int count) -{ - return bdrv_pread(fd, 512 * offset, buf, 512 * count); -} - -/** - * Write with sector offsets - */ -static int bdrv_write(int fd, int64_t offset, const void *buf, int count) -{ - return bdrv_pwrite(fd, 512 * offset, buf, count); -} - - -static int qcow_probe(const uint8_t *buf, int buf_size, const char *filename) -{ - const QCowHeader *cow_header = (const void *)buf; - - if (buf_size >= sizeof(QCowHeader) && - be32_to_cpu(cow_header->magic) == QCOW_MAGIC && - be32_to_cpu(cow_header->version) == QCOW_VERSION) - return 100; - else - return 0; -} - -static int qcow_open(struct disk_driver *bs, const char *filename, td_flag_t flags) -{ - BDRVQcowState *s = bs->private; - int len, i, shift, ret, max_aio_reqs; - QCowHeader header; - - int fd, o_flags; - - o_flags = O_LARGEFILE | ((flags == TD_RDONLY) ? O_RDONLY : O_RDWR); - - DPRINTF("Opening %s\n", filename); - fd = open(filename, o_flags); - if (fd < 0) { - DPRINTF("Unable to open %s (%d)\n", filename, 0 - errno); - return -1; - } - - s->fd = fd; - if (asprintf(&s->name,"%s", filename) == -1) { - close(fd); - return -1; - } - - ret = read(fd, &header, sizeof(header)); - if (ret != sizeof(header)) { - DPRINTF(" ret = %d, errno = %d\n", ret, errno); - goto fail; - } - - be32_to_cpus(&header.magic); - be32_to_cpus(&header.version); - be64_to_cpus(&header.backing_file_offset); - be32_to_cpus(&header.backing_file_size); - be64_to_cpus(&header.size); - be32_to_cpus(&header.cluster_bits); - be32_to_cpus(&header.crypt_method); - be64_to_cpus(&header.l1_table_offset); - be32_to_cpus(&header.l1_size); - be64_to_cpus(&header.refcount_table_offset); - be32_to_cpus(&header.refcount_table_clusters); - be64_to_cpus(&header.snapshots_offset); - be32_to_cpus(&header.nb_snapshots); - - if (header.magic != QCOW_MAGIC || header.version != QCOW_VERSION) - goto fail; - - if (header.size <= 1 || - header.cluster_bits < 9 || - header.cluster_bits > 16) - goto fail; - - s->crypt_method = 0; - if (header.crypt_method > QCOW_CRYPT_AES) - goto fail; - s->crypt_method_header = header.crypt_method; - if (s->crypt_method_header) - s->encrypted = 1; - s->cluster_bits = header.cluster_bits; - s->cluster_size = 1 << s->cluster_bits; - s->cluster_sectors = 1 << (s->cluster_bits - 9); - s->l2_bits = s->cluster_bits - 3; /* L2 is always one cluster */ - s->l2_size = 1 << s->l2_bits; - s->total_sectors = header.size / 512; - s->csize_shift = (62 - (s->cluster_bits - 8)); - s->csize_mask = (1 << (s->cluster_bits - 8)) - 1; - s->cluster_offset_mask = (1LL << s->csize_shift) - 1; - s->refcount_table_offset = header.refcount_table_offset; - s->refcount_table_size = - header.refcount_table_clusters << (s->cluster_bits - 3); - - s->snapshots_offset = header.snapshots_offset; - s->nb_snapshots = header.nb_snapshots; - -// DPRINTF("-- cluster_bits/size/sectors = %d/%d/%d\n", -// s->cluster_bits, s->cluster_size, s->cluster_sectors); -// DPRINTF("-- l2_bits/sizes = %d/%d\n", -// s->l2_bits, s->l2_size); - - /* Set sector size and number */ - bs->td_state->sector_size = 512; - bs->td_state->size = header.size / 512; - bs->td_state->info = 0; - - /* read the level 1 table */ - s->l1_size = header.l1_size; - shift = s->cluster_bits + s->l2_bits; - s->l1_vm_state_index = (header.size + (1LL << shift) - 1) >> shift; - /* the L1 table must contain at least enough entries to put - header.size bytes */ - if (s->l1_size < s->l1_vm_state_index) { - DPRINTF("L1 table tooo small\n"); - goto fail; - } - s->l1_table_offset = header.l1_table_offset; - - s->l1_table = qemu_malloc(s->l1_size * sizeof(uint64_t)); - if (!s->l1_table) - goto fail; - - - if (lseek(fd, s->l1_table_offset, SEEK_SET) == -1) - goto fail; - - if (read(fd, s->l1_table, s->l1_size * sizeof(uint64_t)) != - s->l1_size * sizeof(uint64_t)) { - - DPRINTF("Could not read L1 table\n"); - goto fail; - } - - for(i = 0;i < s->l1_size; i++) { - be64_to_cpus(&s->l1_table[i]); - } - /* alloc L2 cache */ - s->l2_cache = qemu_malloc(s->l2_size * L2_CACHE_SIZE * sizeof(uint64_t)); - if (!s->l2_cache) - goto fail; - s->cluster_cache = qemu_malloc(s->cluster_size); - if (!s->cluster_cache) - goto fail; - /* one more sector for decompressed data alignment */ - s->cluster_data = qemu_malloc(s->cluster_size + 512); - if (!s->cluster_data) - goto fail; - s->cluster_cache_offset = -1; - - if (refcount_init(bs) < 0) - goto fail; - - /* read the backing file name */ - s->backing_file[0] = '\0'; - if (header.backing_file_offset != 0) { - len = header.backing_file_size; - if (len > 1023) - len = 1023; - - if (lseek(fd, header.backing_file_offset, SEEK_SET) == -1) { - DPRINTF("Could not lseek to %#"PRIx64"\n", header.backing_file_offset); - goto fail; - } - - if (read(fd, s->backing_file, len) != len) { - DPRINTF("Could not read %#x bytes from %#"PRIx64": %s\n", - len, header.backing_file_offset, - strerror(errno)); - goto fail; - } - - s->backing_file[len] = '\0'; - } - -#if 0 - s->backing_hd = NULL; - if (qcow_read_snapshots(bs) < 0) { - DPRINTF("Could not read backing files\n"); - goto fail; - } -#endif - -#ifdef DEBUG_ALLOC - check_refcounts(bs); -#endif - - /* Initialize fds */ - for(i = 0; i < MAX_IOFD; i++) - bs->io_fd[i] = 0; - -#ifdef USE_AIO - /* Initialize AIO */ - - /* A segment (i.e. a page) can span multiple clusters */ - max_aio_reqs = ((getpagesize() / s->cluster_size) + 1) * - MAX_SEGMENTS_PER_REQ * MAX_REQUESTS; - - if (tap_aio_init(&s->async, bs->td_state->size, max_aio_reqs)) { - DPRINTF("Unable to initialise AIO state\n"); - tap_aio_free(&s->async); - goto fail; - } - - bs->io_fd[0] = s->async.aio_ctx.pollfd; -#else - /* Synchronous IO */ - if (pipe(s->poll_pipe)) - goto fail; - - bs->io_fd[0] = s->poll_pipe[0]; -#endif - - return 0; - - fail: - DPRINTF("qcow_open failed\n"); - -#ifdef USE_AIO - tap_aio_free(&s->async); -#endif - - qcow_free_snapshots(bs); - refcount_close(bs); - qemu_free(s->l1_table); - qemu_free(s->l2_cache); - qemu_free(s->cluster_cache); - qemu_free(s->cluster_data); - close(fd); - return -1; -} - -static int qcow_set_key(struct disk_driver *bs, const char *key) -{ - BDRVQcowState *s = bs->private; - uint8_t keybuf[16]; - int len, i; - - memset(keybuf, 0, 16); - len = strlen(key); - if (len > 16) - len = 16; - /* XXX: we could compress the chars to 7 bits to increase - entropy */ - for(i = 0;i < len;i++) { - keybuf[i] = key[i]; - } - s->crypt_method = s->crypt_method_header; - - if (AES_set_encrypt_key(keybuf, 128, &s->aes_encrypt_key) != 0) - return -1; - if (AES_set_decrypt_key(keybuf, 128, &s->aes_decrypt_key) != 0) - return -1; -#if 0 - /* test */ - { - uint8_t in[16]; - uint8_t out[16]; - uint8_t tmp[16]; - for(i=0;i<16;i++) - in[i] = i; - AES_encrypt(in, tmp, &s->aes_encrypt_key); - AES_decrypt(tmp, out, &s->aes_decrypt_key); - for(i = 0; i < 16; i++) - printf(" %02x", tmp[i]); - printf("\n"); - for(i = 0; i < 16; i++) - printf(" %02x", out[i]); - printf("\n"); - } -#endif - return 0; -} - -/* The crypt function is compatible with the linux cryptoloop - algorithm for < 4 GB images. NOTE: out_buf == in_buf is - supported */ -static void encrypt_sectors(BDRVQcowState *s, int64_t sector_num, - uint8_t *out_buf, const uint8_t *in_buf, - int nb_sectors, int enc, - const AES_KEY *key) -{ - union { - uint64_t ll[2]; - uint8_t b[16]; - } ivec; - int i; - - for(i = 0; i < nb_sectors; i++) { - ivec.ll[0] = cpu_to_le64(sector_num); - ivec.ll[1] = 0; - AES_cbc_encrypt(in_buf, out_buf, 512, key, - ivec.b, enc); - sector_num++; - in_buf += 512; - out_buf += 512; - } -} - -static int copy_sectors(struct disk_driver *bs, uint64_t start_sect, - uint64_t cluster_offset, int n_start, int n_end) -{ - BDRVQcowState *s = bs->private; - int n, ret; - - n = n_end - n_start; - if (n <= 0) - return 0; - - ret = qcow_read(bs, start_sect + n_start, s->cluster_data, n); - - if (ret < 0) - return ret; - if (s->crypt_method) { - encrypt_sectors(s, start_sect + n_start, - s->cluster_data, - s->cluster_data, n, 1, - &s->aes_encrypt_key); - } - - - ret = bdrv_pwrite(s->fd, cluster_offset + 512*n_start, s->cluster_data, n*512); - - if (ret < 0) - return ret; - return 0; -} - -static void l2_cache_reset(struct disk_driver *bs) -{ - BDRVQcowState *s = bs->private; - - memset(s->l2_cache, 0, s->l2_size * L2_CACHE_SIZE * sizeof(uint64_t)); - memset(s->l2_cache_offsets, 0, L2_CACHE_SIZE * sizeof(uint64_t)); - memset(s->l2_cache_counts, 0, L2_CACHE_SIZE * sizeof(uint32_t)); -} - -static inline int l2_cache_new_entry(struct disk_driver *bs) -{ - BDRVQcowState *s = bs->private; - uint32_t min_count; - int min_index, i; - - /* find a new entry in the least used one */ - min_index = 0; - min_count = 0xffffffff; - for(i = 0; i < L2_CACHE_SIZE; i++) { - if (s->l2_cache_counts[i] < min_count) { - min_count = s->l2_cache_counts[i]; - min_index = i; - } - } - return min_index; -} - -static int64_t align_offset(int64_t offset, int n) -{ - offset = (offset + n - 1) & ~(n - 1); - return offset; -} - -static int grow_l1_table(struct disk_driver *bs, int min_size) -{ - BDRVQcowState *s = bs->private; - int new_l1_size, new_l1_size2, ret, i; - uint64_t *new_l1_table; - uint64_t new_l1_table_offset; - uint64_t data64; - uint32_t data32; - - new_l1_size = s->l1_size; - if (min_size <= new_l1_size) - return 0; - while (min_size > new_l1_size) { - new_l1_size = (new_l1_size * 3 + 1) / 2; - } - -#ifdef DEBUG_ALLOC2 - DPRINTF("grow l1_table from %d to %d\n", s->l1_size, new_l1_size); -#endif - - new_l1_size2 = sizeof(uint64_t) * new_l1_size; - new_l1_table = qemu_mallocz(new_l1_size2); - if (!new_l1_table) - return -ENOMEM; - memcpy(new_l1_table, s->l1_table, s->l1_size * sizeof(uint64_t)); - - /* write new table (align to cluster) */ - new_l1_table_offset = alloc_clusters(bs, new_l1_size2); - - for(i = 0; i < s->l1_size; i++) - new_l1_table[i] = cpu_to_be64(new_l1_table[i]); - - - if (lseek(s->fd, new_l1_table_offset, SEEK_SET) == -1) - goto fail; - - ret = write(s->fd, new_l1_table, new_l1_size2); - if (ret != new_l1_size2) - goto fail; - - - for(i = 0; i < s->l1_size; i++) - new_l1_table[i] = be64_to_cpu(new_l1_table[i]); - - /* set new table */ - data64 = cpu_to_be64(new_l1_table_offset); - - if (lseek(s->fd, offsetof(QCowHeader, l1_table_offset), SEEK_SET) == -1) - goto fail; - - if (write(s->fd, &data64, sizeof(data64)) != sizeof(data64)) - goto fail; - - data32 = cpu_to_be32(new_l1_size); - - if (bdrv_pwrite(s->fd, offsetof(QCowHeader, l1_size), - &data32, sizeof(data32)) != sizeof(data32)) - goto fail; - qemu_free(s->l1_table); - free_clusters(bs, s->l1_table_offset, s->l1_size * sizeof(uint64_t)); - s->l1_table_offset = new_l1_table_offset; - s->l1_table = new_l1_table; - s->l1_size = new_l1_size; - return 0; - fail: - qemu_free(s->l1_table); - return -EIO; -} - -/* 'allocate' is: - * - * 0 not to allocate. - * - * 1 to allocate a normal cluster (for sector indexes 'n_start' to - * 'n_end') - * - * 2 to allocate a compressed cluster of size - * 'compressed_size'. 'compressed_size' must be > 0 and < - * cluster_size - * - * return 0 if not allocated. - */ -static uint64_t get_cluster_offset(struct disk_driver *bs, - uint64_t offset, int allocate, - int compressed_size, - int n_start, int n_end) -{ - BDRVQcowState *s = bs->private; - int min_index, i, j, l1_index, l2_index, ret; - uint64_t l2_offset, *l2_table, cluster_offset, tmp, old_l2_offset; - - l1_index = offset >> (s->l2_bits + s->cluster_bits); - if (l1_index >= s->l1_size) { - /* outside l1 table is allowed: we grow the table if needed */ - if (!allocate) - return 0; - - if (grow_l1_table(bs, l1_index + 1) < 0) { - DPRINTF("Could not grow L1 table"); - return 0; - } - } - - l2_offset = s->l1_table[l1_index]; - if (!l2_offset) { - if (!allocate) - return 0; - - l2_allocate: - old_l2_offset = l2_offset; - /* allocate a new l2 entry */ - l2_offset = alloc_clusters(bs, s->l2_size * sizeof(uint64_t)); - - /* update the L1 entry */ - s->l1_table[l1_index] = l2_offset | QCOW_OFLAG_COPIED; - tmp = cpu_to_be64(l2_offset | QCOW_OFLAG_COPIED); - if (bdrv_pwrite(s->fd, s->l1_table_offset + l1_index * sizeof(tmp), - &tmp, sizeof(tmp)) != sizeof(tmp)) - return 0; - min_index = l2_cache_new_entry(bs); - l2_table = s->l2_cache + (min_index << s->l2_bits); - - if (old_l2_offset == 0) { - memset(l2_table, 0, s->l2_size * sizeof(uint64_t)); - } else { - if (bdrv_pread(s->fd, old_l2_offset, - l2_table, s->l2_size * sizeof(uint64_t)) != - s->l2_size * sizeof(uint64_t)) - return 0; - } - if (bdrv_pwrite(s->fd, l2_offset, - l2_table, s->l2_size * sizeof(uint64_t)) != - s->l2_size * sizeof(uint64_t)) - return 0; - } else { - if (!(l2_offset & QCOW_OFLAG_COPIED)) { - if (allocate) { - free_clusters(bs, l2_offset, s->l2_size * sizeof(uint64_t)); - goto l2_allocate; - } - } else { - l2_offset &= ~QCOW_OFLAG_COPIED; - } - for(i = 0; i < L2_CACHE_SIZE; i++) { - if (l2_offset == s->l2_cache_offsets[i]) { - /* increment the hit count */ - if (++s->l2_cache_counts[i] == 0xffffffff) { - for(j = 0; j < L2_CACHE_SIZE; j++) { - s->l2_cache_counts[j] >>= 1; - } - } - l2_table = s->l2_cache + (i << s->l2_bits); - goto found; - } - } - /* not found: load a new entry in the least used one */ - min_index = l2_cache_new_entry(bs); - l2_table = s->l2_cache + (min_index << s->l2_bits); - - if (bdrv_pread(s->fd, l2_offset, l2_table, s->l2_size * sizeof(uint64_t)) != - s->l2_size * sizeof(uint64_t)) - { - DPRINTF("Could not read L2 table"); - return 0; - } - } - s->l2_cache_offsets[min_index] = l2_offset; - s->l2_cache_counts[min_index] = 1; -found: - l2_index = (offset >> s->cluster_bits) & (s->l2_size - 1); - - cluster_offset = be64_to_cpu(l2_table[l2_index]); - if (!cluster_offset) { - if (!allocate) { - return cluster_offset; - } - } else if (!(cluster_offset & QCOW_OFLAG_COPIED)) { - if (!allocate) - return cluster_offset; - /* free the cluster */ - if (cluster_offset & QCOW_OFLAG_COMPRESSED) { - int nb_csectors; - nb_csectors = ((cluster_offset >> s->csize_shift) & - s->csize_mask) + 1; - free_clusters(bs, (cluster_offset & s->cluster_offset_mask) & ~511, - nb_csectors * 512); - } else { - free_clusters(bs, cluster_offset, s->cluster_size); - } - } else { - cluster_offset &= ~QCOW_OFLAG_COPIED; - return cluster_offset; - } - if (allocate == 1) { - /* allocate a new cluster */ - cluster_offset = alloc_clusters(bs, s->cluster_size); - - /* we must initialize the cluster content which won't be - written */ - if ((n_end - n_start) < s->cluster_sectors) { - uint64_t start_sect; - - start_sect = (offset & ~(s->cluster_size - 1)) >> 9; - ret = copy_sectors(bs, start_sect, - cluster_offset, 0, n_start); - if (ret < 0) - return 0; - ret = copy_sectors(bs, start_sect, - cluster_offset, n_end, s->cluster_sectors); - if (ret < 0) - return 0; - } - tmp = cpu_to_be64(cluster_offset | QCOW_OFLAG_COPIED); - } else { - int nb_csectors; - cluster_offset = alloc_bytes(bs, compressed_size); - nb_csectors = ((cluster_offset + compressed_size - 1) >> 9) - - (cluster_offset >> 9); - cluster_offset |= QCOW_OFLAG_COMPRESSED | - ((uint64_t)nb_csectors << s->csize_shift); - /* compressed clusters never have the copied flag */ - tmp = cpu_to_be64(cluster_offset); - } - /* update L2 table */ - l2_table[l2_index] = tmp; - - if (bdrv_pwrite(s->fd, l2_offset + l2_index * sizeof(tmp), &tmp, sizeof(tmp)) != sizeof(tmp)) - return 0; - return cluster_offset; -} - -static int qcow_is_allocated(struct disk_driver *bs, int64_t sector_num, - int nb_sectors, int *pnum) -{ - BDRVQcowState *s = bs->private; - int index_in_cluster, n; - uint64_t cluster_offset; - - cluster_offset = get_cluster_offset(bs, sector_num << 9, 0, 0, 0, 0); - index_in_cluster = sector_num & (s->cluster_sectors - 1); - n = s->cluster_sectors - index_in_cluster; - if (n > nb_sectors) - n = nb_sectors; - *pnum = n; - return (cluster_offset != 0); -} - -static int decompress_buffer(uint8_t *out_buf, int out_buf_size, - const uint8_t *buf, int buf_size) -{ - z_stream strm1, *strm = &strm1; - int ret, out_len; - - memset(strm, 0, sizeof(*strm)); - - strm->next_in = (uint8_t *)buf; - strm->avail_in = buf_size; - strm->next_out = out_buf; - strm->avail_out = out_buf_size; - - ret = inflateInit2(strm, -12); - if (ret != Z_OK) - return -1; - ret = inflate(strm, Z_FINISH); - out_len = strm->next_out - out_buf; - if ((ret != Z_STREAM_END && ret != Z_BUF_ERROR) || - out_len != out_buf_size) { - inflateEnd(strm); - return -1; - } - inflateEnd(strm); - return 0; -} - -static int decompress_cluster(BDRVQcowState *s, uint64_t cluster_offset) -{ - int ret, csize, nb_csectors, sector_offset; - uint64_t coffset; - - coffset = cluster_offset & s->cluster_offset_mask; - if (s->cluster_cache_offset != coffset) { - nb_csectors = ((cluster_offset >> s->csize_shift) & s->csize_mask) + 1; - sector_offset = coffset & 511; - csize = nb_csectors * 512 - sector_offset; - ret = bdrv_read(s->fd, coffset >> 9, s->cluster_data, nb_csectors); - if (ret < 0) { - return -1; - } - if (decompress_buffer(s->cluster_cache, s->cluster_size, - s->cluster_data + sector_offset, csize) < 0) { - return -1; - } - s->cluster_cache_offset = coffset; - } - return 0; -} - -/* handle reading after the end of the backing file */ -static int backing_read1(struct disk_driver *bs, - int64_t sector_num, uint8_t *buf, int nb_sectors) -{ - int n1; - BDRVQcowState* s = bs->private; - - if ((sector_num + nb_sectors) <= s->total_sectors) - return nb_sectors; - if (sector_num >= s->total_sectors) - n1 = 0; - else - n1 = s->total_sectors - sector_num; - memset(buf + n1 * 512, 0, 512 * (nb_sectors - n1)); - return n1; -} - -/** - * Reads a number of sectors from the image (synchronous) - */ -static int qcow_read(struct disk_driver *bs, uint64_t sector_num, - uint8_t *buf, int nb_sectors) -{ - BDRVQcowState *s = bs->private; - int ret, index_in_cluster, n, n1; - uint64_t cluster_offset; - - while (nb_sectors > 0) { - cluster_offset = get_cluster_offset(bs, sector_num << 9, 0, 0, 0, 0); - index_in_cluster = sector_num & (s->cluster_sectors - 1); - n = s->cluster_sectors - index_in_cluster; - if (n > nb_sectors) - n = nb_sectors; - if (!cluster_offset) { - - if (bs->next) { - - /* Read from backing file */ - struct disk_driver *parent = bs->next; - - ret = qcow_sync_read(parent, sector_num, - nb_sectors, (char*) buf, NULL, 0, NULL); - -#if 0 - /* read from the base image */ - n1 = backing_read1(s->backing_hd, sector_num, buf, n); - if (n1 > 0) { - ret = bdrv_read(((BDRVQcowState*) s->backing_hd)->fd, sector_num, buf, n1); - if (ret < 0) { - DPRINTF("read from backing file failed: ret = %d; errno = %d\n", ret, errno); - return -1; - } - } -#endif - } else { - memset(buf, 0, 512 * n); - } - } else if (cluster_offset & QCOW_OFLAG_COMPRESSED) { - if (decompress_cluster(s, cluster_offset) < 0) { - DPRINTF("read/decompression failed: errno = %d\n", errno); - return -1; - } - memcpy(buf, s->cluster_cache + index_in_cluster * 512, 512 * n); - } else { - ret = bdrv_pread(s->fd, cluster_offset + index_in_cluster * 512, buf, n * 512); - if (ret != n * 512) { - DPRINTF("read failed: ret = %d != n * 512 = %d; errno = %d\n", ret, n * 512, errno); - DPRINTF(" cluster_offset = %"PRIx64", index = %d; sector_num = %"PRId64"", cluster_offset, index_in_cluster, sector_num); - return -1; - } - - if (s->crypt_method) { - encrypt_sectors(s, sector_num, buf, buf, n, 0, - &s->aes_decrypt_key); - } - } - nb_sectors -= n; - sector_num += n; - buf += n * 512; - } - return 0; -} - -/** - * Writes a number of sectors to the image (synchronous) - */ -static int qcow_write(struct disk_driver *bs, uint64_t sector_num, - const uint8_t *buf, int nb_sectors) -{ - BDRVQcowState *s = bs->private; - int ret, index_in_cluster, n; - uint64_t cluster_offset; - - while (nb_sectors > 0) { - index_in_cluster = sector_num & (s->cluster_sectors - 1); - n = s->cluster_sectors - index_in_cluster; - if (n > nb_sectors) - n = nb_sectors; - cluster_offset = get_cluster_offset(bs, sector_num << 9, 1, 0, - index_in_cluster, - index_in_cluster + n); - if (!cluster_offset) { - DPRINTF("qcow_write: cluster_offset == 0\n"); - DPRINTF(" index = %d; sector_num = %"PRId64"\n", - index_in_cluster, sector_num); - return -1; - } - - if (s->crypt_method) { - encrypt_sectors(s, sector_num, s->cluster_data, buf, n, 1, - &s->aes_encrypt_key); - ret = bdrv_pwrite(s->fd, cluster_offset + index_in_cluster * 512, - s->cluster_data, n * 512); - } else { - ret = bdrv_pwrite(s->fd, cluster_offset + index_in_cluster * 512, buf, n * 512); - } - if (ret != n * 512) { - DPRINTF("write failed: ret = %d != n * 512 = %d; errno = %d\n", ret, n * 512, errno); - DPRINTF(" cluster_offset = %"PRIx64", index = %d; sector_num = %"PRId64"\n", cluster_offset, index_in_cluster, sector_num); - return -1; - } - - nb_sectors -= n; - sector_num += n; - buf += n * 512; - } - s->cluster_cache_offset = -1; /* disable compressed cache */ - return 0; -} - - - -#ifdef USE_AIO - -/* - * QCOW2 specific AIO functions - */ - -static int qcow_queue_read(struct disk_driver *bs, uint64_t sector, - int nb_sectors, char *buf, td_callback_t cb, - int id, void *private) -{ - BDRVQcowState *s = bs->private; - int i, index_in_cluster, n, ret; - int rsp = 0; - uint64_t cluster_offset; - - /*Check we can get a lock*/ - for (i = 0; i < nb_sectors; i++) - if (!tap_aio_can_lock(&s->async, sector + i)) - return cb(bs, -EBUSY, sector, nb_sectors, id, private); - - while (nb_sectors > 0) { - - cluster_offset = get_cluster_offset(bs, sector << 9, 0, 0, 0, 0); - - index_in_cluster = sector & (s->cluster_sectors - 1); - n = s->cluster_sectors - index_in_cluster; - if (n > nb_sectors) - n = nb_sectors; - - if (s->async.iocb_free_count == 0 || !tap_aio_lock(&s->async, sector)) - return cb(bs, -EBUSY, sector, nb_sectors, id, private); - - if (!cluster_offset) { - - /* The requested sector is not allocated */ - tap_aio_unlock(&s->async, sector); - ret = cb(bs, BLK_NOT_ALLOCATED, - sector, n, id, private); - if (ret == -EBUSY) { - /* mark remainder of request - * as busy and try again later */ - return cb(bs, -EBUSY, sector + n, - nb_sectors - n, id, private); - } else { - rsp += ret; - } - - } else if (cluster_offset & QCOW_OFLAG_COMPRESSED) { - - /* sync read for compressed clusters */ - tap_aio_unlock(&s->async, sector); - if (decompress_cluster(s, cluster_offset) < 0) { - rsp += cb(bs, -EIO, sector, nb_sectors, id, private); - goto done; - } - memcpy(buf, s->cluster_cache + index_in_cluster * 512, - 512 * n); - rsp += cb(bs, 0, sector, n, id, private); - - } else { - - /* async read */ - tap_aio_read(&s->async, s->fd, n * 512, - (cluster_offset + index_in_cluster * 512), - buf, cb, id, sector, private); - } - - /* Prepare for next sector to read */ - nb_sectors -= n; - sector += n; - buf += n * 512; - } - -done: - return rsp; - -} - -static int qcow_queue_write(struct disk_driver *bs, uint64_t sector, - int nb_sectors, char *buf, td_callback_t cb, - int id, void *private) -{ - BDRVQcowState *s = bs->private; - int i, n, index_in_cluster; - uint64_t cluster_offset; - const uint8_t *src_buf; - - - /*Check we can get a lock*/ - for (i = 0; i < nb_sectors; i++) - if (!tap_aio_can_lock(&s->async, sector + i)) - return cb(bs, -EBUSY, sector, nb_sectors, id, private); - - - while (nb_sectors > 0) { - - index_in_cluster = sector & (s->cluster_sectors - 1); - n = s->cluster_sectors - index_in_cluster; - if (n > nb_sectors) - n = nb_sectors; - - if (s->async.iocb_free_count == 0 || !tap_aio_lock(&s->async, sector)) - return cb(bs, -EBUSY, sector, nb_sectors, id, private); - - - cluster_offset = get_cluster_offset(bs, sector << 9, 1, 0, - index_in_cluster, - index_in_cluster+n); - - if (!cluster_offset) { - DPRINTF("Ooops, no write cluster offset!\n"); - tap_aio_unlock(&s->async, sector); - return cb(bs, -EIO, sector, nb_sectors, id, private); - } - - - // TODO Encryption - - tap_aio_write(&s->async, s->fd, n * 512, - (cluster_offset + index_in_cluster*512), - buf, cb, id, sector, private); - - /* Prepare for next sector to write */ - nb_sectors -= n; - sector += n; - buf += n * 512; - } - - - s->cluster_cache_offset = -1; /* disable compressed cache */ - - return 0; -} - - -#endif /* USE_AIO */ - - -static int qcow_close(struct disk_driver *bs) -{ - BDRVQcowState *s = bs->private; - -#ifdef USE_AIO - io_destroy(s->async.aio_ctx.aio_ctx); - tap_aio_free(&s->async); -#else - close(s->poll_pipe[0]); - close(s->poll_pipe[1]); -#endif - - qemu_free(s->l1_table); - qemu_free(s->l2_cache); - qemu_free(s->cluster_cache); - qemu_free(s->cluster_data); - refcount_close(bs); - return close(s->fd); -} - -/* XXX: use std qcow open function ? */ -typedef struct QCowCreateState { - int cluster_size; - int cluster_bits; - uint16_t *refcount_block; - uint64_t *refcount_table; - int64_t l1_table_offset; - int64_t refcount_table_offset; - int64_t refcount_block_offset; -} QCowCreateState; - -static void create_refcount_update(QCowCreateState *s, - int64_t offset, int64_t size) -{ - int refcount; - int64_t start, last, cluster_offset; - uint16_t *p; - - start = offset & ~(s->cluster_size - 1); - last = (offset + size - 1) & ~(s->cluster_size - 1); - for(cluster_offset = start; cluster_offset <= last; - cluster_offset += s->cluster_size) { - p = &s->refcount_block[cluster_offset >> s->cluster_bits]; - refcount = be16_to_cpu(*p); - refcount++; - *p = cpu_to_be16(refcount); - } -} - -static int qcow_submit(struct disk_driver *bs) -{ - struct BDRVQcowState *s = (struct BDRVQcowState*) bs->private; - - fsync(s->fd); - return tap_aio_submit(&s->async); -} - - -/*********************************************************/ -/* snapshot support */ - - -static void qcow_free_snapshots(struct disk_driver *bs) -{ - BDRVQcowState *s = bs->private; - int i; - - for(i = 0; i < s->nb_snapshots; i++) { - qemu_free(s->snapshots[i].name); - qemu_free(s->snapshots[i].id_str); - } - qemu_free(s->snapshots); - s->snapshots = NULL; - s->nb_snapshots = 0; -} - -static int qcow_read_snapshots(struct disk_driver *bs) -{ - BDRVQcowState *s = bs->private; - QCowSnapshotHeader h; - QCowSnapshot *sn; - int i, id_str_size, name_size; - int64_t offset; - uint32_t extra_data_size; - - offset = s->snapshots_offset; - s->snapshots = qemu_mallocz(s->nb_snapshots * sizeof(QCowSnapshot)); - if (!s->snapshots) - goto fail; - for(i = 0; i < s->nb_snapshots; i++) { - offset = align_offset(offset, 8); - if (bdrv_pread(s->fd, offset, &h, sizeof(h)) != sizeof(h)) - goto fail; - offset += sizeof(h); - sn = s->snapshots + i; - sn->l1_table_offset = be64_to_cpu(h.l1_table_offset); - sn->l1_size = be32_to_cpu(h.l1_size); - sn->vm_state_size = be32_to_cpu(h.vm_state_size); - sn->date_sec = be32_to_cpu(h.date_sec); - sn->date_nsec = be32_to_cpu(h.date_nsec); - sn->vm_clock_nsec = be64_to_cpu(h.vm_clock_nsec); - extra_data_size = be32_to_cpu(h.extra_data_size); - - id_str_size = be16_to_cpu(h.id_str_size); - name_size = be16_to_cpu(h.name_size); - - offset += extra_data_size; - - sn->id_str = qemu_malloc(id_str_size + 1); - if (!sn->id_str) - goto fail; - if (bdrv_pread(s->fd, offset, sn->id_str, id_str_size) != id_str_size) - goto fail; - offset += id_str_size; - sn->id_str[id_str_size] = '\0'; - - sn->name = qemu_malloc(name_size + 1); - if (!sn->name) - goto fail; - if (bdrv_pread(s->fd, offset, sn->name, name_size) != name_size) - goto fail; - offset += name_size; - sn->name[name_size] = '\0'; - } - s->snapshots_size = offset - s->snapshots_offset; - return 0; -fail: - qcow_free_snapshots(bs); - return -1; -} - - -/*********************************************************/ -/* refcount handling */ - -static int refcount_init(struct disk_driver *bs) -{ - BDRVQcowState *s = bs->private; - int ret, refcount_table_size2, i; - - s->refcount_block_cache = qemu_malloc(s->cluster_size); - if (!s->refcount_block_cache) - goto fail; - refcount_table_size2 = s->refcount_table_size * sizeof(uint64_t); - s->refcount_table = qemu_malloc(refcount_table_size2); - if (!s->refcount_table) - goto fail; - if (s->refcount_table_size > 0) { - ret = bdrv_pread(s->fd, s->refcount_table_offset, - s->refcount_table, refcount_table_size2); - if (ret != refcount_table_size2) - goto fail; - for(i = 0; i < s->refcount_table_size; i++) - be64_to_cpus(&s->refcount_table[i]); - } - return 0; - fail: - return -ENOMEM; -} - -static void refcount_close(struct disk_driver *bs) -{ - BDRVQcowState *s = bs->private; - qemu_free(s->refcount_block_cache); - qemu_free(s->refcount_table); -} - - -static int load_refcount_block(struct disk_driver *bs, - int64_t refcount_block_offset) -{ - BDRVQcowState *s = bs->private; - int ret; - ret = bdrv_pread(s->fd, refcount_block_offset, s->refcount_block_cache, - s->cluster_size); - if (ret != s->cluster_size) - return -EIO; - s->refcount_block_cache_offset = refcount_block_offset; - return 0; -} - -static int get_refcount(struct disk_driver *bs, int64_t cluster_index) -{ - BDRVQcowState *s = bs->private; - int refcount_table_index, block_index; - int64_t refcount_block_offset; - - refcount_table_index = cluster_index >> (s->cluster_bits - REFCOUNT_SHIFT); - if (refcount_table_index >= s->refcount_table_size) - return 0; - refcount_block_offset = s->refcount_table[refcount_table_index]; - if (!refcount_block_offset) - return 0; - if (refcount_block_offset != s->refcount_block_cache_offset) { - /* better than nothing: return allocated if read error */ - if (load_refcount_block(bs, refcount_block_offset) < 0) - return 1; - } - block_index = cluster_index & - ((1 << (s->cluster_bits - REFCOUNT_SHIFT)) - 1); - return be16_to_cpu(s->refcount_block_cache[block_index]); -} - -/* return < 0 if error */ -static int64_t alloc_clusters_noref(struct disk_driver *bs, int64_t size) -{ - BDRVQcowState *s = bs->private; - int i, nb_clusters; - - nb_clusters = (size + s->cluster_size - 1) >> s->cluster_bits; - for(;;) { - if (get_refcount(bs, s->free_cluster_index) == 0) { - s->free_cluster_index++; - for(i = 1; i < nb_clusters; i++) { - if (get_refcount(bs, s->free_cluster_index) != 0) - goto not_found; - s->free_cluster_index++; - } - -#ifdef DEBUG_ALLOC2 - DPRINTF("alloc_clusters: size=%ld -> %ld\n", - size, - (s->free_cluster_index - nb_clusters) << s->cluster_bits); -#endif - - return (s->free_cluster_index - nb_clusters) << s->cluster_bits; - } else { - not_found: - s->free_cluster_index++; - } - } -} - -static int64_t alloc_clusters(struct disk_driver *bs, int64_t size) -{ - int64_t offset; - - offset = alloc_clusters_noref(bs, size); - update_refcount(bs, offset, size, 1); - return offset; -} - -/* only used to allocate compressed sectors. We try to allocate - contiguous sectors. size must be <= cluster_size */ -static int64_t alloc_bytes(struct disk_driver *bs, int size) -{ - BDRVQcowState *s = bs->private; - int64_t offset, cluster_offset; - int free_in_cluster; - - assert(size > 0 && size <= s->cluster_size); - if (s->free_byte_offset == 0) { - s->free_byte_offset = alloc_clusters(bs, s->cluster_size); - } -redo: - free_in_cluster = s->cluster_size - - (s->free_byte_offset & (s->cluster_size - 1)); - if (size <= free_in_cluster) { - /* enough space in current cluster */ - offset = s->free_byte_offset; - s->free_byte_offset += size; - free_in_cluster -= size; - if (free_in_cluster == 0) - s->free_byte_offset = 0; - if ((offset & (s->cluster_size - 1)) != 0) - update_cluster_refcount(bs, offset >> s->cluster_bits, 1); - } else { - offset = alloc_clusters(bs, s->cluster_size); - cluster_offset = s->free_byte_offset & ~(s->cluster_size - 1); - if ((cluster_offset + s->cluster_size) == offset) { - /* we are lucky: contiguous data */ - offset = s->free_byte_offset; - update_cluster_refcount(bs, offset >> s->cluster_bits, 1); - s->free_byte_offset += size; - } else { - s->free_byte_offset = offset; - goto redo; - } - } - return offset; -} - -static void free_clusters(struct disk_driver *bs, - int64_t offset, int64_t size) -{ - update_refcount(bs, offset, size, -1); -} - -static int grow_refcount_table(struct disk_driver *bs, int min_size) -{ - BDRVQcowState *s = bs->private; - int new_table_size, new_table_size2, refcount_table_clusters, i, ret; - uint64_t *new_table; - int64_t table_offset; - uint64_t data64; - uint32_t data32; - int old_table_size; - int64_t old_table_offset; - - if (min_size <= s->refcount_table_size) - return 0; - - /* compute new table size */ - refcount_table_clusters = s->refcount_table_size >> (s->cluster_bits - 3); - for(;;) { - if (refcount_table_clusters == 0) { - refcount_table_clusters = 1; - } else { - refcount_table_clusters = (refcount_table_clusters * 3 + 1) / 2; - } - new_table_size = refcount_table_clusters << (s->cluster_bits - 3); - if (min_size <= new_table_size) - break; - } - -#ifdef DEBUG_ALLOC2 - printf("grow_refcount_table from %d to %d\n", - s->refcount_table_size, - new_table_size); -#endif - new_table_size2 = new_table_size * sizeof(uint64_t); - new_table = qemu_mallocz(new_table_size2); - if (!new_table) - return -ENOMEM; - memcpy(new_table, s->refcount_table, - s->refcount_table_size * sizeof(uint64_t)); - for(i = 0; i < s->refcount_table_size; i++) - cpu_to_be64s(&new_table[i]); - /* Note: we cannot update the refcount now to avoid recursion */ - table_offset = alloc_clusters_noref(bs, new_table_size2); - ret = bdrv_pwrite(s->fd, table_offset, new_table, new_table_size2); - if (ret != new_table_size2) - goto fail; - for(i = 0; i < s->refcount_table_size; i++) - be64_to_cpus(&new_table[i]); - - data64 = cpu_to_be64(table_offset); - if (bdrv_pwrite(s->fd, offsetof(QCowHeader, refcount_table_offset), - &data64, sizeof(data64)) != sizeof(data64)) - goto fail; - data32 = cpu_to_be32(refcount_table_clusters); - if (bdrv_pwrite(s->fd, offsetof(QCowHeader, refcount_table_clusters), - &data32, sizeof(data32)) != sizeof(data32)) - goto fail; - qemu_free(s->refcount_table); - old_table_offset = s->refcount_table_offset; - old_table_size = s->refcount_table_size; - s->refcount_table = new_table; - s->refcount_table_size = new_table_size; - s->refcount_table_offset = table_offset; - - update_refcount(bs, table_offset, new_table_size2, 1); - free_clusters(bs, old_table_offset, old_table_size * sizeof(uint64_t)); - return 0; - fail: - free_clusters(bs, table_offset, new_table_size2); - qemu_free(new_table); - return -EIO; -} - -/* addend must be 1 or -1 */ -/* XXX: cache several refcount block clusters ? */ -static int update_cluster_refcount(struct disk_driver *bs, - int64_t cluster_index, - int addend) -{ - BDRVQcowState *s = bs->private; - int64_t offset, refcount_block_offset; - int ret, refcount_table_index, block_index, refcount; - uint64_t data64; - - refcount_table_index = cluster_index >> (s->cluster_bits - REFCOUNT_SHIFT); - if (refcount_table_index >= s->refcount_table_size) { - if (addend < 0) - return -EINVAL; - ret = grow_refcount_table(bs, refcount_table_index + 1); - if (ret < 0) - return ret; - } - refcount_block_offset = s->refcount_table[refcount_table_index]; - if (!refcount_block_offset) { - if (addend < 0) - return -EINVAL; - /* create a new refcount block */ - /* Note: we cannot update the refcount now to avoid recursion */ - offset = alloc_clusters_noref(bs, s->cluster_size); - memset(s->refcount_block_cache, 0, s->cluster_size); - ret = bdrv_pwrite(s->fd, offset, s->refcount_block_cache, s->cluster_size); - if (ret != s->cluster_size) - return -EINVAL; - s->refcount_table[refcount_table_index] = offset; - data64 = cpu_to_be64(offset); - ret = bdrv_pwrite(s->fd, s->refcount_table_offset + - refcount_table_index * sizeof(uint64_t), - &data64, sizeof(data64)); - if (ret != sizeof(data64)) - return -EINVAL; - - refcount_block_offset = offset; - s->refcount_block_cache_offset = offset; - update_refcount(bs, offset, s->cluster_size, 1); - } else { - if (refcount_block_offset != s->refcount_block_cache_offset) { - if (load_refcount_block(bs, refcount_block_offset) < 0) - return -EIO; - } - } - /* we can update the count and save it */ - block_index = cluster_index & - ((1 << (s->cluster_bits - REFCOUNT_SHIFT)) - 1); - refcount = be16_to_cpu(s->refcount_block_cache[block_index]); - refcount += addend; - if (refcount < 0 || refcount > 0xffff) - return -EINVAL; - if (refcount == 0 && cluster_index < s->free_cluster_index) { - s->free_cluster_index = cluster_index; - } - s->refcount_block_cache[block_index] = cpu_to_be16(refcount); - if (bdrv_pwrite(s->fd, - refcount_block_offset + (block_index << REFCOUNT_SHIFT), - &s->refcount_block_cache[block_index], 2) != 2) - return -EIO; - return refcount; -} - -static void update_refcount(struct disk_driver *bs, - int64_t offset, int64_t length, - int addend) -{ - BDRVQcowState *s = bs->private; - int64_t start, last, cluster_offset; - -#ifdef DEBUG_ALLOC2 - printf("update_refcount: offset=%lld size=%lld addend=%d\n", - offset, length, addend); -#endif - if (length <= 0) - return; - start = offset & ~(s->cluster_size - 1); - last = (offset + length - 1) & ~(s->cluster_size - 1); - for(cluster_offset = start; cluster_offset <= last; - cluster_offset += s->cluster_size) { - update_cluster_refcount(bs, cluster_offset >> s->cluster_bits, addend); - } -} - -#ifdef DEBUG_ALLOC -static void inc_refcounts(struct disk_driver *bs, - uint16_t *refcount_table, - int refcount_table_size, - int64_t offset, int64_t size) -{ - BDRVQcowState *s = bs->private; - int64_t start, last, cluster_offset; - int k; - - if (size <= 0) - return; - - start = offset & ~(s->cluster_size - 1); - last = (offset + size - 1) & ~(s->cluster_size - 1); - for(cluster_offset = start; cluster_offset <= last; - cluster_offset += s->cluster_size) { - k = cluster_offset >> s->cluster_bits; - if (k < 0 || k >= refcount_table_size) { - printf("ERROR: invalid cluster offset=0x%llx\n", cluster_offset); - } else { - if (++refcount_table[k] == 0) { - printf("ERROR: overflow cluster offset=0x%llx\n", cluster_offset); - } - } - } -} - -static int check_refcounts_l1(struct disk_driver *bs, - uint16_t *refcount_table, - int refcount_table_size, - int64_t l1_table_offset, int l1_size, - int check_copied) -{ - BDRVQcowState *s = bs->private; - uint64_t *l1_table, *l2_table, l2_offset, offset, l1_size2; - int l2_size, i, j, nb_csectors, refcount; - - l2_table = NULL; - l1_size2 = l1_size * sizeof(uint64_t); - - inc_refcounts(bs, refcount_table, refcount_table_size, - l1_table_offset, l1_size2); - - l1_table = qemu_malloc(l1_size2); - if (!l1_table) - goto fail; - if (bdrv_pread(s->fd, l1_table_offset, - l1_table, l1_size2) != l1_size2) - goto fail; - for(i = 0;i < l1_size; i++) - be64_to_cpus(&l1_table[i]); - - l2_size = s->l2_size * sizeof(uint64_t); - l2_table = qemu_malloc(l2_size); - if (!l2_table) - goto fail; - for(i = 0; i < l1_size; i++) { - l2_offset = l1_table[i]; - if (l2_offset) { - if (check_copied) { - refcount = get_refcount(bs, (l2_offset & ~QCOW_OFLAG_COPIED) >> s->cluster_bits); - if ((refcount == 1) != ((l2_offset & QCOW_OFLAG_COPIED) != 0)) { - printf("ERROR OFLAG_COPIED: l2_offset=%llx refcount=%d\n", - l2_offset, refcount); - } - } - l2_offset &= ~QCOW_OFLAG_COPIED; - if (bdrv_pread(s->fd, l2_offset, l2_table, l2_size) != l2_size) - goto fail; - for(j = 0; j < s->l2_size; j++) { - offset = be64_to_cpu(l2_table[j]); - if (offset != 0) { - if (offset & QCOW_OFLAG_COMPRESSED) { - if (offset & QCOW_OFLAG_COPIED) { - printf("ERROR: cluster %lld: copied flag must never be set for compressed clusters\n", - offset >> s->cluster_bits); - offset &= ~QCOW_OFLAG_COPIED; - } - nb_csectors = ((offset >> s->csize_shift) & - s->csize_mask) + 1; - offset &= s->cluster_offset_mask; - inc_refcounts(bs, refcount_table, - refcount_table_size, - offset & ~511, nb_csectors * 512); - } else { - if (check_copied) { - refcount = get_refcount(bs, (offset & ~QCOW_OFLAG_COPIED) >> s->cluster_bits); - if ((refcount == 1) != ((offset & QCOW_OFLAG_COPIED) != 0)) { - printf("ERROR OFLAG_COPIED: offset=%llx refcount=%d\n", - offset, refcount); - } - } - offset &= ~QCOW_OFLAG_COPIED; - inc_refcounts(bs, refcount_table, - refcount_table_size, - offset, s->cluster_size); - } - } - } - inc_refcounts(bs, refcount_table, - refcount_table_size, - l2_offset, - s->cluster_size); - } - } - qemu_free(l1_table); - qemu_free(l2_table); - return 0; - fail: - printf("ERROR: I/O error in check_refcounts_l1\n"); - qemu_free(l1_table); - qemu_free(l2_table); - return -EIO; -} - -static void check_refcounts(struct disk_driver *bs) -{ - BDRVQcowState *s = bs->private; - int64_t size; - int nb_clusters, refcount1, refcount2, i; - QCowSnapshot *sn; - uint16_t *refcount_table; - - size = bdrv_getlength(s->fd); - nb_clusters = (size + s->cluster_size - 1) >> s->cluster_bits; - refcount_table = qemu_mallocz(nb_clusters * sizeof(uint16_t)); - - /* header */ - inc_refcounts(bs, refcount_table, nb_clusters, - 0, s->cluster_size); - - check_refcounts_l1(bs, refcount_table, nb_clusters, - s->l1_table_offset, s->l1_size, 1); - - /* snapshots */ - for(i = 0; i < s->nb_snapshots; i++) { - sn = s->snapshots + i; - check_refcounts_l1(bs, refcount_table, nb_clusters, - sn->l1_table_offset, sn->l1_size, 0); - } - inc_refcounts(bs, refcount_table, nb_clusters, - s->snapshots_offset, s->snapshots_size); - - /* refcount data */ - inc_refcounts(bs, refcount_table, nb_clusters, - s->refcount_table_offset, - s->refcount_table_size * sizeof(uint64_t)); - - for(i = 0; i < s->refcount_table_size; i++) { - int64_t offset; - offset = s->refcount_table[i]; - if (offset != 0) { - inc_refcounts(bs, refcount_table, nb_clusters, - offset, s->cluster_size); - } - } - - /* compare ref counts */ - for(i = 0; i < nb_clusters; i++) { - refcount1 = get_refcount(bs, i); - refcount2 = refcount_table[i]; - if (refcount1 != refcount2) - printf("ERROR cluster %d refcount=%d reference=%d\n", - i, refcount1, refcount2); - } - - qemu_free(refcount_table); -} -#endif - - -/** - * Wrapper for synchronous read. - * This function is called when not using AIO at all (#undef USE_AIO) or - * for accessing the backing file. - */ -static int qcow_sync_read(struct disk_driver *dd, uint64_t sector, - int nb_sectors, char *buf, td_callback_t cb, - int id, void *prv) -{ - int ret = qcow_read(dd, sector, (uint8_t*) buf, nb_sectors); - - if (cb != NULL) { - return cb(dd, (ret < 0) ? ret : 0, sector, nb_sectors, id, prv); - } else { - return ret; - } -} - -#ifndef USE_AIO -/** - * Wrapper for synchronous write - */ -static int qcow_sync_write(struct disk_driver *dd, uint64_t sector, - int nb_sectors, char *buf, td_callback_t cb, - int id, void *prv) -{ - int ret = qcow_write(dd, sector, (uint8_t*) buf, nb_sectors); - - return cb(dd, (ret < 0) ? ret : 0, sector, nb_sectors, id, prv); -} -#endif - - - -#ifndef USE_AIO - -static int qcow_do_callbacks(struct disk_driver *dd, int sid) -{ - return 1; -} - -#else - -static int qcow_do_callbacks(struct disk_driver *dd, int sid) -{ - int ret, i, nr_events, rsp = 0,*ptr; - struct io_event *ep; - struct BDRVQcowState *prv = (struct BDRVQcowState*)dd->private; - - if (sid > MAX_IOFD) return 1; - - nr_events = tap_aio_get_events(&prv->async.aio_ctx); - -repeat: - for (ep = prv->async.aio_events, i = nr_events; i-- > 0; ep++) { - struct iocb *io = ep->obj; - struct pending_aio *pio; - - pio = &prv->async.pending_aio[(long)io->data]; - - tap_aio_unlock(&prv->async, pio->sector); - - if (prv->crypt_method) - encrypt_sectors(prv, pio->sector, - (unsigned char *)pio->buf, - (unsigned char *)pio->buf, - pio->nb_sectors, 0, - &prv->aes_decrypt_key); - - rsp += pio->cb(dd, ep->res == io->u.c.nbytes ? 0 : 1, - pio->sector, pio->nb_sectors, - pio->id, pio->private); - - prv->async.iocb_free[prv->async.iocb_free_count++] = io; - } - - if (nr_events) { - nr_events = tap_aio_more_events(&prv->async.aio_ctx); - goto repeat; - } - - tap_aio_continue(&prv->async.aio_ctx); - - return rsp; -} - -#endif - -static int get_filesize(char *filename, uint64_t *size, struct stat *st) -{ - int fd; - QCowHeader header; - - /*Set to the backing file size*/ - fd = open(filename, O_RDONLY); - if (fd < 0) - return -1; - if (read(fd, &header, sizeof(header)) < sizeof(header)) { - close(fd); - return -1; - } - close(fd); - - be32_to_cpus(&header.magic); - be32_to_cpus(&header.version); - be64_to_cpus(&header.size); - if (header.magic == QCOW_MAGIC && header.version == QCOW_VERSION) { - *size = header.size >> SECTOR_SHIFT; - return 0; - } - - if(S_ISBLK(st->st_mode)) { - fd = open(filename, O_RDONLY); - if (fd < 0) - return -1; - if (blk_getimagesize(fd, size) != 0) { - close(fd); - return -1; - } - close(fd); - } else *size = (st->st_size >> SECTOR_SHIFT); - return 0; -} - -/** - * @return - * 0 if parent id successfully retrieved; - * TD_NO_PARENT if no parent exists; - * -errno on error - */ -static int qcow_get_parent_id(struct disk_driver *dd, struct disk_id *id) -{ - struct BDRVQcowState* s = (struct BDRVQcowState*) dd->private; - - if (s->backing_file[0] == '\0') - return TD_NO_PARENT; - - id->name = strdup(s->backing_file); - id->drivertype = DISK_TYPE_AIO; - - return 0; -} - -static int qcow_validate_parent(struct disk_driver *child, - struct disk_driver *parent, td_flag_t flags) -{ - struct stat stats; - uint64_t psize, csize; - - if (stat(parent->name, &stats)) - return -EINVAL; - if (get_filesize(parent->name, &psize, &stats)) - return -EINVAL; - - if (stat(child->name, &stats)) - return -EINVAL; - if (get_filesize(child->name, &csize, &stats)) - return -EINVAL; - - if (csize != psize) - return -EINVAL; - - return 0; -} - -int qcow2_create(const char *filename, uint64_t total_size, - const char *backing_file, int flags) -{ - int fd, header_size, backing_filename_len, l1_size, i, shift, l2_bits; - int ret = 0; - QCowHeader header; - uint64_t tmp, offset; - QCowCreateState s1, *s = &s1; - - memset(s, 0, sizeof(*s)); - - fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644); - if (fd < 0) - return -1; - memset(&header, 0, sizeof(header)); - header.magic = cpu_to_be32(QCOW_MAGIC); - header.version = cpu_to_be32(QCOW_VERSION); - header.size = cpu_to_be64(total_size * 512); - header_size = sizeof(header); - backing_filename_len = 0; - if (backing_file) { - header.backing_file_offset = cpu_to_be64(header_size); - backing_filename_len = strlen(backing_file); - header.backing_file_size = cpu_to_be32(backing_filename_len); - header_size += backing_filename_len; - } - s->cluster_bits = 12; /* 4 KB clusters */ - s->cluster_size = 1 << s->cluster_bits; - header.cluster_bits = cpu_to_be32(s->cluster_bits); - header_size = (header_size + 7) & ~7; - if (flags & BLOCK_FLAG_ENCRYPT) { - header.crypt_method = cpu_to_be32(QCOW_CRYPT_AES); - } else { - header.crypt_method = cpu_to_be32(QCOW_CRYPT_NONE); - } - l2_bits = s->cluster_bits - 3; - shift = s->cluster_bits + l2_bits; - l1_size = (((total_size * 512) + (1LL << shift) - 1) >> shift); - offset = align_offset(header_size, s->cluster_size); - s->l1_table_offset = offset; - header.l1_table_offset = cpu_to_be64(s->l1_table_offset); - header.l1_size = cpu_to_be32(l1_size); - offset += align_offset(l1_size * sizeof(uint64_t), s->cluster_size); - - s->refcount_table = qemu_mallocz(s->cluster_size); - s->refcount_block = qemu_mallocz(s->cluster_size); - - s->refcount_table_offset = offset; - header.refcount_table_offset = cpu_to_be64(offset); - header.refcount_table_clusters = cpu_to_be32(1); - offset += s->cluster_size; - - s->refcount_table[0] = cpu_to_be64(offset); - s->refcount_block_offset = offset; - offset += s->cluster_size; - - /* update refcounts */ - create_refcount_update(s, 0, header_size); - create_refcount_update(s, s->l1_table_offset, l1_size * sizeof(uint64_t)); - create_refcount_update(s, s->refcount_table_offset, s->cluster_size); - create_refcount_update(s, s->refcount_block_offset, s->cluster_size); - - /* write all the data */ - ret = write(fd, &header, sizeof(header)); - if (ret < 0) - goto out; - if (backing_file) { - ret = write(fd, backing_file, backing_filename_len); - if (ret < 0) - goto out; - } - lseek(fd, s->l1_table_offset, SEEK_SET); - tmp = 0; - for(i = 0;i < l1_size; i++) { - ret = write(fd, &tmp, sizeof(tmp)); - if (ret < 0) - goto out; - } - lseek(fd, s->refcount_table_offset, SEEK_SET); - ret = write(fd, s->refcount_table, s->cluster_size); - if (ret < 0) - goto out; - - lseek(fd, s->refcount_block_offset, SEEK_SET); - ret = write(fd, s->refcount_block, s->cluster_size); - if (ret < 0) - goto out; - ret = 0; - - out: - qemu_free(s->refcount_table); - qemu_free(s->refcount_block); - close(fd); - return ret; -} - - - -struct tap_disk tapdisk_qcow2 = { - "qcow2", - sizeof(BDRVQcowState), - qcow_open, -#ifdef USE_AIO - qcow_queue_read, - qcow_queue_write, -#else - qcow_sync_read, - qcow_sync_write, -#endif - qcow_submit, - qcow_close, - qcow_do_callbacks, - qcow_get_parent_id, - qcow_validate_parent -}; diff --git a/tools/blktap/drivers/block-ram.c b/tools/blktap/drivers/block-ram.c deleted file mode 100644 index 836a68e255..0000000000 --- a/tools/blktap/drivers/block-ram.c +++ /dev/null @@ -1,295 +0,0 @@ -/* block-ram.c - * - * Fast Ramdisk implementation. - * - * (c) 2006 Andrew Warfield and Julian Chesterfield - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation; or, when distributed - * separately from the Linux kernel or incorporated into other - * software packages, subject to the following license: - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this source file (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, modify, - * merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "tapdisk.h" -#include "blk.h" - -#define MAX_DISK_SIZE 1024000 /*500MB disk limit*/ - -/* *BSD has no O_LARGEFILE */ -#ifndef O_LARGEFILE -#define O_LARGEFILE 0 -#endif - -char *img; -long int disksector_size; -long int disksize; -long int diskinfo; -static int connections = 0; - -struct tdram_state { - int fd; - int poll_pipe[2]; /* dummy fd for polling on */ -}; - -/*Get Image size, secsize*/ -static int get_image_info(struct td_state *s, int fd) -{ - int ret; - long size; - unsigned long total_size; - struct statvfs statBuf; - struct stat stat; - - ret = fstat(fd, &stat); - if (ret != 0) { - DPRINTF("ERROR: fstat failed, Couldn't stat image"); - return -EINVAL; - } - - if (S_ISBLK(stat.st_mode)) { - /*Accessing block device directly*/ - if (blk_getimagesize(fd, &s->size) != 0) - return -EINVAL; - - DPRINTF("Image size: \n\tpre sector_shift [%llu]\n\tpost " - "sector_shift [%llu]\n", - (long long unsigned)(s->size << SECTOR_SHIFT), - (long long unsigned)s->size); - - /*Get the sector size*/ - if (blk_getsectorsize(fd, &s->sector_size) != 0) - s->sector_size = DEFAULT_SECTOR_SIZE; - - } else { - /*Local file? try fstat instead*/ - s->size = (stat.st_size >> SECTOR_SHIFT); - s->sector_size = DEFAULT_SECTOR_SIZE; - DPRINTF("Image size: \n\tpre sector_shift [%llu]\n\tpost " - "sector_shift [%llu]\n", - (long long unsigned)(s->size << SECTOR_SHIFT), - (long long unsigned)s->size); - } - - if (s->size == 0) { - s->size =((uint64_t) MAX_DISK_SIZE); - s->sector_size = DEFAULT_SECTOR_SIZE; - } - s->info = 0; - - /*Store variables locally*/ - disksector_size = s->sector_size; - disksize = s->size; - diskinfo = s->info; - DPRINTF("Image sector_size: \n\t[%"PRIu64"]\n", - s->sector_size); - - return 0; -} - -static inline void init_fds(struct disk_driver *dd) -{ - int i; - struct tdram_state *prv = (struct tdram_state *)dd->private; - - for(i =0 ; i < MAX_IOFD; i++) - dd->io_fd[i] = 0; - - dd->io_fd[0] = prv->poll_pipe[0]; -} - -/* Open the disk file and initialize ram state. */ -static int tdram_open (struct disk_driver *dd, const char *name, td_flag_t flags) -{ - char *p; - uint64_t size; - int i, fd, ret = 0, count = 0, o_flags; - struct td_state *s = dd->td_state; - struct tdram_state *prv = (struct tdram_state *)dd->private; - - connections++; - - /* set up a pipe so that we can hand back a poll fd that won't fire.*/ - ret = pipe(prv->poll_pipe); - if (ret != 0) - return (0 - errno); - - if (connections > 1) { - s->sector_size = disksector_size; - s->size = disksize; - s->info = diskinfo; - DPRINTF("Image already open, returning parameters:\n"); - DPRINTF("Image size: \n\tpre sector_shift [%llu]\n\tpost " - "sector_shift [%llu]\n", - (long long unsigned)(s->size << SECTOR_SHIFT), - (long long unsigned)s->size); - DPRINTF("Image sector_size: \n\t[%"PRIu64"]\n", - s->sector_size); - - prv->fd = -1; - goto done; - } - - /* Open the file */ - o_flags = O_DIRECT | O_LARGEFILE | - ((flags == TD_RDONLY) ? O_RDONLY : O_RDWR); - fd = open(name, o_flags); - - if ((fd == -1) && (errno == EINVAL)) { - - /* Maybe O_DIRECT isn't supported. */ - o_flags &= ~O_DIRECT; - fd = open(name, o_flags); - if (fd != -1) DPRINTF("WARNING: Accessing image without" - "O_DIRECT! (%s)\n", name); - - } else if (fd != -1) DPRINTF("open(%s) with O_DIRECT\n", name); - - if (fd == -1) { - DPRINTF("Unable to open [%s]!\n",name); - ret = 0 - errno; - goto done; - } - - prv->fd = fd; - - ret = get_image_info(s, fd); - size = MAX_DISK_SIZE; - - if (s->size > size) { - DPRINTF("Disk exceeds limit, must be less than [%d]MB", - (MAX_DISK_SIZE<>20); - return -ENOMEM; - } - - /*Read the image into memory*/ - p = img = malloc(s->size << SECTOR_SHIFT); - if (img == NULL) { - DPRINTF("Mem malloc failed\n"); - return -1; - } - DPRINTF("Reading %llu bytes.......",(long long unsigned)s->size << SECTOR_SHIFT); - - for (i = 0; i < s->size; i++) { - ret = read(prv->fd, p, s->sector_size); - if (ret != s->sector_size) { - ret = 0 - errno; - break; - } else { - count += ret; - p = img + count; - } - } - DPRINTF("[%d]\n",count); - if (count != s->size << SECTOR_SHIFT) { - ret = -1; - } else { - ret = 0; - } - - init_fds(dd); -done: - return ret; -} - -static int tdram_queue_read(struct disk_driver *dd, uint64_t sector, - int nb_sectors, char *buf, td_callback_t cb, - int id, void *private) -{ - struct td_state *s = dd->td_state; - struct tdram_state *prv = (struct tdram_state *)dd->private; - int size = nb_sectors * s->sector_size; - uint64_t offset = sector * (uint64_t)s->sector_size; - - memcpy(buf, img + offset, size); - - return cb(dd, 0, sector, nb_sectors, id, private); -} - -static int tdram_queue_write(struct disk_driver *dd, uint64_t sector, - int nb_sectors, char *buf, td_callback_t cb, - int id, void *private) -{ - struct td_state *s = dd->td_state; - struct tdram_state *prv = (struct tdram_state *)dd->private; - int size = nb_sectors * s->sector_size; - uint64_t offset = sector * (uint64_t)s->sector_size; - - /* We assume that write access is controlled - * at a higher level for multiple disks */ - memcpy(img + offset, buf, size); - - return cb(dd, 0, sector, nb_sectors, id, private); -} - -static int tdram_submit(struct disk_driver *dd) -{ - return 0; -} - -static int tdram_close(struct disk_driver *dd) -{ - struct tdram_state *prv = (struct tdram_state *)dd->private; - - connections--; - - return 0; -} - -static int tdram_do_callbacks(struct disk_driver *dd, int sid) -{ - /* always ask for a kick */ - return 1; -} - -static int tdram_get_parent_id(struct disk_driver *dd, struct disk_id *id) -{ - return TD_NO_PARENT; -} - -static int tdram_validate_parent(struct disk_driver *dd, - struct disk_driver *parent, td_flag_t flags) -{ - return -EINVAL; -} - -struct tap_disk tapdisk_ram = { - .disk_type = "tapdisk_ram", - .private_data_size = sizeof(struct tdram_state), - .td_open = tdram_open, - .td_queue_read = tdram_queue_read, - .td_queue_write = tdram_queue_write, - .td_submit = tdram_submit, - .td_close = tdram_close, - .td_do_callbacks = tdram_do_callbacks, - .td_get_parent_id = tdram_get_parent_id, - .td_validate_parent = tdram_validate_parent -}; diff --git a/tools/blktap/drivers/block-sync.c b/tools/blktap/drivers/block-sync.c deleted file mode 100644 index dde4538e7c..0000000000 --- a/tools/blktap/drivers/block-sync.c +++ /dev/null @@ -1,242 +0,0 @@ -/* block-sync.c - * - * simple slow synchronous raw disk implementation. - * - * (c) 2006 Andrew Warfield and Julian Chesterfield - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation; or, when distributed - * separately from the Linux kernel or incorporated into other - * software packages, subject to the following license: - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this source file (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, modify, - * merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "tapdisk.h" -#include "blk.h" - -/* *BSD has no O_LARGEFILE */ -#ifndef O_LARGEFILE -#define O_LARGEFILE 0 -#endif - -struct tdsync_state { - int fd; - int poll_pipe[2]; /* dummy fd for polling on */ -}; - -/*Get Image size, secsize*/ -static int get_image_info(struct td_state *s, int fd) -{ - int ret; - long size; - unsigned long total_size; - struct statvfs statBuf; - struct stat stat; - - ret = fstat(fd, &stat); - if (ret != 0) { - DPRINTF("ERROR: fstat failed, Couldn't stat image"); - return -EINVAL; - } - - if (S_ISBLK(stat.st_mode)) { - /*Accessing block device directly*/ - if (blk_getimagesize(fd, &s->size) != 0) - return -EINVAL; - - DPRINTF("Image size: \n\tpre sector_shift [%llu]\n\tpost " - "sector_shift [%llu]\n", - (long long unsigned)(s->size << SECTOR_SHIFT), - (long long unsigned)s->size); - - /*Get the sector size*/ - if (blk_getsectorsize(fd, &s->sector_size) != 0) - s->sector_size = DEFAULT_SECTOR_SIZE; - - } else { - /*Local file? try fstat instead*/ - s->size = (stat.st_size >> SECTOR_SHIFT); - s->sector_size = DEFAULT_SECTOR_SIZE; - DPRINTF("Image size: \n\tpre sector_shift [%lluu]\n\tpost " - "sector_shift [%lluu]\n", - (long long unsigned)(s->size << SECTOR_SHIFT), - (long long unsigned)s->size); - } - - if (s->size == 0) - return -EINVAL; - - s->info = 0; - - return 0; -} - -static inline void init_fds(struct disk_driver *dd) -{ - int i; - struct tdsync_state *prv = (struct tdsync_state *)dd->private; - - for(i = 0; i < MAX_IOFD; i++) - dd->io_fd[i] = 0; - - dd->io_fd[0] = prv->poll_pipe[0]; -} - -/* Open the disk file and initialize aio state. */ -static int tdsync_open (struct disk_driver *dd, const char *name, td_flag_t flags) -{ - int i, fd, ret = 0, o_flags; - struct td_state *s = dd->td_state; - struct tdsync_state *prv = (struct tdsync_state *)dd->private; - - /* set up a pipe so that we can hand back a poll fd that won't fire.*/ - ret = pipe(prv->poll_pipe); - if (ret != 0) - return (0 - errno); - - /* Open the file */ - o_flags = O_DIRECT | O_LARGEFILE | - ((flags == TD_RDONLY) ? O_RDONLY : O_RDWR); - fd = open(name, o_flags); - - if ( (fd == -1) && (errno == EINVAL) ) { - - /* Maybe O_DIRECT isn't supported. */ - o_flags &= ~O_DIRECT; - fd = open(name, o_flags); - if (fd != -1) DPRINTF("WARNING: Accessing image without" - "O_DIRECT! (%s)\n", name); - - } else if (fd != -1) DPRINTF("open(%s) with O_DIRECT\n", name); - - if (fd == -1) { - DPRINTF("Unable to open [%s]!\n",name); - ret = 0 - errno; - goto done; - } - - prv->fd = fd; - - init_fds(dd); - ret = get_image_info(s, fd); -done: - return ret; -} - -static int tdsync_queue_read(struct disk_driver *dd, uint64_t sector, - int nb_sectors, char *buf, td_callback_t cb, - int id, void *private) -{ - struct td_state *s = dd->td_state; - struct tdsync_state *prv = (struct tdsync_state *)dd->private; - int size = nb_sectors * s->sector_size; - uint64_t offset = sector * (uint64_t)s->sector_size; - int ret; - - ret = lseek(prv->fd, offset, SEEK_SET); - if (ret != (off_t)-1) { - ret = read(prv->fd, buf, size); - if (ret != size) { - ret = 0 - errno; - } else { - ret = 1; - } - } else ret = 0 - errno; - - return cb(dd, (ret < 0) ? ret: 0, sector, nb_sectors, id, private); -} - -static int tdsync_queue_write(struct disk_driver *dd, uint64_t sector, - int nb_sectors, char *buf, td_callback_t cb, - int id, void *private) -{ - struct td_state *s = dd->td_state; - struct tdsync_state *prv = (struct tdsync_state *)dd->private; - int size = nb_sectors * s->sector_size; - uint64_t offset = sector * (uint64_t)s->sector_size; - int ret = 0; - - ret = lseek(prv->fd, offset, SEEK_SET); - if (ret != (off_t)-1) { - ret = write(prv->fd, buf, size); - if (ret != size) { - ret = 0 - errno; - } else { - ret = 1; - } - } else ret = 0 - errno; - - return cb(dd, (ret < 0) ? ret : 0, sector, nb_sectors, id, private); -} - -static int tdsync_submit(struct disk_driver *dd) -{ - return 0; -} - -static int tdsync_close(struct disk_driver *dd) -{ - struct tdsync_state *prv = (struct tdsync_state *)dd->private; - - close(prv->fd); - close(prv->poll_pipe[0]); - close(prv->poll_pipe[1]); - - return 0; -} - -static int tdsync_do_callbacks(struct disk_driver *dd, int sid) -{ - /* always ask for a kick */ - return 1; -} - -static int tdsync_get_parent_id(struct disk_driver *dd, struct disk_id *id) -{ - return TD_NO_PARENT; -} - -static int tdsync_validate_parent(struct disk_driver *dd, - struct disk_driver *parent, td_flag_t flags) -{ - return -EINVAL; -} - -struct tap_disk tapdisk_sync = { - .disk_type = "tapdisk_sync", - .private_data_size = sizeof(struct tdsync_state), - .td_open = tdsync_open, - .td_queue_read = tdsync_queue_read, - .td_queue_write = tdsync_queue_write, - .td_submit = tdsync_submit, - .td_close = tdsync_close, - .td_do_callbacks = tdsync_do_callbacks, - .td_get_parent_id = tdsync_get_parent_id, - .td_validate_parent = tdsync_validate_parent -}; diff --git a/tools/blktap/drivers/block-vmdk.c b/tools/blktap/drivers/block-vmdk.c deleted file mode 100644 index 4d16965213..0000000000 --- a/tools/blktap/drivers/block-vmdk.c +++ /dev/null @@ -1,428 +0,0 @@ -/* block-vmdk.c - * - * VMware Disk format implementation. - * - * (c) 2006 Andrew Warfield and Julian Chesterfield - * - * This is largely the same as the vmdk driver in Qemu, I've just twisted it - * to match our interfaces. The original (BSDish) Copyright message appears - * below: - */ - -/* - * Block driver for the VMDK format - * - * Copyright (c) 2004 Fabrice Bellard - * Copyright (c) 2005 Filip Navara - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "tapdisk.h" -#include "bswap.h" - -/* *BSD has no O_LARGEFILE */ -#ifndef O_LARGEFILE -#define O_LARGEFILE 0 -#endif - -#define safer_free(_x) \ - do { \ - if (NULL != _x) { \ - free(_x); \ - (_x) = NULL; \ - } \ - } while (0) ; - -#define VMDK3_MAGIC (('C' << 24) | ('O' << 16) | ('W' << 8) | 'D') -#define VMDK4_MAGIC (('K' << 24) | ('D' << 16) | ('M' << 8) | 'V') - -typedef struct { - uint32_t version; - uint32_t flags; - uint32_t disk_sectors; - uint32_t granularity; - uint32_t l1dir_offset; - uint32_t l1dir_size; - uint32_t file_sectors; - uint32_t cylinders; - uint32_t heads; - uint32_t sectors_per_track; -} VMDK3Header; - -typedef struct { - uint32_t version; - uint32_t flags; - int64_t capacity; - int64_t granularity; - int64_t desc_offset; - int64_t desc_size; - int32_t num_gtes_per_gte; - int64_t rgd_offset; - int64_t gd_offset; - int64_t grain_offset; - char filler[1]; - char check_bytes[4]; -} __attribute__((packed)) VMDK4Header; - -#define L2_CACHE_SIZE 16 - -struct tdvmdk_state { - int fd; - int poll_pipe[2]; /* dummy fd for polling on */ - - unsigned int l1_size; - int64_t l1_table_offset; - int64_t l1_backup_table_offset; - uint32_t l1_entry_sectors; - unsigned int l2_size; - - uint32_t *l1_table; - uint32_t *l1_backup_table; - uint32_t *l2_cache; - uint32_t l2_cache_offsets[L2_CACHE_SIZE]; - uint32_t l2_cache_counts[L2_CACHE_SIZE]; - - unsigned int cluster_sectors; -}; - -static inline void init_fds(struct disk_driver *dd) -{ - int i; - struct tdvmdk_state *prv = (struct tdvmdk_state *)dd->private; - - for (i = 0; i < MAX_IOFD; i++) - dd->io_fd[i] = 0; - - dd->io_fd[0] = prv->poll_pipe[0]; -} - -/* Open the disk file and initialize aio state. */ -static int tdvmdk_open (struct disk_driver *dd, - const char *name, td_flag_t flags) -{ - int ret, fd; - int l1_size, i, o_flags; - uint32_t magic; - struct td_state *s = dd->td_state; - struct tdvmdk_state *prv = (struct tdvmdk_state *)dd->private; - - /* set up a pipe so that we can hand back a poll fd that won't fire.*/ - ret = pipe(prv->poll_pipe); - if (ret != 0) - return -1; - - /* Open the file */ - o_flags = O_DIRECT | O_LARGEFILE | - ((flags == TD_RDONLY) ? O_RDONLY : O_RDWR); - fd = open(name, o_flags); - - if ( (fd == -1) && (errno == EINVAL) ) { - - /* Maybe O_DIRECT isn't supported. */ - o_flags &= ~O_DIRECT; - fd = open(name, o_flags); - if (fd != -1) DPRINTF("WARNING: Accessing image without" - "O_DIRECT! (%s)\n", name); - - } else if (fd != -1) DPRINTF("open(%s) with O_DIRECT\n", name); - - if (fd == -1) { - DPRINTF("Unable to open [%s]!\n",name); - ret = 0 - errno; - return -1; - } - - prv->fd = fd; - - /* Grok the vmdk header. */ - if ((ret = read(fd, &magic, sizeof(magic))) != sizeof(magic)) - goto fail; - magic = be32_to_cpu(magic); - if (magic == VMDK3_MAGIC) { - VMDK3Header header; - if (read(fd, &header, sizeof(header)) != - sizeof(header)) - goto fail; - prv->cluster_sectors = le32_to_cpu(header.granularity); - prv->l2_size = 1 << 9; - prv->l1_size = 1 << 6; - s->size = le32_to_cpu(header.disk_sectors); - prv->l1_table_offset = le32_to_cpu(header.l1dir_offset) << 9; - prv->l1_backup_table_offset = 0; - prv->l1_entry_sectors = prv->l2_size * prv->cluster_sectors; - } else if (magic == VMDK4_MAGIC) { - VMDK4Header header; - - if (read(fd, &header, sizeof(header)) != sizeof(header)) - goto fail; - s->size = le32_to_cpu(header.capacity); - prv->cluster_sectors = le32_to_cpu(header.granularity); - prv->l2_size = le32_to_cpu(header.num_gtes_per_gte); - prv->l1_entry_sectors = prv->l2_size * prv->cluster_sectors; - if (prv->l1_entry_sectors <= 0) - goto fail; - prv->l1_size = (s->size + prv->l1_entry_sectors - 1) - / prv->l1_entry_sectors; - prv->l1_table_offset = le64_to_cpu(header.rgd_offset) << 9; - prv->l1_backup_table_offset = - le64_to_cpu(header.gd_offset) << 9; - } else { - goto fail; - } - /* read the L1 table */ - l1_size = prv->l1_size * sizeof(uint32_t); - prv->l1_table = malloc(l1_size); - if (!prv->l1_table) - goto fail; - if (lseek(fd, prv->l1_table_offset, SEEK_SET) == -1) - goto fail; - if (read(fd, prv->l1_table, l1_size) != l1_size) - goto fail; - for (i = 0; i < prv->l1_size; i++) { - le32_to_cpus(&prv->l1_table[i]); - } - - if (prv->l1_backup_table_offset) { - prv->l1_backup_table = malloc(l1_size); - if (!prv->l1_backup_table) - goto fail; - if (lseek(fd, prv->l1_backup_table_offset, SEEK_SET) == -1) - goto fail; - if (read(fd, prv->l1_backup_table, l1_size) != l1_size) - goto fail; - for(i = 0; i < prv->l1_size; i++) { - le32_to_cpus(&prv->l1_backup_table[i]); - } - } - - prv->l2_cache = malloc(prv->l2_size * L2_CACHE_SIZE *sizeof(uint32_t)); - if (!prv->l2_cache) - goto fail; - prv->fd = fd; - init_fds(dd); - DPRINTF("VMDK File opened successfully\n"); - return 0; - -fail: - DPRINTF("VMDK File open failed.\n"); - safer_free(prv->l1_backup_table); - free(prv->l1_table); - free(prv->l2_cache); - close(fd); - return -1; -} - -static uint64_t get_cluster_offset(struct tdvmdk_state *prv, - uint64_t offset, int allocate) -{ - unsigned int l1_index, l2_offset, l2_index; - int min_index, i, j; - uint32_t min_count, *l2_table, tmp; - uint64_t cluster_offset; - - l1_index = (offset >> 9) / prv->l1_entry_sectors; - if (l1_index >= prv->l1_size) - return 0; - l2_offset = prv->l1_table[l1_index]; - if (!l2_offset) - return 0; - for (i = 0; i < L2_CACHE_SIZE; i++) { - if (l2_offset == prv->l2_cache_offsets[i]) { - /* increment the hit count */ - if (++prv->l2_cache_counts[i] == 0xffffffff) { - for(j = 0; j < L2_CACHE_SIZE; j++) { - prv->l2_cache_counts[j] >>= 1; - } - } - l2_table = prv->l2_cache + (i * prv->l2_size); - goto found; - } - } - /* not found: load a new entry in the least used one */ - min_index = 0; - min_count = 0xffffffff; - for (i = 0; i < L2_CACHE_SIZE; i++) { - if (prv->l2_cache_counts[i] < min_count) { - min_count = prv->l2_cache_counts[i]; - min_index = i; - } - } - l2_table = prv->l2_cache + (min_index * prv->l2_size); - lseek(prv->fd, (int64_t)l2_offset * 512, SEEK_SET); - if (read(prv->fd, l2_table, prv->l2_size * sizeof(uint32_t)) != - prv->l2_size * sizeof(uint32_t)) - return 0; - prv->l2_cache_offsets[min_index] = l2_offset; - prv->l2_cache_counts[min_index] = 1; - found: - l2_index = ((offset >> 9) / prv->cluster_sectors) % prv->l2_size; - cluster_offset = le32_to_cpu(l2_table[l2_index]); - if (!cluster_offset) { - if (!allocate) - return 0; - cluster_offset = lseek(prv->fd, 0, SEEK_END); - if (ftruncate(prv->fd, cluster_offset + - (prv->cluster_sectors << 9))) - return 0; - cluster_offset >>= 9; - /* update L2 table */ - tmp = cpu_to_le32(cluster_offset); - l2_table[l2_index] = tmp; - lseek(prv->fd, ((int64_t)l2_offset * 512) + - (l2_index * sizeof(tmp)), SEEK_SET); - if (write(prv->fd, &tmp, sizeof(tmp)) != sizeof(tmp)) - return 0; - /* update backup L2 table */ - if (prv->l1_backup_table_offset != 0) { - l2_offset = prv->l1_backup_table[l1_index]; - lseek(prv->fd, ((int64_t)l2_offset * 512) + - (l2_index * sizeof(tmp)), SEEK_SET); - if (write(prv->fd, &tmp, sizeof(tmp)) != sizeof(tmp)) - return 0; - } - } - cluster_offset <<= 9; - return cluster_offset; -} - -static int tdvmdk_queue_read(struct disk_driver *dd, uint64_t sector, - int nb_sectors, char *buf, td_callback_t cb, - int id, void *private) -{ - struct tdvmdk_state *prv = (struct tdvmdk_state *)dd->private; - int index_in_cluster, n; - uint64_t cluster_offset; - int ret = 0; - - while (nb_sectors > 0) { - cluster_offset = get_cluster_offset(prv, sector << 9, 0); - index_in_cluster = sector % prv->cluster_sectors; - n = prv->cluster_sectors - index_in_cluster; - if (n > nb_sectors) - n = nb_sectors; - if (!cluster_offset) { - memset(buf, 0, 512 * n); - } else { - lseek(prv->fd, cluster_offset + index_in_cluster * 512, - SEEK_SET); - ret = read(prv->fd, buf, n * 512); - if (ret != n * 512) { - ret = -1; - goto done; - } - } - nb_sectors -= n; - sector += n; - buf += n * 512; - } -done: - return cb(dd, ret == -1 ? -1 : 0, sector, nb_sectors, id, private); -} - -static int tdvmdk_queue_write(struct disk_driver *dd, uint64_t sector, - int nb_sectors, char *buf, td_callback_t cb, - int id, void *private) -{ - struct tdvmdk_state *prv = (struct tdvmdk_state *)dd->private; - int index_in_cluster, n; - uint64_t cluster_offset; - int ret = 0; - - while (nb_sectors > 0) { - index_in_cluster = sector & (prv->cluster_sectors - 1); - n = prv->cluster_sectors - index_in_cluster; - if (n > nb_sectors) - n = nb_sectors; - cluster_offset = get_cluster_offset(prv, sector << 9, 1); - if (!cluster_offset) { - ret = -1; - goto done; - } - lseek(prv->fd, cluster_offset + index_in_cluster * 512, - SEEK_SET); - ret = write(prv->fd, buf, n * 512); - if (ret != n * 512) { - ret = -1; - goto done; - } - nb_sectors -= n; - sector += n; - buf += n * 512; - } -done: - return cb(dd, ret == -1 ? -1 : 0, sector, nb_sectors, id, private); -} - -static int tdvmdk_submit(struct disk_driver *dd) -{ - return 0; -} - -static int tdvmdk_close(struct disk_driver *dd) -{ - struct tdvmdk_state *prv = (struct tdvmdk_state *)dd->private; - - safer_free(prv->l1_table); - safer_free(prv->l1_backup_table); - safer_free(prv->l2_cache); - close(prv->fd); - close(prv->poll_pipe[0]); - close(prv->poll_pipe[1]); - return 0; -} - -static int tdvmdk_do_callbacks(struct disk_driver *dd, int sid) -{ - /* always ask for a kick */ - return 1; -} - -static int tdvmdk_get_parent_id(struct disk_driver *dd, struct disk_id *id) -{ - return TD_NO_PARENT; -} - -static int tdvmdk_validate_parent(struct disk_driver *dd, - struct disk_driver *parent, td_flag_t flags) -{ - return -EINVAL; -} - -struct tap_disk tapdisk_vmdk = { - .disk_type = "tapdisk_vmdk", - .private_data_size = sizeof(struct tdvmdk_state), - .td_open = tdvmdk_open, - .td_queue_read = tdvmdk_queue_read, - .td_queue_write = tdvmdk_queue_write, - .td_submit = tdvmdk_submit, - .td_close = tdvmdk_close, - .td_do_callbacks = tdvmdk_do_callbacks, - .td_get_parent_id = tdvmdk_get_parent_id, - .td_validate_parent = tdvmdk_validate_parent -}; diff --git a/tools/blktap/drivers/bswap.h b/tools/blktap/drivers/bswap.h deleted file mode 100644 index 5578913fd6..0000000000 --- a/tools/blktap/drivers/bswap.h +++ /dev/null @@ -1,178 +0,0 @@ -#ifndef BSWAP_H -#define BSWAP_H - -//#include "config-host.h" - -#include - -#if defined(__NetBSD__) -#include -#include -#elif defined(__OpenBSD__) -#include -#define bswap_16(x) swap16(x) -#define bswap_32(x) swap32(x) -#define bswap_64(x) swap64(x) -#elif defined(__linux__) - -#include - -static inline uint16_t bswap16(uint16_t x) -{ - return bswap_16(x); -} - -static inline uint32_t bswap32(uint32_t x) -{ - return bswap_32(x); -} - -static inline uint64_t bswap64(uint64_t x) -{ - return bswap_64(x); -} - -static inline void bswap16s(uint16_t *s) -{ - *s = bswap16(*s); -} - -static inline void bswap32s(uint32_t *s) -{ - *s = bswap32(*s); -} - -static inline void bswap64s(uint64_t *s) -{ - *s = bswap64(*s); -} - -#endif - -#if defined(WORDS_BIGENDIAN) -#define be_bswap(v, size) (v) -#define le_bswap(v, size) bswap ## size(v) -#define be_bswaps(v, size) -#define le_bswaps(p, size) *p = bswap ## size(*p); -#else -#define le_bswap(v, size) (v) -#define be_bswap(v, size) bswap ## size(v) -#define le_bswaps(v, size) -#define be_bswaps(p, size) *p = bswap ## size(*p); -#endif - -#define CPU_CONVERT(endian, size, type)\ -static inline type endian ## size ## _to_cpu(type v)\ -{\ - return endian ## _bswap(v, size);\ -}\ -\ -static inline type cpu_to_ ## endian ## size(type v)\ -{\ - return endian ## _bswap(v, size);\ -}\ -\ -static inline void endian ## size ## _to_cpus(type *p)\ -{\ - endian ## _bswaps(p, size)\ -}\ -\ -static inline void cpu_to_ ## endian ## size ## s(type *p)\ -{\ - endian ## _bswaps(p, size)\ -}\ -\ -static inline type endian ## size ## _to_cpup(const type *p)\ -{\ - return endian ## size ## _to_cpu(*p);\ -}\ -\ -static inline void cpu_to_ ## endian ## size ## w(type *p, type v)\ -{\ - *p = cpu_to_ ## endian ## size(v);\ -} - -CPU_CONVERT(be, 16, uint16_t) -CPU_CONVERT(be, 32, uint32_t) -CPU_CONVERT(be, 64, uint64_t) - -CPU_CONVERT(le, 16, uint16_t) -CPU_CONVERT(le, 32, uint32_t) -CPU_CONVERT(le, 64, uint64_t) - -/* unaligned versions (optimized for frequent unaligned accesses)*/ - -#if defined(__i386__) || defined(__powerpc__) - -#define cpu_to_le16wu(p, v) cpu_to_le16w(p, v) -#define cpu_to_le32wu(p, v) cpu_to_le32w(p, v) -#define le16_to_cpupu(p) le16_to_cpup(p) -#define le32_to_cpupu(p) le32_to_cpup(p) - -#define cpu_to_be16wu(p, v) cpu_to_be16w(p, v) -#define cpu_to_be32wu(p, v) cpu_to_be32w(p, v) - -#else - -static inline void cpu_to_le16wu(uint16_t *p, uint16_t v) -{ - uint8_t *p1 = (uint8_t *)p; - - p1[0] = v; - p1[1] = v >> 8; -} - -static inline void cpu_to_le32wu(uint32_t *p, uint32_t v) -{ - uint8_t *p1 = (uint8_t *)p; - - p1[0] = v; - p1[1] = v >> 8; - p1[2] = v >> 16; - p1[3] = v >> 24; -} - -static inline uint16_t le16_to_cpupu(const uint16_t *p) -{ - const uint8_t *p1 = (const uint8_t *)p; - return p1[0] | (p1[1] << 8); -} - -static inline uint32_t le32_to_cpupu(const uint32_t *p) -{ - const uint8_t *p1 = (const uint8_t *)p; - return p1[0] | (p1[1] << 8) | (p1[2] << 16) | (p1[3] << 24); -} - -static inline void cpu_to_be16wu(uint16_t *p, uint16_t v) -{ - uint8_t *p1 = (uint8_t *)p; - - p1[0] = v >> 8; - p1[1] = v; -} - -static inline void cpu_to_be32wu(uint32_t *p, uint32_t v) -{ - uint8_t *p1 = (uint8_t *)p; - - p1[0] = v >> 24; - p1[1] = v >> 16; - p1[2] = v >> 8; - p1[3] = v; -} - -#endif - -#ifdef WORDS_BIGENDIAN -#define cpu_to_32wu cpu_to_be32wu -#else -#define cpu_to_32wu cpu_to_le32wu -#endif - -#undef le_bswap -#undef be_bswap -#undef le_bswaps -#undef be_bswaps - -#endif /* BSWAP_H */ diff --git a/tools/blktap/drivers/img2qcow.c b/tools/blktap/drivers/img2qcow.c deleted file mode 100644 index 6b4fa70cf3..0000000000 --- a/tools/blktap/drivers/img2qcow.c +++ /dev/null @@ -1,282 +0,0 @@ -/* img2qcow.c - * - * Generates a qcow format disk and fills it from an existing image. - * - * (c) 2006 Julian Chesterfield and Andrew Warfield - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation; or, when distributed - * separately from the Linux kernel or incorporated into other - * software packages, subject to the following license: - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this source file (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, modify, - * merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "tapdisk.h" -#include "blk.h" - -#if 1 -#define DFPRINTF(_f, _a...) fprintf ( stderr, _f , ## _a ) -#else -#define DFPRINTF(_f, _a...) ((void)0) -#endif - -/* *BSD has no O_LARGEFILE */ -#ifndef O_LARGEFILE -#define O_LARGEFILE 0 -#endif - - -#define TAPDISK 1 -#define BLOCK_PROCESSSZ 4096 - -static int maxfds, *io_fd, running = 1, complete = 0; -static int returned_events = 0, submit_events = 0; -static uint64_t prev = 0; -static char output[25]; - -static void print_bytes(void *ptr, int length) -{ - int i,k; - unsigned char *p = ptr; - - DFPRINTF("Buf dump, length %d:\n",length); - for (k = 0; k < length; k++) { - DFPRINTF("%x",*p); - *p++; - if(k % 16 == 0) DFPRINTF("\n"); - else if(k % 2 == 0) DFPRINTF(" "); - } - DFPRINTF("\n"); - return; -} - -static void debug_output(uint64_t progress, uint64_t size) -{ - uint64_t blocks = size/20; - - /*Output progress every 5% */ - if (progress/blocks > prev) { - memcpy(output+prev+1,"=>",2); - prev++; - DFPRINTF("\r%s %llu%%", output, - (long long)(prev-1)*5); - } - return; -} - -static inline void LOCAL_FD_SET(fd_set *readfds) -{ - FD_SET(io_fd[0], readfds); - maxfds = io_fd[0] + 1; - - return; -} - -static int get_image_info(struct td_state *s, int fd) -{ - int ret; - long size; - unsigned long total_size; - struct statvfs statBuf; - struct stat stat; - - ret = fstat(fd, &stat); - if (ret != 0) { - DFPRINTF("ERROR: fstat failed, Couldn't stat image"); - return -EINVAL; - } - - if (S_ISBLK(stat.st_mode)) { - /*Accessing block device directly*/ - if (blk_getimagesize(fd, &s->size) != 0) - return -EINVAL; - - DFPRINTF("Image size: \n\tpre sector_shift [%llu]\n\tpost " - "sector_shift [%llu]\n", - (long long unsigned)(s->size << SECTOR_SHIFT), - (long long unsigned)s->size); - - /*Get the sector size*/ - if (blk_getsectorsize(fd, &s->sector_size) != 0) - s->sector_size = DEFAULT_SECTOR_SIZE; - - } else { - /*Local file? try fstat instead*/ - s->size = (stat.st_size >> SECTOR_SHIFT); - s->sector_size = DEFAULT_SECTOR_SIZE; - DFPRINTF("Image size: [%llu]\n", - (long long unsigned)s->size); - } - - return 0; -} - -static int send_responses(struct disk_driver *dd, int res, uint64_t sec, - int nr_secs, int idx, void *private) -{ - if (res < 0) DFPRINTF("AIO FAILURE: res [%d]!\n",res); - - returned_events++; - - free(private); - return 0; -} - -int main(int argc, char *argv[]) -{ - struct disk_driver dd; - struct td_state *s; - int ret = -1, fd, len; - fd_set readfds; - struct timeval timeout; - uint64_t i; - char *buf; - - if (argc != 3) { - fprintf(stderr, "Qcow-utils: v1.0.0\n"); - fprintf(stderr, "usage: %s \n", - argv[0]); - exit(-1); - } - - s = malloc(sizeof(struct td_state)); - - /*Open image*/ - fd = open(argv[2], O_RDONLY | O_LARGEFILE); - - if (fd == -1) { - DFPRINTF("Unable to open [%s], (err %d)!\n",argv[2],0 - errno); - exit(-1); - } - - get_image_info(s, fd); - - /*Create qcow file*/ - ret = qcow_create(argv[1],s->size<size); - - dd.td_state = s; - dd.drv = &tapdisk_qcow; - dd.private = malloc(dd.drv->private_data_size); - - /*Open qcow file*/ - if (dd.drv->td_open(&dd, argv[1], 0)!=0) { - DFPRINTF("Unable to open Qcow file [%s]\n",argv[1]); - exit(-1); - } - - io_fd = dd.io_fd; - - /*Initialise the output string*/ - memset(output,0x20,25); - output[0] = '['; - output[22] = ']'; - output[23] = '\0'; - DFPRINTF("%s",output); - - i = 0; - while (running) { - timeout.tv_sec = 0; - - if (!complete) { - /*Read sector from image*/ - if (lseek(fd, i, SEEK_SET) == (off_t)-1) { - DFPRINTF("Unable to access file offset %llu\n", - (long long)i); - exit(-1); - } - - if( (ret = posix_memalign((void **)&buf, - BLOCK_PROCESSSZ, - BLOCK_PROCESSSZ)) != 0) { - DFPRINTF("Unable to read memalign buf (%d)\n",ret); - exit(-1); - } - - /*We attempt to read 4k sized blocks*/ - len = read(fd, buf, BLOCK_PROCESSSZ); - if (len < 512) { - DFPRINTF("Unable to read sector %llu\n", - (long long unsigned) (i >> 9)); - complete = 1; - continue; - } - - if (len % 512) { - len = (len >> 9) << 9; - } - - ret = dd.drv->td_queue_write(&dd, i >> 9, - len >> 9, buf, - send_responses, 0, buf); - - if (!ret) submit_events++; - - if (ret < 0) { - DFPRINTF("UNABLE TO WRITE block [%llu]\n", - (long long unsigned) (i >> 9)); - } else i += len; - - if (i >> 9 == s->size) complete = 1; - - debug_output(i,s->size << 9); - - if ((submit_events % 10 == 0) || complete) - dd.drv->td_submit(&dd); - timeout.tv_usec = 0; - - } else { - timeout.tv_usec = 1000; - if (!submit_events) running = 0; - } - - - /*Check AIO FD*/ - LOCAL_FD_SET(&readfds); - ret = select(maxfds + 1, &readfds, (fd_set *) 0, - (fd_set *) 0, &timeout); - - if (ret > 0) dd.drv->td_do_callbacks(&dd, 0); - if (complete && (returned_events == submit_events)) - running = 0; - } - memcpy(output+prev+1,"=",1); - DFPRINTF("\r%s 100%%\nTRANSFER COMPLETE\n\n", output); - dd.drv->td_close(&dd); - free(dd.private); - free(s); - - return 0; -} diff --git a/tools/blktap/drivers/qcow-create.c b/tools/blktap/drivers/qcow-create.c deleted file mode 100644 index 25abfcd1d4..0000000000 --- a/tools/blktap/drivers/qcow-create.c +++ /dev/null @@ -1,130 +0,0 @@ -/* qcow-create.c - * - * Generates a qcow format disk. - * - * (c) 2006 Andrew Warfield and Julian Chesterfield - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation; or, when distributed - * separately from the Linux kernel or incorporated into other - * software packages, subject to the following license: - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this source file (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, modify, - * merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "tapdisk.h" - -#if 1 -#define DFPRINTF(_f, _a...) fprintf ( stderr, _f , ## _a ) -#else -#define DFPRINTF(_f, _a...) ((void)0) -#endif - -#define MAX_NAME_LEN 1000 - -static void help(void) -{ - fprintf(stderr, "Qcow-utils: v1.0.0\n"); - fprintf(stderr, - "usage: qcow-create [-h help] [-r reserve] [-f format] " - "[]\n"); - exit(-1); -} - -int main(int argc, char *argv[]) -{ - int ret = -1, c, backed = 0; - int sparse = 1; - char *fmt = "qcow"; - uint64_t size; - char filename[MAX_NAME_LEN], bfilename[MAX_NAME_LEN]; - char *tmpfile; - - for(;;) { - c = getopt(argc, argv, "hrf"); - if (c == -1) - break; - switch(c) { - case 'h': - help(); - exit(0); - break; - case 'f': - fmt = argv[optind++]; - break; - case 'r': - sparse = 0; - break; - default: - fprintf(stderr, "Unknown option\n"); - help(); - } - } - - printf("Optind %d, argc %d\n", optind, argc); - if ( !(optind == (argc - 2) || optind == (argc - 3)) ) - help(); - - size = atoi(argv[optind++]); - size = size << 20; - - if (snprintf(filename, MAX_NAME_LEN, "%s",argv[optind++]) >= - MAX_NAME_LEN) { - fprintf(stderr,"Device name too long\n"); - exit(-1); - } - - if (optind != argc) { - /*Backing file argument*/ - backed = 1; - if (snprintf(bfilename, MAX_NAME_LEN, "%s",argv[optind++]) >= - MAX_NAME_LEN) { - fprintf(stderr,"Device name too long\n"); - exit(-1); - } - } - - tmpfile = backed ? bfilename: NULL; - if (!strcmp(fmt, "qcow")) { - ret = qcow_create(filename, size, tmpfile, sparse); - } else if(!strcmp(fmt, "qcow2")) { - ret = qcow2_create(filename, size, tmpfile, sparse); - } else { - fprintf(stderr,"Unsupport format:%s\n", fmt); - exit(-1); - } - DFPRINTF("Creating file size %llu, name %s\n",(long long unsigned)size, filename); - - if (ret < 0) - DPRINTF("Unable to create QCOW file\n"); - else - DPRINTF("QCOW file successfully created\n"); - - return 0; -} diff --git a/tools/blktap/drivers/qcow2raw.c b/tools/blktap/drivers/qcow2raw.c deleted file mode 100644 index 0fa88c1e60..0000000000 --- a/tools/blktap/drivers/qcow2raw.c +++ /dev/null @@ -1,348 +0,0 @@ -/* qcow2raw.c - * - * Generates raw image data from an existing qcow image - * - * (c) 2006 Julian Chesterfield and Andrew Warfield - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation; or, when distributed - * separately from the Linux kernel or incorporated into other - * software packages, subject to the following license: - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this source file (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, modify, - * merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "tapdisk.h" -#include "blk.h" - -#if 1 -#define DFPRINTF(_f, _a...) fprintf ( stderr, _f , ## _a ) -#else -#define DFPRINTF(_f, _a...) ((void)0) -#endif - - -/* *BSD has no O_LARGEFILE */ -#ifndef O_LARGEFILE -#define O_LARGEFILE 0 -#endif - -#define TAPDISK 1 -#define BLOCK_PROCESSSZ 4096 - -static int maxfds, *qcowio_fd, *aio_fd, running = 1, complete = 0; -static int returned_read_events = 0, returned_write_events = 0; -static int submit_events = 0; -static uint32_t read_idx = 0, write_idx = 0; -struct disk_driver ddqcow, ddaio; -static uint64_t prev = 0, written = 0; -static char output[25]; - -static void print_bytes(void *ptr, int length) -{ - int i,k; - unsigned char *p = ptr; - - DFPRINTF("Buf dump, length %d:\n",length); - for (k = 0; k < length; k++) { - DFPRINTF("%x",*p); - *p++; - if (k % 16 == 0) DFPRINTF("\n"); - else if (k % 2 == 0) DFPRINTF(" "); - } - DFPRINTF("\n"); - return; -} - -static void debug_output(uint64_t progress, uint64_t size) -{ - /*Output progress every 5% */ - uint64_t blocks = size/20; - - if (progress/blocks > prev) { - memcpy(output+prev+1,"=>",2); - prev++; - DFPRINTF("\r%s %llu%%", - output, (long long)((prev-1)*5)); - } - return; -} - -static inline void LOCAL_FD_SET(fd_set *readfds) -{ - FD_SET(qcowio_fd[0], readfds); - FD_SET(aio_fd[0], readfds); - - maxfds = (qcowio_fd[0] > aio_fd[0] ? qcowio_fd[0] : aio_fd[0]) + 1; - - return; -} - -static int send_write_responses(struct disk_driver *dd, int res, uint64_t sec, - int nr_secs, int idx, void *private) -{ - if (res < 0) { - DFPRINTF("AIO FAILURE: res [%d]!\n",res); - return 0; - } - written += BLOCK_PROCESSSZ; - returned_write_events++; - write_idx = idx; - - debug_output(written, dd->td_state->size << 9); - free(private); - return 0; -} - -static int send_read_responses(struct disk_driver *dd, int res, uint64_t sec, - int nr_secs, int idx, void *private) -{ - int ret; - - if (res < 0) DFPRINTF("AIO FAILURE: res [%d]!\n",res); - - returned_read_events++; - read_idx = idx; - - ret = ddaio.drv->td_queue_write(&ddaio, idx, BLOCK_PROCESSSZ>>9, private, - send_write_responses, idx, private); - if (ret != 0) { - DFPRINTF("ERROR in submitting queue write!\n"); - return 0; - } - - if ( (returned_read_events == submit_events) || - (returned_read_events % 10 == 0) ) { - ddaio.drv->td_submit(&ddaio); - } - - return 0; -} - -int main(int argc, char *argv[]) -{ - int ret = -1, fd, len,input; - uint64_t size; - fd_set readfds; - struct timeval timeout; - uint64_t i; - char *buf; - struct stat finfo; - - if (argc != 3) { - fprintf(stderr, "Qcow-utils: v1.0.0\n"); - fprintf(stderr, "usage: %s " - "\n", - argv[0]); - exit(-1); - } - - ddqcow.td_state = malloc(sizeof(struct td_state)); - ddaio.td_state = malloc(sizeof(struct td_state)); - - /*Open qcow source file*/ - ddqcow.drv = &tapdisk_qcow; - ddqcow.private = malloc(ddqcow.drv->private_data_size); - - if (ddqcow.drv->td_open(&ddqcow, argv[2], TD_RDONLY)!=0) { - DFPRINTF("Unable to open Qcow file [%s]\n",argv[2]); - exit(-1); - } else DFPRINTF("QCOW file opened, size %llu\n", - (long long unsigned)ddqcow.td_state->size); - - qcowio_fd = ddqcow.io_fd; - - /*Setup aio destination file*/ - ret = stat(argv[1],&finfo); - if (ret == -1) { - /*Check errno*/ - switch(errno) { - case ENOENT: - /*File doesn't exist, create*/ - fd = open(argv[1], - O_RDWR | O_LARGEFILE | O_CREAT, 0644); - if (fd < 0) { - DFPRINTF("ERROR creating file [%s] " - "(errno %d)\n", - argv[1], 0 - errno); - exit(-1); - } - if (ftruncate(fd, (off_t)ddqcow.td_state->size<<9) < 0) { - DFPRINTF("Unable to create file " - "[%s] of size %llu (errno %d). " - "Exiting...\n", - argv[1], - (long long unsigned)ddqcow.td_state->size<<9, - 0 - errno); - close(fd); - exit(-1); - } - close(fd); - break; - case ENXIO: - DFPRINTF("ERROR Device [%s] does not exist\n",argv[1]); - exit(-1); - default: - DFPRINTF("An error occurred opening Device [%s] " - "(errno %d)\n", - argv[1], 0 - errno); - exit(-1); - } - } else { - fprintf(stderr, "WARNING: All existing data in " - "%s will be overwritten.\nDo you wish to continue? " - "(y or n) ", - argv[1]); - if (getchar() != 'y') { - DFPRINTF("Exiting...\n"); - exit(-1); - } - - /*TODO - Test the existing file or device for adequate space*/ - fd = open(argv[1], O_RDWR | O_LARGEFILE); - if (fd < 0) { - DFPRINTF("ERROR: opening file [%s] (errno %d)\n", - argv[1], 0 - errno); - exit(-1); - } - - if (S_ISBLK(finfo.st_mode)) { - if (blk_getimagesize(fd, &size) != 0) { - close(fd); - return -1; - } - - if (size < ddqcow.td_state->size<<9) { - DFPRINTF("ERROR: Not enough space on device " - "%s (%"PRIu64" bytes available, " - "%llu bytes required\n", - argv[1], size, - (long long unsigned)ddqcow.td_state->size<<9); - close(fd); - exit(-1); - } - } else { - if (ftruncate(fd, (off_t)ddqcow.td_state->size<<9) < 0) { - DFPRINTF("Unable to create file " - "[%s] of size %llu (errno %d). " - "Exiting...\n", - argv[1], - (long long unsigned)ddqcow.td_state->size<<9, - 0 - errno); - close(fd); - exit(-1); - } else DFPRINTF("File [%s] truncated to length %llu " - "(%llu)\n", - argv[1], - (long long unsigned)ddqcow.td_state->size<<9, - (long long unsigned)ddqcow.td_state->size); - } - close(fd); - } - - /*Open aio destination file*/ - ddaio.drv = &tapdisk_aio; - ddaio.private = malloc(ddaio.drv->private_data_size); - - if (ddaio.drv->td_open(&ddaio, argv[1], 0)!=0) { - DFPRINTF("Unable to open Qcow file [%s]\n", argv[1]); - exit(-1); - } - - aio_fd = ddaio.io_fd; - - /*Initialise the output string*/ - memset(output,0x20,25); - output[0] = '['; - output[22] = ']'; - output[23] = '\0'; - DFPRINTF("%s",output); - - i = 0; - while (running) { - timeout.tv_sec = 0; - - if (!complete) { - /*Read Pages from qcow image*/ - if ( (ret = posix_memalign((void **)&buf, - BLOCK_PROCESSSZ, - BLOCK_PROCESSSZ)) - != 0) { - DFPRINTF("Unable to alloc memory (%d)\n",ret); - exit(-1); - } - - /*Attempt to read 4k sized blocks*/ - submit_events++; - ret = ddqcow.drv->td_queue_read(&ddqcow, i>>9, - BLOCK_PROCESSSZ>>9, buf, - send_read_responses, i>>9, buf); - - if (ret < 0) { - DFPRINTF("UNABLE TO READ block [%llu]\n", - (long long unsigned)i); - exit(-1); - } else { - i += BLOCK_PROCESSSZ; - } - - if (i >= ddqcow.td_state->size<<9) { - complete = 1; - } - - if ((submit_events % 10 == 0) || complete) - ddqcow.drv->td_submit(&ddqcow); - timeout.tv_usec = 0; - - } else { - timeout.tv_usec = 1000; - if (!submit_events) running = 0; - } - - - /*Check AIO FD*/ - LOCAL_FD_SET(&readfds); - ret = select(maxfds + 1, &readfds, (fd_set *) 0, - (fd_set *) 0, &timeout); - - if (ret > 0) { - if (FD_ISSET(qcowio_fd[0], &readfds)) - ddqcow.drv->td_do_callbacks(&ddqcow, 0); - if (FD_ISSET(aio_fd[0], &readfds)) - ddaio.drv->td_do_callbacks(&ddaio, 0); - } - if (complete && (returned_write_events == submit_events)) - running = 0; - } - memcpy(output+prev+1,"=",1); - DFPRINTF("\r%s 100%%\nTRANSFER COMPLETE\n\n", output); - - return 0; -} diff --git a/tools/blktap/drivers/tapaio.c b/tools/blktap/drivers/tapaio.c deleted file mode 100644 index 140c44a7d1..0000000000 --- a/tools/blktap/drivers/tapaio.c +++ /dev/null @@ -1,357 +0,0 @@ -/* - * Copyright (c) 2006 Andrew Warfield and Julian Chesterfield - * Copyright (c) 2007 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation; or, when distributed - * separately from the Linux kernel or incorporated into other - * software packages, subject to the following license: - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this source file (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, modify, - * merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "tapaio.h" -#include "tapdisk.h" -#include -#include -#include -#include - -/** - * We used a kernel patch to return an fd associated with the AIO context - * so that we can concurrently poll on synchronous and async descriptors. - * This is signalled by passing 1 as the io context to io_setup. - */ -#define REQUEST_ASYNC_FD 1 - -/* - * If we don't have any way to do epoll on aio events in a normal kernel, - * wait for aio events in a separate thread and return completion status - * that via a pipe that can be waited on normally. - * - * To keep locking problems between the completion thread and the submit - * thread to a minimum, there's a handshake which allows only one thread - * to be doing work on the completion queue at a time: - * - * 1) main thread sends completion thread a command via the command pipe; - * 2) completion thread waits for aio events and returns the number - * received on the completion pipe - * 3) main thread processes the received ctx->aio_events events - * 4) loop back to 1) to let the completion thread refill the aio_events - * buffer. - * - * This workaround needs to disappear once the kernel provides a single - * mechanism for waiting on both aio and normal fd wakeups. - */ -static void * -tap_aio_completion_thread(void *arg) -{ - tap_aio_internal_context_t *ctx = (tap_aio_internal_context_t *) arg; - int command; - int nr_events; - int rc; - - while (1) { - rc = read(ctx->command_fd[0], &command, sizeof(command)); - - do { - rc = io_getevents(ctx->aio_ctx, 1, - ctx->max_aio_events, ctx->aio_events, - NULL); - if (rc) { - nr_events = rc; - rc = write(ctx->completion_fd[1], &nr_events, - sizeof(nr_events)); - } - } while (!rc); - } - return NULL; -} - -void -tap_aio_continue(tap_aio_internal_context_t *ctx) -{ - int cmd = 0; - - if (!ctx->poll_in_thread) - return; - - if (write(ctx->command_fd[1], &cmd, sizeof(cmd)) < 0) - DPRINTF("Cannot write to command pipe\n"); -} - -static int -tap_aio_setup(tap_aio_internal_context_t *ctx, - struct io_event *aio_events, - int max_aio_events) -{ - int ret; - - ctx->aio_events = aio_events; - ctx->max_aio_events = max_aio_events; - ctx->poll_in_thread = 0; - - ctx->aio_ctx = (io_context_t) REQUEST_ASYNC_FD; - ret = io_setup(ctx->max_aio_events, &ctx->aio_ctx); - if (ret < 0 && ret != -EINVAL) - return ret; - else if (ret > 0) { - ctx->pollfd = ret; - return ctx->pollfd; - } - - ctx->aio_ctx = (io_context_t) 0; - ret = io_setup(ctx->max_aio_events, &ctx->aio_ctx); - if (ret < 0) - return ret; - - if ((ret = pipe(ctx->command_fd)) < 0) { - DPRINTF("Unable to create command pipe\n"); - return -1; - } - if ((ret = pipe(ctx->completion_fd)) < 0) { - DPRINTF("Unable to create completion pipe\n"); - return -1; - } - - if ((ret = pthread_create(&ctx->aio_thread, NULL, - tap_aio_completion_thread, ctx)) != 0) { - DPRINTF("Unable to create completion thread\n"); - return -1; - } - - ctx->pollfd = ctx->completion_fd[0]; - ctx->poll_in_thread = 1; - - tap_aio_continue(ctx); - - return 0; -} - -int -tap_aio_get_events(tap_aio_internal_context_t *ctx) -{ - int nr_events = 0; - - if (!ctx->poll_in_thread) - nr_events = io_getevents(ctx->aio_ctx, 1, - ctx->max_aio_events, ctx->aio_events, NULL); - else { - int r; - r = read(ctx->completion_fd[0], &nr_events, sizeof(nr_events)); - if (r < 0) { - if (errno == EAGAIN || errno == EINTR) - return 0; - /* This is pretty bad, we'll probably spin */ - DPRINTF("Aargh, read completion_fd failed: %s", - strerror(errno)); - } else if (r != sizeof(nr_events)) { - /* Should never happen because sizeof(nr_events) - * fits in the guaranteed atomic pipe write size. - * Blundering on is slightly nicer than asserting */ - DPRINTF("Aargh, read completion_fd short read %d", r); - } - } - - return nr_events; -} - -int tap_aio_more_events(tap_aio_internal_context_t *ctx) -{ - return io_getevents(ctx->aio_ctx, 0, - ctx->max_aio_events, ctx->aio_events, NULL); -} - -int tap_aio_init(tap_aio_context_t *ctx, uint64_t sectors, - int max_aio_reqs) -{ - int i, ret; - long ioidx; - - ctx->iocb_list = NULL; - ctx->pending_aio = NULL; - ctx->aio_events = NULL; - ctx->iocb_free = NULL; - ctx->iocb_queue = NULL; - - /*Initialize Locking bitmap*/ - ctx->sector_lock = calloc(1, sectors); - - if (!ctx->sector_lock) { - DPRINTF("Failed to allocate sector lock\n"); - goto fail; - } - - - /* Initialize AIO */ - ctx->max_aio_reqs = max_aio_reqs; - ctx->iocb_free_count = ctx->max_aio_reqs; - ctx->iocb_queued = 0; - - if (!(ctx->iocb_list = malloc(sizeof(struct iocb) * ctx->max_aio_reqs)) || - !(ctx->pending_aio = malloc(sizeof(struct pending_aio) * ctx->max_aio_reqs)) || - !(ctx->aio_events = malloc(sizeof(struct io_event) * ctx->max_aio_reqs)) || - !(ctx->iocb_free = malloc(sizeof(struct iocb *) * ctx->max_aio_reqs)) || - !(ctx->iocb_queue = malloc(sizeof(struct iocb *) * ctx->max_aio_reqs))) - { - DPRINTF("Failed to allocate AIO structs (max_aio_reqs = %d)\n", - ctx->max_aio_reqs); - goto fail; - } - - ret = tap_aio_setup(&ctx->aio_ctx, ctx->aio_events, ctx->max_aio_reqs); - if (ret < 0) { - if (ret == -EAGAIN) { - DPRINTF("Couldn't setup AIO context. If you are " - "trying to concurrently use a large number " - "of blktap-based disks, you may need to " - "increase the system-wide aio request limit. " - "(e.g. 'echo echo 1048576 > /proc/sys/fs/" - "aio-max-nr')\n"); - } else { - DPRINTF("Couldn't setup AIO context.\n"); - } - goto fail; - } - - for (i=0;imax_aio_reqs;i++) - ctx->iocb_free[i] = &ctx->iocb_list[i]; - - DPRINTF("AIO state initialised\n"); - - return 0; - -fail: - return -1; -} - -void tap_aio_free(tap_aio_context_t *ctx) -{ - if (ctx->sector_lock) - free(ctx->sector_lock); - if (ctx->iocb_list) - free(ctx->iocb_list); - if (ctx->pending_aio) - free(ctx->pending_aio); - if (ctx->aio_events) - free(ctx->aio_events); - if (ctx->iocb_free) - free(ctx->iocb_free); - if (ctx->iocb_queue) - free(ctx->iocb_queue); -} - -/*TODO: Fix sector span!*/ -int tap_aio_can_lock(tap_aio_context_t *ctx, uint64_t sector) -{ - return (ctx->sector_lock[sector] ? 0 : 1); -} - -int tap_aio_lock(tap_aio_context_t *ctx, uint64_t sector) -{ - return ++ctx->sector_lock[sector]; -} - -void tap_aio_unlock(tap_aio_context_t *ctx, uint64_t sector) -{ - if (!ctx->sector_lock[sector]) return; - - --ctx->sector_lock[sector]; - return; -} - - -int tap_aio_read(tap_aio_context_t *ctx, int fd, int size, - uint64_t offset, char *buf, td_callback_t cb, - int id, uint64_t sector, void *private) -{ - struct iocb *io; - struct pending_aio *pio; - long ioidx; - - if (ctx->iocb_free_count == 0) - return -ENOMEM; - - io = ctx->iocb_free[--ctx->iocb_free_count]; - - ioidx = IOCB_IDX(ctx, io); - pio = &ctx->pending_aio[ioidx]; - pio->cb = cb; - pio->id = id; - pio->private = private; - pio->nb_sectors = size/512; - pio->buf = buf; - pio->sector = sector; - - io_prep_pread(io, fd, buf, size, offset); - io->data = (void *)ioidx; - - ctx->iocb_queue[ctx->iocb_queued++] = io; - - return 0; -} - -int tap_aio_write(tap_aio_context_t *ctx, int fd, int size, - uint64_t offset, char *buf, td_callback_t cb, - int id, uint64_t sector, void *private) -{ - struct iocb *io; - struct pending_aio *pio; - long ioidx; - - if (ctx->iocb_free_count == 0) - return -ENOMEM; - - io = ctx->iocb_free[--ctx->iocb_free_count]; - - ioidx = IOCB_IDX(ctx, io); - pio = &ctx->pending_aio[ioidx]; - pio->cb = cb; - pio->id = id; - pio->private = private; - pio->nb_sectors = size/512; - pio->buf = buf; - pio->sector = sector; - - io_prep_pwrite(io, fd, buf, size, offset); - io->data = (void *)ioidx; - - ctx->iocb_queue[ctx->iocb_queued++] = io; - - return 0; -} - -int tap_aio_submit(tap_aio_context_t *ctx) -{ - int ret; - - if (!ctx->iocb_queued) - return 0; - - ret = io_submit(ctx->aio_ctx.aio_ctx, ctx->iocb_queued, ctx->iocb_queue); - - /* XXX: TODO: Handle error conditions here. */ - - /* Success case: */ - ctx->iocb_queued = 0; - - return 0; -} - diff --git a/tools/blktap/drivers/tapaio.h b/tools/blktap/drivers/tapaio.h deleted file mode 100644 index 27d3881534..0000000000 --- a/tools/blktap/drivers/tapaio.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (c) 2006 Andrew Warfield and Julian Chesterfield - * Copyright (c) 2007 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation; or, when distributed - * separately from the Linux kernel or incorporated into other - * software packages, subject to the following license: - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this source file (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, modify, - * merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef __TAPAIO_H__ -#define __TAPAIO_H__ - -#include -#include -#include - -#include "tapdisk.h" - -#define IOCB_IDX(_ctx, _io) ((_io) - (_ctx)->iocb_list) - -struct tap_aio_internal_context { - io_context_t aio_ctx; - - struct io_event *aio_events; - int max_aio_events; - - pthread_t aio_thread; - int command_fd[2]; - int completion_fd[2]; - int pollfd; - unsigned int poll_in_thread : 1; -}; - - -typedef struct tap_aio_internal_context tap_aio_internal_context_t; - - -struct pending_aio { - td_callback_t cb; - int id; - void *private; - int nb_sectors; - char *buf; - uint64_t sector; -}; - - -struct tap_aio_context { - tap_aio_internal_context_t aio_ctx; - - int max_aio_reqs; - struct iocb *iocb_list; - struct iocb **iocb_free; - struct pending_aio *pending_aio; - int iocb_free_count; - struct iocb **iocb_queue; - int iocb_queued; - struct io_event *aio_events; - - /* Locking bitmap for AIO reads/writes */ - uint8_t *sector_lock; -}; - -typedef struct tap_aio_context tap_aio_context_t; - -void tap_aio_continue (tap_aio_internal_context_t *ctx); -int tap_aio_get_events (tap_aio_internal_context_t *ctx); -int tap_aio_more_events(tap_aio_internal_context_t *ctx); - - -int tap_aio_init(tap_aio_context_t *ctx, uint64_t sectors, - int max_aio_reqs); -void tap_aio_free(tap_aio_context_t *ctx); - -int tap_aio_can_lock(tap_aio_context_t *ctx, uint64_t sector); -int tap_aio_lock(tap_aio_context_t *ctx, uint64_t sector); -void tap_aio_unlock(tap_aio_context_t *ctx, uint64_t sector); - - -int tap_aio_read(tap_aio_context_t *ctx, int fd, int size, - uint64_t offset, char *buf, td_callback_t cb, - int id, uint64_t sector, void *private); -int tap_aio_write(tap_aio_context_t *ctx, int fd, int size, - uint64_t offset, char *buf, td_callback_t cb, - int id, uint64_t sector, void *private); -int tap_aio_submit(tap_aio_context_t *ctx); - -#endif /* __TAPAIO_H__ */ diff --git a/tools/blktap/drivers/tapdisk.c b/tools/blktap/drivers/tapdisk.c deleted file mode 100644 index 19cd77721d..0000000000 --- a/tools/blktap/drivers/tapdisk.c +++ /dev/null @@ -1,872 +0,0 @@ -/* tapdisk.c - * - * separate disk process, spawned by blktapctrl. Inherits code from driver - * plugins - * - * Copyright (c) 2005 Julian Chesterfield and Andrew Warfield. - * - */ - -#define MSG_SIZE 4096 -#define TAPDISK - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "blktaplib.h" -#include "tapdisk.h" - -#if 1 -#define ASSERT(_p) \ - if ( !(_p) ) { DPRINTF("Assertion '%s' failed, line %d, file %s", #_p , \ - __LINE__, __FILE__); *(int*)0=0; } -#else -#define ASSERT(_p) ((void)0) -#endif - -#define INPUT 0 -#define OUTPUT 1 - -static int maxfds, fds[2], run = 1; - -static pid_t process; -int connected_disks = 0; -fd_list_entry_t *fd_start = NULL; - -int do_cow_read(struct disk_driver *dd, blkif_request_t *req, - int sidx, uint64_t sector, int nr_secs); - -#define td_for_each_disk(tds, drv) \ - for (drv = tds->disks; drv != NULL; drv = drv->next) - -static void usage(void) -{ - fprintf(stderr, "blktap-utils: v1.0.0\n"); - fprintf(stderr, "usage: tapdisk \n"); - exit(-1); -} - -static void daemonize(void) -{ - int i; - - if (getppid()==1) return; /* already a daemon */ - if (fork() != 0) exit(0); - -#if 0 - /*Set new program session ID and close all descriptors*/ - setsid(); - for (i = getdtablesize(); i >= 0; --i) close(i); - - /*Send all I/O to /dev/null */ - i = open("/dev/null",O_RDWR); - dup(i); - dup(i); -#endif - return; -} - -static void free_driver(struct disk_driver *d) -{ - if (d->name) - free(d->name); - if (d->private) - free(d->private); - free(d); -} - -static void unmap_disk(struct td_state *s) -{ - tapdev_info_t *info = s->ring_info; - struct disk_driver *dd, *tmp; - fd_list_entry_t *entry; - - dd = s->disks; - while (dd) { - tmp = dd->next; - dd->drv->td_close(dd); - free_driver(dd); - dd = tmp; - } - - if (info != NULL && info->mem > 0) - munmap(info->mem, getpagesize() * BLKTAP_MMAP_REGION_SIZE); - - entry = s->fd_entry; - *entry->pprev = entry->next; - if (entry->next) - entry->next->pprev = entry->pprev; - - close(info->fd); - - free(s->fd_entry); - free(s->blkif); - free(s->ring_info); - free(s); - - return; -} - -static void sig_handler(int sig) -{ - /*Received signal to close. If no disks are active, we close app.*/ - - if (connected_disks < 1) run = 0; -} - -static inline int LOCAL_FD_SET(fd_set *readfds) -{ - fd_list_entry_t *ptr; - struct disk_driver *dd; - - ptr = fd_start; - while (ptr != NULL) { - if (ptr->tap_fd) { - FD_SET(ptr->tap_fd, readfds); - td_for_each_disk(ptr->s, dd) { - if (dd->io_fd[READ]) - FD_SET(dd->io_fd[READ], readfds); - maxfds = (dd->io_fd[READ] > maxfds ? - dd->io_fd[READ] : maxfds); - } - maxfds = (ptr->tap_fd > maxfds ? ptr->tap_fd : maxfds); - } - ptr = ptr->next; - } - - return 0; -} - -static inline fd_list_entry_t *add_fd_entry(int tap_fd, struct td_state *s) -{ - fd_list_entry_t **pprev, *entry; - int i; - - DPRINTF("Adding fd_list_entry\n"); - - /*Add to linked list*/ - s->fd_entry = entry = malloc(sizeof(fd_list_entry_t)); - entry->tap_fd = tap_fd; - entry->s = s; - entry->next = NULL; - - pprev = &fd_start; - while (*pprev != NULL) - pprev = &(*pprev)->next; - - *pprev = entry; - entry->pprev = pprev; - - return entry; -} - -static inline struct td_state *get_state(int cookie) -{ - fd_list_entry_t *ptr; - - ptr = fd_start; - while (ptr != NULL) { - if (ptr->cookie == cookie) return ptr->s; - ptr = ptr->next; - } - return NULL; -} - -static struct tap_disk *get_driver(int drivertype) -{ - /* blktapctrl has passed us the driver type */ - - return dtypes[drivertype]->drv; -} - -static struct td_state *state_init(void) -{ - int i; - struct td_state *s; - blkif_t *blkif; - - s = malloc(sizeof(struct td_state)); - blkif = s->blkif = malloc(sizeof(blkif_t)); - s->ring_info = calloc(1, sizeof(tapdev_info_t)); - - for (i = 0; i < MAX_REQUESTS; i++) { - blkif->pending_list[i].secs_pending = 0; - blkif->pending_list[i].submitting = 0; - } - - return s; -} - -static int map_new_dev(struct td_state *s, int minor) -{ - int tap_fd; - tapdev_info_t *info = s->ring_info; - char *devname; - fd_list_entry_t *ptr; - int page_size; - - if (asprintf(&devname,"%s/%s%d", BLKTAP_DEV_DIR, BLKTAP_DEV_NAME, minor) == -1) - return -1; - tap_fd = open(devname, O_RDWR); - if (tap_fd == -1) - { - DPRINTF("open failed on dev %s!",devname); - goto fail; - } - info->fd = tap_fd; - - /*Map the shared memory*/ - page_size = getpagesize(); - info->mem = mmap(0, page_size * BLKTAP_MMAP_REGION_SIZE, - PROT_READ | PROT_WRITE, MAP_SHARED, info->fd, 0); - if ((long int)info->mem == -1) - { - DPRINTF("mmap failed on dev %s!\n",devname); - goto fail; - } - - /* assign the rings to the mapped memory */ - info->sring = (blkif_sring_t *)((unsigned long)info->mem); - BACK_RING_INIT(&info->fe_ring, info->sring, page_size); - - info->vstart = - (unsigned long)info->mem + (BLKTAP_RING_PAGES * page_size); - - ioctl(info->fd, BLKTAP_IOCTL_SENDPID, process ); - ioctl(info->fd, BLKTAP_IOCTL_SETMODE, BLKTAP_MODE_INTERPOSE ); - free(devname); - - /*Update the fd entry*/ - ptr = fd_start; - while (ptr != NULL) { - if (s == ptr->s) { - ptr->tap_fd = tap_fd; - break; - } - ptr = ptr->next; - } - - return minor; - - fail: - free(devname); - return -1; -} - -static struct disk_driver *disk_init(struct td_state *s, - struct tap_disk *drv, - char *name, td_flag_t flags) -{ - struct disk_driver *dd; - - dd = calloc(1, sizeof(struct disk_driver)); - if (!dd) - return NULL; - - dd->private = malloc(drv->private_data_size); - if (!dd->private) { - free(dd); - return NULL; - } - - dd->drv = drv; - dd->td_state = s; - dd->name = name; - dd->flags = flags; - - return dd; -} - -static int open_disk(struct td_state *s, - struct tap_disk *drv, char *path, td_flag_t flags) -{ - int err; - char *dup; - td_flag_t pflags; - struct disk_id id; - struct disk_driver *d; - - dup = strdup(path); - if (!dup) - return -ENOMEM; - - memset(&id, 0, sizeof(struct disk_id)); - s->disks = d = disk_init(s, drv, dup, flags); - if (!d) - return -ENOMEM; - - err = drv->td_open(d, path, flags); - if (err) { - free_driver(d); - s->disks = NULL; - return -ENOMEM; - } - pflags = flags | TD_RDONLY; - - /* load backing files as necessary */ - while ((err = d->drv->td_get_parent_id(d, &id)) == 0) { - struct disk_driver *new; - - if (id.drivertype > MAX_DISK_TYPES || - !get_driver(id.drivertype) || !id.name) - goto fail; - - dup = strdup(id.name); - if (!dup) - goto fail; - - new = disk_init(s, get_driver(id.drivertype), dup, pflags); - if (!new) - goto fail; - - err = new->drv->td_open(new, new->name, pflags); - if (err) - goto fail; - - err = d->drv->td_validate_parent(d, new, 0); - if (err) { - d->next = new; - goto fail; - } - - d = d->next = new; - free(id.name); - } - - s->info |= ((flags & TD_RDONLY) ? VDISK_READONLY : 0); - - if (err >= 0) - return 0; - - fail: - DPRINTF("failed opening disk\n"); - if (id.name) - free(id.name); - d = s->disks; - while (d) { - struct disk_driver *tmp = d->next; - d->drv->td_close(d); - free_driver(d); - d = tmp; - } - s->disks = NULL; - return -1; -} - -static int read_msg(char *buf) -{ - int length, len, msglen, tap_fd, *io_fd; - char *ptr, *path; - image_t *img; - msg_hdr_t *msg; - msg_newdev_t *msg_dev; - msg_pid_t *msg_pid; - struct tap_disk *drv; - int ret = -1; - struct td_state *s = NULL; - fd_list_entry_t *entry; - - length = read(fds[READ], buf, MSG_SIZE); - - if (length > 0 && length >= sizeof(msg_hdr_t)) - { - msg = (msg_hdr_t *)buf; - DPRINTF("Tapdisk: Received msg, len %d, type %d, UID %d\n", - length,msg->type,msg->cookie); - - switch (msg->type) { - case CTLMSG_PARAMS: - ptr = buf + sizeof(msg_hdr_t); - len = (length - sizeof(msg_hdr_t)); - path = calloc(1, len); - - memcpy(path, ptr, len); - DPRINTF("Received CTLMSG_PARAMS: [%s]\n", path); - - /*Assign driver*/ - drv = get_driver(msg->drivertype); - if (drv == NULL) - goto params_done; - - DPRINTF("Loaded driver: name [%s], type [%d]\n", - drv->disk_type, msg->drivertype); - - /* Allocate the disk structs */ - s = state_init(); - if (s == NULL) - goto params_done; - - /*Open file*/ - ret = open_disk(s, drv, path, - ((msg->readonly) ? TD_RDONLY : 0)); - if (ret) - goto params_done; - - entry = add_fd_entry(0, s); - entry->cookie = msg->cookie; - DPRINTF("Entered cookie %d\n", entry->cookie); - - memset(buf, 0x00, MSG_SIZE); - - params_done: - if (ret == 0) { - msglen = sizeof(msg_hdr_t) + sizeof(image_t); - msg->type = CTLMSG_IMG; - img = (image_t *)(buf + sizeof(msg_hdr_t)); - img->size = s->size; - img->secsize = s->sector_size; - img->info = s->info; - } else { - msglen = sizeof(msg_hdr_t); - msg->type = CTLMSG_IMG_FAIL; - msg->len = msglen; - } - len = write(fds[WRITE], buf, msglen); - free(path); - return 1; - - case CTLMSG_NEWDEV: - msg_dev = (msg_newdev_t *)(buf + sizeof(msg_hdr_t)); - - s = get_state(msg->cookie); - DPRINTF("Retrieving state, cookie %d.....[%s]\n", - msg->cookie, (s == NULL ? "FAIL":"OK")); - if (s != NULL) { - ret = ((map_new_dev(s, msg_dev->devnum) - == msg_dev->devnum ? 0: -1)); - connected_disks++; - } - - memset(buf, 0x00, MSG_SIZE); - msglen = sizeof(msg_hdr_t); - msg->type = (ret == 0 ? CTLMSG_NEWDEV_RSP - : CTLMSG_NEWDEV_FAIL); - msg->len = msglen; - - len = write(fds[WRITE], buf, msglen); - return 1; - - case CTLMSG_CLOSE: - s = get_state(msg->cookie); - if (s) unmap_disk(s); - - connected_disks--; - sig_handler(SIGINT); - - return 1; - - case CTLMSG_PID: - memset(buf, 0x00, MSG_SIZE); - msglen = sizeof(msg_hdr_t) + sizeof(msg_pid_t); - msg->type = CTLMSG_PID_RSP; - msg->len = msglen; - - msg_pid = (msg_pid_t *)(buf + sizeof(msg_hdr_t)); - process = getpid(); - msg_pid->pid = process; - - len = write(fds[WRITE], buf, msglen); - return 1; - - default: - return 0; - } - } - return 0; -} - -static inline int write_rsp_to_ring(struct td_state *s, blkif_response_t *rsp) -{ - tapdev_info_t *info = s->ring_info; - blkif_response_t *rsp_d; - - rsp_d = RING_GET_RESPONSE(&info->fe_ring, info->fe_ring.rsp_prod_pvt); - memcpy(rsp_d, rsp, sizeof(blkif_response_t)); - info->fe_ring.rsp_prod_pvt++; - - return 0; -} - -static inline void kick_responses(struct td_state *s) -{ - tapdev_info_t *info = s->ring_info; - - if (info->fe_ring.rsp_prod_pvt != info->fe_ring.sring->rsp_prod) - { - RING_PUSH_RESPONSES(&info->fe_ring); - ioctl(info->fd, BLKTAP_IOCTL_KICK_FE); - } -} - -static void io_done(struct disk_driver *dd, int sid) -{ - struct tap_disk *drv = dd->drv; - - if (!run) return; /*We have received signal to close*/ - - if (sid > MAX_IOFD || drv->td_do_callbacks(dd, sid) > 0) - kick_responses(dd->td_state); - - return; -} - -static inline uint64_t -segment_start(blkif_request_t *req, int sidx) -{ - int i; - uint64_t start = req->sector_number; - - for (i = 0; i < sidx; i++) - start += (req->seg[i].last_sect - req->seg[i].first_sect + 1); - - return start; -} - -uint64_t sends, responds; -static int send_responses(struct disk_driver *dd, int res, - uint64_t sector, int nr_secs, int idx, void *private) -{ - pending_req_t *preq; - blkif_request_t *req; - int responses_queued = 0; - struct td_state *s = dd->td_state; - blkif_t *blkif = s->blkif; - int sidx = (int)(long)private, secs_done = nr_secs; - - if ( (idx > MAX_REQUESTS-1) ) - { - DPRINTF("invalid index returned(%u)!\n", idx); - return 0; - } - preq = &blkif->pending_list[idx]; - req = &preq->req; - - if (res == BLK_NOT_ALLOCATED) { - res = do_cow_read(dd, req, sidx, sector, nr_secs); - if (res >= 0) { - secs_done = res; - res = 0; - } else - secs_done = 0; - } - - preq->secs_pending -= secs_done; - - if (res == -EBUSY && preq->submitting) - return -EBUSY; /* propagate -EBUSY back to higher layers */ - if (res) - preq->status = BLKIF_RSP_ERROR; - - if (!preq->submitting && preq->secs_pending == 0) - { - blkif_request_t tmp; - blkif_response_t *rsp; - - tmp = preq->req; - rsp = (blkif_response_t *)req; - - rsp->id = tmp.id; - rsp->operation = tmp.operation; - rsp->status = preq->status; - - write_rsp_to_ring(s, rsp); - responses_queued++; - } - return responses_queued; -} - -int do_cow_read(struct disk_driver *dd, blkif_request_t *req, - int sidx, uint64_t sector, int nr_secs) -{ - char *page; - int ret, early; - uint64_t seg_start, seg_end; - struct td_state *s = dd->td_state; - tapdev_info_t *info = s->ring_info; - struct disk_driver *parent = dd->next; - - seg_start = segment_start(req, sidx); - seg_end = seg_start + req->seg[sidx].last_sect + 1; - - ASSERT(sector >= seg_start && sector + nr_secs <= seg_end); - - page = (char *)MMAP_VADDR(info->vstart, - (unsigned long)req->id, sidx); - page += (req->seg[sidx].first_sect << SECTOR_SHIFT); - page += ((sector - seg_start) << SECTOR_SHIFT); - - if (!parent) { - memset(page, 0, nr_secs << SECTOR_SHIFT); - return nr_secs; - } - - /* reissue request to backing file */ - ret = parent->drv->td_queue_read(parent, sector, nr_secs, - page, send_responses, - req->id, (void *)(long)sidx); - if (ret > 0) - parent->early += ret; - - return ((ret >= 0) ? 0 : ret); -} - -static void get_io_request(struct td_state *s) -{ - RING_IDX rp, rc, j, i; - blkif_request_t *req; - int idx, nsects, ret; - uint64_t sector_nr; - char *page; - int early = 0; /* count early completions */ - struct disk_driver *dd = s->disks; - struct tap_disk *drv = dd->drv; - blkif_t *blkif = s->blkif; - tapdev_info_t *info = s->ring_info; - int page_size = getpagesize(); - - if (!run) return; /*We have received signal to close*/ - - rp = info->fe_ring.sring->req_prod; - xen_rmb(); - for (j = info->fe_ring.req_cons; j != rp; j++) - { - int done = 0, start_seg = 0; - - req = NULL; - req = RING_GET_REQUEST(&info->fe_ring, j); - ++info->fe_ring.req_cons; - - if (req == NULL) continue; - - idx = req->id; - - if (info->busy.req) { - /* continue where we left off last time */ - ASSERT(info->busy.req == req); - start_seg = info->busy.seg_idx; - sector_nr = segment_start(req, start_seg); - info->busy.seg_idx = 0; - info->busy.req = NULL; - } else { - ASSERT(blkif->pending_list[idx].secs_pending == 0); - memcpy(&blkif->pending_list[idx].req, - req, sizeof(*req)); - blkif->pending_list[idx].status = BLKIF_RSP_OKAY; - blkif->pending_list[idx].submitting = 1; - sector_nr = req->sector_number; - } - - if ((dd->flags & TD_RDONLY) && - (req->operation == BLKIF_OP_WRITE)) { - blkif->pending_list[idx].status = BLKIF_RSP_ERROR; - goto send_response; - } - - for (i = start_seg; i < req->nr_segments; i++) { - nsects = req->seg[i].last_sect - - req->seg[i].first_sect + 1; - - if ((req->seg[i].last_sect >= page_size >> 9) || - (nsects <= 0)) - continue; - - page = (char *)MMAP_VADDR(info->vstart, - (unsigned long)req->id, i); - page += (req->seg[i].first_sect << SECTOR_SHIFT); - - if (sector_nr >= s->size) { - DPRINTF("Sector request failed:\n"); - DPRINTF("%s request, idx [%d,%d] size [%llu], " - "sector [%llu,%llu]\n", - (req->operation == BLKIF_OP_WRITE ? - "WRITE" : "READ"), - idx,i, - (long long unsigned) - nsects<pending_list[idx].secs_pending += nsects; - - switch (req->operation) - { - case BLKIF_OP_WRITE: - ret = drv->td_queue_write(dd, sector_nr, - nsects, page, - send_responses, - idx, (void *)(long)i); - if (ret > 0) dd->early += ret; - else if (ret == -EBUSY) { - /* put req back on queue */ - --info->fe_ring.req_cons; - info->busy.req = req; - info->busy.seg_idx = i; - goto out; - } - break; - case BLKIF_OP_READ: - ret = drv->td_queue_read(dd, sector_nr, - nsects, page, - send_responses, - idx, (void *)(long)i); - if (ret > 0) dd->early += ret; - else if (ret == -EBUSY) { - /* put req back on queue */ - --info->fe_ring.req_cons; - info->busy.req = req; - info->busy.seg_idx = i; - goto out; - } - break; - default: - DPRINTF("Unknown block operation\n"); - break; - } - sector_nr += nsects; - } - send_response: - blkif->pending_list[idx].submitting = 0; - /* force write_rsp_to_ring for synchronous case */ - if (blkif->pending_list[idx].secs_pending == 0) - dd->early += send_responses(dd, 0, 0, 0, idx, - (void *)(long)0); - } - - out: - /*Batch done*/ - td_for_each_disk(s, dd) { - dd->early += dd->drv->td_submit(dd); - if (dd->early > 0) { - io_done(dd, MAX_IOFD + 1); - dd->early = 0; - } - } - - return; -} - -int main(int argc, char *argv[]) -{ - int len, msglen, ret; - char *p, *buf; - fd_set readfds, writefds; - fd_list_entry_t *ptr; - struct td_state *s; - char openlogbuf[128]; - - if (argc != 3) usage(); - - daemonize(); - - snprintf(openlogbuf, sizeof(openlogbuf), "TAPDISK[%d]", getpid()); - openlog(openlogbuf, LOG_CONS|LOG_ODELAY, LOG_DAEMON); - /*Setup signal handlers*/ - signal (SIGBUS, sig_handler); - signal (SIGINT, sig_handler); - - /*Open the control channel*/ - fds[READ] = open(argv[1],O_RDWR|O_NONBLOCK); - fds[WRITE] = open(argv[2],O_RDWR|O_NONBLOCK); - - if ( (fds[READ] < 0) || (fds[WRITE] < 0) ) - { - DPRINTF("FD open failed [%d,%d]\n", fds[READ], fds[WRITE]); - exit(-1); - } - - buf = calloc(MSG_SIZE, 1); - - if (buf == NULL) - { - DPRINTF("ERROR: allocating memory.\n"); - exit(-1); - } - - while (run) - { - ret = 0; - FD_ZERO(&readfds); - FD_SET(fds[READ], &readfds); - maxfds = fds[READ]; - - /*Set all tap fds*/ - LOCAL_FD_SET(&readfds); - - /*Wait for incoming messages*/ - ret = select(maxfds + 1, &readfds, (fd_set *) 0, - (fd_set *) 0, NULL); - - if (ret > 0) - { - ptr = fd_start; - while (ptr != NULL) { - int progress_made = 0; - struct disk_driver *dd; - tapdev_info_t *info = ptr->s->ring_info; - - td_for_each_disk(ptr->s, dd) { - if (dd->io_fd[READ] && - FD_ISSET(dd->io_fd[READ], - &readfds)) { - io_done(dd, READ); - progress_made = 1; - } - } - - /* completed io from above may have - * queued new requests on chained disks */ - if (progress_made) { - td_for_each_disk(ptr->s, dd) { - dd->early += - dd->drv->td_submit(dd); - if (dd->early > 0) { - io_done(dd, - MAX_IOFD + 1); - dd->early = 0; - } - } - } - - if (FD_ISSET(ptr->tap_fd, &readfds) || - (info->busy.req && progress_made)) - get_io_request(ptr->s); - - ptr = ptr->next; - } - - if (FD_ISSET(fds[READ], &readfds)) - read_msg(buf); - } - } - free(buf); - close(fds[READ]); - close(fds[WRITE]); - - ptr = fd_start; - while (ptr != NULL) { - s = ptr->s; - unmap_disk(s); - close(ptr->tap_fd); - ptr = ptr->next; - } - closelog(); - - return 0; -} diff --git a/tools/blktap/drivers/tapdisk.h b/tools/blktap/drivers/tapdisk.h deleted file mode 100644 index f3e165ac33..0000000000 --- a/tools/blktap/drivers/tapdisk.h +++ /dev/null @@ -1,259 +0,0 @@ -/* tapdisk.h - * - * Generic disk interface for blktap-based image adapters. - * - * (c) 2006 Andrew Warfield and Julian Chesterfield - * - * Some notes on the tap_disk interface: - * - * tap_disk aims to provide a generic interface to easily implement new - * types of image accessors. The structure-of-function-calls is similar - * to disk interfaces used in qemu/denali/etc, with the significant - * difference being the expectation of asynchronous rather than synchronous - * I/O. The asynchronous interface is intended to allow lots of requests to - * be pipelined through a disk, without the disk requiring any of its own - * threads of control. As such, a batch of requests is delivered to the disk - * using: - * - * td_queue_[read,write]() - * - * and passing in a completion callback, which the disk is responsible for - * tracking. The end of a back is marked with a call to: - * - * td_submit() - * - * The disk implementation must provide a file handle, which is used to - * indicate that it needs to do work. tapdisk will add this file handle - * (returned from td_get_fd()) to it's poll set, and will call into the disk - * using td_do_callbacks() whenever there is data pending. - * - * Two disk implementations demonstrate how this interface may be used to - * implement disks with both asynchronous and synchronous calls. block-aio.c - * maps this interface down onto the linux libaio calls, while block-sync uses - * normal posix read/write. - * - * A few things to realize about the sync case, which doesn't need to defer - * io completions: - * - * - td_queue_[read,write]() call read/write directly, and then call the - * callback immediately. The MUST then return a value greater than 0 - * in order to tell tapdisk that requests have finished early, and to - * force responses to be kicked to the clents. - * - * - The fd used for poll is an otherwise unused pipe, which allows poll to - * be safely called without ever returning anything. - * - * NOTE: tapdisk uses the number of sectors submitted per request as a - * ref count. Plugins must use the callback function to communicate the - * completion--or error--of every sector submitted to them. - * - * td_get_parent_id returns: - * 0 if parent id successfully retrieved - * TD_NO_PARENT if no parent exists - * -errno on error - */ - -#ifndef TAPDISK_H_ -#define TAPDISK_H_ - -#include -#include -#include -#include "blktaplib.h" - -/*If enabled, log all debug messages to syslog*/ -#if 1 -#define DPRINTF(_f, _a...) syslog( LOG_DEBUG, __FILE__ ":%d: " _f , __LINE__, ## _a ) -#else -#define DPRINTF(_f, _a...) ((void)0) -#endif - -/* Things disks need to know about, these should probably be in a higher-level - * header. */ -#define MAX_SEGMENTS_PER_REQ 11 -#define SECTOR_SHIFT 9 -#define DEFAULT_SECTOR_SIZE 512 - -#define MAX_IOFD 2 - -#define BLK_NOT_ALLOCATED 99 -#define TD_NO_PARENT 1 - -typedef uint32_t td_flag_t; - -#define TD_RDONLY 1 - -struct td_state; -struct tap_disk; - -struct disk_id { - char *name; - int drivertype; -}; - -struct disk_driver { - int early; - char *name; - void *private; - td_flag_t flags; - int io_fd[MAX_IOFD]; - struct tap_disk *drv; - struct td_state *td_state; - struct disk_driver *next; -}; - -/* This structure represents the state of an active virtual disk. */ -struct td_state { - struct disk_driver *disks; - void *blkif; - void *image; - void *ring_info; - void *fd_entry; - uint64_t sector_size; - uint64_t size; - unsigned int info; -}; - -/* Prototype of the callback to activate as requests complete. */ -typedef int (*td_callback_t)(struct disk_driver *dd, int res, uint64_t sector, - int nb_sectors, int id, void *private); - -/* Structure describing the interface to a virtual disk implementation. */ -/* See note at the top of this file describing this interface. */ -struct tap_disk { - const char *disk_type; - int private_data_size; - int (*td_open) (struct disk_driver *dd, - const char *name, td_flag_t flags); - int (*td_queue_read) (struct disk_driver *dd, uint64_t sector, - int nb_sectors, char *buf, td_callback_t cb, - int id, void *prv); - int (*td_queue_write) (struct disk_driver *dd, uint64_t sector, - int nb_sectors, char *buf, td_callback_t cb, - int id, void *prv); - int (*td_submit) (struct disk_driver *dd); - int (*td_close) (struct disk_driver *dd); - int (*td_do_callbacks) (struct disk_driver *dd, int sid); - int (*td_get_parent_id) (struct disk_driver *dd, struct disk_id *id); - int (*td_validate_parent)(struct disk_driver *dd, - struct disk_driver *p, td_flag_t flags); -}; - -typedef struct disk_info { - int idnum; - char name[50]; /* e.g. "RAMDISK" */ - char handle[10]; /* xend handle, e.g. 'ram' */ - int single_handler; /* is there a single controller for all */ - /* instances of disk type? */ - int use_ioemu; /* backend provider: 0 = tapdisk; 1 = ioemu */ - -#ifdef TAPDISK - struct tap_disk *drv; -#endif -} disk_info_t; - -void debug_fe_ring(struct td_state *s); - -extern struct tap_disk tapdisk_aio; -extern struct tap_disk tapdisk_sync; -extern struct tap_disk tapdisk_vmdk; -extern struct tap_disk tapdisk_ram; -extern struct tap_disk tapdisk_qcow; -extern struct tap_disk tapdisk_qcow2; - - -/*Define Individual Disk Parameters here */ -static disk_info_t aio_disk = { - DISK_TYPE_AIO, - "raw image (aio)", - "aio", - 0, - 0, -#ifdef TAPDISK - &tapdisk_aio, -#endif -}; - -static disk_info_t sync_disk = { - DISK_TYPE_SYNC, - "raw image (sync)", - "sync", - 0, - 0, -#ifdef TAPDISK - &tapdisk_sync, -#endif -}; - -static disk_info_t vmdk_disk = { - DISK_TYPE_VMDK, - "vmware image (vmdk)", - "vmdk", - 1, - 0, -#ifdef TAPDISK - &tapdisk_vmdk, -#endif -}; - -static disk_info_t ram_disk = { - DISK_TYPE_RAM, - "ramdisk image (ram)", - "ram", - 1, - 0, -#ifdef TAPDISK - &tapdisk_ram, -#endif -}; - -static disk_info_t qcow_disk = { - DISK_TYPE_QCOW, - "qcow disk (qcow)", - "qcow", - 0, - 0, -#ifdef TAPDISK - &tapdisk_qcow, -#endif -}; - -static disk_info_t qcow2_disk = { - DISK_TYPE_QCOW2, - "qcow2 disk (qcow2)", - "qcow2", - 0, - 0, -#ifdef TAPDISK - &tapdisk_qcow2, -#endif -}; - -/*Main disk info array */ -static disk_info_t *dtypes[] = { - &aio_disk, - &sync_disk, - &vmdk_disk, - &ram_disk, - &qcow_disk, - &qcow2_disk, -}; - -typedef struct driver_list_entry { - struct blkif *blkif; - struct driver_list_entry **pprev, *next; -} driver_list_entry_t; - -typedef struct fd_list_entry { - int cookie; - int tap_fd; - struct td_state *s; - struct fd_list_entry **pprev, *next; -} fd_list_entry_t; - -int qcow_create(const char *filename, uint64_t total_size, - const char *backing_file, int flags); - -int qcow2_create(const char *filename, uint64_t total_size, - const char *backing_file, int flags); -#endif /*TAPDISK_H_*/ diff --git a/tools/blktap/lib/Makefile b/tools/blktap/lib/Makefile deleted file mode 100644 index 8852c46e5f..0000000000 --- a/tools/blktap/lib/Makefile +++ /dev/null @@ -1,60 +0,0 @@ -XEN_ROOT = $(CURDIR)/../../.. -include $(XEN_ROOT)/tools/Rules.mk - -MAJOR = 3.0 -MINOR = 0 -SONAME = libblktap.so.$(MAJOR) - -CFLAGS += -I. -CFLAGS += $(CFLAGS_libxenctrl) -CFLAGS += $(CFLAGS_libxenstore) -LDLIBS += $(LDLIBS_libxenstore) - -SRCS := -SRCS += xenbus.c blkif.c xs_api.c - -CFLAGS += -Werror -CFLAGS += -Wno-unused -CFLAGS += -fPIC -# get asprintf(): -CFLAGS += -D _GNU_SOURCE - -OBJS = $(SRCS:.c=.o) -OBJS_PIC = $(SRCS:.c=.opic) -IBINS := - -LIB = libblktap.a -LIB_SO = libblktap.so.$(MAJOR).$(MINOR) - -.PHONY: all -all: $(LIB) $(LIB_SO) - -.PHONY: install -install: all - $(INSTALL_DIR) $(DESTDIR)$(LIBDIR) - $(INSTALL_DIR) $(DESTDIR)$(INCLUDEDIR) - $(INSTALL_PROG) $(LIB_SO) $(DESTDIR)$(LIBDIR) - $(INSTALL_DATA) $(LIB) $(DESTDIR)$(LIBDIR) - ln -sf libblktap.so.$(MAJOR).$(MINOR) $(DESTDIR)$(LIBDIR)/libblktap.so.$(MAJOR) - ln -sf libblktap.so.$(MAJOR) $(DESTDIR)$(LIBDIR)/libblktap.so - $(INSTALL_DATA) blktaplib.h $(DESTDIR)$(INCLUDEDIR) - -.PHONY: clean -clean: - rm -rf *.a *.so* *.o *.opic *.rpm $(LIB) $(LIB_SO) *~ $(DEPS) xen TAGS - -libblktap.so.$(MAJOR).$(MINOR): $(OBJS_PIC) - $(CC) $(LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,$(SONAME) $(SHLIB_LDFLAGS) \ - -o $@ $^ $(LDLIBS) - ln -sf libblktap.so.$(MAJOR).$(MINOR) libblktap.so.$(MAJOR) - ln -sf libblktap.so.$(MAJOR) libblktap.so - -libblktap.a: $(OBJS) - $(AR) rc $@ $^ - -.PHONY: TAGS -TAGS: - etags -t $(SRCS) *.h - --include $(DEPS) - diff --git a/tools/blktap/lib/blkif.c b/tools/blktap/lib/blkif.c deleted file mode 100644 index 9a195960a0..0000000000 --- a/tools/blktap/lib/blkif.c +++ /dev/null @@ -1,185 +0,0 @@ -/* - * tools/blktap_user/blkif.c - * - * The blkif interface for blktap. A blkif describes an in-use virtual disk. - * (c) 2005 Andrew Warfield and Julian Chesterfield - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation; or, when distributed - * separately from the Linux kernel or incorporated into other - * software packages, subject to the following license: - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this source file (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, modify, - * merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include - -#include "blktaplib.h" - -#if 0 -#define DPRINTF(_f, _a...) printf ( _f , ## _a ) -#else -#define DPRINTF(_f, _a...) ((void)0) -#endif - -#define BLKIF_HASHSZ 1024 -#define BLKIF_HASH(_d,_h) (((int)(_d)^(int)(_h))&(BLKIF_HASHSZ-1)) - -static blkif_t *blkif_hash[BLKIF_HASHSZ]; - -blkif_t *blkif_find_by_handle(domid_t domid, unsigned int handle) -{ - blkif_t *blkif = blkif_hash[BLKIF_HASH(domid, handle)]; - while ( (blkif != NULL) && - ((blkif->domid != domid) || (blkif->handle != handle)) ) - blkif = blkif->hash_next; - return blkif; -} - -blkif_t *alloc_blkif(domid_t domid) -{ - blkif_t *blkif; - DPRINTF("Alloc_blkif called [%d]\n",domid); - blkif = (blkif_t *)malloc(sizeof(blkif_t)); - if (!blkif) - return NULL; - memset(blkif, 0, sizeof(*blkif)); - blkif->domid = domid; - blkif->devnum = -1; - return blkif; -} - -/*Controller callbacks*/ -static int (*new_devmap_hook)(blkif_t *blkif) = NULL; -void register_new_devmap_hook(int (*fn)(blkif_t *blkif)) -{ - new_devmap_hook = fn; -} - -static int (*new_unmap_hook)(blkif_t *blkif) = NULL; -void register_new_unmap_hook(int (*fn)(blkif_t *blkif)) -{ - new_unmap_hook = fn; -} - -static int (*new_blkif_hook)(blkif_t *blkif) = NULL; -void register_new_blkif_hook(int (*fn)(blkif_t *blkif)) -{ - new_blkif_hook = fn; -} - -int blkif_init(blkif_t *blkif, long int handle, long int pdev, - long int readonly) -{ - domid_t domid; - blkif_t **pblkif; - int devnum; - - if (blkif == NULL) - return -EINVAL; - - domid = blkif->domid; - blkif->handle = handle; - blkif->pdev = pdev; - blkif->readonly = readonly; - - /* - * Call out to the new_blkif_hook. - * The tap application should define this, - * and it should return having set blkif->ops - * - */ - if (new_blkif_hook == NULL) - { - DPRINTF("Probe detected a new blkif, but no new_blkif_hook!"); - return -1; - } - if (new_blkif_hook(blkif)!=0) { - DPRINTF("BLKIF: Image open failed\n"); - return -1; - } - - /* Now wire it in. */ - pblkif = &blkif_hash[BLKIF_HASH(domid, handle)]; - DPRINTF("Created hash entry: %d [%d,%ld]\n", - BLKIF_HASH(domid, handle), domid, handle); - - while ( *pblkif != NULL ) - { - if ( ((*pblkif)->domid == domid) && - ((*pblkif)->handle == handle) ) - { - DPRINTF("Could not create blkif: already exists\n"); - return -1; - } - pblkif = &(*pblkif)->hash_next; - } - blkif->hash_next = NULL; - *pblkif = blkif; - - if (new_devmap_hook == NULL) - { - DPRINTF("Probe setting up new blkif but no devmap hook!"); - return -1; - } - - devnum = new_devmap_hook(blkif); - if (devnum == -1) - return -1; - blkif->devnum = devnum; - - return 0; -} - -void free_blkif(blkif_t *blkif) -{ - blkif_t **pblkif, *curs; - image_t *image; - - pblkif = &blkif_hash[BLKIF_HASH(blkif->domid, blkif->handle)]; - while ( (curs = *pblkif) != NULL ) - { - if ( blkif == curs ) - { - *pblkif = curs->hash_next; - } - pblkif = &curs->hash_next; - } - if (blkif != NULL) { - if ((image=(image_t *)blkif->prv)!=NULL) { - free(blkif->prv); - } - if (blkif->info!=NULL) { - free(blkif->info); - } - if (new_unmap_hook != NULL) new_unmap_hook(blkif); - free(blkif); - } -} - -void __init_blkif(void) -{ - memset(blkif_hash, 0, sizeof(blkif_hash)); -} diff --git a/tools/blktap/lib/blktaplib.h b/tools/blktap/lib/blktaplib.h deleted file mode 100644 index a80e518361..0000000000 --- a/tools/blktap/lib/blktaplib.h +++ /dev/null @@ -1,240 +0,0 @@ -/* blktaplib.h - * - * Blktap library userspace code. - * - * (c) 2005 Andrew Warfield and Julian Chesterfield - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation; or, when distributed - * separately from the Linux kernel or incorporated into other - * software packages, subject to the following license: - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this source file (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, modify, - * merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef __BLKTAPLIB_H__ -#define __BLKTAPLIB_H__ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define BLK_RING_SIZE __CONST_RING_SIZE(blkif, XC_PAGE_SIZE) - -/* size of the extra VMA area to map in attached pages. */ -#define BLKTAP_VMA_PAGES BLK_RING_SIZE - -/* blktap IOCTLs: These must correspond with the blktap driver ioctls*/ -#define BLKTAP_IOCTL_KICK_FE 1 -#define BLKTAP_IOCTL_KICK_BE 2 -#define BLKTAP_IOCTL_SETMODE 3 -#define BLKTAP_IOCTL_SENDPID 4 -#define BLKTAP_IOCTL_NEWINTF 5 -#define BLKTAP_IOCTL_MINOR 6 -#define BLKTAP_IOCTL_MAJOR 7 -#define BLKTAP_QUERY_ALLOC_REQS 8 -#define BLKTAP_IOCTL_FREEINTF 9 -#define BLKTAP_IOCTL_NEWINTF_EXT 50 -#define BLKTAP_IOCTL_PRINT_IDXS 100 - -/* blktap switching modes: (Set with BLKTAP_IOCTL_SETMODE) */ -#define BLKTAP_MODE_PASSTHROUGH 0x00000000 /* default */ -#define BLKTAP_MODE_INTERCEPT_FE 0x00000001 -#define BLKTAP_MODE_INTERCEPT_BE 0x00000002 - -#define BLKTAP_MODE_INTERPOSE \ - (BLKTAP_MODE_INTERCEPT_FE | BLKTAP_MODE_INTERCEPT_BE) - -static inline int BLKTAP_MODE_VALID(unsigned long arg) -{ - return ( - ( arg == BLKTAP_MODE_PASSTHROUGH ) || - ( arg == BLKTAP_MODE_INTERCEPT_FE ) || - ( arg == BLKTAP_MODE_INTERPOSE ) ); -} - -#define MAX_REQUESTS BLK_RING_SIZE - -#define BLKTAP_IOCTL_KICK 1 -#define MAX_PENDING_REQS BLK_RING_SIZE -#define BLKTAP_DEV_DIR "/dev/xen" -#define BLKTAP_DEV_NAME "blktap" -#define BLKTAP_DEV_MINOR 0 -#define BLKTAP_CTRL_DIR "/var/run/tap" - -extern int blktap_major; - -#define BLKTAP_RING_PAGES 1 /* Front */ -#define BLKTAP_MMAP_REGION_SIZE (BLKTAP_RING_PAGES + MMAP_PAGES) - -struct blkif; - -typedef struct { - blkif_request_t req; - struct blkif *blkif; - int submitting; - int secs_pending; - int16_t status; -} pending_req_t; - -struct blkif_ops { - unsigned long long (*get_size)(struct blkif *blkif); - unsigned long (*get_secsize)(struct blkif *blkif); - unsigned int (*get_info)(struct blkif *blkif); -}; - -typedef struct blkif { - domid_t domid; - long int handle; - - long int pdev; - long int readonly; - - enum { DISCONNECTED, DISCONNECTING, CONNECTED } state; - - struct blkif_ops *ops; - struct blkif *hash_next; - - void *prv; /* device-specific data */ - void *info; /*Image parameter passing */ - pending_req_t pending_list[MAX_REQUESTS]; - int devnum; - int fds[2]; - int be_id; - int major; - int minor; - pid_t tappid; - int drivertype; - uint16_t cookie; -} blkif_t; - -typedef struct blkif_info { - char *params; -} blkif_info_t; - -void register_new_devmap_hook(int (*fn)(blkif_t *blkif)); -void register_new_unmap_hook(int (*fn)(blkif_t *blkif)); -void register_new_blkif_hook(int (*fn)(blkif_t *blkif)); -blkif_t *blkif_find_by_handle(domid_t domid, unsigned int handle); -blkif_t *alloc_blkif(domid_t domid); -int blkif_init(blkif_t *blkif, long int handle, long int pdev, - long int readonly); -void free_blkif(blkif_t *blkif); -void __init_blkif(void); - -typedef struct busy_state { - int seg_idx; - blkif_request_t *req; -} busy_state_t; - -typedef struct tapdev_info { - int fd; - char *mem; - blkif_sring_t *sring; - blkif_back_ring_t fe_ring; - unsigned long vstart; - blkif_t *blkif; - busy_state_t busy; -} tapdev_info_t; - -typedef struct domid_translate { - unsigned short domid; - unsigned short busid; -} domid_translate_t ; - -typedef struct domid_translate_ext { - unsigned short domid; - uint32_t busid; -} domid_translate_ext_t ; - -typedef struct image { - unsigned long long size; - unsigned long secsize; - unsigned int info; -} image_t; - -/* 16-byte message header, immediately followed by message payload. */ -typedef struct msg_hdr { - uint16_t type; - uint16_t len; - uint16_t drivertype; - uint16_t cookie; - uint8_t readonly; - uint8_t pad[7]; -} msg_hdr_t; - -typedef struct msg_newdev { - uint8_t devnum; - uint16_t domid; -} msg_newdev_t; - -typedef struct msg_pid { - pid_t pid; -} msg_pid_t; - -#define READ 0 -#define WRITE 1 - -/*Control Messages between manager and tapdev*/ -#define CTLMSG_PARAMS 1 -#define CTLMSG_IMG 2 -#define CTLMSG_IMG_FAIL 3 -#define CTLMSG_NEWDEV 4 -#define CTLMSG_NEWDEV_RSP 5 -#define CTLMSG_NEWDEV_FAIL 6 -#define CTLMSG_CLOSE 7 -#define CTLMSG_CLOSE_RSP 8 -#define CTLMSG_PID 9 -#define CTLMSG_PID_RSP 10 - -/* disk driver types */ -#define MAX_DISK_TYPES 20 - -#define DISK_TYPE_AIO 0 -#define DISK_TYPE_SYNC 1 -#define DISK_TYPE_VMDK 2 -#define DISK_TYPE_RAM 3 -#define DISK_TYPE_QCOW 4 -#define DISK_TYPE_QCOW2 5 - -/* xenstore/xenbus: */ -#define DOMNAME "Domain-0" -int setup_probe_watch(struct xs_handle *h); - - -/* Abitrary values, must match the underlying driver... */ -#define MAX_TAP_DEV 100 - -/* Accessing attached data page mappings */ -#define MMAP_PAGES \ - (MAX_PENDING_REQS * BLKIF_MAX_SEGMENTS_PER_REQUEST) -#define MMAP_VADDR(_vstart,_req,_seg) \ - ((_vstart) + \ - ((_req) * BLKIF_MAX_SEGMENTS_PER_REQUEST * getpagesize()) + \ - ((_seg) * getpagesize())) - - -#endif /* __BLKTAPLIB_H__ */ diff --git a/tools/blktap/lib/list.h b/tools/blktap/lib/list.h deleted file mode 100644 index c82242f56f..0000000000 --- a/tools/blktap/lib/list.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * list.h - * - * This is a subset of linux's list.h intended to be used in user-space. - * - */ - -#ifndef __LIST_H__ -#define __LIST_H__ - -#ifdef LIST_HEAD -#undef LIST_HEAD -#endif - -#define LIST_POISON1 ((void *) 0x00100100) -#define LIST_POISON2 ((void *) 0x00200200) - -struct list_head { - struct list_head *next, *prev; -}; - -#define LIST_HEAD_INIT(name) { &(name), &(name) } - -#define LIST_HEAD(name) \ - struct list_head name = LIST_HEAD_INIT(name) - -static inline void __list_add(struct list_head *new, - struct list_head *prev, - struct list_head *next) -{ - next->prev = new; - new->next = next; - new->prev = prev; - prev->next = new; -} - -static inline void list_add(struct list_head *new, struct list_head *head) -{ - __list_add(new, head, head->next); -} -static inline void __list_del(struct list_head * prev, struct list_head * next) -{ - next->prev = prev; - prev->next = next; -} -static inline void list_del(struct list_head *entry) -{ - __list_del(entry->prev, entry->next); - entry->next = LIST_POISON1; - entry->prev = LIST_POISON2; -} -#define list_entry(ptr, type, member) \ - ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) -#define list_for_each_entry(pos, head, member) \ - for (pos = list_entry((head)->next, typeof(*pos), member); \ - &pos->member != (head); \ - pos = list_entry(pos->member.next, typeof(*pos), member)) - -#endif /* __LIST_H__ */ diff --git a/tools/blktap/lib/xenbus.c b/tools/blktap/lib/xenbus.c deleted file mode 100644 index 948eb02664..0000000000 --- a/tools/blktap/lib/xenbus.c +++ /dev/null @@ -1,617 +0,0 @@ -/* - * xenbus.c - * - * xenbus interface to the blocktap. - * - * this handles the top-half of integration with block devices through the - * store -- the tap driver negotiates the device channel etc, while the - * userland tap client needs to sort out the disk parameters etc. - * - * (c) 2005 Andrew Warfield and Julian Chesterfield - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation; or, when distributed - * separately from the Linux kernel or incorporated into other - * software packages, subject to the following license: - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this source file (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, modify, - * merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "blktaplib.h" -#include "list.h" -#include "xs_api.h" - -#if 0 -#define DPRINTF(_f, _a...) printf ( _f , ## _a ) -#else -#define DPRINTF(_f, _a...) ((void)0) -#endif - -struct backend_info -{ - /* our communications channel */ - blkif_t *blkif; - - long int frontend_id; - long int pdev; - long int readonly; - - char *backpath; - char *frontpath; - - struct list_head list; -}; - -static LIST_HEAD(belist); - -static int strsep_len(const char *str, char c, unsigned int len) -{ - unsigned int i; - - for (i = 0; str[i]; i++) - if (str[i] == c) { - if (len == 0) - return i; - len--; - } - return (len == 0) ? i : -ERANGE; -} - -static int get_be_id(const char *str) -{ - int len,end; - const char *ptr; - char *tptr, num[10]; - - len = strsep_len(str, '/', 6); - end = strlen(str); - if( (len < 0) || (end < 0) ) return -1; - - ptr = str + len + 1; - strncpy(num, ptr, end - len); - tptr = num + (end - (len + 1)); - *tptr = '\0'; - - return atoi(num); -} - -static int get_be_domid(const char *str) -{ - int len1, len2; - const char *ptr; - char *tptr, num[10]; - - len2 = strsep_len(str, '/', 3); - if ( len2 < 0 ) return -1; - len1 = strsep_len(str, '/', 2); - - ptr = str + len1 + 1; - strncpy(num, ptr, len2 - len1 - 1); - tptr = num + (len2 - len1 - 1); - *tptr = '\0'; - - return atoi(num); -} - -static struct backend_info *be_lookup_be(const char *bepath) -{ - struct backend_info *be; - - list_for_each_entry(be, &belist, list) - if (strcmp(bepath, be->backpath) == 0) - return be; - return (struct backend_info *)NULL; -} - -static int be_exists_be(const char *bepath) -{ - return (be_lookup_be(bepath) != NULL); -} - -static struct backend_info *be_lookup_fe(const char *fepath) -{ - struct backend_info *be; - - list_for_each_entry(be, &belist, list) - if (strcmp(fepath, be->frontpath) == 0) - return be; - return (struct backend_info *)NULL; -} - -static int backend_remove(struct xs_handle *h, struct backend_info *be) -{ - /* Unhook from be list. */ - list_del(&be->list); - - /* Free everything else. */ - if (be->blkif) { - DPRINTF("Freeing blkif dev [%d]\n",be->blkif->devnum); - free_blkif(be->blkif); - } - if (be->frontpath) - free(be->frontpath); - if (be->backpath) - free(be->backpath); - free(be); - return 0; -} - -static const char *get_image_path(const char *path) -{ - const char *tmp; - - /* Strip off the image type */ - if (!strncmp(path, "tapdisk:", strlen("tapdisk:"))) { - path += strlen("tapdisk:"); - } else if (!strncmp(path, "ioemu:", strlen("ioemu:"))) { - path += strlen("ioemu:"); - } - - tmp = strchr(path, ':'); - if (tmp != NULL) - path = tmp + 1; - - return path; -} - -static int check_sharing(struct xs_handle *h, struct backend_info *be) -{ - char *dom_uuid; - char *cur_dom_uuid; - char *path; - char *mode; - char *params; - char **domains; - char **devices; - int i, j; - unsigned int num_dom, num_dev; - blkif_info_t *info = be->blkif->info; - int ret = 0; - const char *image_path[2]; - int be_domid = get_be_domid(be->backpath); - - image_path[0] = get_image_path(info->params); - - /* If the mode contains '!' or doesn't contain 'w' don't check anything */ - xs_gather(h, be->backpath, "mode", NULL, &mode, NULL); - if (strchr(mode, '!')) - goto out; - if (strchr(mode, 'w') == NULL) - goto out; - - /* Get the UUID of the domain we want to attach to */ - if (asprintf(&path, "/local/domain/%ld", be->frontend_id) == -1) - goto fail; - xs_gather(h, path, "vm", NULL, &dom_uuid, NULL); - free(path); - - /* Iterate through the devices of all VMs */ - if (asprintf(&path, "/local/domain/%d/backend/tap", be_domid) == -1) - goto fail; - domains = xs_directory(h, XBT_NULL, path, &num_dom); - free(path); - if (domains == NULL) - num_dom = 0; - - for (i = 0; !ret && (i < num_dom); i++) { - - /* If it's the same VM, no action needed */ - if (asprintf(&path, "/local/domain/%s", domains[i]) == -1) { - ret = -1; - break; - } - cur_dom_uuid = NULL; - xs_gather(h, path, "vm", NULL, &cur_dom_uuid, NULL); - free(path); - if (!cur_dom_uuid) - continue; - - if (!strcmp(cur_dom_uuid, dom_uuid)) { - free(cur_dom_uuid); - continue; - } - - /* Check the devices */ - if (asprintf(&path, "/local/domain/%d/backend/tap/%s", be_domid, domains[i]) == -1) { - ret = -1; - free(cur_dom_uuid); - break; - } - devices = xs_directory(h, XBT_NULL, path, &num_dev); - if (devices == NULL) - num_dev = 0; - free(path); - - for (j = 0; !ret && (j < num_dev); j++) { - if (asprintf(&path, "/local/domain/%d/backend/tap/%s/%s", be_domid, domains[i], devices[j]) == -1) { - ret = -1; - break; - } - params = NULL; - xs_gather(h, path, "params", NULL, ¶ms, NULL); - free(path); - if (!params) - continue; - - image_path[1] = get_image_path(params); - if (!strcmp(image_path[0], image_path[1])) { - ret = -1; - } - - free(params); - } - - free(cur_dom_uuid); - free(devices); - } - free(domains); - free(dom_uuid); - goto out; - -fail: - ret = -1; -out: - free(mode); - return ret; -} - -static int check_image(struct xs_handle *h, struct backend_info *be, - const char** errmsg) -{ - const char *path; - int mode; - blkif_t *blkif = be->blkif; - blkif_info_t *info = blkif->info; - - path = get_image_path(info->params); - - /* Check if the image exists and access is permitted */ - mode = R_OK; - if (!be->readonly) - mode |= W_OK; - if (access(path, mode)) { - if (errno == ENOENT) - *errmsg = "File not found."; - else - *errmsg = "Insufficient file permissions."; - return -1; - } - - /* Check that the image is not attached to a different VM */ - if (check_sharing(h, be)) { - *errmsg = "File already in use by other domain"; - return -1; - } - - return 0; -} - -static void ueblktap_setup(struct xs_handle *h, char *bepath) -{ - struct backend_info *be; - char *path = NULL, *p,*dev; - int len, er, deverr; - long int pdev = 0, handle; - blkif_info_t *blk; - const char* errmsg = NULL; - - be = be_lookup_be(bepath); - if (be == NULL) - { - DPRINTF("ERROR: backend changed called for nonexistent " - "backend! (%s)\n", bepath); - goto fail; - } - - deverr = xs_gather(h, bepath, "physical-device", "%li", &pdev, NULL); - if (!deverr) { - DPRINTF("pdev set to %ld\n",pdev); - if (be->pdev && be->pdev != pdev) { - DPRINTF("changing physical-device not supported"); - goto fail; - } - be->pdev = pdev; - } - - /* Check to see if device is to be opened read-only. */ - deverr = xs_gather(h, bepath, "mode", NULL, &path, NULL); - if (deverr) { - DPRINTF("ERROR: could not find read/write mode\n"); - goto fail; - } else if (path[0] == 'r') - be->readonly = 1; - - if (be->blkif == NULL) { - /* Front end dir is a number, which is used as the handle. */ - p = strrchr(be->frontpath, '/') + 1; - handle = strtoul(p, NULL, 0); - - be->blkif = alloc_blkif(be->frontend_id); - if (be->blkif == NULL) - goto fail; - - be->blkif->be_id = get_be_id(bepath); - - /* Insert device specific info, */ - blk = malloc(sizeof(blkif_info_t)); - if (!blk) { - DPRINTF("Out of memory - blkif_info_t\n"); - goto fail; - } - er = xs_gather(h, bepath, "params", NULL, &blk->params, NULL); - if (er) - goto fail; - be->blkif->info = blk; - - if (deverr) { - /*Dev number was not available, try to set manually*/ - pdev = convert_dev_name_to_num(blk->params); - be->pdev = pdev; - } - - if (check_image(h, be, &errmsg)) - goto fail; - - er = blkif_init(be->blkif, handle, be->pdev, be->readonly); - if (er != 0) { - DPRINTF("Unable to open device %s\n",blk->params); - goto fail; - } - - DPRINTF("[BECHG]: ADDED A NEW BLKIF (%s)\n", bepath); - } - - /* Supply the information about the device to xenstore */ - er = xs_printf(h, be->backpath, "sectors", "%llu", - be->blkif->ops->get_size(be->blkif)); - - if (er == 0) { - DPRINTF("ERROR: Failed writing sectors"); - goto fail; - } - - er = xs_printf(h, be->backpath, "sector-size", "%lu", - be->blkif->ops->get_secsize(be->blkif)); - - if (er == 0) { - DPRINTF("ERROR: Failed writing sector-size"); - goto fail; - } - - er = xs_printf(h, be->backpath, "info", "%u", - be->blkif->ops->get_info(be->blkif)); - - if (er == 0) { - DPRINTF("ERROR: Failed writing info"); - goto fail; - } - - be->blkif->state = CONNECTED; - xs_printf(h, be->backpath, "hotplug-status", "connected"); - - DPRINTF("[SETUP] Complete\n\n"); - goto close; - -fail: - if (be) { - if (errmsg == NULL) - errmsg = "Setting up the backend failed. See the log " - "files in /var/log/xen/ for details."; - xs_printf(h, be->backpath, "hotplug-error", errmsg); - xs_printf(h, be->backpath, "hotplug-status", "error"); - - backend_remove(h, be); - } -close: - if (path) - free(path); - return; -} - -/** - * Xenstore watch callback entry point. This code replaces the hotplug scripts, - * and as soon as the xenstore backend driver entries are created, this script - * gets called. - */ -static void ueblktap_probe(struct xs_handle *h, struct xenbus_watch *w, - const char *bepath_im) -{ - struct backend_info *be = NULL; - char *frontend = NULL, *bepath = NULL, *p; - int er, len; - blkif_t *blkif; - - - bepath = strdup(bepath_im); - - if (!bepath) { - DPRINTF("No path\n"); - return; - } - - /* - *asserts that xenstore structure is always 7 levels deep - *e.g. /local/domain/0/backend/vbd/1/2049 - */ - len = strsep_len(bepath, '/', 7); - if (len < 0) - goto free_be; - if (bepath[len] != '\0') - goto free_be; - - be = malloc(sizeof(*be)); - if (!be) { - DPRINTF("ERROR: allocating backend structure\n"); - goto free_be; - } - memset(be, 0, sizeof(*be)); - frontend = NULL; - - er = xs_gather(h, bepath, - "frontend-id", "%li", &be->frontend_id, - "frontend", NULL, &frontend, - NULL); - - if (er) { - /* - *Unable to find frontend entries, - *bus-id is no longer valid - */ - DPRINTF("ERROR: Frontend-id check failed, removing backend: " - "[%s]\n",bepath); - - /** - * BE info should already exist, - * free new mem and find old entry - */ - free(be); - be = be_lookup_be(bepath); - if ( (be != NULL) && (be->blkif != NULL) ) - backend_remove(h, be); - else goto free_be; - if (bepath) - free(bepath); - return; - } - - /* Are we already tracking this device? */ - if (be_exists_be(bepath)) - goto free_be; - - be->backpath = bepath; - be->frontpath = frontend; - - list_add(&be->list, &belist); - - DPRINTF("[PROBE]\tADDED NEW DEVICE (%s)\n", bepath); - DPRINTF("\tFRONTEND (%s),(%ld)\n", frontend,be->frontend_id); - - ueblktap_setup(h, bepath); - return; - - free_be: - if (frontend) - free(frontend); - if (bepath) - free(bepath); - if (be) - free(be); -} - -/** - *We set a general watch on the backend vbd directory - *ueblktap_probe is called for every update - *Our job is to monitor for new entries. As they - *are created, we initalise the state and attach a disk. - */ - -static int add_blockdevice_probe_watch(struct xs_handle *h, const char *domid) -{ - char *path; - struct xenbus_watch *vbd_watch; - - if (asprintf(&path, "/local/domain/%s/backend/tap", domid) == -1) - return -ENOMEM; - - vbd_watch = (struct xenbus_watch *)malloc(sizeof(struct xenbus_watch)); - if (!vbd_watch) { - DPRINTF("ERROR: unable to malloc vbd_watch [%s]\n", path); - return -EINVAL; - } - vbd_watch->node = path; - vbd_watch->callback = ueblktap_probe; - if (register_xenbus_watch(h, vbd_watch) != 0) { - DPRINTF("ERROR: adding vbd probe watch %s\n", path); - return -EINVAL; - } - return 0; -} - -/* Asynch callback to check for /local/domain//name */ -static void check_dom(struct xs_handle *h, struct xenbus_watch *w, - const char *bepath_im) -{ - char *domid; - - domid = get_dom_domid(h); - if (domid == NULL) - return; - - add_blockdevice_probe_watch(h, domid); - free(domid); - unregister_xenbus_watch(h, w); -} - -/* We must wait for xend to register /local/domain/ */ -static int watch_for_domid(struct xs_handle *h) -{ - struct xenbus_watch *domid_watch; - char *path = NULL; - - if (asprintf(&path, "/local/domain") == -1) - return -ENOMEM; - - domid_watch = malloc(sizeof(struct xenbus_watch)); - if (domid_watch == NULL) { - DPRINTF("ERROR: unable to malloc domid_watch [%s]\n", path); - return -EINVAL; - } - - domid_watch->node = path; - domid_watch->callback = check_dom; - - if (register_xenbus_watch(h, domid_watch) != 0) { - DPRINTF("ERROR: adding vbd probe watch %s\n", path); - return -EINVAL; - } - - DPRINTF("Set async watch for /local/domain\n"); - - return 0; -} - -int setup_probe_watch(struct xs_handle *h) -{ - char *domid; - int ret; - - domid = get_dom_domid(h); - if (domid == NULL) - return watch_for_domid(h); - - ret = add_blockdevice_probe_watch(h, domid); - free(domid); - return ret; -} diff --git a/tools/blktap/lib/xs_api.c b/tools/blktap/lib/xs_api.c deleted file mode 100644 index 464843239e..0000000000 --- a/tools/blktap/lib/xs_api.c +++ /dev/null @@ -1,360 +0,0 @@ -/* - * xs_api.c - * - * blocktap interface functions to xenstore - * - * (c) 2005 Andrew Warfield and Julian Chesterfield - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation; or, when distributed - * separately from the Linux kernel or incorporated into other - * software packages, subject to the following license: - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this source file (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, modify, - * merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "blktaplib.h" -#include "list.h" -#include "xs_api.h" - -#if 0 -#define DPRINTF(_f, _a...) printf ( _f , ## _a ) -#else -#define DPRINTF(_f, _a...) ((void)0) -#endif - -static LIST_HEAD(watches); -#define BASE_DEV_VAL 2048 - -int xs_gather(struct xs_handle *xs, const char *dir, ...) -{ - va_list ap; - const char *name; - char *path, **e; - int ret = 0, num,i; - unsigned int len; - xs_transaction_t xth; - -again: - if ( (xth = xs_transaction_start(xs)) == XBT_NULL) { - DPRINTF("unable to start xs trasanction\n"); - ret = ENOMEM; - return ret; - } - - va_start(ap, dir); - while ( (ret == 0) && (name = va_arg(ap, char *)) != NULL) { - const char *fmt = va_arg(ap, char *); - void *result = va_arg(ap, void *); - char *p; - - if (asprintf(&path, "%s/%s", dir, name) == -1) - { - printf("allocation error in xs_gather!\n"); - ret = ENOMEM; - break; - } - - p = xs_read(xs, xth, path, &len); - - - free(path); - if (p == NULL) { - ret = ENOENT; - break; - } - if (fmt) { - if (sscanf(p, fmt, result) == 0) - ret = EINVAL; - free(p); - } else - *(char **)result = p; - } - va_end(ap); - - if (!xs_transaction_end(xs, xth, ret)) { - if (ret == 0 && errno == EAGAIN) - goto again; - else - ret = errno; - } - - return ret; -} - - -/* Single printf and write: returns -errno or 0. */ -int xs_printf(struct xs_handle *h, const char *dir, const char *node, - const char *fmt, ...) -{ - char *buf, *path; - va_list ap; - int ret; - - va_start(ap, fmt); - ret = vasprintf(&buf, fmt, ap); - va_end(ap); - - if (ret == -1) - return ENOMEM; - if (asprintf(&path, "%s/%s", dir, node) == -1) { - free(buf); - return ENOMEM; - } - - ret = xs_write(h, XBT_NULL, path, buf, strlen(buf)); - - free(buf); - free(path); - - return ret; -} - - -int xs_exists(struct xs_handle *h, const char *path) -{ - char **d; - unsigned int num; - xs_transaction_t xth; - - if ( (xth = xs_transaction_start(h)) == XBT_NULL) { - printf("unable to start xs trasanction\n"); - return 0; - } - - d = xs_directory(h, xth, path, &num); - xs_transaction_end(h, xth, 0); - if (d == NULL) - return 0; - free(d); - return 1; -} - - - -/** - * This assumes that the domain name we are looking for is unique. - * Name parameter Domain-0 - */ -char *get_dom_domid(struct xs_handle *h) -{ - char **e, *val, *domid = NULL; - unsigned int num, len; - int i; - char *path; - xs_transaction_t xth; - - if ( (xth = xs_transaction_start(h)) == XBT_NULL) { - warn("unable to start xs trasanction\n"); - return NULL; - } - - e = xs_directory(h, xth, "/local/domain", &num); - if (e == NULL) - goto done; - - for (i = 0; (i < num) && (domid == NULL); i++) { - if (asprintf(&path, "/local/domain/%s/name", e[i]) == -1) - break; - val = xs_read(h, xth, path, &len); - free(path); - if (val == NULL) - continue; - - if (strcmp(val, DOMNAME) == 0) { - /* match! */ - if (asprintf(&path, "/local/domain/%s/domid", e[i]) == -1) { - free(val); - break; - } - domid = xs_read(h, xth, path, &len); - free(path); - } - free(val); - } -done: - xs_transaction_end(h, xth, 0); - if (e) - free(e); - return domid; -} - -int convert_dev_name_to_num(char *name) { - char *p, *ptr; - int majors[10] = {3,22,33,34,56,57,88,89,90,91}; - int maj,i,ret = 0; - char *p_sd = "/dev/sd"; - char *p_hd = "/dev/hd"; - char *p_xvd = "/dev/xvd"; - char *p_plx = "plx"; - char *alpha = "abcdefghijklmnop"; - - if (strstr(name, p_sd) != NULL) { - p = name + strlen(p_sd); - for(i = 0, ptr = alpha; i < strlen(alpha); i++) { - if(*ptr == *p) - break; - *ptr++; - } - *p++; - ret = BASE_DEV_VAL + (16*i) + atoi(p); - } else if (strstr(name, p_hd) != NULL) { - p = name + strlen(p_hd); - for (i = 0, ptr = alpha; i < strlen(alpha); i++) { - if(*ptr == *p) break; - *ptr++; - } - *p++; - ret = (majors[i/2]*256) + atoi(p); - - } else if (strstr(name, p_xvd) != NULL) { - p = name + strlen(p_xvd); - for(i = 0, ptr = alpha; i < strlen(alpha); i++) { - if(*ptr == *p) break; - *ptr++; - } - *p++; - ret = (202*256) + (16*i) + atoi(p); - - } else if (strstr(name, p_plx) != NULL) { - p = name + strlen(p_plx); - ret = atoi(p); - - } else { - DPRINTF("Unknown device type, setting to default.\n"); - ret = BASE_DEV_VAL; - } - - return ret; -} - -/** - * A little paranoia: we don't just trust token. - */ -static struct xenbus_watch *find_watch(const char *token) -{ - struct xenbus_watch *i, *cmp; - - cmp = (void *)strtoul(token, NULL, 16); - - list_for_each_entry(i, &watches, list) - if (i == cmp) - return i; - return NULL; -} - -/** - * Register callback to watch this node. - * like xs_watch, return 0 on failure - */ -int register_xenbus_watch(struct xs_handle *h, struct xenbus_watch *watch) -{ - /* Pointer in ascii is the token. */ - char token[sizeof(watch) * 2 + 1]; - - snprintf(token, sizeof(token), "%lX", (long)watch); - if (find_watch(token)) { - DPRINTF("watch collision!\n"); - return -EINVAL; - } - - if (!xs_watch(h, watch->node, token)) { - DPRINTF("unable to set watch!\n"); - return -EINVAL; - } - - list_add(&watch->list, &watches); - - return 0; -} - -int unregister_xenbus_watch(struct xs_handle *h, struct xenbus_watch *watch) -{ - char token[sizeof(watch) * 2 + 1]; - - snprintf(token, sizeof(token), "%lX", (long)watch); - if (!find_watch(token)) { - DPRINTF("no such watch!\n"); - return -EINVAL; - } - - if (!xs_unwatch(h, watch->node, token)) - DPRINTF("XENBUS Failed to release watch %s\n", - watch->node); - - list_del(&watch->list); - - return 0; -} - -/** - * Re-register callbacks to all watches. - */ -void reregister_xenbus_watches(struct xs_handle *h) -{ - struct xenbus_watch *watch; - char token[sizeof(watch) * 2 + 1]; - - list_for_each_entry(watch, &watches, list) { - snprintf(token, sizeof(token), "%lX", (long)watch); - xs_watch(h, watch->node, token); - } -} - -/** - * based on watch_thread() - */ -int xs_fire_next_watch(struct xs_handle *h) -{ - char **res; - char *token; - char *node = NULL; - struct xenbus_watch *w; - int er; - unsigned int num; - - res = xs_read_watch(h, &num); - if (res == NULL) - return -EAGAIN; /* in O_NONBLOCK, read_watch returns 0... */ - - node = res[XS_WATCH_PATH]; - token = res[XS_WATCH_TOKEN]; - - w = find_watch(token); - if (w) - w->callback(h, w, node); - - free(res); - - return 1; -} diff --git a/tools/blktap/lib/xs_api.h b/tools/blktap/lib/xs_api.h deleted file mode 100644 index 34430dcc48..0000000000 --- a/tools/blktap/lib/xs_api.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * xs_api.h - * - * (c) 2005 Andrew Warfield and Julian Chesterfield - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation; or, when distributed - * separately from the Linux kernel or incorporated into other - * software packages, subject to the following license: - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this source file (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, modify, - * merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -struct xenbus_watch -{ - struct list_head list; - char *node; - void (*callback)(struct xs_handle *h, - struct xenbus_watch *, - const char *node); -}; - -int xs_gather(struct xs_handle *xs, const char *dir, ...); -int xs_printf(struct xs_handle *h, const char *dir, const char *node, - const char *fmt, ...); -int xs_exists(struct xs_handle *h, const char *path); -char *get_dom_domid(struct xs_handle *h); -int convert_dev_name_to_num(char *name); -int register_xenbus_watch(struct xs_handle *h, struct xenbus_watch *watch); -int unregister_xenbus_watch(struct xs_handle *h, struct xenbus_watch *watch); -void reregister_xenbus_watches(struct xs_handle *h); -int xs_fire_next_watch(struct xs_handle *h); -- 2.30.2