From: Joe Perches <joe@perches.com>
To: Andrew Morton <akpm@linux-foundation.org>
Cc: LKML <linux-kernel@vger.kernel.org>
Subject: Re: [RFC patch] vsprintf: Add %pav extension for print_vma_addr
Date: Sun, 31 May 2015 10:51:17 -0700 [thread overview]
Message-ID: <1433094677.2984.27.camel@perches.com> (raw)
In-Reply-To: <20150527141908.4cf02ef4456201ad7db78883@linux-foundation.org>
On Wed, 2015-05-27 at 14:19 -0700, Andrew Morton wrote:
> On Wed, 27 May 2015 14:09:31 -0700 Joe Perches <joe@perches.com> wrote:
>
> > > Problems when CONFIG_PREEMPT=n.
> > >
> > > > + down_read(&mm->mmap_sem);
> > > > + vma = find_vma(mm, ip);
> > > > + if (vma && vma->vm_file) {
> > > > + struct file *f = vma->vm_file;
> > > > + char *gfp_buf = (char *)__get_free_page(GFP_KERNEL);
> > >
> > > We shouldn't assume we can use GFP_KERNEL here. Even if the
> > > preempt_count() worked, we might be in a context which requires
> > > GFP_NOFS or GFP_NOIO.
> >
> > This code is basically a copy of the existing print_vma_addr()
> > so is that true for all the existing uses too?
>
> Yeah, the current code is pretty junky. But normally print_vma_addr()
> should never be called so nobody noticed...
>
> In e8bff74a Ingo did a fiddle to preempt_conditional_sti() which looks
> like it will address the CONFIG_PREEMPT=n issue, but only on x86.
Maybe this? (using GFP_ATOMIC and __GFP_NOWARN)
Documentation/printk-formats.txt | 5 +++
lib/vsprintf.c | 66 ++++++++++++++++++++++++++++++++++++----
2 files changed, 65 insertions(+), 6 deletions(-)
diff --git a/Documentation/printk-formats.txt b/Documentation/printk-formats.txt
index 2ec6d84..962f82c 100644
--- a/Documentation/printk-formats.txt
+++ b/Documentation/printk-formats.txt
@@ -86,6 +86,11 @@ DMA addresses types dma_addr_t:
For printing a dma_addr_t type which can vary based on build options,
regardless of the width of the CPU data path. Passed by reference.
+VMA addresses: where the content of an unsigned long * is used in find_vma()
+ %pav "%s[%lx+%lx]",
+ kbasename(d_path(vma->vm_file)),
+ vma->vm_start, vma->vm_end - vma->vm_start)
+
Raw buffer as an escaped string:
%*pE[achnops]
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 8243e2f..bb4fa63 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -1313,23 +1313,74 @@ char *netdev_feature_string(char *buf, char *end, const u8 *addr,
}
static noinline_for_stack
+char *vma_addr(char *buf, char *end, const void *addr,
+ struct printf_spec spec, const char *fmt)
+{
+ struct mm_struct *mm = current->mm;
+ const char *errmsg;
+ struct vm_area_struct *vma;
+ char *page;
+ char *path;
+
+ /* if we are in atomic contexts (in exception stacks, etc.) */
+ if (preempt_count()) {
+ errmsg = "(atomic context)";
+ goto err_string;
+ }
+
+ down_read(&mm->mmap_sem);
+ vma = find_vma(mm, *(unsigned long *)addr);
+
+ if (!vma || !vma->vm_file) {
+ errmsg = "(find_vma failed)";
+ goto err_up_read;
+ }
+
+ page = (char *)__get_free_page(GFP_ATOMIC | __GFP_NOWARN);
+ if (!page) {
+ errmsg = "(__get_free_page failed)";
+ goto err_up_read;
+ }
+
+ path = d_path(&vma->vm_file->f_path, page, PAGE_SIZE);
+ if (IS_ERR(path))
+ path = "?";
+
+ buf += snprintf(buf, end > buf ? end - buf : 0, "%s[%lx+%lx]",
+ kbasename(path),
+ vma->vm_start, vma->vm_end - vma->vm_start);
+
+ free_page((unsigned long)page);
+ up_read(&mm->mmap_sem);
+ return buf;
+
+err_up_read:
+ up_read(&mm->mmap_sem);
+err_string:
+ return string(buf, end, errmsg, spec);
+}
+
+static noinline_for_stack
char *address_val(char *buf, char *end, const void *addr,
struct printf_spec spec, const char *fmt)
{
unsigned long long num;
- spec.flags |= SPECIAL | SMALL | ZEROPAD;
- spec.base = 16;
-
switch (fmt[1]) {
+ case 'v':
+ return vma_addr(buf, end, addr, spec, fmt);
case 'd':
- num = *(const dma_addr_t *)addr;
+ spec.flags |= SPECIAL | SMALL | ZEROPAD;
+ spec.base = 16;
spec.field_width = sizeof(dma_addr_t) * 2 + 2;
+ num = *(const dma_addr_t *)addr;
break;
case 'p':
default:
- num = *(const phys_addr_t *)addr;
+ spec.flags |= SPECIAL | SMALL | ZEROPAD;
+ spec.base = 16;
spec.field_width = sizeof(phys_addr_t) * 2 + 2;
+ num = *(const phys_addr_t *)addr;
break;
}
@@ -1453,7 +1504,10 @@ int kptr_restrict __read_mostly;
* N no separator
* The maximum supported length is 64 bytes of the input. Consider
* to use print_hex_dump() for the larger input.
- * - 'a[pd]' For address types [p] phys_addr_t, [d] dma_addr_t and derivatives
+ * - 'a[pdv]' For address types:
+ * [p] phys_addr_t and derivatives (resource_size_t)
+ * [d] dma_addr_t
+ * [v] vma_addr
* (default assumed to be phys_addr_t, passed by reference)
* - 'd[234]' For a dentry name (optionally 2-4 last components)
* - 'D[234]' Same as 'd' but for a struct file
next prev parent reply other threads:[~2015-05-31 17:51 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-05-26 23:05 [RFC patch] vsprintf: Add %pav extension for print_vma_addr Joe Perches
2015-05-27 21:04 ` Andrew Morton
2015-05-27 21:09 ` Joe Perches
2015-05-27 21:19 ` Andrew Morton
2015-05-31 17:51 ` Joe Perches [this message]
2015-06-01 23:36 ` Andrew Morton
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=1433094677.2984.27.camel@perches.com \
--to=joe@perches.com \
--cc=akpm@linux-foundation.org \
--cc=linux-kernel@vger.kernel.org \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.