From: Andrew Morton <akpm@linux-foundation.org>
To: Dan Williams <dan.j.williams@intel.com>
Cc: Wei Liu <wei.liu2@citrix.com>,
Eric Dumazet <eric.dumazet@gmail.com>,
Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>,
netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
Sander Eikelenboom <linux@eikelenboom.it>,
Francois Romieu <romieu@fr.zoreil.com>,
Dave Jones <davej@redhat.com>
Subject: Re: [PATCH regression] dma debug: account for cachelines and read-only mappings in overlap tracking
Date: Thu, 13 Feb 2014 14:05:23 -0800 [thread overview]
Message-ID: <20140213140523.099fd03418d8fe1467db3bd9@linux-foundation.org> (raw)
In-Reply-To: <20140213215652.22950.12180.stgit@viggo.jf.intel.com>
On Thu, 13 Feb 2014 13:58:00 -0800 Dan Williams <dan.j.williams@intel.com> wrote:
> While debug_dma_assert_idle() checks if a given *page* is actively
> undergoing dma the valid granularity of a dma mapping is a *cacheline*.
> Sander's testing shows that the warning message "DMA-API: exceeded 7
> overlapping mappings of pfn..." is falsely triggering. The test is
> simply mapping multiple cachelines in a given page.
>
> Ultimately we want overlap tracking to be valid as it is a real api
> violation, so we need to track active mappings by cachelines. Update
> the active dma tracking to use the page-frame-relative cacheline of the
> mapping as the key, and update debug_dma_assert_idle() to check for all
> possible mapped cachelines for a given page.
>
> However, the need to track active mappings is only relevant when the
> dma-mapping is writable by the device. In fact it is fairly standard
> for read-only mappings to have hundreds or thousands of overlapping
> mappings at once. Limiting the overlap tracking to writable
> (!DMA_TO_DEVICE) eliminates this class of false-positive overlap
> reports.
>
> Note, the radix gang lookup is sub-optimal. It would be best if it
> stopped fetching entries once the search passed a page boundary.
> Nevertheless, this implementation does not perturb the original net_dma
> failing case. That is to say the extra overhead does not show up in
> terms of making the failing case pass due to a timing change.
>
> References:
> http://marc.info/?l=linux-netdev&m=139232263419315&w=2
> http://marc.info/?l=linux-netdev&m=139217088107122&w=2
>
> ...
>
> --- a/lib/dma-debug.c
> +++ b/lib/dma-debug.c
> @@ -424,111 +424,132 @@ void debug_dma_dump_mappings(struct device *dev)
> EXPORT_SYMBOL(debug_dma_dump_mappings);
>
> /*
> - * For each page mapped (initial page in the case of
> - * dma_alloc_coherent/dma_map_{single|page}, or each page in a
> - * scatterlist) insert into this tree using the pfn as the key. At
> + * For each mapping (initial cacheline in the case of
> + * dma_alloc_coherent/dma_map_page, initial cacheline in each page of a
> + * scatterlist, or the cacheline specified in dma_map_single) insert
> + * into this tree using the cacheline as the key. At
> * dma_unmap_{single|sg|page} or dma_free_coherent delete the entry. If
> - * the pfn already exists at insertion time add a tag as a reference
> + * the entry already exists at insertion time add a tag as a reference
> * count for the overlapping mappings. For now, the overlap tracking
> - * just ensures that 'unmaps' balance 'maps' before marking the pfn
> - * idle, but we should also be flagging overlaps as an API violation.
> + * just ensures that 'unmaps' balance 'maps' before marking the
> + * cacheline idle, but we should also be flagging overlaps as an API
> + * violation.
> *
> * Memory usage is mostly constrained by the maximum number of available
> * dma-debug entries in that we need a free dma_debug_entry before
> - * inserting into the tree. In the case of dma_map_{single|page} and
> - * dma_alloc_coherent there is only one dma_debug_entry and one pfn to
> - * track per event. dma_map_sg(), on the other hand,
> - * consumes a single dma_debug_entry, but inserts 'nents' entries into
> - * the tree.
> + * inserting into the tree. In the case of dma_map_page and
> + * dma_alloc_coherent there is only one dma_debug_entry and one
> + * dma_active_cacheline entry to track per event. dma_map_sg(), on the
> + * other hand, consumes a single dma_debug_entry, but inserts 'nents'
> + * entries into the tree.
> *
> * At any time debug_dma_assert_idle() can be called to trigger a
> - * warning if the given page is in the active set.
> + * warning if any cachelines in the given page are in the active set.
> */
> -static RADIX_TREE(dma_active_pfn, GFP_NOWAIT);
> +static RADIX_TREE(dma_active_cacheline, GFP_NOWAIT);
> static DEFINE_SPINLOCK(radix_lock);
> -#define ACTIVE_PFN_MAX_OVERLAP ((1 << RADIX_TREE_MAX_TAGS) - 1)
> +#define ACTIVE_CLN_MAX_OVERLAP ((1 << RADIX_TREE_MAX_TAGS) - 1)
> +#define CACHELINE_PER_PAGE_SHIFT (PAGE_SHIFT - L1_CACHE_SHIFT)
> +#define CACHELINES_PER_PAGE (1 << CACHELINE_PER_PAGE_SHIFT)
>
> -static int active_pfn_read_overlap(unsigned long pfn)
> +unsigned long to_cln(struct dma_debug_entry *entry)
> +{
> + return (entry->pfn << CACHELINE_PER_PAGE_SHIFT) +
> + (entry->offset >> L1_CACHE_SHIFT);
> +}
"cln" is ugly and isn't a well-known kernel abbreviation. We typically
spell these things out, so "cacheline". But I think you mean
"cacheline number", and that is too long to spell out.
So I guess "cln" just became a well-known kernel abbreviation.
> ....
>
> void debug_dma_assert_idle(struct page *page)
> {
> + unsigned long cln = page_to_pfn(page) << CACHELINE_PER_PAGE_SHIFT;
This worries me. Are you sure we cannot overflow the ulong here under
any circumstances? 32GB PAE with sparsemem or whatever?
next prev parent reply other threads:[~2014-02-13 22:05 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-02-13 21:58 Dan Williams
2014-02-13 22:05 ` Andrew Morton [this message]
2014-02-13 22:33 ` Dan Williams
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20140213140523.099fd03418d8fe1467db3bd9@linux-foundation.org \
--to=akpm@linux-foundation.org \
--cc=dan.j.williams@intel.com \
--cc=davej@redhat.com \
--cc=eric.dumazet@gmail.com \
--cc=konrad.wilk@oracle.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux@eikelenboom.it \
--cc=netdev@vger.kernel.org \
--cc=romieu@fr.zoreil.com \
--cc=wei.liu2@citrix.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®