From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933077AbZHDVbJ (ORCPT ); Tue, 4 Aug 2009 17:31:09 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S932601AbZHDVbI (ORCPT ); Tue, 4 Aug 2009 17:31:08 -0400 Received: from smtp1.linux-foundation.org ([140.211.169.13]:50484 "EHLO smtp1.linux-foundation.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932502AbZHDVbH (ORCPT ); Tue, 4 Aug 2009 17:31:07 -0400 Date: Tue, 4 Aug 2009 14:30:31 -0700 From: Andrew Morton To: KAMEZAWA Hiroyuki Cc: kamezawa.hiroyu@jp.fujitsu.com, scgtrp@gmail.com, bugzilla-daemon@bugzilla.kernel.org, bugme-daemon@bugzilla.kernel.org, xiyou.wangcong@gmail.com, linux-kernel@vger.kernel.org Subject: Re: [BUGFIX][PATCH 2/3] kcore: fix vread/vwrite to be aware of holes. Message-Id: <20090804143031.b9769a13.akpm@linux-foundation.org> In-Reply-To: <20090803201845.c3ae49b5.kamezawa.hiroyu@jp.fujitsu.com> References: <20090728160527.1da52682.akpm@linux-foundation.org> <20090729084825.1363c880.kamezawa.hiroyu@jp.fujitsu.com> <525c5a6c0907281946t249ef288v77ee94edd16f054@mail.gmail.com> <20090803201418.040bb3ee.kamezawa.hiroyu@jp.fujitsu.com> <20090803201845.c3ae49b5.kamezawa.hiroyu@jp.fujitsu.com> X-Mailer: Sylpheed version 2.2.4 (GTK+ 2.8.20; i486-pc-linux-gnu) Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Mon, 3 Aug 2009 20:18:45 +0900 KAMEZAWA Hiroyuki wrote: > From: KAMEZAWA Hiroyuki > > vread/vwrite access vmalloc area without checking there is a page or not. > In most case, this works well. > > In old ages, the caller of get_vm_ara() is only IOREMAP and there is no > memory hole within vm_struct's [addr...addr + size - PAGE_SIZE] > ( -PAGE_SIZE is for a guard page.) > > After per-cpu-alloc patch, it uses get_vm_area() for reserve continuous > virtual address but remap _later_. There tend to be a hole in valid vmalloc > area in vm_struct lists. > Then, skip the hole (not mapped page) is necessary. > This patch updates vread/vwrite() for avoiding memory hole. > > Routines which access vmalloc area without knowing for which addr is used > are > - /proc/kcore > - /dev/kmem > > kcore checks IOREMAP, /dev/kmem doesn't. After this patch, IOREMAP is > checked and /dev/kmem will avoid to read/write it. > Fixes to /proc/kcore will be in the next patch in series. > > Changelog v2->v3: > - fixed typos. > - use kmap. (if not using kmap, we have to add lock here.) > - fixed PAGE_MASK miss-use. > Changelog v1->v2: > - enhanced comments. > - treat IOREMAP as hole always. > - zero-fill memory hole if [addr...addr+size] includes valid pages. > - returns 0 if [addr...addr+size) includes no valid pages. > > ... > > +static int aligned_vread(char *buf, char *addr, unsigned long count) > +{ > + struct page *p; > + int copied = 0; > + > + while (count) { > + unsigned long offset, length; > + > + offset = (unsigned long)addr & ~PAGE_MASK; > + length = PAGE_SIZE - offset; > + if (length > count) > + length = count; > + p = vmalloc_to_page(addr); > + /* > + * To do safe access to this _mapped_ area, we need > + * lock. But adding lock here means that we need to add > + * overhead of vmalloc()/vfree() calles for this _debug_ > + * interface, rarely used. Instead of that, we'll use > + * kmap() and get small overhead in this access function. > + */ > + if (p) { > + /* we can expect USR1 is not used */ It would be nice if the comment were to explain _why_ KM_USER1 is known to be free here. > + void *map = kmap_atomic(p, KM_USER1); > + memcpy(buf, map + offset, length); > + kunmap_atomic(map, KM_USER1); Can use clear_highpage(). > + } else > + memset(buf, 0, length); > + > + addr += length; > + buf += length; > + copied += length; > + count -= length; > + } > + return copied; > +} > + > +static int aligned_vwrite(char *buf, char *addr, unsigned long count) > +{ > + struct page *p; > + int copied = 0; > + > + while (count) { > + unsigned long offset, length; > + > + offset = (unsigned long)addr & ~PAGE_MASK; > + length = PAGE_SIZE - offset; > + if (length > count) > + length = count; > + p = vmalloc_to_page(addr); > + /* > + * To do safe access to this _mapped_ area, we need > + * lock. But adding lock here means that we need to add > + * overhead of vmalloc()/vfree() calles for this _debug_ > + * interface, rarely used. Instead of that, we'll use > + * kmap() and get small overhead in this access function. > + */ > + if (p) { > + /* we can expect USR1 is not used */ > + void *map = kmap_atomic(p, KM_USER1); > + memcpy(map + offset, buf, length); > + kunmap_atomic(map, KM_USER1); clear_highpage(). > + } > + addr += length; > + buf += length; > + copied += length; > + count -= length; > + } > + return copied; > +}