[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH] tools: remove blktap1
This was disabled by default in Xen 4.4. Since xend has now been removed from the tree I don't believe anything is using it. We need to pass an explicit CONFIG_BLKTAP1=n to qemu-xen-traditional otherwise it defaults to y and doesn't build. Signed-off-by: Ian Campbell <ian.campbell@xxxxxxxxxx> Cc: Konrad Rzeszutek Wilk <konrad.wilk@xxxxxxxxxx> --- I think this has probably missed the boat for 4.5 and there isn't much harm in waiting for 4.6. I'm open to being told otherwise though ;-) --- .gitignore | 5 - .hgignore | 5 - INSTALL | 1 - config/Tools.mk.in | 1 - tools/Makefile | 2 +- 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 - tools/configure | 29 +- tools/configure.ac | 4 +- tools/hotplug/Linux/Makefile | 1 - tools/hotplug/Linux/blktap | 94 -- tools/hotplug/Linux/xen-backend.rules.in | 2 - 41 files changed, 3 insertions(+), 11664 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 delete mode 100644 tools/hotplug/Linux/blktap diff --git a/.gitignore b/.gitignore index b24e905..6830a06 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 da27f80..0bd29a1 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/INSTALL b/INSTALL index 6bb9d23..f0fc6f1 100644 --- a/INSTALL +++ b/INSTALL @@ -149,7 +149,6 @@ this detection and the sysv runlevel scripts have to be used. The old backend drivers are disabled because qdisk is now the default. This option can be used to build them anyway. - --enable-blktap1 --enable-blktap2 Build various stubom components, some are only example code. Its usually diff --git a/config/Tools.mk.in b/config/Tools.mk.in index 89de5bd..30267fa 100644 --- a/config/Tools.mk.in +++ b/config/Tools.mk.in @@ -57,7 +57,6 @@ CONFIG_ROMBIOS := @rombios@ CONFIG_SEABIOS := @seabios@ CONFIG_QEMU_TRAD := @qemu_traditional@ CONFIG_QEMU_XEN := @qemu_xen@ -CONFIG_BLKTAP1 := @blktap1@ CONFIG_BLKTAP2 := @blktap2@ CONFIG_QEMUU_EXTRA_ARGS:= @EXTRA_QEMUU_CONFIGURE_ARGS@ CONFIG_REMUS_NETBUF := @remus_netbuf@ diff --git a/tools/Makefile b/tools/Makefile index af9798a..1ad7a5d 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -16,7 +16,6 @@ SUBDIRS-y += console SUBDIRS-y += xenmon SUBDIRS-y += xenstat SUBDIRS-$(CONFIG_Linux) += memshr -SUBDIRS-$(CONFIG_BLKTAP1) += blktap SUBDIRS-$(CONFIG_BLKTAP2) += blktap2 SUBDIRS-$(CONFIG_NetBSD) += xenbackendd SUBDIRS-y += libfsimage @@ -169,6 +168,7 @@ subdir-all-qemu-xen-traditional-dir: qemu-xen-traditional-dir-find subdir-install-qemu-xen-traditional-dir: qemu-xen-traditional-dir-find set -e; \ $(buildmakevars2shellvars); \ + export CONFIG_BLKTAP1=n; \ cd qemu-xen-traditional-dir; \ $(QEMU_ROOT)/xen-setup \ --extra-cflags="$(EXTRA_CFLAGS_QEMU_TRADITIONAL)" \ diff --git a/tools/blktap/Makefile b/tools/blktap/Makefile deleted file mode 100644 index 4020566..0000000 --- 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 5e41080..0000000 --- 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:<FILENAME>,sda1,w'] - -e.g. for a qcow image: - -disk = ['tap:qcow:<FILENAME>,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 <FILENAME> that would normally be mounted using -the loopback driver (such as 'mount -o loop <FILENAME> /mnt/disk'), do the -following: - -xm block-attach 0 tap:aio:<FILENAME> /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:<FILENAME> /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 7461a95..0000000 --- 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 4d83fac..0000000 --- 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 <vincent.rijmen@xxxxxxxxxxxxxxxxxxx> - * @author Antoon Bosselaers <antoon.bosselaers@xxxxxxxxxxxxxxxxxxx> - * @author Paulo Barreto <paulo.barreto@xxxxxxxxxxxx> - * - * 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 <inttypes.h> -#include <string.h> -#include "aes.h" - -//#define NDEBUG -#include <assert.h> - -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 9fb54a9..0000000 --- a/tools/blktap/drivers/aes.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef QEMU_AES_H -#define QEMU_AES_H - -#include <stdint.h> - -#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 1cdc980..0000000 --- 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 bb52717..0000000 --- a/tools/blktap/drivers/blk_linux.c +++ /dev/null @@ -1,42 +0,0 @@ -#include <inttypes.h> -#include <sys/ioctl.h> -#include <sys/mount.h> -#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 0a8b880..0000000 --- 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 <stdio.h> -#include <stdlib.h> -#include <sys/mman.h> -#include <err.h> -#include <errno.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <signal.h> -#include <fcntl.h> -#include <sys/poll.h> -#include <sys/ioctl.h> -#include <string.h> -#include <unistd.h> -#include <xenstore.h> -#include <sys/time.h> -#include <syslog.h> -#ifdef MEMSHR -#include <memshr.h> -#endif -#include <sys/stat.h> - -#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 4512807..0000000 --- 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 6282fa6..0000000 --- a/tools/blktap/drivers/blktapctrl_linux.c +++ /dev/null @@ -1,89 +0,0 @@ - -#include <stdio.h> -#include <fcntl.h> -#include <sys/stat.h> -#include <sys/ioctl.h> - -#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 98727f4..0000000 --- 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 <errno.h> -#include <libaio.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/statvfs.h> -#include <sys/stat.h> -#include <sys/ioctl.h> -#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 0e4e9cf..0000000 --- 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 <errno.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/statvfs.h> -#include <sys/stat.h> -#include <sys/ioctl.h> -#include <string.h> -#include <zlib.h> -#include <inttypes.h> -#include <libaio.h> -#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 <gcrypt.h> - -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 <openssl/md5.h> - -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 ceda4f0..0000000 --- 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 <zlib.h> -#include "aes.h" -#include <assert.h> -#include <stdint.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/stat.h> - -#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 836a68e..0000000 --- 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 <errno.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <inttypes.h> -#include <unistd.h> -#include <sys/statvfs.h> -#include <sys/stat.h> -#include <sys/ioctl.h> -#include <string.h> -#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<<SECTOR_SHIFT)>>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 dde4538..0000000 --- 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 <errno.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/statvfs.h> -#include <sys/stat.h> -#include <sys/ioctl.h> -#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 4d16965..0000000 --- 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 <errno.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/statvfs.h> -#include <sys/stat.h> -#include <sys/ioctl.h> -#include <string.h> -#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 5578913..0000000 --- a/tools/blktap/drivers/bswap.h +++ /dev/null @@ -1,178 +0,0 @@ -#ifndef BSWAP_H -#define BSWAP_H - -//#include "config-host.h" - -#include <inttypes.h> - -#if defined(__NetBSD__) -#include <sys/endian.h> -#include <sys/types.h> -#elif defined(__OpenBSD__) -#include <machine/endian.h> -#define bswap_16(x) swap16(x) -#define bswap_32(x) swap32(x) -#define bswap_64(x) swap64(x) -#elif defined(__linux__) - -#include <byteswap.h> - -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 6b4fa70..0000000 --- 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 <errno.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/statvfs.h> -#include <sys/stat.h> -#include <sys/ioctl.h> -#include <string.h> -#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 <QCOW FILENAME> <SRC IMAGE>\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<<SECTOR_SHIFT,NULL,0); - - if (ret < 0) { - DFPRINTF("Unable to create QCOW file\n"); - exit(-1); - } else DFPRINTF("Qcow file created: size %llu sectors\n", - (long long unsigned)s->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 25abfcd..0000000 --- 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 <errno.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/statvfs.h> -#include <sys/stat.h> -#include <sys/ioctl.h> -#include <string.h> -#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] <SIZE(MB)> <FILENAME> " - "[<BACKING_FILENAME>]\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 0fa88c1..0000000 --- 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 <errno.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <inttypes.h> -#include <unistd.h> -#include <sys/statvfs.h> -#include <sys/stat.h> -#include <sys/ioctl.h> -#include <string.h> -#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 <Dest File descriptor> " - "<Qcow SRC IMAGE>\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 140c44a..0000000 --- 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 <unistd.h> -#include <errno.h> -#include <string.h> -#include <stdlib.h> - -/** - * 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;i<ctx->max_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 27d3881..0000000 --- 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 <pthread.h> -#include <libaio.h> -#include <stdint.h> - -#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 19cd777..0000000 --- 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 <stdio.h> -#include <stdlib.h> -#include <sys/mman.h> -#include <fcntl.h> -#include <string.h> -#include <signal.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <sys/poll.h> -#include <unistd.h> -#include <errno.h> -#include <pthread.h> -#include <time.h> -#include <err.h> -#include <poll.h> -#include <sys/statvfs.h> -#include <sys/ioctl.h> -#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 <READ fifo> <WRITE fifo>\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<<SECTOR_SHIFT, - (long long unsigned) - sector_nr<<SECTOR_SHIFT, - (long long unsigned) sector_nr); - continue; - } - - blkif->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 f3e165a..0000000 --- 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 <stdint.h> -#include <syslog.h> -#include <stdio.h> -#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 8852c46..0000000 --- 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 9a19596..0000000 --- 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 <stdio.h> -#include <stdlib.h> -#include <errno.h> -#include <string.h> -#include <err.h> -#include <unistd.h> - -#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 a80e518..0000000 --- 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 <xenctrl.h> -#include <sys/param.h> -#include <sys/user.h> -#include <xen/xen.h> -#include <xen/io/blkif.h> -#include <xen/io/ring.h> -#include <xenstore.h> -#include <sys/types.h> -#include <unistd.h> - -#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 c82242f..0000000 --- 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 948eb02..0000000 --- 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 <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <err.h> -#include <stdarg.h> -#include <errno.h> -#include <xenstore.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <poll.h> -#include <time.h> -#include <sys/time.h> -#include <unistd.h> -#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/<DOMID>/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/<DOMID> */ -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 4648432..0000000 --- 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 <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <err.h> -#include <stdarg.h> -#include <errno.h> -#include <xenstore.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <poll.h> -#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 34430dc..0000000 --- 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); diff --git a/tools/configure b/tools/configure index c65ad3a..b1261a1 100755 --- a/tools/configure +++ b/tools/configure @@ -700,7 +700,6 @@ rombios qemu_traditional blktap2 LINUX_BACKEND_MODULES -blktap1 debug seabios ovmf @@ -790,7 +789,6 @@ enable_xsmpolicy enable_ovmf enable_seabios enable_debug -enable_blktap1 with_linux_backend_modules enable_blktap2 enable_qemu_traditional @@ -1463,7 +1461,6 @@ Optional Features: --enable-ovmf Enable OVMF (default is DISABLED) --disable-seabios Disable SeaBIOS (default is ENABLED) --disable-debug Disable debug build of tools (default is ENABLED) - --enable-blktap1 Enable blktap1 tools (default is DISABLED) --enable-blktap2 Enable blktap2, (DEFAULT is on for Linux, otherwise off) --enable-qemu-traditional @@ -3991,29 +3988,6 @@ debug=$ax_cv_debug -# Check whether --enable-blktap1 was given. -if test "${enable_blktap1+set}" = set; then : - enableval=$enable_blktap1; -fi - - -if test "x$enable_blktap1" = "xno"; then : - - ax_cv_blktap1="n" - -elif test "x$enable_blktap1" = "xyes"; then : - - ax_cv_blktap1="y" - -elif test -z $ax_cv_blktap1; then : - - ax_cv_blktap1="n" - -fi -blktap1=$ax_cv_blktap1 - - - # Check whether --with-linux-backend-modules was given. if test "${with_linux_backend_modules+set}" = set; then : @@ -4037,7 +4011,6 @@ usbbk pciback xen-acpi-processor blktap2 -blktap " ;; *) @@ -7935,7 +7908,7 @@ fi -if test "x$enable_blktap1" = "xyes" || test "x$enable_blktap2" = "xyes"; then : +if test "x$enable_blktap2" = "xyes"]; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for io_setup in -laio" >&5 $as_echo_n "checking for io_setup in -laio... " >&6; } diff --git a/tools/configure.ac b/tools/configure.ac index 1ac63a3..72e2465 100644 --- a/tools/configure.ac +++ b/tools/configure.ac @@ -89,7 +89,6 @@ AX_ARG_DEFAULT_ENABLE([xsmpolicy], [Disable XSM policy compilation]) AX_ARG_DEFAULT_DISABLE([ovmf], [Enable OVMF]) AX_ARG_DEFAULT_ENABLE([seabios], [Disable SeaBIOS]) AX_ARG_DEFAULT_ENABLE([debug], [Disable debug build of tools]) -AX_ARG_DEFAULT_DISABLE([blktap1], [Enable blktap1 tools]) AC_ARG_WITH([linux-backend-modules], AS_HELP_STRING([--with-linux-backend-modules="mod1 mod2"], @@ -113,7 +112,6 @@ usbbk pciback xen-acpi-processor blktap2 -blktap " ;; *) @@ -338,7 +336,7 @@ AC_CHECK_HEADER([lzo/lzo1x.h], [ AC_CHECK_LIB([lzo2], [lzo1x_decompress], [zlib="$zlib -DHAVE_LZO1X -llzo2"]) ]) AC_SUBST(zlib) -AS_IF([test "x$enable_blktap1" = "xyes" || test "x$enable_blktap2" = "xyes"], [ +AS_IF(test "x$enable_blktap2" = "xyes"], [ AC_CHECK_LIB([aio], [io_setup], [], [AC_MSG_ERROR([Could not find libaio])]) ]) AC_SUBST(system_aio) diff --git a/tools/hotplug/Linux/Makefile b/tools/hotplug/Linux/Makefile index 1706c05..b8490f9 100644 --- a/tools/hotplug/Linux/Makefile +++ b/tools/hotplug/Linux/Makefile @@ -19,7 +19,6 @@ XEN_SCRIPTS += vif-setup XEN_SCRIPTS-$(CONFIG_REMUS_NETBUF) += remus-netbuf-setup XEN_SCRIPTS += block XEN_SCRIPTS += block-enbd block-nbd -XEN_SCRIPTS-$(CONFIG_BLKTAP1) += blktap XEN_SCRIPTS += xen-hotplug-cleanup XEN_SCRIPTS += external-device-migrate XEN_SCRIPTS += vscsi diff --git a/tools/hotplug/Linux/blktap b/tools/hotplug/Linux/blktap deleted file mode 100644 index cd30a38..0000000 --- a/tools/hotplug/Linux/blktap +++ /dev/null @@ -1,94 +0,0 @@ -#!/bin/bash - -# Copyright (c) 2005, XenSource Ltd. - -dir=$(dirname "$0") -. "$dir/xen-hotplug-common.sh" -. "$dir/block-common.sh" - -findCommand "$@" - -## -# check_blktap_sharing file mode -# -# Perform the sharing check for the given blktap and mode. -# -check_blktap_sharing() -{ - local file="$1" - local mode="$2" - - local base_path="$XENBUS_BASE_PATH/$XENBUS_TYPE" - for dom in $(xenstore-list "$base_path") - do - for dev in $(xenstore-list "$base_path/$dom") - do - params=$(xenstore_read_default "$base_path/$dom/$dev/params" "" | cut -d: -f2) - if [ "$file" = "$params" ] - then - - if [ "$mode" = 'w' ] - then - if ! same_vm "$dom" - then - echo 'guest' - return - fi - else - local m=$(xenstore_read_default "$base_path/$dom/$dev/mode" "") - m=$(canonicalise_mode "$m") - - if [ "$m" = 'w' ] - then - if ! same_vm "$dom" - then - echo 'guest' - return - fi - fi - fi - fi - done - done - - echo 'ok' -} - - -t=$(xenstore_read_default "$XENBUS_PATH/type" 'MISSING') -if [ -n "$t" ] -then - p=$(xenstore_read "$XENBUS_PATH/params") - p=${p#tapdisk:} - # if we have a ':', chew from head including : - if echo $p | grep -q \: - then - p=${p#*:} - fi -fi -# some versions of readlink cannot be passed a regular file -if [ -L "$p" ]; then - file=$(readlink -f "$p") || fatal "$p link does not exist." -else - file="$p" -fi - -if [ "$command" = 'add' ] -then - [ -e "$file" ] || { fatal $file does not exist; } - - FRONTEND_ID=$(xenstore_read "$XENBUS_PATH/frontend-id") - FRONTEND_UUID=$(xenstore_read "/local/domain/$FRONTEND_ID/vm") - mode=$(xenstore_read "$XENBUS_PATH/mode") - mode=$(canonicalise_mode "$mode") - - if [ "$mode" != '!' ] - then - result=$(check_blktap_sharing "$file" "$mode") - [ "$result" = 'ok' ] || ebusy "$file already in use by other domain" - fi - - success -fi - -exit 0 diff --git a/tools/hotplug/Linux/xen-backend.rules.in b/tools/hotplug/Linux/xen-backend.rules.in index 7d2f914..ee107af 100644 --- a/tools/hotplug/Linux/xen-backend.rules.in +++ b/tools/hotplug/Linux/xen-backend.rules.in @@ -1,4 +1,3 @@ -SUBSYSTEM=="xen-backend", KERNEL=="tap*", ENV{UDEV_CALL}="1", RUN+="@XEN_SCRIPT_DIR@/blktap $env{ACTION}" SUBSYSTEM=="xen-backend", KERNEL=="vbd*", ENV{UDEV_CALL}="1", RUN+="@XEN_SCRIPT_DIR@/block $env{ACTION}" SUBSYSTEM=="xen-backend", KERNEL=="vif2-*", RUN+="@XEN_SCRIPT_DIR@/vif2 $env{ACTION}" SUBSYSTEM=="xen-backend", KERNEL=="vif-*", ENV{UDEV_CALL}="1", ACTION=="online", RUN+="@XEN_SCRIPT_DIR@/vif-setup online type_if=vif" @@ -6,7 +5,6 @@ SUBSYSTEM=="xen-backend", KERNEL=="vif-*", ENV{UDEV_CALL}="1", ACTION=="offline" SUBSYSTEM=="xen-backend", KERNEL=="vscsi*", RUN+="@XEN_SCRIPT_DIR@/vscsi $env{ACTION}" SUBSYSTEM=="xen-backend", ACTION=="remove", ENV{UDEV_CALL}="1", RUN+="@XEN_SCRIPT_DIR@/xen-hotplug-cleanup" KERNEL=="evtchn", NAME="xen/%k" -SUBSYSTEM=="xen", KERNEL=="blktap[0-9]*", NAME="xen/%k", MODE="0600" SUBSYSTEM=="blktap2", KERNEL=="blktap[0-9]*", NAME="xen/blktap-2/%k", MODE="0600" KERNEL=="blktap-control", NAME="xen/blktap-2/control", MODE="0600" KERNEL=="gntdev", NAME="xen/%k", MODE="0600" -- 1.7.10.4 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |