From: Konrad Rzeszutek Wilk Date: Tue, 25 Aug 2015 15:22:10 +0000 (-0400) Subject: tmem-test: Initial work. X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=3e38048aecd94db339b35791366cc4ccc6bc5bda;p=xentesttools%2Fbootstrap.git tmem-test: Initial work. Signed-off-by: Konrad Rzeszutek Wilk --- diff --git a/root_image/Makefile b/root_image/Makefile index 78104b7..174cea7 100644 --- a/root_image/Makefile +++ b/root_image/Makefile @@ -472,9 +472,6 @@ endif $(call RPM_TO_USERSPACE,./sbin/fdisk,$(RPM_DIR)/util-linux-ng) $(call RPM_TO_USERSPACE,./sbin/losetup,$(RPM_DIR)/util-linux-ng) $(call RPM_TO_USERSPACE,./sbin/pivot_root,$(RPM_DIR)/util-linux-ng) - $(call RPM_TO_USERSPACE,./sbin/swapon,$(RPM_DIR)/util-linux-ng) - $(call RPM_TO_USERSPACE,./sbin/swapoff,$(RPM_DIR)/util-linux-ng) - $(call RPM_TO_USERSPACE,./sbin/mkswap,$(RPM_DIR)/util-linux-ng) $(call RPM_TO_USERSPACE,./usr/bin/hexdump,$(RPM_DIR)/util-linux-ng) $(call RPM_TO_USERSPACE,./usr/bin/flock,$(RPM_DIR)/util-linux-ng) $(call RPM_TO_USERSPACE,./usr/bin/time,$(RPM_DIR)/time) @@ -974,8 +971,16 @@ xtt-tools-install-fb: directfb-install LDLIBS="-L$(shell pwd)/userspace/$(LIBSDIR)" $(MAKE) -j$$(($(NCPUS) * 2)) $(MFLAGS) -C tools/drfb_test $(INSTALL_PROG) tools/drfb_test/dfbtest_fillrect userspace/usr/bin/ +.PHONY: xtt-tools-install-eatmem +xtt-tools-install-eatmem: + LDLIBS="-L$(shell pwd)/userspace/$(LIBSDIR)" $(MAKE) -j$$(($(NCPUS) * 2)) $(MFLAGS) -C tools/eatmem + $(call RPM_TO_USERSPACE,./sbin/mkswap,$(RPM_DIR)/util-linux-ng) + $(call RPM_TO_USERSPACE,./sbin/swapon,$(RPM_DIR)/util-linux-ng) + $(call RPM_TO_USERSPACE,./sbin/swapoff,$(RPM_DIR)/util-linux-ng) + $(INSTALL_PROG) tools/eatmem/eatmem userspace/usr/bin/ + .PHONY: xtt-tools-install -xtt-tools-install: +xtt-tools-install: xtt-tools-install-eatmem LDLIBS="-L$(shell pwd)/userspace/$(LIBSDIR)" $(MAKE) -j$$(($(NCPUS) * 2)) $(MFLAGS) -C tools $(INSTALL_PROG) tools/ssh_support/ssh-shadowgen userspace/usr/sbin/ $(INSTALL_SCRIPT) tools/ssh_support/sshd_server userspace/usr/bin/ @@ -986,7 +991,6 @@ xtt-tools-install: $(INSTALL_PROG) tools/read_intr/read_intr userspace/usr/bin/ $(INSTALL_PROG) tools/debug/fb_test userspace/usr/bin/ $(INSTALL_PROG) tools/crashme/crashme userspace/usr/bin/ - $(INSTALL_PROG) tools/eatmem/eatmem userspace/usr/bin/ $(INSTALL_PROG) tools/discard_io/discard_io userspace/usr/bin/ fio/fio: fio/fio diff --git a/root_image/drivers/Makefile b/root_image/drivers/Makefile index 209a3c3..45d68e1 100644 --- a/root_image/drivers/Makefile +++ b/root_image/drivers/Makefile @@ -2,6 +2,7 @@ obj-m += dma_test/ obj-m += wb_to_wc/ obj-m += xen_diag/ obj-m += spinlock_hog/ +obj-m += tmem_test/ .PHONY: distclean distclean: clean diff --git a/root_image/drivers/tmem_test/Makefile b/root_image/drivers/tmem_test/Makefile new file mode 100644 index 0000000..4a02fb4 --- /dev/null +++ b/root_image/drivers/tmem_test/Makefile @@ -0,0 +1,37 @@ +# Comment/uncomment the following line to disable/enable debugging +#DEBUG = y + +# Add your debugging flag (or not) to CFLAGS +ifeq ($(DEBUG),y) + DEBFLAGS = -O -g # "-O" is needed to expand inlines +else + DEBFLAGS = -O2 +endif + +EXTRA_CFLAGS += $(DEBFLAGS) -I$(LDDINCDIR) + +ifneq ($(KERNELRELEASE),) +# call from kernel build system + +obj-m := tmem_test.o + +else + +KERNELDIR ?= /lib/modules/$(shell uname -r)/build +PWD := $(shell pwd) + +default: + $(MAKE) -C $(KERNELDIR) M=$(PWD) LDDINCDIR=$(PWD)/../include modules + +endif + +clean: + rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions + +depend .depend dep: + $(CC) $(CFLAGS) -M *.c > .depend + + +ifeq (.depend,$(wildcard .depend)) +include .depend +endif diff --git a/root_image/drivers/tmem_test/tmem_test.c b/root_image/drivers/tmem_test/tmem_test.c new file mode 100644 index 0000000..a162afd --- /dev/null +++ b/root_image/drivers/tmem_test/tmem_test.c @@ -0,0 +1,322 @@ +#define pr_fmt(fmt) "xen:" KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define TMEM_TEST "0.1" + +MODULE_AUTHOR("Konrad Rzeszutek Wilk "); +MODULE_DESCRIPTION("tmem_test"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(TMEM_TEST); + +static bool shared __read_mostly = true; +module_param(shared, bool, S_IRUGO); + +#define MAX_PAGES 20 +struct tmem_oid { + u64 oid[3]; +}; +struct tmem_pool_uuid { + u64 lo; + u64 hi; +}; +struct _arg { + int flags; + int pool; + int rc; + struct tmem_oid oid; + struct tmem_pool_uuid uuid; +}; + + +#define TMEM_CONTROL 0 +#define TMEM_NEW_POOL 1 +#define TMEM_DESTROY_POOL 2 +#define TMEM_NEW_PAGE 3 +#define TMEM_PUT_PAGE 4 +#define TMEM_GET_PAGE 5 + +#define TMEM_FLUSH_PAGE 6 +#define TMEM_FLUSH_OBJECT 7 +#define TMEM_READ 8 +#define TMEM_WRITE 9 +#define TMEM_XCHG 10 + +/* Bits for HYPERVISOR_tmem_op(TMEM_NEW_POOL) */ +#define TMEM_POOL_PERSIST 1 +#define TMEM_POOL_SHARED 2 +#define TMEM_POOL_PAGESIZE_SHIFT 4 +#define TMEM_VERSION_SHIFT 24 + +#define EFROZEN 1000 +#define EEMPTY 1001 +static inline int xen_tmem_op(u32 tmem_cmd, u32 tmem_pool, struct tmem_oid oid, + u32 index, unsigned long gmfn) +{ + struct tmem_op op; + int rc = 0; + + op.cmd = tmem_cmd; + op.pool_id = tmem_pool; + op.u.gen.oid[0] = oid.oid[0]; + op.u.gen.oid[1] = oid.oid[1]; + op.u.gen.oid[2] = oid.oid[2]; + op.u.gen.index = index; + op.u.gen.tmem_offset = 0; + op.u.gen.pfn_offset = 0; + op.u.gen.len = 0; + set_xen_guest_handle(op.u.gen.gmfn, (void *)gmfn); + rc = HYPERVISOR_tmem_op(&op); + return rc; +} +static int xen_tmem_new_pool(struct tmem_pool_uuid uuid, u32 flags, unsigned long pagesize) +{ + struct tmem_op op; + int rc = 0, pageshift; + + for (pageshift = 0; pagesize != 1; pageshift++) + pagesize >>= 1; + flags |= (pageshift - 12) << TMEM_POOL_PAGESIZE_SHIFT; + flags |= TMEM_SPEC_VERSION << TMEM_VERSION_SHIFT; + op.cmd = TMEM_NEW_POOL; + op.u.new.uuid[0] = uuid.lo; + op.u.new.uuid[1] = uuid.hi; + op.u.new.flags = flags; + rc = HYPERVISOR_tmem_op(&op); + return rc; +} + +/* xen generic tmem ops */ + +static int xen_tmem_put_page(u32 pool_id, struct tmem_oid oid, + u32 index, unsigned long pfn) +{ + unsigned long gmfn = xen_pv_domain() ? pfn_to_mfn(pfn) : pfn; + + return xen_tmem_op(TMEM_PUT_PAGE, pool_id, oid, index, gmfn); +} +static int xen_tmem_get_page(u32 pool_id, struct tmem_oid oid, + u32 index, unsigned long pfn) +{ + unsigned long gmfn = xen_pv_domain() ? pfn_to_mfn(pfn) : pfn; + + return xen_tmem_op(TMEM_GET_PAGE, pool_id, oid, index, gmfn); +} + +static int xen_tmem_destroy_pool(u32 pool_id) +{ + struct tmem_oid oid = { { 0 } }; + + return xen_tmem_op(TMEM_DESTROY_POOL, pool_id, oid, 0, 0); +} + +static int thread(void *_arg) +{ + struct _arg *arg = (struct _arg *)_arg; + struct page *a[MAX_PAGES]; + struct tmem_oid oid[MAX_PAGES]; + unsigned int i, j; + int rc = 0; + + if (!_arg) { + pr_warn("No arguments passed in thread!\n"); + return -EINVAL; + } + pr_info("pool=%d, flags=%d, uuid=%lx:%lx\n", arg->pool, arg->flags, + (unsigned long)arg->uuid.lo, (unsigned long)arg->uuid.hi); + arg->rc = 0; + do { + for (j = 0, i = 0;i < MAX_PAGES; i++, j++) { + a[i] = alloc_page(GFP_KERNEL); + if (!a[i]) + break; + } + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout_interruptible(HZ); + for (i = 0; i < j; i++) { + unsigned long *addr = page_address(a[i]); + if (addr) { + memset(addr, 0xc2, PAGE_SIZE); + } + oid[i].oid[0] = arg->oid.oid[0]; + oid[i].oid[1] = arg->oid.oid[1]; + oid[i].oid[2] = (u64)addr; + } +again: + /* Do the tmem operation. */ + for (i = 0; i < j; i++) { + struct page *page = a[i]; + unsigned long pfn = page_to_pfn(page); + + rc = xen_tmem_put_page(arg->pool, oid[i], 0, pfn); + + if (rc != 1) { + pr_warn("pool=%d i=%d PUT PFN=0x%lx, rc=%d!\n", arg->pool,i, pfn, rc); + if (rc == -EFROZEN || rc == -ENOMEM) { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout_interruptible(HZ); + goto again; + } + arg->rc = rc; + break; + } + } + if (rc != 1) + break; + rc = 0; + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout_interruptible(HZ); + for (i = 0; i < j; i++) { + struct page *page = a[i]; + unsigned long pfn = page_to_pfn(page); + unsigned long *addr = page_address(page); + + rc = xen_tmem_get_page(arg->pool, oid[i], 0, pfn); + + if (rc != 1) { + pr_warn("pool=%d i=%d GET PFN=0x%lx, rc=%d!\n", arg->pool, i, pfn, rc); + arg->rc = rc; + break; + } + if (addr) { + unsigned long v; + for (v = 0; v < PAGE_SIZE / sizeof(*addr); v += sizeof(*addr)) + { + if (addr[v] != 0xc2c2c2c2c2c2c2c2) { + print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, addr, PAGE_SIZE); + pr_warn("pool=%d i=%d UUID=%lx:%lx failed! Have: [0x%lx]\n", arg->pool, i, + (unsigned long)arg->uuid.lo, (unsigned long)arg->uuid.hi, + addr[v]); + BUG(); + } + } + } + } + if (rc != 1) + break; + rc = 0; + for (i = 0; i< MAX_PAGES; i++) { + if (a[i]) + __free_page(a[i]); + a[i] = NULL; + } + } while (!kthread_should_stop()); + return rc; +} +#define MAX_THREADS 4 +static struct task_struct *t[MAX_THREADS]; +static struct _arg a[MAX_THREADS]; + +static int __init tmem_test_init(void) +{ + unsigned int i; + int rc; + + /* First is TMEM_POOL_PERSIST */ + i = 0; + a[i].uuid.lo = 0; + a[i].uuid.hi = 0; + a[i].flags = TMEM_POOL_PERSIST; + a[i].pool = -1; + a[i].oid.oid[0] = 0x1000+i; + + if (shared) { + i++; + a[i].uuid.lo = 0xdeadbeef; + a[i].uuid.hi = 0; + a[i].flags = TMEM_POOL_SHARED; + a[i].pool = -1; + a[i].oid.oid[0] = 0x1000+i; + + i++; + a[i].uuid.lo = 0xdeadbeef; + a[i].uuid.hi = 0; + a[i].flags = TMEM_POOL_SHARED; + a[i].pool = -1; + a[i].oid.oid[0] = 0x1000+i; + } else { + i++; + a[i].oid.oid[0] = 0; + a[i].pool = -1; + i++; + a[i].oid.oid[0] = 0; + a[i].pool = -1; + } + i++; + a[i].uuid.lo = 0xbad; + a[i].uuid.hi = 0xf00d; + a[i].flags = 0; + a[i].pool = -1; + a[i].oid.oid[0] = 0x1000+i; + + for (i = 0; i < MAX_THREADS; i++) { + a[i].rc = 0; + if (!a[i].oid.oid[0]) + continue; + + rc = xen_tmem_new_pool(a[i].uuid, a[i].flags, PAGE_SIZE); + if (rc < 0) { + pr_warn("%d UUID=%lx:%lx flags=0x%x failed with rc=%d\n", + i, (unsigned long)a[i].uuid.lo, (unsigned long)a[i].uuid.hi, a[i].flags, rc); + rc = -EINVAL; + goto exit; + } + a[i].pool = rc; + } + pr_info("Pools allocated.\n"); + for (i = 0; i < MAX_THREADS; i++) { + if (!a[i].oid.oid[0]) + continue; + t[i] = kthread_run(thread, &a[i], "tmem_test"); + if (!t[i]) { + rc = -EINVAL; + goto exit; + } + } + + pr_info("Threads running.\n"); + return 0; +exit: + for (i = 0; i < MAX_THREADS; i++) + { + if (!a[i].oid.oid[0]) + continue; + if (t[i]) + kthread_stop(t[i]); + } + /* Two of the pools are shared so we need to stop workers first.*/ + for (i = 0; i < MAX_THREADS; i++) + if (a[i].pool != -1) + xen_tmem_destroy_pool(a[i].pool); + return rc; +} +static void __exit tmem_test_exit(void) +{ + unsigned int i; + + for (i = 0; i < MAX_THREADS; i++) { + if (!a[i].oid.oid[0]) + continue; + if (t[i] && a[i].rc == 0) + kthread_stop(t[i]); + } + + for (i = 0; i < MAX_THREADS; i++) { + if (a[i].pool != -1) + xen_tmem_destroy_pool(a[i].pool); + } +} +module_init(tmem_test_init); +module_exit(tmem_test_exit); diff --git a/root_image/etc/init.d/rcS b/root_image/etc/init.d/rcS index df6eff4..c1490c4 100755 --- a/root_image/etc/init.d/rcS +++ b/root_image/etc/init.d/rcS @@ -145,8 +145,8 @@ if [ $? == 0 ]; then crashme) while (true); do crashme +2000 666 100 1:00:00; echo "testing.."; done & ;; - eatmem) - while (true); do eatmem 64MB 10; echo "testing ..";done & + tmem) + /etc/init.d/tmem ;; dfb) while (true); do dfbtest_fillrect; done & diff --git a/root_image/etc/init.d/tmem b/root_image/etc/init.d/tmem new file mode 100755 index 0000000..1b6e9c1 --- /dev/null +++ b/root_image/etc/init.d/tmem @@ -0,0 +1,109 @@ +#!/bin/bash + + . /etc/init.d/functions + +SWAP_SIZE="+768M" +FS_SIZE="+256M" +FIO_TEST="/tmp/read.fio" + +tmem_check() +{ + local _rc=$1 + if [ $_rc -ne 0 ]; then + echo "Failed with $_rc" + exit $rc + fi +} +tmem_setup () +{ + local disk=$1 + echo "Erasing $disk" + + (echo o; echo w) | fdisk $disk + rc=$? + tmem_check $rc + echo "-----------------------------------" + echo "Creating swap fs with $SWAP_SIZE" + (echo n; echo p;echo 1; echo 1; echo $SWAP_SIZE; echo w) | fdisk $disk + rc=$? + tmem_check $rc + echo "-----------------------------------" + echo "Creating fs partition" + echo -e "n\np\n2\n\n\nw" | fdisk $disk + #(echo n; echo p; echo 2; echo 1; echo $FS_SIZE; echo w) | fdisk $disk + rc=$? + tmem_check $rc + + sync + sleep 5 + echo "-----------------------------------" + echo "Formating swap partition" + + mkswap ${disk}1 + rc=$? + tmem_check $rc + + echo "-----------------------------------" + echo "Formating FS partition" + mkfs.ext3 ${disk}2 + rc=$? + tmem_check $rc + + echo "sync" + + sync + + + mkdir /TEST + mount ${disk}2 /TEST + rc=$? + tmem_check $rc + + swapon ${disk}1 + rc=$? + tmem_check $rc + + return 0; +} + +tmem_missing() +{ + echo "Missing binaries. Disabling tmem tests." + exit 1; +} + +which mkswap 1>/dev/null 2>/dev/null +if [ $? -eq 1 ]; then + tmem_missing +fi +which swapon 1>/dev/null 2>/dev/null +if [ $? -eq 1 ]; then + tmem_missing +fi + +# This should be figured by some boot parameters, but for now just assume +# xvda +tmem_setup /dev/xvda +rc=$? +if [ $rc -ne 0 ]; then + echo "Test failed with $rc!" + exit $rc +fi +modprobe tmem +# Now the kernel will start pushing pages in swap.. +echo "Kicking off eatmem." + +echo "while (true); do eatmem 100M 10; echo '+'; done" > /tmp/tmem.sh + +echo "[/TEST/test]" > $FIO_TEST +echo "buffered=1" >> $FIO_TEST +echo "rw=read" >> $FIO_TEST +echo "runtime=360" >> $FIO_TEST +echo "size=250M" >> $FIO_TEST +echo "directory=/TEST" >> $FIO_TEST + +chmod 755 /tmp/tmem.sh +nohup bash /tmp/tmem.sh & +nohup bash fio $FIO_TEST & + +modprobe tmem-test