linux/arch
Stefano Stabellini 318095d39c xen: mark local pages as FOREIGN in the m2p_override
commit b9e0d95c04 upstream.

When the frontend and the backend reside on the same domain, even if we
add pages to the m2p_override, these pages will never be returned by
mfn_to_pfn because the check "get_phys_to_machine(pfn) != mfn" will
always fail, so the pfn of the frontend will be returned instead
(resulting in a deadlock because the frontend pages are already locked).

INFO: task qemu-system-i38:1085 blocked for more than 120 seconds.
"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
qemu-system-i38 D ffff8800cfc137c0     0  1085      1 0x00000000
 ffff8800c47ed898 0000000000000282 ffff8800be4596b0 00000000000137c0
 ffff8800c47edfd8 ffff8800c47ec010 00000000000137c0 00000000000137c0
 ffff8800c47edfd8 00000000000137c0 ffffffff82213020 ffff8800be4596b0
Call Trace:
 [<ffffffff81101ee0>] ? __lock_page+0x70/0x70
 [<ffffffff81a0fdd9>] schedule+0x29/0x70
 [<ffffffff81a0fe80>] io_schedule+0x60/0x80
 [<ffffffff81101eee>] sleep_on_page+0xe/0x20
 [<ffffffff81a0e1ca>] __wait_on_bit_lock+0x5a/0xc0
 [<ffffffff81101ed7>] __lock_page+0x67/0x70
 [<ffffffff8106f750>] ? autoremove_wake_function+0x40/0x40
 [<ffffffff811867e6>] ? bio_add_page+0x36/0x40
 [<ffffffff8110b692>] set_page_dirty_lock+0x52/0x60
 [<ffffffff81186021>] bio_set_pages_dirty+0x51/0x70
 [<ffffffff8118c6b4>] do_blockdev_direct_IO+0xb24/0xeb0
 [<ffffffff811e71a0>] ? ext3_get_blocks_handle+0xe00/0xe00
 [<ffffffff8118ca95>] __blockdev_direct_IO+0x55/0x60
 [<ffffffff811e71a0>] ? ext3_get_blocks_handle+0xe00/0xe00
 [<ffffffff811e91c8>] ext3_direct_IO+0xf8/0x390
 [<ffffffff811e71a0>] ? ext3_get_blocks_handle+0xe00/0xe00
 [<ffffffff81004b60>] ? xen_mc_flush+0xb0/0x1b0
 [<ffffffff81104027>] generic_file_aio_read+0x737/0x780
 [<ffffffff813bedeb>] ? gnttab_map_refs+0x15b/0x1e0
 [<ffffffff811038f0>] ? find_get_pages+0x150/0x150
 [<ffffffff8119736c>] aio_rw_vect_retry+0x7c/0x1d0
 [<ffffffff811972f0>] ? lookup_ioctx+0x90/0x90
 [<ffffffff81198856>] aio_run_iocb+0x66/0x1a0
 [<ffffffff811998b8>] do_io_submit+0x708/0xb90
 [<ffffffff81199d50>] sys_io_submit+0x10/0x20
 [<ffffffff81a18d69>] system_call_fastpath+0x16/0x1b

The explanation is in the comment within the code:

We need to do this because the pages shared by the frontend
(xen-blkfront) can be already locked (lock_page, called by
do_read_cache_page); when the userspace backend tries to use them
with direct_IO, mfn_to_pfn returns the pfn of the frontend, so
do_blockdev_direct_IO is going to try to lock the same pages
again resulting in a deadlock.

A simplified call graph looks like this:

pygrub                          QEMU
-----------------------------------------------
do_read_cache_page              io_submit
  |                              |
lock_page                       ext3_direct_IO
                                 |
                                bio_add_page
                                 |
                                lock_page

Internally the xen-blkback uses m2p_add_override to swizzle (temporarily)
a 'struct page' to have a different MFN (so that it can point to another
guest). It also can easily find out whether another pfn corresponding
to the mfn exists in the m2p, and can set the FOREIGN bit
in the p2m, making sure that mfn_to_pfn returns the pfn of the backend.

This allows the backend to perform direct_IO on these pages, but as a
side effect prevents the frontend from using get_user_pages_fast on
them while they are being shared with the backend.

Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2012-08-26 15:12:11 -07:00
..
alpha alpha: fix 32/64-bit bug in futex support 2012-03-12 10:32:55 -07:00
arm ARM: mxs: Remove MMAP_MIN_ADDR setting from mxs_defconfig 2012-08-15 12:04:29 -07:00
avr32 avr32: select generic atomic64_t support 2012-03-12 10:32:57 -07:00
blackfin rtc: fix build warnings in defconfigs 2011-06-15 20:04:02 -07:00
cris cris: add missing declaration of kgdb_init() and breakpoint() 2011-08-15 18:31:32 -07:00
frv Merge branch 'setns' 2011-05-28 10:51:01 -07:00
h8300 Merge branch 'setns' 2011-05-28 10:51:01 -07:00
ia64 random: remove rand_initialize_irq() 2012-08-15 12:04:28 -07:00
m32r Fix node_start/end_pfn() definition for mm/page_cgroup.c 2011-06-27 14:13:09 -07:00
m68k m68k: Correct the Atari ALLOWINT definition 2012-08-09 08:27:53 -07:00
microblaze Merge branch 'setns' 2011-05-28 10:51:01 -07:00
mips MIPS: Properly align the .data..init_task section. 2012-08-01 12:26:54 -07:00
mn10300 MN10300: asm/uaccess.h needs to #include linux/kernel.h for might_sleep() 2011-06-21 18:31:44 -07:00
parisc PARISC: fix TLB fault path on PA2.0 narrow systems 2012-06-10 00:32:58 +09:00
powerpc powerpc: Fix wrong divisor in usecs_to_cputime 2012-08-09 08:27:34 -07:00
s390 s390/compat: fix mmap compat system calls 2012-08-26 15:12:10 -07:00
score score: fix off-by-one index into syscall table 2012-01-25 17:25:04 -08:00
sh oprofile, arm/sh: Fix oprofile_arch_exit() linkage issue 2012-01-06 14:13:57 -08:00
sparc KEYS: Use the compat keyctl() syscall wrapper on Sparc64 for Sparc32 compat 2012-06-01 15:12:54 +08:00
tile tile: fix bug where fls(0) was not returning 0 2012-06-01 15:13:00 +08:00
um um: Implement a custom pte_same() function 2012-06-01 15:12:55 +08:00
unicore32 unicore32: using generic-y format for one line asm-generic files 2011-06-09 16:29:52 +08:00
x86 xen: mark local pages as FOREIGN in the m2p_override 2012-08-26 15:12:11 -07:00
xtensa xtensa: prevent arbitrary read in ptrace 2011-08-04 21:58:39 -07:00
.gitignore
Kconfig mm, powerpc: move the RCU page-table freeing into generic code 2011-05-25 08:39:16 -07:00