From: Greg KH <gregkh@suse.de>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: torvalds@linux-foundation.org, akpm@linux-foundation.org,
alan@lxorguk.ukuu.org.uk, Tejun Heo <tj@kernel.org>,
Thomas Renninger <trenn@suse.de>
Subject: [27/53] percpu: fix chunk range calculation
Date: Fri, 16 Dec 2011 11:45:24 -0800 [thread overview]
Message-ID: <20111216194558.410207481@clark.kroah.org> (raw)
In-Reply-To: <20111216194613.GA18395@kroah.com>
3.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tejun Heo <tj@kernel.org>
commit a855b84c3d8c73220d4d3cd392a7bee7c83de70e upstream.
Percpu allocator recorded the cpus which map to the first and last
units in pcpu_first/last_unit_cpu respectively and used them to
determine the address range of a chunk - e.g. it assumed that the
first unit has the lowest address in a chunk while the last unit has
the highest address.
This simply isn't true. Groups in a chunk can have arbitrary positive
or negative offsets from the previous one and there is no guarantee
that the first unit occupies the lowest offset while the last one the
highest.
Fix it by actually comparing unit offsets to determine cpus occupying
the lowest and highest offsets. Also, rename pcu_first/last_unit_cpu
to pcpu_low/high_unit_cpu to avoid confusion.
The chunk address range is used to flush cache on vmalloc area
map/unmap and decide whether a given address is in the first chunk by
per_cpu_ptr_to_phys() and the bug was discovered by invalid
per_cpu_ptr_to_phys() translation for crash_note.
Kudos to Dave Young for tracking down the problem.
Signed-off-by: Tejun Heo <tj@kernel.org>
Reported-by: WANG Cong <xiyou.wangcong@gmail.com>
Reported-by: Dave Young <dyoung@redhat.com>
Tested-by: Dave Young <dyoung@redhat.com>
LKML-Reference: <4EC21F67.10905@redhat.com>
Signed-off-by: Thomas Renninger <trenn@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
mm/percpu-vm.c | 12 ++++++------
mm/percpu.c | 34 ++++++++++++++++++++--------------
2 files changed, 26 insertions(+), 20 deletions(-)
--- a/mm/percpu-vm.c
+++ b/mm/percpu-vm.c
@@ -143,8 +143,8 @@ static void pcpu_pre_unmap_flush(struct
int page_start, int page_end)
{
flush_cache_vunmap(
- pcpu_chunk_addr(chunk, pcpu_first_unit_cpu, page_start),
- pcpu_chunk_addr(chunk, pcpu_last_unit_cpu, page_end));
+ pcpu_chunk_addr(chunk, pcpu_low_unit_cpu, page_start),
+ pcpu_chunk_addr(chunk, pcpu_high_unit_cpu, page_end));
}
static void __pcpu_unmap_pages(unsigned long addr, int nr_pages)
@@ -206,8 +206,8 @@ static void pcpu_post_unmap_tlb_flush(st
int page_start, int page_end)
{
flush_tlb_kernel_range(
- pcpu_chunk_addr(chunk, pcpu_first_unit_cpu, page_start),
- pcpu_chunk_addr(chunk, pcpu_last_unit_cpu, page_end));
+ pcpu_chunk_addr(chunk, pcpu_low_unit_cpu, page_start),
+ pcpu_chunk_addr(chunk, pcpu_high_unit_cpu, page_end));
}
static int __pcpu_map_pages(unsigned long addr, struct page **pages,
@@ -284,8 +284,8 @@ static void pcpu_post_map_flush(struct p
int page_start, int page_end)
{
flush_cache_vmap(
- pcpu_chunk_addr(chunk, pcpu_first_unit_cpu, page_start),
- pcpu_chunk_addr(chunk, pcpu_last_unit_cpu, page_end));
+ pcpu_chunk_addr(chunk, pcpu_low_unit_cpu, page_start),
+ pcpu_chunk_addr(chunk, pcpu_high_unit_cpu, page_end));
}
/**
--- a/mm/percpu.c
+++ b/mm/percpu.c
@@ -116,9 +116,9 @@ static int pcpu_atom_size __read_mostly;
static int pcpu_nr_slots __read_mostly;
static size_t pcpu_chunk_struct_size __read_mostly;
-/* cpus with the lowest and highest unit numbers */
-static unsigned int pcpu_first_unit_cpu __read_mostly;
-static unsigned int pcpu_last_unit_cpu __read_mostly;
+/* cpus with the lowest and highest unit addresses */
+static unsigned int pcpu_low_unit_cpu __read_mostly;
+static unsigned int pcpu_high_unit_cpu __read_mostly;
/* the address of the first chunk which starts with the kernel static area */
void *pcpu_base_addr __read_mostly;
@@ -984,19 +984,19 @@ phys_addr_t per_cpu_ptr_to_phys(void *ad
{
void __percpu *base = __addr_to_pcpu_ptr(pcpu_base_addr);
bool in_first_chunk = false;
- unsigned long first_start, first_end;
+ unsigned long first_low, first_high;
unsigned int cpu;
/*
- * The following test on first_start/end isn't strictly
+ * The following test on unit_low/high isn't strictly
* necessary but will speed up lookups of addresses which
* aren't in the first chunk.
*/
- first_start = pcpu_chunk_addr(pcpu_first_chunk, pcpu_first_unit_cpu, 0);
- first_end = pcpu_chunk_addr(pcpu_first_chunk, pcpu_last_unit_cpu,
- pcpu_unit_pages);
- if ((unsigned long)addr >= first_start &&
- (unsigned long)addr < first_end) {
+ first_low = pcpu_chunk_addr(pcpu_first_chunk, pcpu_low_unit_cpu, 0);
+ first_high = pcpu_chunk_addr(pcpu_first_chunk, pcpu_high_unit_cpu,
+ pcpu_unit_pages);
+ if ((unsigned long)addr >= first_low &&
+ (unsigned long)addr < first_high) {
for_each_possible_cpu(cpu) {
void *start = per_cpu_ptr(base, cpu);
@@ -1233,7 +1233,9 @@ int __init pcpu_setup_first_chunk(const
for (cpu = 0; cpu < nr_cpu_ids; cpu++)
unit_map[cpu] = UINT_MAX;
- pcpu_first_unit_cpu = NR_CPUS;
+
+ pcpu_low_unit_cpu = NR_CPUS;
+ pcpu_high_unit_cpu = NR_CPUS;
for (group = 0, unit = 0; group < ai->nr_groups; group++, unit += i) {
const struct pcpu_group_info *gi = &ai->groups[group];
@@ -1253,9 +1255,13 @@ int __init pcpu_setup_first_chunk(const
unit_map[cpu] = unit + i;
unit_off[cpu] = gi->base_offset + i * ai->unit_size;
- if (pcpu_first_unit_cpu == NR_CPUS)
- pcpu_first_unit_cpu = cpu;
- pcpu_last_unit_cpu = cpu;
+ /* determine low/high unit_cpu */
+ if (pcpu_low_unit_cpu == NR_CPUS ||
+ unit_off[cpu] < unit_off[pcpu_low_unit_cpu])
+ pcpu_low_unit_cpu = cpu;
+ if (pcpu_high_unit_cpu == NR_CPUS ||
+ unit_off[cpu] > unit_off[pcpu_high_unit_cpu])
+ pcpu_high_unit_cpu = cpu;
}
}
pcpu_nr_units = unit;
next prev parent reply other threads:[~2011-12-16 20:07 UTC|newest]
Thread overview: 54+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-12-16 19:46 [00/53] 3.1.6-stable review Greg KH
2011-12-16 19:44 ` [01/53] ALSA: sis7019 - give slow codecs more time to reset Greg KH
2011-12-16 19:44 ` [02/53] ALSA: hda/realtek - Fix Oops in alc_mux_select() Greg KH
2011-12-16 19:45 ` [03/53] ALSA: hda - Fix GPIO LED setup for IDT 92HD75 codecs Greg KH
2011-12-16 19:45 ` [04/53] alarmtimers: Fix time comparison Greg KH
2011-12-16 19:45 ` [05/53] ARM: davinci: da850 evm: change audio edma event queue to EVENTQ_0 Greg KH
2011-12-16 19:45 ` [06/53] arm: mx23: recognise stmp378x as mx23 Greg KH
2011-12-16 19:45 ` [07/53] ARM: at91: fix clock conid for atmel_tcb.1 on 9260/9g20 Greg KH
2011-12-16 19:45 ` [08/53] ARM: at91: Fix USB AT91 gadget registration Greg KH
2011-12-16 19:45 ` [09/53] ARM: davinci: dm646x evm: wrong register used in setup_vpif_input_channel_mode Greg KH
2011-12-16 19:45 ` [10/53] ASoC: Provide a more complete DMA driver stub Greg KH
2011-12-16 19:45 ` [11/53] drivers/rtc/rtc-s3c.c: fix driver clock enable/disable balance issues Greg KH
2011-12-16 19:45 ` [12/53] fs/proc/meminfo.c: fix compilation error Greg KH
2011-12-16 19:45 ` [13/53] thp: add compound tail page _mapcount when mapped Greg KH
2011-12-16 19:45 ` [14/53] thp: set compound tail page _count to zero Greg KH
2011-12-16 19:45 ` [15/53] lockdep, kmemcheck: Annotate ->lock in lockdep_init_map() Greg KH
2011-12-16 19:45 ` [16/53] ptp: Fix clock_getres() implementation Greg KH
2011-12-16 19:45 ` [17/53] mm: Ensure that pfn_valid() is called once per pageblock when reserving pageblocks Greg KH
2011-12-16 19:45 ` [18/53] mm: vmalloc: check for page allocation failure before vmlist insertion Greg KH
2011-12-16 19:45 ` [19/53] fix apparmor dereferencing potentially freed dentry, sanitize __d_path() API Greg KH
2011-12-16 19:45 ` [20/53] TOMOYO: Fix pathname handling of disconnected paths Greg KH
2011-12-16 19:45 ` [21/53] target: Reject SCSI data overflow for fabrics using transport_generic_map_mem_to_cmd Greg KH
2011-12-16 19:45 ` [22/53] iscsi-target: Fix residual count hanlding + remove iscsi_cmd->residual_count Greg KH
2011-12-16 19:45 ` [23/53] target: Handle 0 correctly in transport_get_sectors_6() Greg KH
2011-12-16 19:45 ` [24/53] target: Fix page length in emulated INQUIRY VPD page 86h Greg KH
2011-12-16 19:45 ` [25/53] iscsi-target: Add missing F_BIT for iscsi_tm_rsp Greg KH
2011-12-16 19:45 ` [26/53] target/file: walk properly over sg list Greg KH
2011-12-16 19:45 ` Greg KH [this message]
2011-12-16 19:45 ` [28/53] cifs: check for NULL last_entry before calling cifs_save_resume_key Greg KH
2011-12-16 19:45 ` [29/53] linux/log2.h: Fix rounddown_pow_of_two(1) Greg KH
2011-12-16 19:45 ` [30/53] hwmon: (jz4740) fix signedness bug Greg KH
2011-12-16 19:45 ` [31/53] ARM: 7204/1: arch/arm/kernel/setup.c: initialize arm_dma_zone_size earlier Greg KH
2011-12-16 19:45 ` [32/53] mmc: mxcmmc: fix falling back to PIO Greg KH
2011-12-16 19:45 ` [33/53] xen/pm_idle: Make pm_idle be default_idle under Xen Greg KH
2011-12-16 19:45 ` [34/53] x86, hpet: Immediately disable HPET timer 1 if rtc irq is masked Greg KH
2011-12-16 19:45 ` [35/53] jbd/jbd2: validate sb->s_first in journal_get_superblock() Greg KH
2011-12-16 19:45 ` [36/53] hfs: fix hfs_find_init() sb->ext_tree NULL ptr oops Greg KH
2011-12-16 19:45 ` [37/53] drm/radeon/kms: cleanup atombios_adjust_pll() Greg KH
2011-12-16 19:45 ` [38/53] drm/radeon/kms: rework DP bridge checks Greg KH
2011-12-16 19:45 ` [39/53] drm/radeon/kms: fix DP setup on TRAVIS bridges Greg KH
2011-12-16 19:45 ` [40/53] xen: only limit memory map to maximum reservation for domain 0 Greg KH
2011-12-16 19:45 ` [41/53] ext4: fix ext4_end_io_dio() racing against fsync() Greg KH
2011-12-16 19:45 ` [42/53] ext4: display the correct mount option in /proc/mounts for [no]init_itable Greg KH
2011-12-16 19:45 ` [43/53] ext4: avoid hangs in ext4_da_should_update_i_disksize() Greg KH
2011-12-16 19:45 ` [44/53] ext4: avoid potential hang in mpage_submit_io() when blocksize < pagesize Greg KH
2011-12-16 19:45 ` [45/53] ext4: handle EOF correctly in ext4_bio_write_page() Greg KH
2011-12-16 19:45 ` [46/53] fuse: fix fuse_retrieve Greg KH
2011-12-16 19:45 ` [47/53] fuse: fix llseek bug Greg KH
2011-12-16 19:45 ` [48/53] staging: r8712u: Add new USB ID Greg KH
2011-12-16 19:45 ` [49/53] drm/radeon/kms: add some new pci ids Greg KH
2011-12-16 19:45 ` [50/53] ibft: Fix finding IBFT ACPI table on UEFI Greg KH
2011-12-16 19:45 ` [51/53] USB: cdc-acm: add IDs for Motorola H24 HSPA USB module Greg KH
2011-12-16 19:45 ` [52/53] usb: option: Add Huawei E398 controlling interfaces Greg KH
2011-12-16 19:45 ` [53/53] USB: option: Removing one bogus and adding some new Huawei combinations Greg KH
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=20111216194558.410207481@clark.kroah.org \
--to=gregkh@suse.de \
--cc=akpm@linux-foundation.org \
--cc=alan@lxorguk.ukuu.org.uk \
--cc=linux-kernel@vger.kernel.org \
--cc=stable@vger.kernel.org \
--cc=tj@kernel.org \
--cc=torvalds@linux-foundation.org \
--cc=trenn@suse.de \
/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®