debuggers.hg

changeset 30:62cf917432fa sync with ovm216/ovm22

Refresh to unstable c/s 19745
author Mukesh Rathor
date Wed Jun 17 17:24:56 2009 -0700 (2009-06-17)
parents 955d83a212d2
children 9cc44b0b31a2
files .hgignore COPYING Config.mk Makefile README buildconfigs/mk.linux-2.6-pvops config/StdGNU.mk config/SunOS.mk docs/ChangeLog docs/man/xend-config.sxp.pod.5 docs/misc/xsm-flask.txt extras/mini-os/COPYING extras/mini-os/arch/ia64/time.c extras/mini-os/arch/x86/x86_64.S extras/mini-os/blkfront.c extras/mini-os/fbfront.c extras/mini-os/include/posix/strings.h extras/mini-os/include/posix/unistd.h extras/mini-os/include/xenbus.h extras/mini-os/lib/string.c extras/mini-os/lib/sys.c extras/mini-os/main.c extras/mini-os/netfront.c extras/mini-os/pcifront.c extras/mini-os/xenbus/xenbus.c stubdom/Makefile stubdom/README stubdom/caml/Makefile stubdom/ocaml.patch stubdom/stubdom-dm tools/Makefile tools/blktap/drivers/blktapctrl.c tools/blktap/drivers/block-qcow.c tools/blktap2/Makefile tools/blktap2/README tools/blktap2/daemon/Makefile tools/blktap2/daemon/lib/Makefile tools/blktap2/daemon/lib/xs_api.c tools/blktap2/daemon/lib/xs_api.h tools/blktap2/daemon/tapdisk-channel.c tools/blktap2/daemon/tapdisk-daemon.c tools/blktap2/daemon/tapdisk-dispatch-common.c tools/blktap2/daemon/tapdisk-dispatch.h tools/blktap2/drivers/Makefile tools/blktap2/drivers/aes.c tools/blktap2/drivers/aes.h tools/blktap2/drivers/atomicio.c tools/blktap2/drivers/blk.h tools/blktap2/drivers/blk_linux.c tools/blktap2/drivers/blktap2.h tools/blktap2/drivers/block-aio.c tools/blktap2/drivers/block-cache.c tools/blktap2/drivers/block-log.c tools/blktap2/drivers/block-qcow.c tools/blktap2/drivers/block-ram.c tools/blktap2/drivers/block-vhd.c tools/blktap2/drivers/bswap.h tools/blktap2/drivers/check_gcrypt tools/blktap2/drivers/disktypes.h tools/blktap2/drivers/img2qcow.c tools/blktap2/drivers/io-optimize.c tools/blktap2/drivers/io-optimize.h tools/blktap2/drivers/lock.c tools/blktap2/drivers/lock.h tools/blktap2/drivers/log.h tools/blktap2/drivers/profile.h tools/blktap2/drivers/qcow-create.c tools/blktap2/drivers/qcow.h tools/blktap2/drivers/qcow2raw.c tools/blktap2/drivers/scheduler.c tools/blktap2/drivers/scheduler.h tools/blktap2/drivers/tapdisk-client.c tools/blktap2/drivers/tapdisk-diff.c tools/blktap2/drivers/tapdisk-driver.c tools/blktap2/drivers/tapdisk-driver.h tools/blktap2/drivers/tapdisk-filter.c tools/blktap2/drivers/tapdisk-filter.h tools/blktap2/drivers/tapdisk-image.c tools/blktap2/drivers/tapdisk-image.h tools/blktap2/drivers/tapdisk-interface.c tools/blktap2/drivers/tapdisk-interface.h tools/blktap2/drivers/tapdisk-ipc.c tools/blktap2/drivers/tapdisk-ipc.h tools/blktap2/drivers/tapdisk-log.c tools/blktap2/drivers/tapdisk-log.h tools/blktap2/drivers/tapdisk-queue.c tools/blktap2/drivers/tapdisk-queue.h tools/blktap2/drivers/tapdisk-ring.c tools/blktap2/drivers/tapdisk-ring.h tools/blktap2/drivers/tapdisk-server.c tools/blktap2/drivers/tapdisk-server.h tools/blktap2/drivers/tapdisk-stream.c tools/blktap2/drivers/tapdisk-utils.c tools/blktap2/drivers/tapdisk-utils.h tools/blktap2/drivers/tapdisk-vbd.c tools/blktap2/drivers/tapdisk-vbd.h tools/blktap2/drivers/tapdisk.c tools/blktap2/drivers/tapdisk.h tools/blktap2/drivers/tapdisk2.c tools/blktap2/drivers/td.c tools/blktap2/drivers/xmsnap tools/blktap2/include/Makefile tools/blktap2/include/atomicio.h tools/blktap2/include/blktaplib.h tools/blktap2/include/libvhd-journal.h tools/blktap2/include/libvhd.h tools/blktap2/include/list.h tools/blktap2/include/lvm-util.h tools/blktap2/include/relative-path.h tools/blktap2/include/tapdisk-message.h tools/blktap2/include/vhd-util.h tools/blktap2/include/vhd.h tools/blktap2/lvm/Makefile tools/blktap2/lvm/lvm-util.c tools/blktap2/vhd/Makefile tools/blktap2/vhd/lib/Makefile tools/blktap2/vhd/lib/atomicio.c tools/blktap2/vhd/lib/libvhd-journal.c tools/blktap2/vhd/lib/libvhd.c tools/blktap2/vhd/lib/relative-path.c tools/blktap2/vhd/lib/vhd-util-check.c tools/blktap2/vhd/lib/vhd-util-coalesce.c tools/blktap2/vhd/lib/vhd-util-create.c tools/blktap2/vhd/lib/vhd-util-fill.c tools/blktap2/vhd/lib/vhd-util-modify.c tools/blktap2/vhd/lib/vhd-util-query.c tools/blktap2/vhd/lib/vhd-util-read.c tools/blktap2/vhd/lib/vhd-util-repair.c tools/blktap2/vhd/lib/vhd-util-resize.c tools/blktap2/vhd/lib/vhd-util-revert.c tools/blktap2/vhd/lib/vhd-util-scan.c tools/blktap2/vhd/lib/vhd-util-set-field.c tools/blktap2/vhd/lib/vhd-util-snapshot.c tools/blktap2/vhd/vhd-update.c tools/blktap2/vhd/vhd-util.c tools/check/check_uuid_devel tools/examples/Makefile tools/examples/xend-config.sxp tools/examples/xmexample.hvm-dm tools/examples/xmexample.hvm-stubdom tools/firmware/hvmloader/hvmloader.c tools/firmware/rombios/rombios.c tools/flask/policy/Makefile tools/hotplug/Linux/Makefile tools/hotplug/Linux/block tools/hotplug/Linux/block-common.sh tools/hotplug/Linux/vif-common.sh tools/hotplug/Linux/xen-backend.rules tools/hotplug/NetBSD/Makefile tools/hotplug/common/Makefile tools/include/xen-foreign/Makefile tools/libxc/Makefile tools/libxc/ia64/xc_ia64_linux_restore.c tools/libxc/xc_core.h tools/libxc/xc_core_x86.c tools/libxc/xc_dom.h tools/libxc/xc_dom_boot.c tools/libxc/xc_dom_compat_linux.c tools/libxc/xc_dom_ia64.c tools/libxc/xc_dom_x86.c tools/libxc/xc_domain_restore.c tools/libxc/xc_domain_save.c tools/libxc/xc_linux.c tools/libxc/xc_minios.c tools/libxc/xc_netbsd.c tools/libxc/xc_offline_page.c tools/libxc/xc_solaris.c tools/libxc/xc_suspend.c tools/libxc/xc_tmem.c tools/libxc/xenctrl.h tools/libxc/xenguest.h tools/misc/Makefile tools/misc/xen-tmem-list-parse.c tools/pygrub/Makefile tools/python/Makefile tools/python/xen/lowlevel/xc/xc.c tools/python/xen/util/acmpolicy.py tools/python/xen/util/auxbin.py tools/python/xen/util/pci.py tools/python/xen/util/xsm/acm/acm.py tools/python/xen/web/connection.py tools/python/xen/xend/XendAPI.py tools/python/xen/xend/XendCheckpoint.py tools/python/xen/xend/XendConfig.py tools/python/xen/xend/XendConstants.py tools/python/xen/xend/XendDPCI.py tools/python/xen/xend/XendDomain.py tools/python/xen/xend/XendDomainInfo.py tools/python/xen/xend/XendNode.py tools/python/xen/xend/XendOptions.py tools/python/xen/xend/XendPIF.py tools/python/xen/xend/balloon.py tools/python/xen/xend/image.py tools/python/xen/xend/osdep.py tools/python/xen/xend/server/BlktapController.py tools/python/xen/xend/server/DevConstants.py tools/python/xen/xend/server/DevController.py tools/python/xen/xend/server/XMLRPCServer.py tools/python/xen/xend/server/blkif.py tools/python/xen/xend/server/pciif.py tools/python/xen/xend/server/pciquirk.py tools/python/xen/xm/addlabel.py tools/python/xen/xm/create.dtd tools/python/xen/xm/create.py tools/python/xen/xm/getlabel.py tools/python/xen/xm/main.py tools/python/xen/xm/rmlabel.py tools/python/xen/xm/tests/test_create.py tools/python/xen/xm/xenapi_create.py tools/security/Makefile tools/vnet/examples/Makefile tools/xcutils/xc_restore.c tools/xenstore/Makefile tools/xenstore/xs.h tools/xentrace/formats tools/xentrace/xentrace_format unmodified_drivers/linux-2.6/compat-include/xen/platform-compat.h xen/Makefile xen/arch/ia64/linux-xen/acpi.c xen/arch/ia64/linux-xen/iosapic.c xen/arch/ia64/linux-xen/mca.c xen/arch/ia64/linux-xen/perfmon.c xen/arch/ia64/linux-xen/smp.c xen/arch/ia64/linux-xen/smpboot.c xen/arch/ia64/linux-xen/sn/kernel/sn2_smp.c xen/arch/ia64/vmx/vmmu.c xen/arch/ia64/vmx/vtlb.c xen/arch/ia64/xen/cpufreq/cpufreq.c xen/arch/ia64/xen/flushtlb.c xen/arch/ia64/xen/fw_emul.c xen/arch/ia64/xen/mm.c xen/arch/ia64/xen/vhpt.c xen/arch/x86/acpi/boot.c xen/arch/x86/acpi/cpu_idle.c xen/arch/x86/acpi/cpufreq/cpufreq.c xen/arch/x86/acpi/cpufreq/powernow.c xen/arch/x86/acpi/cpuidle_menu.c xen/arch/x86/apic.c xen/arch/x86/cpu/amd.c xen/arch/x86/cpu/mcheck/amd_nonfatal.c xen/arch/x86/cpu/mcheck/mce.c xen/arch/x86/cpu/mcheck/mce.h xen/arch/x86/cpu/mcheck/mce_intel.c xen/arch/x86/cpu/mcheck/non-fatal.c xen/arch/x86/cpu/mcheck/x86_mca.h xen/arch/x86/cpu/mtrr/main.c xen/arch/x86/crash.c xen/arch/x86/domain.c xen/arch/x86/domain_build.c xen/arch/x86/e820.c xen/arch/x86/genapic/x2apic.c xen/arch/x86/hpet.c xen/arch/x86/hvm/emulate.c xen/arch/x86/hvm/hvm.c xen/arch/x86/hvm/irq.c xen/arch/x86/hvm/mtrr.c xen/arch/x86/hvm/svm/svm.c xen/arch/x86/hvm/svm/vmcb.c xen/arch/x86/hvm/viridian.c xen/arch/x86/hvm/vlapic.c xen/arch/x86/hvm/vmx/vmcs.c xen/arch/x86/hvm/vmx/vmx.c xen/arch/x86/i8259.c xen/arch/x86/io_apic.c xen/arch/x86/ioport_emulate.c xen/arch/x86/irq.c xen/arch/x86/machine_kexec.c xen/arch/x86/mm.c xen/arch/x86/mm/hap/hap.c xen/arch/x86/mm/p2m.c xen/arch/x86/mm/paging.c xen/arch/x86/mm/shadow/common.c xen/arch/x86/mm/shadow/multi.c xen/arch/x86/mm/shadow/private.h xen/arch/x86/msi.c xen/arch/x86/numa.c xen/arch/x86/oprofile/nmi_int.c xen/arch/x86/pci.c xen/arch/x86/physdev.c xen/arch/x86/platform_hypercall.c xen/arch/x86/setup.c xen/arch/x86/shutdown.c xen/arch/x86/smp.c xen/arch/x86/srat.c xen/arch/x86/tboot.c xen/arch/x86/time.c xen/arch/x86/traps.c xen/arch/x86/x86_32/Makefile xen/arch/x86/x86_32/pci.c xen/arch/x86/x86_32/supervisor_mode_kernel.S xen/arch/x86/x86_32/traps.c xen/arch/x86/x86_64/Makefile xen/arch/x86/x86_64/acpi_mmcfg.c xen/arch/x86/x86_64/mmconfig-shared.c xen/arch/x86/x86_64/mmconfig.h xen/arch/x86/x86_64/mmconfig_64.c xen/arch/x86/x86_64/pci.c xen/arch/x86/x86_emulate/x86_emulate.c xen/common/Makefile xen/common/compat/Makefile xen/common/compat/tmem_xen.c xen/common/cpu.c xen/common/domain.c xen/common/domctl.c xen/common/event_channel.c xen/common/gdbstub.c xen/common/grant_table.c xen/common/keyhandler.c xen/common/lzo.c xen/common/memory.c xen/common/page_alloc.c xen/common/radix-tree.c xen/common/rbtree.c xen/common/spinlock.c xen/common/tmem.c xen/common/tmem_xen.c xen/common/xmalloc_tlsf.c xen/drivers/acpi/numa.c xen/drivers/cpufreq/cpufreq_ondemand.c xen/drivers/passthrough/amd/iommu_intr.c xen/drivers/passthrough/io.c xen/drivers/passthrough/pci.c xen/drivers/passthrough/vtd/dmar.c xen/drivers/passthrough/vtd/dmar.h xen/drivers/passthrough/vtd/extern.h xen/drivers/passthrough/vtd/ia64/Makefile xen/drivers/passthrough/vtd/ia64/ats.c xen/drivers/passthrough/vtd/intremap.c xen/drivers/passthrough/vtd/iommu.c xen/drivers/passthrough/vtd/iommu.h xen/drivers/passthrough/vtd/qinval.c xen/drivers/passthrough/vtd/utils.c xen/drivers/passthrough/vtd/x86/Makefile xen/drivers/passthrough/vtd/x86/ats.c xen/drivers/passthrough/vtd/x86/vtd.c xen/include/Makefile xen/include/asm-ia64/linux-xen/asm/iosapic.h xen/include/asm-ia64/linux-xen/asm/numa.h xen/include/asm-ia64/linux-xen/asm/perfmon_default_smpl.h xen/include/asm-ia64/linux-xen/asm/smp.h xen/include/asm-ia64/linux-xen/asm/spinlock.h xen/include/asm-ia64/linux-xen/linux/efi.h xen/include/asm-ia64/mm.h xen/include/asm-ia64/tlbflush.h xen/include/asm-x86/acpi.h xen/include/asm-x86/config.h xen/include/asm-x86/domain.h xen/include/asm-x86/e820.h xen/include/asm-x86/flushtlb.h xen/include/asm-x86/genapic.h xen/include/asm-x86/hap.h xen/include/asm-x86/hvm/domain.h xen/include/asm-x86/hvm/svm/svm.h xen/include/asm-x86/hvm/svm/vmcb.h xen/include/asm-x86/hvm/vcpu.h xen/include/asm-x86/hvm/vmx/vmcs.h xen/include/asm-x86/hvm/vmx/vmx.h xen/include/asm-x86/io_apic.h xen/include/asm-x86/ipi.h xen/include/asm-x86/irq.h xen/include/asm-x86/mach-default/smpboot_hooks.h xen/include/asm-x86/mm.h xen/include/asm-x86/msr-index.h xen/include/asm-x86/numa.h xen/include/asm-x86/paging.h xen/include/asm-x86/perfc_defn.h xen/include/asm-x86/smp.h xen/include/asm-x86/spinlock.h xen/include/public/arch-x86/hvm/save.h xen/include/public/io/blkif.h xen/include/public/tmem.h xen/include/public/trace.h xen/include/public/xen.h xen/include/xen/acpi.h xen/include/xen/compiler.h xen/include/xen/config.h xen/include/xen/cpumask.h xen/include/xen/grant_table.h xen/include/xen/hash.h xen/include/xen/hvm/irq.h xen/include/xen/hypercall.h xen/include/xen/iommu.h xen/include/xen/irq.h xen/include/xen/lib.h xen/include/xen/lzo.h xen/include/xen/mm.h xen/include/xen/pci.h xen/include/xen/pci_regs.h xen/include/xen/radix-tree.h xen/include/xen/rbtree.h xen/include/xen/sched.h xen/include/xen/smp.h xen/include/xen/softirq.h xen/include/xen/spinlock.h xen/include/xen/tmem.h xen/include/xen/tmem_xen.h xen/include/xen/xmalloc.h xen/include/xlat.lst xen/kdb/include/kdbinc.h xen/kdb/kdb_cmds.c xen/kdb/kdbmain.c
line diff
     1.1 --- a/.hgignore	Tue Jun 16 17:03:31 2009 -0700
     1.2 +++ b/.hgignore	Wed Jun 17 17:24:56 2009 -0700
     1.3 @@ -90,6 +90,7 @@
     1.4  ^stubdom/gcc-.*$
     1.5  ^stubdom/include$
     1.6  ^stubdom/ioemu$
     1.7 +^stubdom/xenstore$
     1.8  ^stubdom/libxc-.*$
     1.9  ^stubdom/lwip-.*$
    1.10  ^stubdom/mini-os-.*$
    1.11 @@ -98,10 +99,23 @@
    1.12  ^stubdom/pciutils-.*$
    1.13  ^stubdom/zlib-.*$
    1.14  ^stubdom/grub-.*$
    1.15 +^stubdom/ocaml-.*$
    1.16  ^stubdom/lwip/
    1.17  ^stubdom/ioemu/
    1.18  ^tools/.*/build/lib.*/.*\.py$
    1.19 -^tools/blktap/Makefile\.smh$
    1.20 +^tools/blktap2/daemon/blktapctrl$
    1.21 +^tools/blktap2/drivers/img2qcow$
    1.22 +^tools/blktap2/drivers/lock-util$
    1.23 +^tools/blktap2/drivers/qcow-create$
    1.24 +^tools/blktap2/drivers/qcow2raw$
    1.25 +^tools/blktap2/drivers/tapdisk$
    1.26 +^tools/blktap2/drivers/tapdisk-client$
    1.27 +^tools/blktap2/drivers/tapdisk-diff$
    1.28 +^tools/blktap2/drivers/tapdisk-stream$
    1.29 +^tools/blktap2/drivers/tapdisk2$
    1.30 +^tools/blktap2/drivers/td-util$
    1.31 +^tools/blktap2/vhd/vhd-update$
    1.32 +^tools/blktap2/vhd/vhd-util$
    1.33  ^tools/blktap/drivers/blktapctrl$
    1.34  ^tools/blktap/drivers/img2qcow$
    1.35  ^tools/blktap/drivers/qcow-create$
    1.36 @@ -183,10 +197,12 @@
    1.37  ^tools/misc/xc_shadow$
    1.38  ^tools/misc/xen_cpuperf$
    1.39  ^tools/misc/xen-detect$
    1.40 +^tools/misc/xen-tmem-list-parse$
    1.41  ^tools/misc/xenperf$
    1.42  ^tools/misc/xenpm$
    1.43  ^tools/pygrub/build/.*$
    1.44  ^tools/python/build/.*$
    1.45 +^tools/python/xen/util/path\.py$
    1.46  ^tools/security/secpol_tool$
    1.47  ^tools/security/xen/.*$
    1.48  ^tools/security/xensec_tool$
    1.49 @@ -254,6 +270,7 @@
    1.50  ^tools/xm-test/tests/.*\.test$
    1.51  ^tools/ioemu-remote
    1.52  ^tools/ioemu-dir$
    1.53 +^tools/ocaml-xenstored.*$
    1.54  ^xen/\.banner.*$
    1.55  ^xen/BLOG$
    1.56  ^xen/System.map$
     2.1 --- a/COPYING	Tue Jun 16 17:03:31 2009 -0700
     2.2 +++ b/COPYING	Wed Jun 17 17:24:56 2009 -0700
     2.3 @@ -17,12 +17,13 @@ Xen guests, certain files in this reposi
     2.4  GPL when distributed separately or included in software packages
     2.5  outside this repository. Instead we specify a much more relaxed
     2.6  BSD-style license. Affected files include the Xen interface headers
     2.7 -(xen/include/public/COPYING), and various drivers, support functions
     2.8 -and header files within the Linux source trees on
     2.9 -http://xenbits.xensource.com/linux-2.6.X-xen.hg. In all such cases,
    2.10 -license terms are stated at the top of the file or in a COPYING file
    2.11 -in the same directory. Note that _any_ file that is modified and then
    2.12 -distributed within a Linux kernel is still subject to the GNU GPL.
    2.13 +(xen/include/public/COPYING), MiniOS (extras/mini-os) and various
    2.14 +drivers, support functions and header files within the Linux source
    2.15 +trees on http://xenbits.xensource.com/linux-2.6.X-xen.hg.
    2.16 +In all such cases, license terms are stated at the top of the file or in
    2.17 +a COPYING file in the same directory. Note that _any_ file that is
    2.18 +modified and then distributed within a Linux kernel is still subject to
    2.19 +the GNU GPL.
    2.20  
    2.21   -- Keir Fraser (on behalf of the Xen team)
    2.22  
     3.1 --- a/Config.mk	Tue Jun 16 17:03:31 2009 -0700
     3.2 +++ b/Config.mk	Wed Jun 17 17:24:56 2009 -0700
     3.3 @@ -35,6 +35,12 @@ EXTRA_INCLUDES += $(EXTRA_PREFIX)/includ
     3.4  EXTRA_LIB += $(EXTRA_PREFIX)/$(LIBLEAFDIR)
     3.5  endif
     3.6  
     3.7 +PYTHON      ?= python
     3.8 +PYTHON_PREFIX_ARG ?= --prefix="$(PREFIX)"
     3.9 +# The above requires that PREFIX contains *no spaces*. This variable is here
    3.10 +# to permit the user to set PYTHON_PREFIX_ARG to '' to workaround this bug:
    3.11 +#  https://bugs.launchpad.net/ubuntu/+bug/362570
    3.12 +
    3.13  # cc-option: Check if compiler supports first option, else fall back to second.
    3.14  # Usage: cflags-y += $(call cc-option,$(CC),-march=winchip-c6,-march=i586)
    3.15  cc-option = $(shell if test -z "`$(1) $(2) -S -o /dev/null -xc \
    3.16 @@ -126,6 +132,16 @@ QEMU_REMOTE=http://xenbits.xensource.com
    3.17  # CONFIG_QEMU ?= ../qemu-xen.git
    3.18  CONFIG_QEMU ?= $(QEMU_REMOTE)
    3.19  
    3.20 +QEMU_TAG ?= e0bb6b8df60863bca0163a1688baf4854e931e55
    3.21 +# Mon Jun 8 17:45:42 2009 +0100
    3.22 +# stdvga + videoram config option
    3.23 +
    3.24 +OCAML_XENSTORED_REPO=http://xenbits.xensource.com/ext/xen-ocaml-tools.hg
    3.25 +
    3.26 +# Build OCAML version of xenstored instead of the in-tree C version?
    3.27 +# This will cause $(OCAML_XENSTORED_REPO) to be cloned.
    3.28 +CONFIG_OCAML_XENSTORED ?= n
    3.29 +
    3.30  # Optional components
    3.31  XENSTAT_XENTOP     ?= y
    3.32  VTPM_TOOLS         ?= n
     4.1 --- a/Makefile	Tue Jun 16 17:03:31 2009 -0700
     4.2 +++ b/Makefile	Wed Jun 17 17:24:56 2009 -0700
     4.3 @@ -194,37 +194,37 @@ help:
     4.4  .PHONY: uninstall
     4.5  uninstall: D=$(DESTDIR)
     4.6  uninstall:
     4.7 -	[ -d $(D)/etc/xen ] && mv -f $(D)/etc/xen $(D)/etc/xen.old-`date +%s` || true
     4.8 -	rm -rf $(D)/etc/init.d/xend*
     4.9 -	rm -rf $(D)/etc/hotplug/xen-backend.agent
    4.10 -	rm -f  $(D)/etc/udev/rules.d/xen-backend.rules
    4.11 -	rm -f  $(D)/etc/udev/xen-backend.rules
    4.12 -	rm -f  $(D)/etc/udev/rules.d/xend.rules
    4.13 -	rm -f  $(D)/etc/udev/xend.rules
    4.14 -	rm -f  $(D)/etc/sysconfig/xendomains
    4.15 +	[ -d $(D)$(XEN_CONFIG_DIR) ] && mv -f $(D)$(XEN_CONFIG_DIR) $(D)$(XEN_CONFIG_DIR).old-`date +%s` || true
    4.16 +	rm -rf $(D)$(CONFIG_DIR)/init.d/xend*
    4.17 +	rm -rf $(D)$(CONFIG_DIR)/hotplug/xen-backend.agent
    4.18 +	rm -f  $(D)$(CONFIG_DIR)/udev/rules.d/xen-backend.rules
    4.19 +	rm -f  $(D)$(CONFIG_DIR)/udev/xen-backend.rules
    4.20 +	rm -f  $(D)$(CONFIG_DIR)/udev/rules.d/xend.rules
    4.21 +	rm -f  $(D)$(CONFIG_DIR)/udev/xend.rules
    4.22 +	rm -f  $(D)$(CONFIG_DIR)/sysconfig/xendomains
    4.23  	rm -rf $(D)/var/run/xen* $(D)/var/lib/xen*
    4.24  	rm -rf $(D)/boot/*xen*
    4.25  	rm -rf $(D)/lib/modules/*xen*
    4.26 -	rm -rf $(D)/usr/bin/xen* $(D)/usr/bin/lomount
    4.27 -	rm -rf $(D)/usr/bin/cpuperf-perfcntr $(D)/usr/bin/cpuperf-xen
    4.28 -	rm -rf $(D)/usr/bin/xc_shadow
    4.29 -	rm -rf $(D)/usr/bin/pygrub
    4.30 -	rm -rf $(D)/usr/bin/setsize $(D)/usr/bin/tbctl
    4.31 -	rm -rf $(D)/usr/bin/xsls
    4.32 -	rm -rf $(D)/usr/include/xenctrl.h $(D)/usr/include/xenguest.h
    4.33 -	rm -rf $(D)/usr/include/xs_lib.h $(D)/usr/include/xs.h
    4.34 -	rm -rf $(D)/usr/include/xen
    4.35 +	rm -rf $(D)$(LIBDIR)/xen* $(D)$(BINDIR)/lomount
    4.36 +	rm -rf $(D)$(BINDIR)/cpuperf-perfcntr $(D)$(BINDIR)/cpuperf-xen
    4.37 +	rm -rf $(D)$(BINDIR)/xc_shadow
    4.38 +	rm -rf $(D)$(BINDIR)/pygrub
    4.39 +	rm -rf $(D)$(BINDIR)/setsize $(D)$(BINDIR)/tbctl
    4.40 +	rm -rf $(D)$(BINDIR)/xsls
    4.41 +	rm -rf $(D)$(INCLUDEDIR)/xenctrl.h $(D)$(INCLUDEDIR)/xenguest.h
    4.42 +	rm -rf $(D)$(INCLUDEDIR)/xs_lib.h $(D)$(INCLUDEDIR)/xs.h
    4.43 +	rm -rf $(D)$(INCLUDEDIR)/xen
    4.44  	rm -rf $(D)$(LIBDIR)/libxenctrl* $(D)$(LIBDIR)/libxenguest*
    4.45  	rm -rf $(D)$(LIBDIR)/libxenstore*
    4.46  	rm -rf $(D)$(LIBDIR)/python/xen $(D)$(LIBDIR)/python/grub
    4.47  	rm -rf $(D)$(LIBDIR)/xen/
    4.48 -	rm -rf $(D)/usr/lib/xen/
    4.49 -	rm -rf $(D)/usr/local/sbin/setmask $(D)/usr/local/sbin/xen*
    4.50 -	rm -rf $(D)/usr/sbin/xen* $(D)/usr/sbin/netfix $(D)/usr/sbin/xm
    4.51 -	rm -rf $(D)/usr/share/doc/xen
    4.52 -	rm -rf $(D)/usr/share/xen
    4.53 -	rm -rf $(D)/usr/share/man/man1/xen*
    4.54 -	rm -rf $(D)/usr/share/man/man8/xen*
    4.55 +	rm -rf $(D)$(LIBEXEC)/xen*
    4.56 +	rm -rf $(D)$(SBINDIR)/setmask
    4.57 +	rm -rf $(D)$(SBINDIR)/xen* $(D)$(SBINDIR)/netfix $(D)$(SBINDIR)/xm
    4.58 +	rm -rf $(D)$(SHAREDIR)/doc/xen
    4.59 +	rm -rf $(D)$(SHAREDIR)/xen
    4.60 +	rm -rf $(D)$(MAN1DIR)/xen*
    4.61 +	rm -rf $(D)$(MAN8DIR)/xen*
    4.62  	rm -rf $(D)/boot/tboot*
    4.63  
    4.64  # Legacy targets for compatibility
     5.1 --- a/README	Tue Jun 16 17:03:31 2009 -0700
     5.2 +++ b/README	Wed Jun 17 17:24:56 2009 -0700
     5.3 @@ -1,9 +1,9 @@
     5.4  #################################
     5.5 - __  __            _____  _____  
     5.6 - \ \/ /___ _ __   |___ / |___ /  
     5.7 -  \  // _ \ '_ \    |_ \   |_ \  
     5.8 -  /  \  __/ | | |  ___) | ___) | 
     5.9 - /_/\_\___|_| |_| |____(_)____/  
    5.10 + __  __            _____ _  _   
    5.11 + \ \/ /___ _ __   |___ /| || |  
    5.12 +  \  // _ \ '_ \    |_ \| || |_ 
    5.13 +  /  \  __/ | | |  ___) |__   _|
    5.14 + /_/\_\___|_| |_| |____(_) |_|  
    5.15                                   
    5.16  #################################
    5.17  
    5.18 @@ -21,7 +21,7 @@ development community, spearheaded by Xe
    5.19  by the original Xen development team to build enterprise products
    5.20  around Xen.
    5.21  
    5.22 -The 3.3 release offers excellent performance, hardware support and
    5.23 +The 3.4 release offers excellent performance, hardware support and
    5.24  enterprise-grade features such as x86_32-PAE, x86_64, SMP guests and
    5.25  live relocation of VMs. Ports to Linux 2.6, Linux 2.4, NetBSD, FreeBSD
    5.26  and Solaris are available from the community.
    5.27 @@ -54,8 +54,8 @@ 2. Configure your bootloader to boot Xen
    5.28     /boot/grub/menu.lst: edit this file to include an entry like the
    5.29     following:
    5.30  
    5.31 -    title Xen 3.3 / XenLinux 2.6
    5.32 -       kernel /boot/xen-3.3.gz console=vga
    5.33 +    title Xen 3.4 / XenLinux 2.6
    5.34 +       kernel /boot/xen-3.4.gz console=vga
    5.35         module /boot/vmlinuz-2.6-xen root=<root-dev> ro console=tty0
    5.36         module /boot/initrd-2.6-xen.img
    5.37  
    5.38 @@ -74,7 +74,7 @@ 2. Configure your bootloader to boot Xen
    5.39     32MB memory for internal use, which is not available for allocation
    5.40     to virtual machines.
    5.41  
    5.42 -3. Reboot your system and select the "Xen 3.3 / XenLinux 2.6" menu
    5.43 +3. Reboot your system and select the "Xen 3.4 / XenLinux 2.6" menu
    5.44     option. After booting Xen, Linux will start and your initialisation
    5.45     scripts should execute in the usual way.
    5.46  
     6.1 --- a/buildconfigs/mk.linux-2.6-pvops	Tue Jun 16 17:03:31 2009 -0700
     6.2 +++ b/buildconfigs/mk.linux-2.6-pvops	Wed Jun 17 17:24:56 2009 -0700
     6.3 @@ -7,7 +7,7 @@ XEN_LINUX_CONFIG_UPDATE := buildconfigs/
     6.4  
     6.5  XEN_LINUX_GIT_URL ?= git://git.kernel.org/pub/scm/linux/kernel/git/jeremy/xen.git
     6.6  XEN_LINUX_GIT_REMOTENAME ?= xen
     6.7 -XEN_LINUX_GIT_REMOTEBRANCH ?= xen/dom0/hackery
     6.8 +XEN_LINUX_GIT_REMOTEBRANCH ?= xen-tip/master
     6.9  
    6.10  EXTRAVERSION ?=
    6.11  
     7.1 --- a/config/StdGNU.mk	Tue Jun 16 17:03:31 2009 -0700
     7.2 +++ b/config/StdGNU.mk	Wed Jun 17 17:24:56 2009 -0700
     7.3 @@ -40,6 +40,14 @@ SBINDIR = $(PREFIX)/sbin
     7.4  PRIVATE_PREFIX = $(LIBDIR)/xen
     7.5  PRIVATE_BINDIR = $(PRIVATE_PREFIX)/bin
     7.6  
     7.7 +ifeq ($(PREFIX),/usr)
     7.8 +CONFIG_DIR = /etc
     7.9 +else
    7.10 +CONFIG_DIR = $(PREFIX)/etc
    7.11 +endif
    7.12 +XEN_CONFIG_DIR = $(CONFIG_DIR)/xen
    7.13 +XEN_SCRIPT_DIR = $(XEN_CONFIG_DIR)/scripts
    7.14 +
    7.15  SOCKET_LIBS =
    7.16  CURSES_LIBS = -lncurses
    7.17  PTHREAD_LIBS = -lpthread
     8.1 --- a/config/SunOS.mk	Tue Jun 16 17:03:31 2009 -0700
     8.2 +++ b/config/SunOS.mk	Wed Jun 17 17:24:56 2009 -0700
     8.3 @@ -34,6 +34,14 @@ SBINDIR = $(PREFIX)/sbin
     8.4  PRIVATE_PREFIX = $(LIBDIR)/xen
     8.5  PRIVATE_BINDIR = $(PRIVATE_PREFIX)/bin
     8.6  
     8.7 +ifeq ($(PREFIX),/usr)
     8.8 +CONFIG_DIR = /etc
     8.9 +else
    8.10 +CONFIG_DIR = $(PREFIX)/etc
    8.11 +endif
    8.12 +XEN_CONFIG_DIR = $(CONFIG_DIR)/xen
    8.13 +XEN_SCRIPT_DIR = $(PRIVATE_PREFIX)/scripts
    8.14 +
    8.15  SunOS_LIBDIR = /usr/sfw/lib
    8.16  SunOS_LIBDIR_x86_64 = /usr/sfw/lib/amd64
    8.17  
     9.1 --- a/docs/ChangeLog	Tue Jun 16 17:03:31 2009 -0700
     9.2 +++ b/docs/ChangeLog	Wed Jun 17 17:24:56 2009 -0700
     9.3 @@ -13,6 +13,11 @@ Add a ChangeLog file indicating changes 
     9.4  here:
     9.5  http://lists.xensource.com/archives/html/xen-devel/2008-01/msg00010.html
     9.6  
     9.7 +Xen 3.4 release (and later)
     9.8 +---------------------------
     9.9 +
    9.10 +This file not updated.
    9.11 +
    9.12  Xen 3.3 release
    9.13  ---------------
    9.14  
    10.1 --- a/docs/man/xend-config.sxp.pod.5	Tue Jun 16 17:03:31 2009 -0700
    10.2 +++ b/docs/man/xend-config.sxp.pod.5	Wed Jun 17 17:24:56 2009 -0700
    10.3 @@ -115,6 +115,16 @@ The name of an application or script tha
    10.4  migration, such as for example virtual TPM migration. An example
    10.5  script is I</etc/xen/scripts/external-device-migrate>.
    10.6  
    10.7 +=item I<device-create-timeout>
    10.8 +
    10.9 +Integer value that tells xend how long it should wait for a new device
   10.10 +to be created. Defaults to I<100>.
   10.11 +
   10.12 +=item I<device-destroy-timeout>
   10.13 +
   10.14 +Integer value that tells xend how long it should wait for a device to
   10.15 +be destroyed. Defaults to I<100>.
   10.16 +
   10.17  =back
   10.18  
   10.19  =head1 EXAMPLES
    11.1 --- a/docs/misc/xsm-flask.txt	Tue Jun 16 17:03:31 2009 -0700
    11.2 +++ b/docs/misc/xsm-flask.txt	Wed Jun 17 17:24:56 2009 -0700
    11.3 @@ -1,4 +1,4 @@
    11.4 -These notes are compiled from xen-devel questions and postings that have occured
    11.5 +These notes are compiled from xen-devel questions and postings that have occurred
    11.6  since the inclusion of XSM.  These notes are not intended to be definitive
    11.7  documentation but should address many common problems that arrise when
    11.8  experimenting with XSM:FLASK.
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/extras/mini-os/COPYING	Wed Jun 17 17:24:56 2009 -0700
    12.3 @@ -0,0 +1,23 @@
    12.4 +Copyright (c) 2009 Citrix Systems, Inc. All rights reserved.
    12.5 +
    12.6 +Redistribution and use in source and binary forms, with or without
    12.7 +modification, are permitted provided that the following conditions
    12.8 +are met:
    12.9 +1. Redistributions of source code must retain the above copyright
   12.10 +   notice, this list of conditions and the following disclaimer.
   12.11 +2. Redistributions in binary form must reproduce the above copyright
   12.12 +   notice, this list of conditions and the following disclaimer in the
   12.13 +   documentation and/or other materials provided with the distribution.
   12.14 +
   12.15 +THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   12.16 +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   12.17 +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   12.18 +ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
   12.19 +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   12.20 +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   12.21 +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   12.22 +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   12.23 +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   12.24 +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   12.25 +SUCH DAMAGE.
   12.26 +
    13.1 --- a/extras/mini-os/arch/ia64/time.c	Tue Jun 16 17:03:31 2009 -0700
    13.2 +++ b/extras/mini-os/arch/ia64/time.c	Wed Jun 17 17:24:56 2009 -0700
    13.3 @@ -1,26 +1,9 @@
    13.4  /* 
    13.5   * Done by Dietmar Hahn <dietmar.hahn@fujitsu-siemens.com>
    13.6   * Description: simple ia64 specific time handling
    13.7 - * mktime() is taken from Linux (see copyright below)
    13.8   * Parts are taken from FreeBSD.
    13.9   *
   13.10   ****************************************************************************
   13.11 - * For the copy of the mktime() from linux.
   13.12 - * This program is free software; you can redistribute it and/or modify
   13.13 - * it under the terms of the GNU General Public License as published by
   13.14 - * the Free Software Foundation; either version 2 of the License, or
   13.15 - * (at your option) any later version.
   13.16 - *
   13.17 - * This program is distributed in the hope that it will be useful,
   13.18 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   13.19 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   13.20 - * GNU General Public License for more details.
   13.21 - *
   13.22 - * You should have received a copy of the GNU General Public License
   13.23 - * along with this program; if not, write to the Free Software
   13.24 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   13.25 - *
   13.26 - ****************************************************************************
   13.27   *
   13.28   * Redistribution and use in source and binary forms, with or without
   13.29   * modification, are permitted provided that the following conditions
   13.30 @@ -57,45 +40,73 @@ static uint64_t itc_frequency;
   13.31  static uint64_t processor_frequency;
   13.32  static uint64_t itm_val;
   13.33  
   13.34 +static int is_leap_year(int year)
   13.35 +{
   13.36 +	if( year % 4 == 0 )
   13.37 +	{
   13.38 +		if( year % 100 == 0 )
   13.39 +		{
   13.40 +			if( year % 400 == 0 ) return 1;
   13.41 +			else return 0;
   13.42 +		}
   13.43 +		return 1;
   13.44 +	}
   13.45 +	return 0;
   13.46 +}
   13.47 +
   13.48 +static int count_leap_years(int epoch, int year)
   13.49 +{
   13.50 +	int i, result = 0;
   13.51 +	for( i = epoch ; i < year ; i++ ) if( is_leap_year(i) ) result++;
   13.52 +	return result;
   13.53 +}
   13.54 +
   13.55 +static int get_day(int year, int mon, int day) {
   13.56 +	int result;
   13.57 +	switch(mon)
   13.58 +	{
   13.59 +		case 0: result = 0; break;
   13.60 +		case 1: result = 31; break; /* 1: 31 */
   13.61 +		case 2: result = 59; break; /* 2: 31+28 */
   13.62 +		case 3: result = 90; break; /* 3: 59+31 */
   13.63 +		case 4: result = 120;break; /* 4: 90+30 */
   13.64 +		case 5: result = 151;break; /* 5: 120+31 */
   13.65 +		case 6: result = 181;break; /* 6: 151+30 */
   13.66 +		case 7: result = 212;break; /* 7: 181+31 */
   13.67 +		case 8: result = 243;break; /* 8: 212+31 */
   13.68 +		case 9: result = 273;break; /* 9: 243+30 */
   13.69 +		case 10:result = 304;break; /* 10:273+31 */
   13.70 +		case 11:result = 334;break; /* 11:304+30 */
   13.71 +		default: break;
   13.72 +	}
   13.73 +	if( is_leap_year(year) && mon > 2 ) result++;
   13.74 +	result += day - 1;
   13.75 +	return result;
   13.76 +}
   13.77  
   13.78  /*
   13.79 - * mktime() is take from Linux. See copyright above.
   13.80   * Converts Gregorian date to seconds since 1970-01-01 00:00:00.
   13.81   * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
   13.82   * => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
   13.83   *
   13.84 - * [For the Julian calendar (which was used in Russia before 1917,
   13.85 - * Britain & colonies before 1752, anywhere else before 1582,
   13.86 - * and is still in use by some communities) leave out the
   13.87 - * -year/100+year/400 terms, and add 10.]
   13.88 - *
   13.89 - * This algorithm was first published by Gauss (I think).
   13.90 - *
   13.91   * WARNING: this function will overflow on 2106-02-07 06:28:16 on
   13.92   * machines were long is 32-bit! (However, as time_t is signed, we
   13.93   * will already get problems at other places on 2038-01-19 03:14:08)
   13.94   */
   13.95 -static unsigned long
   13.96 -_mktime(const unsigned int year0, const unsigned int mon0,
   13.97 -       const unsigned int day, const unsigned int hour,
   13.98 -       const unsigned int min, const unsigned int sec)
   13.99 +static unsigned long _mktime(const unsigned int year, const unsigned int mon,
  13.100 +			    const unsigned int day, const unsigned int hour,
  13.101 +		            const unsigned int min, const unsigned int sec)
  13.102  {
  13.103 -	unsigned int mon = mon0, year = year0;
  13.104 +	unsigned long result = 0;
  13.105  
  13.106 -	/* 1..12 -> 11,12,1..10 */
  13.107 -	if (0 >= (int) (mon -= 2)) {
  13.108 -		mon += 12;	/* Puts Feb last since it has leap day */
  13.109 -		year -= 1;
  13.110 -	}
  13.111 +	result = sec;
  13.112 +	result += min * 60;
  13.113 +	result += hour * 3600;
  13.114 +	result += get_day(year, mon - 1, day) * 86400;
  13.115 +	result += (year - 1970) * 31536000;
  13.116 +	result += count_leap_years(1970, year) * 86400;
  13.117  
  13.118 -	return (
  13.119 -		(
  13.120 -		 ((unsigned long)
  13.121 -		  (year/4 - year/100 + year/400 + 367*mon/12 + day) +
  13.122 -		   year*365 - 719499
  13.123 -		 ) * 24 + hour /* now have hours */
  13.124 -		) * 60 + min /* now have minutes */
  13.125 -	       ) * 60 + sec; /* finally seconds */
  13.126 +	return result;
  13.127  }
  13.128  
  13.129  static inline uint64_t
    14.1 --- a/extras/mini-os/arch/x86/x86_64.S	Tue Jun 16 17:03:31 2009 -0700
    14.2 +++ b/extras/mini-os/arch/x86/x86_64.S	Wed Jun 17 17:24:56 2009 -0700
    14.3 @@ -46,88 +46,21 @@ NMI_MASK = 0x80000000
    14.4  #define ORIG_RAX 120       /* + error_code */ 
    14.5  #define EFLAGS 144
    14.6  
    14.7 -#define REST_SKIP 6*8			
    14.8 -.macro SAVE_REST
    14.9 -	subq $REST_SKIP,%rsp
   14.10 -#	CFI_ADJUST_CFA_OFFSET	REST_SKIP
   14.11 -	movq %rbx,5*8(%rsp) 
   14.12 -#	CFI_REL_OFFSET	rbx,5*8
   14.13 -	movq %rbp,4*8(%rsp) 
   14.14 -#	CFI_REL_OFFSET	rbp,4*8
   14.15 -	movq %r12,3*8(%rsp) 
   14.16 -#	CFI_REL_OFFSET	r12,3*8
   14.17 -	movq %r13,2*8(%rsp) 
   14.18 -#	CFI_REL_OFFSET	r13,2*8
   14.19 -	movq %r14,1*8(%rsp) 
   14.20 -#	CFI_REL_OFFSET	r14,1*8
   14.21 -	movq %r15,(%rsp) 
   14.22 -#	CFI_REL_OFFSET	r15,0*8
   14.23 -.endm		
   14.24 -
   14.25 -
   14.26 -.macro RESTORE_REST
   14.27 -	movq (%rsp),%r15
   14.28 -#	CFI_RESTORE r15
   14.29 -	movq 1*8(%rsp),%r14
   14.30 -#	CFI_RESTORE r14
   14.31 -	movq 2*8(%rsp),%r13
   14.32 -#	CFI_RESTORE r13
   14.33 -	movq 3*8(%rsp),%r12
   14.34 -#	CFI_RESTORE r12
   14.35 -	movq 4*8(%rsp),%rbp
   14.36 -#	CFI_RESTORE rbp
   14.37 -	movq 5*8(%rsp),%rbx
   14.38 -#	CFI_RESTORE rbx
   14.39 -	addq $REST_SKIP,%rsp
   14.40 -#	CFI_ADJUST_CFA_OFFSET	-(REST_SKIP)
   14.41 -.endm
   14.42 -
   14.43 -
   14.44 -#define ARG_SKIP 9*8
   14.45 -.macro RESTORE_ARGS skiprax=0,addskip=0,skiprcx=0,skipr11=0,skipr8910=0,skiprdx=0
   14.46 -	.if \skipr11
   14.47 -	.else
   14.48 +.macro RESTORE_ALL
   14.49  	movq (%rsp),%r11
   14.50 -#	CFI_RESTORE r11
   14.51 -	.endif
   14.52 -	.if \skipr8910
   14.53 -	.else
   14.54  	movq 1*8(%rsp),%r10
   14.55 -#	CFI_RESTORE r10
   14.56  	movq 2*8(%rsp),%r9
   14.57 -#	CFI_RESTORE r9
   14.58  	movq 3*8(%rsp),%r8
   14.59 -#	CFI_RESTORE r8
   14.60 -	.endif
   14.61 -	.if \skiprax
   14.62 -	.else
   14.63  	movq 4*8(%rsp),%rax
   14.64 -#	CFI_RESTORE rax
   14.65 -	.endif
   14.66 -	.if \skiprcx
   14.67 -	.else
   14.68  	movq 5*8(%rsp),%rcx
   14.69 -#	CFI_RESTORE rcx
   14.70 -	.endif
   14.71 -	.if \skiprdx
   14.72 -	.else
   14.73  	movq 6*8(%rsp),%rdx
   14.74 -#	CFI_RESTORE rdx
   14.75 -	.endif
   14.76  	movq 7*8(%rsp),%rsi
   14.77 -#	CFI_RESTORE rsi
   14.78  	movq 8*8(%rsp),%rdi
   14.79 -#	CFI_RESTORE rdi
   14.80 -	.if ARG_SKIP+\addskip > 0
   14.81 -	addq $ARG_SKIP+\addskip,%rsp
   14.82 -#	CFI_ADJUST_CFA_OFFSET	-(ARG_SKIP+\addskip)
   14.83 -	.endif
   14.84 +	addq $9*8+8,%rsp
   14.85  .endm	
   14.86  
   14.87  
   14.88  .macro HYPERVISOR_IRET flag
   14.89 -#    testb $3,1*8(%rsp)    /* Don't need to do that in Mini-os, as */
   14.90 -#	jnz   2f               /* there is no userspace? */
   14.91  	testl $NMI_MASK,2*8(%rsp)
   14.92  	jnz   2f
   14.93  
   14.94 @@ -150,44 +83,25 @@ 2:	/* Slow iret via hypervisor. */
   14.95   * and the exception handler in %rax.	
   14.96   */ 		  				
   14.97  ENTRY(error_entry)
   14.98 -#	_frame RDI
   14.99  	/* rdi slot contains rax, oldrax contains error code */
  14.100  	cld	
  14.101  	subq  $14*8,%rsp
  14.102 -#	CFI_ADJUST_CFA_OFFSET	(14*8)
  14.103  	movq %rsi,13*8(%rsp)
  14.104 -#	CFI_REL_OFFSET	rsi,RSI
  14.105  	movq 14*8(%rsp),%rsi	/* load rax from rdi slot */
  14.106  	movq %rdx,12*8(%rsp)
  14.107 -#	CFI_REL_OFFSET	rdx,RDX
  14.108  	movq %rcx,11*8(%rsp)
  14.109 -#	CFI_REL_OFFSET	rcx,RCX
  14.110  	movq %rsi,10*8(%rsp)	/* store rax */ 
  14.111 -#	CFI_REL_OFFSET	rax,RAX
  14.112  	movq %r8, 9*8(%rsp)
  14.113 -#	CFI_REL_OFFSET	r8,R8
  14.114  	movq %r9, 8*8(%rsp)
  14.115 -#	CFI_REL_OFFSET	r9,R9
  14.116  	movq %r10,7*8(%rsp)
  14.117 -#	CFI_REL_OFFSET	r10,R10
  14.118  	movq %r11,6*8(%rsp)
  14.119 -#	CFI_REL_OFFSET	r11,R11
  14.120  	movq %rbx,5*8(%rsp) 
  14.121 -#	CFI_REL_OFFSET	rbx,RBX
  14.122  	movq %rbp,4*8(%rsp) 
  14.123 -#	CFI_REL_OFFSET	rbp,RBP
  14.124  	movq %r12,3*8(%rsp) 
  14.125 -#	CFI_REL_OFFSET	r12,R12
  14.126  	movq %r13,2*8(%rsp) 
  14.127 -#	CFI_REL_OFFSET	r13,R13
  14.128  	movq %r14,1*8(%rsp) 
  14.129 -#	CFI_REL_OFFSET	r14,R14
  14.130  	movq %r15,(%rsp) 
  14.131 -#	CFI_REL_OFFSET	r15,R15
  14.132 -#if 0        
  14.133 -	cmpl $__KERNEL_CS,CS(%rsp)
  14.134 -	je  error_kernelspace
  14.135 -#endif        
  14.136 +
  14.137  error_call_handler:
  14.138  	movq %rdi, RDI(%rsp)            
  14.139  	movq %rsp,%rdi
  14.140 @@ -197,29 +111,22 @@ error_call_handler:
  14.141  	jmp error_exit
  14.142  
  14.143  .macro zeroentry sym
  14.144 -#	INTR_FRAME
  14.145      movq (%rsp),%rcx
  14.146      movq 8(%rsp),%r11
  14.147      addq $0x10,%rsp /* skip rcx and r11 */
  14.148  	pushq $0	/* push error code/oldrax */ 
  14.149 -#	CFI_ADJUST_CFA_OFFSET 8
  14.150  	pushq %rax	/* push real oldrax to the rdi slot */ 
  14.151 -#	CFI_ADJUST_CFA_OFFSET 8
  14.152  	leaq  \sym(%rip),%rax
  14.153  	jmp error_entry
  14.154 -#	CFI_ENDPROC
  14.155  .endm	
  14.156  
  14.157  .macro errorentry sym
  14.158 -#	XCPT_FRAME
  14.159          movq (%rsp),%rcx
  14.160          movq 8(%rsp),%r11
  14.161          addq $0x10,%rsp /* rsp points to the error code */
  14.162  	pushq %rax
  14.163 -#	CFI_ADJUST_CFA_OFFSET 8
  14.164  	leaq  \sym(%rip),%rax
  14.165  	jmp error_entry
  14.166 -#	CFI_ENDPROC
  14.167  .endm
  14.168  
  14.169  #define XEN_GET_VCPU_INFO(reg)	movq HYPERVISOR_shared_info,reg
  14.170 @@ -253,7 +160,6 @@ 11:     movq %gs:8,%rax
  14.171          decl %gs:0
  14.172          jmp error_exit
  14.173  
  14.174 -#        ALIGN
  14.175  restore_all_enable_events:  
  14.176  	XEN_UNBLOCK_EVENTS(%rsi)        # %rsi is already set up...
  14.177  
  14.178 @@ -261,12 +167,18 @@ scrit:	/**** START OF CRITICAL REGION **
  14.179  	XEN_TEST_PENDING(%rsi)
  14.180  	jnz  14f			# process more events if necessary...
  14.181  	XEN_PUT_VCPU_INFO(%rsi)
  14.182 -        RESTORE_ARGS 0,8,0
  14.183 +        RESTORE_ALL
  14.184          HYPERVISOR_IRET 0
  14.185          
  14.186  14:	XEN_LOCKED_BLOCK_EVENTS(%rsi)
  14.187  	XEN_PUT_VCPU_INFO(%rsi)
  14.188 -	SAVE_REST
  14.189 +	subq $6*8,%rsp
  14.190 +	movq %rbx,5*8(%rsp) 
  14.191 +	movq %rbp,4*8(%rsp) 
  14.192 +	movq %r12,3*8(%rsp) 
  14.193 +	movq %r13,2*8(%rsp) 
  14.194 +	movq %r14,1*8(%rsp) 
  14.195 +	movq %r15,(%rsp) 
  14.196          movq %rsp,%rdi                  # set the argument again
  14.197  	jmp  11b
  14.198  ecrit:  /**** END OF CRITICAL REGION ****/
  14.199 @@ -274,7 +186,7 @@ ecrit:  /**** END OF CRITICAL REGION ***
  14.200  
  14.201  retint_kernel:
  14.202  retint_restore_args:
  14.203 -	movl EFLAGS-REST_SKIP(%rsp), %eax
  14.204 +	movl EFLAGS-6*8(%rsp), %eax
  14.205  	shr $9, %eax			# EAX[0] == IRET_EFLAGS.IF
  14.206  	XEN_GET_VCPU_INFO(%rsi)
  14.207  	andb evtchn_upcall_mask(%rsi),%al
  14.208 @@ -282,13 +194,18 @@ retint_restore_args:
  14.209  	jnz restore_all_enable_events	#        != 0 => enable event delivery
  14.210  	XEN_PUT_VCPU_INFO(%rsi)
  14.211  		
  14.212 -	RESTORE_ARGS 0,8,0
  14.213 +	RESTORE_ALL
  14.214  	HYPERVISOR_IRET 0
  14.215  
  14.216  
  14.217  error_exit:		
  14.218 -	RESTORE_REST
  14.219 -/*	cli */
  14.220 +	movq (%rsp),%r15
  14.221 +	movq 1*8(%rsp),%r14
  14.222 +	movq 2*8(%rsp),%r13
  14.223 +	movq 3*8(%rsp),%r12
  14.224 +	movq 4*8(%rsp),%rbp
  14.225 +	movq 5*8(%rsp),%rbx
  14.226 +	addq $6*8,%rsp
  14.227  	XEN_BLOCK_EVENTS(%rsi)		
  14.228  	jmp retint_kernel
  14.229  
  14.230 @@ -313,17 +230,11 @@ ENTRY(device_not_available)
  14.231  
  14.232  
  14.233  ENTRY(debug)
  14.234 -#       INTR_FRAME
  14.235 -#       CFI_ADJUST_CFA_OFFSET 8 */
  14.236          zeroentry do_debug
  14.237 -#       CFI_ENDPROC
  14.238  
  14.239  
  14.240  ENTRY(int3)
  14.241 -#       INTR_FRAME
  14.242 -#       CFI_ADJUST_CFA_OFFSET 8 */
  14.243          zeroentry do_int3
  14.244 -#       CFI_ENDPROC
  14.245  
  14.246  ENTRY(overflow)
  14.247          zeroentry do_overflow
  14.248 @@ -351,9 +262,7 @@ ENTRY(segment_not_present)
  14.249  
  14.250  /* runs on exception stack */
  14.251  ENTRY(stack_segment)
  14.252 -#       XCPT_FRAME
  14.253          errorentry do_stack_segment
  14.254 -#       CFI_ENDPROC
  14.255                      
  14.256  
  14.257  ENTRY(general_protection)
    15.1 --- a/extras/mini-os/blkfront.c	Tue Jun 16 17:03:31 2009 -0700
    15.2 +++ b/extras/mini-os/blkfront.c	Wed Jun 17 17:24:56 2009 -0700
    15.3 @@ -149,8 +149,12 @@ again:
    15.4          goto abort_transaction;
    15.5      }
    15.6  
    15.7 -    err = xenbus_printf(xbt, nodename, "state", "%u",
    15.8 -            4); /* connected */
    15.9 +    snprintf(path, sizeof(path), "%s/state", nodename);
   15.10 +    err = xenbus_switch_state(xbt, path, XenbusStateConnected);
   15.11 +    if (err) {
   15.12 +        message = "switching state";
   15.13 +        goto abort_transaction;
   15.14 +    }
   15.15  
   15.16  
   15.17      err = xenbus_transaction_end(xbt, 0, &retry);
   15.18 @@ -179,6 +183,7 @@ done:
   15.19      dev->handle = strtoul(strrchr(nodename, '/')+1, NULL, 0);
   15.20  
   15.21      {
   15.22 +        XenbusState state;
   15.23          char path[strlen(dev->backend) + 1 + 19 + 1];
   15.24          snprintf(path, sizeof(path), "%s/mode", dev->backend);
   15.25          msg = xenbus_read(XBT_NIL, path, &c);
   15.26 @@ -196,7 +201,15 @@ done:
   15.27  
   15.28          xenbus_watch_path_token(XBT_NIL, path, path, &dev->events);
   15.29  
   15.30 -        xenbus_wait_for_value(path, "4", &dev->events);
   15.31 +        msg = NULL;
   15.32 +        state = xenbus_read_integer(path);
   15.33 +        while (msg == NULL && state < XenbusStateConnected)
   15.34 +            msg = xenbus_wait_for_state_change(path, &state, &dev->events);
   15.35 +        if (msg != NULL || state != XenbusStateConnected) {
   15.36 +            printk("backend not available, state=%d\n", state);
   15.37 +            xenbus_unwatch_path(XBT_NIL, path);
   15.38 +            goto error;
   15.39 +        }
   15.40  
   15.41          snprintf(path, sizeof(path), "%s/info", dev->backend);
   15.42          dev->info.info = xenbus_read_integer(path);
   15.43 @@ -230,21 +243,48 @@ error:
   15.44  
   15.45  void shutdown_blkfront(struct blkfront_dev *dev)
   15.46  {
   15.47 -    char* err;
   15.48 -    char *nodename = dev->nodename;
   15.49 +    char* err = NULL;
   15.50 +    XenbusState state;
   15.51  
   15.52      char path[strlen(dev->backend) + 1 + 5 + 1];
   15.53 +    char nodename[strlen(dev->nodename) + 1 + 5 + 1];
   15.54  
   15.55      blkfront_sync(dev);
   15.56  
   15.57 -    printk("close blk: backend at %s\n",dev->backend);
   15.58 +    printk("close blk: backend=%s node=%s\n", dev->backend, dev->nodename);
   15.59  
   15.60      snprintf(path, sizeof(path), "%s/state", dev->backend);
   15.61 -    err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 5); /* closing */
   15.62 -    xenbus_wait_for_value(path, "5", &dev->events);
   15.63 +    snprintf(nodename, sizeof(nodename), "%s/state", dev->nodename);
   15.64 +
   15.65 +    if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosing)) != NULL) {
   15.66 +        printk("shutdown_blkfront: error changing state to %d: %s\n",
   15.67 +                XenbusStateClosing, err);
   15.68 +        goto close;
   15.69 +    }
   15.70 +    state = xenbus_read_integer(path);
   15.71 +    while (err == NULL && state < XenbusStateClosing)
   15.72 +        err = xenbus_wait_for_state_change(path, &state, &dev->events);
   15.73  
   15.74 -    err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 6);
   15.75 +    if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosed)) != NULL) {
   15.76 +        printk("shutdown_blkfront: error changing state to %d: %s\n",
   15.77 +                XenbusStateClosed, err);
   15.78 +        goto close;
   15.79 +    }
   15.80 +    state = xenbus_read_integer(path);
   15.81 +    if (state < XenbusStateClosed)
   15.82 +        xenbus_wait_for_state_change(path, &state, &dev->events);
   15.83  
   15.84 +    if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateInitialising)) != NULL) {
   15.85 +        printk("shutdown_blkfront: error changing state to %d: %s\n",
   15.86 +                XenbusStateInitialising, err);
   15.87 +        goto close;
   15.88 +    }
   15.89 +    err = NULL;
   15.90 +    state = xenbus_read_integer(path);
   15.91 +    while (err == NULL && (state < XenbusStateInitWait || state >= XenbusStateClosed))
   15.92 +        err = xenbus_wait_for_state_change(path, &state, &dev->events);
   15.93 +
   15.94 +close:
   15.95      xenbus_unwatch_path(XBT_NIL, path);
   15.96  
   15.97      snprintf(path, sizeof(path), "%s/ring-ref", nodename);
   15.98 @@ -310,14 +350,14 @@ void blkfront_aio(struct blkfront_aiocb 
   15.99      req->nr_segments = n;
  15.100      req->handle = dev->handle;
  15.101      req->id = (uintptr_t) aiocbp;
  15.102 -    req->sector_number = aiocbp->aio_offset / dev->info.sector_size;
  15.103 +    req->sector_number = aiocbp->aio_offset / 512;
  15.104  
  15.105      for (j = 0; j < n; j++) {
  15.106          req->seg[j].first_sect = 0;
  15.107 -        req->seg[j].last_sect = PAGE_SIZE / dev->info.sector_size - 1;
  15.108 +        req->seg[j].last_sect = PAGE_SIZE / 512 - 1;
  15.109      }
  15.110 -    req->seg[0].first_sect = ((uintptr_t)aiocbp->aio_buf & ~PAGE_MASK) / dev->info.sector_size;
  15.111 -    req->seg[n-1].last_sect = (((uintptr_t)aiocbp->aio_buf + aiocbp->aio_nbytes - 1) & ~PAGE_MASK) / dev->info.sector_size;
  15.112 +    req->seg[0].first_sect = ((uintptr_t)aiocbp->aio_buf & ~PAGE_MASK) / 512;
  15.113 +    req->seg[n-1].last_sect = (((uintptr_t)aiocbp->aio_buf + aiocbp->aio_nbytes - 1) & ~PAGE_MASK) / 512;
  15.114      for (j = 0; j < n; j++) {
  15.115  	uintptr_t data = start + j * PAGE_SIZE;
  15.116          if (!write) {
    16.1 --- a/extras/mini-os/fbfront.c	Tue Jun 16 17:03:31 2009 -0700
    16.2 +++ b/extras/mini-os/fbfront.c	Wed Jun 17 17:24:56 2009 -0700
    16.3 @@ -121,7 +121,8 @@ again:
    16.4          }
    16.5      }
    16.6  
    16.7 -    err = xenbus_printf(xbt, nodename, "state", "%u", 3); /* initialized */
    16.8 +    snprintf(path, sizeof(path), "%s/state", nodename);
    16.9 +    err = xenbus_switch_state(xbt, path, XenbusStateInitialised);
   16.10      if (err)
   16.11          printk("error writing initialized: %s\n", err);
   16.12  
   16.13 @@ -150,17 +151,33 @@ done:
   16.14      printk("backend at %s\n", dev->backend);
   16.15  
   16.16      {
   16.17 +        XenbusState state;
   16.18          char path[strlen(dev->backend) + 1 + 6 + 1];
   16.19 +        char frontpath[strlen(nodename) + 1 + 6 + 1];
   16.20  
   16.21          snprintf(path, sizeof(path), "%s/state", dev->backend);
   16.22  
   16.23          xenbus_watch_path_token(XBT_NIL, path, path, &dev->events);
   16.24  
   16.25 -        xenbus_wait_for_value(path, "4", &dev->events);
   16.26 +        err = NULL;
   16.27 +        state = xenbus_read_integer(path);
   16.28 +        while (err == NULL && state < XenbusStateConnected)
   16.29 +            err = xenbus_wait_for_state_change(path, &state, &dev->events);
   16.30 +        if (state != XenbusStateConnected) {
   16.31 +            printk("backend not available, state=%d\n", state);
   16.32 +            xenbus_unwatch_path(XBT_NIL, path);
   16.33 +            goto error;
   16.34 +        }
   16.35  
   16.36          printk("%s connected\n", dev->backend);
   16.37  
   16.38 -        err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 4); /* connected */
   16.39 +        snprintf(frontpath, sizeof(frontpath), "%s/state", nodename);
   16.40 +        if((err = xenbus_switch_state(XBT_NIL, frontpath, XenbusStateConnected))
   16.41 +            != NULL) {
   16.42 +            printk("error switching state: %s\n", err);
   16.43 +            xenbus_unwatch_path(XBT_NIL, path);
   16.44 +            goto error;
   16.45 +        }
   16.46      }
   16.47      unmask_evtchn(dev->evtchn);
   16.48  
   16.49 @@ -211,24 +228,43 @@ int kbdfront_receive(struct kbdfront_dev
   16.50  
   16.51  void shutdown_kbdfront(struct kbdfront_dev *dev)
   16.52  {
   16.53 -    char* err;
   16.54 -    char *nodename = dev->nodename;
   16.55 +    char* err = NULL;
   16.56 +    XenbusState state;
   16.57  
   16.58      char path[strlen(dev->backend) + 1 + 5 + 1];
   16.59 +    char nodename[strlen(dev->nodename) + 1 + 5 + 1];
   16.60  
   16.61      printk("close kbd: backend at %s\n",dev->backend);
   16.62  
   16.63      snprintf(path, sizeof(path), "%s/state", dev->backend);
   16.64 -    err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 5); /* closing */
   16.65 -    xenbus_wait_for_value(path, "5", &dev->events);
   16.66 +    snprintf(nodename, sizeof(nodename), "%s/state", dev->nodename);
   16.67 +    if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosing)) != NULL) {
   16.68 +        printk("shutdown_kbdfront: error changing state to %d: %s\n",
   16.69 +                XenbusStateClosing, err);
   16.70 +        goto close_kbdfront;
   16.71 +    }
   16.72 +    state = xenbus_read_integer(path);
   16.73 +    while (err == NULL && state < XenbusStateClosing)
   16.74 +        err = xenbus_wait_for_state_change(path, &state, &dev->events);
   16.75  
   16.76 -    err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 6);
   16.77 -    xenbus_wait_for_value(path, "6", &dev->events);
   16.78 +    if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosed)) != NULL) {
   16.79 +        printk("shutdown_kbdfront: error changing state to %d: %s\n",
   16.80 +                XenbusStateClosed, err);
   16.81 +        goto close_kbdfront;
   16.82 +    }
   16.83 +    state = xenbus_read_integer(path);
   16.84 +    if (state < XenbusStateClosed)
   16.85 +        xenbus_wait_for_state_change(path, &state, &dev->events);
   16.86  
   16.87 -    err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 1);
   16.88 +    if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateInitialising)) != NULL) {
   16.89 +        printk("shutdown_kbdfront: error changing state to %d: %s\n",
   16.90 +                XenbusStateInitialising, err);
   16.91 +        goto close_kbdfront;
   16.92 +    }
   16.93      // does not work yet.
   16.94      //xenbus_wait_for_value(path, "2", &dev->events);
   16.95  
   16.96 +close_kbdfront:
   16.97      xenbus_unwatch_path(XBT_NIL, path);
   16.98  
   16.99      snprintf(path, sizeof(path), "%s/page-ref", nodename);
  16.100 @@ -432,8 +468,12 @@ again:
  16.101          goto abort_transaction;
  16.102      }
  16.103  
  16.104 -    err = xenbus_printf(xbt, nodename, "state", "%u", 3); /* initialized */
  16.105 -
  16.106 +    snprintf(path, sizeof(path), "%s/state", nodename);
  16.107 +    err = xenbus_switch_state(xbt, path, XenbusStateInitialised);
  16.108 +    if (err) {
  16.109 +        message = "switching state";
  16.110 +        goto abort_transaction;
  16.111 +    }
  16.112  
  16.113      err = xenbus_transaction_end(xbt, 0, &retry);
  16.114      if (retry) {
  16.115 @@ -459,20 +499,36 @@ done:
  16.116      printk("backend at %s\n", dev->backend);
  16.117  
  16.118      {
  16.119 +        XenbusState state;
  16.120          char path[strlen(dev->backend) + 1 + 14 + 1];
  16.121 +        char frontpath[strlen(nodename) + 1 + 6 + 1];
  16.122  
  16.123          snprintf(path, sizeof(path), "%s/state", dev->backend);
  16.124  
  16.125          xenbus_watch_path_token(XBT_NIL, path, path, &dev->events);
  16.126  
  16.127 -        xenbus_wait_for_value(path, "4", &dev->events);
  16.128 +        err = NULL;
  16.129 +        state = xenbus_read_integer(path);
  16.130 +        while (err == NULL && state < XenbusStateConnected)
  16.131 +            err = xenbus_wait_for_state_change(path, &state, &dev->events);
  16.132 +        if (state != XenbusStateConnected) {
  16.133 +            printk("backend not available, state=%d\n", state);
  16.134 +            xenbus_unwatch_path(XBT_NIL, path);
  16.135 +            goto error;
  16.136 +        }
  16.137  
  16.138          printk("%s connected\n", dev->backend);
  16.139  
  16.140          snprintf(path, sizeof(path), "%s/request-update", dev->backend);
  16.141          dev->request_update = xenbus_read_integer(path);
  16.142  
  16.143 -        err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 4); /* connected */
  16.144 +        snprintf(frontpath, sizeof(frontpath), "%s/state", nodename);
  16.145 +        if ((err = xenbus_switch_state(XBT_NIL, frontpath, XenbusStateConnected))
  16.146 +            != NULL) {
  16.147 +            printk("error switching state: %s\n", err);
  16.148 +            xenbus_unwatch_path(XBT_NIL, path);
  16.149 +            goto error;
  16.150 +        }
  16.151      }
  16.152      unmask_evtchn(dev->evtchn);
  16.153  
  16.154 @@ -551,24 +607,43 @@ void fbfront_resize(struct fbfront_dev *
  16.155  
  16.156  void shutdown_fbfront(struct fbfront_dev *dev)
  16.157  {
  16.158 -    char* err;
  16.159 -    char *nodename = dev->nodename;
  16.160 +    char* err = NULL;
  16.161 +    XenbusState state;
  16.162  
  16.163      char path[strlen(dev->backend) + 1 + 5 + 1];
  16.164 +    char nodename[strlen(dev->nodename) + 1 + 5 + 1];
  16.165  
  16.166      printk("close fb: backend at %s\n",dev->backend);
  16.167  
  16.168      snprintf(path, sizeof(path), "%s/state", dev->backend);
  16.169 -    err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 5); /* closing */
  16.170 -    xenbus_wait_for_value(path, "5", &dev->events);
  16.171 +    snprintf(nodename, sizeof(nodename), "%s/state", dev->nodename);
  16.172 +    if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosing)) != NULL) {
  16.173 +        printk("shutdown_fbfront: error changing state to %d: %s\n",
  16.174 +                XenbusStateClosing, err);
  16.175 +        goto close_fbfront;
  16.176 +    }
  16.177 +    state = xenbus_read_integer(path);
  16.178 +    while (err == NULL && state < XenbusStateClosing)
  16.179 +        err = xenbus_wait_for_state_change(path, &state, &dev->events);
  16.180  
  16.181 -    err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 6);
  16.182 -    xenbus_wait_for_value(path, "6", &dev->events);
  16.183 +    if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosed)) != NULL) {
  16.184 +        printk("shutdown_fbfront: error changing state to %d: %s\n",
  16.185 +                XenbusStateClosed, err);
  16.186 +        goto close_fbfront;
  16.187 +    }
  16.188 +    state = xenbus_read_integer(path);
  16.189 +    if (state < XenbusStateClosed)
  16.190 +        xenbus_wait_for_state_change(path, &state, &dev->events);
  16.191  
  16.192 -    err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 1);
  16.193 +    if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateInitialising)) != NULL) {
  16.194 +        printk("shutdown_fbfront: error changing state to %d: %s\n",
  16.195 +                XenbusStateInitialising, err);
  16.196 +        goto close_fbfront;
  16.197 +    }
  16.198      // does not work yet
  16.199      //xenbus_wait_for_value(path, "2", &dev->events);
  16.200  
  16.201 +close_fbfront:
  16.202      xenbus_unwatch_path(XBT_NIL, path);
  16.203  
  16.204      snprintf(path, sizeof(path), "%s/page-ref", nodename);
    17.1 --- a/extras/mini-os/include/posix/strings.h	Tue Jun 16 17:03:31 2009 -0700
    17.2 +++ b/extras/mini-os/include/posix/strings.h	Wed Jun 17 17:24:56 2009 -0700
    17.3 @@ -5,4 +5,8 @@
    17.4  
    17.5  #define bzero(ptr, size) (memset((ptr), '\0', (size)), (void) 0)
    17.6  
    17.7 +int ffs (int i);
    17.8 +int ffsl (long int li);
    17.9 +int ffsll (long long int lli);
   17.10 +
   17.11  #endif /* _POSIX_STRINGS_H */
    18.1 --- a/extras/mini-os/include/posix/unistd.h	Tue Jun 16 17:03:31 2009 -0700
    18.2 +++ b/extras/mini-os/include/posix/unistd.h	Wed Jun 17 17:24:56 2009 -0700
    18.3 @@ -3,8 +3,14 @@
    18.4  
    18.5  #include_next <unistd.h>
    18.6  
    18.7 +uid_t getuid(void);
    18.8 +uid_t geteuid(void);
    18.9 +gid_t getgid(void);
   18.10 +gid_t getegid(void);
   18.11 +int gethostname(char *name, size_t namelen);
   18.12  size_t getpagesize(void);
   18.13  int ftruncate(int fd, off_t length);
   18.14  int lockf(int fd, int cmd, off_t len);
   18.15 +int nice(int inc);
   18.16  
   18.17  #endif /* _POSIX_UNISTD_H */
    19.1 --- a/extras/mini-os/include/xenbus.h	Tue Jun 16 17:03:31 2009 -0700
    19.2 +++ b/extras/mini-os/include/xenbus.h	Wed Jun 17 17:24:56 2009 -0700
    19.3 @@ -1,6 +1,8 @@
    19.4  #ifndef XENBUS_H__
    19.5  #define XENBUS_H__
    19.6  
    19.7 +#include <xen/io/xenbus.h>
    19.8 +
    19.9  typedef unsigned long xenbus_transaction_t;
   19.10  #define XBT_NIL ((xenbus_transaction_t)0)
   19.11  
   19.12 @@ -27,6 +29,8 @@ extern struct wait_queue_head xenbus_wat
   19.13  void xenbus_wait_for_watch(xenbus_event_queue *queue);
   19.14  char **xenbus_wait_for_watch_return(xenbus_event_queue *queue);
   19.15  char* xenbus_wait_for_value(const char *path, const char *value, xenbus_event_queue *queue);
   19.16 +char *xenbus_wait_for_state_change(const char* path, XenbusState *state, xenbus_event_queue *queue);
   19.17 +char *xenbus_switch_state(xenbus_transaction_t xbt, const char* path, XenbusState state);
   19.18  
   19.19  /* When no token is provided, use a global queue. */
   19.20  #define XENBUS_WATCH_PATH_TOKEN "xenbus_watch_path"
    20.1 --- a/extras/mini-os/lib/string.c	Tue Jun 16 17:03:31 2009 -0700
    20.2 +++ b/extras/mini-os/lib/string.c	Wed Jun 17 17:24:56 2009 -0700
    20.3 @@ -18,6 +18,43 @@
    20.4   ****************************************************************************
    20.5   */
    20.6  
    20.7 +#include <strings.h>
    20.8 +
    20.9 +/* newlib defines ffs but not ffsll or ffsl */
   20.10 +int __ffsti2 (long long int lli)
   20.11 +{
   20.12 +    int i, num, t, tmpint, len;
   20.13 +
   20.14 +    num = sizeof(long long int) / sizeof(int);
   20.15 +    if (num == 1) return (ffs((int) lli));
   20.16 +    len = sizeof(int) * 8;
   20.17 +
   20.18 +    for (i = 0; i < num; i++) {
   20.19 +        tmpint = (int) (((lli >> len) << len) ^ lli);
   20.20 +
   20.21 +        t = ffs(tmpint);
   20.22 +        if (t)
   20.23 +            return (t + i * len);
   20.24 +        lli = lli >> len;
   20.25 +    }
   20.26 +    return 0;
   20.27 +}
   20.28 +
   20.29 +int __ffsdi2 (long int li)
   20.30 +{
   20.31 +    return __ffsti2 ((long long int) li);
   20.32 +}
   20.33 +
   20.34 +int ffsl (long int li)
   20.35 +{
   20.36 +    return __ffsti2 ((long long int) li);
   20.37 +}
   20.38 +
   20.39 +int ffsll (long long int lli)
   20.40 +{
   20.41 +    return __ffsti2 (lli);
   20.42 +}
   20.43 +
   20.44  #if !defined HAVE_LIBC
   20.45  
   20.46  #include <os.h>
   20.47 @@ -175,4 +212,17 @@ char *strdup(const char *x)
   20.48      return res;
   20.49  }
   20.50  
   20.51 +int ffs(int i)
   20.52 +{
   20.53 +   int c = 1;
   20.54 +
   20.55 +   do {
   20.56 +      if (i & 1)
   20.57 +         return (c);
   20.58 +      i = i >> 1;
   20.59 +      c++;
   20.60 +   } while (i);
   20.61 +   return 0;
   20.62 +}
   20.63 +
   20.64  #endif
    21.1 --- a/extras/mini-os/lib/sys.c	Tue Jun 16 17:03:31 2009 -0700
    21.2 +++ b/extras/mini-os/lib/sys.c	Wed Jun 17 17:24:56 2009 -0700
    21.3 @@ -677,7 +677,7 @@ static int select_poll(int nfds, fd_set 
    21.4  {
    21.5      int i, n = 0;
    21.6  #ifdef HAVE_LWIP
    21.7 -    int sock_n, sock_nfds = 0;
    21.8 +    int sock_n = 0, sock_nfds = 0;
    21.9      fd_set sock_readfds, sock_writefds, sock_exceptfds;
   21.10      struct timeval timeout = { .tv_sec = 0, .tv_usec = 0};
   21.11  #endif
   21.12 @@ -711,12 +711,14 @@ static int select_poll(int nfds, fd_set 
   21.13  	    }
   21.14  	}
   21.15      }
   21.16 -    DEBUG("lwip_select(");
   21.17 -    dump_set(nfds, &sock_readfds, &sock_writefds, &sock_exceptfds, &timeout);
   21.18 -    DEBUG("); -> ");
   21.19 -    sock_n = lwip_select(sock_nfds, &sock_readfds, &sock_writefds, &sock_exceptfds, &timeout);
   21.20 -    dump_set(nfds, &sock_readfds, &sock_writefds, &sock_exceptfds, &timeout);
   21.21 -    DEBUG("\n");
   21.22 +    if (sock_nfds > 0) {
   21.23 +        DEBUG("lwip_select(");
   21.24 +        dump_set(nfds, &sock_readfds, &sock_writefds, &sock_exceptfds, &timeout);
   21.25 +        DEBUG("); -> ");
   21.26 +        sock_n = lwip_select(sock_nfds, &sock_readfds, &sock_writefds, &sock_exceptfds, &timeout);
   21.27 +        dump_set(nfds, &sock_readfds, &sock_writefds, &sock_exceptfds, &timeout);
   21.28 +        DEBUG("\n");
   21.29 +    }
   21.30  #endif
   21.31  
   21.32      /* Then see others as well. */
   21.33 @@ -1183,6 +1185,32 @@ int clock_gettime(clockid_t clk_id, stru
   21.34      return 0;
   21.35  }
   21.36  
   21.37 +uid_t getuid(void)
   21.38 +{
   21.39 +	return 0;
   21.40 +}
   21.41 +
   21.42 +uid_t geteuid(void)
   21.43 +{
   21.44 +	return 0;
   21.45 +}
   21.46 +
   21.47 +gid_t getgid(void)
   21.48 +{
   21.49 +	return 0;
   21.50 +}
   21.51 +
   21.52 +gid_t getegid(void)
   21.53 +{
   21.54 +	return 0;
   21.55 +}
   21.56 +
   21.57 +int gethostname(char *name, size_t namelen)
   21.58 +{
   21.59 +	strncpy(name, "mini-os", namelen);
   21.60 +	return 0;
   21.61 +}
   21.62 +
   21.63  size_t getpagesize(void)
   21.64  {
   21.65      return PAGE_SIZE;
   21.66 @@ -1253,6 +1281,12 @@ void sparse(unsigned long data, size_t s
   21.67      do_map_zero(data, n);
   21.68  }
   21.69  
   21.70 +int nice(int inc)
   21.71 +{
   21.72 +    printk("nice() stub called with inc=%d\n", inc);
   21.73 +    return 0;
   21.74 +}
   21.75 +
   21.76  
   21.77  /* Not supported by FS yet.  */
   21.78  unsupported_function_crash(link);
   21.79 @@ -1299,7 +1333,10 @@ unsupported_function_log(char *, if_inde
   21.80  unsupported_function_log(struct  if_nameindex *, if_nameindex, (struct  if_nameindex *) NULL);
   21.81  unsupported_function_crash(if_freenameindex);
   21.82  
   21.83 -/* Linuxish abi for the Caml runtime, don't support */
   21.84 +/* Linuxish abi for the Caml runtime, don't support 
   21.85 +   Log, and return an error code if possible.  If it is not possible
   21.86 +   to inform the application of an error, then crash instead!
   21.87 +*/
   21.88  unsupported_function_log(struct dirent *, readdir64, NULL);
   21.89  unsupported_function_log(int, getrusage, -1);
   21.90  unsupported_function_log(int, getrlimit, -1);
   21.91 @@ -1307,4 +1344,58 @@ unsupported_function_log(int, getrlimit6
   21.92  unsupported_function_log(int, __xstat64, -1);
   21.93  unsupported_function_log(long, __strtol_internal, LONG_MIN);
   21.94  unsupported_function_log(double, __strtod_internal, HUGE_VAL);
   21.95 +unsupported_function_log(int, utime, -1);
   21.96 +unsupported_function_log(int, truncate64, -1);
   21.97 +unsupported_function_log(int, tcflow, -1);
   21.98 +unsupported_function_log(int, tcflush, -1);
   21.99 +unsupported_function_log(int, tcdrain, -1);
  21.100 +unsupported_function_log(int, tcsendbreak, -1);
  21.101 +unsupported_function_log(int, cfsetospeed, -1);
  21.102 +unsupported_function_log(int, cfsetispeed, -1);
  21.103 +unsupported_function_crash(cfgetospeed);
  21.104 +unsupported_function_crash(cfgetispeed);
  21.105 +unsupported_function_log(int, symlink, -1);
  21.106 +unsupported_function_log(const char*, inet_ntop, NULL);
  21.107 +unsupported_function_crash(__fxstat64);
  21.108 +unsupported_function_crash(__lxstat64);
  21.109 +unsupported_function_log(int, socketpair, -1);
  21.110 +unsupported_function_crash(sigsuspend);
  21.111 +unsupported_function_log(int, sigpending, -1);
  21.112 +unsupported_function_log(int, shutdown, -1);
  21.113 +unsupported_function_log(int, setuid, -1);
  21.114 +unsupported_function_log(int, setgid, -1);
  21.115 +unsupported_function_crash(rewinddir);
  21.116 +unsupported_function_log(int, getpriority, -1);
  21.117 +unsupported_function_log(int, setpriority, -1);
  21.118 +unsupported_function_log(int, mkfifo, -1);
  21.119 +unsupported_function_log(int, getitimer, -1);
  21.120 +unsupported_function_log(int, setitimer, -1);
  21.121 +unsupported_function_log(void *, getservbyport, NULL);
  21.122 +unsupported_function_log(void *, getservbyname, NULL);
  21.123 +unsupported_function_log(void *, getpwuid, NULL);
  21.124 +unsupported_function_log(void *, getpwnam, NULL);
  21.125 +unsupported_function_log(void *, getprotobynumber, NULL);
  21.126 +unsupported_function_log(void *, getprotobyname, NULL);
  21.127 +unsupported_function_log(int, getpeername, -1);
  21.128 +unsupported_function_log(int, getnameinfo, -1);
  21.129 +unsupported_function_log(char *, getlogin, NULL);
  21.130 +unsupported_function_crash(__h_errno_location);
  21.131 +unsupported_function_log(int, gethostbyname_r, -1);
  21.132 +unsupported_function_log(int, gethostbyaddr_r, -1);
  21.133 +unsupported_function_log(int, getgroups, -1);
  21.134 +unsupported_function_log(void *, getgrgid, NULL);
  21.135 +unsupported_function_log(void *, getgrnam, NULL);
  21.136 +unsupported_function_log(int, getaddrinfo, -1);
  21.137 +unsupported_function_log(int, freeaddrinfo, -1);
  21.138 +unsupported_function_log(int, ftruncate64, -1);
  21.139 +unsupported_function_log(int, fchown, -1);
  21.140 +unsupported_function_log(int, fchmod, -1);
  21.141 +unsupported_function_crash(execvp);
  21.142 +unsupported_function_log(int, dup, -1)
  21.143 +unsupported_function_log(int, chroot, -1)
  21.144 +unsupported_function_log(int, chown, -1);
  21.145 +unsupported_function_log(int, chmod, -1);
  21.146 +unsupported_function_crash(alarm);
  21.147 +unsupported_function_log(int, inet_pton, -1);
  21.148 +unsupported_function_log(int, access, -1);
  21.149  #endif
    22.1 --- a/extras/mini-os/main.c	Tue Jun 16 17:03:31 2009 -0700
    22.2 +++ b/extras/mini-os/main.c	Wed Jun 17 17:24:56 2009 -0700
    22.3 @@ -62,7 +62,7 @@ static void call_main(void *p)
    22.4  
    22.5  #ifndef CONFIG_GRUB
    22.6      sparse((unsigned long) &__app_bss_start, &__app_bss_end - &__app_bss_start);
    22.7 -#ifdef HAVE_LWIP
    22.8 +#if defined(HAVE_LWIP) && !defined(CONFIG_QEMU)
    22.9      start_networking();
   22.10  #endif
   22.11      init_fs_frontend();
    23.1 --- a/extras/mini-os/netfront.c	Tue Jun 16 17:03:31 2009 -0700
    23.2 +++ b/extras/mini-os/netfront.c	Wed Jun 17 17:24:56 2009 -0700
    23.3 @@ -306,11 +306,16 @@ struct netfront_dev *init_netfront(char 
    23.4      int retry=0;
    23.5      int i;
    23.6      char* msg;
    23.7 -    char* nodename = _nodename ? _nodename : "device/vif/0";
    23.8 -
    23.9 +    char nodename[256];
   23.10 +    char path[256];
   23.11      struct netfront_dev *dev;
   23.12 +    static int netfrontends = 0;
   23.13  
   23.14 -    char path[strlen(nodename) + 1 + 10 + 1];
   23.15 +    if (!_nodename)
   23.16 +        snprintf(nodename, sizeof(nodename), "device/vif/%d", netfrontends);
   23.17 +    else
   23.18 +        strncpy(nodename, _nodename, strlen(nodename));
   23.19 +    netfrontends++;
   23.20  
   23.21      if (!thenetif_rx)
   23.22  	thenetif_rx = netif_rx;
   23.23 @@ -400,9 +405,12 @@ again:
   23.24          goto abort_transaction;
   23.25      }
   23.26  
   23.27 -    err = xenbus_printf(xbt, nodename, "state", "%u",
   23.28 -            4); /* connected */
   23.29 -
   23.30 +    snprintf(path, sizeof(path), "%s/state", nodename);
   23.31 +    err = xenbus_switch_state(xbt, path, XenbusStateConnected);
   23.32 +    if (err) {
   23.33 +        message = "switching state";
   23.34 +        goto abort_transaction;
   23.35 +    }
   23.36  
   23.37      err = xenbus_transaction_end(xbt, 0, &retry);
   23.38      if (retry) {
   23.39 @@ -432,12 +440,21 @@ done:
   23.40      printk("mac is %s\n",dev->mac);
   23.41  
   23.42      {
   23.43 +        XenbusState state;
   23.44          char path[strlen(dev->backend) + 1 + 5 + 1];
   23.45          snprintf(path, sizeof(path), "%s/state", dev->backend);
   23.46  
   23.47          xenbus_watch_path_token(XBT_NIL, path, path, &dev->events);
   23.48  
   23.49 -        xenbus_wait_for_value(path, "4", &dev->events);
   23.50 +        err = NULL;
   23.51 +        state = xenbus_read_integer(path);
   23.52 +        while (err == NULL && state < XenbusStateConnected)
   23.53 +            err = xenbus_wait_for_state_change(path, &state, &dev->events);
   23.54 +        if (state != XenbusStateConnected) {
   23.55 +            printk("backend not avalable, state=%d\n", state);
   23.56 +            xenbus_unwatch_path(XBT_NIL, path);
   23.57 +            goto error;
   23.58 +        }
   23.59  
   23.60          if (ip) {
   23.61              snprintf(path, sizeof(path), "%s/ip", dev->backend);
   23.62 @@ -485,24 +502,46 @@ int netfront_tap_open(char *nodename) {
   23.63  
   23.64  void shutdown_netfront(struct netfront_dev *dev)
   23.65  {
   23.66 -    char* err;
   23.67 -    char *nodename = dev->nodename;
   23.68 +    char* err = NULL;
   23.69 +    XenbusState state;
   23.70  
   23.71      char path[strlen(dev->backend) + 1 + 5 + 1];
   23.72 +    char nodename[strlen(dev->nodename) + 1 + 5 + 1];
   23.73  
   23.74      printk("close network: backend at %s\n",dev->backend);
   23.75  
   23.76      snprintf(path, sizeof(path), "%s/state", dev->backend);
   23.77 +    snprintf(nodename, sizeof(nodename), "%s/state", dev->nodename);
   23.78  
   23.79 -    err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 5); /* closing */
   23.80 -    xenbus_wait_for_value(path, "5", &dev->events);
   23.81 +    if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosing)) != NULL) {
   23.82 +        printk("shutdown_netfront: error changing state to %d: %s\n",
   23.83 +                XenbusStateClosing, err);
   23.84 +        goto close;
   23.85 +    }
   23.86 +    state = xenbus_read_integer(path);
   23.87 +    while (err == NULL && state < XenbusStateClosing)
   23.88 +        err = xenbus_wait_for_state_change(path, &state, &dev->events);
   23.89  
   23.90 -    err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 6);
   23.91 -    xenbus_wait_for_value(path, "6", &dev->events);
   23.92 +    if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosed)) != NULL) {
   23.93 +        printk("shutdown_netfront: error changing state to %d: %s\n",
   23.94 +                XenbusStateClosed, err);
   23.95 +        goto close;
   23.96 +    }
   23.97 +    state = xenbus_read_integer(path);
   23.98 +    if (state < XenbusStateClosed)
   23.99 +        xenbus_wait_for_state_change(path, &state, &dev->events);
  23.100  
  23.101 -    err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 1);
  23.102 -    xenbus_wait_for_value(path, "2", &dev->events);
  23.103 +    if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateInitialising)) != NULL) {
  23.104 +        printk("shutdown_netfront: error changing state to %d: %s\n",
  23.105 +                XenbusStateInitialising, err);
  23.106 +        goto close;
  23.107 +    }
  23.108 +    err = NULL;
  23.109 +    state = xenbus_read_integer(path);
  23.110 +    while (err == NULL && (state < XenbusStateInitWait || state >= XenbusStateClosed))
  23.111 +        err = xenbus_wait_for_state_change(path, &state, &dev->events);
  23.112  
  23.113 +close:
  23.114      xenbus_unwatch_path(XBT_NIL, path);
  23.115  
  23.116      snprintf(path, sizeof(path), "%s/tx-ring-ref", nodename);
    24.1 --- a/extras/mini-os/pcifront.c	Tue Jun 16 17:03:31 2009 -0700
    24.2 +++ b/extras/mini-os/pcifront.c	Wed Jun 17 17:24:56 2009 -0700
    24.3 @@ -111,9 +111,12 @@ again:
    24.4          goto abort_transaction;
    24.5      }
    24.6  
    24.7 -    err = xenbus_printf(xbt, nodename, "state", "%u",
    24.8 -            3); /* initialised */
    24.9 -
   24.10 +    snprintf(path, sizeof(path), "%s/state", nodename);
   24.11 +    err = xenbus_switch_state(xbt, path, XenbusStateInitialised);
   24.12 +    if (err) {
   24.13 +        message = "switching state";
   24.14 +        goto abort_transaction;
   24.15 +    }
   24.16  
   24.17      err = xenbus_transaction_end(xbt, 0, &retry);
   24.18      if (retry) {
   24.19 @@ -140,13 +143,29 @@ done:
   24.20  
   24.21      {
   24.22          char path[strlen(dev->backend) + 1 + 5 + 1];
   24.23 +        char frontpath[strlen(nodename) + 1 + 5 + 1];
   24.24 +        XenbusState state;
   24.25          snprintf(path, sizeof(path), "%s/state", dev->backend);
   24.26  
   24.27          xenbus_watch_path_token(XBT_NIL, path, path, &dev->events);
   24.28  
   24.29 -        xenbus_wait_for_value(path, "4", &dev->events);
   24.30 +        err = NULL;
   24.31 +        state = xenbus_read_integer(path);
   24.32 +        while (err == NULL && state < XenbusStateConnected)
   24.33 +            err = xenbus_wait_for_state_change(path, &state, &dev->events);
   24.34 +        if (state != XenbusStateConnected) {
   24.35 +            printk("backend not avalable, state=%d\n", state);
   24.36 +            xenbus_unwatch_path(XBT_NIL, path);
   24.37 +            goto error;
   24.38 +        }
   24.39  
   24.40 -        xenbus_printf(xbt, nodename, "state", "%u", 4); /* connected */
   24.41 +        snprintf(frontpath, sizeof(frontpath), "%s/state", nodename);
   24.42 +        if ((err = xenbus_switch_state(XBT_NIL, frontpath, XenbusStateConnected))
   24.43 +            != NULL) {
   24.44 +            printk("error switching state %s\n", err);
   24.45 +            xenbus_unwatch_path(XBT_NIL, path);
   24.46 +            goto error;
   24.47 +        }
   24.48      }
   24.49      unmask_evtchn(dev->evtchn);
   24.50  
   24.51 @@ -190,23 +209,45 @@ void pcifront_scan(struct pcifront_dev *
   24.52  
   24.53  void shutdown_pcifront(struct pcifront_dev *dev)
   24.54  {
   24.55 -    char* err;
   24.56 -    char *nodename = dev->nodename;
   24.57 +    char* err = NULL;
   24.58 +    XenbusState state;
   24.59  
   24.60      char path[strlen(dev->backend) + 1 + 5 + 1];
   24.61 +    char nodename[strlen(dev->nodename) + 1 + 5 + 1];
   24.62  
   24.63      printk("close pci: backend at %s\n",dev->backend);
   24.64  
   24.65      snprintf(path, sizeof(path), "%s/state", dev->backend);
   24.66 -    err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 5); /* closing */
   24.67 -    xenbus_wait_for_value(path, "5", &dev->events);
   24.68 +    snprintf(nodename, sizeof(nodename), "%s/state", dev->nodename);
   24.69 +    if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosing)) != NULL) {
   24.70 +        printk("shutdown_pcifront: error changing state to %d: %s\n",
   24.71 +                XenbusStateClosing, err);
   24.72 +        goto close_pcifront;
   24.73 +    }
   24.74 +    state = xenbus_read_integer(path);
   24.75 +    while (err == NULL && state < XenbusStateClosing)
   24.76 +        err = xenbus_wait_for_state_change(path, &state, &dev->events);
   24.77  
   24.78 -    err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 6);
   24.79 -    xenbus_wait_for_value(path, "6", &dev->events);
   24.80 +    if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosed)) != NULL) {
   24.81 +        printk("shutdown_pcifront: error changing state to %d: %s\n",
   24.82 +                XenbusStateClosed, err);
   24.83 +        goto close_pcifront;
   24.84 +    }
   24.85 +    state = xenbus_read_integer(path);
   24.86 +    if (state < XenbusStateClosed)
   24.87 +        xenbus_wait_for_state_change(path, &state, &dev->events);
   24.88  
   24.89 -    err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 1);
   24.90 -    xenbus_wait_for_value(path, "2", &dev->events);
   24.91 +    if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateInitialising)) != NULL) {
   24.92 +        printk("shutdown_pcifront: error changing state to %d: %s\n",
   24.93 +                XenbusStateInitialising, err);
   24.94 +        goto close_pcifront;
   24.95 +    }
   24.96 +    err = NULL;
   24.97 +    state = xenbus_read_integer(path);
   24.98 +    while (err == NULL && (state < XenbusStateInitWait || state >= XenbusStateClosed))
   24.99 +        err = xenbus_wait_for_state_change(path, &state, &dev->events);
  24.100  
  24.101 +close_pcifront:
  24.102      xenbus_unwatch_path(XBT_NIL, path);
  24.103  
  24.104      snprintf(path, sizeof(path), "%s/info-ref", nodename);
    25.1 --- a/extras/mini-os/xenbus/xenbus.c	Tue Jun 16 17:03:31 2009 -0700
    25.2 +++ b/extras/mini-os/xenbus/xenbus.c	Wed Jun 17 17:24:56 2009 -0700
    25.3 @@ -120,6 +120,70 @@ char* xenbus_wait_for_value(const char* 
    25.4      return NULL;
    25.5  }
    25.6  
    25.7 +char *xenbus_switch_state(xenbus_transaction_t xbt, const char* path, XenbusState state)
    25.8 +{
    25.9 +    char *current_state;
   25.10 +    char *msg = NULL;
   25.11 +    char *msg2 = NULL;
   25.12 +    char value[2];
   25.13 +    XenbusState rs;
   25.14 +    int xbt_flag = 0;
   25.15 +    int retry = 0;
   25.16 +
   25.17 +    do {
   25.18 +        if (xbt == XBT_NIL) {
   25.19 +            xenbus_transaction_start(&xbt);
   25.20 +            xbt_flag = 1;
   25.21 +        }
   25.22 +
   25.23 +        msg = xenbus_read(xbt, path, &current_state);
   25.24 +        if (msg) goto exit;
   25.25 +
   25.26 +        rs = (XenbusState) (current_state[0] - '0');
   25.27 +        free(current_state);
   25.28 +        if (rs == state) {
   25.29 +            msg = NULL;
   25.30 +            goto exit;
   25.31 +        }
   25.32 +
   25.33 +        snprintf(value, 2, "%d", state);
   25.34 +        msg = xenbus_write(xbt, path, value);
   25.35 +
   25.36 +exit:
   25.37 +        if (xbt_flag)
   25.38 +            msg2 = xenbus_transaction_end(xbt, 0, &retry);
   25.39 +        if (msg == NULL && msg2 != NULL)
   25.40 +            msg = msg2;
   25.41 +    } while (retry);
   25.42 +
   25.43 +    return msg;
   25.44 +}
   25.45 +
   25.46 +char *xenbus_wait_for_state_change(const char* path, XenbusState *state, xenbus_event_queue *queue)
   25.47 +{
   25.48 +    if (!queue)
   25.49 +        queue = &xenbus_events;
   25.50 +    for(;;)
   25.51 +    {
   25.52 +        char *res, *msg;
   25.53 +        XenbusState rs;
   25.54 +
   25.55 +        msg = xenbus_read(XBT_NIL, path, &res);
   25.56 +        if(msg) return msg;
   25.57 +
   25.58 +        rs = (XenbusState) (res[0] - 48);
   25.59 +        free(res);
   25.60 +
   25.61 +        if (rs == *state)
   25.62 +            xenbus_wait_for_watch(queue);
   25.63 +        else {
   25.64 +            *state = rs;
   25.65 +            break;
   25.66 +        }
   25.67 +    }
   25.68 +    return NULL;
   25.69 +}
   25.70 +
   25.71  
   25.72  static void xenbus_thread_func(void *ign)
   25.73  {
    26.1 --- a/stubdom/Makefile	Tue Jun 16 17:03:31 2009 -0700
    26.2 +++ b/stubdom/Makefile	Wed Jun 17 17:24:56 2009 -0700
    26.3 @@ -27,6 +27,10 @@ LWIP_VERSION=1.3.0
    26.4  GRUB_URL?=$(XEN_EXTFILES_URL)
    26.5  GRUB_VERSION=0.97
    26.6  
    26.7 +#OCAML_URL?=$(XEN_EXTFILES_URL)
    26.8 +OCAML_URL?=http://caml.inria.fr/pub/distrib/ocaml-3.11
    26.9 +OCAML_VERSION=3.11.0
   26.10 +
   26.11  WGET=wget -c
   26.12  
   26.13  GNU_TARGET_ARCH:=$(XEN_TARGET_ARCH)
   26.14 @@ -164,6 +168,37 @@ lwip-$(XEN_TARGET_ARCH): lwip-$(LWIP_VER
   26.15  	patch -d $@ -p0 < lwip.patch-cvs
   26.16  	touch $@
   26.17  
   26.18 +#############
   26.19 +# Cross-ocaml
   26.20 +#############
   26.21 +
   26.22 +CAMLLIB = $(CROSS_PREFIX)/$(GNU_TARGET_ARCH)-xen-elf/lib/ocaml
   26.23 +OCAML_STAMPFILE=$(CAMLLIB)/.dirstamp
   26.24 +
   26.25 +ocaml-$(OCAML_VERSION).tar.gz:
   26.26 +	$(WGET) $(OCAML_URL)/$@
   26.27 +
   26.28 +ocaml-$(XEN_TARGET_ARCH)/.dirstamp: ocaml-$(OCAML_VERSION).tar.gz ocaml.patch
   26.29 +	tar xzf $<
   26.30 +	cd ocaml-$(OCAML_VERSION) && patch -p0 < ../ocaml.patch
   26.31 +	rm -rf ocaml-$(XEN_TARGET_ARCH)
   26.32 +	mv ocaml-$(OCAML_VERSION) ocaml-$(XEN_TARGET_ARCH)
   26.33 +	touch $@
   26.34 +
   26.35 +MINIOS_HASNOT=IPV6 INET_ATON
   26.36 +
   26.37 +.PHONY: cross-ocaml
   26.38 +cross-ocaml: $(OCAML_STAMPFILE)
   26.39 +$(OCAML_STAMPFILE): ocaml-$(XEN_TARGET_ARCH)/.dirstamp
   26.40 +	cd ocaml-$(XEN_TARGET_ARCH) &&  ./configure -prefix $(CROSS_PREFIX)/$(GNU_TARGET_ARCH)-xen-elf \
   26.41 +		-no-pthread -no-shared-libs -no-tk -no-curses \
   26.42 +		-cc "$(CC) -U_FORTIFY_SOURCE -fno-stack-protector"
   26.43 +	$(foreach i,$(MINIOS_HASNOT),sed -i 's,^\(#define HAS_$(i)\),//\1,' ocaml-$(XEN_TARGET_ARCH)/config/s.h ; )
   26.44 +	$(MAKE) -C ocaml-$(XEN_TARGET_ARCH) world
   26.45 +	$(MAKE) -C ocaml-$(XEN_TARGET_ARCH) opt
   26.46 +	$(MAKE) -C ocaml-$(XEN_TARGET_ARCH) install
   26.47 +	touch $@
   26.48 +
   26.49  #######
   26.50  # Links
   26.51  #######
   26.52 @@ -235,6 +270,8 @@ libxc-$(XEN_TARGET_ARCH)/libxenctrl.a li
   26.53  ioemu: cross-zlib cross-libpci libxc
   26.54  	[ -f ioemu/config-host.mak ] || \
   26.55  	  ( $(absolutify_xen_root); \
   26.56 +	    PREFIX=$(PREFIX); \
   26.57 +	    export PREFIX; \
   26.58  	    cd ioemu ; \
   26.59  	    LWIPDIR=$(CURDIR)/lwip-$(XEN_TARGET_ARCH) \
   26.60  	    TARGET_CPPFLAGS="$(TARGET_CPPFLAGS)" \
   26.61 @@ -249,7 +286,7 @@ ioemu: cross-zlib cross-libpci libxc
   26.62  
   26.63  .PHONY: caml
   26.64  caml: $(CROSS_ROOT)
   26.65 -	CPPFLAGS="$(TARGET_CPPFLAGS)" CFLAGS="$(TARGET_CFLAGS)" $(MAKE) -C $@ LWIPDIR=$(CURDIR)/lwip-$(XEN_TARGET_ARCH) 
   26.66 +	CPPFLAGS="$(TARGET_CPPFLAGS)" CFLAGS="$(TARGET_CFLAGS)" $(MAKE) -C $@ LWIPDIR=$(CURDIR)/lwip-$(XEN_TARGET_ARCH) OCAMLC_CROSS_PREFIX=$(CROSS_PREFIX)/$(GNU_TARGET_ARCH)-xen-elf/bin/
   26.67  
   26.68  ###
   26.69  # C
   26.70 @@ -287,7 +324,6 @@ ioemu-stubdom: APP_OBJS=$(CURDIR)/ioemu/
   26.71  ioemu-stubdom: mini-os-$(XEN_TARGET_ARCH)-ioemu lwip-$(XEN_TARGET_ARCH) libxc ioemu
   26.72  	DEF_CPPFLAGS="$(TARGET_CPPFLAGS)" DEF_CFLAGS="-DCONFIG_QEMU $(TARGET_CFLAGS)" DEF_LDFLAGS="$(TARGET_LDFLAGS)" $(MAKE) -C $(MINI_OS) OBJ_DIR=$(CURDIR)/$< LWIPDIR=$(CURDIR)/lwip-$(XEN_TARGET_ARCH) APP_OBJS="$(APP_OBJS)"
   26.73  
   26.74 -CAMLLIB = $(shell ocamlc -where)
   26.75  .PHONY: caml-stubdom
   26.76  caml-stubdom: mini-os-$(XEN_TARGET_ARCH)-caml lwip-$(XEN_TARGET_ARCH) libxc caml
   26.77  	DEF_CPPFLAGS="$(TARGET_CPPFLAGS)" DEF_CFLAGS="-DCONFIG_CAML $(TARGET_CFLAGS)" DEF_LDFLAGS="$(TARGET_LDFLAGS)" $(MAKE) -C $(MINI_OS) OBJ_DIR=$(CURDIR)/$< LWIPDIR=$(CURDIR)/lwip-$(XEN_TARGET_ARCH) APP_OBJS="$(CURDIR)/caml/main-caml.o $(CURDIR)/caml/caml.o $(CAMLLIB)/libasmrun.a"
   26.78 @@ -349,6 +385,7 @@ crossclean: clean
   26.79  	rm -fr zlib-$(XEN_TARGET_ARCH) pciutils-$(XEN_TARGET_ARCH)
   26.80  	rm -fr libxc-$(XEN_TARGET_ARCH) ioemu
   26.81  	rm -f mk-headers-$(XEN_TARGET_ARCH)
   26.82 +	rm -fr ocaml-$(XEN_TARGET_ARCH)
   26.83  
   26.84  # clean patched sources
   26.85  .PHONY: patchclean
   26.86 @@ -365,6 +402,7 @@ downloadclean: patchclean
   26.87  	rm -f pciutils-$(LIBPCI_VERSION).tar.bz2
   26.88  	rm -f grub-$(GRUB_VERSION).tar.gz
   26.89  	rm -f lwip-$(LWIP_VERSION).tar.gz
   26.90 +	rm -f ocaml-$(OCAML_VERSION).tar.gz
   26.91  
   26.92  .PHONY: distclean
   26.93  distclean: downloadclean
    27.1 --- a/stubdom/README	Tue Jun 16 17:03:31 2009 -0700
    27.2 +++ b/stubdom/README	Wed Jun 17 17:24:56 2009 -0700
    27.3 @@ -11,81 +11,12 @@ of video memory for the HVM domain, you 
    27.4  by using the hypervisor dom0_mem= option for instance.
    27.5  
    27.6  
    27.7 -There is a sample configuration set in xmexample.hvm-stubdom and
    27.8 -xmexample.hvm-dm
    27.9 +There is a sample configuration set in xmexample.hvm-stubdom
   27.10  
   27.11 -In your HVM config "hvmconfig",
   27.12 -
   27.13 -- use /usr/lib/xen/bin/stubdom-dm as dm script:
   27.14 +In your HVM config "hvmconfig" use /usr/lib/xen/bin/stubdom-dm as dm script:
   27.15  
   27.16  device_model = '/usr/lib/xen/bin/stubdom-dm'
   27.17  
   27.18 -- comment the disk statement:
   27.19 -
   27.20 -#disk = [  'file:/tmp/install.iso,hdc:cdrom,r', 'phy:/dev/sda6,hda,w', 'file:/tmp/test,hdb,r' ]
   27.21 -
   27.22 -- disable anything related to dom0, like pty serial assignments
   27.23 -
   27.24 -
   27.25 -Create /etc/xen/hvmconfig-dm (where "hvmconfig" is the name of your HVM
   27.26 -guest) with
   27.27 -
   27.28 -kernel = "/usr/lib/xen/boot/ioemu-stubdom.gz"
   27.29 -vif = [ '', 'ip=10.0.1.1,mac=aa:00:00:12:23:34']
   27.30 -disk = [  'file:/tmp/install.iso,hdc:cdrom,r', 'phy:/dev/sda6,hda,w', 'file:/tmp/test,hdb,r' ]
   27.31 -
   27.32 -where
   27.33 -- the first vif ('') is reserved for VNC (see below)
   27.34 -- 'ip=10.0.1.1,mac= etc...' is the same net configuration as in the hvmconfig
   27.35 -script,
   27.36 -- and disk = is the same block configuration as in the hvmconfig script.
   27.37 -
   27.38 -Display Configuration
   27.39 -=====================
   27.40 -
   27.41 -There are three posibilities
   27.42 -
   27.43 -* Using SDL
   27.44 -
   27.45 -  - In hvmconfig, disable vnc and sdl:
   27.46 -
   27.47 -vnc = 0
   27.48 -sdl = 0
   27.49 -
   27.50 -  - In hvmconfig-dm, set an sdl vfb:
   27.51 -
   27.52 -vfb = [ 'type=sdl' ]
   27.53 -
   27.54 -    by default qemu will use sdl together with opengl for rendering, if
   27.55 -    you do not want qemu to use opengl then also pass opengl=0:
   27.56 -
   27.57 -vfb = [ 'type=sdl, opengl=0' ]
   27.58 -
   27.59 -* Using a VNC server in the stub domain
   27.60 -
   27.61 -  - In hvmconfig, set vnclisten to "172.30.206.1" for instance.  Do not use a
   27.62 -host name as Mini-OS does not have a name resolver.  Do not use 127.0.0.1 since
   27.63 -then you will not be able to connect to it.
   27.64 -
   27.65 -vnc = 1
   27.66 -vnclisten = "172.30.206.1"
   27.67 -
   27.68 -  - In hvmconfig-dm, fill the reserved vif with the same IP, for instance:
   27.69 -
   27.70 -vif = [ 'ip=172.30.206.1', 'ip=10.0.1.1,mac=aa:00:00:12:23:34']
   27.71 -
   27.72 -* Using a VNC server in dom0
   27.73 -
   27.74 -  - In hvmconfig, disable vnc and sdl:
   27.75 -
   27.76 -vnc = 0
   27.77 -sdl = 0
   27.78 -
   27.79 -  - In hvmconfig-dm, set a vnc vfb:
   27.80 -
   27.81 -vfb = [ 'type=vnc' ]
   27.82 -
   27.83 -and any other parameter as wished.
   27.84  
   27.85  To run
   27.86  ======
    28.1 --- a/stubdom/caml/Makefile	Tue Jun 16 17:03:31 2009 -0700
    28.2 +++ b/stubdom/caml/Makefile	Wed Jun 17 17:24:56 2009 -0700
    28.3 @@ -2,11 +2,10 @@ XEN_ROOT = ../..
    28.4  
    28.5  include $(XEN_ROOT)/Config.mk
    28.6  
    28.7 -CAMLLIB = $(shell ocamlc -where)
    28.8 +CAMLLIB = $(shell $(OCAMLC_CROSS_PREFIX)ocamlc -where)
    28.9  DEF_CPPFLAGS += -I$(CAMLLIB)
   28.10  
   28.11 -OCAMLFIND=ocamlfind
   28.12 -OCAMLOPT=ocamlopt
   28.13 +OCAMLOPT=$(OCAMLC_CROSS_PREFIX)ocamlopt
   28.14  
   28.15  OBJS := hello.cmx
   28.16  LIBS := 
   28.17 @@ -14,10 +13,10 @@ LIBS :=
   28.18  all: main-caml.o caml.o
   28.19  
   28.20  %.cmx: %.ml
   28.21 -	$(OCAMLFIND) $(OCAMLOPT) -c $< -o $@
   28.22 +	$(OCAMLOPT) -c $< -o $@
   28.23  
   28.24  caml.o: $(OBJS)
   28.25 -	$(OCAMLFIND) $(OCAMLOPT) $(LIBS) $^ -output-obj -o $@
   28.26 +	$(OCAMLOPT) $(LIBS) $^ -output-obj -o $@
   28.27  
   28.28  clean:
   28.29  	rm -f *.a *.o *.cmx *.cmi
    29.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.2 +++ b/stubdom/ocaml.patch	Wed Jun 17 17:24:56 2009 -0700
    29.3 @@ -0,0 +1,19 @@
    29.4 +--- byterun/Makefile.orig	2009-04-07 12:14:02.000000000 +0100
    29.5 ++++ byterun/Makefile	2009-04-07 12:13:50.000000000 +0100
    29.6 +@@ -22,14 +22,14 @@
    29.7 + DOBJS=$(OBJS:.o=.d.o) instrtrace.d.o
    29.8 + PICOBJS=$(OBJS:.o=.pic.o)
    29.9 + 
   29.10 +-#ifeq ($(SUPPORTS_SHARED_LIBRARIES),true)
   29.11 ++ifeq ($(SUPPORTS_SHARED_LIBRARIES),true)
   29.12 + 
   29.13 + all:: libcamlrun_shared.so
   29.14 + 
   29.15 + install::
   29.16 + 	cp libcamlrun_shared.so $(LIBDIR)/libcamlrun_shared.so
   29.17 + 
   29.18 +-#endif
   29.19 ++endif
   29.20 + 
   29.21 + ocamlrun$(EXE): libcamlrun.a prims.o
   29.22 + 	$(MKEXE) $(BYTECCLINKOPTS) -o ocamlrun$(EXE) \
    30.1 --- a/stubdom/stubdom-dm	Tue Jun 16 17:03:31 2009 -0700
    30.2 +++ b/stubdom/stubdom-dm	Wed Jun 17 17:24:56 2009 -0700
    30.3 @@ -112,15 +112,13 @@ do
    30.4      vbd_disk=`xenstore-read $i/params`
    30.5      vbd_type=`xenstore-read $i/type`
    30.6      vbd_dev=`xenstore-read $i/dev`
    30.7 -    if [ $vbd_type = "file" ]
    30.8 -    then
    30.9 -        vbd_type="tap:aio"
   30.10 -    fi
   30.11 +    vbd_front=`xenstore-read $i/frontend`
   30.12 +    vbd_devtype=`xenstore-read $vbd_front/device-type`
   30.13      if [ $j -ne 0 ]
   30.14      then
   30.15          echo -n "," >> /etc/xen/stubdoms/$domname-dm
   30.16      fi
   30.17 -    echo -n "'$vbd_type:$vbd_disk,$vbd_dev,$vbd_mode'" >> /etc/xen/stubdoms/$domname-dm
   30.18 +    echo -n "'$vbd_type:$vbd_disk,$vbd_dev:$vbd_devtype,$vbd_mode'" >> /etc/xen/stubdoms/$domname-dm
   30.19      j=$(( $j + 1 ))
   30.20  done
   30.21  echo " ] " >> /etc/xen/stubdoms/$domname-dm
    31.1 --- a/tools/Makefile	Tue Jun 16 17:03:31 2009 -0700
    31.2 +++ b/tools/Makefile	Wed Jun 17 17:24:56 2009 -0700
    31.3 @@ -6,6 +6,7 @@ SUBDIRS-y += check
    31.4  SUBDIRS-y += include
    31.5  SUBDIRS-y += libxc
    31.6  SUBDIRS-y += flask
    31.7 +SUBDIRS-$(CONFIG_OCAML_XENSTORED) += ocaml-xenstored
    31.8  SUBDIRS-y += xenstore
    31.9  SUBDIRS-y += misc
   31.10  SUBDIRS-y += examples
   31.11 @@ -21,6 +22,7 @@ SUBDIRS-$(VTPM_TOOLS) += vtpm
   31.12  SUBDIRS-y += xenstat
   31.13  SUBDIRS-$(CONFIG_Linux) += libaio
   31.14  SUBDIRS-$(CONFIG_Linux) += blktap
   31.15 +SUBDIRS-$(CONFIG_Linux) += blktap2
   31.16  SUBDIRS-y += libfsimage
   31.17  SUBDIRS-$(LIBXENAPI_BINDINGS) += libxen
   31.18  SUBDIRS-$(CONFIG_Linux) += fs-back
   31.19 @@ -49,6 +51,7 @@ install: subdirs-install
   31.20  	$(INSTALL_DIR) $(DESTDIR)/var/xen/dump
   31.21  	$(INSTALL_DIR) $(DESTDIR)/var/log/xen
   31.22  	$(INSTALL_DIR) $(DESTDIR)/var/lib/xen
   31.23 +	$(INSTALL_DIR) $(DESTDIR)/var/lock/subsys
   31.24  
   31.25  .PHONY: clean distclean
   31.26  clean distclean: subdirs-clean
   31.27 @@ -91,6 +94,10 @@ ioemu-dir-find:
   31.28  	fi
   31.29  	set -e; \
   31.30  		$(absolutify_xen_root); \
   31.31 +		PREFIX=$(PREFIX); \
   31.32 +		XEN_SCRIPT_DIR=$(XEN_SCRIPT_DIR); \
   31.33 +		export PREFIX; \
   31.34 +		export XEN_SCRIPT_DIR; \
   31.35  		cd ioemu-dir; \
   31.36  		./xen-setup $(IOEMU_CONFIGURE_CROSS)
   31.37  
   31.38 @@ -101,3 +108,23 @@ subdir-clean-ioemu-dir:
   31.39  		$(absolutify_xen_root); \
   31.40  		$(MAKE) -C ioemu-dir clean; \
   31.41  	fi
   31.42 +
   31.43 +ocaml-xenstored:
   31.44 +	set -ex; \
   31.45 +	rm -rf ocaml-xenstored.tmp; \
   31.46 +	hg clone $(OCAML_XENSTORED_REPO) ocaml-xenstored.tmp; \
   31.47 +	if [ "$(OCAML_XENSTORED_TAG)" ]; then \
   31.48 +		hg -R ocaml-xenstored.tmp update -r $(OCAML_XENSTORED_TAG) ;\
   31.49 +		hg -R ocaml-xenstored.tmp branch mybranch ;\
   31.50 +	fi;						\
   31.51 +	mv ocaml-xenstored.tmp ocaml-xenstored; \
   31.52 +
   31.53 +subdir-all-ocaml-xenstored subdir-install-ocaml-xenstored: ocaml-xenstored
   31.54 +	$(absolutify_xen_root); \
   31.55 +	$(MAKE) -C ocaml-xenstored $(patsubst subdir-%-ocaml-xenstored,%,$@);
   31.56 +
   31.57 +subdir-clean-ocaml-xenstored:
   31.58 +	set -e; if test -d ocaml-xenstored; then \
   31.59 +		$(MAKE) -C ocaml-xenstored clean; \
   31.60 +	fi
   31.61 +
    32.1 --- a/tools/blktap/drivers/blktapctrl.c	Tue Jun 16 17:03:31 2009 -0700
    32.2 +++ b/tools/blktap/drivers/blktapctrl.c	Wed Jun 17 17:24:56 2009 -0700
    32.3 @@ -659,6 +659,9 @@ static int blktapctrl_new_blkif(blkif_t 
    32.4  
    32.5  	DPRINTF("Received a poll for a new vbd\n");
    32.6  	if ( ((blk=blkif->info) != NULL) && (blk->params != NULL) ) {
    32.7 +		if (blktap_interface_create(ctlfd, &major, &minor, blkif) < 0)
    32.8 +			return -1;
    32.9 +
   32.10  		if (test_path(blk->params, &ptr, &type, &exist, &use_ioemu) != 0) {
   32.11                          DPRINTF("Error in blktap device string(%s).\n",
   32.12                                  blk->params);
   32.13 @@ -682,6 +685,10 @@ static int blktapctrl_new_blkif(blkif_t 
   32.14  			blkif->fds[WRITE] = exist->fds[WRITE];
   32.15  		}
   32.16  
   32.17 +		add_disktype(blkif, type);
   32.18 +		blkif->major = major;
   32.19 +		blkif->minor = minor;
   32.20 +
   32.21  		image = (image_t *)malloc(sizeof(image_t));
   32.22  		blkif->prv = (void *)image;
   32.23  		blkif->ops = &tapdisk_ops;
   32.24 @@ -705,18 +712,11 @@ static int blktapctrl_new_blkif(blkif_t 
   32.25  			goto fail;
   32.26  		}
   32.27  
   32.28 -		if (blktap_interface_create(ctlfd, &major, &minor, blkif) < 0)
   32.29 -			return -1;
   32.30 -
   32.31 -		blkif->major = major;
   32.32 -		blkif->minor = minor;
   32.33 -
   32.34 -		add_disktype(blkif, type);
   32.35 -
   32.36  	} else return -1;
   32.37  
   32.38  	return 0;
   32.39  fail:
   32.40 +	ioctl(ctlfd, BLKTAP_IOCTL_FREEINTF, minor);
   32.41  	return -EINVAL;
   32.42  }
   32.43  
    33.1 --- a/tools/blktap/drivers/block-qcow.c	Tue Jun 16 17:03:31 2009 -0700
    33.2 +++ b/tools/blktap/drivers/block-qcow.c	Wed Jun 17 17:24:56 2009 -0700
    33.3 @@ -55,7 +55,7 @@
    33.4  #define ROUNDUP(l, s) \
    33.5  ({ \
    33.6      (uint64_t)( \
    33.7 -        (l + (s - 1)) - ((l + (s - 1)) % s)); \
    33.8 +        ((l) + ((s) - 1)) - (((l) + ((s) - 1)) % (s))); \
    33.9  })
   33.10  
   33.11  #undef IOCB_IDX
   33.12 @@ -800,14 +800,14 @@ static int tdqcow_open (struct disk_driv
   33.13  
   33.14  	/* read the level 1 table */
   33.15  	shift = s->cluster_bits + s->l2_bits;
   33.16 -	s->l1_size = (header->size + (1LL << shift) - 1) >> shift;
   33.17 +	s->l1_size = ROUNDUP(header->size, 1LL << shift);
   33.18  	
   33.19  	s->l1_table_offset = header->l1_table_offset;
   33.20  
   33.21  	/*allocate a 4Kbyte multiple of memory*/
   33.22  	l1_table_size = s->l1_size * sizeof(uint64_t);
   33.23  	if (l1_table_size % 4096 > 0) {
   33.24 -		l1_table_size = ((l1_table_size >> 12) + 1) << 12;
   33.25 +		l1_table_size = ROUNDUP(l1_table_size, 4096);
   33.26  	}
   33.27  	ret = posix_memalign((void **)&s->l1_table, 4096, l1_table_size);
   33.28  	if (ret != 0) goto fail;
   33.29 @@ -821,10 +821,10 @@ static int tdqcow_open (struct disk_driv
   33.30  
   33.31  	lseek(fd, 0, SEEK_SET);
   33.32  	l1_table_block = l1_table_size + s->l1_table_offset;
   33.33 -	l1_table_block = l1_table_block + 512 - (l1_table_block % 512); 
   33.34 +	l1_table_block = ROUNDUP(l1_table_block, 512);
   33.35  	ret = posix_memalign((void **)&buf2, 4096, l1_table_block);
   33.36  	if (ret != 0) goto fail;
   33.37 -	if (read(fd, buf2, l1_table_block) != l1_table_block)
   33.38 +	if (read(fd, buf2, l1_table_block) < l1_table_size + s->l1_table_offset)
   33.39  		goto fail;
   33.40  	memcpy(s->l1_table, buf2 + s->l1_table_offset, l1_table_size);
   33.41  
   33.42 @@ -878,7 +878,8 @@ static int tdqcow_open (struct disk_driv
   33.43  
   33.44  			memcpy(buf2 + s->l1_table_offset, s->l1_table, l1_table_size);
   33.45  			lseek(fd, 0, SEEK_SET);
   33.46 -			if (write(fd, buf2, l1_table_block) != l1_table_block) {
   33.47 +			if (write(fd, buf2, l1_table_block) < 
   33.48 +				l1_table_size + s->l1_table_offset) {
   33.49  				DPRINTF("qcow: Failed to write new L1 table\n");
   33.50  				goto fail;
   33.51  			}
   33.52 @@ -1226,11 +1227,11 @@ int qcow_create(const char *filename, ui
   33.53  	
   33.54  	header_size = (header_size + 7) & ~7;
   33.55  	if (header_size % 4096 > 0) {
   33.56 -		header_size = ((header_size >> 12) + 1) << 12;
   33.57 +		header_size = ROUNDUP(header_size, 4096);
   33.58  	}
   33.59  
   33.60  	shift = header.cluster_bits + header.l2_bits;
   33.61 -	l1_size = ((size * 512) + (1LL << shift) - 1) >> shift;
   33.62 +	l1_size = ROUNDUP(size * 512, 1LL << shift);
   33.63  
   33.64  	header.l1_table_offset = cpu_to_be64(header_size);
   33.65  	DPRINTF("L1 Table offset: %d, size %d\n",
    34.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.2 +++ b/tools/blktap2/Makefile	Wed Jun 17 17:24:56 2009 -0700
    34.3 @@ -0,0 +1,18 @@
    34.4 +XEN_ROOT = ../..
    34.5 +include $(XEN_ROOT)/tools/Rules.mk
    34.6 +
    34.7 +CFLAGS  += $(CFLAGS_libxenctrl)
    34.8 +LDFLAGS += $(LDFLAGS_libxenctrl)
    34.9 +
   34.10 +SUBDIRS-y :=
   34.11 +SUBDIRS-y += include
   34.12 +SUBDIRS-y += lvm
   34.13 +SUBDIRS-y += vhd
   34.14 +SUBDIRS-y += drivers
   34.15 +SUBDIRS-y += daemon
   34.16 +
   34.17 +clean:
   34.18 +	rm -rf *.a *.so *.o *.rpm $(LIB) *~ $(DEPS) TAGS
   34.19 +
   34.20 +.PHONY: all clean install
   34.21 +all clean install: %: subdirs-%
    35.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    35.2 +++ b/tools/blktap2/README	Wed Jun 17 17:24:56 2009 -0700
    35.3 @@ -0,0 +1,321 @@
    35.4 +Blktap2 Userspace Tools + Library
    35.5 +================================
    35.6 +
    35.7 +Dutch Meyer
    35.8 +4th June 2009
    35.9 +
   35.10 +Andrew Warfield and Julian Chesterfield
   35.11 +16th June 2006
   35.12 +
   35.13 +
   35.14 +The blktap2 userspace toolkit provides a user-level disk I/O
   35.15 +interface. The blktap2 mechanism involves a kernel driver that acts
   35.16 +similarly to the existing Xen/Linux blkback driver, and a set of
   35.17 +associated user-level libraries.  Using these tools, blktap2 allows
   35.18 +virtual block devices presented to VMs to be implemented in userspace
   35.19 +and to be backed by raw partitions, files, network, etc.
   35.20 +
   35.21 +The key benefit of blktap2 is that it makes it easy and fast to write
   35.22 +arbitrary block backends, and that these user-level backends actually
   35.23 +perform very well.  Specifically:
   35.24 +
   35.25 +- Metadata disk formats such as Copy-on-Write, encrypted disks, sparse
   35.26 +  formats and other compression features can be easily implemented.
   35.27 +
   35.28 +- Accessing file-based images from userspace avoids problems related
   35.29 +  to flushing dirty pages which are present in the Linux loopback
   35.30 +  driver.  (Specifically, doing a large number of writes to an
   35.31 +  NFS-backed image don't result in the OOM killer going berserk.)
   35.32 +
   35.33 +- Per-disk handler processes enable easier userspace policing of block
   35.34 +  resources, and process-granularity QoS techniques (disk scheduling
   35.35 +  and related tools) may be trivially applied to block devices.
   35.36 +
   35.37 +- It's very easy to take advantage of userspace facilities such as
   35.38 +  networking libraries, compression utilities, peer-to-peer
   35.39 +  file-sharing systems and so on to build more complex block backends.
   35.40 +
   35.41 +- Crashes are contained -- incremental development/debugging is very
   35.42 +  fast.
   35.43 +
   35.44 +How it works (in one paragraph):
   35.45 +
   35.46 +Working in conjunction with the kernel blktap2 driver, all disk I/O
   35.47 +requests from VMs are passed to the userspace deamon (using a shared
   35.48 +memory interface) through a character device. Each active disk is
   35.49 +mapped to an individual device node, allowing per-disk processes to
   35.50 +implement individual block devices where desired.  The userspace
   35.51 +drivers are implemented using asynchronous (Linux libaio),
   35.52 +O_DIRECT-based calls to preserve the unbuffered, batched and
   35.53 +asynchronous request dispatch achieved with the existing blkback
   35.54 +code.  We provide a simple, asynchronous virtual disk interface that
   35.55 +makes it quite easy to add new disk implementations.
   35.56 +
   35.57 +As of June 2009 the current supported disk formats are:
   35.58 +
   35.59 + - Raw Images (both on partitions and in image files)
   35.60 + - Fast sharable RAM disk between VMs (requires some form of 
   35.61 +   cluster-based filesystem support e.g. OCFS2 in the guest kernel)
   35.62 + - VHD, including snapshots and sparse images
   35.63 + - Qcow, including snapshots and sparse images
   35.64 +
   35.65 +
   35.66 +Build and Installation Instructions
   35.67 +===================================
   35.68 +
   35.69 +Make to configure the blktap2 backend driver in your dom0 kernel.  It
   35.70 +will inter-operate with the existing backend and frontend drivers.  It
   35.71 +will also cohabitate with the original blktap driver.  However, some
   35.72 +formats (currently aio and qcow) will default to their blktap2
   35.73 +versions when specified in a vm configuration file.
   35.74 +
   35.75 +To build the tools separately, "make && make install" in
   35.76 +tools/blktap2.
   35.77 +
   35.78 +
   35.79 +Using the Tools
   35.80 +===============
   35.81 +
   35.82 +Preparing an image for boot:
   35.83 +
   35.84 +The userspace disk agent is configured to start automatically via xend
   35.85 +
   35.86 +Customize the VM config file to use the 'tap:tapdisk' handler,
   35.87 +followed by the driver type. e.g. for a raw image such as a file or
   35.88 +partition:
   35.89 +
   35.90 +disk = ['tap:tapdisk:aio:<FILENAME>,sda1,w']
   35.91 +
   35.92 +Alternatively, the vhd-util tool (installed with make install, or in
   35.93 +/blktap2/vhd) can be used to build sparse copy-on-write vhd images.
   35.94 +
   35.95 +For example, to build a sparse image -
   35.96 +  vhd-util create -n MyVHDFile -s 1024
   35.97 +
   35.98 +This creates a sparse 1GB file named "MyVHDFile" that can be mounted
   35.99 +and populated with data.
  35.100 +
  35.101 +One can also base the image on a raw file -
  35.102 +  vhd-util snapshot -n MyVHDFile -p SomeRawFile -m
  35.103 +
  35.104 +This creates a sparse VHD file named "MyVHDFile" using "SomeRawFile"
  35.105 +as a parent image.  Copy-on-write semantics ensure that writes will be
  35.106 +stored in "MyVHDFile" while reads will be directed to the most
  35.107 +recently written version of the data, either in "MyVHDFile" or
  35.108 +"SomeRawFile" as is appropriate.  Other options exist as well, consult
  35.109 +the vhd-util application for the complete set of VHD tools.
  35.110 +
  35.111 +VHD files can be mounted automatically in a guest similarly to the
  35.112 +above AIO example simply by specifying the vhd driver.
  35.113 +
  35.114 +disk = ['tap:tapdisk:vhd:<VHD FILENAME>,sda1,w']
  35.115 +
  35.116 +
  35.117 +Snapshots:
  35.118 +
  35.119 +Pausing a guest will also plug the corresponding IO queue for blktap2
  35.120 +devices and stop blktap2 drivers.  This can be used to implement a
  35.121 +safe live snapshot of qcow and vhd disks.  An example script "xmsnap"
  35.122 +is shown in the tools/blktap2/drivers directory.  This script will
  35.123 +perform a live snapshot of a qcow disk.  VHD files can use the
  35.124 +"vhd-util snapshot" tool discussed above.  If this snapshot command is
  35.125 +applied to a raw file mounted with tap:tapdisk:AIO, include the -m
  35.126 +flag and the driver will be reloaded as VHD.  If applied to an already
  35.127 +mounted VHD file, omit the -m flag.
  35.128 +
  35.129 +
  35.130 +Mounting images in Dom0 using the blktap2 driver
  35.131 +===============================================
  35.132 +Tap (and blkback) disks are also mountable in Dom0 without requiring an
  35.133 +active VM to attach. 
  35.134 +
  35.135 +The syntax is -
  35.136 +  tapdisk2 -n <type>:<full path to file>
  35.137 +
  35.138 +For example -
  35.139 +  tapdisk2  -n aio:/home/images/rawFile.img
  35.140 +
  35.141 +When successful the location of the new device will be provided by
  35.142 +tapdisk2 to stdout and tapdisk2 will terminate.  From that point
  35.143 +forward control of the device is provided through sysfs in the
  35.144 +directory-
  35.145 +
  35.146 +  /sys/class/blktap2/blktap#/
  35.147 +
  35.148 +Where # is a blktap2 device number present in the path that tapdisk2
  35.149 +printed before terminating.  The sysfs interface is largely intuitive,
  35.150 +for example, to remove tap device 0 one would-
  35.151 +  
  35.152 +  echo 1 > /sys/class/blktap2/blktap0/remove
  35.153 +
  35.154 +Similarly, a pause control is available, which is can be used to plug
  35.155 +the request queue of a live running guest.
  35.156 +
  35.157 +Previous versions of blktap mounted devices in dom0 by using blkfront
  35.158 +in dom0 and the xm block-attach command.  This approach is still
  35.159 +available, though slightly more cumbersome.
  35.160 +
  35.161 +
  35.162 +Tapdisk Development
  35.163 +===============================================
  35.164 +
  35.165 +People regularly ask how to develop their own tapdisk drivers, and
  35.166 +while it has not yet been well documented, the process is relatively
  35.167 +easy.  Here I will provide a brief overview.  The best reference, of
  35.168 +course, comes from the existing drivers.  Specifically,
  35.169 +blktap2/drivers/block-ram.c and blktap2/drivers/block-aio.c provide
  35.170 +the clearest examples of simple drivers.
  35.171 + 
  35.172 +
  35.173 +Setup:
  35.174 +
  35.175 +First you need to register your new driver with blktap. This is done
  35.176 +in disktypes.h.  There are five things that you must do.  To
  35.177 +demonstrate, I will create a disk called "mynewdisk", you can name
  35.178 +yours freely.
  35.179 +
  35.180 +1) Forward declare an instance of struct tap_disk.
  35.181 +
  35.182 +e.g. -  
  35.183 +  extern struct tap_disk tapdisk_mynewdisk;
  35.184 +
  35.185 +2) Claim one of the unused disk type numbers, take care to observe the
  35.186 +MAX_DISK_TYPES macro, increasing the number if necessary.
  35.187 +
  35.188 +e.g. -
  35.189 +  #define DISK_TYPE_MYNEWDISK         10
  35.190 +
  35.191 +3) Create an instance of disk_info_t.  The bulk of this file contains examples of these.
  35.192 +
  35.193 +e.g. -
  35.194 +  static disk_info_t mynewdisk_disk = {
  35.195 +          DISK_TYPE_MYNEWDISK,
  35.196 +          "My New Disk (mynewdisk)",
  35.197 +          "mynewdisk",
  35.198 +          0,
  35.199 +  #ifdef TAPDISK
  35.200 +          &tapdisk_mynewdisk,
  35.201 +  #endif
  35.202 +  };
  35.203 +
  35.204 +A few words about what these mean.  The first field must be the disk
  35.205 +type number you claimed in step (2).  The second field is a string
  35.206 +describing your disk, and may contain any relevant info.  The third
  35.207 +field is the name of your disk as will be used by the tapdisk2 utility
  35.208 +and xend (for example tapdisk2 -n mynewdisk:/path/to/disk.image, or in
  35.209 +your xm create config file).  The forth is binary and determines
  35.210 +whether you will have one instance of your driver, or many.  Here, a 1
  35.211 +means that your driver is a singleton and will coordinate access to
  35.212 +any number of tap devices.  0 is more common, meaning that you will
  35.213 +have one driver for each device that is created.  The final field
  35.214 +should contain a reference to the struct tap_disk you created in step
  35.215 +(1).
  35.216 +
  35.217 +4) Add a reference to your disk info structure (from step (3)) to the
  35.218 +dtypes array.  Take care here - you need to place it in the position
  35.219 +corresponding to the device type number you claimed in step (2).  So
  35.220 +we would place &mynewdisk_disk in dtypes[10].  Look at the other
  35.221 +devices in this array and pad with "&null_disk," as necessary.
  35.222 +
  35.223 +5) Modify the xend python scripts.  You need to add your disk name to
  35.224 +the list of disks that xend recognizes.
  35.225 +
  35.226 +edit:
  35.227 +  tools/python/xen/xend/server/BlktapController.py
  35.228 +
  35.229 +And add your disk to the "blktap_disk_types" array near the top of
  35.230 +your file.  Use the same name you specified in the third field of step
  35.231 +(3).  The order of this list is not important.
  35.232 +
  35.233 +
  35.234 +Now your driver is ready to be written.  Create a block-mynewdisk.c in
  35.235 +tools/blktap2/drivers and add it to the Makefile.
  35.236 +
  35.237 +
  35.238 +Development:
  35.239 +
  35.240 +Copying block-aio.c and block-ram.c would be a good place to start.
  35.241 +Read those files as you go through this, I will be assisting by
  35.242 +commenting on a few useful functions and structures.
  35.243 +
  35.244 +struct tap_disk:
  35.245 +
  35.246 +Remember the forward declaration in step (1) of the setup phase above?
  35.247 +Now is the time to make that structure a reality.  This structure
  35.248 +contains a list of function pointers for all the routines that will be
  35.249 +asked of your driver.  Currently the required functions are open,
  35.250 +close, read, write, get_parent_id, validate_parent, and debug.
  35.251 +
  35.252 +e.g. -
  35.253 +  struct tap_disk tapdisk_mynewdisk = {
  35.254 +          .disk_type          = "tapdisk_mynewdisk",
  35.255 +          .flags              = 0,
  35.256 +          .private_data_size  = sizeof(struct tdmynewdisk_state),
  35.257 +          .td_open            = tdmynewdisk_open,
  35.258 +                 ....
  35.259 +
  35.260 +The private_data_size field is used to provide a structure to store
  35.261 +the state of your device.  It is very likely that you will want
  35.262 +something here, but you are free to design whatever structure you
  35.263 +want.  Blktap will allocate this space for you, you just need to tell
  35.264 +it how much space you want.
  35.265 +
  35.266 +
  35.267 +tdmynewdisk_open:
  35.268 +
  35.269 +This is the open routine.  The first argument is a structure
  35.270 +representing your driver.  Two fields in this array are
  35.271 +interesting. 
  35.272 +
  35.273 +driver->data will contain a block of memory of the size your requested
  35.274 +in in the .private_data_size field of your struct tap_disk (above).
  35.275 +
  35.276 +driver->info contains a structure that details information about your
  35.277 +disk.  You need to fill this out.  By convention this is done with a
  35.278 +_get_image_info() function.  Assign a size (the total number of
  35.279 +sectors), sector_size (the size of each sector in bytes, and set
  35.280 +driver->info->info to 0.
  35.281 +
  35.282 +The second parameter contains the name that was specified in the
  35.283 +creation of your device, either through xend, or on the command line
  35.284 +with tapdisk2.  Usually this specifies a file that you will open in
  35.285 +this routine.  The final parameter, flags, contains one of a number of
  35.286 +flags specified in tapdisk.h that may change the way you treat the
  35.287 +disk.
  35.288 +
  35.289 +
  35.290 +_queue_read/write:
  35.291 +
  35.292 +These are your read and write operations.  What you do here will
  35.293 +depend on your disk, but you should do exactly one of- 
  35.294 +
  35.295 +1) call td_complete_request with either error or success code.
  35.296 +
  35.297 +2) Call td_forward_request, which will forward the request to the next
  35.298 +driver in the stack.
  35.299 +
  35.300 +3) Queue the request for asynchronous processing with
  35.301 +td_prep_read/write.  In doing so, you will also register a callback
  35.302 +for request completion.  When the request completes you must do one of
  35.303 +options (1) or (2) above.  Finally, call td_queue_tiocb to submit the
  35.304 +request to a wait queue.
  35.305 +
  35.306 +The above functions are defined in tapdisk-interface.c.  If you don't
  35.307 +use them as specified you will run into problems as your driver will
  35.308 +fail to inform blktap of the state of requests that have been
  35.309 +submitted.  Blktap keeps track of all requests and does not like losing track.
  35.310 +
  35.311 +
  35.312 +_close, _get_parent_id, _validate_parent:
  35.313 +
  35.314 +These last few tend to be very routine.  _close is called when the
  35.315 +device is closed, and also when it is paused (in this case, open will
  35.316 +also be called later).  The other functions are used in stacking
  35.317 +drivers.  Most often drivers will return TD_NO_PARENT and -EINVAL,
  35.318 +respectively.
  35.319 +
  35.320 +
  35.321 +
  35.322 +
  35.323 +
  35.324 +
    36.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    36.2 +++ b/tools/blktap2/daemon/Makefile	Wed Jun 17 17:24:56 2009 -0700
    36.3 @@ -0,0 +1,54 @@
    36.4 +XEN_ROOT=../../../
    36.5 +BLKTAP_ROOT := ..
    36.6 +include $(XEN_ROOT)/tools/Rules.mk
    36.7 +
    36.8 +SUBDIRS-y    :=
    36.9 +SUBDIRS-y    += lib
   36.10 +
   36.11 +IBIN          = blktapctrl
   36.12 +INST_DIR      = $(SBINDIR)
   36.13 +
   36.14 +LIBS         := -lxenstore
   36.15 +LIBS         += -Llib
   36.16 +LIBS         += -lblktap
   36.17 +LIBS         += -lxenctrl
   36.18 +
   36.19 +ifneq ($(USE_SYSTEM_LIBRARIES),y)
   36.20 +INCLUDES     += -I $(XEN_LIBXC) -I $(XEN_XENSTORE)
   36.21 +LIBS         += -L $(XEN_LIBXC) -L $(XEN_XENSTORE)
   36.22 +endif
   36.23 +
   36.24 +OBJS         := tapdisk-dispatch-common.o
   36.25 +OBJS         += tapdisk-channel.o
   36.26 +
   36.27 +CFLAGS       += -Werror
   36.28 +CFLAGS       += -Wno-unused
   36.29 +CFLAGS       += -fno-strict-aliasing -fPIC
   36.30 +CFLAGS       += -Ilib -I../include -I../drivers -I../../include $(INCLUDES)
   36.31 +CFLAGS       += -D_GNU_SOURCE
   36.32 +CFLAGS       += -g
   36.33 +
   36.34 +# Get gcc to generate the dependencies for us.
   36.35 +CFLAGS       += -Wp,-MD,.$(@F).d
   36.36 +DEPS          = .*.d
   36.37 +
   36.38 +all: subdirs-all $(IBIN)
   36.39 +
   36.40 +LIBS_DEPENDS := lib/libblktap.a lib/libblktap.so
   36.41 +$(LIBS_DEPENDS):subdirs-all
   36.42 +
   36.43 +blktapctrl: tapdisk-daemon.c $(OBJS) $(LIBS_DEPENDS)
   36.44 +	$(CC) $(CFLAGS) -o blktapctrl tapdisk-daemon.c $(LDFLAGS) $(LIBS) $(OBJS)
   36.45 +
   36.46 +install: all
   36.47 +	$(MAKE) subdirs-install
   36.48 +	$(INSTALL_DIR) -p $(DESTDIR)$(INST_DIR)
   36.49 +	$(INSTALL_PROG) $(IBIN) $(DESTDIR)$(INST_DIR)
   36.50 +
   36.51 +clean: subdirs-clean
   36.52 +	rm -rf *.o *~ $(IBIN) $(DEPS) xen TAGS
   36.53 +
   36.54 +.PHONY: all clean install blktapctrl
   36.55 +
   36.56 +-include $(DEPS)
   36.57 +
    37.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    37.2 +++ b/tools/blktap2/daemon/lib/Makefile	Wed Jun 17 17:24:56 2009 -0700
    37.3 @@ -0,0 +1,69 @@
    37.4 +XEN_ROOT=../../../../
    37.5 +BLKTAP_ROOT := ../../
    37.6 +include $(XEN_ROOT)/tools/Rules.mk
    37.7 +
    37.8 +MAJOR    = 3.1
    37.9 +MINOR    = 0
   37.10 +SONAME   = libblktap.so.$(MAJOR)
   37.11 +
   37.12 +BLKTAP_INSTALL_DIR = /usr/sbin
   37.13 +
   37.14 +LIBS     := -lxenstore
   37.15 +
   37.16 +ifneq ($(USE_SYSTEM_LIBRARIES),y)
   37.17 +INCLUDES += -I $(XEN_LIBXC) -I $(XEN_XENSTORE)
   37.18 +LIBS     += -L$(XEN_XENSTORE)
   37.19 +endif
   37.20 +
   37.21 +SRCS     :=
   37.22 +SRCS     += xs_api.c
   37.23 +CFLAGS   += -Werror
   37.24 +CFLAGS   += -Wno-unused
   37.25 +CFLAGS   += -fno-strict-aliasing -fPIC
   37.26 +# get asprintf():
   37.27 +CFLAGS   += -D _GNU_SOURCE
   37.28 +CFLAGS   += -g
   37.29 +CFLAGS   += -I../../include -I../../../include/ $(INCLUDES) 
   37.30 +
   37.31 +
   37.32 +# Get gcc to generate the dependencies for us.
   37.33 +CFLAGS  += -Wp,-MD,.$(@F).d
   37.34 +DEPS     = .*.d
   37.35 +
   37.36 +OBJS     = $(patsubst %.c,%.o,$(SRCS))
   37.37 +IBINS   :=
   37.38 +
   37.39 +LIB      = libblktap.a libblktap.so.$(MAJOR).$(MINOR)
   37.40 +
   37.41 +.PHONY: all
   37.42 +all: build
   37.43 +
   37.44 +.PHONY: build
   37.45 +build: libblktap.a
   37.46 +
   37.47 +.PHONY: libblktap
   37.48 +libblktap: libblktap.a
   37.49 +
   37.50 +install: all
   37.51 +	$(INSTALL_DIR) -p $(DESTDIR)$(LIBDIR)
   37.52 +	$(INSTALL_DATA) $(LIB) $(DESTDIR)$(LIBDIR)
   37.53 +	ln -sf libblktap.so.$(MAJOR).$(MINOR) $(DESTDIR)$(LIBDIR)/libblktap.so.$(MAJOR)
   37.54 +	ln -sf libblktap.so.$(MAJOR) $(DESTDIR)$(LIBDIR)/libblktap.so
   37.55 +
   37.56 +clean:
   37.57 +	rm -rf *.a *.so* *.o *.rpm $(LIB) *~ $(DEPS) xen TAGS
   37.58 +
   37.59 +libblktap.a: $(OBJS) 
   37.60 +	$(CC) $(CFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,$(SONAME) $(SHLIB_CFLAGS) \
   37.61 +	      $(LDFLAGS) -o libblktap.so.$(MAJOR).$(MINOR) $^ $(LIBS)
   37.62 +	ln -sf libblktap.so.$(MAJOR).$(MINOR) libblktap.so.$(MAJOR)
   37.63 +	ln -sf libblktap.so.$(MAJOR) libblktap.so
   37.64 +	$(AR) rc $@ libblktap.so
   37.65 +
   37.66 +.PHONY: TAGS all build clean install libblktap
   37.67 +
   37.68 +TAGS:
   37.69 +	etags -t $(SRCS) *.h
   37.70 +
   37.71 +-include $(DEPS)
   37.72 +
    38.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    38.2 +++ b/tools/blktap2/daemon/lib/xs_api.c	Wed Jun 17 17:24:56 2009 -0700
    38.3 @@ -0,0 +1,323 @@
    38.4 +/*
    38.5 + * xs_api.c
    38.6 + * 
    38.7 + * blocktap interface functions to xenstore
    38.8 + *
    38.9 + * (c) 2005 Andrew Warfield and Julian Chesterfield
   38.10 + *
   38.11 + *
   38.12 + * This program is free software; you can redistribute it and/or
   38.13 + * modify it under the terms of the GNU General Public License version 2
   38.14 + * as published by the Free Software Foundation; or, when distributed
   38.15 + * separately from the Linux kernel or incorporated into other
   38.16 + * software packages, subject to the following license:
   38.17 + *
   38.18 + * Permission is hereby granted, free of charge, to any person obtaining a copy
   38.19 + * of this source file (the "Software"), to deal in the Software without
   38.20 + * restriction, including without limitation the rights to use, copy, modify,
   38.21 + * merge, publish, distribute, sublicense, and/or sell copies of the Software,
   38.22 + * and to permit persons to whom the Software is furnished to do so, subject to
   38.23 + * the following conditions:
   38.24 + *
   38.25 + * The above copyright notice and this permission notice shall be included in
   38.26 + * all copies or substantial portions of the Software.
   38.27 + *
   38.28 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   38.29 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   38.30 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   38.31 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   38.32 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   38.33 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
   38.34 + * IN THE SOFTWARE.
   38.35 + *
   38.36 + */
   38.37 +
   38.38 +#include <time.h>
   38.39 +#include <stdio.h>
   38.40 +#include <errno.h>
   38.41 +#include <stdlib.h>
   38.42 +#include <string.h>
   38.43 +#include <stdarg.h>
   38.44 +#include <xs.h>
   38.45 +
   38.46 +#include "xs_api.h"
   38.47 +#include "blktaplib.h"
   38.48 +
   38.49 +#define DOMNAME "Domain-0"
   38.50 +#define BASE_DEV_VAL 2048
   38.51 +
   38.52 +static LIST_HEAD(watches);
   38.53 +
   38.54 +int
   38.55 +xs_gather(struct xs_handle *xs, const char *dir, ...)
   38.56 +{
   38.57 +	va_list ap;
   38.58 +	const char *name;
   38.59 +	char *path, **e;
   38.60 +	int ret = 0, num,i;
   38.61 +	unsigned int len;
   38.62 +	xs_transaction_t xth;
   38.63 +
   38.64 +again:
   38.65 +	if ((xth = xs_transaction_start(xs)) == XBT_NULL) {
   38.66 +		DPRINTF("unable to start xs trasanction\n");
   38.67 +		ret = ENOMEM;
   38.68 +		return ret;
   38.69 +	}
   38.70 +
   38.71 +	va_start(ap, dir);
   38.72 +	while ((ret == 0) && (name = va_arg(ap, char *)) != NULL) {
   38.73 +		char *p;
   38.74 +		const char *fmt = va_arg(ap, char *);
   38.75 +		void *result = va_arg(ap, void *);
   38.76 +		
   38.77 +		if (asprintf(&path, "%s/%s", dir, name) == -1) {
   38.78 +			EPRINTF("allocation error in xs_gather!\n");
   38.79 +			ret = ENOMEM;
   38.80 +			break;
   38.81 +		}
   38.82 +
   38.83 +		p = xs_read(xs, xth, path, &len);
   38.84 +		free(path);
   38.85 +
   38.86 +		if (!p) {
   38.87 +			ret = ENOENT;
   38.88 +			break;
   38.89 +		}
   38.90 +
   38.91 +		if (fmt) {
   38.92 +			if (sscanf(p, fmt, result) == 0)
   38.93 +				ret = EINVAL;
   38.94 +			free(p);
   38.95 +		} else
   38.96 +			*(char **)result = p;
   38.97 +	}
   38.98 +
   38.99 +	va_end(ap);
  38.100 +
  38.101 +	if (!xs_transaction_end(xs, xth, ret)) {
  38.102 +		if (ret == 0 && errno == EAGAIN)
  38.103 +			goto again;
  38.104 +		else
  38.105 +			ret = errno;
  38.106 +	}
  38.107 +
  38.108 +	return ret;
  38.109 +}
  38.110 +
  38.111 +/* Single printf and write: returns -errno or 0. */
  38.112 +int
  38.113 +xs_printf(struct xs_handle *h, const char *dir,
  38.114 +	  const char *node, const char *fmt, ...)
  38.115 +{
  38.116 +	int ret;
  38.117 +	va_list ap;
  38.118 +	char *buf, *path;
  38.119 +
  38.120 +	va_start(ap, fmt);
  38.121 +	ret = vasprintf(&buf, fmt, ap);
  38.122 +	va_end(ap);
  38.123 +
  38.124 +	if (ret == -1)
  38.125 +		return 0;
  38.126 +
  38.127 +	ret = asprintf(&path, "%s/%s", dir, node);
  38.128 +	if (ret == -1) {
  38.129 +		free(buf);
  38.130 +		return 0;
  38.131 +	}
  38.132 +
  38.133 +	ret = xs_write(h, XBT_NULL, path, buf, strlen(buf)+1);
  38.134 +
  38.135 +	free(buf);
  38.136 +	free(path);
  38.137 +
  38.138 +	return ret;
  38.139 +}
  38.140 +
  38.141 +int
  38.142 +xs_exists(struct xs_handle *h, const char *path)
  38.143 +{
  38.144 +	char **d;
  38.145 +	unsigned int num;
  38.146 +	xs_transaction_t xth;
  38.147 +
  38.148 +	if ((xth = xs_transaction_start(h)) == XBT_NULL) {
  38.149 +		EPRINTF("unable to start xs trasanction\n");
  38.150 +		return 0;
  38.151 +	}
  38.152 +
  38.153 +	d = xs_directory(h, xth, path, &num);
  38.154 +	xs_transaction_end(h, xth, 0);
  38.155 +	if (!d)
  38.156 +		return 0;
  38.157 +
  38.158 +	free(d);
  38.159 +	return 1;
  38.160 +}
  38.161 +
  38.162 +
  38.163 +
  38.164 +/**
  38.165 + * This assumes that the domain name we are looking for is unique. 
  38.166 + * Name parameter Domain-0 
  38.167 + */
  38.168 +char *
  38.169 +get_dom_domid(struct xs_handle *h)
  38.170 +{
  38.171 +	int i;
  38.172 +	xs_transaction_t xth;
  38.173 +	unsigned int num, len;
  38.174 +	char *val, *path, *domid, **e;
  38.175 +
  38.176 +	e     = NULL;
  38.177 +	domid = NULL;
  38.178 +
  38.179 +	if ((xth = xs_transaction_start(h)) == XBT_NULL) {
  38.180 +		EPRINTF("unable to start xs trasanction\n");
  38.181 +		return NULL;
  38.182 +	}
  38.183 +
  38.184 +	e = xs_directory(h, xth, "/local/domain", &num);
  38.185 +	if (e == NULL)
  38.186 +		goto done;
  38.187 +
  38.188 +	for (i = 0; (i < num) && (domid == NULL); i++) {
  38.189 +		if (asprintf(&path, "/local/domain/%s/name", e[i]) == -1)
  38.190 +			break;
  38.191 +
  38.192 +		val = xs_read(h, xth, path, &len);
  38.193 +		free(path);
  38.194 +		if (val == NULL)
  38.195 +			continue;
  38.196 +
  38.197 +		if (strcmp(val, DOMNAME) == 0) {
  38.198 +			/* match! */
  38.199 +			if (asprintf(&path, 
  38.200 +				     "/local/domain/%s/domid", e[i]) == -1) {
  38.201 +				free(val);
  38.202 +				break;
  38.203 +			}
  38.204 +			domid = xs_read(h, xth, path, &len);
  38.205 +			free(path);
  38.206 +		}
  38.207 +		free(val);
  38.208 +	}
  38.209 +
  38.210 + done:
  38.211 +	xs_transaction_end(h, xth, 0);
  38.212 +	free(e);
  38.213 +	return domid;
  38.214 +}
  38.215 +
  38.216 +/*
  38.217 + * a little paranoia: we don't just trust token
  38.218 + */
  38.219 +static struct xenbus_watch *find_watch(const char *token)
  38.220 +{
  38.221 +	int ret;
  38.222 +	long nonce;
  38.223 +	unsigned long addr;
  38.224 +	struct xenbus_watch *i, *cmp;
  38.225 +
  38.226 +	ret = sscanf(token, "%lX:%lX", &addr, &nonce);
  38.227 +	if (ret != 2) {
  38.228 +		EPRINTF("invalid watch token %s\n", token);
  38.229 +		return NULL;
  38.230 +	}
  38.231 +
  38.232 +	cmp = (struct xenbus_watch *)addr;
  38.233 +	list_for_each_entry(i, &watches, list)
  38.234 +		if (i == cmp && i->nonce == nonce)
  38.235 +			return i;
  38.236 +
  38.237 +	return NULL;
  38.238 +}
  38.239 +
  38.240 +/*
  38.241 + * Register callback to watch this node;
  38.242 + * like xs_watch, return 0 on failure
  38.243 + */
  38.244 +int register_xenbus_watch(struct xs_handle *h, struct xenbus_watch *watch)
  38.245 +{
  38.246 +	/* Pointer in ascii is the token. */
  38.247 +	char token[(sizeof(watch) + sizeof(long)) * 2 + 2];
  38.248 +
  38.249 +	/* 1-second granularity should suffice here */
  38.250 +	watch->nonce = time(NULL);
  38.251 +
  38.252 +	sprintf(token, "%lX:%lX", (long)watch, watch->nonce);
  38.253 +	if (find_watch(token)) {
  38.254 +		EPRINTF("watch collision!\n");
  38.255 +		return -EINVAL;
  38.256 +	}
  38.257 +
  38.258 +	if (!xs_watch(h, watch->node, token)) {
  38.259 +		EPRINTF("unable to set watch!\n");
  38.260 +		return -EINVAL;
  38.261 +	}
  38.262 +
  38.263 +	list_add(&watch->list, &watches);
  38.264 +
  38.265 +	return 0;
  38.266 +}
  38.267 +
  38.268 +int unregister_xenbus_watch(struct xs_handle *h, struct xenbus_watch *watch)
  38.269 +{
  38.270 +	char token[(sizeof(watch) + sizeof(long)) * 2 + 2];
  38.271 +
  38.272 +	sprintf(token, "%lX:%lX", (long)watch, watch->nonce);
  38.273 +	if (!find_watch(token)) {
  38.274 +		EPRINTF("no such watch!\n");
  38.275 +		return -EINVAL;
  38.276 +	}
  38.277 +
  38.278 +	if (!xs_unwatch(h, watch->node, token))
  38.279 +		EPRINTF("XENBUS Failed to release watch %s\n", watch->node);
  38.280 +
  38.281 +	list_del(&watch->list);
  38.282 +
  38.283 +	return 0;
  38.284 +}
  38.285 +
  38.286 +/*
  38.287 + * re-register callbacks to all watches
  38.288 + */
  38.289 +void reregister_xenbus_watches(struct xs_handle *h)
  38.290 +{
  38.291 +	struct xenbus_watch *watch;
  38.292 +	char token[(sizeof(watch) + sizeof(long)) * 2 + 2];
  38.293 +
  38.294 +	list_for_each_entry(watch, &watches, list) {
  38.295 +		sprintf(token, "%lX:%lX", (long)watch, watch->nonce);
  38.296 +		xs_watch(h, watch->node, token);
  38.297 +	}
  38.298 +}
  38.299 +
  38.300 +/*
  38.301 + * based on watch_thread() 
  38.302 + */
  38.303 +int xs_fire_next_watch(struct xs_handle *h)
  38.304 +{
  38.305 +	unsigned int num;
  38.306 +	struct xenbus_watch *w;
  38.307 +	char **res, *token, *node = NULL;
  38.308 +
  38.309 +	res = xs_read_watch(h, &num);
  38.310 +	if (res == NULL) 
  38.311 +		return -EAGAIN; /* in O_NONBLOCK, read_watch returns 0... */
  38.312 +
  38.313 +	node  = res[XS_WATCH_PATH];
  38.314 +	token = res[XS_WATCH_TOKEN];
  38.315 +	DPRINTF("got watch %s on %s\n", token, node);
  38.316 +
  38.317 +	w = find_watch(token);
  38.318 +	if (w) 
  38.319 +		w->callback(h, w, node);
  38.320 +
  38.321 +	DPRINTF("handled watch %s on %s\n", token, node);
  38.322 +
  38.323 +	free(res);
  38.324 +
  38.325 +	return 1;
  38.326 +}
    39.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    39.2 +++ b/tools/blktap2/daemon/lib/xs_api.h	Wed Jun 17 17:24:56 2009 -0700
    39.3 @@ -0,0 +1,62 @@
    39.4 +/*
    39.5 + * xs_api.h
    39.6 + *
    39.7 + * (c) 2005 Andrew Warfield and Julian Chesterfield
    39.8 + *
    39.9 + *
   39.10 + * This program is free software; you can redistribute it and/or
   39.11 + * modify it under the terms of the GNU General Public License version 2
   39.12 + * as published by the Free Software Foundation; or, when distributed
   39.13 + * separately from the Linux kernel or incorporated into other
   39.14 + * software packages, subject to the following license:
   39.15 + *
   39.16 + * Permission is hereby granted, free of charge, to any person obtaining a copy
   39.17 + * of this source file (the "Software"), to deal in the Software without
   39.18 + * restriction, including without limitation the rights to use, copy, modify,
   39.19 + * merge, publish, distribute, sublicense, and/or sell copies of the Software,
   39.20 + * and to permit persons to whom the Software is furnished to do so, subject to
   39.21 + * the following conditions:
   39.22 + *
   39.23 + * The above copyright notice and this permission notice shall be included in
   39.24 + * all copies or substantial portions of the Software.
   39.25 + *
   39.26 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   39.27 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   39.28 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   39.29 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   39.30 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   39.31 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
   39.32 + * IN THE SOFTWARE.
   39.33 + */
   39.34 +
   39.35 +#ifndef _XS_API_H_
   39.36 +#define _XS_API_H_
   39.37 +
   39.38 +#include <xs.h>
   39.39 +
   39.40 +#include "list.h"
   39.41 +
   39.42 +struct xenbus_watch
   39.43 +{
   39.44 +        struct list_head  list;
   39.45 +        char             *node;
   39.46 +	void             *data;
   39.47 +	long              nonce;
   39.48 +        void (*callback) (struct xs_handle *h, 
   39.49 +			  struct xenbus_watch *, 
   39.50 +			  const  char *node);
   39.51 +};
   39.52 +
   39.53 +int xs_gather(struct xs_handle *xs, const char *dir, ...);
   39.54 +int xs_printf(struct xs_handle *h, const char *dir, const char *node, 
   39.55 +	      const char *fmt, ...) __attribute__((format(printf, 4, 5)));
   39.56 +int xs_exists(struct xs_handle *h, const char *path);
   39.57 +char *get_dom_domid(struct xs_handle *h);
   39.58 +int convert_dev_name_to_num(char *name);
   39.59 +
   39.60 +int register_xenbus_watch(struct xs_handle *h, struct xenbus_watch *watch);
   39.61 +int unregister_xenbus_watch(struct xs_handle *h, struct xenbus_watch *watch);
   39.62 +void reregister_xenbus_watches(struct xs_handle *h);
   39.63 +int xs_fire_next_watch(struct xs_handle *h);
   39.64 +
   39.65 +#endif
    40.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    40.2 +++ b/tools/blktap2/daemon/tapdisk-channel.c	Wed Jun 17 17:24:56 2009 -0700
    40.3 @@ -0,0 +1,1367 @@
    40.4 +/* Copyright (c) 2008, XenSource Inc.
    40.5 + * All rights reserved.
    40.6 + *
    40.7 + * Redistribution and use in source and binary forms, with or without
    40.8 + * modification, are permitted provided that the following conditions are met:
    40.9 + *     * Redistributions of source code must retain the above copyright
   40.10 + *       notice, this list of conditions and the following disclaimer.
   40.11 + *     * Redistributions in binary form must reproduce the above copyright
   40.12 + *       notice, this list of conditions and the following disclaimer in the
   40.13 + *       documentation and/or other materials provided with the distribution.
   40.14 + *     * Neither the name of XenSource Inc. nor the names of its contributors
   40.15 + *       may be used to endorse or promote products derived from this software
   40.16 + *       without specific prior written permission.
   40.17 + *
   40.18 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   40.19 + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   40.20 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   40.21 + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
   40.22 + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
   40.23 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   40.24 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
   40.25 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   40.26 + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   40.27 + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   40.28 + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   40.29 +*/
   40.30 +#include <stdio.h>
   40.31 +#include <errno.h>
   40.32 +#include <fcntl.h>
   40.33 +#include <stdlib.h>
   40.34 +#include <unistd.h>
   40.35 +#include <string.h>
   40.36 +#include <stdarg.h>
   40.37 +#include <sys/wait.h>
   40.38 +#include <sys/ioctl.h>
   40.39 +#include <sys/resource.h>
   40.40 +
   40.41 +#include <xs.h>
   40.42 +#include "disktypes.h"
   40.43 +#include "tapdisk-dispatch.h"
   40.44 +
   40.45 +#define TAPDISK_CHANNEL_IDLE          1
   40.46 +#define TAPDISK_CHANNEL_WAIT_PID      2
   40.47 +#define TAPDISK_CHANNEL_WAIT_OPEN     3
   40.48 +#define TAPDISK_CHANNEL_WAIT_PAUSE    4
   40.49 +#define TAPDISK_CHANNEL_WAIT_RESUME   5
   40.50 +#define TAPDISK_CHANNEL_WAIT_CLOSE    6
   40.51 +#define TAPDISK_CHANNEL_CLOSED        7
   40.52 +
   40.53 +static void tapdisk_channel_error(tapdisk_channel_t *,
   40.54 +				  const char *fmt, ...)
   40.55 +  __attribute__((format(printf, 2, 3)));
   40.56 +static void tapdisk_channel_fatal(tapdisk_channel_t *,
   40.57 +				  const char *fmt, ...)
   40.58 +  __attribute__((format(printf, 2, 3)));
   40.59 +static int tapdisk_channel_parse_params(tapdisk_channel_t *);
   40.60 +static void tapdisk_channel_pause_event(struct xs_handle *,
   40.61 +					struct xenbus_watch *,
   40.62 +					const char *);
   40.63 +
   40.64 +static int
   40.65 +tapdisk_channel_check_uuid(tapdisk_channel_t *channel)
   40.66 +{
   40.67 +	uint32_t uuid;
   40.68 +	char *uuid_str;
   40.69 +
   40.70 +	uuid_str = xs_read(channel->xsh, XBT_NULL, channel->uuid_str, NULL);
   40.71 +	if (!uuid_str)
   40.72 +		return -errno;
   40.73 +
   40.74 +	uuid = strtoul(uuid_str, NULL, 10);
   40.75 +	free(uuid_str);
   40.76 +
   40.77 +	if (uuid != channel->cookie)
   40.78 +		return -EINVAL;
   40.79 +
   40.80 +	return 0;
   40.81 +}
   40.82 +
   40.83 +static inline int
   40.84 +tapdisk_channel_validate_watch(tapdisk_channel_t *channel, const char *path)
   40.85 +{
   40.86 +	int err, len;
   40.87 +
   40.88 +	len = strsep_len(path, '/', 7);
   40.89 +	if (len < 0)
   40.90 +		return -EINVAL;
   40.91 +
   40.92 +	err = tapdisk_channel_check_uuid(channel);
   40.93 +	if (err)
   40.94 +		return err;
   40.95 +
   40.96 +	if (!xs_exists(channel->xsh, path))
   40.97 +		return -ENOENT;
   40.98 +
   40.99 +	return 0;
  40.100 +}
  40.101 +
  40.102 +static inline int
  40.103 +tapdisk_channel_validate_message(tapdisk_channel_t *channel,
  40.104 +				 tapdisk_message_t *message)
  40.105 +{
  40.106 +	switch (message->type) {
  40.107 +	case TAPDISK_MESSAGE_PID_RSP:
  40.108 +		if (channel->state != TAPDISK_CHANNEL_WAIT_PID)
  40.109 +			return -EINVAL;
  40.110 +		break;
  40.111 +
  40.112 +	case TAPDISK_MESSAGE_OPEN_RSP:
  40.113 +		if (channel->state != TAPDISK_CHANNEL_WAIT_OPEN)
  40.114 +			return -EINVAL;
  40.115 +		break;
  40.116 +
  40.117 +	case TAPDISK_MESSAGE_PAUSE_RSP:
  40.118 +		if (channel->state != TAPDISK_CHANNEL_WAIT_PAUSE)
  40.119 +			return -EINVAL;
  40.120 +		break;
  40.121 +
  40.122 +	case TAPDISK_MESSAGE_RESUME_RSP:
  40.123 +		if (channel->state != TAPDISK_CHANNEL_WAIT_RESUME)
  40.124 +			return -EINVAL;
  40.125 +		break;
  40.126 +
  40.127 +	case TAPDISK_MESSAGE_CLOSE_RSP:
  40.128 +		if (channel->state != TAPDISK_CHANNEL_WAIT_CLOSE)
  40.129 +			return -EINVAL;
  40.130 +		break;
  40.131 +
  40.132 +	case TAPDISK_MESSAGE_RUNTIME_ERROR:
  40.133 +		/*
  40.134 +		 * runtime errors can be received at any time
  40.135 +		 * and should not affect the state machine
  40.136 +		 */
  40.137 +		return 0;
  40.138 +	}
  40.139 +
  40.140 +	channel->state = TAPDISK_CHANNEL_IDLE;
  40.141 +	return 0;
  40.142 +}
  40.143 +
  40.144 +static int
  40.145 +tapdisk_channel_send_message(tapdisk_channel_t *channel,
  40.146 +			     tapdisk_message_t *message, int timeout)
  40.147 +{
  40.148 +	fd_set writefds;
  40.149 +	struct timeval tv;
  40.150 +	int ret, len, offset;
  40.151 +
  40.152 +	tv.tv_sec  = timeout;
  40.153 +	tv.tv_usec = 0;
  40.154 +	offset     = 0;
  40.155 +	len        = sizeof(tapdisk_message_t);
  40.156 +
  40.157 +	DPRINTF("%s: sending '%s' message to %d:%d\n",
  40.158 +		channel->path, tapdisk_message_name(message->type),
  40.159 +		channel->channel_id, channel->cookie);
  40.160 +
  40.161 +	if (channel->state != TAPDISK_CHANNEL_IDLE &&
  40.162 +	    message->type  != TAPDISK_MESSAGE_CLOSE)
  40.163 +		EPRINTF("%s: writing message to non-idle channel (%d)\n",
  40.164 +			channel->path, channel->state);
  40.165 +
  40.166 +	while (offset < len) {
  40.167 +		FD_ZERO(&writefds);
  40.168 +		FD_SET(channel->write_fd, &writefds);
  40.169 +
  40.170 +		/* we don't bother reinitializing tv. at worst, it will wait a
  40.171 +		 * bit more time than expected. */
  40.172 +
  40.173 +		ret = select(channel->write_fd + 1,
  40.174 +			     NULL, &writefds, NULL, &tv);
  40.175 +		if (ret == -1)
  40.176 +			break;
  40.177 +		else if (FD_ISSET(channel->write_fd, &writefds)) {
  40.178 +			ret = write(channel->write_fd,
  40.179 +				    message + offset, len - offset);
  40.180 +			if (ret <= 0)
  40.181 +				break;
  40.182 +			offset += ret;
  40.183 +		} else
  40.184 +			break;
  40.185 +	}
  40.186 +
  40.187 +	if (offset != len) {
  40.188 +		EPRINTF("%s: error writing '%s' message to %d:%d\n",
  40.189 +			channel->path, tapdisk_message_name(message->type),
  40.190 +			channel->channel_id, channel->cookie);
  40.191 +		return -EIO;
  40.192 +	}
  40.193 +
  40.194 +	switch (message->type) {
  40.195 +	case TAPDISK_MESSAGE_PID:
  40.196 +		channel->state = TAPDISK_CHANNEL_WAIT_PID;
  40.197 +		break;
  40.198 +
  40.199 +	case TAPDISK_MESSAGE_OPEN:
  40.200 +		channel->state = TAPDISK_CHANNEL_WAIT_OPEN;
  40.201 +		break;
  40.202 +
  40.203 +	case TAPDISK_MESSAGE_PAUSE:
  40.204 +		channel->state = TAPDISK_CHANNEL_WAIT_PAUSE;
  40.205 +		break;
  40.206 +
  40.207 +	case TAPDISK_MESSAGE_RESUME:
  40.208 +		channel->state = TAPDISK_CHANNEL_WAIT_RESUME;
  40.209 +		break;
  40.210 +
  40.211 +	case TAPDISK_MESSAGE_CLOSE:
  40.212 +		channel->state = TAPDISK_CHANNEL_WAIT_CLOSE;
  40.213 +		break;
  40.214 +
  40.215 +	default:
  40.216 +		EPRINTF("%s: unrecognized message type %d\n",
  40.217 +			channel->path, message->type);
  40.218 +	}
  40.219 +
  40.220 +	return 0;
  40.221 +}
  40.222 +
  40.223 +static void
  40.224 +__tapdisk_channel_error(tapdisk_channel_t *channel,
  40.225 +			const char *fmt, va_list ap)
  40.226 +{
  40.227 +	int err;
  40.228 +	char *dir, *buf, *message;
  40.229 +
  40.230 +	err = vasprintf(&buf, fmt, ap);
  40.231 +	if (err == -1) {
  40.232 +		EPRINTF("failed to allocate error message\n");
  40.233 +		buf = NULL;
  40.234 +	}
  40.235 +
  40.236 +	if (buf)
  40.237 +		message = buf;
  40.238 +	else
  40.239 +		message = "tapdisk error";
  40.240 +
  40.241 +	EPRINTF("%s: %s\n", channel->path, message);
  40.242 +
  40.243 +	err = asprintf(&dir, "%s/tapdisk-error", channel->path);
  40.244 +	if (err == -1) {
  40.245 +		EPRINTF("%s: failed to write %s\n", __func__, message);
  40.246 +		dir = NULL;
  40.247 +		goto out;
  40.248 +	}
  40.249 +
  40.250 +	xs_write(channel->xsh, XBT_NULL, dir, message, strlen(message));
  40.251 +
  40.252 +out:
  40.253 +	free(dir);
  40.254 +	free(buf);
  40.255 +}
  40.256 +
  40.257 +static void
  40.258 +tapdisk_channel_error(tapdisk_channel_t *channel, const char *fmt, ...)
  40.259 +{
  40.260 +	va_list ap;
  40.261 +
  40.262 +	va_start(ap, fmt);
  40.263 +	__tapdisk_channel_error(channel, fmt, ap);
  40.264 +	va_end(ap);
  40.265 +}
  40.266 +
  40.267 +static void
  40.268 +tapdisk_channel_fatal(tapdisk_channel_t *channel, const char *fmt, ...)
  40.269 +{
  40.270 +	va_list ap;
  40.271 +
  40.272 +	va_start(ap, fmt);
  40.273 +	__tapdisk_channel_error(channel, fmt, ap);
  40.274 +	va_end(ap);
  40.275 +
  40.276 +	tapdisk_channel_close(channel);
  40.277 +}
  40.278 +
  40.279 +static int
  40.280 +tapdisk_channel_connect_backdev(tapdisk_channel_t *channel)
  40.281 +{
  40.282 +	int err, major, minor;
  40.283 +	char *s, *path, *devname;
  40.284 +
  40.285 +	s       = NULL;
  40.286 +	path    = NULL;
  40.287 +	devname = NULL;
  40.288 +
  40.289 +	err = ioctl(channel->blktap_fd,
  40.290 +		    BLKTAP_IOCTL_BACKDEV_SETUP, channel->minor);
  40.291 +	if (err) {
  40.292 +		err = -errno;
  40.293 +		goto fail;
  40.294 +	}
  40.295 +
  40.296 +	err = asprintf(&path, "%s/backdev-node", channel->path);
  40.297 +	if (err == -1) {
  40.298 +		path = NULL;
  40.299 +		err  = -ENOMEM;
  40.300 +		goto fail;
  40.301 +	}
  40.302 +
  40.303 +	s = xs_read(channel->xsh, XBT_NULL, path, NULL);
  40.304 +	if (!s) {
  40.305 +		err = -errno;
  40.306 +		goto fail;
  40.307 +	}
  40.308 +
  40.309 +	err = sscanf(s, "%d:%d", &major, &minor);
  40.310 +	if (err != 2) {
  40.311 +		err = -EINVAL;
  40.312 +		goto fail;
  40.313 +	}
  40.314 +
  40.315 +	err = asprintf(&devname,"%s/%s%d",
  40.316 +		       BLKTAP_DEV_DIR, BACKDEV_NAME, minor);
  40.317 +	if (err == -1) {
  40.318 +		devname = NULL;
  40.319 +		err = -ENOMEM;
  40.320 +		goto fail;
  40.321 +	}
  40.322 +
  40.323 +	err = make_blktap_device(devname, major, minor, S_IFBLK | 0600);
  40.324 +	if (err)
  40.325 +		goto fail;
  40.326 +
  40.327 +	free(path);
  40.328 +	err = asprintf(&path, "%s/backdev-path", channel->path);
  40.329 +	if (err == -1) {
  40.330 +		path = NULL;
  40.331 +		err  = -ENOMEM;
  40.332 +		goto fail;
  40.333 +	}
  40.334 +
  40.335 +	err = xs_write(channel->xsh, XBT_NULL, path, devname, strlen(devname));
  40.336 +	if (err == 0) {
  40.337 +		err = -errno;
  40.338 +		goto fail;
  40.339 +	}
  40.340 +
  40.341 +	err = 0;
  40.342 + out:
  40.343 +	free(devname);
  40.344 +	free(path);
  40.345 +	free(s);
  40.346 +	return err;
  40.347 +
  40.348 + fail:
  40.349 +	EPRINTF("backdev setup failed [%d]\n", err);
  40.350 +	goto out;
  40.351 +}
  40.352 +
  40.353 +static int
  40.354 +tapdisk_channel_complete_connection(tapdisk_channel_t *channel)
  40.355 +{
  40.356 +	int err;
  40.357 +	char *path;
  40.358 +
  40.359 +	if (!xs_printf(channel->xsh, channel->path,
  40.360 +		       "sectors", "%llu", channel->image.size)) {
  40.361 +		EPRINTF("ERROR: Failed writing sectors");
  40.362 +		return -errno;
  40.363 +	}
  40.364 +
  40.365 +	if (!xs_printf(channel->xsh, channel->path,
  40.366 +		       "sector-size", "%lu", channel->image.secsize)) {
  40.367 +		EPRINTF("ERROR: Failed writing sector-size");
  40.368 +		return -errno;
  40.369 +	}
  40.370 +
  40.371 +	if (!xs_printf(channel->xsh, channel->path,
  40.372 +		       "info", "%u", channel->image.info)) {
  40.373 +		EPRINTF("ERROR: Failed writing info");
  40.374 +		return -errno;
  40.375 +	}
  40.376 +
  40.377 +	err = tapdisk_channel_connect_backdev(channel);
  40.378 +	if (err)
  40.379 +		goto clean;
  40.380 +
  40.381 +	channel->connected = 1;
  40.382 +	return 0;
  40.383 +
  40.384 + clean:
  40.385 +	if (asprintf(&path, "%s/info", channel->path) == -1)
  40.386 +		return err;
  40.387 +
  40.388 +	if (!xs_rm(channel->xsh, XBT_NULL, path))
  40.389 +		goto clean_out;
  40.390 +
  40.391 +	free(path);
  40.392 +	if (asprintf(&path, "%s/sector-size", channel->path) == -1)
  40.393 +		return err;
  40.394 +
  40.395 +	if (!xs_rm(channel->xsh, XBT_NULL, path))
  40.396 +		goto clean_out;
  40.397 +
  40.398 +	free(path);
  40.399 +	if (asprintf(&path, "%s/sectors", channel->path) == -1)
  40.400 +		return err;
  40.401 +
  40.402 +	xs_rm(channel->xsh, XBT_NULL, path);
  40.403 +
  40.404 + clean_out:
  40.405 +	free(path);
  40.406 +	return err;
  40.407 +}
  40.408 +
  40.409 +static int
  40.410 +tapdisk_channel_send_open_request(tapdisk_channel_t *channel)
  40.411 +{
  40.412 +	int len;
  40.413 +	tapdisk_message_t message;
  40.414 +
  40.415 +	memset(&message, 0, sizeof(tapdisk_message_t));
  40.416 +
  40.417 +	len = strlen(channel->vdi_path);
  40.418 +
  40.419 +	message.type              = TAPDISK_MESSAGE_OPEN;
  40.420 +	message.cookie            = channel->cookie;
  40.421 +	message.drivertype        = channel->drivertype;
  40.422 +	message.u.params.storage  = channel->storage;
  40.423 +	message.u.params.devnum   = channel->minor;
  40.424 +	message.u.params.domid    = channel->domid;
  40.425 +	message.u.params.path_len = len;
  40.426 +	strncpy(message.u.params.path, channel->vdi_path, len);
  40.427 +
  40.428 +	if (channel->mode == 'r')
  40.429 +		message.u.params.flags |= TAPDISK_MESSAGE_FLAG_RDONLY;
  40.430 +	if (channel->shared)
  40.431 +		message.u.params.flags |= TAPDISK_MESSAGE_FLAG_SHARED;
  40.432 +
  40.433 +	/* TODO: clean this up */
  40.434 +	if (xs_exists(channel->xsh, "/local/domain/0/tapdisk/add-cache"))
  40.435 +		message.u.params.flags |= TAPDISK_MESSAGE_FLAG_ADD_CACHE;
  40.436 +	if (xs_exists(channel->xsh, "/local/domain/0/tapdisk/log-dirty"))
  40.437 +		message.u.params.flags |= TAPDISK_MESSAGE_FLAG_LOG_DIRTY;
  40.438 +
  40.439 +	return tapdisk_channel_send_message(channel, &message, 2);
  40.440 +}
  40.441 +
  40.442 +static int
  40.443 +tapdisk_channel_receive_open_response(tapdisk_channel_t *channel,
  40.444 +				      tapdisk_message_t *message)
  40.445 +{
  40.446 +	int err;
  40.447 +
  40.448 +	channel->image.size    = message->u.image.sectors;
  40.449 +	channel->image.secsize = message->u.image.sector_size;
  40.450 +	channel->image.info    = message->u.image.info;
  40.451 +
  40.452 +	err = tapdisk_channel_complete_connection(channel);
  40.453 +	if (err)
  40.454 +		goto fail;
  40.455 +
  40.456 +	/* did we receive a pause request before the connection completed? */
  40.457 +	if (channel->pause_needed) {
  40.458 +		DPRINTF("%s: deferred pause request\n", channel->path);
  40.459 +		tapdisk_channel_pause_event(channel->xsh,
  40.460 +					    &channel->pause_watch,
  40.461 +					    channel->pause_str);
  40.462 +		channel->pause_needed = 0;
  40.463 +	}
  40.464 +
  40.465 +	return 0;
  40.466 +
  40.467 +fail:
  40.468 +	tapdisk_channel_fatal(channel,
  40.469 +			      "failure completing connection: %d", err);
  40.470 +	return err;
  40.471 +}
  40.472 +
  40.473 +static int
  40.474 +tapdisk_channel_send_shutdown_request(tapdisk_channel_t *channel)
  40.475 +{
  40.476 +	tapdisk_message_t message;
  40.477 +
  40.478 +	memset(&message, 0, sizeof(tapdisk_message_t));
  40.479 +
  40.480 +	message.type       = TAPDISK_MESSAGE_CLOSE;
  40.481 +	message.drivertype = channel->drivertype;
  40.482 +	message.cookie     = channel->cookie;
  40.483 +
  40.484 +	return tapdisk_channel_send_message(channel, &message, 2);
  40.485 +}
  40.486 +
  40.487 +static int
  40.488 +tapdisk_channel_receive_shutdown_response(tapdisk_channel_t *channel,
  40.489 +					  tapdisk_message_t *message)
  40.490 +{
  40.491 +	channel->open  = 0;
  40.492 +	channel->state = TAPDISK_CHANNEL_CLOSED;
  40.493 +	tapdisk_channel_close(channel);
  40.494 +	return 0;
  40.495 +}
  40.496 +
  40.497 +static int
  40.498 +tapdisk_channel_receive_runtime_error(tapdisk_channel_t *channel,
  40.499 +				      tapdisk_message_t *message)
  40.500 +{
  40.501 +	tapdisk_channel_error(channel,
  40.502 +			      "runtime error: %s", message->u.string.text);
  40.503 +	return 0;
  40.504 +}
  40.505 +
  40.506 +static int
  40.507 +tapdisk_channel_send_pid_request(tapdisk_channel_t *channel)
  40.508 +{
  40.509 +	int err;
  40.510 +	tapdisk_message_t message;
  40.511 +
  40.512 +	memset(&message, 0, sizeof(tapdisk_message_t));
  40.513 +
  40.514 +	message.type       = TAPDISK_MESSAGE_PID;
  40.515 +	message.drivertype = channel->drivertype;
  40.516 +	message.cookie     = channel->cookie;
  40.517 +
  40.518 +	err = tapdisk_channel_send_message(channel, &message, 2);
  40.519 +
  40.520 +	if (!err)
  40.521 +		channel->open = 1;
  40.522 +
  40.523 +	return err;
  40.524 +}
  40.525 +
  40.526 +static int
  40.527 +tapdisk_channel_receive_pid_response(tapdisk_channel_t *channel,
  40.528 +				     tapdisk_message_t *message)
  40.529 +{
  40.530 +	int err;
  40.531 +
  40.532 +	channel->tapdisk_pid = message->u.tapdisk_pid;
  40.533 +
  40.534 +	DPRINTF("%s: tapdisk pid: %d\n", channel->path, channel->tapdisk_pid);
  40.535 +
  40.536 +	err = setpriority(PRIO_PROCESS, channel->tapdisk_pid, PRIO_SPECIAL_IO);
  40.537 +	if (err) {
  40.538 +		tapdisk_channel_fatal(channel,
  40.539 +				      "setting tapdisk priority: %d", err);
  40.540 +		return err;
  40.541 +	}
  40.542 +
  40.543 +	err = tapdisk_channel_send_open_request(channel);
  40.544 +	if (err) {
  40.545 +		tapdisk_channel_fatal(channel,
  40.546 +				      "sending open request: %d", err);
  40.547 +		return err;
  40.548 +	}
  40.549 +
  40.550 +	return 0;
  40.551 +}
  40.552 +
  40.553 +static int
  40.554 +tapdisk_channel_send_pause_request(tapdisk_channel_t *channel)
  40.555 +{
  40.556 +	tapdisk_message_t message;
  40.557 +
  40.558 +	memset(&message, 0, sizeof(tapdisk_message_t));
  40.559 +
  40.560 +	DPRINTF("pausing %s\n", channel->path);
  40.561 +
  40.562 +	message.type       = TAPDISK_MESSAGE_PAUSE;
  40.563 +	message.drivertype = channel->drivertype;
  40.564 +	message.cookie     = channel->cookie;
  40.565 +
  40.566 +	return tapdisk_channel_send_message(channel, &message, 2);
  40.567 +}
  40.568 +
  40.569 +static int
  40.570 +tapdisk_channel_receive_pause_response(tapdisk_channel_t *channel,
  40.571 +				       tapdisk_message_t *message)
  40.572 +{
  40.573 +	int err;
  40.574 +
  40.575 +	if (!xs_write(channel->xsh, XBT_NULL,
  40.576 +		      channel->pause_done_str, "", strlen(""))) {
  40.577 +		err = -errno;
  40.578 +		goto fail;
  40.579 +	}
  40.580 +
  40.581 +	return 0;
  40.582 +
  40.583 +fail:
  40.584 +	tapdisk_channel_fatal(channel,
  40.585 +			      "failure receiving pause response: %d\n", err);
  40.586 +	return err;
  40.587 +}
  40.588 +
  40.589 +static int
  40.590 +tapdisk_channel_send_resume_request(tapdisk_channel_t *channel)
  40.591 +{
  40.592 +	int len;
  40.593 +	tapdisk_message_t message;
  40.594 +
  40.595 +	memset(&message, 0, sizeof(tapdisk_message_t));
  40.596 +
  40.597 +	len = strlen(channel->vdi_path);
  40.598 +
  40.599 +	DPRINTF("resuming %s\n", channel->path);
  40.600 +
  40.601 +	message.type              = TAPDISK_MESSAGE_RESUME;
  40.602 +	message.drivertype        = channel->drivertype;
  40.603 +	message.cookie            = channel->cookie;
  40.604 +	message.u.params.path_len = len;
  40.605 +	strncpy(message.u.params.path, channel->vdi_path, len);
  40.606 +
  40.607 +	return tapdisk_channel_send_message(channel, &message, 2);
  40.608 +}
  40.609 +
  40.610 +static int
  40.611 +tapdisk_channel_receive_resume_response(tapdisk_channel_t *channel,
  40.612 +					tapdisk_message_t *message)
  40.613 +{
  40.614 +	int err;
  40.615 +
  40.616 +	if (!xs_rm(channel->xsh, XBT_NULL, channel->pause_done_str)) {
  40.617 +		err = -errno;
  40.618 +		goto fail;
  40.619 +	}
  40.620 +
  40.621 +	return 0;
  40.622 +
  40.623 +fail:
  40.624 +	tapdisk_channel_fatal(channel,
  40.625 +			      "failure receiving pause response: %d", err);
  40.626 +	return err;
  40.627 +}
  40.628 +
  40.629 +static void
  40.630 +tapdisk_channel_shutdown_event(struct xs_handle *xsh,
  40.631 +			       struct xenbus_watch *watch, const char *path)
  40.632 +{
  40.633 +	int err;
  40.634 +	tapdisk_channel_t *channel;
  40.635 +
  40.636 +	channel = watch->data;
  40.637 +
  40.638 +	DPRINTF("%s: got watch on %s\n", channel->path, path);
  40.639 +
  40.640 +	if (!xs_exists(channel->xsh, channel->path)) {
  40.641 +		tapdisk_channel_close(channel);
  40.642 +		return;
  40.643 +	}
  40.644 +
  40.645 +	err = tapdisk_channel_validate_watch(channel, path);
  40.646 +	if (err) {
  40.647 +		if (err == -EINVAL)
  40.648 +			tapdisk_channel_fatal(channel, "bad shutdown watch");
  40.649 +		return;
  40.650 +	}
  40.651 +
  40.652 +	tapdisk_channel_send_shutdown_request(channel);
  40.653 +}
  40.654 +
  40.655 +static void
  40.656 +tapdisk_channel_pause_event(struct xs_handle *xsh,
  40.657 +			    struct xenbus_watch *watch, const char *path)
  40.658 +{
  40.659 +	int err, paused;
  40.660 +	tapdisk_channel_t *channel;
  40.661 +
  40.662 +	channel = watch->data;
  40.663 +
  40.664 +	DPRINTF("%s: got watch on %s\n", channel->path, path);
  40.665 +
  40.666 +	if (!xs_exists(channel->xsh, channel->path)) {
  40.667 +		tapdisk_channel_close(channel);
  40.668 +		return;
  40.669 +	}
  40.670 +
  40.671 +	/* NB: The VBD is essentially considered ready since the
  40.672 +	 * backend hotplug event ocurred, which is just after
  40.673 +	 * start-tapdisk, not after watch registration. We start
  40.674 +	 * testing xenstore keys with the very first shot, but defer
  40.675 +	 * until after connection completion. */
  40.676 +
  40.677 +	err = tapdisk_channel_validate_watch(channel, path);
  40.678 +	if (err) {
  40.679 +		if (err == -EINVAL)
  40.680 +			tapdisk_channel_fatal(channel, "bad pause watch");
  40.681 +
  40.682 +		if (err != -ENOENT)
  40.683 +			return;
  40.684 +
  40.685 +		err = 0;
  40.686 +	}
  40.687 +
  40.688 +	paused  = xs_exists(xsh, channel->pause_done_str);
  40.689 +
  40.690 +	if (xs_exists(xsh, channel->pause_str)) {
  40.691 +		/*
  40.692 +		 * Duplicate requests are a protocol validation, but
  40.693 +		 * impossible to identify if watch registration and an
  40.694 +		 * actual pause request may fire separately in close
  40.695 +		 * succession. Warn, but do not signal an error.
  40.696 +		 */
  40.697 +		int pausing = channel->state == TAPDISK_CHANNEL_WAIT_PAUSE;
  40.698 +		if (pausing || paused) {
  40.699 +			DPRINTF("Ignoring pause event for %s vbd %s\n",
  40.700 +				pausing ? "pausing" : "paused", channel->path);
  40.701 +			goto out;
  40.702 +		}
  40.703 +
  40.704 +		/* defer if tapdisk is not ready yet */
  40.705 +		if (!channel->connected) {
  40.706 +			DPRINTF("%s: deferring pause request\n", path);
  40.707 +			channel->pause_needed = 1;
  40.708 +			goto out;
  40.709 +		}
  40.710 +
  40.711 +		err = tapdisk_channel_send_pause_request(channel);
  40.712 +
  40.713 +	} else if (xs_exists(xsh, channel->pause_done_str)) {
  40.714 +		free(channel->params);
  40.715 +		channel->params   = NULL;
  40.716 +		channel->vdi_path = NULL;
  40.717 +
  40.718 +		err = xs_gather(channel->xsh, channel->path,
  40.719 +				"params", NULL, &channel->params, NULL);
  40.720 +		if (err) {
  40.721 +			EPRINTF("failure re-reading params: %d\n", err);
  40.722 +			channel->params = NULL;
  40.723 +			goto out;
  40.724 +		}
  40.725 +
  40.726 +		err = tapdisk_channel_parse_params(channel);
  40.727 +		if (err)
  40.728 +			goto out;
  40.729 +
  40.730 +		err = tapdisk_channel_send_resume_request(channel);
  40.731 +		if (err)
  40.732 +			goto out;
  40.733 +	}
  40.734 +
  40.735 +	err = 0;
  40.736 +
  40.737 +out:
  40.738 +	if (err)
  40.739 +		tapdisk_channel_error(channel, "pause event failed: %d", err);
  40.740 +}
  40.741 +
  40.742 +static int
  40.743 +tapdisk_channel_open_control_socket(char *devname)
  40.744 +{
  40.745 +	int err, fd;
  40.746 +	fd_set socks;
  40.747 +	struct timeval timeout;
  40.748 +
  40.749 +	err = mkdir(BLKTAP_CTRL_DIR, 0755);
  40.750 +	if (err == -1 && errno != EEXIST) {
  40.751 +		EPRINTF("Failure creating %s directory: %d\n",
  40.752 +			BLKTAP_CTRL_DIR, errno);
  40.753 +		return -errno;
  40.754 +	}
  40.755 +
  40.756 +	err = mkfifo(devname, S_IRWXU | S_IRWXG | S_IRWXO);
  40.757 +	if (err) {
  40.758 +		if (errno == EEXIST) {
  40.759 +			/*
  40.760 +			 * Remove fifo since it may have data from
  40.761 +			 * it's previous use --- earlier invocation
  40.762 +			 * of tapdisk may not have read all messages.
  40.763 +			 */
  40.764 +			err = unlink(devname);
  40.765 +			if (err) {
  40.766 +				EPRINTF("ERROR: unlink(%s) failed (%d)\n",
  40.767 +					devname, errno);
  40.768 +				return -errno;
  40.769 +			}
  40.770 +
  40.771 +			err = mkfifo(devname, S_IRWXU | S_IRWXG | S_IRWXO);
  40.772 +		}
  40.773 +
  40.774 +		if (err) {
  40.775 +			EPRINTF("ERROR: pipe failed (%d)\n", errno);
  40.776 +			return -errno;
  40.777 +		}
  40.778 +	}
  40.779 +
  40.780 +	fd = open(devname, O_RDWR | O_NONBLOCK);
  40.781 +	if (fd == -1) {
  40.782 +		EPRINTF("Failed to open %s\n", devname);
  40.783 +		return -errno;
  40.784 +	}
  40.785 +
  40.786 +	return fd;
  40.787 +}
  40.788 +
  40.789 +static int
  40.790 +tapdisk_channel_get_device_number(tapdisk_channel_t *channel)
  40.791 +{
  40.792 +	char *devname;
  40.793 +	domid_translate_t tr;
  40.794 +	int major, minor, err;
  40.795 +
  40.796 +	tr.domid = channel->domid;
  40.797 +        tr.busid = channel->busid;
  40.798 +
  40.799 +	minor = ioctl(channel->blktap_fd, BLKTAP_IOCTL_NEWINTF, tr);
  40.800 +	if (minor <= 0 || minor > MAX_TAP_DEV) {
  40.801 +		EPRINTF("invalid dev id: %d\n", minor);
  40.802 +		return -EINVAL;
  40.803 +	}
  40.804 +
  40.805 +	major = ioctl(channel->blktap_fd, BLKTAP_IOCTL_MAJOR, minor);
  40.806 +	if (major < 0) {
  40.807 +		EPRINTF("invalid major id: %d\n", major);
  40.808 +		return -EINVAL;
  40.809 +	}
  40.810 +
  40.811 +	err = asprintf(&devname, "%s/%s%d",
  40.812 +		       BLKTAP_DEV_DIR, BLKTAP_DEV_NAME, minor);
  40.813 +	if (err == -1) {
  40.814 +		EPRINTF("get_new_dev: malloc failed\n");
  40.815 +		return -ENOMEM;
  40.816 +	}
  40.817 +
  40.818 +	err = make_blktap_device(devname, major, minor, S_IFCHR | 0600);
  40.819 +	free(devname);
  40.820 +
  40.821 +	if (err)
  40.822 +		return err;
  40.823 +
  40.824 +	DPRINTF("Received device id %d and major %d, "
  40.825 +		"sent domid %d and be_id %d\n",
  40.826 +		minor, major, tr.domid, tr.busid);
  40.827 +
  40.828 +	channel->major = major;
  40.829 +	channel->minor = minor;
  40.830 +
  40.831 +	return 0;
  40.832 +}
  40.833 +
  40.834 +static int
  40.835 +tapdisk_channel_start_process(tapdisk_channel_t *channel,
  40.836 +			      char *write_dev, char *read_dev)
  40.837 +{
  40.838 +	pid_t child;
  40.839 +	char *argv[] = { "tapdisk", write_dev, read_dev, NULL };
  40.840 +
  40.841 +	if ((child = fork()) == -1)
  40.842 +		return -errno;
  40.843 +
  40.844 +	if (!child) {
  40.845 +		int i;
  40.846 +		for (i = 0 ; i < sysconf(_SC_OPEN_MAX) ; i++)
  40.847 +			if (i != STDIN_FILENO &&
  40.848 +			    i != STDOUT_FILENO &&
  40.849 +			    i != STDERR_FILENO)
  40.850 +				close(i);
  40.851 +
  40.852 +		execvp("tapdisk", argv);
  40.853 +		_exit(1);
  40.854 +	} else {
  40.855 +		pid_t got;
  40.856 +		do {
  40.857 +			got = waitpid(child, NULL, 0);
  40.858 +		} while (got != child);
  40.859 +	}
  40.860 +	return 0;
  40.861 +}
  40.862 +
  40.863 +static int
  40.864 +tapdisk_channel_launch_tapdisk(tapdisk_channel_t *channel)
  40.865 +{
  40.866 +	int err;
  40.867 +	char *read_dev, *write_dev;
  40.868 +
  40.869 +	read_dev          = NULL;
  40.870 +	write_dev         = NULL;
  40.871 +	channel->read_fd  = -1;
  40.872 +	channel->write_fd = -1;
  40.873 +
  40.874 +	err = tapdisk_channel_get_device_number(channel);
  40.875 +	if (err)
  40.876 +		return err;
  40.877 +
  40.878 +	err = asprintf(&write_dev,
  40.879 +		       "%s/tapctrlwrite%d", BLKTAP_CTRL_DIR, channel->minor);
  40.880 +	if (err == -1) {
  40.881 +		err = -ENOMEM;
  40.882 +		write_dev = NULL;
  40.883 +		goto fail;
  40.884 +	}
  40.885 +
  40.886 +	err = asprintf(&read_dev,
  40.887 +		       "%s/tapctrlread%d", BLKTAP_CTRL_DIR, channel->minor);
  40.888 +	if (err == -1) {
  40.889 +		err = -ENOMEM;
  40.890 +		read_dev = NULL;
  40.891 +		goto fail;
  40.892 +	}
  40.893 +
  40.894 +	channel->write_fd = tapdisk_channel_open_control_socket(write_dev);
  40.895 +	if (channel->write_fd < 0) {
  40.896 +		err = channel->write_fd;
  40.897 +		channel->write_fd = -1;
  40.898 +		goto fail;
  40.899 +	}
  40.900 +
  40.901 +	channel->read_fd = tapdisk_channel_open_control_socket(read_dev);
  40.902 +	if (channel->read_fd < 0) {
  40.903 +		err = channel->read_fd;
  40.904 +		channel->read_fd = -1;
  40.905 +		goto fail;
  40.906 +	}
  40.907 +
  40.908 +	err = tapdisk_channel_start_process(channel, write_dev, read_dev);
  40.909 +	if (err)
  40.910 +		goto fail;
  40.911 +
  40.912 +	channel->open       = 1;
  40.913 +	channel->channel_id = channel->write_fd;
  40.914 +
  40.915 +	free(read_dev);
  40.916 +	free(write_dev);
  40.917 +
  40.918 +	DPRINTF("process launched, channel = %d:%d\n",
  40.919 +		channel->channel_id, channel->cookie);
  40.920 +
  40.921 +	return tapdisk_channel_send_pid_request(channel);
  40.922 +
  40.923 +fail:
  40.924 +	free(read_dev);
  40.925 +	free(write_dev);
  40.926 +	if (channel->read_fd != -1)
  40.927 +		close(channel->read_fd);
  40.928 +	if (channel->write_fd != -1)
  40.929 +		close(channel->write_fd);
  40.930 +	return err;
  40.931 +}
  40.932 +
  40.933 +static int
  40.934 +tapdisk_channel_connect(tapdisk_channel_t *channel)
  40.935 +{
  40.936 +	int err;
  40.937 +
  40.938 +	tapdisk_daemon_find_channel(channel);
  40.939 +
  40.940 +	if (!channel->tapdisk_pid)
  40.941 +		return tapdisk_channel_launch_tapdisk(channel);
  40.942 +
  40.943 +	DPRINTF("%s: process exists: %d, channel = %d:%d\n",
  40.944 +		channel->path, channel->tapdisk_pid,
  40.945 +		channel->channel_id, channel->cookie);
  40.946 +
  40.947 +	err = tapdisk_channel_get_device_number(channel);
  40.948 +	if (err)
  40.949 +		return err;
  40.950 +
  40.951 +	return tapdisk_channel_send_pid_request(channel);
  40.952 +}
  40.953 +
  40.954 +static int
  40.955 +tapdisk_channel_init(tapdisk_channel_t *channel)
  40.956 +{
  40.957 +	int err;
  40.958 +
  40.959 +	channel->uuid_str          = NULL;
  40.960 +	channel->pause_str         = NULL;
  40.961 +	channel->pause_done_str    = NULL;
  40.962 +	channel->shutdown_str      = NULL;
  40.963 +	channel->share_tapdisk_str = NULL;
  40.964 +
  40.965 +	err = asprintf(&channel->uuid_str,
  40.966 +		       "%s/tapdisk-uuid", channel->path);
  40.967 +	if (err == -1) {
  40.968 +		channel->uuid_str = NULL;
  40.969 +		goto fail;
  40.970 +	}
  40.971 +
  40.972 +	err = asprintf(&channel->pause_str, "%s/pause", channel->path);
  40.973 +	if (err == -1) {
  40.974 +		channel->pause_str = NULL;
  40.975 +		goto fail;
  40.976 +	}
  40.977 +
  40.978 +	err = asprintf(&channel->pause_done_str,
  40.979 +		       "%s/pause-done", channel->path);
  40.980 +	if (err == -1) {
  40.981 +		channel->pause_done_str = NULL;
  40.982 +		goto fail;
  40.983 +	}
  40.984 +
  40.985 +	err = asprintf(&channel->shutdown_str,
  40.986 +		       "%s/shutdown-tapdisk", channel->path);
  40.987 +	if (err == -1) {
  40.988 +		channel->shutdown_str = NULL;
  40.989 +		goto fail;
  40.990 +	}
  40.991 +
  40.992 +	channel->share_tapdisk_str = "/local/domain/0/tapdisk/share-tapdisks";
  40.993 +
  40.994 +	return 0;
  40.995 +
  40.996 +fail:
  40.997 +	free(channel->uuid_str);
  40.998 +	free(channel->pause_str);
  40.999 +	free(channel->pause_done_str);
 40.1000 +	free(channel->shutdown_str);
 40.1001 +	channel->uuid_str          = NULL;
 40.1002 +	channel->pause_str         = NULL;
 40.1003 +	channel->pause_done_str    = NULL;
 40.1004 +	channel->shutdown_str      = NULL;
 40.1005 +	channel->share_tapdisk_str = NULL;
 40.1006 +	return -ENOMEM;
 40.1007 +}
 40.1008 +
 40.1009 +static int
 40.1010 +tapdisk_channel_set_watches(tapdisk_channel_t *channel)
 40.1011 +{
 40.1012 +	int err;
 40.1013 +
 40.1014 +	/* watch for pause events */
 40.1015 +	channel->pause_watch.node            = channel->pause_str;
 40.1016 +	channel->pause_watch.callback        = tapdisk_channel_pause_event;
 40.1017 +	channel->pause_watch.data            = channel;
 40.1018 +	err = register_xenbus_watch(channel->xsh, &channel->pause_watch);
 40.1019 +	if (err) {
 40.1020 +		channel->pause_watch.node    = NULL;
 40.1021 +		goto fail;
 40.1022 +	}
 40.1023 +
 40.1024 +	/* watch for shutdown events */
 40.1025 +	channel->shutdown_watch.node         = channel->shutdown_str;
 40.1026 +	channel->shutdown_watch.callback     = tapdisk_channel_shutdown_event;
 40.1027 +	channel->shutdown_watch.data         = channel;
 40.1028 +	err = register_xenbus_watch(channel->xsh, &channel->shutdown_watch);
 40.1029 +	if (err) {
 40.1030 +		channel->shutdown_watch.node = NULL;
 40.1031 +		goto fail;
 40.1032 +	}
 40.1033 +
 40.1034 +	return 0;
 40.1035 +
 40.1036 +fail:
 40.1037 +	if (channel->pause_watch.node) {
 40.1038 +		unregister_xenbus_watch(channel->xsh, &channel->pause_watch);
 40.1039 +		channel->pause_watch.node    = NULL;
 40.1040 +	}
 40.1041 +	if (channel->shutdown_watch.node) {
 40.1042 +		unregister_xenbus_watch(channel->xsh, &channel->shutdown_watch);
 40.1043 +		channel->shutdown_watch.node = NULL;
 40.1044 +	}
 40.1045 +	return err;
 40.1046 +}
 40.1047 +
 40.1048 +static void
 40.1049 +tapdisk_channel_get_storage_type(tapdisk_channel_t *channel)
 40.1050 +{
 40.1051 +	int err, type;
 40.1052 +	unsigned int len;
 40.1053 +	char *path, *stype;
 40.1054 +
 40.1055 +	channel->storage = TAPDISK_STORAGE_TYPE_DEFAULT;
 40.1056 +
 40.1057 +	err = asprintf(&path, "%s/sm-data/storage-type", channel->path);
 40.1058 +	if (err == -1)
 40.1059 +		return;
 40.1060 +
 40.1061 +	stype = xs_read(channel->xsh, XBT_NULL, path, &len);
 40.1062 +	if (!stype)
 40.1063 +		goto out;
 40.1064 +	else if (!strcmp(stype, "nfs"))
 40.1065 +		channel->storage = TAPDISK_STORAGE_TYPE_NFS;
 40.1066 +	else if (!strcmp(stype, "ext"))
 40.1067 +		channel->storage = TAPDISK_STORAGE_TYPE_EXT;
 40.1068 +	else if (!strcmp(stype, "lvm"))
 40.1069 +		channel->storage = TAPDISK_STORAGE_TYPE_LVM;
 40.1070 +
 40.1071 +out:
 40.1072 +	free(path);
 40.1073 +	free(stype);
 40.1074 +}
 40.1075 +
 40.1076 +static int
 40.1077 +tapdisk_channel_get_busid(tapdisk_channel_t *channel)
 40.1078 +{
 40.1079 +	int len, end;
 40.1080 +	const char *ptr;
 40.1081 +	char *tptr, num[10];
 40.1082 +
 40.1083 +	len = strsep_len(channel->path, '/', 6);
 40.1084 +	end = strlen(channel->path);
 40.1085 +	if(len < 0 || end < 0) {
 40.1086 +		EPRINTF("invalid path: %s\n", channel->path);
 40.1087 +		return -EINVAL;
 40.1088 +	}
 40.1089 +	
 40.1090 +	ptr = channel->path + len + 1;
 40.1091 +	strncpy(num, ptr, end - len);
 40.1092 +	tptr = num + (end - (len + 1));
 40.1093 +	*tptr = '\0';
 40.1094 +
 40.1095 +	channel->busid = atoi(num);
 40.1096 +	return 0;
 40.1097 +}
 40.1098 +
 40.1099 +static int
 40.1100 +tapdisk_channel_parse_params(tapdisk_channel_t *channel)
 40.1101 +{
 40.1102 +	int i, size, err;
 40.1103 +	unsigned int len;
 40.1104 +	char *ptr, *path, handle[10];
 40.1105 +	char *vdi_type;
 40.1106 +	char *vtype;
 40.1107 +
 40.1108 +	path = channel->params;
 40.1109 +	size = sizeof(dtypes) / sizeof(disk_info_t *);
 40.1110 +
 40.1111 +	if (strlen(path) + 1 >= TAPDISK_MESSAGE_MAX_PATH_LENGTH)
 40.1112 +		goto fail;
 40.1113 +
 40.1114 +	ptr = strchr(path, ':');
 40.1115 +	if (!ptr)
 40.1116 +		goto fail;
 40.1117 +
 40.1118 +	channel->vdi_path = ptr + 1;
 40.1119 +	memcpy(handle, path, (ptr - path));
 40.1120 +	ptr  = handle + (ptr - path);
 40.1121 +	*ptr = '\0';
 40.1122 +
 40.1123 +	err = asprintf(&vdi_type, "%s/sm-data/vdi-type", channel->path);
 40.1124 +	if (err == -1)
 40.1125 +		goto fail;
 40.1126 +
 40.1127 +	if (xs_exists(channel->xsh, vdi_type)) {
 40.1128 +		vtype = xs_read(channel->xsh, XBT_NULL, vdi_type, &len);
 40.1129 +		free(vdi_type);
 40.1130 +		if (!vtype)
 40.1131 +			goto fail;
 40.1132 +		if (len >= sizeof(handle) - 1) {
 40.1133 +			free(vtype);
 40.1134 +			goto fail;
 40.1135 +		}
 40.1136 +		sprintf(handle, "%s", vtype);
 40.1137 +		free(vtype);
 40.1138 +	}
 40.1139 +
 40.1140 +	for (i = 0; i < size; i++) {
 40.1141 +		if (strncmp(handle, dtypes[i]->handle, (ptr - path)))
 40.1142 +			continue;
 40.1143 +
 40.1144 +		if (dtypes[i]->idnum == -1)
 40.1145 +			goto fail;
 40.1146 +
 40.1147 +		channel->drivertype = dtypes[i]->idnum;
 40.1148 +		return 0;
 40.1149 +	}
 40.1150 +
 40.1151 +fail:
 40.1152 +	EPRINTF("%s: invalid blktap params: %s\n",
 40.1153 +		channel->path, channel->params);
 40.1154 +	channel->vdi_path = NULL;
 40.1155 +	return -EINVAL;
 40.1156 +}
 40.1157 +
 40.1158 +static int
 40.1159 +tapdisk_channel_gather_info(tapdisk_channel_t *channel)
 40.1160 +{
 40.1161 +	int err;
 40.1162 +
 40.1163 +	err = xs_gather(channel->xsh, channel->path,
 40.1164 +			"frontend", NULL, &channel->frontpath,
 40.1165 +			"frontend-id", "%li", &channel->domid,
 40.1166 +			"params", NULL, &channel->params,
 40.1167 +			"mode", "%c", &channel->mode, NULL);
 40.1168 +	if (err) {
 40.1169 +		EPRINTF("could not find device info: %d\n", err);
 40.1170 +		return err;
 40.1171 +	}
 40.1172 +
 40.1173 +	err = tapdisk_channel_parse_params(channel);
 40.1174 +	if (err)
 40.1175 +		return err;
 40.1176 +
 40.1177 +	err = tapdisk_channel_get_busid(channel);
 40.1178 +	if (err)
 40.1179 +		return err;
 40.1180 +
 40.1181 +	tapdisk_channel_get_storage_type(channel);
 40.1182 +
 40.1183 +	return 0;
 40.1184 +}
 40.1185 +
 40.1186 +static int
 40.1187 +tapdisk_channel_verify_start_request(tapdisk_channel_t *channel)
 40.1188 +{
 40.1189 +	char *path;
 40.1190 +	unsigned int err;
 40.1191 +
 40.1192 +	err = asprintf(&path, "%s/start-tapdisk", channel->path);
 40.1193 +	if (err == -1)
 40.1194 +		goto mem_fail;
 40.1195 +
 40.1196 +	if (!xs_exists(channel->xsh, path))
 40.1197 +		goto fail;
 40.1198 +
 40.1199 +	free(path);
 40.1200 +	err = asprintf(&path, "%s/shutdown-request", channel->path);
 40.1201 +	if (err == -1)
 40.1202 +		goto mem_fail;
 40.1203 +
 40.1204 +	if (xs_exists(channel->xsh, path))
 40.1205 +		goto fail;
 40.1206 +
 40.1207 +	if (xs_exists(channel->xsh, channel->shutdown_str))
 40.1208 +		goto fail;
 40.1209 +
 40.1210 +	free(path);
 40.1211 +	err = asprintf(&path, "%s/shutdown-done", channel->path);
 40.1212 +	if (err == -1)
 40.1213 +		goto mem_fail;
 40.1214 +
 40.1215 +	if (xs_exists(channel->xsh, path))
 40.1216 +		goto fail;
 40.1217 +
 40.1218 +	free(path);
 40.1219 +
 40.1220 +	return 0;
 40.1221 +
 40.1222 +fail:
 40.1223 +	free(path);
 40.1224 +	EPRINTF("%s:%s: invalid start request\n", __func__, channel->path);
 40.1225 +	return -EINVAL;
 40.1226 +
 40.1227 +mem_fail:
 40.1228 +	EPRINTF("%s:%s: out of memory\n", __func__, channel->path);
 40.1229 +	return -ENOMEM;
 40.1230 +}
 40.1231 +
 40.1232 +void
 40.1233 +tapdisk_channel_close(tapdisk_channel_t *channel)
 40.1234 +{
 40.1235 +	if (channel->channel_id)
 40.1236 +		DPRINTF("%s: closing channel %d:%d\n",
 40.1237 +			channel->path, channel->channel_id, channel->cookie);
 40.1238 +
 40.1239 +	if (channel->open)
 40.1240 +		tapdisk_channel_send_shutdown_request(channel);
 40.1241 +
 40.1242 +	if (channel->pause_watch.node) {
 40.1243 +		unregister_xenbus_watch(channel->xsh, &channel->pause_watch);
 40.1244 +		channel->pause_watch.node = NULL;
 40.1245 +	}
 40.1246 +
 40.1247 +	if (channel->shutdown_watch.node) {
 40.1248 +		unregister_xenbus_watch(channel->xsh, &channel->shutdown_watch);
 40.1249 +		channel->shutdown_watch.node = NULL;
 40.1250 +	}
 40.1251 +
 40.1252 +	tapdisk_daemon_close_channel(channel);
 40.1253 +
 40.1254 +	free(channel->params);
 40.1255 +	free(channel->frontpath);
 40.1256 +	free(channel->shutdown_str);
 40.1257 +	free(channel->pause_done_str);
 40.1258 +	free(channel->pause_str);
 40.1259 +	free(channel->uuid_str);
 40.1260 +	free(channel->path);
 40.1261 +	free(channel);
 40.1262 +}
 40.1263 +
 40.1264 +int
 40.1265 +tapdisk_channel_open(tapdisk_channel_t **_channel,
 40.1266 +		     char *path, struct xs_handle *xsh,
 40.1267 +		     int blktap_fd, uint16_t cookie)
 40.1268 +{
 40.1269 +	int err;
 40.1270 +	char *msg;
 40.1271 +	tapdisk_channel_t *channel;
 40.1272 +
 40.1273 +	msg       = NULL;
 40.1274 +	*_channel = NULL;
 40.1275 +
 40.1276 +	channel = calloc(1, sizeof(tapdisk_channel_t));
 40.1277 +	if (!channel)
 40.1278 +		return -ENOMEM;
 40.1279 +
 40.1280 +	channel->xsh       = xsh;
 40.1281 +	channel->blktap_fd = blktap_fd;
 40.1282 +	channel->cookie    = cookie;
 40.1283 +	channel->state     = TAPDISK_CHANNEL_IDLE;
 40.1284 +
 40.1285 +	INIT_LIST_HEAD(&channel->list);
 40.1286 +
 40.1287 +	channel->path = strdup(path);
 40.1288 +	if (!channel->path) {
 40.1289 +		err = -ENOMEM;
 40.1290 +		goto fail;
 40.1291 +	}
 40.1292 +
 40.1293 +	err = tapdisk_channel_init(channel);
 40.1294 +	if (err) {
 40.1295 +		msg = "allocating device";
 40.1296 +		goto fail;
 40.1297 +	}
 40.1298 +
 40.1299 +	err = tapdisk_channel_check_uuid(channel);
 40.1300 +	if (err) {
 40.1301 +		msg = "checking uuid";
 40.1302 +		goto fail;
 40.1303 +	}
 40.1304 +
 40.1305 +	err = tapdisk_channel_gather_info(channel);
 40.1306 +	if (err) {
 40.1307 +		msg = "gathering parameters";
 40.1308 +		goto fail;
 40.1309 +	}
 40.1310 +
 40.1311 +	err = tapdisk_channel_verify_start_request(channel);
 40.1312 +	if (err) {
 40.1313 +		msg = "invalid start request";
 40.1314 +		goto fail;
 40.1315 +	}
 40.1316 +
 40.1317 +	err = tapdisk_channel_set_watches(channel);
 40.1318 +	if (err) {
 40.1319 +		msg = "registering xenstore watches";
 40.1320 +		goto fail;
 40.1321 +	}
 40.1322 +
 40.1323 +	err = tapdisk_channel_connect(channel);
 40.1324 +	if (err) {
 40.1325 +		msg = "connecting to tapdisk";
 40.1326 +		goto fail;
 40.1327 +	}
 40.1328 +
 40.1329 +	*_channel = channel;
 40.1330 +	return 0;
 40.1331 +
 40.1332 +fail:
 40.1333 +	tapdisk_channel_fatal(channel, "%s: %d", (msg ? : "failure"), err);
 40.1334 +	return err;
 40.1335 +}
 40.1336 +
 40.1337 +int
 40.1338 +tapdisk_channel_receive_message(tapdisk_channel_t *c, tapdisk_message_t *m)
 40.1339 +{
 40.1340 +	int err;
 40.1341 +
 40.1342 +	err = tapdisk_channel_validate_message(c, m);
 40.1343 +	if (err)
 40.1344 +		goto fail;
 40.1345 +
 40.1346 +	switch (m->type) {
 40.1347 +	case TAPDISK_MESSAGE_PID_RSP:
 40.1348 +		return tapdisk_channel_receive_pid_response(c, m);
 40.1349 +
 40.1350 +	case TAPDISK_MESSAGE_OPEN_RSP:
 40.1351 +		return tapdisk_channel_receive_open_response(c, m);
 40.1352 +
 40.1353 +	case TAPDISK_MESSAGE_PAUSE_RSP:
 40.1354 +		return tapdisk_channel_receive_pause_response(c, m);
 40.1355 +
 40.1356 +	case TAPDISK_MESSAGE_RESUME_RSP:
 40.1357 +		return tapdisk_channel_receive_resume_response(c, m);
 40.1358 +
 40.1359 +	case TAPDISK_MESSAGE_CLOSE_RSP:
 40.1360 +		return tapdisk_channel_receive_shutdown_response(c, m);
 40.1361 +
 40.1362 +	case TAPDISK_MESSAGE_RUNTIME_ERROR:
 40.1363 +		return tapdisk_channel_receive_runtime_error(c, m);
 40.1364 +	}
 40.1365 +
 40.1366 +fail:
 40.1367 +	tapdisk_channel_fatal(c, "received unexpected message %s in state %d",
 40.1368 +			      tapdisk_message_name(m->type), c->state);
 40.1369 +	return -EINVAL;
 40.1370 +}
    41.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    41.2 +++ b/tools/blktap2/daemon/tapdisk-daemon.c	Wed Jun 17 17:24:56 2009 -0700
    41.3 @@ -0,0 +1,599 @@
    41.4 +/* Copyright (c) 2008, XenSource Inc.
    41.5 + * All rights reserved.
    41.6 + *
    41.7 + * Redistribution and use in source and binary forms, with or without
    41.8 + * modification, are permitted provided that the following conditions are met:
    41.9 + *     * Redistributions of source code must retain the above copyright
   41.10 + *       notice, this list of conditions and the following disclaimer.
   41.11 + *     * Redistributions in binary form must reproduce the above copyright
   41.12 + *       notice, this list of conditions and the following disclaimer in the
   41.13 + *       documentation and/or other materials provided with the distribution.
   41.14 + *     * Neither the name of XenSource Inc. nor the names of its contributors
   41.15 + *       may be used to endorse or promote products derived from this software
   41.16 + *       without specific prior written permission.
   41.17 + *
   41.18 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   41.19 + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   41.20 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   41.21 + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
   41.22 + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
   41.23 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   41.24 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
   41.25 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   41.26 + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   41.27 + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   41.28 + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   41.29 +*/
   41.30 +#include <stdio.h>
   41.31 +#include <errno.h>
   41.32 +#include <fcntl.h>
   41.33 +#include <unistd.h>
   41.34 +#include <stdlib.h>
   41.35 +#include <string.h>
   41.36 +#include <sys/ioctl.h>
   41.37 +#include <sys/resource.h>
   41.38 +
   41.39 +#include <xs.h>
   41.40 +#include "disktypes.h"
   41.41 +#include "tapdisk-dispatch.h"
   41.42 +
   41.43 +#define TAPDISK_DAEMON_DOMID_WATCH   "domid-watch"
   41.44 +#define TAPDISK_DAEMON_PIDFILE       "/var/run/blktapctrl.pid"
   41.45 +
   41.46 +typedef struct tapdisk_daemon {
   41.47 +	char                         *node;
   41.48 +	int                           blktap_fd;
   41.49 +	uint16_t                      cookie;
   41.50 +
   41.51 +	struct xs_handle             *xsh;
   41.52 +	struct list_head              channels;
   41.53 +	struct xenbus_watch           watch;
   41.54 +} tapdisk_daemon_t;
   41.55 +
   41.56 +static tapdisk_daemon_t tapdisk_daemon;
   41.57 +
   41.58 +#define tapdisk_daemon_for_each_channel(c, tmp) \
   41.59 +	list_for_each_entry_safe(c, tmp, &tapdisk_daemon.channels, list)
   41.60 +
   41.61 +#define MAX(a, b) ((a) >= (b) ? (a) : (b))
   41.62 +
   41.63 +static void
   41.64 +tapdisk_daemon_print_drivers(void)
   41.65 +{
   41.66 +	int i, size;
   41.67 +
   41.68 +	DPRINTF("blktap-daemon: v1.0.2\n");
   41.69 +
   41.70 +	size = sizeof(dtypes) / sizeof(disk_info_t *);
   41.71 +	for (i = 0; i < size; i++)
   41.72 +		DPRINTF("Found driver: [%s]\n", dtypes[i]->name);
   41.73 +}
   41.74 +
   41.75 +static int
   41.76 +tapdisk_daemon_write_pidfile(long pid)
   41.77 +{
   41.78 +	char buf[100];
   41.79 +	int len, fd, flags, err;
   41.80 +
   41.81 +	fd = open(TAPDISK_DAEMON_PIDFILE, O_RDWR | O_CREAT, 0600);
   41.82 +	if (fd == -1) {
   41.83 +		EPRINTF("Opening pid file failed (%d)\n", errno);
   41.84 +		return -errno;
   41.85 +	}
   41.86 +
   41.87 +	/* We exit silently if daemon already running */
   41.88 +	err = lockf(fd, F_TLOCK, 0);
   41.89 +	if (err == -1)
   41.90 +		exit(0);
   41.91 +
   41.92 +	/* Set FD_CLOEXEC, so that tapdisk doesn't get this file descriptor */
   41.93 +	flags = fcntl(fd, F_GETFD);
   41.94 +	if (flags == -1) {
   41.95 +		EPRINTF("F_GETFD failed (%d)\n", errno);
   41.96 +		return -errno;
   41.97 +	}
   41.98 +
   41.99 +	flags |= FD_CLOEXEC;
  41.100 +	err = fcntl(fd, F_SETFD, flags);
  41.101 +	if (err == -1) {
  41.102 +		EPRINTF("F_SETFD failed (%d)\n", errno);
  41.103 +		return -errno;
  41.104 +	}
  41.105 +
  41.106 +	len = sprintf(buf, "%ld\n", pid);
  41.107 +	err = write(fd, buf, len);
  41.108 +	if (err != len) {
  41.109 +		EPRINTF("Writing pid file failed (%d)\n", errno);
  41.110 +		return -errno;
  41.111 +	}
  41.112 +
  41.113 +	return 0;
  41.114 +}
  41.115 +
  41.116 +static int
  41.117 +tapdisk_daemon_init(void)
  41.118 +{
  41.119 +	char *devname;
  41.120 +	int i, err, blktap_major;
  41.121 +
  41.122 +	memset(&tapdisk_daemon, 0, sizeof(tapdisk_daemon_t));
  41.123 +
  41.124 +	err = asprintf(&devname, "%s/%s0", BLKTAP_DEV_DIR, BLKTAP_DEV_NAME);
  41.125 +	if (err == -1) {
  41.126 +		devname = NULL;
  41.127 +		err = -ENOMEM;
  41.128 +		goto fail;
  41.129 +	}
  41.130 +
  41.131 +	err = xc_find_device_number("blktap0");
  41.132 +	if (err < 0)
  41.133 +		goto fail;
  41.134 +
  41.135 +	blktap_major = major(err);
  41.136 +	err = make_blktap_device(devname, blktap_major, 0, S_IFCHR | 0600);
  41.137 +	if (err)
  41.138 +		goto fail;
  41.139 +
  41.140 +	tapdisk_daemon.blktap_fd = open(devname, O_RDWR);
  41.141 +	if (tapdisk_daemon.blktap_fd == -1) {
  41.142 +		err = -errno;
  41.143 +		EPRINTF("blktap0 open failed\n");
  41.144 +		goto fail;
  41.145 +	}
  41.146 +
  41.147 +	for (i = 0; i < 2; i++) {
  41.148 +		tapdisk_daemon.xsh = xs_daemon_open();
  41.149 +		if (!tapdisk_daemon.xsh) {
  41.150 +			EPRINTF("xs_daemon_open failed -- is xenstore running?\n");
  41.151 +			sleep(2);
  41.152 +		} else
  41.153 +			break;
  41.154 +	}
  41.155 +
  41.156 +	if (!tapdisk_daemon.xsh) {
  41.157 +		err = -ENOSYS;
  41.158 +		goto fail;
  41.159 +	}
  41.160 +
  41.161 +	INIT_LIST_HEAD(&tapdisk_daemon.channels);
  41.162 +
  41.163 +	free(devname);
  41.164 +	return 0;
  41.165 +
  41.166 +fail:
  41.167 +	if (tapdisk_daemon.blktap_fd > 0)
  41.168 +		close(tapdisk_daemon.blktap_fd);
  41.169 +	free(devname);
  41.170 +	memset(&tapdisk_daemon, 0, sizeof(tapdisk_daemon_t));
  41.171 +	EPRINTF("%s: %d\n", __func__, err);
  41.172 +
  41.173 +	return err;
  41.174 +}
  41.175 +
  41.176 +static int
  41.177 +tapdisk_daemon_set_node(void)
  41.178 +{
  41.179 +	int err;
  41.180 +	char *domid;
  41.181 +
  41.182 +	domid = get_dom_domid(tapdisk_daemon.xsh);
  41.183 +	if (!domid)
  41.184 +		return -EAGAIN;
  41.185 +
  41.186 +	err = asprintf(&tapdisk_daemon.node,
  41.187 +		       "/local/domain/%s/backend/tap", domid);
  41.188 +	if (err == -1) {
  41.189 +		tapdisk_daemon.node = NULL;
  41.190 +		err = -ENOMEM;
  41.191 +		goto out;
  41.192 +	}
  41.193 +
  41.194 +	err = 0;
  41.195 +
  41.196 +out:
  41.197 +	free(domid);
  41.198 +	return err;
  41.199 +}
  41.200 +
  41.201 +static int
  41.202 +tapdisk_daemon_get_domid(void)
  41.203 +{
  41.204 +	int err;
  41.205 +	unsigned int num;
  41.206 +	char **res, *node, *token, *domid;
  41.207 +
  41.208 +	res = xs_read_watch(tapdisk_daemon.xsh, &num);
  41.209 +	if (!res)
  41.210 +		return -EAGAIN;
  41.211 +
  41.212 +	err   = 0;
  41.213 +	node  = res[XS_WATCH_PATH];
  41.214 +	token = res[XS_WATCH_TOKEN];
  41.215 +
  41.216 +	if (strcmp(token, TAPDISK_DAEMON_DOMID_WATCH)) {
  41.217 +		err = -EINVAL;
  41.218 +		goto out;
  41.219 +	}
  41.220 +
  41.221 +	err = tapdisk_daemon_set_node();
  41.222 +
  41.223 +out:
  41.224 +	free(res);
  41.225 +	return err;
  41.226 +}
  41.227 +
  41.228 +static int
  41.229 +tapdisk_daemon_wait_for_domid(void)
  41.230 +{
  41.231 +	int err;
  41.232 +	char *domid;
  41.233 +	fd_set readfds;
  41.234 +
  41.235 +	err = tapdisk_daemon_set_node();
  41.236 +	if (!err)
  41.237 +		return 0;
  41.238 +
  41.239 +	if (!xs_watch(tapdisk_daemon.xsh, "/local/domain",
  41.240 +		      TAPDISK_DAEMON_DOMID_WATCH)) {
  41.241 +		EPRINTF("unable to set domain id watch\n");
  41.242 +		return -EINVAL;
  41.243 +	}
  41.244 +
  41.245 +	do {
  41.246 +		FD_ZERO(&readfds);
  41.247 +		FD_SET(xs_fileno(tapdisk_daemon.xsh), &readfds);
  41.248 +
  41.249 +		select(xs_fileno(tapdisk_daemon.xsh) + 1,
  41.250 +		       &readfds, NULL, NULL, NULL);
  41.251 +
  41.252 +		if (FD_ISSET(xs_fileno(tapdisk_daemon.xsh), &readfds))
  41.253 +			err = tapdisk_daemon_get_domid();
  41.254 +		else
  41.255 +			err = -EAGAIN;
  41.256 +	} while (err == -EAGAIN);
  41.257 +
  41.258 +	xs_unwatch(tapdisk_daemon.xsh,
  41.259 +		   "/local/domain", TAPDISK_DAEMON_DOMID_WATCH);
  41.260 +	return err;
  41.261 +}
  41.262 +
  41.263 +static inline int
  41.264 +tapdisk_daemon_new_vbd_event(const char *node)
  41.265 +{
  41.266 +	return (!strcmp(node, "start-tapdisk"));
  41.267 +}
  41.268 +
  41.269 +static int
  41.270 +tapdisk_daemon_write_uuid(char *path, uint32_t uuid)
  41.271 +{
  41.272 +	int err;
  41.273 +	char *cpath, uuid_str[12];
  41.274 +
  41.275 +	snprintf(uuid_str, sizeof(uuid_str), "%u", uuid);
  41.276 +
  41.277 +	err = asprintf(&cpath, "%s/tapdisk-uuid", path);
  41.278 +	if (err == -1)
  41.279 +		return -ENOMEM;
  41.280 +
  41.281 +	err = xs_write(tapdisk_daemon.xsh, XBT_NULL,
  41.282 +		       cpath, uuid_str, strlen(uuid_str));
  41.283 +	free(cpath);
  41.284 +
  41.285 +	return (err ? 0 : -errno);
  41.286 +}
  41.287 +
  41.288 +static void
  41.289 +tapdisk_daemon_probe(struct xs_handle *xsh,
  41.290 +		     struct xenbus_watch *watch, const char *path)
  41.291 +{
  41.292 +	char *cpath;
  41.293 +	int len, err;
  41.294 +	uint32_t cookie;
  41.295 +	const char *node;
  41.296 +	tapdisk_channel_t *channel;
  41.297 +
  41.298 +	len = strsep_len(path, '/', 7);
  41.299 +	if (len < 0)
  41.300 +		return;
  41.301 +
  41.302 +	node = path + len + 1;
  41.303 +
  41.304 +	if (!tapdisk_daemon_new_vbd_event(node))
  41.305 +		return;
  41.306 +
  41.307 +	if (!xs_exists(xsh, path))
  41.308 +		return;
  41.309 +
  41.310 +	cpath = strdup(path);
  41.311 +	if (!cpath) {
  41.312 +		EPRINTF("failed to allocate control path for %s\n", path);
  41.313 +		return;
  41.314 +	}
  41.315 +	cpath[len] = '\0';
  41.316 +
  41.317 +	cookie = tapdisk_daemon.cookie++;
  41.318 +	err    = tapdisk_daemon_write_uuid(cpath, cookie);
  41.319 +	if (err)
  41.320 +		goto out;
  41.321 +
  41.322 +	DPRINTF("%s: got watch on %s, uuid = %u\n", __func__, path, cookie);
  41.323 +
  41.324 +	err = tapdisk_channel_open(&channel, cpath,
  41.325 +				   tapdisk_daemon.xsh,
  41.326 +				   tapdisk_daemon.blktap_fd,
  41.327 +				   cookie);
  41.328 +	if (!err)
  41.329 +		list_add(&channel->list, &tapdisk_daemon.channels);
  41.330 +	else
  41.331 +		EPRINTF("failed to open tapdisk channel for %s: %d\n",
  41.332 +			path, err);
  41.333 +
  41.334 +out:
  41.335 +	free(cpath);
  41.336 +}
  41.337 +
  41.338 +static int
  41.339 +tapdisk_daemon_start(void)
  41.340 +{
  41.341 +	int err;
  41.342 +
  41.343 +	err = tapdisk_daemon_wait_for_domid();
  41.344 +	if (err)
  41.345 +		return err;
  41.346 +
  41.347 +	tapdisk_daemon.watch.node     = tapdisk_daemon.node;
  41.348 +	tapdisk_daemon.watch.callback = tapdisk_daemon_probe;
  41.349 +
  41.350 +	err = register_xenbus_watch(tapdisk_daemon.xsh, &tapdisk_daemon.watch);
  41.351 +	if (err)
  41.352 +		goto fail;
  41.353 +
  41.354 +	ioctl(tapdisk_daemon.blktap_fd,
  41.355 +	      BLKTAP_IOCTL_SETMODE, BLKTAP_MODE_INTERPOSE);
  41.356 +	ioctl(tapdisk_daemon.blktap_fd, BLKTAP_IOCTL_SENDPID, getpid());
  41.357 +
  41.358 +	return 0;
  41.359 +
  41.360 +fail:
  41.361 +	free(tapdisk_daemon.node);
  41.362 +	tapdisk_daemon.node       = NULL;
  41.363 +	tapdisk_daemon.watch.node = NULL;
  41.364 +	EPRINTF("%s: %d\n", __func__, err);
  41.365 +	return err;
  41.366 +}
  41.367 +
  41.368 +static int
  41.369 +tapdisk_daemon_stop(void)
  41.370 +{
  41.371 +	unregister_xenbus_watch(tapdisk_daemon.xsh, &tapdisk_daemon.watch);
  41.372 +
  41.373 +	ioctl(tapdisk_daemon.blktap_fd,
  41.374 +	      BLKTAP_IOCTL_SETMODE, BLKTAP_MODE_PASSTHROUGH);
  41.375 +	close(tapdisk_daemon.blktap_fd);
  41.376 +
  41.377 +	return 0;
  41.378 +}
  41.379 +
  41.380 +static void
  41.381 +tapdisk_daemon_free(void)
  41.382 +{
  41.383 +	free(tapdisk_daemon.node);
  41.384 +	xs_daemon_close(tapdisk_daemon.xsh);
  41.385 +	memset(&tapdisk_daemon, 0, sizeof(tapdisk_daemon_t));
  41.386 +}
  41.387 +
  41.388 +static int
  41.389 +tapdisk_daemon_read_message(int fd, tapdisk_message_t *message, int timeout)
  41.390 +{
  41.391 +	fd_set readfds;
  41.392 +	struct timeval tv;
  41.393 +	int ret, len, offset;
  41.394 +
  41.395 +	tv.tv_sec  = timeout;
  41.396 +	tv.tv_usec = 0;
  41.397 +	offset     = 0;
  41.398 +	len        = sizeof(tapdisk_message_t);
  41.399 +
  41.400 +	memset(message, 0, sizeof(tapdisk_message_t));
  41.401 +
  41.402 +	while (offset < len) {
  41.403 +		FD_ZERO(&readfds);
  41.404 +		FD_SET(fd, &readfds);
  41.405 +
  41.406 +		/* we don't bother reinitializing tv. at worst, it will wait a
  41.407 +		 * bit more time than expected. */
  41.408 +
  41.409 +		ret = select(fd + 1, &readfds, NULL, NULL, &tv);
  41.410 +		if (ret == -1)
  41.411 +			break;
  41.412 +		else if (FD_ISSET(fd, &readfds)) {
  41.413 +			ret = read(fd, message + offset, len - offset);
  41.414 +			if (ret <= 0)
  41.415 +				break;
  41.416 +			offset += ret;
  41.417 +		} else
  41.418 +			break;
  41.419 +	}
  41.420 +
  41.421 +	return (offset == len ? 0 : -EIO);
  41.422 +}
  41.423 +
  41.424 +static int
  41.425 +tapdisk_daemon_receive_message(int fd)
  41.426 +{
  41.427 +	int err;
  41.428 +	tapdisk_message_t m;
  41.429 +	tapdisk_channel_t *c, *tmp;
  41.430 +
  41.431 +	err = tapdisk_daemon_read_message(fd, &m, 2);
  41.432 +	if (err) {
  41.433 +		EPRINTF("failed reading message on %d: %d\n", fd, err);
  41.434 +		return err;
  41.435 +	}
  41.436 +
  41.437 +	tapdisk_daemon_for_each_channel(c, tmp)
  41.438 +		if (c->cookie == m.cookie && c->read_fd == fd) {
  41.439 +			DPRINTF("got '%s' message from %d:%d\n",
  41.440 +				tapdisk_message_name(m.type),
  41.441 +				c->channel_id, c->cookie);
  41.442 +
  41.443 +			return tapdisk_channel_receive_message(c, &m);
  41.444 +		}
  41.445 +
  41.446 +	EPRINTF("unrecognized message on %d: '%s' (uuid = %u)\n",
  41.447 +		fd, tapdisk_message_name(m.type), m.cookie);
  41.448 +
  41.449 +	return -EINVAL;
  41.450 +}
  41.451 +
  41.452 +static int
  41.453 +tapdisk_daemon_set_fds(fd_set *readfds)
  41.454 +{
  41.455 +	int max, fd;
  41.456 +	tapdisk_channel_t *channel, *tmp;
  41.457 +
  41.458 +	max = xs_fileno(tapdisk_daemon.xsh);
  41.459 +
  41.460 +	FD_ZERO(readfds);
  41.461 +	FD_SET(max, readfds);
  41.462 +
  41.463 +	tapdisk_daemon_for_each_channel(channel, tmp) {
  41.464 +		fd  = channel->read_fd;
  41.465 +		max = MAX(fd, max);
  41.466 +		FD_SET(fd, readfds);
  41.467 +	}
  41.468 +
  41.469 +	return max;
  41.470 +}
  41.471 +
  41.472 +static int
  41.473 +tapdisk_daemon_check_fds(fd_set *readfds)
  41.474 +{
  41.475 +	int err;
  41.476 +	tapdisk_channel_t *channel, *tmp;
  41.477 +
  41.478 +	if (FD_ISSET(xs_fileno(tapdisk_daemon.xsh), readfds))
  41.479 +		xs_fire_next_watch(tapdisk_daemon.xsh);
  41.480 +
  41.481 +	tapdisk_daemon_for_each_channel(channel, tmp)
  41.482 +		if (FD_ISSET(channel->read_fd, readfds))
  41.483 +			return tapdisk_daemon_receive_message(channel->read_fd);
  41.484 +
  41.485 +	return 0;
  41.486 +}
  41.487 +
  41.488 +static int
  41.489 +tapdisk_daemon_run(void)
  41.490 +{
  41.491 +	int err, max;
  41.492 +	fd_set readfds;
  41.493 +
  41.494 +	while (1) {
  41.495 +		max = tapdisk_daemon_set_fds(&readfds);
  41.496 +
  41.497 +		err = select(max + 1, &readfds, NULL, NULL, NULL);
  41.498 +		if (err < 0)
  41.499 +			continue;
  41.500 +
  41.501 +		err = tapdisk_daemon_check_fds(&readfds);
  41.502 +	}
  41.503 +
  41.504 +	return err;
  41.505 +}
  41.506 +
  41.507 +void
  41.508 +tapdisk_daemon_find_channel(tapdisk_channel_t *channel)
  41.509 +{
  41.510 +	tapdisk_channel_t *c, *tmp;
  41.511 +
  41.512 +	channel->read_fd     = 0;
  41.513 +	channel->write_fd    = 0;
  41.514 +	channel->tapdisk_pid = 0;
  41.515 +
  41.516 +	/* do we want multiple vbds per tapdisk? */
  41.517 +	if (!xs_exists(tapdisk_daemon.xsh, channel->share_tapdisk_str)) {
  41.518 +		channel->shared = 0;
  41.519 +		return;
  41.520 +	}
  41.521 +
  41.522 +	channel->shared = 1;
  41.523 +
  41.524 +	/* check if we already have a process started */
  41.525 +	tapdisk_daemon_for_each_channel(c, tmp)
  41.526 +		if (c->drivertype == channel->drivertype) {
  41.527 +			channel->write_fd    = c->write_fd;
  41.528 +			channel->read_fd     = c->read_fd;
  41.529 +			channel->channel_id  = c->channel_id;
  41.530 +			channel->tapdisk_pid = c->tapdisk_pid;
  41.531 +			return;
  41.532 +		}
  41.533 +}
  41.534 +
  41.535 +void
  41.536 +tapdisk_daemon_close_channel(tapdisk_channel_t *channel)
  41.537 +{
  41.538 +	tapdisk_channel_t *c, *tmp;
  41.539 +
  41.540 +	list_del(&channel->list);
  41.541 +
  41.542 +	tapdisk_daemon_for_each_channel(c, tmp)
  41.543 +		if (c->channel_id == channel->channel_id)
  41.544 +			return;
  41.545 +
  41.546 +	close(channel->read_fd);
  41.547 +	close(channel->write_fd);
  41.548 +}
  41.549 +
  41.550 +int
  41.551 +main(int argc, char *argv[])
  41.552 +{
  41.553 +	int err;
  41.554 +	char buf[128];
  41.555 +
  41.556 +	if (daemon(0, 0)) {
  41.557 +	  EPRINTF("daemon() failed (%d)\n", errno);
  41.558 +	  return -errno;
  41.559 +	}
  41.560 +
  41.561 +#define CORE_DUMP
  41.562 +#if defined(CORE_DUMP)
  41.563 +	{
  41.564 +		/* set up core-dumps*/
  41.565 +		struct rlimit rlim;
  41.566 +		rlim.rlim_cur = RLIM_INFINITY;
  41.567 +		rlim.rlim_max = RLIM_INFINITY;
  41.568 +		if (setrlimit(RLIMIT_CORE, &rlim) < 0)
  41.569 +			EPRINTF("setrlimit failed: %d\n", errno);
  41.570 +	}
  41.571 +#endif
  41.572 +
  41.573 +	snprintf(buf, sizeof(buf), "BLKTAP-DAEMON[%d]", getpid());
  41.574 +	openlog(buf, LOG_CONS | LOG_ODELAY, LOG_DAEMON);
  41.575 +
  41.576 +	err = tapdisk_daemon_write_pidfile(getpid());
  41.577 +	if (err)
  41.578 +		goto out;
  41.579 +
  41.580 +	tapdisk_daemon_print_drivers();
  41.581 +
  41.582 +	err = tapdisk_daemon_init();
  41.583 +	if (err)
  41.584 +		goto out;
  41.585 +
  41.586 +	err = tapdisk_daemon_start();
  41.587 +	if (err)
  41.588 +		goto out;
  41.589 +
  41.590 +	tapdisk_daemon_run();
  41.591 +
  41.592 +	tapdisk_daemon_stop();
  41.593 +	tapdisk_daemon_free();
  41.594 +
  41.595 +	err = 0;
  41.596 +
  41.597 +out:
  41.598 +	if (err)
  41.599 +		EPRINTF("failed to start %s: %d\n", argv[0], err);
  41.600 +	closelog();
  41.601 +	return err;
  41.602 +}
    42.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    42.2 +++ b/tools/blktap2/daemon/tapdisk-dispatch-common.c	Wed Jun 17 17:24:56 2009 -0700
    42.3 @@ -0,0 +1,94 @@
    42.4 +/*
    42.5 + * (c) 2005 Andrew Warfield and Julian Chesterfield
    42.6 + *
    42.7 + * This program is free software; you can redistribute it and/or
    42.8 + * modify it under the terms of the GNU General Public License version 2
    42.9 + * as published by the Free Software Foundation; or, when distributed
   42.10 + * separately from the Linux kernel or incorporated into other
   42.11 + * software packages, subject to the following license:
   42.12 + *
   42.13 + * Permission is hereby granted, free of charge, to any person obtaining a copy
   42.14 + * of this source file (the "Software"), to deal in the Software without
   42.15 + * restriction, including without limitation the rights to use, copy, modify,
   42.16 + * merge, publish, distribute, sublicense, and/or sell copies of the Software,
   42.17 + * and to permit persons to whom the Software is furnished to do so, subject to
   42.18 + * the following conditions:
   42.19 + *
   42.20 + * The above copyright notice and this permission notice shall be included in
   42.21 + * all copies or substantial portions of the Software.
   42.22 + *
   42.23 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   42.24 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   42.25 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   42.26 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   42.27 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   42.28 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
   42.29 + * IN THE SOFTWARE.
   42.30 + */
   42.31 +#include <errno.h>
   42.32 +#include <fcntl.h>
   42.33 +#include <unistd.h>
   42.34 +#include <sys/stat.h>
   42.35 +#include <sys/types.h>
   42.36 +
   42.37 +#include "tapdisk-dispatch.h"
   42.38 +
   42.39 +int
   42.40 +strsep_len(const char *str, char c, unsigned int len)
   42.41 +{
   42.42 +	unsigned int i;
   42.43 +	
   42.44 +	for (i = 0; str[i]; i++)
   42.45 +		if (str[i] == c) {
   42.46 +			if (len == 0)
   42.47 +				return i;
   42.48 +			len--;
   42.49 +		}
   42.50 +
   42.51 +	return (len == 0) ? i : -ERANGE;
   42.52 +}
   42.53 +
   42.54 +int
   42.55 +make_blktap_device(char *devname, int major, int minor, int perm)
   42.56 +{
   42.57 +	int err;
   42.58 +
   42.59 +	err = unlink(devname);
   42.60 +	if (err && errno != ENOENT) {
   42.61 +		EPRINTF("unlink %s failed: %d\n", devname, errno);
   42.62 +		return -errno;
   42.63 +	}
   42.64 +
   42.65 +	/* Need to create device */
   42.66 +	err = mkdir(BLKTAP_DEV_DIR, 0755);
   42.67 +	if (err && errno != EEXIST) {
   42.68 +		EPRINTF("Failed to create %s directory\n", BLKTAP_DEV_DIR);
   42.69 +		return -errno;
   42.70 +	}
   42.71 +
   42.72 +	err = mknod(devname, perm, makedev(major, minor));
   42.73 +	if (err) {
   42.74 +		int ret = -errno;
   42.75 +		struct stat st;
   42.76 +
   42.77 +		EPRINTF("mknod %s failed: %d\n", devname, -errno);
   42.78 +
   42.79 +		err = lstat(devname, &st);
   42.80 +		if (err) {
   42.81 +			DPRINTF("lstat %s failed: %d\n", devname, -errno);
   42.82 +			err = access(devname, F_OK);
   42.83 +			if (err)
   42.84 +				DPRINTF("access %s failed: %d\n", devname, -errno);
   42.85 +			else
   42.86 +				DPRINTF("access %s succeeded\n", devname);
   42.87 +		} else
   42.88 +			DPRINTF("lstat %s: %u:%u\n", devname,
   42.89 +				(unsigned int)st.st_rdev >> 8,
   42.90 +				(unsigned int)st.st_rdev & 0xff);
   42.91 +
   42.92 +		return ret;
   42.93 +	}
   42.94 +
   42.95 +	DPRINTF("Created %s device\n", devname);
   42.96 +	return 0;
   42.97 +}
    43.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    43.2 +++ b/tools/blktap2/daemon/tapdisk-dispatch.h	Wed Jun 17 17:24:56 2009 -0700
    43.3 @@ -0,0 +1,95 @@
    43.4 +/* Copyright (c) 2008, XenSource Inc.
    43.5 + * All rights reserved.
    43.6 + *
    43.7 + * Redistribution and use in source and binary forms, with or without
    43.8 + * modification, are permitted provided that the following conditions are met:
    43.9 + *     * Redistributions of source code must retain the above copyright
   43.10 + *       notice, this list of conditions and the following disclaimer.
   43.11 + *     * Redistributions in binary form must reproduce the above copyright
   43.12 + *       notice, this list of conditions and the following disclaimer in the
   43.13 + *       documentation and/or other materials provided with the distribution.
   43.14 + *     * Neither the name of XenSource Inc. nor the names of its contributors
   43.15 + *       may be used to endorse or promote products derived from this software
   43.16 + *       without specific prior written permission.
   43.17 + *
   43.18 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   43.19 + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   43.20 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   43.21 + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
   43.22 + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
   43.23 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   43.24 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
   43.25 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   43.26 + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   43.27 + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   43.28 + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   43.29 +*/
   43.30 +#ifndef _TAPDISK_DISPATCH_H_
   43.31 +#define _TAPDISK_DISPATCH_H_
   43.32 +
   43.33 +#include "xs_api.h"
   43.34 +#include "blktaplib.h"
   43.35 +#include "tapdisk-message.h"
   43.36 +
   43.37 +struct tapdisk_channel {
   43.38 +	int                       state;
   43.39 +
   43.40 +	int                       read_fd;
   43.41 +	int                       write_fd;
   43.42 +	int                       blktap_fd;
   43.43 +	int                       channel_id;
   43.44 +
   43.45 +	char                      mode;
   43.46 +	char                      shared;
   43.47 +	char                      open;
   43.48 +	unsigned int              domid;
   43.49 +	unsigned int              busid;
   43.50 +	unsigned int              major;
   43.51 +	unsigned int              minor;
   43.52 +	unsigned int              storage;
   43.53 +	unsigned int              drivertype;
   43.54 +	uint16_t                  cookie;
   43.55 +	pid_t                     tapdisk_pid;
   43.56 +
   43.57 +	/*
   43.58 +	 * special accounting needed to handle pause
   43.59 +	 * requests received before tapdisk process is ready
   43.60 +	 */
   43.61 +	char                      connected;
   43.62 +	char                      pause_needed;
   43.63 +
   43.64 +	char                     *path;
   43.65 +	char                     *frontpath;
   43.66 +	char                     *params;
   43.67 +	char                     *vdi_path;
   43.68 +	char                     *uuid_str;
   43.69 +	char                     *pause_str;
   43.70 +	char                     *pause_done_str;
   43.71 +	char                     *shutdown_str;
   43.72 +	char                     *share_tapdisk_str;
   43.73 +
   43.74 +	image_t                   image;
   43.75 +
   43.76 +	struct list_head          list;
   43.77 +	struct xenbus_watch       pause_watch;
   43.78 +	struct xenbus_watch       shutdown_watch;
   43.79 +
   43.80 +	struct xs_handle         *xsh;
   43.81 +};
   43.82 +
   43.83 +typedef struct tapdisk_channel tapdisk_channel_t;
   43.84 +
   43.85 +int strsep_len(const char *str, char c, unsigned int len);
   43.86 +int make_blktap_device(char *devname, int major, int minor, int perm);
   43.87 +
   43.88 +int tapdisk_channel_open(tapdisk_channel_t **,
   43.89 +			 char *node, struct xs_handle *,
   43.90 +			 int blktap_fd, uint16_t cookie);
   43.91 +void tapdisk_channel_close(tapdisk_channel_t *);
   43.92 +
   43.93 +void tapdisk_daemon_find_channel(tapdisk_channel_t *);
   43.94 +void tapdisk_daemon_close_channel(tapdisk_channel_t *);
   43.95 +
   43.96 +int tapdisk_channel_receive_message(tapdisk_channel_t *, tapdisk_message_t *);
   43.97 +
   43.98 +#endif
    44.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    44.2 +++ b/tools/blktap2/drivers/Makefile	Wed Jun 17 17:24:56 2009 -0700
    44.3 @@ -0,0 +1,105 @@
    44.4 +XEN_ROOT=../../../
    44.5 +BLKTAP_ROOT= ..
    44.6 +include $(XEN_ROOT)/tools/Rules.mk
    44.7 +
    44.8 +LIBVHDDIR  = $(BLKTAP_ROOT)/vhd/lib
    44.9 +
   44.10 +IBIN       = tapdisk tapdisk2 td-util tapdisk-client tapdisk-stream tapdisk-diff
   44.11 +QCOW_UTIL  = img2qcow qcow-create qcow2raw
   44.12 +LOCK_UTIL  = lock-util
   44.13 +INST_DIR   = $(SBINDIR)
   44.14 +
   44.15 +CFLAGS    += -Werror -g -O0
   44.16 +CFLAGS    += -Wno-unused
   44.17 +CFLAGS    += -fno-strict-aliasing
   44.18 +CFLAGS    += -I../lib -I../../libxc
   44.19 +CFLAGS    += -I../include -I../../include
   44.20 +CFLAGS    += -I $(LIBAIO_DIR)
   44.21 +CFLAGS    += -D_GNU_SOURCE
   44.22 +CFLAGS    += -DUSE_NFS_LOCKS
   44.23 +
   44.24 +ifeq ($(CONFIG_X86_64),y)
   44.25 +CFLAGS            += -fPIC
   44.26 +endif
   44.27 +
   44.28 +LIBS      += -lrt -lz
   44.29 +
   44.30 +ifeq ($(shell . ./check_gcrypt $(CC)),yes)
   44.31 +CFLAGS += -DUSE_GCRYPT
   44.32 +CRYPT_LIB += -lgcrypt
   44.33 +else
   44.34 +CRYPT_LIB += -lcrypto
   44.35 +$(warning === libgcrypt not installed: falling back to libcrypto ===)
   44.36 +endif
   44.37 +
   44.38 +LDFLAGS_img := $(CRYPT_LIB) -lpthread -lz
   44.39 +
   44.40 +tapdisk tapdisk2 td-util tapdisk-stream tapdisk-diff $(QCOW_UTIL): LIBS += -L$(LIBVHDDIR) -lvhd -luuid
   44.41 +
   44.42 +LIBAIO_DIR = $(XEN_ROOT)/tools/libaio/src
   44.43 +tapdisk tapdisk2 tapdisk-stream tapdisk-diff $(QCOW_UTIL): AIOLIBS := $(LIBAIO_DIR)/libaio.a
   44.44 +tapdisk tapdisk-client tapdisk-stream tapdisk-diff $(QCOW_UTIL): CFLAGS  += -I$(LIBAIO_DIR) -I$(XEN_LIBXC)
   44.45 +
   44.46 +ifeq ($(VHD_STATIC),y)
   44.47 +td-util: CFLAGS += -static
   44.48 +endif
   44.49 +
   44.50 +TAP-OBJS-y  := scheduler.o
   44.51 +TAP-OBJS-y  += tapdisk-ipc.o
   44.52 +TAP-OBJS-y  += tapdisk-vbd.o
   44.53 +TAP-OBJS-y  += tapdisk-image.o
   44.54 +TAP-OBJS-y  += tapdisk-driver.o
   44.55 +TAP-OBJS-y  += tapdisk-interface.o
   44.56 +TAP-OBJS-y  += tapdisk-server.o
   44.57 +TAP-OBJS-y  += tapdisk-queue.o
   44.58 +TAP-OBJS-y  += tapdisk-filter.o
   44.59 +TAP-OBJS-y  += tapdisk-log.o
   44.60 +TAP-OBJS-y  += tapdisk-utils.o
   44.61 +TAP-OBJS-y  += io-optimize.o
   44.62 +TAP-OBJS-y  += lock.o
   44.63 +TAP-OBJS-$(CONFIG_Linux)  += blk_linux.o
   44.64 +
   44.65 +MISC-OBJS-y := atomicio.o
   44.66 +
   44.67 +BLK-OBJS-y  := block-aio.o
   44.68 +BLK-OBJS-y  += block-ram.o
   44.69 +BLK-OBJS-y  += block-cache.o
   44.70 +BLK-OBJS-y  += block-vhd.o
   44.71 +BLK-OBJS-y  += block-log.o
   44.72 +BLK-OBJS-y  += block-qcow.o
   44.73 +BLK-OBJS-y  += aes.o
   44.74 +
   44.75 +all: $(IBIN) lock-util qcow-util
   44.76 +
   44.77 +tapdisk: $(TAP-OBJS-y) $(BLK-OBJS-y) $(MISC-OBJS-y) tapdisk.c
   44.78 +	$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(LIBS) $(AIOLIBS)  $(LDFLAGS_img)
   44.79 +
   44.80 +tapdisk2: $(TAP-OBJS-y) $(BLK-OBJS-y) $(MISC-OBJS-y) tapdisk2.c
   44.81 +	$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(LIBS) $(AIOLIBS) $(LDFLAGS_img)
   44.82 +
   44.83 +tapdisk-client: tapdisk-client.o
   44.84 +	$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(LIBS)  $(LDFLAGS_img)
   44.85 +
   44.86 +tapdisk-stream tapdisk-diff: %: %.o $(TAP-OBJS-y) $(BLK-OBJS-y)
   44.87 +	$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(LIBS) $(AIOLIBS)  $(LDFLAGS_img)
   44.88 +
   44.89 +td-util: td.o tapdisk-utils.o tapdisk-log.o
   44.90 +	$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(LIBS)  $(LDFLAGS_img)
   44.91 +
   44.92 +lock-util: lock.c
   44.93 +	$(CC) $(CFLAGS) -DUTIL -o lock-util lock.c $(LDFLAGS) $(LIBS)
   44.94 +
   44.95 +.PHONY: qcow-util
   44.96 +qcow-util: img2qcow qcow2raw qcow-create
   44.97 +
   44.98 +img2qcow qcow2raw qcow-create: %: %.o $(TAP-OBJS-y) $(BLK-OBJS-y)
   44.99 +	$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(LIBS) $(AIOLIBS) $(LDFLAGS_img)
  44.100 +
  44.101 +install: all
  44.102 +	$(INSTALL_DIR) -p $(DESTDIR)$(INST_DIR)
  44.103 +	$(INSTALL_PROG) $(IBIN) $(LOCK_UTIL) $(QCOW_UTIL) $(DESTDIR)$(INST_DIR)
  44.104 +
  44.105 +clean:
  44.106 +	rm -rf *.o *~ xen TAGS $(IBIN) $(LIB) $(LOCK_UTIL) $(QCOW_UTIL)
  44.107 +
  44.108 +.PHONY: clean install
    45.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    45.2 +++ b/tools/blktap2/drivers/aes.c	Wed Jun 17 17:24:56 2009 -0700
    45.3 @@ -0,0 +1,1319 @@
    45.4 +/**
    45.5 + * 
    45.6 + * aes.c - integrated in QEMU by Fabrice Bellard from the OpenSSL project.
    45.7 + */
    45.8 +/*
    45.9 + * rijndael-alg-fst.c
   45.10 + *
   45.11 + * @version 3.0 (December 2000)
   45.12 + *
   45.13 + * Optimised ANSI C code for the Rijndael cipher (now AES)
   45.14 + *
   45.15 + * @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>
   45.16 + * @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>
   45.17 + * @author Paulo Barreto <paulo.barreto@terra.com.br>
   45.18 + *
   45.19 + * This code is hereby placed in the public domain.
   45.20 + *
   45.21 + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
   45.22 + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   45.23 + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   45.24 + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
   45.25 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   45.26 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   45.27 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
   45.28 + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
   45.29 + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
   45.30 + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
   45.31 + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   45.32 + */
   45.33 +//#include "vl.h"
   45.34 +#include <inttypes.h>
   45.35 +#include <string.h>
   45.36 +#include "aes.h"
   45.37 +
   45.38 +//#define NDEBUG
   45.39 +#include <assert.h>
   45.40 +
   45.41 +typedef uint32_t u32;
   45.42 +typedef uint16_t u16;
   45.43 +typedef uint8_t u8;
   45.44 +
   45.45 +#define MAXKC   (256/32)
   45.46 +#define MAXKB   (256/8)
   45.47 +#define MAXNR   14
   45.48 +
   45.49 +/* This controls loop-unrolling in aes_core.c */
   45.50 +#undef FULL_UNROLL
   45.51 +# define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ ((u32)(pt)[2] <<  8) ^ ((u32)(pt)[3]))
   45.52 +# define PUTU32(ct, st) { (ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); (ct)[2] = (u8)((st) >>  8); (ct)[3] = (u8)(st); }
   45.53 +
   45.54 +/*
   45.55 +Te0[x] = S [x].[02, 01, 01, 03];
   45.56 +Te1[x] = S [x].[03, 02, 01, 01];
   45.57 +Te2[x] = S [x].[01, 03, 02, 01];
   45.58 +Te3[x] = S [x].[01, 01, 03, 02];
   45.59 +Te4[x] = S [x].[01, 01, 01, 01];
   45.60 +
   45.61 +Td0[x] = Si[x].[0e, 09, 0d, 0b];
   45.62 +Td1[x] = Si[x].[0b, 0e, 09, 0d];
   45.63 +Td2[x] = Si[x].[0d, 0b, 0e, 09];
   45.64 +Td3[x] = Si[x].[09, 0d, 0b, 0e];
   45.65 +Td4[x] = Si[x].[01, 01, 01, 01];
   45.66 +*/
   45.67 +
   45.68 +static const u32 Te0[256] = {
   45.69 +    0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU,
   45.70 +    0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U,
   45.71 +    0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU,
   45.72 +    0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU,
   45.73 +    0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U,
   45.74 +    0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU,
   45.75 +    0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU,
   45.76 +    0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU,
   45.77 +    0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU,
   45.78 +    0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU,
   45.79 +    0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U,
   45.80 +    0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU,
   45.81 +    0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU,
   45.82 +    0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U,
   45.83 +    0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU,
   45.84 +    0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU,
   45.85 +    0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU,
   45.86 +    0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU,
   45.87 +    0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU,
   45.88 +    0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U,
   45.89 +    0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU,
   45.90 +    0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU,
   45.91 +    0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU,
   45.92 +    0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU,
   45.93 +    0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U,
   45.94 +    0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U,
   45.95 +    0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U,
   45.96 +    0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U,
   45.97 +    0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU,
   45.98 +    0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U,
   45.99 +    0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U,
  45.100 +    0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU,
  45.101 +    0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU,
  45.102 +    0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U,
  45.103 +    0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U,
  45.104 +    0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U,
  45.105 +    0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU,
  45.106 +    0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U,
  45.107 +    0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU,
  45.108 +    0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U,
  45.109 +    0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU,
  45.110 +    0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U,
  45.111 +    0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U,
  45.112 +    0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU,
  45.113 +    0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U,
  45.114 +    0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U,
  45.115 +    0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U,
  45.116 +    0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U,
  45.117 +    0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U,
  45.118 +    0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U,
  45.119 +    0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U,
  45.120 +    0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U,
  45.121 +    0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU,
  45.122 +    0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U,
  45.123 +    0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U,
  45.124 +    0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U,
  45.125 +    0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U,
  45.126 +    0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U,
  45.127 +    0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U,
  45.128 +    0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU,
  45.129 +    0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U,
  45.130 +    0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U,
  45.131 +    0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U,
  45.132 +    0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU,
  45.133 +};
  45.134 +static const u32 Te1[256] = {
  45.135 +    0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU,
  45.136 +    0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U,
  45.137 +    0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU,
  45.138 +    0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U,
  45.139 +    0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU,
  45.140 +    0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U,
  45.141 +    0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU,
  45.142 +    0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U,
  45.143 +    0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U,
  45.144 +    0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU,
  45.145 +    0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U,
  45.146 +    0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U,
  45.147 +    0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U,
  45.148 +    0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU,
  45.149 +    0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U,
  45.150 +    0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U,
  45.151 +    0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU,
  45.152 +    0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U,
  45.153 +    0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U,
  45.154 +    0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U,
  45.155 +    0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU,
  45.156 +    0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU,
  45.157 +    0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U,
  45.158 +    0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU,
  45.159 +    0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU,
  45.160 +    0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U,
  45.161 +    0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU,
  45.162 +    0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U,
  45.163 +    0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU,
  45.164 +    0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U,
  45.165 +    0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U,
  45.166 +    0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U,
  45.167 +    0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU,
  45.168 +    0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U,
  45.169 +    0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU,
  45.170 +    0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U,
  45.171 +    0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU,
  45.172 +    0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U,
  45.173 +    0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U,
  45.174 +    0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU,
  45.175 +    0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU,
  45.176 +    0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU,
  45.177 +    0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U,
  45.178 +    0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U,
  45.179 +    0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU,
  45.180 +    0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U,
  45.181 +    0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU,
  45.182 +    0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U,
  45.183 +    0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU,
  45.184 +    0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U,
  45.185 +    0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU,
  45.186 +    0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU,
  45.187 +    0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U,
  45.188 +    0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU,
  45.189 +    0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U,
  45.190 +    0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU,
  45.191 +    0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U,
  45.192 +    0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U,
  45.193 +    0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U,
  45.194 +    0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU,
  45.195 +    0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU,
  45.196 +    0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U,
  45.197 +    0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU,
  45.198 +    0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U,
  45.199 +};
  45.200 +static const u32 Te2[256] = {
  45.201 +    0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU,
  45.202 +    0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U,
  45.203 +    0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU,
  45.204 +    0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U,
  45.205 +    0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU,
  45.206 +    0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U,
  45.207 +    0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU,
  45.208 +    0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U,
  45.209 +    0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U,
  45.210 +    0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU,
  45.211 +    0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U,
  45.212 +    0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U,
  45.213 +    0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U,
  45.214 +    0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU,
  45.215 +    0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U,
  45.216 +    0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U,
  45.217 +    0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU,
  45.218 +    0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U,
  45.219 +    0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U,
  45.220 +    0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U,
  45.221 +    0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU,
  45.222 +    0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU,
  45.223 +    0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U,
  45.224 +    0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU,
  45.225 +    0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU,
  45.226 +    0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U,
  45.227 +    0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU,
  45.228 +    0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U,
  45.229 +    0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU,
  45.230 +    0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U,
  45.231 +    0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U,
  45.232 +    0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U,
  45.233 +    0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU,
  45.234 +    0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U,
  45.235 +    0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU,
  45.236 +    0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U,
  45.237 +    0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU,
  45.238 +    0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U,
  45.239 +    0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U,
  45.240 +    0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU,
  45.241 +    0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU,
  45.242 +    0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU,
  45.243 +    0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U,
  45.244 +    0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U,
  45.245 +    0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU,
  45.246 +    0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U,
  45.247 +    0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU,
  45.248 +    0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U,
  45.249 +    0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU,
  45.250 +    0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U,
  45.251 +    0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU,
  45.252 +    0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU,
  45.253 +    0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U,
  45.254 +    0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU,
  45.255 +    0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U,
  45.256 +    0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU,
  45.257 +    0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U,
  45.258 +    0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U,
  45.259 +    0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U,
  45.260 +    0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU,
  45.261 +    0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU,
  45.262 +    0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U,
  45.263 +    0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU,
  45.264 +    0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U,
  45.265 +};
  45.266 +static const u32 Te3[256] = {
  45.267 +
  45.268 +    0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U,
  45.269 +    0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U,
  45.270 +    0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U,
  45.271 +    0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU,
  45.272 +    0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU,
  45.273 +    0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU,
  45.274 +    0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U,
  45.275 +    0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU,
  45.276 +    0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU,
  45.277 +    0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U,
  45.278 +    0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U,
  45.279 +    0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU,
  45.280 +    0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU,
  45.281 +    0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU,
  45.282 +    0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU,
  45.283 +    0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU,
  45.284 +    0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U,
  45.285 +    0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU,
  45.286 +    0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU,
  45.287 +    0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U,
  45.288 +    0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U,
  45.289 +    0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U,
  45.290 +    0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U,
  45.291 +    0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U,
  45.292 +    0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU,
  45.293 +    0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U,
  45.294 +    0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU,
  45.295 +    0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU,
  45.296 +    0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U,
  45.297 +    0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U,
  45.298 +    0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U,
  45.299 +    0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU,
  45.300 +    0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U,
  45.301 +    0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU,
  45.302 +    0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU,
  45.303 +    0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U,
  45.304 +    0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U,
  45.305 +    0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU,
  45.306 +    0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U,
  45.307 +    0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU,
  45.308 +    0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U,
  45.309 +    0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U,
  45.310 +    0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U,
  45.311 +    0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U,
  45.312 +    0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU,
  45.313 +    0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U,
  45.314 +    0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU,
  45.315 +    0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U,
  45.316 +    0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU,
  45.317 +    0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U,
  45.318 +    0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU,
  45.319 +    0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU,
  45.320 +    0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU,
  45.321 +    0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU,
  45.322 +    0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U,
  45.323 +    0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U,
  45.324 +    0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U,
  45.325 +    0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U,
  45.326 +    0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U,
  45.327 +    0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U,
  45.328 +    0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU,
  45.329 +    0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U,
  45.330 +    0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU,
  45.331 +    0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU,
  45.332 +};
  45.333 +static const u32 Te4[256] = {
  45.334 +    0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU,
  45.335 +    0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U,
  45.336 +    0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU,
  45.337 +    0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U,
  45.338 +    0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU,
  45.339 +    0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U,
  45.340 +    0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU,
  45.341 +    0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U,
  45.342 +    0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U,
  45.343 +    0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU,
  45.344 +    0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U,
  45.345 +    0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U,
  45.346 +    0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U,
  45.347 +    0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU,
  45.348 +    0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U,
  45.349 +    0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U,
  45.350 +    0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU,
  45.351 +    0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U,
  45.352 +    0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U,
  45.353 +    0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U,
  45.354 +    0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU,
  45.355 +    0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU,
  45.356 +    0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U,
  45.357 +    0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU,
  45.358 +    0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU,
  45.359 +    0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U,
  45.360 +    0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU,
  45.361 +    0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U,
  45.362 +    0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU,
  45.363 +    0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U,
  45.364 +    0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U,
  45.365 +    0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U,
  45.366 +    0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU,
  45.367 +    0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U,
  45.368 +    0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU,
  45.369 +    0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U,
  45.370 +    0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU,
  45.371 +    0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U,
  45.372 +    0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U,
  45.373 +    0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU,
  45.374 +    0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU,
  45.375 +    0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU,
  45.376 +    0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U,
  45.377 +    0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U,
  45.378 +    0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU,
  45.379 +    0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U,
  45.380 +    0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU,
  45.381 +    0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U,
  45.382 +    0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU,
  45.383 +    0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U,
  45.384 +    0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU,
  45.385 +    0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU,
  45.386 +    0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U,
  45.387 +    0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU,
  45.388 +    0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U,
  45.389 +    0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU,
  45.390 +    0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U,
  45.391 +    0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U,
  45.392 +    0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U,
  45.393 +    0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU,
  45.394 +    0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU,
  45.395 +    0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U,
  45.396 +    0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU,
  45.397 +    0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U,
  45.398 +};
  45.399 +static const u32 Td0[256] = {
  45.400 +    0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U,
  45.401 +    0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U,
  45.402 +    0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U,
  45.403 +    0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU,
  45.404 +    0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U,
  45.405 +    0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U,
  45.406 +    0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU,
  45.407 +    0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U,
  45.408 +    0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU,
  45.409 +    0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U,
  45.410 +    0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U,
  45.411 +    0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U,
  45.412 +    0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U,
  45.413 +    0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU,
  45.414 +    0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U,
  45.415 +    0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU,
  45.416 +    0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U,
  45.417 +    0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU,
  45.418 +    0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U,
  45.419 +    0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U,
  45.420 +    0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U,
  45.421 +    0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU,
  45.422 +    0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U,
  45.423 +    0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU,
  45.424 +    0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U,
  45.425 +    0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU,
  45.426 +    0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U,
  45.427 +    0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU,
  45.428 +    0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU,
  45.429 +    0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U,
  45.430 +    0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU,
  45.431 +    0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U,
  45.432 +    0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU,
  45.433 +    0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U,
  45.434 +    0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U,
  45.435 +    0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U,
  45.436 +    0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU,
  45.437 +    0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U,
  45.438 +    0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U,
  45.439 +    0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU,
  45.440 +    0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U,
  45.441 +    0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U,
  45.442 +    0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U,
  45.443 +    0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U,
  45.444 +    0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U,
  45.445 +    0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU,
  45.446 +    0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U,
  45.447 +    0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U,
  45.448 +    0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U,
  45.449 +    0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U,
  45.450 +    0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U,
  45.451 +    0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU,
  45.452 +    0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU,
  45.453 +    0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU,
  45.454 +    0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU,
  45.455 +    0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U,
  45.456 +    0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U,
  45.457 +    0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU,
  45.458 +    0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU,
  45.459 +    0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U,
  45.460 +    0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU,
  45.461 +    0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U,
  45.462 +    0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U,
  45.463 +    0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U,
  45.464 +};
  45.465 +static const u32 Td1[256] = {
  45.466 +    0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU,
  45.467 +    0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U,
  45.468 +    0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU,
  45.469 +    0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U,
  45.470 +    0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U,
  45.471 +    0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U,
  45.472 +    0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U,
  45.473 +    0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U,
  45.474 +    0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U,
  45.475 +    0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU,
  45.476 +    0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU,
  45.477 +    0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU,
  45.478 +    0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U,
  45.479 +    0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU,
  45.480 +    0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U,
  45.481 +    0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U,
  45.482 +    0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U,
  45.483 +    0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU,
  45.484 +    0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU,
  45.485 +    0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U,
  45.486 +    0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU,
  45.487 +    0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U,
  45.488 +    0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU,
  45.489 +    0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU,
  45.490 +    0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U,
  45.491 +    0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U,
  45.492 +    0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U,
  45.493 +    0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU,
  45.494 +    0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U,
  45.495 +    0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU,
  45.496 +    0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U,
  45.497 +    0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U,
  45.498 +    0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U,
  45.499 +    0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU,
  45.500 +    0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U,
  45.501 +    0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U,
  45.502 +    0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U,
  45.503 +    0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U,
  45.504 +    0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U,
  45.505 +    0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U,
  45.506 +    0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU,
  45.507 +    0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU,
  45.508 +    0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U,
  45.509 +    0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU,
  45.510 +    0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U,
  45.511 +    0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU,
  45.512 +    0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU,
  45.513 +    0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U,
  45.514 +    0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU,
  45.515 +    0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U,
  45.516 +    0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U,
  45.517 +    0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U,
  45.518 +    0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U,
  45.519 +    0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U,
  45.520 +    0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U,
  45.521 +    0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U,
  45.522 +    0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU,
  45.523 +    0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U,
  45.524 +    0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U,
  45.525 +    0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU,
  45.526 +    0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U,
  45.527 +    0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U,
  45.528 +    0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U,
  45.529 +    0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U,
  45.530 +};
  45.531 +static const u32 Td2[256] = {
  45.532 +    0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U,
  45.533 +    0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U,
  45.534 +    0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U,
  45.535 +    0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U,
  45.536 +    0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU,
  45.537 +    0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U,
  45.538 +    0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U,
  45.539 +    0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U,
  45.540 +    0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U,
  45.541 +    0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU,
  45.542 +    0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U,
  45.543 +    0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U,
  45.544 +    0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU,
  45.545 +    0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U,
  45.546 +    0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U,
  45.547 +    0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U,
  45.548 +    0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U,
  45.549 +    0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U,
  45.550 +    0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U,
  45.551 +    0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU,
  45.552 +
  45.553 +    0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U,
  45.554 +    0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U,
  45.555 +    0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U,
  45.556 +    0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U,
  45.557 +    0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U,
  45.558 +    0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU,
  45.559 +    0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU,
  45.560 +    0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U,
  45.561 +    0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU,
  45.562 +    0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U,
  45.563 +    0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU,
  45.564 +    0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU,
  45.565 +    0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU,
  45.566 +    0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU,
  45.567 +    0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U,
  45.568 +    0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U,
  45.569 +    0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U,
  45.570 +    0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U,
  45.571 +    0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U,
  45.572 +    0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U,
  45.573 +    0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U,
  45.574 +    0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU,
  45.575 +    0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU,
  45.576 +    0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U,
  45.577 +    0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U,
  45.578 +    0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU,
  45.579 +    0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU,
  45.580 +    0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U,
  45.581 +    0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U,
  45.582 +    0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U,
  45.583 +    0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U,
  45.584 +    0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U,
  45.585 +    0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U,
  45.586 +    0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U,
  45.587 +    0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU,
  45.588 +    0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U,
  45.589 +    0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U,
  45.590 +    0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U,
  45.591 +    0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U,
  45.592 +    0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U,
  45.593 +    0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U,
  45.594 +    0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU,
  45.595 +    0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U,
  45.596 +    0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U,
  45.597 +};
  45.598 +static const u32 Td3[256] = {
  45.599 +    0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU,
  45.600 +    0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU,
  45.601 +    0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U,
  45.602 +    0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U,
  45.603 +    0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU,
  45.604 +    0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU,
  45.605 +    0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U,
  45.606 +    0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU,
  45.607 +    0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U,
  45.608 +    0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU,
  45.609 +    0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U,
  45.610 +    0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U,
  45.611 +    0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U,
  45.612 +    0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U,
  45.613 +    0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U,
  45.614 +    0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU,
  45.615 +    0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU,
  45.616 +    0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U,
  45.617 +    0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U,
  45.618 +    0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU,
  45.619 +    0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU,
  45.620 +    0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U,
  45.621 +    0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U,
  45.622 +    0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U,
  45.623 +    0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U,
  45.624 +    0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU,
  45.625 +    0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U,
  45.626 +    0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U,
  45.627 +    0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU,
  45.628 +    0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU,
  45.629 +    0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U,
  45.630 +    0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U,
  45.631 +    0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U,
  45.632 +    0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU,
  45.633 +    0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U,
  45.634 +    0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U,
  45.635 +    0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U,
  45.636 +    0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U,
  45.637 +    0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U,
  45.638 +    0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U,
  45.639 +    0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U,
  45.640 +    0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU,
  45.641 +    0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U,
  45.642 +    0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U,
  45.643 +    0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU,
  45.644 +    0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU,
  45.645 +    0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U,
  45.646 +    0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU,
  45.647 +    0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U,
  45.648 +    0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U,
  45.649 +    0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U,
  45.650 +    0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U,
  45.651 +    0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U,
  45.652 +    0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U,
  45.653 +    0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU,
  45.654 +    0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU,
  45.655 +    0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU,
  45.656 +    0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU,
  45.657 +    0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U,
  45.658 +    0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U,
  45.659 +    0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U,
  45.660 +    0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU,
  45.661 +    0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U,
  45.662 +    0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U,
  45.663 +};
  45.664 +static const u32 Td4[256] = {
  45.665 +    0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U,
  45.666 +    0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U,
  45.667 +    0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU,
  45.668 +    0x81818181U, 0xf3f3f3f3U, 0xd7d7d7d7U, 0xfbfbfbfbU,
  45.669 +    0x7c7c7c7cU, 0xe3e3e3e3U, 0x39393939U, 0x82828282U,
  45.670 +    0x9b9b9b9bU, 0x2f2f2f2fU, 0xffffffffU, 0x87878787U,
  45.671 +    0x34343434U, 0x8e8e8e8eU, 0x43434343U, 0x44444444U,
  45.672 +    0xc4c4c4c4U, 0xdedededeU, 0xe9e9e9e9U, 0xcbcbcbcbU,
  45.673 +    0x54545454U, 0x7b7b7b7bU, 0x94949494U, 0x32323232U,
  45.674 +    0xa6a6a6a6U, 0xc2c2c2c2U, 0x23232323U, 0x3d3d3d3dU,
  45.675 +    0xeeeeeeeeU, 0x4c4c4c4cU, 0x95959595U, 0x0b0b0b0bU,
  45.676 +    0x42424242U, 0xfafafafaU, 0xc3c3c3c3U, 0x4e4e4e4eU,
  45.677 +    0x08080808U, 0x2e2e2e2eU, 0xa1a1a1a1U, 0x66666666U,
  45.678 +    0x28282828U, 0xd9d9d9d9U, 0x24242424U, 0xb2b2b2b2U,
  45.679 +    0x76767676U, 0x5b5b5b5bU, 0xa2a2a2a2U, 0x49494949U,
  45.680 +    0x6d6d6d6dU, 0x8b8b8b8bU, 0xd1d1d1d1U, 0x25252525U,
  45.681 +    0x72727272U, 0xf8f8f8f8U, 0xf6f6f6f6U, 0x64646464U,
  45.682 +    0x86868686U, 0x68686868U, 0x98989898U, 0x16161616U,
  45.683 +    0xd4d4d4d4U, 0xa4a4a4a4U, 0x5c5c5c5cU, 0xccccccccU,
  45.684 +    0x5d5d5d5dU, 0x65656565U, 0xb6b6b6b6U, 0x92929292U,
  45.685 +    0x6c6c6c6cU, 0x70707070U, 0x48484848U, 0x50505050U,
  45.686 +    0xfdfdfdfdU, 0xededededU, 0xb9b9b9b9U, 0xdadadadaU,
  45.687 +    0x5e5e5e5eU, 0x15151515U, 0x46464646U, 0x57575757U,
  45.688 +    0xa7a7a7a7U, 0x8d8d8d8dU, 0x9d9d9d9dU, 0x84848484U,
  45.689 +    0x90909090U, 0xd8d8d8d8U, 0xababababU, 0x00000000U,
  45.690 +    0x8c8c8c8cU, 0xbcbcbcbcU, 0xd3d3d3d3U, 0x0a0a0a0aU,
  45.691 +    0xf7f7f7f7U, 0xe4e4e4e4U, 0x58585858U, 0x05050505U,
  45.692 +    0xb8b8b8b8U, 0xb3b3b3b3U, 0x45454545U, 0x06060606U,
  45.693 +    0xd0d0d0d0U, 0x2c2c2c2cU, 0x1e1e1e1eU, 0x8f8f8f8fU,
  45.694 +    0xcacacacaU, 0x3f3f3f3fU, 0x0f0f0f0fU, 0x02020202U,
  45.695 +    0xc1c1c1c1U, 0xafafafafU, 0xbdbdbdbdU, 0x03030303U,
  45.696 +    0x01010101U, 0x13131313U, 0x8a8a8a8aU, 0x6b6b6b6bU,
  45.697 +    0x3a3a3a3aU, 0x91919191U, 0x11111111U, 0x41414141U,
  45.698 +    0x4f4f4f4fU, 0x67676767U, 0xdcdcdcdcU, 0xeaeaeaeaU,
  45.699 +    0x97979797U, 0xf2f2f2f2U, 0xcfcfcfcfU, 0xcecececeU,
  45.700 +    0xf0f0f0f0U, 0xb4b4b4b4U, 0xe6e6e6e6U, 0x73737373U,
  45.701 +    0x96969696U, 0xacacacacU, 0x74747474U, 0x22222222U,
  45.702 +    0xe7e7e7e7U, 0xadadadadU, 0x35353535U, 0x85858585U,
  45.703 +    0xe2e2e2e2U, 0xf9f9f9f9U, 0x37373737U, 0xe8e8e8e8U,
  45.704 +    0x1c1c1c1cU, 0x75757575U, 0xdfdfdfdfU, 0x6e6e6e6eU,
  45.705 +    0x47474747U, 0xf1f1f1f1U, 0x1a1a1a1aU, 0x71717171U,
  45.706 +    0x1d1d1d1dU, 0x29292929U, 0xc5c5c5c5U, 0x89898989U,
  45.707 +    0x6f6f6f6fU, 0xb7b7b7b7U, 0x62626262U, 0x0e0e0e0eU,
  45.708 +    0xaaaaaaaaU, 0x18181818U, 0xbebebebeU, 0x1b1b1b1bU,
  45.709 +    0xfcfcfcfcU, 0x56565656U, 0x3e3e3e3eU, 0x4b4b4b4bU,
  45.710 +    0xc6c6c6c6U, 0xd2d2d2d2U, 0x79797979U, 0x20202020U,
  45.711 +    0x9a9a9a9aU, 0xdbdbdbdbU, 0xc0c0c0c0U, 0xfefefefeU,
  45.712 +    0x78787878U, 0xcdcdcdcdU, 0x5a5a5a5aU, 0xf4f4f4f4U,
  45.713 +    0x1f1f1f1fU, 0xddddddddU, 0xa8a8a8a8U, 0x33333333U,
  45.714 +    0x88888888U, 0x07070707U, 0xc7c7c7c7U, 0x31313131U,
  45.715 +    0xb1b1b1b1U, 0x12121212U, 0x10101010U, 0x59595959U,
  45.716 +    0x27272727U, 0x80808080U, 0xececececU, 0x5f5f5f5fU,
  45.717 +    0x60606060U, 0x51515151U, 0x7f7f7f7fU, 0xa9a9a9a9U,
  45.718 +    0x19191919U, 0xb5b5b5b5U, 0x4a4a4a4aU, 0x0d0d0d0dU,
  45.719 +    0x2d2d2d2dU, 0xe5e5e5e5U, 0x7a7a7a7aU, 0x9f9f9f9fU,
  45.720 +    0x93939393U, 0xc9c9c9c9U, 0x9c9c9c9cU, 0xefefefefU,
  45.721 +    0xa0a0a0a0U, 0xe0e0e0e0U, 0x3b3b3b3bU, 0x4d4d4d4dU,
  45.722 +    0xaeaeaeaeU, 0x2a2a2a2aU, 0xf5f5f5f5U, 0xb0b0b0b0U,
  45.723 +    0xc8c8c8c8U, 0xebebebebU, 0xbbbbbbbbU, 0x3c3c3c3cU,
  45.724 +    0x83838383U, 0x53535353U, 0x99999999U, 0x61616161U,
  45.725 +    0x17171717U, 0x2b2b2b2bU, 0x04040404U, 0x7e7e7e7eU,
  45.726 +    0xbabababaU, 0x77777777U, 0xd6d6d6d6U, 0x26262626U,
  45.727 +    0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U,
  45.728 +    0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU,
  45.729 +};
  45.730 +static const u32 rcon[] = {
  45.731 +	0x01000000, 0x02000000, 0x04000000, 0x08000000,
  45.732 +	0x10000000, 0x20000000, 0x40000000, 0x80000000,
  45.733 +	0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
  45.734 +};
  45.735 +
  45.736 +/**
  45.737 + * Expand the cipher key into the encryption key schedule.
  45.738 + */
  45.739 +int AES_set_encrypt_key(const unsigned char *userKey, const int bits,
  45.740 +			AES_KEY *key) {
  45.741 +
  45.742 +	u32 *rk;
  45.743 +   	int i = 0;
  45.744 +	u32 temp;
  45.745 +
  45.746 +	if (!userKey || !key)
  45.747 +		return -1;
  45.748 +	if (bits != 128 && bits != 192 && bits != 256)
  45.749 +		return -2;
  45.750 +
  45.751 +	rk = key->rd_key;
  45.752 +
  45.753 +	if (bits==128)
  45.754 +		key->rounds = 10;
  45.755 +	else if (bits==192)
  45.756 +		key->rounds = 12;
  45.757 +	else
  45.758 +		key->rounds = 14;
  45.759 +
  45.760 +	rk[0] = GETU32(userKey     );
  45.761 +	rk[1] = GETU32(userKey +  4);
  45.762 +	rk[2] = GETU32(userKey +  8);
  45.763 +	rk[3] = GETU32(userKey + 12);
  45.764 +	if (bits == 128) {
  45.765 +		while (1) {
  45.766 +			temp  = rk[3];
  45.767 +			rk[4] = rk[0] ^
  45.768 +				(Te4[(temp >> 16) & 0xff] & 0xff000000) ^
  45.769 +				(Te4[(temp >>  8) & 0xff] & 0x00ff0000) ^
  45.770 +				(Te4[(temp      ) & 0xff] & 0x0000ff00) ^
  45.771 +				(Te4[(temp >> 24)       ] & 0x000000ff) ^
  45.772 +				rcon[i];
  45.773 +			rk[5] = rk[1] ^ rk[4];
  45.774 +			rk[6] = rk[2] ^ rk[5];
  45.775 +			rk[7] = rk[3] ^ rk[6];
  45.776 +			if (++i == 10) {
  45.777 +				return 0;
  45.778 +			}
  45.779 +			rk += 4;
  45.780 +		}
  45.781 +	}
  45.782 +	rk[4] = GETU32(userKey + 16);
  45.783 +	rk[5] = GETU32(userKey + 20);
  45.784 +	if (bits == 192) {
  45.785 +		while (1) {
  45.786 +			temp = rk[ 5];
  45.787 +			rk[ 6] = rk[ 0] ^
  45.788 +				(Te4[(temp >> 16) & 0xff] & 0xff000000) ^
  45.789 +				(Te4[(temp >>  8) & 0xff] & 0x00ff0000) ^
  45.790 +				(Te4[(temp      ) & 0xff] & 0x0000ff00) ^
  45.791 +				(Te4[(temp >> 24)       ] & 0x000000ff) ^
  45.792 +				rcon[i];
  45.793 +			rk[ 7] = rk[ 1] ^ rk[ 6];
  45.794 +			rk[ 8] = rk[ 2] ^ rk[ 7];
  45.795 +			rk[ 9] = rk[ 3] ^ rk[ 8];
  45.796 +			if (++i == 8) {
  45.797 +				return 0;
  45.798 +			}
  45.799 +			rk[10] = rk[ 4] ^ rk[ 9];
  45.800 +			rk[11] = rk[ 5] ^ rk[10];
  45.801 +			rk += 6;
  45.802 +		}
  45.803 +	}
  45.804 +	rk[6] = GETU32(userKey + 24);
  45.805 +	rk[7] = GETU32(userKey + 28);
  45.806 +	if (bits == 256) {
  45.807 +		while (1) {
  45.808 +			temp = rk[ 7];
  45.809 +			rk[ 8] = rk[ 0] ^
  45.810 +				(Te4[(temp >> 16) & 0xff] & 0xff000000) ^
  45.811 +				(Te4[(temp >>  8) & 0xff] & 0x00ff0000) ^
  45.812 +				(Te4[(temp      ) & 0xff] & 0x0000ff00) ^
  45.813 +				(Te4[(temp >> 24)       ] & 0x000000ff) ^
  45.814 +				rcon[i];
  45.815 +			rk[ 9] = rk[ 1] ^ rk[ 8];
  45.816 +			rk[10] = rk[ 2] ^ rk[ 9];
  45.817 +			rk[11] = rk[ 3] ^ rk[10];
  45.818 +			if (++i == 7) {
  45.819 +				return 0;
  45.820 +			}
  45.821 +			temp = rk[11];
  45.822 +			rk[12] = rk[ 4] ^
  45.823 +				(Te4[(temp >> 24)       ] & 0xff000000) ^
  45.824 +				(Te4[(temp >> 16) & 0xff] & 0x00ff0000) ^
  45.825 +				(Te4[(temp >>  8) & 0xff] & 0x0000ff00) ^
  45.826 +				(Te4[(temp      ) & 0xff] & 0x000000ff);
  45.827 +			rk[13] = rk[ 5] ^ rk[12];
  45.828 +			rk[14] = rk[ 6] ^ rk[13];
  45.829 +			rk[15] = rk[ 7] ^ rk[14];
  45.830 +
  45.831 +			rk += 8;
  45.832 +        	}
  45.833 +	}
  45.834 +	return 0;
  45.835 +}
  45.836 +
  45.837 +/**
  45.838 + * Expand the cipher key into the decryption key schedule.
  45.839 + */
  45.840 +int AES_set_decrypt_key(const unsigned char *userKey, const int bits,
  45.841 +			 AES_KEY *key) {
  45.842 +
  45.843 +        u32 *rk;
  45.844 +	int i, j, status;
  45.845 +	u32 temp;
  45.846 +
  45.847 +	/* first, start with an encryption schedule */
  45.848 +	status = AES_set_encrypt_key(userKey, bits, key);
  45.849 +	if (status < 0)
  45.850 +		return status;
  45.851 +
  45.852 +	rk = key->rd_key;
  45.853 +
  45.854 +	/* invert the order of the round keys: */
  45.855 +	for (i = 0, j = 4*(key->rounds); i < j; i += 4, j -= 4) {
  45.856 +		temp = rk[i    ]; rk[i    ] = rk[j    ]; rk[j    ] = temp;
  45.857 +		temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp;
  45.858 +		temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp;
  45.859 +		temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp;
  45.860 +	}
  45.861 +	/* apply the inverse MixColumn transform to all round keys but the first and the last: */
  45.862 +	for (i = 1; i < (key->rounds); i++) {
  45.863 +		rk += 4;
  45.864 +		rk[0] =
  45.865 +			Td0[Te4[(rk[0] >> 24)       ] & 0xff] ^
  45.866 +			Td1[Te4[(rk[0] >> 16) & 0xff] & 0xff] ^
  45.867 +			Td2[Te4[(rk[0] >>  8) & 0xff] & 0xff] ^
  45.868 +			Td3[Te4[(rk[0]      ) & 0xff] & 0xff];
  45.869 +		rk[1] =
  45.870 +			Td0[Te4[(rk[1] >> 24)       ] & 0xff] ^
  45.871 +			Td1[Te4[(rk[1] >> 16) & 0xff] & 0xff] ^
  45.872 +			Td2[Te4[(rk[1] >>  8) & 0xff] & 0xff] ^
  45.873 +			Td3[Te4[(rk[1]      ) & 0xff] & 0xff];
  45.874 +		rk[2] =
  45.875 +			Td0[Te4[(rk[2] >> 24)       ] & 0xff] ^
  45.876 +			Td1[Te4[(rk[2] >> 16) & 0xff] & 0xff] ^
  45.877 +			Td2[Te4[(rk[2] >>  8) & 0xff] & 0xff] ^
  45.878 +			Td3[Te4[(rk[2]      ) & 0xff] & 0xff];
  45.879 +		rk[3] =
  45.880 +			Td0[Te4[(rk[3] >> 24)       ] & 0xff] ^
  45.881 +			Td1[Te4[(rk[3] >> 16) & 0xff] & 0xff] ^
  45.882 +			Td2[Te4[(rk[3] >>  8) & 0xff] & 0xff] ^
  45.883 +			Td3[Te4[(rk[3]      ) & 0xff] & 0xff];
  45.884 +	}
  45.885 +	return 0;
  45.886 +}
  45.887 +
  45.888 +#ifndef AES_ASM
  45.889 +/*
  45.890 + * Encrypt a single block
  45.891 + * in and out can overlap
  45.892 + */
  45.893 +void AES_encrypt(const unsigned char *in, unsigned char *out,
  45.894 +		 const AES_KEY *key) {
  45.895 +
  45.896 +	const u32 *rk;
  45.897 +	u32 s0, s1, s2, s3, t0, t1, t2, t3;
  45.898 +#ifndef FULL_UNROLL
  45.899 +	int r;
  45.900 +#endif /* ?FULL_UNROLL */
  45.901 +
  45.902 +	assert(in && out && key);
  45.903 +	rk = key->rd_key;
  45.904 +
  45.905 +	/*
  45.906 +	 * map byte array block to cipher state
  45.907 +	 * and add initial round key:
  45.908 +	 */
  45.909 +	s0 = GETU32(in     ) ^ rk[0];
  45.910 +	s1 = GETU32(in +  4) ^ rk[1];
  45.911 +	s2 = GETU32(in +  8) ^ rk[2];
  45.912 +	s3 = GETU32(in + 12) ^ rk[3];
  45.913 +#ifdef FULL_UNROLL
  45.914 +	/* round 1: */
  45.915 +   	t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[ 4];
  45.916 +   	t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[ 5];
  45.917 +   	t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[ 6];
  45.918 +   	t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[ 7];
  45.919 +   	/* round 2: */
  45.920 +   	s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[ 8];
  45.921 +   	s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[ 9];
  45.922 +   	s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[10];
  45.923 +   	s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[11];
  45.924 +	/* round 3: */
  45.925 +   	t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[12];
  45.926 +   	t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[13];
  45.927 +   	t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[14];
  45.928 +   	t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[15];
  45.929 +   	/* round 4: */
  45.930 +   	s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[16];
  45.931 +   	s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[17];
  45.932 +   	s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[18];
  45.933 +   	s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[19];
  45.934 +	/* round 5: */
  45.935 +   	t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[20];
  45.936 +   	t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[21];
  45.937 +   	t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[22];
  45.938 +   	t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[23];
  45.939 +   	/* round 6: */
  45.940 +   	s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[24];
  45.941 +   	s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[25];
  45.942 +   	s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[26];
  45.943 +   	s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[27];
  45.944 +	/* round 7: */
  45.945 +   	t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[28];
  45.946 +   	t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[29];
  45.947 +   	t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[30];
  45.948 +   	t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[31];
  45.949 +   	/* round 8: */
  45.950 +   	s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[32];
  45.951 +   	s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[33];
  45.952 +   	s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[34];
  45.953 +   	s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[35];
  45.954 +	/* round 9: */
  45.955 +   	t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[36];
  45.956 +   	t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[37];
  45.957 +   	t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[38];
  45.958 +   	t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[39];
  45.959 +    if (key->rounds > 10) {
  45.960 +        /* round 10: */
  45.961 +        s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[40];
  45.962 +        s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[41];
  45.963 +        s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[42];
  45.964 +        s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[43];
  45.965 +        /* round 11: */
  45.966 +        t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[44];
  45.967 +        t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[45];
  45.968 +        t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[46];
  45.969 +        t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[47];
  45.970 +        if (key->rounds > 12) {
  45.971 +            /* round 12: */
  45.972 +            s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[48];
  45.973 +            s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[49];
  45.974 +            s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[50];
  45.975 +            s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[51];
  45.976 +            /* round 13: */
  45.977 +            t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[52];
  45.978 +            t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[53];
  45.979 +            t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[54];
  45.980 +            t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[55];
  45.981 +        }
  45.982 +    }
  45.983 +    rk += key->rounds << 2;
  45.984 +#else  /* !FULL_UNROLL */
  45.985 +    /*
  45.986 +     * Nr - 1 full rounds:
  45.987 +     */
  45.988 +    r = key->rounds >> 1;
  45.989 +    for (;;) {
  45.990 +        t0 =
  45.991 +            Te0[(s0 >> 24)       ] ^
  45.992 +            Te1[(s1 >> 16) & 0xff] ^
  45.993 +            Te2[(s2 >>  8) & 0xff] ^
  45.994 +            Te3[(s3      ) & 0xff] ^
  45.995 +            rk[4];
  45.996 +        t1 =
  45.997 +            Te0[(s1 >> 24)       ] ^
  45.998 +            Te1[(s2 >> 16) & 0xff] ^
  45.999 +            Te2[(s3 >>  8) & 0xff] ^
 45.1000 +            Te3[(s0      ) & 0xff] ^
 45.1001 +            rk[5];
 45.1002 +        t2 =
 45.1003 +            Te0[(s2 >> 24)       ] ^
 45.1004 +            Te1[(s3 >> 16) & 0xff] ^
 45.1005 +            Te2[(s0 >>  8) & 0xff] ^
 45.1006 +            Te3[(s1      ) & 0xff] ^
 45.1007 +            rk[6];
 45.1008 +        t3 =
 45.1009 +            Te0[(s3 >> 24)       ] ^
 45.1010 +            Te1[(s0 >> 16) & 0xff] ^
 45.1011 +            Te2[(s1 >>  8) & 0xff] ^
 45.1012 +            Te3[(s2      ) & 0xff] ^
 45.1013 +            rk[7];
 45.1014 +
 45.1015 +        rk += 8;
 45.1016 +        if (--r == 0) {
 45.1017 +            break;
 45.1018 +        }
 45.1019 +
 45.1020 +        s0 =
 45.1021 +            Te0[(t0 >> 24)       ] ^
 45.1022 +            Te1[(t1 >> 16) & 0xff] ^
 45.1023 +            Te2[(t2 >>  8) & 0xff] ^
 45.1024 +            Te3[(t3      ) & 0xff] ^
 45.1025 +            rk[0];
 45.1026 +        s1 =
 45.1027 +            Te0[(t1 >> 24)       ] ^
 45.1028 +            Te1[(t2 >> 16) & 0xff] ^
 45.1029 +            Te2[(t3 >>  8) & 0xff] ^
 45.1030 +            Te3[(t0      ) & 0xff] ^
 45.1031 +            rk[1];
 45.1032 +        s2 =
 45.1033 +            Te0[(t2 >> 24)       ] ^
 45.1034 +            Te1[(t3 >> 16) & 0xff] ^
 45.1035 +            Te2[(t0 >>  8) & 0xff] ^
 45.1036 +            Te3[(t1      ) & 0xff] ^
 45.1037 +            rk[2];
 45.1038 +        s3 =
 45.1039 +            Te0[(t3 >> 24)       ] ^
 45.1040 +            Te1[(t0 >> 16) & 0xff] ^
 45.1041 +            Te2[(t1 >>  8) & 0xff] ^
 45.1042 +            Te3[(t2      ) & 0xff] ^
 45.1043 +            rk[3];
 45.1044 +    }
 45.1045 +#endif /* ?FULL_UNROLL */
 45.1046 +    /*
 45.1047 +	 * apply last round and
 45.1048 +	 * map cipher state to byte array block:
 45.1049 +	 */
 45.1050 +	s0 =
 45.1051 +		(Te4[(t0 >> 24)       ] & 0xff000000) ^
 45.1052 +		(Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^
 45.1053 +		(Te4[(t2 >>  8) & 0xff] & 0x0000ff00) ^
 45.1054 +		(Te4[(t3      ) & 0xff] & 0x000000ff) ^
 45.1055 +		rk[0];
 45.1056 +	PUTU32(out     , s0);
 45.1057 +	s1 =
 45.1058 +		(Te4[(t1 >> 24)       ] & 0xff000000) ^
 45.1059 +		(Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^
 45.1060 +		(Te4[(t3 >>  8) & 0xff] & 0x0000ff00) ^
 45.1061 +		(Te4[(t0      ) & 0xff] & 0x000000ff) ^
 45.1062 +		rk[1];
 45.1063 +	PUTU32(out +  4, s1);
 45.1064 +	s2 =
 45.1065 +		(Te4[(t2 >> 24)       ] & 0xff000000) ^
 45.1066 +		(Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^
 45.1067 +		(Te4[(t0 >>  8) & 0xff] & 0x0000ff00) ^
 45.1068 +		(Te4[(t1      ) & 0xff] & 0x000000ff) ^
 45.1069 +		rk[2];
 45.1070 +	PUTU32(out +  8, s2);
 45.1071 +	s3 =
 45.1072 +		(Te4[(t3 >> 24)       ] & 0xff000000) ^
 45.1073 +		(Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^
 45.1074 +		(Te4[(t1 >>  8) & 0xff] & 0x0000ff00) ^
 45.1075 +		(Te4[(t2      ) & 0xff] & 0x000000ff) ^
 45.1076 +		rk[3];
 45.1077 +	PUTU32(out + 12, s3);
 45.1078 +}
 45.1079 +
 45.1080 +/*
 45.1081 + * Decrypt a single block
 45.1082 + * in and out can overlap
 45.1083 + */
 45.1084 +void AES_decrypt(const unsigned char *in, unsigned char *out,
 45.1085 +		 const AES_KEY *key) {
 45.1086 +
 45.1087 +	const u32 *rk;
 45.1088 +	u32 s0, s1, s2, s3, t0, t1, t2, t3;
 45.1089 +#ifndef FULL_UNROLL
 45.1090 +	int r;
 45.1091 +#endif /* ?FULL_UNROLL */
 45.1092 +
 45.1093 +	assert(in && out && key);
 45.1094 +	rk = key->rd_key;
 45.1095 +
 45.1096 +	/*
 45.1097 +	 * map byte array block to cipher state
 45.1098 +	 * and add initial round key:
 45.1099 +	 */
 45.1100 +    s0 = GETU32(in     ) ^ rk[0];
 45.1101 +    s1 = GETU32(in +  4) ^ rk[1];
 45.1102 +    s2 = GETU32(in +  8) ^ rk[2];
 45.1103 +    s3 = GETU32(in + 12) ^ rk[3];
 45.1104 +#ifdef FULL_UNROLL
 45.1105 +    /* round 1: */
 45.1106 +    t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[ 4];
 45.1107 +    t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[ 5];
 45.1108 +    t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[ 6];
 45.1109 +    t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[ 7];
 45.1110 +    /* round 2: */
 45.1111 +    s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[ 8];
 45.1112 +    s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[ 9];
 45.1113 +    s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[10];
 45.1114 +    s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[11];
 45.1115 +    /* round 3: */
 45.1116 +    t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[12];
 45.1117 +    t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[13];
 45.1118 +    t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[14];
 45.1119 +    t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[15];
 45.1120 +    /* round 4: */
 45.1121 +    s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[16];
 45.1122 +    s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[17];
 45.1123 +    s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[18];
 45.1124 +    s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[19];
 45.1125 +    /* round 5: */
 45.1126 +    t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[20];
 45.1127 +    t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[21];
 45.1128 +    t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[22];
 45.1129 +    t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[23];
 45.1130 +    /* round 6: */
 45.1131 +    s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[24];
 45.1132 +    s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[25];
 45.1133 +    s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[26];
 45.1134 +    s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[27];
 45.1135 +    /* round 7: */
 45.1136 +    t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[28];
 45.1137 +    t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[29];
 45.1138 +    t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[30];
 45.1139 +    t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[31];
 45.1140 +    /* round 8: */
 45.1141 +    s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[32];
 45.1142 +    s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[33];
 45.1143 +    s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[34];
 45.1144 +    s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[35];
 45.1145 +    /* round 9: */
 45.1146 +    t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[36];
 45.1147 +    t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[37];
 45.1148 +    t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[38];
 45.1149 +    t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[39];
 45.1150 +    if (key->rounds > 10) {
 45.1151 +        /* round 10: */
 45.1152 +        s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[40];
 45.1153 +        s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[41];
 45.1154 +        s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[42];
 45.1155 +        s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[43];
 45.1156 +        /* round 11: */
 45.1157 +        t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[44];
 45.1158 +        t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[45];
 45.1159 +        t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[46];
 45.1160 +        t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[47];
 45.1161 +        if (key->rounds > 12) {
 45.1162 +            /* round 12: */
 45.1163 +            s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[48];
 45.1164 +            s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[49];
 45.1165 +            s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[50];
 45.1166 +            s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[51];
 45.1167 +            /* round 13: */
 45.1168 +            t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[52];
 45.1169 +            t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[53];
 45.1170 +            t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[54];
 45.1171 +            t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[55];
 45.1172 +        }
 45.1173 +    }
 45.1174 +	rk += key->rounds << 2;
 45.1175 +#else  /* !FULL_UNROLL */
 45.1176 +    /*
 45.1177 +     * Nr - 1 full rounds:
 45.1178 +     */
 45.1179 +    r = key->rounds >> 1;
 45.1180 +    for (;;) {
 45.1181 +        t0 =
 45.1182 +            Td0[(s0 >> 24)       ] ^
 45.1183 +            Td1[(s3 >> 16) & 0xff] ^
 45.1184 +            Td2[(s2 >>  8) & 0xff] ^
 45.1185 +            Td3[(s1      ) & 0xff] ^
 45.1186 +            rk[4];
 45.1187 +        t1 =
 45.1188 +            Td0[(s1 >> 24)       ] ^
 45.1189 +            Td1[(s0 >> 16) & 0xff] ^
 45.1190 +            Td2[(s3 >>  8) & 0xff] ^
 45.1191 +            Td3[(s2      ) & 0xff] ^
 45.1192 +            rk[5];
 45.1193 +        t2 =
 45.1194 +            Td0[(s2 >> 24)       ] ^
 45.1195 +            Td1[(s1 >> 16) & 0xff] ^
 45.1196 +            Td2[(s0 >>  8) & 0xff] ^
 45.1197 +            Td3[(s3      ) & 0xff] ^
 45.1198 +            rk[6];
 45.1199 +        t3 =
 45.1200 +            Td0[(s3 >> 24)       ] ^
 45.1201 +            Td1[(s2 >> 16) & 0xff] ^
 45.1202 +            Td2[(s1 >>  8) & 0xff] ^
 45.1203 +            Td3[(s0      ) & 0xff] ^
 45.1204 +            rk[7];
 45.1205 +
 45.1206 +        rk += 8;
 45.1207 +        if (--r == 0) {
 45.1208 +            break;
 45.1209 +        }
 45.1210 +
 45.1211 +        s0 =
 45.1212 +            Td0[(t0 >> 24)       ] ^
 45.1213 +            Td1[(t3 >> 16) & 0xff] ^
 45.1214 +            Td2[(t2 >>  8) & 0xff] ^
 45.1215 +            Td3[(t1      ) & 0xff] ^
 45.1216 +            rk[0];
 45.1217 +        s1 =
 45.1218 +            Td0[(t1 >> 24)       ] ^
 45.1219 +            Td1[(t0 >> 16) & 0xff] ^
 45.1220 +            Td2[(t3 >>  8) & 0xff] ^
 45.1221 +            Td3[(t2      ) & 0xff] ^
 45.1222 +            rk[1];
 45.1223 +        s2 =
 45.1224 +            Td0[(t2 >> 24)       ] ^
 45.1225 +            Td1[(t1 >> 16) & 0xff] ^
 45.1226 +            Td2[(t0 >>  8) & 0xff] ^
 45.1227 +            Td3[(t3      ) & 0xff] ^
 45.1228 +            rk[2];
 45.1229 +        s3 =
 45.1230 +            Td0[(t3 >> 24)       ] ^
 45.1231 +            Td1[(t2 >> 16) & 0xff] ^
 45.1232 +            Td2[(t1 >>  8) & 0xff] ^
 45.1233 +            Td3[(t0      ) & 0xff] ^
 45.1234 +            rk[3];
 45.1235 +    }
 45.1236 +#endif /* ?FULL_UNROLL */
 45.1237 +    /*
 45.1238 +	 * apply last round and
 45.1239 +	 * map cipher state to byte array block:
 45.1240 +	 */
 45.1241 +   	s0 =
 45.1242 +   		(Td4[(t0 >> 24)       ] & 0xff000000) ^
 45.1243 +   		(Td4[(t3 >> 16) & 0xff] & 0x00ff0000) ^
 45.1244 +   		(Td4[(t2 >>  8) & 0xff] & 0x0000ff00) ^
 45.1245 +   		(Td4[(t1      ) & 0xff] & 0x000000ff) ^
 45.1246 +   		rk[0];
 45.1247 +	PUTU32(out     , s0);
 45.1248 +   	s1 =
 45.1249 +   		(Td4[(t1 >> 24)       ] & 0xff000000) ^
 45.1250 +   		(Td4[(t0 >> 16) & 0xff] & 0x00ff0000) ^
 45.1251 +   		(Td4[(t3 >>  8) & 0xff] & 0x0000ff00) ^
 45.1252 +   		(Td4[(t2      ) & 0xff] & 0x000000ff) ^
 45.1253 +   		rk[1];
 45.1254 +	PUTU32(out +  4, s1);
 45.1255 +   	s2 =
 45.1256 +   		(Td4[(t2 >> 24)       ] & 0xff000000) ^
 45.1257 +   		(Td4[(t1 >> 16) & 0xff] & 0x00ff0000) ^
 45.1258 +   		(Td4[(t0 >>  8) & 0xff] & 0x0000ff00) ^
 45.1259 +   		(Td4[(t3      ) & 0xff] & 0x000000ff) ^
 45.1260 +   		rk[2];
 45.1261 +	PUTU32(out +  8, s2);
 45.1262 +   	s3 =
 45.1263 +   		(Td4[(t3 >> 24)       ] & 0xff000000) ^
 45.1264 +   		(Td4[(t2 >> 16) & 0xff] & 0x00ff0000) ^
 45.1265 +   		(Td4[(t1 >>  8) & 0xff] & 0x0000ff00) ^
 45.1266 +   		(Td4[(t0      ) & 0xff] & 0x000000ff) ^
 45.1267 +   		rk[3];
 45.1268 +	PUTU32(out + 12, s3);
 45.1269 +}
 45.1270 +
 45.1271 +#endif /* AES_ASM */
 45.1272 +
 45.1273 +void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,
 45.1274 +		     const unsigned long length, const AES_KEY *key,
 45.1275 +		     unsigned char *ivec, const int enc) 
 45.1276 +{
 45.1277 +
 45.1278 +	unsigned long n;
 45.1279 +	unsigned long len = length;
 45.1280 +	unsigned char tmp[AES_BLOCK_SIZE];
 45.1281 +
 45.1282 +	assert(in && out && key && ivec);
 45.1283 +
 45.1284 +	if (enc) {
 45.1285 +		while (len >= AES_BLOCK_SIZE) {
 45.1286 +			for(n=0; n < AES_BLOCK_SIZE; ++n)
 45.1287 +				tmp[n] = in[n] ^ ivec[n];
 45.1288 +			AES_encrypt(tmp, out, key);
 45.1289 +			memcpy(ivec, out, AES_BLOCK_SIZE);
 45.1290 +			len -= AES_BLOCK_SIZE;
 45.1291 +			in += AES_BLOCK_SIZE;
 45.1292 +			out += AES_BLOCK_SIZE;
 45.1293 +		}
 45.1294 +		if (len) {
 45.1295 +			for(n=0; n < len; ++n)
 45.1296 +				tmp[n] = in[n] ^ ivec[n];
 45.1297 +			for(n=len; n < AES_BLOCK_SIZE; ++n)
 45.1298 +				tmp[n] = ivec[n];
 45.1299 +			AES_encrypt(tmp, tmp, key);
 45.1300 +			memcpy(out, tmp, AES_BLOCK_SIZE);
 45.1301 +			memcpy(ivec, tmp, AES_BLOCK_SIZE);
 45.1302 +		}			
 45.1303 +	} else {
 45.1304 +		while (len >= AES_BLOCK_SIZE) {
 45.1305 +			memcpy(tmp, in, AES_BLOCK_SIZE);
 45.1306 +			AES_decrypt(in, out, key);
 45.1307 +			for(n=0; n < AES_BLOCK_SIZE; ++n)
 45.1308 +				out[n] ^= ivec[n];
 45.1309 +			memcpy(ivec, tmp, AES_BLOCK_SIZE);
 45.1310 +			len -= AES_BLOCK_SIZE;
 45.1311 +			in += AES_BLOCK_SIZE;
 45.1312 +			out += AES_BLOCK_SIZE;
 45.1313 +		}
 45.1314 +		if (len) {
 45.1315 +			memcpy(tmp, in, AES_BLOCK_SIZE);
 45.1316 +			AES_decrypt(tmp, tmp, key);
 45.1317 +			for(n=0; n < len; ++n)
 45.1318 +				out[n] = tmp[n] ^ ivec[n];
 45.1319 +			memcpy(ivec, tmp, AES_BLOCK_SIZE);
 45.1320 +		}			
 45.1321 +	}
 45.1322 +}
    46.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    46.2 +++ b/tools/blktap2/drivers/aes.h	Wed Jun 17 17:24:56 2009 -0700
    46.3 @@ -0,0 +1,28 @@
    46.4 +#ifndef QEMU_AES_H
    46.5 +#define QEMU_AES_H
    46.6 +
    46.7 +#include <stdint.h>
    46.8 +
    46.9 +#define AES_MAXNR 14
   46.10 +#define AES_BLOCK_SIZE 16
   46.11 +
   46.12 +struct aes_key_st {
   46.13 +    uint32_t rd_key[4 *(AES_MAXNR + 1)];
   46.14 +    int rounds;
   46.15 +};
   46.16 +typedef struct aes_key_st AES_KEY;
   46.17 +
   46.18 +int AES_set_encrypt_key(const unsigned char *userKey, const int bits,
   46.19 +	AES_KEY *key);
   46.20 +int AES_set_decrypt_key(const unsigned char *userKey, const int bits,
   46.21 +	AES_KEY *key);
   46.22 +
   46.23 +void AES_encrypt(const unsigned char *in, unsigned char *out,
   46.24 +	const AES_KEY *key);
   46.25 +void AES_decrypt(const unsigned char *in, unsigned char *out,
   46.26 +	const AES_KEY *key);
   46.27 +void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,
   46.28 +		     const unsigned long length, const AES_KEY *key,
   46.29 +		     unsigned char *ivec, const int enc);
   46.30 +
   46.31 +#endif
    47.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    47.2 +++ b/tools/blktap2/drivers/atomicio.c	Wed Jun 17 17:24:56 2009 -0700
    47.3 @@ -0,0 +1,61 @@
    47.4 +/*
    47.5 + * Copyright (c) 2005 Anil Madhavapeddy. All rights reserved.
    47.6 + * Copyright (c) 1995,1999 Theo de Raadt.  All rights reserved.
    47.7 + * All rights reserved.
    47.8 + *
    47.9 + * Redistribution and use in source and binary forms, with or without
   47.10 + * modification, are permitted provided that the following conditions
   47.11 + * are met:
   47.12 + * 1. Redistributions of source code must retain the above copyright
   47.13 + *    notice, this list of conditions and the following disclaimer.
   47.14 + * 2. Redistributions in binary form must reproduce the above copyright
   47.15 + *    notice, this list of conditions and the following disclaimer in the
   47.16 + *    documentation and/or other materials provided with the distribution.
   47.17 + *
   47.18 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   47.19 + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   47.20 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   47.21 + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   47.22 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   47.23 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   47.24 + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   47.25 + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   47.26 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   47.27 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   47.28 + */
   47.29 +
   47.30 +#include <stdlib.h>
   47.31 +#include <errno.h>
   47.32 +#include "atomicio.h"
   47.33 +
   47.34 +/*
   47.35 + * ensure all of data on socket comes through. f==read || f==vwrite
   47.36 + */
   47.37 +size_t
   47.38 +atomicio(f, fd, _s, n)
   47.39 +	ssize_t (*f) (int, void *, size_t);
   47.40 +	int fd;
   47.41 +	void *_s;
   47.42 +	size_t n;
   47.43 +{
   47.44 +	char *s = _s;
   47.45 +	size_t pos = 0;
   47.46 +	ssize_t res;
   47.47 +
   47.48 +	while (n > pos) {
   47.49 +		res = (f) (fd, s + pos, n - pos);
   47.50 +		switch (res) {
   47.51 +		case -1:
   47.52 +			if (errno == EINTR || errno == EAGAIN)
   47.53 +				continue;
   47.54 +			return 0;
   47.55 +		case 0:
   47.56 +			errno = EPIPE;
   47.57 +			return pos;
   47.58 +		default:
   47.59 +			pos += (size_t)res;
   47.60 +		}
   47.61 +	}
   47.62 +	return (pos);
   47.63 +}
   47.64 +
    48.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    48.2 +++ b/tools/blktap2/drivers/blk.h	Wed Jun 17 17:24:56 2009 -0700
    48.3 @@ -0,0 +1,30 @@
    48.4 +/* 
    48.5 + * Copyright (c) 2008, XenSource Inc.
    48.6 + * All rights reserved.
    48.7 + *
    48.8 + * Redistribution and use in source and binary forms, with or without
    48.9 + * modification, are permitted provided that the following conditions are met:
   48.10 + *     * Redistributions of source code must retain the above copyright
   48.11 + *       notice, this list of conditions and the following disclaimer.
   48.12 + *     * Redistributions in binary form must reproduce the above copyright
   48.13 + *       notice, this list of conditions and the following disclaimer in the
   48.14 + *       documentation and/or other materials provided with the distribution.
   48.15 + *     * Neither the name of XenSource Inc. nor the names of its contributors
   48.16 + *       may be used to endorse or promote products derived from this software
   48.17 + *       without specific prior written permission.
   48.18 + *
   48.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   48.20 + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   48.21 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   48.22 + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
   48.23 + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
   48.24 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   48.25 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
   48.26 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   48.27 + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   48.28 + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   48.29 + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   48.30 +*/
   48.31 +
   48.32 +int blk_getimagesize(int fd, uint64_t *size);
   48.33 +int blk_getsectorsize(int fd, uint64_t *sector_size);
    49.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    49.2 +++ b/tools/blktap2/drivers/blk_linux.c	Wed Jun 17 17:24:56 2009 -0700
    49.3 @@ -0,0 +1,43 @@
    49.4 +#include <inttypes.h>
    49.5 +#include <sys/ioctl.h>
    49.6 +#include <linux/fs.h>
    49.7 +#include <linux/errno.h>
    49.8 +#include "tapdisk.h"
    49.9 +#include "blk.h"
   49.10 +
   49.11 +int blk_getimagesize(int fd, uint64_t *size)
   49.12 +{
   49.13 +	int rc;
   49.14 +
   49.15 +	*size = 0;
   49.16 +	rc = ioctl(fd, BLKGETSIZE, size);
   49.17 +	if (rc) {
   49.18 +		DPRINTF("ERR: BLKGETSIZE failed, couldn't stat image");
   49.19 +		return -EINVAL;
   49.20 +	}
   49.21 +
   49.22 +	return 0;
   49.23 +}
   49.24 +
   49.25 +int blk_getsectorsize(int fd, uint64_t *sector_size)
   49.26 +{
   49.27 +#if defined(BLKSSZGET)
   49.28 +	int rc;
   49.29 +
   49.30 +	*sector_size = DEFAULT_SECTOR_SIZE;
   49.31 +	rc = ioctl(fd, BLKSSZGET, sector_size);
   49.32 +	if (rc) {
   49.33 +		DPRINTF("ERR: BLKSSZGET failed. Falling back to use default sector size");
   49.34 +		*sector_size = DEFAULT_SECTOR_SIZE;
   49.35 +	}
   49.36 +
   49.37 +	if (*sector_size != DEFAULT_SECTOR_SIZE)
   49.38 +		DPRINTF("Note: sector size is %"PRIu64" (not %u)\n",
   49.39 +			*sector_size, DEFAULT_SECTOR_SIZE);
   49.40 +#else
   49.41 +	*sector_size = DEFAULT_SECTOR_SIZE;
   49.42 +#endif
   49.43 +
   49.44 +	return 0;
   49.45 +}
   49.46 +
    50.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    50.2 +++ b/tools/blktap2/drivers/blktap2.h	Wed Jun 17 17:24:56 2009 -0700
    50.3 @@ -0,0 +1,66 @@
    50.4 +/*
    50.5 + * Copyright (c) 2008, XenSource Inc.
    50.6 + * All rights reserved.
    50.7 + *
    50.8 + * Redistribution and use in source and binary forms, with or without
    50.9 + * modification, are permitted provided that the following conditions are met:
   50.10 + *     * Redistributions of source code must retain the above copyright
   50.11 + *       notice, this list of conditions and the following disclaimer.
   50.12 + *     * Redistributions in binary form must reproduce the above copyright
   50.13 + *       notice, this list of conditions and the following disclaimer in the
   50.14 + *       documentation and/or other materials provided with the distribution.
   50.15 + *     * Neither the name of XenSource Inc. nor the names of its contributors
   50.16 + *       may be used to endorse or promote products derived from this software
   50.17 + *       without specific prior written permission.
   50.18 + *
   50.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   50.20 + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   50.21 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   50.22 + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
   50.23 + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
   50.24 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   50.25 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
   50.26 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   50.27 + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   50.28 + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   50.29 + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   50.30 + */
   50.31 +#ifndef _BLKTAP_2_H_
   50.32 +#define _BLKTAP_2_H_
   50.33 +
   50.34 +#define MISC_MAJOR_NUMBER              10
   50.35 +
   50.36 +#define BLKTAP2_MAX_MESSAGE_LEN        256
   50.37 +
   50.38 +#define BLKTAP2_RING_MESSAGE_PAUSE     1
   50.39 +#define BLKTAP2_RING_MESSAGE_RESUME    2
   50.40 +#define BLKTAP2_RING_MESSAGE_CLOSE     3
   50.41 +
   50.42 +#define BLKTAP2_IOCTL_KICK_FE          1
   50.43 +#define BLKTAP2_IOCTL_ALLOC_TAP        200
   50.44 +#define BLKTAP2_IOCTL_FREE_TAP         201
   50.45 +#define BLKTAP2_IOCTL_CREATE_DEVICE    202
   50.46 +#define BLKTAP2_IOCTL_SET_PARAMS       203
   50.47 +#define BLKTAP2_IOCTL_PAUSE            204
   50.48 +#define BLKTAP2_IOCTL_REOPEN           205
   50.49 +#define BLKTAP2_IOCTL_RESUME           206
   50.50 +
   50.51 +#define BLKTAP2_CONTROL_NAME           "blktap-control"
   50.52 +#define BLKTAP2_DIRECTORY              "/dev/xen/blktap-2"
   50.53 +#define BLKTAP2_CONTROL_DEVICE         BLKTAP2_DIRECTORY"/control"
   50.54 +#define BLKTAP2_RING_DEVICE            BLKTAP2_DIRECTORY"/blktap"
   50.55 +#define BLKTAP2_IO_DEVICE              BLKTAP2_DIRECTORY"/tapdev"
   50.56 +
   50.57 +struct blktap2_handle {
   50.58 +	unsigned int                   ring;
   50.59 +	unsigned int                   device;
   50.60 +	unsigned int                   minor;
   50.61 +};
   50.62 +
   50.63 +struct blktap2_params {
   50.64 +	char                           name[BLKTAP2_MAX_MESSAGE_LEN];
   50.65 +	unsigned long long             capacity;
   50.66 +	unsigned long                  sector_size;
   50.67 +};
   50.68 +
   50.69 +#endif
    51.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    51.2 +++ b/tools/blktap2/drivers/block-aio.c	Wed Jun 17 17:24:56 2009 -0700
    51.3 @@ -0,0 +1,272 @@
    51.4 +/* 
    51.5 + * Copyright (c) 2007, XenSource Inc.
    51.6 + * All rights reserved.
    51.7 + *
    51.8 + * Redistribution and use in source and binary forms, with or without
    51.9 + * modification, are permitted provided that the following conditions are met:
   51.10 + *     * Redistributions of source code must retain the above copyright
   51.11 + *       notice, this list of conditions and the following disclaimer.
   51.12 + *     * Redistributions in binary form must reproduce the above copyright
   51.13 + *       notice, this list of conditions and the following disclaimer in the
   51.14 + *       documentation and/or other materials provided with the distribution.
   51.15 + *     * Neither the name of XenSource Inc. nor the names of its contributors
   51.16 + *       may be used to endorse or promote products derived from this software
   51.17 + *       without specific prior written permission.
   51.18 + *
   51.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   51.20 + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   51.21 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   51.22 + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
   51.23 + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
   51.24 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   51.25 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
   51.26 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   51.27 + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   51.28 + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   51.29 + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   51.30 + */
   51.31 +
   51.32 +
   51.33 +#include <errno.h>
   51.34 +#include <libaio.h>
   51.35 +#include <fcntl.h>
   51.36 +#include <stdio.h>
   51.37 +#include <stdlib.h>
   51.38 +#include <unistd.h>
   51.39 +#include <sys/statvfs.h>
   51.40 +#include <sys/stat.h>
   51.41 +#include <sys/ioctl.h>
   51.42 +#include <linux/fs.h>
   51.43 +
   51.44 +#include "tapdisk.h"
   51.45 +#include "tapdisk-driver.h"
   51.46 +#include "tapdisk-interface.h"
   51.47 +
   51.48 +#define MAX_AIO_REQS         TAPDISK_DATA_REQUESTS
   51.49 +
   51.50 +struct tdaio_state;
   51.51 +
   51.52 +struct aio_request {
   51.53 +	td_request_t         treq;
   51.54 +	struct tiocb         tiocb;
   51.55 +	struct tdaio_state  *state;
   51.56 +};
   51.57 +
   51.58 +struct tdaio_state {
   51.59 +	int                  fd;
   51.60 +	td_driver_t         *driver;
   51.61 +
   51.62 +	int                  aio_free_count;	
   51.63 +	struct aio_request   aio_requests[MAX_AIO_REQS];
   51.64 +	struct aio_request  *aio_free_list[MAX_AIO_REQS];
   51.65 +};
   51.66 +
   51.67 +/*Get Image size, secsize*/
   51.68 +static int tdaio_get_image_info(int fd, td_disk_info_t *info)
   51.69 +{
   51.70 +	int ret;
   51.71 +	long size;
   51.72 +	unsigned long total_size;
   51.73 +	struct statvfs statBuf;
   51.74 +	struct stat stat;
   51.75 +
   51.76 +	ret = fstat(fd, &stat);
   51.77 +	if (ret != 0) {
   51.78 +		DPRINTF("ERROR: fstat failed, Couldn't stat image");
   51.79 +		return -EINVAL;
   51.80 +	}
   51.81 +
   51.82 +	if (S_ISBLK(stat.st_mode)) {
   51.83 +		/*Accessing block device directly*/
   51.84 +		info->size = 0;
   51.85 +		if (ioctl(fd,BLKGETSIZE,&info->size)!=0) {
   51.86 +			DPRINTF("ERR: BLKGETSIZE failed, couldn't stat image");
   51.87 +			return -EINVAL;
   51.88 +		}
   51.89 +
   51.90 +		DPRINTF("Image size: \n\tpre sector_shift  [%llu]\n\tpost "
   51.91 +			"sector_shift [%llu]\n",
   51.92 +			(long long unsigned)(info->size << SECTOR_SHIFT),
   51.93 +			(long long unsigned)info->size);
   51.94 +
   51.95 +		/*Get the sector size*/
   51.96 +#if defined(BLKSSZGET)
   51.97 +		{
   51.98 +			int arg;
   51.99 +			info->sector_size = DEFAULT_SECTOR_SIZE;
  51.100 +			ioctl(fd, BLKSSZGET, &info->sector_size);
  51.101 +			
  51.102 +			if (info->sector_size != DEFAULT_SECTOR_SIZE)
  51.103 +				DPRINTF("Note: sector size is %ld (not %d)\n",
  51.104 +					info->sector_size, DEFAULT_SECTOR_SIZE);
  51.105 +		}
  51.106 +#else
  51.107 +		info->sector_size = DEFAULT_SECTOR_SIZE;
  51.108 +#endif
  51.109 +
  51.110 +	} else {
  51.111 +		/*Local file? try fstat instead*/
  51.112 +		info->size = (stat.st_size >> SECTOR_SHIFT);
  51.113 +		info->sector_size = DEFAULT_SECTOR_SIZE;
  51.114 +		DPRINTF("Image size: \n\tpre sector_shift  [%llu]\n\tpost "
  51.115 +			"sector_shift [%llu]\n",
  51.116 +			(long long unsigned)(info->size << SECTOR_SHIFT),
  51.117 +			(long long unsigned)info->size);
  51.118 +	}
  51.119 +
  51.120 +	if (info->size == 0) {		
  51.121 +		info->size =((uint64_t) 16836057);
  51.122 +		info->sector_size = DEFAULT_SECTOR_SIZE;
  51.123 +	}
  51.124 +	info->info = 0;
  51.125 +
  51.126 +	return 0;
  51.127 +}
  51.128 +
  51.129 +/* Open the disk file and initialize aio state. */
  51.130 +int tdaio_open(td_driver_t *driver, const char *name, td_flag_t flags)
  51.131 +{
  51.132 +	int i, fd, ret, o_flags;
  51.133 +	struct tdaio_state *prv;
  51.134 +
  51.135 +	ret = 0;
  51.136 +	prv = (struct tdaio_state *)driver->data;
  51.137 +
  51.138 +	DPRINTF("block-aio open('%s')", name);
  51.139 +
  51.140 +	memset(prv, 0, sizeof(struct tdaio_state));
  51.141 +
  51.142 +	prv->aio_free_count = MAX_AIO_REQS;
  51.143 +	for (i = 0; i < MAX_AIO_REQS; i++)
  51.144 +		prv->aio_free_list[i] = &prv->aio_requests[i];
  51.145 +
  51.146 +	/* Open the file */
  51.147 +	o_flags = O_DIRECT | O_LARGEFILE | 
  51.148 +		((flags & TD_OPEN_RDONLY) ? O_RDONLY : O_RDWR);
  51.149 +        fd = open(name, o_flags);
  51.150 +
  51.151 +        if ( (fd == -1) && (errno == EINVAL) ) {
  51.152 +
  51.153 +                /* Maybe O_DIRECT isn't supported. */
  51.154 +		o_flags &= ~O_DIRECT;
  51.155 +                fd = open(name, o_flags);
  51.156 +                if (fd != -1) DPRINTF("WARNING: Accessing image without"
  51.157 +                                     "O_DIRECT! (%s)\n", name);
  51.158 +
  51.159 +        } else if (fd != -1) DPRINTF("open(%s) with O_DIRECT\n", name);
  51.160 +	
  51.161 +        if (fd == -1) {
  51.162 +		DPRINTF("Unable to open [%s] (%d)!\n", name, 0 - errno);
  51.163 +        	ret = 0 - errno;
  51.164 +        	goto done;
  51.165 +        }
  51.166 +
  51.167 +	ret = tdaio_get_image_info(fd, &driver->info);
  51.168 +	if (ret) {
  51.169 +		close(fd);
  51.170 +		goto done;
  51.171 +	}
  51.172 +
  51.173 +        prv->fd = fd;
  51.174 +
  51.175 +done:
  51.176 +	return ret;	
  51.177 +}
  51.178 +
  51.179 +void tdaio_complete(void *arg, struct tiocb *tiocb, int err)
  51.180 +{
  51.181 +	struct aio_request *aio = (struct aio_request *)arg;
  51.182 +	struct tdaio_state *prv = aio->state;
  51.183 +
  51.184 +	td_complete_request(aio->treq, err);
  51.185 +	prv->aio_free_list[prv->aio_free_count++] = aio;
  51.186 +}
  51.187 +
  51.188 +void tdaio_queue_read(td_driver_t *driver, td_request_t treq)
  51.189 +{
  51.190 +	int size;
  51.191 +	uint64_t offset;
  51.192 +	struct aio_request *aio;
  51.193 +	struct tdaio_state *prv;
  51.194 +
  51.195 +	prv    = (struct tdaio_state *)driver->data;
  51.196 +	size   = treq.secs * driver->info.sector_size;
  51.197 +	offset = treq.sec  * (uint64_t)driver->info.sector_size;
  51.198 +
  51.199 +	if (prv->aio_free_count == 0)
  51.200 +		goto fail;
  51.201 +
  51.202 +	aio        = prv->aio_free_list[--prv->aio_free_count];
  51.203 +	aio->treq  = treq;
  51.204 +	aio->state = prv;
  51.205 +
  51.206 +	td_prep_read(&aio->tiocb, prv->fd, treq.buf,
  51.207 +		     size, offset, tdaio_complete, aio);
  51.208 +	td_queue_tiocb(driver, &aio->tiocb);
  51.209 +
  51.210 +	return;
  51.211 +
  51.212 +fail:
  51.213 +	td_complete_request(treq, -EBUSY);
  51.214 +}
  51.215 +
  51.216 +void tdaio_queue_write(td_driver_t *driver, td_request_t treq)
  51.217 +{
  51.218 +	int size;
  51.219 +	uint64_t offset;
  51.220 +	struct aio_request *aio;
  51.221 +	struct tdaio_state *prv;
  51.222 +
  51.223 +	prv     = (struct tdaio_state *)driver->data;
  51.224 +	size    = treq.secs * driver->info.sector_size;
  51.225 +	offset  = treq.sec  * (uint64_t)driver->info.sector_size;
  51.226 +
  51.227 +	if (prv->aio_free_count == 0)
  51.228 +		goto fail;
  51.229 +
  51.230 +	aio        = prv->aio_free_list[--prv->aio_free_count];
  51.231 +	aio->treq  = treq;
  51.232 +	aio->state = prv;
  51.233 +
  51.234 +	td_prep_write(&aio->tiocb, prv->fd, treq.buf,
  51.235 +		      size, offset, tdaio_complete, aio);
  51.236 +	td_queue_tiocb(driver, &aio->tiocb);
  51.237 +
  51.238 +	return;
  51.239 +
  51.240 +fail:
  51.241 +	td_complete_request(treq, -EBUSY);
  51.242 +}
  51.243 +
  51.244 +int tdaio_close(td_driver_t *driver)
  51.245 +{
  51.246 +	struct tdaio_state *prv = (struct tdaio_state *)driver->data;
  51.247 +	
  51.248 +	close(prv->fd);
  51.249 +
  51.250 +	return 0;
  51.251 +}
  51.252 +
  51.253 +int tdaio_get_parent_id(td_driver_t *driver, td_disk_id_t *id)
  51.254 +{
  51.255 +	return TD_NO_PARENT;
  51.256 +}
  51.257 +
  51.258 +int tdaio_validate_parent(td_driver_t *driver,
  51.259 +			  td_driver_t *pdriver, td_flag_t flags)
  51.260 +{
  51.261 +	return -EINVAL;
  51.262 +}
  51.263 +
  51.264 +struct tap_disk tapdisk_aio = {
  51.265 +	.disk_type          = "tapdisk_aio",
  51.266 +	.flags              = 0,
  51.267 +	.private_data_size  = sizeof(struct tdaio_state),
  51.268 +	.td_open            = tdaio_open,
  51.269 +	.td_close           = tdaio_close,
  51.270 +	.td_queue_read      = tdaio_queue_read,
  51.271 +	.td_queue_write     = tdaio_queue_write,
  51.272 +	.td_get_parent_id   = tdaio_get_parent_id,
  51.273 +	.td_validate_parent = tdaio_validate_parent,
  51.274 +	.td_debug           = NULL,
  51.275 +};
    52.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    52.2 +++ b/tools/blktap2/drivers/block-cache.c	Wed Jun 17 17:24:56 2009 -0700
    52.3 @@ -0,0 +1,787 @@
    52.4 +/* 
    52.5 + * Copyright (c) 2008, XenSource Inc.
    52.6 + * All rights reserved.
    52.7 + *
    52.8 + * Redistribution and use in source and binary forms, with or without
    52.9 + * modification, are permitted provided that the following conditions are met:
   52.10 + *     * Redistributions of source code must retain the above copyright
   52.11 + *       notice, this list of conditions and the following disclaimer.
   52.12 + *     * Redistributions in binary form must reproduce the above copyright
   52.13 + *       notice, this list of conditions and the following disclaimer in the
   52.14 + *       documentation and/or other materials provided with the distribution.
   52.15 + *     * Neither the name of XenSource Inc. nor the names of its contributors
   52.16 + *       may be used to endorse or promote products derived from this software
   52.17 + *       without specific prior written permission.
   52.18 + *
   52.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   52.20 + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   52.21 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   52.22 + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
   52.23 + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
   52.24 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   52.25 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
   52.26 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   52.27 + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   52.28 + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   52.29 + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   52.30 + */
   52.31 +#include <errno.h>
   52.32 +#include <fcntl.h>
   52.33 +#include <unistd.h>
   52.34 +#include <stdlib.h>
   52.35 +#include <sys/mman.h>
   52.36 +
   52.37 +#include "tapdisk.h"
   52.38 +#include "tapdisk-utils.h"
   52.39 +#include "tapdisk-driver.h"
   52.40 +#include "tapdisk-server.h"
   52.41 +#include "tapdisk-interface.h"
   52.42 +
   52.43 +#ifdef DEBUG
   52.44 +#define DBG(_f, _a...) tlog_write(TLOG_DBG, _f, ##_a)
   52.45 +#else
   52.46 +#define DBG(_f, _a...) ((void)0)
   52.47 +#endif
   52.48 +
   52.49 +#define WARN(_f, _a...) tlog_write(TLOG_WARN, _f, ##_a)
   52.50 +
   52.51 +#define RADIX_TREE_PAGE_SHIFT           12 /* 4K pages */
   52.52 +#define RADIX_TREE_PAGE_SIZE            (1 << RADIX_TREE_PAGE_SHIFT)
   52.53 +
   52.54 +#define RADIX_TREE_NODE_SHIFT           9 /* 512B nodes */
   52.55 +#define RADIX_TREE_NODE_SIZE            (1 << RADIX_TREE_NODE_SHIFT)
   52.56 +#define RADIX_TREE_NODE_MASK            (RADIX_TREE_NODE_SIZE - 1)
   52.57 +
   52.58 +#define BLOCK_CACHE_NODES_PER_PAGE      (1 << (RADIX_TREE_PAGE_SHIFT - RADIX_TREE_NODE_SHIFT))
   52.59 +
   52.60 +#define BLOCK_CACHE_MAX_SIZE            (10 << 20) /* 100MB cache */
   52.61 +#define BLOCK_CACHE_REQUESTS            (TAPDISK_DATA_REQUESTS << 3)
   52.62 +#define BLOCK_CACHE_PAGE_IDLETIME       60
   52.63 +
   52.64 +typedef struct radix_tree               radix_tree_t;
   52.65 +typedef struct radix_tree_node          radix_tree_node_t;
   52.66 +typedef struct radix_tree_link          radix_tree_link_t;
   52.67 +typedef struct radix_tree_leaf          radix_tree_leaf_t;
   52.68 +typedef struct radix_tree_page          radix_tree_page_t;
   52.69 +
   52.70 +typedef struct block_cache              block_cache_t;
   52.71 +typedef struct block_cache_request      block_cache_request_t;
   52.72 +typedef struct block_cache_stats        block_cache_stats_t;
   52.73 +
   52.74 +struct radix_tree_page {
   52.75 +	char                           *buf;
   52.76 +	size_t                          size;
   52.77 +	uint64_t                        sec;
   52.78 +	radix_tree_link_t              *owners[BLOCK_CACHE_NODES_PER_PAGE];
   52.79 +};
   52.80 +
   52.81 +struct radix_tree_leaf {
   52.82 +	radix_tree_page_t              *page;
   52.83 +	char                           *buf;
   52.84 +};
   52.85 +
   52.86 +struct radix_tree_link {
   52.87 +	uint32_t                        time;
   52.88 +	union {
   52.89 +		radix_tree_node_t      *next;
   52.90 +		radix_tree_leaf_t       leaf;
   52.91 +	} u;
   52.92 +};
   52.93 +
   52.94 +struct radix_tree_node {
   52.95 +	int                             height;
   52.96 +	radix_tree_link_t               links[RADIX_TREE_NODE_SIZE];
   52.97 +};
   52.98 +
   52.99 +struct radix_tree {
  52.100 +	int                             height;
  52.101 +	uint64_t                        size;
  52.102 +	uint32_t                        nodes;
  52.103 +	radix_tree_node_t              *root;
  52.104 +
  52.105 +	block_cache_t                  *cache;
  52.106 +};
  52.107 +
  52.108 +struct block_cache_request {
  52.109 +	int                             err;
  52.110 +	char                           *buf;
  52.111 +	uint64_t                        secs;
  52.112 +	td_request_t                    treq;
  52.113 +	block_cache_t                  *cache;
  52.114 +};
  52.115 +
  52.116 +struct block_cache_stats {
  52.117 +	uint64_t                        reads;
  52.118 +	uint64_t                        hits;
  52.119 +	uint64_t                        misses;
  52.120 +	uint64_t                        prunes;
  52.121 +};
  52.122 +
  52.123 +struct block_cache {
  52.124 +	int                             ptype;
  52.125 +	char                           *name;
  52.126 +
  52.127 +	uint64_t                        sectors;
  52.128 +
  52.129 +	block_cache_request_t           requests[BLOCK_CACHE_REQUESTS];
  52.130 +	block_cache_request_t          *request_free_list[BLOCK_CACHE_REQUESTS];
  52.131 +	int                             requests_free;
  52.132 +
  52.133 +	event_id_t                      timeout_id;
  52.134 +
  52.135 +	radix_tree_t                    tree;
  52.136 +
  52.137 +	block_cache_stats_t             stats;
  52.138 +};
  52.139 +
  52.140 +static inline uint64_t
  52.141 +radix_tree_calculate_size(int height)
  52.142 +{
  52.143 +	return (uint64_t)RADIX_TREE_NODE_SIZE <<
  52.144 +	  (height * RADIX_TREE_NODE_SHIFT);
  52.145 +}
  52.146 +
  52.147 +static inline int
  52.148 +radix_tree_calculate_height(uint64_t sectors)
  52.149 +{
  52.150 +	int height;
  52.151 +	uint64_t tree_size;
  52.152 +
  52.153 +	height = 1;  /* always allocate root node */
  52.154 +	tree_size = radix_tree_calculate_size(height);
  52.155 +	while (sectors > tree_size)
  52.156 +		tree_size = radix_tree_calculate_size(++height);
  52.157 +
  52.158 +	return height;
  52.159 +}
  52.160 +
  52.161 +static inline int
  52.162 +radix_tree_index(radix_tree_node_t *node, uint64_t sector)
  52.163 +{
  52.164 +	return ((sector >> (node->height * RADIX_TREE_NODE_SHIFT)) &
  52.165 +		RADIX_TREE_NODE_MASK);
  52.166 +}
  52.167 +
  52.168 +static inline int
  52.169 +radix_tree_node_contains_leaves(radix_tree_t *tree, radix_tree_node_t *node)
  52.170 +{
  52.171 +	return (node->height == 0);
  52.172 +}
  52.173 +
  52.174 +static inline int
  52.175 +radix_tree_node_is_root(radix_tree_t *tree, radix_tree_node_t *node)
  52.176 +{
  52.177 +	return (node->height == tree->height);
  52.178 +}
  52.179 +
  52.180 +static inline uint64_t
  52.181 +radix_tree_size(radix_tree_t *tree)
  52.182 +{
  52.183 +	return tree->size + tree->nodes * sizeof(radix_tree_node_t);
  52.184 +}
  52.185 +
  52.186 +static inline void
  52.187 +radix_tree_clear_link(radix_tree_link_t *link)
  52.188 +{
  52.189 +	if (link)
  52.190 +		memset(link, 0, sizeof(radix_tree_link_t));
  52.191 +}
  52.192 +
  52.193 +static inline radix_tree_node_t *
  52.194 +radix_tree_allocate_node(radix_tree_t *tree, int height)
  52.195 +{
  52.196 +	radix_tree_node_t *node;
  52.197 +
  52.198 +	node = calloc(1, sizeof(radix_tree_node_t));
  52.199 +	if (!node)
  52.200 +		return NULL;
  52.201 +
  52.202 +	node->height = height;
  52.203 +	tree->nodes++;
  52.204 +
  52.205 +	return node;
  52.206 +}
  52.207 +
  52.208 +static inline radix_tree_node_t *
  52.209 +radix_tree_allocate_child_node(radix_tree_t *tree, radix_tree_node_t *parent)
  52.210 +{
  52.211 +	return radix_tree_allocate_node(tree, parent->height - 1);
  52.212 +}
  52.213 +
  52.214 +void
  52.215 +radix_tree_free_node(radix_tree_t *tree, radix_tree_node_t *node)
  52.216 +{
  52.217 +	if (!node)
  52.218 +		return;
  52.219 +
  52.220 +	free(node);
  52.221 +	tree->nodes--;
  52.222 +}
  52.223 +
  52.224 +static inline radix_tree_page_t *
  52.225 +radix_tree_allocate_page(radix_tree_t *tree,
  52.226 +			 char *buf, uint64_t sec, size_t size)
  52.227 +{
  52.228 +	radix_tree_page_t *page;
  52.229 +
  52.230 +	page = calloc(1, sizeof(radix_tree_page_t));
  52.231 +	if (!page)
  52.232 +		return NULL;
  52.233 +
  52.234 +	page->buf   = buf;
  52.235 +	page->sec   = sec;
  52.236 +	page->size  = size;
  52.237 +	tree->size += size;
  52.238 +
  52.239 +	return page;
  52.240 +}
  52.241 +
  52.242 +static inline void
  52.243 +radix_tree_free_page(radix_tree_t *tree, radix_tree_page_t *page)
  52.244 +{
  52.245 +	int i;
  52.246 +
  52.247 +	for (i = 0; i < page->size >> RADIX_TREE_NODE_SHIFT; i++)
  52.248 +		DBG("%s: ejecting sector 0x%llx\n",
  52.249 +		    tree->cache->name, page->sec + i);
  52.250 +
  52.251 +	tree->cache->stats.prunes += (page->size >> RADIX_TREE_NODE_SHIFT);
  52.252 +	tree->size -= page->size;
  52.253 +	free(page->buf);
  52.254 +	free(page);
  52.255 +}
  52.256 +
  52.257 +/*
  52.258 + * remove a leaf and the shared radix_tree_page_t containing its buffer.
  52.259 + * leaves are deleted, nodes are not; gc will reap the nodes later.
  52.260 + */
  52.261 +static void
  52.262 +radix_tree_remove_page(radix_tree_t *tree, radix_tree_page_t *page)
  52.263 +{
  52.264 +	int i;
  52.265 +
  52.266 +	if (!page)
  52.267 +		return;
  52.268 +
  52.269 +	for (i = 0; i < BLOCK_CACHE_NODES_PER_PAGE; i++)
  52.270 +		radix_tree_clear_link(page->owners[i]);
  52.271 +
  52.272 +	radix_tree_free_page(tree, page);
  52.273 +}
  52.274 +
  52.275 +static void
  52.276 +radix_tree_insert_leaf(radix_tree_t *tree, radix_tree_link_t *link,
  52.277 +		       radix_tree_page_t *page, off_t off)
  52.278 +{
  52.279 +	int i;
  52.280 +
  52.281 +	if (off + RADIX_TREE_NODE_SIZE > page->size)
  52.282 +		return;
  52.283 +
  52.284 +	for (i = 0; i < BLOCK_CACHE_NODES_PER_PAGE; i++) {
  52.285 +		if (page->owners[i])
  52.286 +			continue;
  52.287 +
  52.288 +		page->owners[i]   = link;
  52.289 +		link->u.leaf.page = page;
  52.290 +		link->u.leaf.buf  = page->buf + off;
  52.291 +
  52.292 +		break;
  52.293 +	}
  52.294 +}
  52.295 +
  52.296 +static char *
  52.297 +radix_tree_find_leaf(radix_tree_t *tree, uint64_t sector)
  52.298 +{
  52.299 +	int idx;
  52.300 +	struct timeval now;
  52.301 +	radix_tree_link_t *link;
  52.302 +	radix_tree_node_t *node;
  52.303 +
  52.304 +	node = tree->root;
  52.305 +	gettimeofday(&now, NULL);
  52.306 +
  52.307 +	do {
  52.308 +		idx        = radix_tree_index(node, sector);
  52.309 +		link       = node->links + idx;
  52.310 +		link->time = now.tv_sec;
  52.311 +
  52.312 +		if (radix_tree_node_contains_leaves(tree, node))
  52.313 +			return link->u.leaf.buf;
  52.314 +
  52.315 +		if (!link->u.next)
  52.316 +			return NULL;
  52.317 +
  52.318 +		node = link->u.next;
  52.319 +	} while (1);
  52.320 +}
  52.321 +
  52.322 +static char *
  52.323 +radix_tree_add_leaf(radix_tree_t *tree, uint64_t sector,
  52.324 +		    radix_tree_page_t *page, off_t off)
  52.325 +{
  52.326 +	int idx;
  52.327 +	struct timeval now;
  52.328 +	radix_tree_link_t *link;
  52.329 +	radix_tree_node_t *node;
  52.330 +
  52.331 +	node = tree->root;
  52.332 +	gettimeofday(&now, NULL);
  52.333 +
  52.334 +	do {
  52.335 +		idx        = radix_tree_index(node, sector);
  52.336 +		link       = node->links + idx;
  52.337 +		link->time = now.tv_sec;
  52.338 +
  52.339 +		if (radix_tree_node_contains_leaves(tree, node)) {
  52.340 +			radix_tree_remove_page(tree, link->u.leaf.page);
  52.341 +			radix_tree_insert_leaf(tree, link, page, off);
  52.342 +			return link->u.leaf.buf;
  52.343 +		}
  52.344 +
  52.345 +		if (!link->u.next) {
  52.346 +			link->u.next = radix_tree_allocate_child_node(tree,
  52.347 +								      node);
  52.348 +			if (!link->u.next)
  52.349 +				return NULL;
  52.350 +		}
  52.351 +
  52.352 +		node = link->u.next;
  52.353 +	} while (1);
  52.354 +}
  52.355 +
  52.356 +static int
  52.357 +radix_tree_add_leaves(radix_tree_t *tree, char *buf,
  52.358 +		      uint64_t sector, uint64_t sectors)
  52.359 +{
  52.360 +	int i;
  52.361 +	radix_tree_page_t *page;
  52.362 +
  52.363 +	page = radix_tree_allocate_page(tree, buf, sector,
  52.364 +					sectors << RADIX_TREE_NODE_SHIFT);
  52.365 +	if (!page)
  52.366 +		return -ENOMEM;
  52.367 +
  52.368 +	for (i = 0; i < sectors; i++)
  52.369 +		if (!radix_tree_add_leaf(tree, sector + i, 
  52.370 +					 page, (i << RADIX_TREE_NODE_SHIFT)))
  52.371 +			goto fail;
  52.372 +
  52.373 +	return 0;
  52.374 +
  52.375 +fail:
  52.376 +	page->buf = NULL;
  52.377 +	radix_tree_remove_page(tree, page);
  52.378 +	return -ENOMEM;
  52.379 +}
  52.380 +
  52.381 +static void
  52.382 +radix_tree_delete_branch(radix_tree_t *tree, radix_tree_node_t *node)
  52.383 +{
  52.384 +	int i;
  52.385 +	radix_tree_link_t *link;
  52.386 +
  52.387 +	if (!node)
  52.388 +		return;
  52.389 +
  52.390 +	for (i = 0; i < RADIX_TREE_NODE_SIZE; i++) {
  52.391 +		link = node->links + i;
  52.392 +
  52.393 +		if (radix_tree_node_contains_leaves(tree, node))
  52.394 +			radix_tree_remove_page(tree, link->u.leaf.page);
  52.395 +		else
  52.396 +			radix_tree_delete_branch(tree, link->u.next);
  52.397 +
  52.398 +		radix_tree_clear_link(link);
  52.399 +	}
  52.400 +
  52.401 +	radix_tree_free_node(tree, node);
  52.402 +}
  52.403 +
  52.404 +static inline void
  52.405 +radix_tree_destroy(radix_tree_t *tree)
  52.406 +{
  52.407 +	radix_tree_delete_branch(tree, tree->root);
  52.408 +	tree->root = NULL;
  52.409 +}
  52.410 +
  52.411 +/*
  52.412 + * returns 1 if @node is empty after pruning, 0 otherwise
  52.413 + */
  52.414 +static int
  52.415 +radix_tree_prune_branch(radix_tree_t *tree,
  52.416 +			radix_tree_node_t *node, uint32_t now)
  52.417 +{
  52.418 +	int i, empty;
  52.419 +	radix_tree_link_t *link;
  52.420 +
  52.421 +	empty = 1;
  52.422 +	if (!node)
  52.423 +		return empty;
  52.424 +
  52.425 +	for (i = 0; i < RADIX_TREE_NODE_SIZE; i++) {
  52.426 +		link = node->links + i;
  52.427 +
  52.428 +		if (now - link->time < BLOCK_CACHE_PAGE_IDLETIME) {
  52.429 +			if (radix_tree_node_contains_leaves(tree, node)) {
  52.430 +				empty = 0;
  52.431 +				continue;
  52.432 +			}
  52.433 +
  52.434 +			if (radix_tree_prune_branch(tree, link->u.next, now))
  52.435 +				radix_tree_clear_link(link);
  52.436 +			else
  52.437 +				empty = 0;
  52.438 +
  52.439 +			continue;
  52.440 +		}
  52.441 +
  52.442 +		if (radix_tree_node_contains_leaves(tree, node))
  52.443 +			radix_tree_remove_page(tree, link->u.leaf.page);
  52.444 +		else
  52.445 +			radix_tree_delete_branch(tree, link->u.next);
  52.446 +
  52.447 +		radix_tree_clear_link(link);
  52.448 +	}
  52.449 +
  52.450 +	if (empty && !radix_tree_node_is_root(tree, node))
  52.451 +		radix_tree_free_node(tree, node);
  52.452 +
  52.453 +	return empty;
  52.454 +}
  52.455 +
  52.456 +/*
  52.457 + * walk tree and free any node that has been idle for too long
  52.458 + */
  52.459 +static void
  52.460 +radix_tree_prune(radix_tree_t *tree)
  52.461 +{
  52.462 +	struct timeval now;
  52.463 +
  52.464 +	if (!tree->root)
  52.465 +		return;
  52.466 +
  52.467 +	DPRINTF("tree %s has %"PRIu64" bytes\n",
  52.468 +		tree->cache->name, tree->size);
  52.469 +
  52.470 +	gettimeofday(&now, NULL);
  52.471 +	radix_tree_prune_branch(tree, tree->root, now.tv_sec);
  52.472 +
  52.473 +	DPRINTF("tree %s now has %"PRIu64" bytes\n",
  52.474 +		tree->cache->name, tree->size);
  52.475 +}
  52.476 +
  52.477 +static inline int
  52.478 +radix_tree_initialize(radix_tree_t *tree, uint64_t sectors)
  52.479 +{
  52.480 +	tree->height = radix_tree_calculate_height(sectors);
  52.481 +	tree->root   = radix_tree_allocate_node(tree, tree->height);
  52.482 +	if (!tree->root)
  52.483 +		return -ENOMEM;
  52.484 +
  52.485 +	return 0;
  52.486 +}
  52.487 +
  52.488 +static inline void
  52.489 +radix_tree_free(radix_tree_t *tree)
  52.490 +{
  52.491 +	radix_tree_destroy(tree);
  52.492 +}
  52.493 +
  52.494 +static void
  52.495 +block_cache_prune_event(event_id_t id, char mode, void *private)
  52.496 +{
  52.497 +	radix_tree_t *tree;
  52.498 +	block_cache_t *cache;
  52.499 +
  52.500 +	cache = (block_cache_t *)private;
  52.501 +	tree  = &cache->tree;
  52.502 +
  52.503 +	radix_tree_prune(tree);
  52.504 +}
  52.505 +
  52.506 +static inline block_cache_request_t *
  52.507 +block_cache_get_request(block_cache_t *cache)
  52.508 +{
  52.509 +	if (!cache->requests_free)
  52.510 +		return NULL;
  52.511 +
  52.512 +	return cache->request_free_list[--cache->requests_free];
  52.513 +}
  52.514 +
  52.515 +static inline void
  52.516 +block_cache_put_request(block_cache_t *cache, block_cache_request_t *breq)
  52.517 +{
  52.518 +	memset(breq, 0, sizeof(block_cache_request_t));
  52.519 +	cache->request_free_list[cache->requests_free++] = breq;
  52.520 +}
  52.521 +
  52.522 +static int
  52.523 +block_cache_open(td_driver_t *driver, const char *name, td_flag_t flags)
  52.524 +{
  52.525 +	int i, err;
  52.526 +	radix_tree_t *tree;
  52.527 +	block_cache_t *cache;
  52.528 +
  52.529 +	if (!td_flag_test(flags, TD_OPEN_RDONLY))
  52.530 +		return -EINVAL;
  52.531 +
  52.532 +	if (driver->info.sector_size != RADIX_TREE_NODE_SIZE)
  52.533 +		return -EINVAL;
  52.534 +
  52.535 +	cache = (block_cache_t *)driver->data;
  52.536 +	err   = tapdisk_namedup(&cache->name, (char *)name);
  52.537 +	if (err)
  52.538 +		return -ENOMEM;
  52.539 +
  52.540 +	cache->sectors = driver->info.size;
  52.541 +
  52.542 +	tree = &cache->tree;
  52.543 +	err  = radix_tree_initialize(tree, cache->sectors);
  52.544 +	if (err)
  52.545 +		goto fail;
  52.546 +
  52.547 +	tree->cache = cache;
  52.548 +	cache->requests_free = BLOCK_CACHE_REQUESTS;
  52.549 +	for (i = 0; i < BLOCK_CACHE_REQUESTS; i++)
  52.550 +		cache->request_free_list[i] = cache->requests + i;
  52.551 +
  52.552 +	cache->timeout_id = tapdisk_server_register_event(SCHEDULER_POLL_TIMEOUT,
  52.553 +							  -1, /* dummy fd */
  52.554 +							  BLOCK_CACHE_PAGE_IDLETIME << 1,
  52.555 +							  block_cache_prune_event,
  52.556 +							  cache);
  52.557 +	if (cache->timeout_id < 0)
  52.558 +		goto fail;
  52.559 +
  52.560 +	DPRINTF("opening cache for %s, sectors: %"PRIu64", "
  52.561 +		"tree: %p, height: %d\n",
  52.562 +		cache->name, cache->sectors, tree, tree->height);
  52.563 +
  52.564 +	if (mlockall(MCL_CURRENT | MCL_FUTURE))
  52.565 +		DPRINTF("mlockall failed: %d\n", -errno);
  52.566 +
  52.567 +	return 0;
  52.568 +
  52.569 +fail:
  52.570 +	free(cache->name);
  52.571 +	radix_tree_free(&cache->tree);
  52.572 +	return err;
  52.573 +}
  52.574 +
  52.575 +static int
  52.576 +block_cache_close(td_driver_t *driver)
  52.577 +{
  52.578 +	radix_tree_t *tree;
  52.579 +	block_cache_t *cache;
  52.580 +
  52.581 +	cache = (block_cache_t *)driver->data;
  52.582 +	tree  = &cache->tree;
  52.583 +
  52.584 +	DPRINTF("closing cache for %s\n", cache->name);
  52.585 +
  52.586 +	tapdisk_server_unregister_event(cache->timeout_id);
  52.587 +	radix_tree_free(tree);
  52.588 +	free(cache->name);
  52.589 +
  52.590 +	return 0;
  52.591 +}
  52.592 +
  52.593 +static inline uint64_t
  52.594 +block_cache_hash(block_cache_t *cache, char *buf)
  52.595 +{
  52.596 +	int i, n;
  52.597 +	uint64_t cksm, *data;
  52.598 +
  52.599 +	return 0;
  52.600 +
  52.601 +	cksm = 0;
  52.602 +	data = (uint64_t *)buf;
  52.603 +	n    = RADIX_TREE_NODE_SIZE / sizeof(uint64_t);
  52.604 +
  52.605 +	for (i = 0; i < n; i++)
  52.606 +		cksm += data[i];
  52.607 +
  52.608 +	return ~cksm;
  52.609 +}
  52.610 +
  52.611 +static void
  52.612 +block_cache_hit(block_cache_t *cache, td_request_t treq, char *iov[])
  52.613 +{
  52.614 +	int i;
  52.615 +	off_t off;
  52.616 +
  52.617 +	cache->stats.hits += treq.secs;
  52.618 +
  52.619 +	for (i = 0; i < treq.secs; i++) {
  52.620 +		DBG("%s: block cache hit: sec 0x%08llx, hash: 0x%08llx\n",
  52.621 +		    cache->name, treq.sec + i, block_cache_hash(cache, iov[i]));
  52.622 +
  52.623 +		off = i << RADIX_TREE_NODE_SHIFT;
  52.624 +		memcpy(treq.buf + off, iov[i], RADIX_TREE_NODE_SIZE);
  52.625 +	}
  52.626 +
  52.627 +	td_complete_request(treq, 0);
  52.628 +}
  52.629 +
  52.630 +static void
  52.631 +block_cache_populate_cache(td_request_t clone, int err)
  52.632 +{
  52.633 +	int i;
  52.634 +	radix_tree_t *tree;
  52.635 +	block_cache_t *cache;
  52.636 +	block_cache_request_t *breq;
  52.637 +
  52.638 +	breq        = (block_cache_request_t *)clone.cb_data;
  52.639 +	cache       = breq->cache;
  52.640 +	tree        = &cache->tree;
  52.641 +	breq->secs -= clone.secs;
  52.642 +	breq->err   = (breq->err ? breq->err : err);
  52.643 +
  52.644 +	if (breq->secs)
  52.645 +		return;
  52.646 +
  52.647 +	if (breq->err) {
  52.648 +		free(breq->buf);
  52.649 +		goto out;
  52.650 +	}
  52.651 +
  52.652 +	for (i = 0; i < breq->treq.secs; i++) {
  52.653 +		off_t off = i << RADIX_TREE_NODE_SHIFT;
  52.654 +		DBG("%s: populating sec 0x%08llx\n",
  52.655 +		    cache->name, breq->treq.sec + i);
  52.656 +		memcpy(breq->treq.buf + off,
  52.657 +		       breq->buf + off, RADIX_TREE_NODE_SIZE);
  52.658 +	}
  52.659 +
  52.660 +	if (radix_tree_add_leaves(tree, breq->buf,
  52.661 +				  breq->treq.sec, breq->treq.secs))
  52.662 +		free(breq->buf);
  52.663 +
  52.664 +out:
  52.665 +	td_complete_request(breq->treq, breq->err);
  52.666 +	block_cache_put_request(cache, breq);
  52.667 +}
  52.668 +
  52.669 +static void
  52.670 +block_cache_miss(block_cache_t *cache, td_request_t treq)
  52.671 +{
  52.672 +	char *buf;
  52.673 +	size_t size;
  52.674 +	td_request_t clone;
  52.675 +	radix_tree_t *tree;
  52.676 +	block_cache_request_t *breq;
  52.677 +
  52.678 +	DBG("%s: block cache miss: sec 0x%08llx\n", cache->name, treq.sec);
  52.679 +
  52.680 +	clone = treq;
  52.681 +	tree  = &cache->tree;
  52.682 +	size  = treq.secs << RADIX_TREE_NODE_SHIFT;
  52.683 +
  52.684 +	cache->stats.misses += treq.secs;
  52.685 +
  52.686 +	if (radix_tree_size(tree) + size >= BLOCK_CACHE_MAX_SIZE)
  52.687 +		goto out;
  52.688 +
  52.689 +	breq = block_cache_get_request(cache);
  52.690 +	if (!breq)
  52.691 +		goto out;
  52.692 +
  52.693 +	if (posix_memalign((void **)&buf, RADIX_TREE_NODE_SIZE, size)) {
  52.694 +		block_cache_put_request(cache, breq);
  52.695 +		goto out;
  52.696 +	}
  52.697 +
  52.698 +	breq->treq    = treq;
  52.699 +	breq->secs    = treq.secs;
  52.700 +	breq->err     = 0;
  52.701 +	breq->buf     = buf;
  52.702 +	breq->cache   = cache;
  52.703 +
  52.704 +	clone.buf     = buf;
  52.705 +	clone.cb      = block_cache_populate_cache;
  52.706 +	clone.cb_data = breq;
  52.707 +
  52.708 +out:
  52.709 +	td_forward_request(clone);
  52.710 +}
  52.711 +
  52.712 +static void
  52.713 +block_cache_queue_read(td_driver_t *driver, td_request_t treq)
  52.714 +{
  52.715 +	int i;
  52.716 +	radix_tree_t *tree;
  52.717 +	block_cache_t *cache;
  52.718 +	char *iov[BLOCK_CACHE_NODES_PER_PAGE];
  52.719 +
  52.720 +	cache = (block_cache_t *)driver->data;
  52.721 +	tree  = &cache->tree;
  52.722 +
  52.723 +	cache->stats.reads += treq.secs;
  52.724 +
  52.725 +	if (treq.secs > BLOCK_CACHE_NODES_PER_PAGE)
  52.726 +		return td_forward_request(treq);
  52.727 +
  52.728 +	for (i = 0; i < treq.secs; i++) {
  52.729 +		iov[i] = radix_tree_find_leaf(tree, treq.sec + i);
  52.730 +		if (!iov[i])
  52.731 +			return block_cache_miss(cache, treq);
  52.732 +	}
  52.733 +
  52.734 +	return block_cache_hit(cache, treq, iov);
  52.735 +}
  52.736 +
  52.737 +static void
  52.738 +block_cache_queue_write(td_driver_t *driver, td_request_t treq)
  52.739 +{
  52.740 +	td_complete_request(treq, -EPERM);
  52.741 +}
  52.742 +
  52.743 +static int
  52.744 +block_cache_get_parent_id(td_driver_t *driver, td_disk_id_t *id)
  52.745 +{
  52.746 +	return -EINVAL;
  52.747 +}
  52.748 +
  52.749 +static int
  52.750 +block_cache_validate_parent(td_driver_t *driver,
  52.751 +			    td_driver_t *pdriver, td_flag_t flags)
  52.752 +{
  52.753 +	block_cache_t *cache;
  52.754 +
  52.755 +	if (!td_flag_test(pdriver->state, TD_DRIVER_RDONLY))
  52.756 +		return -EINVAL;
  52.757 +
  52.758 +	cache = (block_cache_t *)driver->data;
  52.759 +	if (strcmp(driver->name, pdriver->name))
  52.760 +		return -EINVAL;
  52.761 +
  52.762 +	return 0;
  52.763 +}
  52.764 +
  52.765 +static void
  52.766 +block_cache_debug(td_driver_t *driver)
  52.767 +{
  52.768 +	block_cache_t *cache;
  52.769 +	block_cache_stats_t *stats;
  52.770 +
  52.771 +	cache = (block_cache_t *)driver->data;
  52.772 +	stats = &cache->stats;
  52.773 +
  52.774 +	WARN("BLOCK CACHE %s\n", cache->name);
  52.775 +	WARN("reads: %"PRIu64", hits: %"PRIu64", misses: %"PRIu64", prunes: %"PRIu64"\n",
  52.776 +	     stats->reads, stats->hits, stats->misses, stats->prunes);
  52.777 +}
  52.778 +
  52.779 +struct tap_disk tapdisk_block_cache = {
  52.780 +	.disk_type                  = "tapdisk_block_cache",
  52.781 +	.flags                      = 0,
  52.782 +	.private_data_size          = sizeof(block_cache_t),
  52.783 +	.td_open                    = block_cache_open,
  52.784 +	.td_close                   = block_cache_close,
  52.785 +	.td_queue_read              = block_cache_queue_read,
  52.786 +	.td_queue_write             = block_cache_queue_write,
  52.787 +	.td_get_parent_id           = block_cache_get_parent_id,
  52.788 +	.td_validate_parent         = block_cache_validate_parent,
  52.789 +	.td_debug                   = block_cache_debug,
  52.790 +};
    53.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    53.2 +++ b/tools/blktap2/drivers/block-log.c	Wed Jun 17 17:24:56 2009 -0700
    53.3 @@ -0,0 +1,688 @@
    53.4 +/* 
    53.5 + * Copyright (c) 2008, XenSource Inc.
    53.6 + * All rights reserved.
    53.7 + *
    53.8 + * Redistribution and use in source and binary forms, with or without
    53.9 + * modification, are permitted provided that the following conditions are met:
   53.10 + *     * Redistributions of source code must retain the above copyright
   53.11 + *       notice, this list of conditions and the following disclaimer.
   53.12 + *     * Redistributions in binary form must reproduce the above copyright
   53.13 + *       notice, this list of conditions and the following disclaimer in the
   53.14 + *       documentation and/or other materials provided with the distribution.
   53.15 + *     * Neither the name of XenSource Inc. nor the names of its contributors
   53.16 + *       may be used to endorse or promote products derived from this software
   53.17 + *       without specific prior written permission.
   53.18 + *
   53.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   53.20 + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   53.21 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   53.22 + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
   53.23 + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
   53.24 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   53.25 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
   53.26 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   53.27 + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   53.28 + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   53.29 + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   53.30 + */
   53.31 +
   53.32 +/* Driver to sit on top of another disk and log writes, in order
   53.33 + * to synchronize two distinct disks
   53.34 + *
   53.35 + * On receipt of a control request it can export a list of dirty
   53.36 + * sectors in the following format:
   53.37 + * struct writerange {
   53.38 + *   u64 sector;
   53.39 + *   u32 count;
   53.40 + * }
   53.41 + * terminated by { 0, 0 }
   53.42 + */
   53.43 +
   53.44 +#include <errno.h>
   53.45 +#include <stdio.h>
   53.46 +#include <fcntl.h>
   53.47 +#include <unistd.h>
   53.48 +#include <stdlib.h>
   53.49 +#include <sys/mman.h>
   53.50 +#include <sys/socket.h>
   53.51 +#include <sys/un.h>
   53.52 +
   53.53 +#include "log.h"
   53.54 +#include "tapdisk.h"
   53.55 +#include "tapdisk-server.h"
   53.56 +#include "tapdisk-driver.h"
   53.57 +#include "tapdisk-interface.h"
   53.58 +
   53.59 +#define MAX_CONNECTIONS 1
   53.60 +
   53.61 +typedef struct poll_fd {
   53.62 +  int          fd;
   53.63 +  event_id_t   id;
   53.64 +} poll_fd_t;
   53.65 +
   53.66 +struct tdlog_state {
   53.67 +  uint64_t     size;
   53.68 +
   53.69 +  void*        writelog;
   53.70 +
   53.71 +  char*        ctlpath;
   53.72 +  poll_fd_t    ctl;
   53.73 +
   53.74 +  int          connected;
   53.75 +  poll_fd_t    connections[MAX_CONNECTIONS];
   53.76 +
   53.77 +  char*        shmpath;
   53.78 +  void*        shm;
   53.79 +
   53.80 +  log_sring_t* sring;
   53.81 +  log_back_ring_t bring;
   53.82 +};
   53.83 +
   53.84 +#define BDPRINTF(_f, _a...) syslog (LOG_DEBUG, "log: " _f "\n", ## _a)
   53.85 +
   53.86 +#define BWPRINTF(_f, _a...) syslog (LOG_WARNING, "log: " _f "\n", ## _a)
   53.87 +
   53.88 +static void ctl_accept(event_id_t, char, void *);
   53.89 +static void ctl_request(event_id_t, char, void *);
   53.90 +
   53.91 +/* -- write log -- */
   53.92 +
   53.93 +/* large flat bitmaps don't scale particularly well either in size or scan
   53.94 + * time, but they'll do for now */
   53.95 +#define BITS_PER_LONG (sizeof(unsigned long) * 8)
   53.96 +#define BITS_TO_LONGS(bits) (((bits)+BITS_PER_LONG-1)/BITS_PER_LONG)
   53.97 +
   53.98 +#define BITMAP_ENTRY(_nr, _bmap) ((unsigned long*)(_bmap))[(_nr)/BITS_PER_LONG]
   53.99 +#define BITMAP_SHIFT(_nr) ((_nr) % BITS_PER_LONG)
  53.100 +
  53.101 +static inline int test_bit(int nr, void* bmap)
  53.102 +{
  53.103 +  return (BITMAP_ENTRY(nr, bmap) >> BITMAP_SHIFT(nr)) & 1;
  53.104 +}
  53.105 +
  53.106 +static inline void clear_bit(int nr, void* bmap)
  53.107 +{
  53.108 +  BITMAP_ENTRY(nr, bmap) &= ~(1UL << BITMAP_SHIFT(nr));
  53.109 +}
  53.110 +
  53.111 +static inline void set_bit(int nr, void* bmap)
  53.112 +{
  53.113 +  BITMAP_ENTRY(nr, bmap) |= (1UL << BITMAP_SHIFT(nr));
  53.114 +}
  53.115 +
  53.116 +static inline int bitmap_size(uint64_t sz)
  53.117 +{
  53.118 +  return sz >> 3;
  53.119 +}
  53.120 +
  53.121 +static int writelog_create(struct tdlog_state *s)
  53.122 +{
  53.123 +  uint64_t bmsize;
  53.124 +
  53.125 +  bmsize = bitmap_size(s->size);
  53.126 +
  53.127 +  BDPRINTF("allocating %"PRIu64" bytes for dirty bitmap", bmsize);
  53.128 +
  53.129 +  if (!(s->writelog = calloc(bmsize, 1))) {
  53.130 +    BWPRINTF("could not allocate dirty bitmap of size %"PRIu64, bmsize);
  53.131 +    return -1;
  53.132 +  }
  53.133 +
  53.134 +  return 0;
  53.135 +}
  53.136 +
  53.137 +static int writelog_free(struct tdlog_state *s)
  53.138 +{
  53.139 +  if (s->writelog)
  53.140 +    free(s->writelog);
  53.141 +
  53.142 +  return 0;
  53.143 +}
  53.144 +
  53.145 +static int writelog_set(struct tdlog_state* s, uint64_t sector, int count)
  53.146 +{
  53.147 +  int i;
  53.148 +
  53.149 +  for (i = 0; i < count; i++) 
  53.150 +    set_bit(sector + i, s->writelog);
  53.151 +
  53.152 +  return 0;
  53.153 +}
  53.154 +
  53.155 +/* if end is 0, clear to end of disk */
  53.156 +int writelog_clear(struct tdlog_state* s, uint64_t start, uint64_t end)
  53.157 +{
  53.158 +  if (!end)
  53.159 +    end = s->size;
  53.160 +
  53.161 +  /* clear to word boundaries */
  53.162 +  while (BITMAP_SHIFT(start))
  53.163 +    clear_bit(start++, s->writelog);
  53.164 +  while (BITMAP_SHIFT(end))
  53.165 +    clear_bit(end--, s->writelog);
  53.166 +
  53.167 +  memset(s->writelog + start / BITS_PER_LONG, 0, (end - start) >> 3);
  53.168 +
  53.169 +  return 0;
  53.170 +}
  53.171 +
  53.172 +/* returns last block exported (may not be end of disk if shm region
  53.173 + * overflows) */
  53.174 +static uint64_t writelog_export(struct tdlog_state* s)
  53.175 +{
  53.176 +  struct disk_range* range = s->shm;
  53.177 +  uint64_t i = 0;
  53.178 +
  53.179 +  BDPRINTF("sector count: %"PRIu64, s->size);
  53.180 +
  53.181 +  for (i = 0; i < s->size; i++) {
  53.182 +    if (test_bit(i, s->writelog)) {
  53.183 +      /* range start */
  53.184 +      range->sector = i;
  53.185 +      range->count = 1;
  53.186 +      /* find end */
  53.187 +      for (i++; i < s->size && test_bit(i, s->writelog); i++)
  53.188 +	range->count++;
  53.189 +
  53.190 +      BDPRINTF("export: dirty extent %"PRIu64":%u",
  53.191 +	       range->sector, range->count);
  53.192 +      range++;
  53.193 +
  53.194 +      /* out of space in shared memory region */
  53.195 +      if ((void*)range >= bmend(s->shm)) {
  53.196 +	BDPRINTF("out of space in shm region at sector %"PRIu64, i);
  53.197 +	return i;
  53.198 +      }
  53.199 +
  53.200 +      /* undo forloop increment */
  53.201 +      i--;
  53.202 +    }
  53.203 +  }
  53.204 +
  53.205 +  /* NULL-terminate range list */
  53.206 +  range->sector = 0;
  53.207 +  range->count = 0;
  53.208 +
  53.209 +  return i;
  53.210 +}
  53.211 +
  53.212 +/* -- communication channel -- */
  53.213 +
  53.214 +/* remove FS special characters in up to len bytes of path */
  53.215 +static inline void path_escape(char* path, size_t len) {
  53.216 +  int i;
  53.217 +
  53.218 +  for (i = 0; i < len && path[i]; i++)
  53.219 +    if (strchr(":/", path[i]))
  53.220 +      path[i] = '_';
  53.221 +}
  53.222 +
  53.223 +static char* ctl_makepath(const char* name, const char* ext)
  53.224 +{
  53.225 +  char* res;
  53.226 +  char *file;
  53.227 +
  53.228 +  file = strrchr(name, '/');
  53.229 +  if (!file) {
  53.230 +    BWPRINTF("invalid name %s\n", name);
  53.231 +    return NULL;
  53.232 +  }
  53.233 +
  53.234 +  if (asprintf(&res, BLKTAP_CTRL_DIR "/log_%s.%s", file, ext) < 0) {
  53.235 +    BWPRINTF("could not allocate path");
  53.236 +    return NULL;
  53.237 +  }
  53.238 +
  53.239 +  path_escape(res + strlen(BLKTAP_CTRL_DIR) + 5, strlen(file));
  53.240 +
  53.241 +  return res;
  53.242 +}
  53.243 +
  53.244 +static int shmem_open(struct tdlog_state* s, const char* name)
  53.245 +{
  53.246 +  int i, l, fd;
  53.247 +
  53.248 +  /* device name -> path */
  53.249 +  if (asprintf(&s->shmpath, "/log_%s.wlog", name) < 0) {
  53.250 +    BWPRINTF("could not allocate shm path");
  53.251 +    return -1;
  53.252 +  }
  53.253 +
  53.254 +  path_escape(s->shmpath + 5, strlen(name));
  53.255 +
  53.256 +  if ((fd = shm_open(s->shmpath, O_CREAT|O_RDWR, 0750)) < 0) {
  53.257 +    BWPRINTF("could not open shared memory file %s: %s", s->shmpath,
  53.258 +	     strerror(errno));
  53.259 +    goto err;
  53.260 +  }
  53.261 +  if (ftruncate(fd, SHMSIZE) < 0) {
  53.262 +    BWPRINTF("error truncating shmem to size %u", SHMSIZE);
  53.263 +    close(fd);
  53.264 +    goto err;
  53.265 +  }
  53.266 +
  53.267 +  s->shm = mmap(NULL, SHMSIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
  53.268 +  close(fd);
  53.269 +  if (s->shm == MAP_FAILED) {
  53.270 +    BWPRINTF("could not mmap write log shm: %s", strerror(errno));
  53.271 +    goto err;
  53.272 +  }
  53.273 +  return 0;
  53.274 +
  53.275 +  err:
  53.276 +  s->shm = NULL;
  53.277 +  free(s->shmpath);
  53.278 +  s->shmpath = NULL;
  53.279 +  return -1;
  53.280 +}
  53.281 +
  53.282 +static int shmem_close(struct tdlog_state* s)
  53.283 +{
  53.284 +  if (s->shm) {
  53.285 +    munmap(s->shm, SHMSIZE);
  53.286 +    s->shm = NULL;
  53.287 +  }
  53.288 +
  53.289 +  if (s->shmpath) {
  53.290 +    shm_unlink(s->shmpath);
  53.291 +    s->shmpath = NULL;
  53.292 +  }
  53.293 +
  53.294 +  return 0;
  53.295 +}
  53.296 +
  53.297 +/* control socket */
  53.298 +
  53.299 +static int ctl_open(struct tdlog_state* s, const char* name)
  53.300 +{
  53.301 +  struct sockaddr_un saddr;
  53.302 +
  53.303 +  if (!(s->ctlpath = ctl_makepath(name, "ctl")))
  53.304 +    return -1;
  53.305 +
  53.306 +  if ((s->ctl.fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
  53.307 +    BWPRINTF("error opening control socket: %s", strerror(errno));
  53.308 +    goto err;
  53.309 +  }
  53.310 +
  53.311 +  memset(&saddr, 0, sizeof(saddr));
  53.312 +  saddr.sun_family = AF_UNIX;
  53.313 +  memcpy(saddr.sun_path, s->ctlpath, strlen(s->ctlpath));
  53.314 +  if (unlink(s->ctlpath) && errno != ENOENT) {
  53.315 +    BWPRINTF("error unlinking old socket path %s: %s", s->ctlpath,
  53.316 +	     strerror(errno));
  53.317 +    goto err_sock;
  53.318 +  }
  53.319 +    
  53.320 +  if (bind(s->ctl.fd, &saddr, sizeof(saddr)) < 0) {
  53.321 +    BWPRINTF("error binding control socket to %s: %s", s->ctlpath,
  53.322 +	     strerror(errno));
  53.323 +    goto err_sock;
  53.324 +  }
  53.325 +
  53.326 +  if (listen(s->ctl.fd, 1) < 0) {
  53.327 +    BWPRINTF("error listening on control socket: %s", strerror(errno));
  53.328 +    goto err_sock;
  53.329 +  }
  53.330 +
  53.331 +  s->ctl.id = tapdisk_server_register_event(SCHEDULER_POLL_READ_FD,
  53.332 +					    s->ctl.fd, 0, ctl_accept, s);
  53.333 +  if (s->ctl.id < 0) {
  53.334 +    BWPRINTF("error register event handler: %s", strerror(s->ctl.id));
  53.335 +    goto err_sock;
  53.336 +  }
  53.337 +
  53.338 +  return 0;
  53.339 +
  53.340 +  err_sock:
  53.341 +  close(s->ctl.fd);
  53.342 +  s->ctl.fd = -1;
  53.343 +  err:
  53.344 +  free(s->ctlpath);
  53.345 +  s->ctlpath = NULL;
  53.346 +
  53.347 +  return -1;
  53.348 +}
  53.349 +
  53.350 +static int ctl_close(struct tdlog_state* s)
  53.351 +{
  53.352 +  while (s->connected) {
  53.353 +    tapdisk_server_unregister_event(s->connections[s->connected].id);
  53.354 +    close(s->connections[s->connected].fd);
  53.355 +    s->connections[s->connected].fd = -1;
  53.356 +    s->connections[s->connected].id = 0;
  53.357 +    s->connected--;
  53.358 +  }
  53.359 +
  53.360 +  if (s->ctl.fd >= 0) {
  53.361 +    tapdisk_server_unregister_event(s->ctl.id);
  53.362 +    close(s->ctl.fd);
  53.363 +    s->ctl.fd = -1;
  53.364 +    s->ctl.id = 0;
  53.365 +  }
  53.366 +
  53.367 +  if (s->ctlpath) {
  53.368 +    unlink(s->ctlpath);
  53.369 +    free(s->ctlpath);
  53.370 +    s->ctlpath = NULL;
  53.371 +  }
  53.372 +
  53.373 +  /* XXX this must be fixed once requests are actually in flight */
  53.374 +  /* could just drain the existing ring here first */
  53.375 +  if (s->sring) {
  53.376 +    SHARED_RING_INIT(s->sring);
  53.377 +    BACK_RING_INIT(&s->bring, s->sring, SRINGSIZE);
  53.378 +  }
  53.379 +
  53.380 +  return 0;
  53.381 +}
  53.382 +
  53.383 +/* walk list of open sockets, close matching fd */
  53.384 +static int ctl_close_sock(struct tdlog_state* s, int fd)
  53.385 +{
  53.386 +  int i;
  53.387 +
  53.388 +  for (i = 0; i <= s->connected; i++) {
  53.389 +    if (s->connections[i].fd == fd) {
  53.390 +      tapdisk_server_unregister_event(s->connections[i].id);
  53.391 +      close(s->connections[i].fd);
  53.392 +      s->connections[i].fd = -1;
  53.393 +      s->connections[i].id = 0;
  53.394 +      s->connected--;
  53.395 +      return 0;
  53.396 +    }
  53.397 +  }
  53.398 +
  53.399 +  BWPRINTF("requested to close unknown socket %d", fd);
  53.400 +  return -1;
  53.401 +}
  53.402 +
  53.403 +static void ctl_accept(event_id_t id, char mode, void *private)
  53.404 +{
  53.405 +  struct tdlog_state* s = (struct tdlog_state *)private;
  53.406 +  int fd;
  53.407 +  event_id_t cid;
  53.408 +
  53.409 +  if ((fd = accept(s->ctl.fd, NULL, NULL)) < 0) {
  53.410 +    BWPRINTF("error accepting control connection: %s", strerror(errno));
  53.411 +    return;
  53.412 +  }
  53.413 +
  53.414 +  if (s->connected) {
  53.415 +    BWPRINTF("control session in progress, closing new connection");
  53.416 +    close(fd);
  53.417 +    return;
  53.418 +  }
  53.419 +
  53.420 +  cid = tapdisk_server_register_event(SCHEDULER_POLL_READ_FD,
  53.421 +				      fd, 0, ctl_request, s);
  53.422 +  if (cid < 0) {
  53.423 +    BWPRINTF("error registering connection event handler: %s", strerror(cid));
  53.424 +    close(fd);
  53.425 +    return;
  53.426 +  }
  53.427 +
  53.428 +  s->connections[s->connected].fd = fd;
  53.429 +  s->connections[s->connected].id = cid;
  53.430 +  s->connected++;
  53.431 +}
  53.432 +
  53.433 +/* response format: 4 bytes shmsize, 0-terminated path */
  53.434 +static int ctl_get_shmpath(struct tdlog_state* s, int fd)
  53.435 +{
  53.436 +  char msg[CTLRSPLEN_SHMP + 1];
  53.437 +  uint32_t sz;
  53.438 +  int rc;
  53.439 +
  53.440 +  BDPRINTF("ctl: sending shared memory parameters (size: %u, path: %s)",
  53.441 +	   SHMSIZE, s->shmpath);
  53.442 +
  53.443 +  /* TMP: sanity-check shm */
  53.444 +  sz = 0xdeadbeef;
  53.445 +  memcpy(s->shm, &sz, sizeof(sz));
  53.446 +
  53.447 +  sz = SHMSIZE;
  53.448 +  memcpy(msg, &sz, sizeof(sz));
  53.449 +  snprintf(msg + sizeof(sz), sizeof(msg) - sizeof(sz), "%s", s->shmpath);
  53.450 +  if ((rc = write(fd, msg, CTLRSPLEN_SHMP)) < 0) {
  53.451 +    BWPRINTF("error writing shmpath: %s", strerror(errno));
  53.452 +    return -1;
  53.453 +  }
  53.454 +
  53.455 +  return 0;
  53.456 +}
  53.457 +
  53.458 +static int ctl_peek_writes(struct tdlog_state* s, int fd)
  53.459 +{
  53.460 +  int rc;
  53.461 +
  53.462 +  BDPRINTF("ctl: peeking bitmap");
  53.463 +
  53.464 +  writelog_export(s);
  53.465 +
  53.466 +  if ((rc = write(fd, "done", CTLRSPLEN_PEEK)) < 0) {
  53.467 +    BWPRINTF("error writing peek ack: %s", strerror(errno));
  53.468 +    return -1;
  53.469 +  }
  53.470 +
  53.471 +  return 0;
  53.472 +}
  53.473 +
  53.474 +static int ctl_clear_writes(struct tdlog_state* s, int fd)
  53.475 +{
  53.476 +  int rc;
  53.477 +
  53.478 +  BDPRINTF("ctl: clearing bitmap");
  53.479 +
  53.480 +  writelog_clear(s, 0, 0);
  53.481 +
  53.482 +  if ((rc = write(fd, "done", CTLRSPLEN_CLEAR)) < 0) {
  53.483 +    BWPRINTF("error writing clear ack: %s", strerror(errno));
  53.484 +    return -1;
  53.485 +  }
  53.486 +
  53.487 +  return 0;
  53.488 +}
  53.489 +
  53.490 +/* get dirty bitmap and clear it atomically */
  53.491 +static int ctl_get_writes(struct tdlog_state* s, int fd)
  53.492 +{
  53.493 +  int rc;
  53.494 +
  53.495 +  BDPRINTF("ctl: getting bitmap");
  53.496 +
  53.497 +  writelog_export(s);
  53.498 +  writelog_clear(s, 0, 0);
  53.499 +
  53.500 +  if ((rc = write(fd, "done", CTLRSPLEN_GET)) < 0) {
  53.501 +    BWPRINTF("error writing get ack: %s", strerror(errno));
  53.502 +    return -1;
  53.503 +  }
  53.504 +
  53.505 +  return 0;
  53.506 +}
  53.507 +
  53.508 +/* get requests from ring */
  53.509 +static int ctl_kick(struct tdlog_state* s, int fd)
  53.510 +{
  53.511 +  RING_IDX reqstart, reqend;
  53.512 +  log_request_t req;
  53.513 +
  53.514 +  /* XXX testing */
  53.515 +  RING_IDX rspstart, rspend;
  53.516 +  log_response_t rsp;
  53.517 +  struct log_ctlmsg msg;
  53.518 +  int rc;
  53.519 +
  53.520 +  reqstart = s->bring.req_cons;
  53.521 +  reqend = s->sring->req_prod;
  53.522 +
  53.523 +  BDPRINTF("ctl: ring kicked (start = %u, end = %u)", reqstart, reqend);
  53.524 +
  53.525 +  while (reqstart != reqend) {
  53.526 +    /* XXX actually submit these! */
  53.527 +    memcpy(&req, RING_GET_REQUEST(&s->bring, reqstart), sizeof(req));
  53.528 +    BDPRINTF("ctl: read request %"PRIu64":%u", req.sector, req.count);
  53.529 +    s->bring.req_cons = ++reqstart;
  53.530 +
  53.531 +    rsp.sector = req.sector;
  53.532 +    rsp.count = req.count;
  53.533 +    memcpy(RING_GET_RESPONSE(&s->bring, s->bring.rsp_prod_pvt), &rsp,
  53.534 +	   sizeof(rsp));
  53.535 +    s->bring.rsp_prod_pvt++;
  53.536 +  }
  53.537 +
  53.538 +  RING_PUSH_RESPONSES(&s->bring);
  53.539 +  memset(&msg, 0, sizeof(msg));
  53.540 +  memcpy(msg.msg, LOGCMD_KICK, 4);
  53.541 +  if ((rc = write(fd, &msg, sizeof(msg))) < 0) {
  53.542 +    BWPRINTF("error sending notify: %s", strerror(errno));
  53.543 +    return -1;
  53.544 +  } else if (rc < sizeof(msg)) {
  53.545 +    BWPRINTF("short notify write (%d/%zd)", rc, sizeof(msg));
  53.546 +    return -1;
  53.547 +  }
  53.548 +
  53.549 +  return 0;
  53.550 +}
  53.551 +
  53.552 +static int ctl_do_request(struct tdlog_state* s, int fd, struct log_ctlmsg* msg)
  53.553 +{
  53.554 +  if (!strncmp(msg->msg, LOGCMD_SHMP, 4)) {
  53.555 +    return ctl_get_shmpath(s, fd);
  53.556 +  } else if (!strncmp(msg->msg, LOGCMD_PEEK, 4)) {
  53.557 +    return ctl_peek_writes(s, fd);
  53.558 +  } else if (!strncmp(msg->msg, LOGCMD_CLEAR, 4)) {
  53.559 +    return ctl_clear_writes(s, fd);
  53.560 +  } else if (!strncmp(msg->msg, LOGCMD_GET, 4)) {
  53.561 +    return ctl_get_writes(s, fd);
  53.562 +  } else if (!strncmp(msg->msg, LOGCMD_KICK, 4)) {
  53.563 +    return ctl_kick(s, fd);
  53.564 +  }
  53.565 +
  53.566 +  BWPRINTF("unknown control request %.4s", msg->msg);
  53.567 +  return -1;
  53.568 +}
  53.569 +
  53.570 +static inline int ctl_find_connection(struct tdlog_state *s, event_id_t id)
  53.571 +{
  53.572 +  int i;
  53.573 +
  53.574 +  for (i = 0; i < s->connected; i++)
  53.575 +    if (s->connections[i].id == id)
  53.576 +      return s->connections[i].fd;
  53.577 +
  53.578 +  BWPRINTF("unrecognized event callback id %d", id);
  53.579 +  return -1;
  53.580 +}
  53.581 +
  53.582 +static void ctl_request(event_id_t id, char mode, void *private)
  53.583 +{
  53.584 +  struct tdlog_state* s = (struct tdlog_state*)private;
  53.585 +  struct log_ctlmsg msg;
  53.586 +  int rc, i, fd = -1;
  53.587 +
  53.588 +  fd = ctl_find_connection(s, id);
  53.589 +  if (fd == -1)
  53.590 +    return;
  53.591 +
  53.592 +  if ((rc = read(fd, &msg, sizeof(msg))) < 0) {
  53.593 +    BWPRINTF("error reading from ctl socket %d, closing: %s", fd,
  53.594 +	     strerror(errno));
  53.595 +    ctl_close_sock(s, fd);
  53.596 +    return;
  53.597 +  } else if (rc == 0) {
  53.598 +    BDPRINTF("ctl_request: EOF, closing socket");
  53.599 +    ctl_close_sock(s, fd);
  53.600 +    return;
  53.601 +  } else if (rc < sizeof(msg)) {
  53.602 +    BWPRINTF("short request received (%d/%zd bytes), ignoring", rc,
  53.603 +	     sizeof(msg));
  53.604 +    return;
  53.605 +  }
  53.606 +
  53.607 +  ctl_do_request(s, fd, &msg);
  53.608 +}
  53.609 +
  53.610 +/* -- interface -- */
  53.611 +
  53.612 +static int tdlog_close(td_driver_t*);
  53.613 +
  53.614 +static int tdlog_open(td_driver_t* driver, const char* name, td_flag_t flags)
  53.615 +{
  53.616 +  struct tdlog_state* s = (struct tdlog_state*)driver->data;
  53.617 +  int rc;
  53.618 +
  53.619 +  memset(s, 0, sizeof(*s));
  53.620 +
  53.621 +  s->size = driver->info.size;
  53.622 +
  53.623 +  if ((rc = writelog_create(s))) {
  53.624 +    tdlog_close(driver);
  53.625 +    return rc;
  53.626 +  }
  53.627 +  if ((rc = shmem_open(s, name))) {
  53.628 +    tdlog_close(driver);
  53.629 +    return rc;
  53.630 +  }
  53.631 +  if ((rc = ctl_open(s, name))) {
  53.632 +    tdlog_close(driver);
  53.633 +    return rc;
  53.634 +  }
  53.635 +
  53.636 +  s->sring = (log_sring_t*)sringstart(s->shm);
  53.637 +  SHARED_RING_INIT(s->sring);
  53.638 +  BACK_RING_INIT(&s->bring, s->sring, SRINGSIZE);
  53.639 +
  53.640 +  BDPRINTF("opened ctl socket");
  53.641 +
  53.642 +  return 0;
  53.643 +}
  53.644 +
  53.645 +static int tdlog_close(td_driver_t* driver)
  53.646 +{
  53.647 +  struct tdlog_state* s = (struct tdlog_state*)driver->data;
  53.648 +
  53.649 +  ctl_close(s);
  53.650 +  shmem_close(s);
  53.651 +  writelog_free(s);
  53.652 +
  53.653 +  return 0;
  53.654 +}
  53.655 +
  53.656 +static void tdlog_queue_read(td_driver_t* driver, td_request_t treq)
  53.657 +{
  53.658 +  td_forward_request(treq);
  53.659 +}
  53.660 +
  53.661 +static void tdlog_queue_write(td_driver_t* driver, td_request_t treq)
  53.662 +{
  53.663 +  struct tdlog_state* s = (struct tdlog_state*)driver->data;
  53.664 +  int rc;
  53.665 +
  53.666 +  writelog_set(s, treq.sec, treq.secs);
  53.667 +  td_forward_request(treq);
  53.668 +}
  53.669 +
  53.670 +static int tdlog_get_parent_id(td_driver_t* driver, td_disk_id_t* id)
  53.671 +{
  53.672 +  return -EINVAL;
  53.673 +}
  53.674 +
  53.675 +static int tdlog_validate_parent(td_driver_t *driver,
  53.676 +				 td_driver_t *parent, td_flag_t flags)
  53.677 +{
  53.678 +  return 0;
  53.679 +}
  53.680 +
  53.681 +struct tap_disk tapdisk_log = {
  53.682 +  .disk_type          = "tapdisk_log",
  53.683 +  .private_data_size  = sizeof(struct tdlog_state),
  53.684 +  .flags              = 0,
  53.685 +  .td_open            = tdlog_open,
  53.686 +  .td_close           = tdlog_close,
  53.687 +  .td_queue_read      = tdlog_queue_read,
  53.688 +  .td_queue_write     = tdlog_queue_write,
  53.689 +  .td_get_parent_id   = tdlog_get_parent_id,
  53.690 +  .td_validate_parent = tdlog_validate_parent,
  53.691 +};
    54.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    54.2 +++ b/tools/blktap2/drivers/block-qcow.c	Wed Jun 17 17:24:56 2009 -0700
    54.3 @@ -0,0 +1,1518 @@
    54.4 +/* block-qcow.c
    54.5 + *
    54.6 + * Asynchronous Qemu copy-on-write disk implementation.
    54.7 + * Code based on the Qemu implementation
    54.8 + * (see copyright notice below)
    54.9 + *
   54.10 + * (c) 2006 Andrew Warfield and Julian Chesterfield
   54.11 + *
   54.12 + */
   54.13 +
   54.14 +/*
   54.15 + * Block driver for the QCOW format
   54.16 + * 
   54.17 + * Copyright (c) 2004 Fabrice Bellard
   54.18 + * 
   54.19 + * Permission is hereby granted, free of charge, to any person obtaining a copy
   54.20 + * of this software and associated documentation files(the "Software"), to deal
   54.21 + * in the Software without restriction, including without limitation the rights
   54.22 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   54.23 + * copies of the Software, and to permit persons to whom the Software is
   54.24 + * furnished to do so, subject to the following conditions:
   54.25 + */
   54.26 +
   54.27 +#include <errno.h>
   54.28 +#include <fcntl.h>
   54.29 +#include <stdio.h>
   54.30 +#include <stdlib.h>
   54.31 +#include <unistd.h>
   54.32 +#include <sys/statvfs.h>
   54.33 +#include <sys/stat.h>
   54.34 +#include <sys/ioctl.h>
   54.35 +#include <linux/fs.h>
   54.36 +#include <string.h>
   54.37 +#include <zlib.h>
   54.38 +#include <inttypes.h>
   54.39 +#include <libaio.h>
   54.40 +#include <openssl/md5.h>
   54.41 +#include <limits.h>
   54.42 +#include "bswap.h"
   54.43 +#include "aes.h"
   54.44 +
   54.45 +#include "tapdisk.h"
   54.46 +#include "tapdisk-driver.h"
   54.47 +#include "tapdisk-interface.h"
   54.48 +#include "qcow.h"
   54.49 +#include "blk.h"
   54.50 +#include "atomicio.h"
   54.51 +
   54.52 +/* *BSD has no O_LARGEFILE */
   54.53 +#ifndef O_LARGEFILE
   54.54 +#define O_LARGEFILE     0
   54.55 +#endif
   54.56 +
   54.57 +#if 1
   54.58 +#define ASSERT(_p) \
   54.59 +    if ( !(_p) ) { DPRINTF("Assertion '%s' failed, line %d, file %s", #_p , \
   54.60 +    __LINE__, __FILE__); *(int*)0=0; }
   54.61 +#else
   54.62 +#define ASSERT(_p) ((void)0)
   54.63 +#endif
   54.64 +
   54.65 +struct pending_aio {
   54.66 +        td_callback_t cb;
   54.67 +        int id;
   54.68 +        void *private;
   54.69 +	int nb_sectors;
   54.70 +	char *buf;
   54.71 +	uint64_t sector;
   54.72 +};
   54.73 +
   54.74 +#undef IOCB_IDX
   54.75 +#define IOCB_IDX(_s, _io) ((_io) - (_s)->iocb_list)
   54.76 +
   54.77 +#define ZERO_TEST(_b) (_b | 0x00)
   54.78 +
   54.79 +struct qcow_request {
   54.80 +	td_request_t         treq;
   54.81 +	struct tiocb         tiocb;
   54.82 +	struct tdqcow_state  *state;
   54.83 +};
   54.84 +
   54.85 +static int decompress_cluster(struct tdqcow_state *s, uint64_t cluster_offset);
   54.86 +
   54.87 +#ifdef USE_GCRYPT
   54.88 +
   54.89 +#include <gcrypt.h>
   54.90 +
   54.91 +uint32_t gen_cksum(char *ptr, int len)
   54.92 +{
   54.93 +  int i;
   54.94 +  uint32_t md[4];
   54.95 +
   54.96 +  /* Generate checksum */
   54.97 +  gcry_md_hash_buffer(GCRY_MD_MD5, md, ptr, len);
   54.98 +
   54.99 +  return md[0];
  54.100 +}
  54.101 +
  54.102 +#else /* use libcrypto */
  54.103 +
  54.104 +#include <openssl/md5.h>
  54.105 +
  54.106 +uint32_t gen_cksum(char *ptr, int len)
  54.107 +{
  54.108 +  int i;
  54.109 +  unsigned char *md;
  54.110 +  uint32_t ret;
  54.111 +
  54.112 +  md = malloc(MD5_DIGEST_LENGTH);
  54.113 +  if(!md) return 0;
  54.114 +
  54.115 +  /* Generate checksum */
  54.116 +  if (MD5((unsigned char *)ptr, len, md) != md)
  54.117 +    ret = 0;
  54.118 +  else
  54.119 +    memcpy(&ret, md, sizeof(uint32_t));
  54.120 +
  54.121 +  free(md);
  54.122 +  return ret;
  54.123 +}
  54.124 +
  54.125 +#endif
  54.126 +
  54.127 +
  54.128 +static void free_aio_state(struct tdqcow_state* s)
  54.129 +{
  54.130 +	free(s->aio_requests);
  54.131 +	free(s->aio_free_list);
  54.132 +}
  54.133 +
  54.134 +static int init_aio_state(td_driver_t *driver)
  54.135 +{
  54.136 +	int i, ret;
  54.137 +	td_disk_info_t *bs = &(driver->info);
  54.138 +	struct tdqcow_state   *s  = (struct tdqcow_state *)driver->data;
  54.139 +	
  54.140 +        // A segment (i.e. a page) can span multiple clusters
  54.141 +        s->max_aio_reqs = ((getpagesize() / s->cluster_size) + 1) *
  54.142 +	  MAX_SEGMENTS_PER_REQ * MAX_REQUESTS;
  54.143 +
  54.144 +	s->aio_free_count = s->max_aio_reqs;
  54.145 +
  54.146 +	if (!(s->aio_requests  = calloc(s->max_aio_reqs, sizeof(struct qcow_request))) || 
  54.147 +	    !(s->aio_free_list = calloc(s->max_aio_reqs, sizeof(struct qcow_request)))) {
  54.148 +	    DPRINTF("Failed to allocate AIO structs (max_aio_reqs = %d)\n",
  54.149 +		    s->max_aio_reqs);
  54.150 +	    goto fail;
  54.151 +	}
  54.152 +
  54.153 +	for (i = 0; i < s->max_aio_reqs; i++)
  54.154 +		s->aio_free_list[i] = &s->aio_requests[i];
  54.155 +
  54.156 +        DPRINTF("AIO state initialised\n");
  54.157 +
  54.158 +        return 0;
  54.159 + fail:
  54.160 +	return -1;
  54.161 +}
  54.162 +
  54.163 +int get_filesize(char *filename, uint64_t *size, struct stat *st)
  54.164 +{
  54.165 +	int fd;
  54.166 +	QCowHeader header;
  54.167 +
  54.168 +	/*Set to the backing file size*/
  54.169 +	fd = open(filename, O_RDONLY);
  54.170 +	if (fd < 0)
  54.171 +		return -1;
  54.172 +	if (read(fd, &header, sizeof(header)) < sizeof(header)) {
  54.173 +		close(fd);
  54.174 +		return -1;
  54.175 +	}
  54.176 +	close(fd);
  54.177 +	
  54.178 +	be32_to_cpus(&header.magic);
  54.179 +	be64_to_cpus(&header.size);
  54.180 +	if (header.magic == QCOW_MAGIC) {
  54.181 +		*size = header.size >> SECTOR_SHIFT;
  54.182 +		return 0;
  54.183 +	}
  54.184 +
  54.185 +	if(S_ISBLK(st->st_mode)) {
  54.186 +		fd = open(filename, O_RDONLY);
  54.187 +		if (fd < 0)
  54.188 +			return -1;
  54.189 +		if (blk_getimagesize(fd, size) != 0) {
  54.190 +			printf("Unable to get Block device size\n");
  54.191 +			close(fd);
  54.192 +			return -1;
  54.193 +		}
  54.194 +		close(fd);
  54.195 +	} else *size = (st->st_size >> SECTOR_SHIFT);	
  54.196 +	return 0;
  54.197 +}
  54.198 +
  54.199 +static int qcow_set_key(struct tdqcow_state *s, const char *key)
  54.200 +{
  54.201 +	uint8_t keybuf[16];
  54.202 +	int len, i;
  54.203 +	
  54.204 +	memset(keybuf, 0, 16);
  54.205 +	len = strlen(key);
  54.206 +	if (len > 16)
  54.207 +		len = 16;
  54.208 +	/* XXX: we could compress the chars to 7 bits to increase
  54.209 +	   entropy */
  54.210 +	for (i = 0; i < len; i++) {
  54.211 +		keybuf[i] = key[i];
  54.212 +	}
  54.213 +	s->crypt_method = s->crypt_method_header;
  54.214 +	
  54.215 +	if (AES_set_encrypt_key(keybuf, 128, &s->aes_encrypt_key) != 0)
  54.216 +		return -1;
  54.217 +	if (AES_set_decrypt_key(keybuf, 128, &s->aes_decrypt_key) != 0)
  54.218 +		return -1;
  54.219 +#if 0
  54.220 +	/* test */
  54.221 +	{
  54.222 +		uint8_t in[16];
  54.223 +		uint8_t out[16];
  54.224 +		uint8_t tmp[16];
  54.225 +		for (i=0; i<16; i++)
  54.226 +			in[i] = i;
  54.227 +		AES_encrypt(in, tmp, &s->aes_encrypt_key);
  54.228 +		AES_decrypt(tmp, out, &s->aes_decrypt_key);
  54.229 +		for (i = 0; i < 16; i++)
  54.230 +			DPRINTF(" %02x", tmp[i]);
  54.231 +		DPRINTF("\n");
  54.232 +		for (i = 0; i < 16; i++)
  54.233 +			DPRINTF(" %02x", out[i]);
  54.234 +		DPRINTF("\n");
  54.235 +	}
  54.236 +#endif
  54.237 +	return 0;
  54.238 +}
  54.239 +
  54.240 +void tdqcow_complete(void *arg, struct tiocb *tiocb, int err)
  54.241 +{
  54.242 +	struct qcow_request *aio = (struct qcow_request *)arg;
  54.243 +	struct tdqcow_state *s = aio->state;
  54.244 +
  54.245 +	td_complete_request(aio->treq, err);
  54.246 +
  54.247 +	s->aio_free_list[s->aio_free_count++] = aio;
  54.248 +}
  54.249 +
  54.250 +static void async_read(td_driver_t *driver, td_request_t treq)
  54.251 +{
  54.252 +	int size;
  54.253 +	uint64_t offset;
  54.254 +	struct qcow_request *aio;
  54.255 +	struct tdqcow_state *prv;
  54.256 +
  54.257 +	prv    = (struct tdqcow_state *)driver->data;
  54.258 +	size   = treq.secs * driver->info.sector_size;
  54.259 +	offset = treq.sec  * (uint64_t)driver->info.sector_size;
  54.260 +
  54.261 +	if (prv->aio_free_count == 0)
  54.262 +		goto fail;
  54.263 +
  54.264 +	aio        = prv->aio_free_list[--prv->aio_free_count];
  54.265 +	aio->treq  = treq;
  54.266 +	aio->state = prv;
  54.267 +
  54.268 +	td_prep_read(&aio->tiocb, prv->fd, treq.buf,
  54.269 +		     size, offset, tdqcow_complete, aio);
  54.270 +	td_queue_tiocb(driver, &aio->tiocb);
  54.271 +
  54.272 +	return;
  54.273 +
  54.274 +fail:
  54.275 +	td_complete_request(treq, -EBUSY);
  54.276 +}
  54.277 +
  54.278 +static void async_write(td_driver_t *driver, td_request_t treq)
  54.279 +{
  54.280 +	int size;
  54.281 +	uint64_t offset;
  54.282 +	struct qcow_request *aio;
  54.283 +	struct tdqcow_state *prv;
  54.284 +
  54.285 +	prv     = (struct tdqcow_state *)driver->data;
  54.286 +	size    = treq.secs * driver->info.sector_size;
  54.287 +	offset  = treq.sec  * (uint64_t)driver->info.sector_size;
  54.288 +
  54.289 +	if (prv->aio_free_count == 0)
  54.290 +		goto fail;
  54.291 +
  54.292 +	aio        = prv->aio_free_list[--prv->aio_free_count];
  54.293 +	aio->treq  = treq;
  54.294 +	aio->state = prv;
  54.295 +
  54.296 +	td_prep_write(&aio->tiocb, prv->fd, treq.buf,
  54.297 +		      size, offset, tdqcow_complete, aio);
  54.298 +	td_queue_tiocb(driver, &aio->tiocb);
  54.299 +
  54.300 +	return;
  54.301 +
  54.302 +fail:
  54.303 +	td_complete_request(treq, -EBUSY);
  54.304 +}
  54.305 +
  54.306 +/* 
  54.307 + * The crypt function is compatible with the linux cryptoloop
  54.308 + * algorithm for < 4 GB images. NOTE: out_buf == in_buf is
  54.309 + * supported .
  54.310 + */
  54.311 +static void encrypt_sectors(struct tdqcow_state *s, int64_t sector_num,
  54.312 +                            uint8_t *out_buf, const uint8_t *in_buf,
  54.313 +                            int nb_sectors, int enc,
  54.314 +                            const AES_KEY *key)
  54.315 +{
  54.316 +	union {
  54.317 +		uint64_t ll[2];
  54.318 +		uint8_t b[16];
  54.319 +	} ivec;
  54.320 +	int i;
  54.321 +	
  54.322 +	for (i = 0; i < nb_sectors; i++) {
  54.323 +		ivec.ll[0] = cpu_to_le64(sector_num);
  54.324 +		ivec.ll[1] = 0;
  54.325 +		AES_cbc_encrypt(in_buf, out_buf, 512, key, 
  54.326 +				ivec.b, enc);
  54.327 +		sector_num++;
  54.328 +		in_buf += 512;
  54.329 +		out_buf += 512;
  54.330 +	}
  54.331 +}
  54.332 +
  54.333 +int qtruncate(int fd, off_t length, int sparse)
  54.334 +{
  54.335 +	int ret, i; 
  54.336 +	int current = 0, rem = 0;
  54.337 +	uint64_t sectors;
  54.338 +	struct stat st;
  54.339 +	char *buf;
  54.340 +
  54.341 +	/* If length is greater than the current file len
  54.342 +	 * we synchronously write zeroes to the end of the 
  54.343 +	 * file, otherwise we truncate the length down
  54.344 +	 */
  54.345 +	ret = fstat(fd, &st);
  54.346 +	if (ret == -1) 
  54.347 +		return -1;
  54.348 +	if (S_ISBLK(st.st_mode))
  54.349 +		return 0;
  54.350 +
  54.351 +	sectors = (length + DEFAULT_SECTOR_SIZE - 1)/DEFAULT_SECTOR_SIZE;
  54.352 +	current = (st.st_size + DEFAULT_SECTOR_SIZE - 1)/DEFAULT_SECTOR_SIZE;
  54.353 +	rem     = st.st_size % DEFAULT_SECTOR_SIZE;
  54.354 +
  54.355 +	/* If we are extending this file, we write zeros to the end --
  54.356 +	 * this tries to ensure that the extents allocated wind up being
  54.357 +	 * contiguous on disk.
  54.358 +	 */
  54.359 +	if(st.st_size < sectors * DEFAULT_SECTOR_SIZE) {
  54.360 +		/*We are extending the file*/
  54.361 +		if ((ret = posix_memalign((void **)&buf, 
  54.362 +					  512, DEFAULT_SECTOR_SIZE))) {
  54.363 +			DPRINTF("posix_memalign failed: %d\n", ret);
  54.364 +			return -1;
  54.365 +		}
  54.366 +		memset(buf, 0x00, DEFAULT_SECTOR_SIZE);
  54.367 +		if (lseek(fd, 0, SEEK_END)==-1) {
  54.368 +			DPRINTF("Lseek EOF failed (%d), internal error\n",
  54.369 +				errno);
  54.370 +			free(buf);
  54.371 +			return -1;
  54.372 +		}
  54.373 +		if (rem) {
  54.374 +			ret = write(fd, buf, rem);
  54.375 +			if (ret != rem) {
  54.376 +				DPRINTF("write failed: ret = %d, err = %s\n",
  54.377 +					ret, strerror(errno));
  54.378 +				free(buf);
  54.379 +				return -1;
  54.380 +			}
  54.381 +		}
  54.382 +		for (i = current; i < sectors; i++ ) {
  54.383 +			ret = write(fd, buf, DEFAULT_SECTOR_SIZE);
  54.384 +			if (ret != DEFAULT_SECTOR_SIZE) {
  54.385 +				DPRINTF("write failed: ret = %d, err = %s\n",
  54.386 +					ret, strerror(errno));
  54.387 +				free(buf);
  54.388 +				return -1;
  54.389 +			}
  54.390 +		}
  54.391 +		free(buf);
  54.392 +	} else if(sparse && (st.st_size > sectors * DEFAULT_SECTOR_SIZE))
  54.393 +		if (ftruncate(fd, (off_t)sectors * DEFAULT_SECTOR_SIZE)==-1) {
  54.394 +			DPRINTF("Ftruncate failed (%s)\n", strerror(errno));
  54.395 +			return -1;
  54.396 +		}
  54.397 +	return 0;
  54.398 +}
  54.399 +
  54.400 +/* 'allocate' is:
  54.401 + *
  54.402 + * 0 to not allocate.
  54.403 + *
  54.404 + * 1 to allocate a normal cluster (for sector indexes 'n_start' to
  54.405 + * 'n_end')
  54.406 + *
  54.407 + * 2 to allocate a compressed cluster of size
  54.408 + * 'compressed_size'. 'compressed_size' must be > 0 and <
  54.409 + * cluster_size 
  54.410 + *
  54.411 + * return 0 if not allocated.
  54.412 + */
  54.413 +static uint64_t get_cluster_offset(struct tdqcow_state *s,
  54.414 +                                   uint64_t offset, int allocate,
  54.415 +                                   int compressed_size,
  54.416 +                                   int n_start, int n_end)
  54.417 +{
  54.418 +	int min_index, i, j, l1_index, l2_index, l2_sector, l1_sector;
  54.419 +	char *tmp_ptr2, *l2_ptr, *l1_ptr;
  54.420 +	uint64_t *tmp_ptr;
  54.421 +	uint64_t l2_offset, *l2_table, cluster_offset, tmp;
  54.422 +	uint32_t min_count;
  54.423 +	int new_l2_table;
  54.424 +
  54.425 +	/*Check L1 table for the extent offset*/
  54.426 +	l1_index = offset >> (s->l2_bits + s->cluster_bits);
  54.427 +	l2_offset = s->l1_table[l1_index];
  54.428 +	new_l2_table = 0;
  54.429 +	if (!l2_offset) {
  54.430 +		if (!allocate)
  54.431 +			return 0;
  54.432 +		/* 
  54.433 +		 * allocating a new l2 entry + extent 
  54.434 +		 * at the end of the file, we must also
  54.435 +		 * update the L1 entry safely.
  54.436 +		 */
  54.437 +		l2_offset = s->fd_end;
  54.438 +
  54.439 +		/* round to cluster size */
  54.440 +		l2_offset = (l2_offset + s->cluster_size - 1) 
  54.441 +			& ~(s->cluster_size - 1);
  54.442 +
  54.443 +		/* update the L1 entry */
  54.444 +		s->l1_table[l1_index] = l2_offset;
  54.445 +		
  54.446 +		/*Truncate file for L2 table 
  54.447 +		 *(initialised to zero in case we crash)*/
  54.448 +		if (qtruncate(s->fd, 
  54.449 +			      l2_offset + (s->l2_size * sizeof(uint64_t)),
  54.450 +			      s->sparse) != 0) {
  54.451 +			DPRINTF("ERROR truncating file\n");
  54.452 +			return 0;
  54.453 +		}
  54.454 +		s->fd_end = l2_offset + (s->l2_size * sizeof(uint64_t));
  54.455 +
  54.456 +		/*Update the L1 table entry on disk
  54.457 +                 * (for O_DIRECT we write 4KByte blocks)*/
  54.458 +		l1_sector = (l1_index * sizeof(uint64_t)) >> 12;
  54.459 +		l1_ptr = (char *)s->l1_table + (l1_sector << 12);
  54.460 +
  54.461 +		if (posix_memalign((void **)&tmp_ptr, 4096, 4096) != 0) {
  54.462 +			DPRINTF("ERROR allocating memory for L1 table\n");
  54.463 +		}
  54.464 +		memcpy(tmp_ptr, l1_ptr, 4096);
  54.465 +
  54.466 +		/* Convert block to write to big endian */
  54.467 +		for(i = 0; i < 4096 / sizeof(uint64_t); i++) {
  54.468 +			cpu_to_be64s(&tmp_ptr[i]);
  54.469 +		}
  54.470 +
  54.471 +		/*
  54.472 +		 * Issue non-asynchronous L1 write.
  54.473 +		 * For safety, we must ensure that
  54.474 +		 * entry is written before blocks.
  54.475 +		 */
  54.476 +		lseek(s->fd, s->l1_table_offset + (l1_sector << 12), SEEK_SET);
  54.477 +		if (write(s->fd, tmp_ptr, 4096) != 4096) {
  54.478 +			free(tmp_ptr);
  54.479 +		 	return 0;
  54.480 +		}
  54.481 +		free(tmp_ptr);
  54.482 +
  54.483 +		new_l2_table = 1;
  54.484 +		goto cache_miss;
  54.485 +	} else if (s->min_cluster_alloc == s->l2_size) {
  54.486 +		/*Fast-track the request*/
  54.487 +		cluster_offset = l2_offset + (s->l2_size * sizeof(uint64_t));
  54.488 +		l2_index = (offset >> s->cluster_bits) & (s->l2_size - 1);
  54.489 +		return cluster_offset + (l2_index * s->cluster_size);
  54.490 +	}
  54.491 +
  54.492 +	/*Check to see if L2 entry is already cached*/
  54.493 +	for (i = 0; i < L2_CACHE_SIZE; i++) {
  54.494 +		if (l2_offset == s->l2_cache_offsets[i]) {
  54.495 +			/* increment the hit count */
  54.496 +			if (++s->l2_cache_counts[i] == 0xffffffff) {
  54.497 +				for (j = 0; j < L2_CACHE_SIZE; j++) {
  54.498 +					s->l2_cache_counts[j] >>= 1;
  54.499 +				}
  54.500 +			}
  54.501 +			l2_table = s->l2_cache + (i << s->l2_bits);
  54.502 +			goto found;
  54.503 +		}
  54.504 +	}
  54.505 +
  54.506 +cache_miss:
  54.507 +	/* not found: load a new entry in the least used one */
  54.508 +	min_index = 0;
  54.509 +	min_count = 0xffffffff;
  54.510 +	for (i = 0; i < L2_CACHE_SIZE; i++) {
  54.511 +		if (s->l2_cache_counts[i] < min_count) {
  54.512 +			min_count = s->l2_cache_counts[i];
  54.513 +			min_index = i;
  54.514 +		}
  54.515 +	}
  54.516 +	l2_table = s->l2_cache + (min_index << s->l2_bits);
  54.517 +
  54.518 +	/*If extent pre-allocated, read table from disk, 
  54.519 +	 *otherwise write new table to disk*/
  54.520 +	if (new_l2_table) {
  54.521 +		/*Should we allocate the whole extent? Adjustable parameter.*/
  54.522 +		if (s->cluster_alloc == s->l2_size) {
  54.523 +			cluster_offset = l2_offset + 
  54.524 +				(s->l2_size * sizeof(uint64_t));
  54.525 +			cluster_offset = (cluster_offset + s->cluster_size - 1)
  54.526 +				& ~(s->cluster_size - 1);
  54.527 +			if (qtruncate(s->fd, cluster_offset + 
  54.528 +				  (s->cluster_size * s->l2_size), 
  54.529 +				      s->sparse) != 0) {
  54.530 +				DPRINTF("ERROR truncating file\n");
  54.531 +				return 0;
  54.532 +			}
  54.533 +			s->fd_end = cluster_offset + 
  54.534 +				(s->cluster_size * s->l2_size);
  54.535 +			for (i = 0; i < s->l2_size; i++) {
  54.536 +				l2_table[i] = cpu_to_be64(cluster_offset + 
  54.537 +							  (i*s->cluster_size));
  54.538 +			}  
  54.539 +		} else memset(l2_table, 0, s->l2_size * sizeof(uint64_t));
  54.540 +
  54.541 +		lseek(s->fd, l2_offset, SEEK_SET);
  54.542 +		if (write(s->fd, l2_table, s->l2_size * sizeof(uint64_t)) !=
  54.543 +		   s->l2_size * sizeof(uint64_t))
  54.544 +			return 0;
  54.545 +	} else {
  54.546 +		lseek(s->fd, l2_offset, SEEK_SET);
  54.547 +		if (read(s->fd, l2_table, s->l2_size * sizeof(uint64_t)) != 
  54.548 +		    s->l2_size * sizeof(uint64_t))
  54.549 +			return 0;
  54.550 +	}
  54.551 +	
  54.552 +	/*Update the cache entries*/ 
  54.553 +	s->l2_cache_offsets[min_index] = l2_offset;
  54.554 +	s->l2_cache_counts[min_index] = 1;
  54.555 +
  54.556 +found:
  54.557 +	/*The extent is split into 's->l2_size' blocks of 
  54.558 +	 *size 's->cluster_size'*/
  54.559 +	l2_index = (offset >> s->cluster_bits) & (s->l2_size - 1);
  54.560 +	cluster_offset = be64_to_cpu(l2_table[l2_index]);
  54.561 +
  54.562 +	if (!cluster_offset || 
  54.563 +	    ((cluster_offset & QCOW_OFLAG_COMPRESSED) && allocate == 1) ) {
  54.564 +		if (!allocate)
  54.565 +			return 0;
  54.566 +		
  54.567 +		if ((cluster_offset & QCOW_OFLAG_COMPRESSED) &&
  54.568 +		    (n_end - n_start) < s->cluster_sectors) {
  54.569 +			/* cluster is already allocated but compressed, we must
  54.570 +			   decompress it in the case it is not completely
  54.571 +			   overwritten */
  54.572 +			if (decompress_cluster(s, cluster_offset) < 0)
  54.573 +				return 0;
  54.574 +			cluster_offset = lseek(s->fd, s->fd_end, SEEK_SET);
  54.575 +			cluster_offset = (cluster_offset + s->cluster_size - 1)
  54.576 +				& ~(s->cluster_size - 1);
  54.577 +			/* write the cluster content - not asynchronous */
  54.578 +			lseek(s->fd, cluster_offset, SEEK_SET);
  54.579 +			if (write(s->fd, s->cluster_cache, s->cluster_size) != 
  54.580 +			    s->cluster_size)
  54.581 +			    return -1;
  54.582 +		} else {
  54.583 +			/* allocate a new cluster */
  54.584 +			cluster_offset = lseek(s->fd, s->fd_end, SEEK_SET);
  54.585 +			if (allocate == 1) {
  54.586 +				/* round to cluster size */
  54.587 +				cluster_offset = 
  54.588 +					(cluster_offset + s->cluster_size - 1) 
  54.589 +					& ~(s->cluster_size - 1);
  54.590 +				if (qtruncate(s->fd, cluster_offset + 
  54.591 +					      s->cluster_size, s->sparse)!=0) {
  54.592 +					DPRINTF("ERROR truncating file\n");
  54.593 +					return 0;
  54.594 +				}
  54.595 +				s->fd_end = (cluster_offset + s->cluster_size);
  54.596 +				/* if encrypted, we must initialize the cluster
  54.597 +				   content which won't be written */
  54.598 +				if (s->crypt_method && 
  54.599 +				    (n_end - n_start) < s->cluster_sectors) {
  54.600 +					uint64_t start_sect;
  54.601 +					start_sect = (offset & 
  54.602 +						      ~(s->cluster_size - 1)) 
  54.603 +							      >> 9;
  54.604 +					memset(s->cluster_data + 512, 
  54.605 +					       0xaa, 512);
  54.606 +					for (i = 0; i < s->cluster_sectors;i++)
  54.607 +					{
  54.608 +						if (i < n_start || i >= n_end) 
  54.609 +						{
  54.610 +							encrypt_sectors(s, start_sect + i, 
  54.611 +									s->cluster_data, 
  54.612 +									s->cluster_data + 512, 1, 1,
  54.613 +									&s->aes_encrypt_key);
  54.614 +							lseek(s->fd, cluster_offset + i * 512, SEEK_SET);
  54.615 +							if (write(s->fd, s->cluster_data, 512) != 512)
  54.616 +								return -1;
  54.617 +						}
  54.618 +					}
  54.619 +				}
  54.620 +			} else {
  54.621 +				cluster_offset |= QCOW_OFLAG_COMPRESSED | 
  54.622 +					(uint64_t)compressed_size 
  54.623 +						<< (63 - s->cluster_bits);
  54.624 +			}
  54.625 +		}
  54.626 +		/* update L2 table */
  54.627 +		tmp = cpu_to_be64(cluster_offset);
  54.628 +		l2_table[l2_index] = tmp;
  54.629 +
  54.630 +		/*For IO_DIRECT we write 4KByte blocks*/
  54.631 +		l2_sector = (l2_index * sizeof(uint64_t)) >> 12;
  54.632 +		l2_ptr = (char *)l2_table + (l2_sector << 12);
  54.633 +		
  54.634 +		if (posix_memalign((void **)&tmp_ptr2, 4096, 4096) != 0) {
  54.635 +			DPRINTF("ERROR allocating memory for L1 table\n");
  54.636 +		}
  54.637 +		memcpy(tmp_ptr2, l2_ptr, 4096);
  54.638 +		lseek(s->fd, l2_offset + (l2_sector << 12), SEEK_SET);
  54.639 +		if (write(s->fd, tmp_ptr2, 4096) != 4096) {
  54.640 +			free(tmp_ptr2);
  54.641 +			return -1;
  54.642 +		}
  54.643 +		free(tmp_ptr2);
  54.644 +	}
  54.645 +	return cluster_offset;
  54.646 +}
  54.647 +
  54.648 +static int qcow_is_allocated(struct tdqcow_state *s, int64_t sector_num,
  54.649 +                             int nb_sectors, int *pnum)
  54.650 +{
  54.651 +	int index_in_cluster, n;
  54.652 +	uint64_t cluster_offset;
  54.653 +
  54.654 +	cluster_offset = get_cluster_offset(s, sector_num << 9, 0, 0, 0, 0);
  54.655 +	index_in_cluster = sector_num & (s->cluster_sectors - 1);
  54.656 +	n = s->cluster_sectors - index_in_cluster;
  54.657 +	if (n > nb_sectors)
  54.658 +		n = nb_sectors;
  54.659 +	*pnum = n;
  54.660 +	return (cluster_offset != 0);
  54.661 +}
  54.662 +
  54.663 +static int decompress_buffer(uint8_t *out_buf, int out_buf_size,
  54.664 +                             const uint8_t *buf, int buf_size)
  54.665 +{
  54.666 +	z_stream strm1, *strm = &strm1;
  54.667 +	int ret, out_len;
  54.668 +	
  54.669 +	memset(strm, 0, sizeof(*strm));
  54.670 +	
  54.671 +	strm->next_in = (uint8_t *)buf;
  54.672 +	strm->avail_in = buf_size;
  54.673 +	strm->next_out = out_buf;
  54.674 +	strm->avail_out = out_buf_size;
  54.675 +	
  54.676 +	ret = inflateInit2(strm, -12);
  54.677 +	if (ret != Z_OK)
  54.678 +		return -1;
  54.679 +	ret = inflate(strm, Z_FINISH);
  54.680 +	out_len = strm->next_out - out_buf;
  54.681 +	if ( (ret != Z_STREAM_END && ret != Z_BUF_ERROR) ||
  54.682 +	    (out_len != out_buf_size) ) {
  54.683 +		inflateEnd(strm);
  54.684 +		return -1;
  54.685 +	}
  54.686 +	inflateEnd(strm);
  54.687 +	return 0;
  54.688 +}
  54.689 +                              
  54.690 +static int decompress_cluster(struct tdqcow_state *s, uint64_t cluster_offset)
  54.691 +{
  54.692 +	int ret, csize;
  54.693 +	uint64_t coffset;
  54.694 +
  54.695 +	coffset = cluster_offset & s->cluster_offset_mask;
  54.696 +	if (s->cluster_cache_offset != coffset) {
  54.697 +		csize = cluster_offset >> (63 - s->cluster_bits);
  54.698 +		csize &= (s->cluster_size - 1);
  54.699 +		lseek(s->fd, coffset, SEEK_SET);
  54.700 +		ret = read(s->fd, s->cluster_data, csize);
  54.701 +		if (ret != csize) 
  54.702 +			return -1;
  54.703 +		if (decompress_buffer(s->cluster_cache, s->cluster_size,
  54.704 +				      s->cluster_data, csize) < 0) {
  54.705 +			return -1;
  54.706 +		}
  54.707 +		s->cluster_cache_offset = coffset;
  54.708 +	}
  54.709 +	return 0;
  54.710 +}
  54.711 +
  54.712 +static int
  54.713 +tdqcow_read_header(int fd, QCowHeader *header)
  54.714 +{
  54.715 +	int err;
  54.716 +	char *buf;
  54.717 +	struct stat st;
  54.718 +	size_t size, expected;
  54.719 +
  54.720 +	memset(header, 0, sizeof(*header));
  54.721 +
  54.722 +	err = fstat(fd, &st);
  54.723 +	if (err)
  54.724 +		return -errno;
  54.725 +
  54.726 +	err = lseek(fd, 0, SEEK_SET);
  54.727 +	if (err == (off_t)-1)
  54.728 +		return -errno;
  54.729 +
  54.730 +	size = (sizeof(*header) + 511) & ~511;
  54.731 +	err = posix_memalign((void **)&buf, 512, size);
  54.732 +	if (err)
  54.733 +		return err;
  54.734 +
  54.735 +	expected = size;
  54.736 +	if (st.st_size < size)
  54.737 +		expected = st.st_size;
  54.738 +
  54.739 +	errno = 0;
  54.740 +	err = read(fd, buf, size);
  54.741 +	if (err != expected) {
  54.742 +		err = (errno ? -errno : -EIO);
  54.743 +		goto out;
  54.744 +	}
  54.745 +
  54.746 +	memcpy(header, buf, sizeof(*header));
  54.747 +	be32_to_cpus(&header->magic);
  54.748 +	be32_to_cpus(&header->version);
  54.749 +	be64_to_cpus(&header->backing_file_offset);
  54.750 +	be32_to_cpus(&header->backing_file_size);
  54.751 +	be32_to_cpus(&header->mtime);
  54.752 +	be64_to_cpus(&header->size);
  54.753 +	be32_to_cpus(&header->crypt_method);
  54.754 +	be64_to_cpus(&header->l1_table_offset);
  54.755 +
  54.756 +	err = 0;
  54.757 +
  54.758 +out:
  54.759 +	free(buf);
  54.760 +	return err;
  54.761 +}
  54.762 +
  54.763 +static int
  54.764 +tdqcow_load_l1_table(struct tdqcow_state *s, QCowHeader *header)
  54.765 +{
  54.766 +	char *buf;
  54.767 +	struct stat st;
  54.768 +	size_t expected;
  54.769 +	int i, err, shift;
  54.770 +	QCowHeader_ext *exthdr;
  54.771 +	uint32_t l1_table_bytes, l1_table_block, l1_table_size;
  54.772 +
  54.773 +	buf         = NULL;
  54.774 +	s->l1_table = NULL;
  54.775 +
  54.776 +	shift = s->cluster_bits + s->l2_bits;
  54.777 +
  54.778 +	s->l1_size = (header->size + (1LL << shift) - 1) >> shift;
  54.779 +	s->l1_table_offset = header->l1_table_offset;
  54.780 +
  54.781 +	s->min_cluster_alloc = 1; /* default */
  54.782 +
  54.783 +	l1_table_bytes = s->l1_size * sizeof(uint64_t);
  54.784 +	l1_table_size  = (l1_table_bytes + 4095) & ~4095;
  54.785 +	l1_table_block = (l1_table_bytes + s->l1_table_offset + 4095) & ~4095;
  54.786 +
  54.787 +	DPRINTF("L1 Table offset detected: %"PRIu64", size %d (%d)\n",
  54.788 +		(uint64_t)s->l1_table_offset,
  54.789 +		(int) (s->l1_size * sizeof(uint64_t)), 
  54.790 +		l1_table_size);
  54.791 +
  54.792 +	err = fstat(s->fd, &st);
  54.793 +	if (err) {
  54.794 +		err = -errno;
  54.795 +		goto out;
  54.796 +	}
  54.797 +
  54.798 +	err = lseek(s->fd, 0, SEEK_SET);
  54.799 +	if (err == (off_t)-1) {
  54.800 +		err = -errno;
  54.801 +		goto out;
  54.802 +	}
  54.803 +
  54.804 +	err = posix_memalign((void **)&buf, 512, l1_table_block);
  54.805 +	if (err) {
  54.806 +		buf = NULL;
  54.807 +		goto out;
  54.808 +	}
  54.809 +
  54.810 +	err = posix_memalign((void **)&s->l1_table, 4096, l1_table_size);
  54.811 +	if (err) {
  54.812 +		s->l1_table = NULL;
  54.813 +		goto out;
  54.814 +	}
  54.815 +
  54.816 +	memset(buf, 0, l1_table_block);
  54.817 +	memset(s->l1_table, 0, l1_table_size);
  54.818 +
  54.819 +	expected = l1_table_block;
  54.820 +	if (st.st_size < l1_table_block)
  54.821 +		expected = st.st_size;
  54.822 +
  54.823 +	errno = 0;
  54.824 +	err = read(s->fd, buf, l1_table_block);
  54.825 +	if (err != expected) {
  54.826 +		err = (errno ? -errno : -EIO);
  54.827 +		goto out;
  54.828 +	}
  54.829 +
  54.830 +	memcpy(s->l1_table, buf + s->l1_table_offset, l1_table_size);
  54.831 +	exthdr = (QCowHeader_ext *)(buf + sizeof(QCowHeader));
  54.832 +
  54.833 +	/* check for xen extended header */
  54.834 +	if (s->l1_table_offset % 4096 == 0 &&
  54.835 +	    be32_to_cpu(exthdr->xmagic) == XEN_MAGIC) {
  54.836 +		uint32_t flags = be32_to_cpu(exthdr->flags);
  54.837 +		uint32_t cksum = be32_to_cpu(exthdr->cksum);
  54.838 +
  54.839 +		/*
  54.840 +		 * Try to detect old tapdisk images. They have to be fixed
  54.841 +		 * because they use big endian rather than native endian for
  54.842 +		 * the L1 table.  After this block, the l1 table will
  54.843 +		 * definitely be in BIG endian.
  54.844 +		 */
  54.845 +		if (!(flags & EXTHDR_L1_BIG_ENDIAN)) {
  54.846 +			DPRINTF("qcow: converting to big endian L1 table\n");
  54.847 +
  54.848 +			/* convert to big endian */
  54.849 +			for (i = 0; i < s->l1_size; i++)
  54.850 +				cpu_to_be64s(&s->l1_table[i]);
  54.851 +
  54.852 +			flags |= EXTHDR_L1_BIG_ENDIAN;
  54.853 +			exthdr->flags = cpu_to_be32(flags);
  54.854 +
  54.855 +			memcpy(buf + s->l1_table_offset,
  54.856 +			       s->l1_table, l1_table_size);
  54.857 +			
  54.858 +			err = lseek(s->fd, 0, SEEK_SET);
  54.859 +			if (err == (off_t)-1) {
  54.860 +				err = -errno;
  54.861 +				goto out;
  54.862 +			}
  54.863 +
  54.864 +			err = atomicio(vwrite, s->fd, buf, l1_table_block);
  54.865 +			if (err != l1_table_block) {
  54.866 +				err = -errno;
  54.867 +				goto out;
  54.868 +			}
  54.869 +		}
  54.870 +
  54.871 +		/* check the L1 table checksum */
  54.872 +		if (cksum != gen_cksum((char *)s->l1_table,
  54.873 +				       s->l1_size * sizeof(uint64_t)))
  54.874 +			DPRINTF("qcow: bad L1 checksum\n");
  54.875 +		else {
  54.876 +			s->extended = 1;
  54.877 +			s->sparse = (be32_to_cpu(exthdr->flags) & SPARSE_FILE);
  54.878 +			s->min_cluster_alloc =
  54.879 +				be32_to_cpu(exthdr->min_cluster_alloc);
  54.880 +		}
  54.881 +	}
  54.882 +
  54.883 +	/* convert L1 table to native endian for operation */
  54.884 +	for (i = 0; i < s->l1_size; i++)
  54.885 +		be64_to_cpus(&s->l1_table[i]);
  54.886 +
  54.887 +	err = 0;
  54.888 +
  54.889 +out:
  54.890 +	if (err) {
  54.891 +		free(buf);
  54.892 +		free(s->l1_table);
  54.893 +		s->l1_table = NULL;
  54.894 +	}
  54.895 +	return err;
  54.896 +}
  54.897 +
  54.898 +/* Open the disk file and initialize qcow state. */
  54.899 +int tdqcow_open (td_driver_t *driver, const char *name, td_flag_t flags)
  54.900 +{
  54.901 +	int fd, len, i, ret, size, o_flags;
  54.902 +	td_disk_info_t *bs = &(driver->info);
  54.903 +	struct tdqcow_state   *s  = (struct tdqcow_state *)driver->data;
  54.904 +	QCowHeader header;
  54.905 +	uint64_t final_cluster = 0;
  54.906 +
  54.907 + 	DPRINTF("QCOW: Opening %s\n", name);
  54.908 +
  54.909 +	o_flags = O_DIRECT | O_LARGEFILE | 
  54.910 +		((flags == TD_OPEN_RDONLY) ? O_RDONLY : O_RDWR);
  54.911 +	fd = open(name, o_flags);
  54.912 +	if (fd < 0) {
  54.913 +		DPRINTF("Unable to open %s (%d)\n", name, -errno);
  54.914 +		return -1;
  54.915 +	}
  54.916 +
  54.917 +	s->fd = fd;
  54.918 +	s->name = strdup(name);
  54.919 +	if (!s->name)
  54.920 +		goto fail;
  54.921 +
  54.922 +	if (tdqcow_read_header(fd, &header))
  54.923 +		goto fail;
  54.924 +
  54.925 +	if (header.magic != QCOW_MAGIC)
  54.926 +		goto fail;
  54.927 +
  54.928 +	switch (header.version) {
  54.929 +	case QCOW_VERSION:
  54.930 +		break;
  54.931 +	case 2:
  54.932 +	  //TODO: Port qcow2 to new blktap framework.
  54.933 +	  //		close(fd);
  54.934 +	  //		dd->drv = &tapdisk_qcow2;
  54.935 +	  //		return dd->drv->td_open(dd, name, flags);
  54.936 +	  goto fail;
  54.937 +	default:
  54.938 +		goto fail;
  54.939 +	}
  54.940 +
  54.941 +	if (header.size <= 1 || header.cluster_bits < 9)
  54.942 +		goto fail;
  54.943 +	if (header.crypt_method > QCOW_CRYPT_AES)
  54.944 +		goto fail;
  54.945 +	s->crypt_method_header = header.crypt_method;
  54.946 +	if (s->crypt_method_header)
  54.947 +		s->encrypted = 1;
  54.948 +	s->cluster_bits = header.cluster_bits;
  54.949 +	s->cluster_size = 1 << s->cluster_bits;
  54.950 +	s->cluster_sectors = 1 << (s->cluster_bits - 9);
  54.951 +	s->l2_bits = header.l2_bits;
  54.952 +	s->l2_size = 1 << s->l2_bits;
  54.953 +	s->cluster_alloc = s->l2_size;
  54.954 +	bs->size = header.size / 512;
  54.955 +	s->cluster_offset_mask = (1LL << (63 - s->cluster_bits)) - 1;
  54.956 +	s->backing_file_offset = header.backing_file_offset;
  54.957 +	s->backing_file_size   = header.backing_file_size;
  54.958 +
  54.959 +	/* allocate and load l1 table */
  54.960 +	if (tdqcow_load_l1_table(s, &header))
  54.961 +		goto fail;
  54.962 +
  54.963 +	/* alloc L2 cache */
  54.964 +	size = s->l2_size * L2_CACHE_SIZE * sizeof(uint64_t);
  54.965 +	ret = posix_memalign((void **)&s->l2_cache, 4096, size);
  54.966 +	if(ret != 0) goto fail;
  54.967 +
  54.968 +	size = s->cluster_size;
  54.969 +	ret = posix_memalign((void **)&s->cluster_cache, 4096, size);
  54.970 +	if(ret != 0) goto fail;
  54.971 +
  54.972 +	ret = posix_memalign((void **)&s->cluster_data, 4096, size);
  54.973 +	if(ret != 0) goto fail;
  54.974 +	s->cluster_cache_offset = -1;
  54.975 +
  54.976 +	if (s->backing_file_offset != 0)
  54.977 +		s->cluster_alloc = 1; /*Cannot use pre-alloc*/
  54.978 +
  54.979 +        bs->sector_size = 512;
  54.980 +        bs->info = 0;
  54.981 +
  54.982 +	for(i = 0; i < s->l1_size; i++)
  54.983 +		if (s->l1_table[i] > final_cluster)
  54.984 +			final_cluster = s->l1_table[i];
  54.985 +
  54.986 +	if (init_aio_state(driver)!=0) {
  54.987 +	  DPRINTF("Unable to initialise AIO state\n");
  54.988 +	  free_aio_state(s);
  54.989 +	  goto fail;
  54.990 +	}
  54.991 +
  54.992 +	if (!final_cluster)
  54.993 +		s->fd_end = s->l1_table_offset +
  54.994 +			((s->l1_size * sizeof(uint64_t) + 4095) & ~4095);
  54.995 +	else {
  54.996 +		s->fd_end = lseek64(fd, 0, SEEK_END);
  54.997 +		if (s->fd_end == (off64_t)-1)
  54.998 +			goto fail;
  54.999 +	}
 54.1000 +
 54.1001 +	return 0;
 54.1002 +	
 54.1003 +fail:
 54.1004 +	DPRINTF("QCOW Open failed\n");
 54.1005 +
 54.1006 +	free_aio_state(s);
 54.1007 +	free(s->l1_table);
 54.1008 +	free(s->l2_cache);
 54.1009 +	free(s->cluster_cache);
 54.1010 +	free(s->cluster_data);
 54.1011 +	close(fd);
 54.1012 +	return -1;
 54.1013 +}
 54.1014 +
 54.1015 +void tdqcow_queue_read(td_driver_t *driver, td_request_t treq)
 54.1016 +{
 54.1017 +	struct tdqcow_state   *s  = (struct tdqcow_state *)driver->data;
 54.1018 +	int ret = 0, index_in_cluster, n, i;
 54.1019 +	uint64_t cluster_offset, sector, nb_sectors;
 54.1020 +	struct qcow_prv* prv;
 54.1021 +	td_request_t clone = treq;
 54.1022 +	char* buf = treq.buf;
 54.1023 +
 54.1024 +	sector     = treq.sec;
 54.1025 +	nb_sectors = treq.secs;
 54.1026 +
 54.1027 +	/*We store a local record of the request*/
 54.1028 +	while (nb_sectors > 0) {
 54.1029 +		cluster_offset = 
 54.1030 +			get_cluster_offset(s, sector << 9, 0, 0, 0, 0);
 54.1031 +		index_in_cluster = sector & (s->cluster_sectors - 1);
 54.1032 +		n = s->cluster_sectors - index_in_cluster;
 54.1033 +		if (n > nb_sectors)
 54.1034 +			n = nb_sectors;
 54.1035 +
 54.1036 +		if (s->aio_free_count == 0) {
 54.1037 +			td_complete_request(treq, -EBUSY);
 54.1038 +			return;
 54.1039 +		}
 54.1040 +		
 54.1041 +		if(!cluster_offset) {
 54.1042 +			treq.buf  = buf;
 54.1043 +			treq.sec  = sector;
 54.1044 +			treq.secs = n;
 54.1045 +			td_forward_request(treq);
 54.1046 +
 54.1047 +		} else if (cluster_offset & QCOW_OFLAG_COMPRESSED) {
 54.1048 +			if (decompress_cluster(s, cluster_offset) < 0) {
 54.1049 +				td_complete_request(treq, -EIO);
 54.1050 +				goto done;
 54.1051 +			}
 54.1052 +			memcpy(buf, s->cluster_cache + index_in_cluster * 512, 
 54.1053 +			       512 * n);
 54.1054 +			
 54.1055 +			treq.buf  = buf;
 54.1056