virtual alias problem with vmap and I/O (xfs)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi all,

In some cases, xfs can end up doing I/O on a set of physical pages
that have been written to via a virtual alias set up by vmap().  (And
possibly in the other direction as well.)

Currently, xfs doesn't do anything special to handle this,
which means we can and do end up with on-disk fs corruption on
architectures with virtual caches.

I can't find any primitive that xfs should use to handle this.  Just
calling flush_dcache_page() obviously won't work since it cleans the
kernel direct mapping of the page, which isn't the one being used to
access the page.  flush_cache_range() would be suitable if it weren't
restricted to work on user addresses only, and as to
flush_cache_{vmap,vunmap}, I can't figure out what the semantics of
these are supposed to be.[*]

I guess that what xfs wants to do just isn't currently supported.

The DMA API doesn't seem right the right place to handle this, since
that deals with coherence between page_address(page) and external DMA
agents.

xfs doesn't need to guarantee coherence with DMA agents, it just needs
to make sure that the virtual aliases it uses are coherent with the
kernel direct mappings of the underlying physical pages, but such
semantics are problematic as well, since just cache cleaning the
virtual address region corresponding to a vmap() alias doesn't
guarantee that there isn't still (dirty) data in the kernel direct
mapped area.

Ideas?


thanks,
Lennert



[*] From cachetlb.txt:

	6) void flush_cache_vmap(unsigned long start, unsigned long end)
	   void flush_cache_vunmap(unsigned long start, unsigned long end)

		Here in these two interfaces we are flushing a specific range
		of (kernel) virtual addresses from the cache.  After running,
		there will be no entries in the cache for the kernel address
		space for virtual addresses in the range 'start' to 'end-1'.

		The first of these two routines is invoked after map_vm_area()
		has installed the page table entries.  The second is invoked
		before unmap_kernel_range() deletes the page table entries.

    For one, all architectures either define both flush_cache_vmap()
    and flush_cache_vunmap() to NOPs, or define both of them to
    flush_cache_all(), which I don't understand.

    Surely, in flush_cache_vunmap(), just flushing the given range
    should be sufficient for machines with virtual caches?  (Hmmm,
    e.g. ARM always does a flush_cache_all() even though ARMs with
    physical caches exist.)

    And I'm not sure why flush_cache_vmap() needs to do anything at
    all.  If we're worried about there still being (possibly dirty)
    data in the cache from a previous mapping at this virtual address,
    shouldn't we be flushing the virtual address range _first_,
    before setting up new mappings in this address range (for those
    virtual cache setups that don't store physical tags and can end
    up doing TLB lookups when evicting data?)
--
To unsubscribe from this list: send the line "unsubscribe linux-arch" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel]     [Kernel Newbies]     [x86 Platform Driver]     [Netdev]     [Linux Wireless]     [Netfilter]     [Bugtraq]     [Linux Filesystems]     [Yosemite Discussion]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Device Mapper]

  Powered by Linux