Skip to contentSkip to conversation

2.6.27.4-stable review

PATCH In review Greg KH 5 participants 37 messages Oct 24, 2008 – Oct 25, 2008

Subsystems (23)
lore
Share & tools
lore

Greg KH

author
#0 lore raw

cover 2.6.27.4-stable review

This is the start of the stable review cycle for the 2.6.27.4 release. There are 27 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let us know. If anyone is a maintainer of the proper subsystem, and wants to add a Signed-off-by: line to the patch, please respond with it.

These patches are sent out with a number of different people on the Cc:
line. If you wish to be a reviewer, please email [email protected] to add your name to the list. If you want to be off the reviewer list, also email us.

Responses should be made by Sunday, October 26 04:00:00 UTC. Anything received after that time might be too late.

The whole patch series can be found in one patch at:

	kernel.org/pub/linux/kernel/v2.6/stable-review/patch-2.6.27.4-rc1.gz

and the diffstat can be found below.

thanks,

the -stable release team

 arch/x86/kernel/acpi/sleep.c                   |    3 
 arch/x86/kernel/amd_iommu_init.c               |    2 
 drivers/acpi/hardware/hwsleep.c                |   37 ++------
 drivers/acpi/sleep/main.c                      |   10 ++
 drivers/char/hvc_console.c                     |   10 +-
 drivers/edac/cell_edac.c                       |    2 
 drivers/gpio/gpiolib.c                         |    2 
 drivers/md/dm-exception-store.c                |  106 +++++++++++++++++--------
 drivers/md/dm-kcopyd.c                         |   13 ++-
 drivers/md/dm-snap.c                           |   10 --
 drivers/net/wireless/ath5k/base.c              |   28 ++++--
 drivers/net/wireless/ath5k/base.h              |    3 
 drivers/pci/hotplug/cpqphp_core.c              |    2 
 drivers/scsi/device_handler/scsi_dh_rdac.c     |    2 
 drivers/usb/atm/speedtch.c                     |   12 ++
 drivers/usb/class/cdc-acm.c                    |    3 
 drivers/usb/class/cdc-wdm.c                    |    2 
 drivers/usb/core/driver.c                      |    3 
 drivers/usb/core/hub.c                         |    2 
 fs/cifs/readdir.c                              |    3 
 fs/ext2/dir.c                                  |   60 ++++++++------
 fs/ext3/dir.c                                  |   10 +-
 fs/ext4/dir.c                                  |   11 +-
 fs/proc/task_mmu.c                             |   34 +++++---
 kernel/sched_stats.h                           |    2 
 mm/rmap.c                                      |   42 +++++++--
 net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c |    2 
 net/ipv4/netfilter/nf_nat_snmp_basic.c         |    1 
 net/netfilter/xt_iprange.c                     |    8 -
 29 files changed, 278 insertions(+), 147 deletions(-)
author
#18 lore raw

PATCH 15/27 ext: Avoid printk floods in the face of directory corruption (CVE-2008-3528)

2.6.27-stable review patch. If anyone has any objections, please let us know.

------------------
From: Eric Sandeen <[email protected]>

This is a trivial backport of the following upstream commits:

- bd39597cbd42a784105a04010100e27267481c67 (ext2)
- cdbf6dba28e8e6268c8420857696309470009fd9 (ext3)
- 9d9f177572d9e4eba0f2e18523b44f90dd51fe74 (ext4)

This addresses CVE-2008-3528

ext[234]: Avoid printk floods in the face of directory corruption

Note: some people thinks this represents a security bug, since it might make the system go away while it is printing a large number of console messages, especially if a serial console is involved. Hence, it has been assigned CVE-2008-3528, but it requires that the attacker either has physical access to your machine to insert a USB disk with a corrupted filesystem image (at which point why not just hit the power button), or is otherwise able to convince the system administrator to mount an arbitrary filesystem image (at which point why not just include a setuid shell or world-writable hard disk device file or some such). Me, I think they're just being silly. --tytso

---
 fs/ext2/dir.c |   60 +++++++++++++++++++++++++++++++++-------------------------
 fs/ext3/dir.c |   10 ++++++---
 fs/ext4/dir.c |   11 +++++++---
 3 files changed, 50 insertions(+), 31 deletions(-)
fs/ext2/dir.c +35 -25
@@ -103,7 +103,7 @@ static int ext2_commit_chunk(struct page
 	return err;
 }
 
-static void ext2_check_page(struct page *page)
+static void ext2_check_page(struct page *page, int quiet)
 {
 	struct inode *dir = page->mapping->host;
 	struct super_block *sb = dir->i_sb;
@@ -146,10 +146,10 @@ out:
 	/* Too bad, we had an error */
 
 Ebadsize:
-	ext2_error(sb, "ext2_check_page",
-		"size of directory #%lu is not a multiple of chunk size",
-		dir->i_ino
-	);
+	if (!quiet)
+		ext2_error(sb, __func__,
+			"size of directory #%lu is not a multiple "
+			"of chunk size", dir->i_ino);
 	goto fail;
 Eshort:
 	error = "rec_len is smaller than minimal";
@@ -166,32 +166,36 @@ Espan:
 Einumber:
 	error = "inode out of bounds";
 bad_entry:
-	ext2_error (sb, "ext2_check_page", "bad entry in directory #%lu: %s - "
-		"offset=%lu, inode=%lu, rec_len=%d, name_len=%d",
-		dir->i_ino, error, (page->index<<PAGE_CACHE_SHIFT)+offs,
-		(unsigned long) le32_to_cpu(p->inode),
-		rec_len, p->name_len);
+	if (!quiet)
+		ext2_error(sb, __func__, "bad entry in directory #%lu: : %s - "
+			"offset=%lu, inode=%lu, rec_len=%d, name_len=%d",
+			dir->i_ino, error, (page->index<<PAGE_CACHE_SHIFT)+offs,
+			(unsigned long) le32_to_cpu(p->inode),
+			rec_len, p->name_len);
 	goto fail;
 Eend:
-	p = (ext2_dirent *)(kaddr + offs);
-	ext2_error (sb, "ext2_check_page",
-		"entry in directory #%lu spans the page boundary"
-		"offset=%lu, inode=%lu",
-		dir->i_ino, (page->index<<PAGE_CACHE_SHIFT)+offs,
-		(unsigned long) le32_to_cpu(p->inode));
+	if (!quiet) {
+		p = (ext2_dirent *)(kaddr + offs);
+		ext2_error(sb, "ext2_check_page",
+			"entry in directory #%lu spans the page boundary"
+			"offset=%lu, inode=%lu",
+			dir->i_ino, (page->index<<PAGE_CACHE_SHIFT)+offs,
+			(unsigned long) le32_to_cpu(p->inode));
+	}
 fail:
 	SetPageChecked(page);
 	SetPageError(page);
 }
 
-static struct page * ext2_get_page(struct inode *dir, unsigned long n)
+static struct page * ext2_get_page(struct inode *dir, unsigned long n,
+				   int quiet)
 {
 	struct address_space *mapping = dir->i_mapping;
 	struct page *page = read_mapping_page(mapping, n, NULL);
 	if (!IS_ERR(page)) {
 		kmap(page);
 		if (!PageChecked(page))
-			ext2_check_page(page);
+			ext2_check_page(page, quiet);
 		if (PageError(page))
 			goto fail;
 	}
@@ -292,7 +296,7 @@ ext2_readdir (struct file * filp, void *
 	for ( ; n < npages; n++, offset = 0) {
 		char *kaddr, *limit;
 		ext2_dirent *de;
-		struct page *page = ext2_get_page(inode, n);
+		struct page *page = ext2_get_page(inode, n, 0);
 
 		if (IS_ERR(page)) {
 			ext2_error(sb, __func__,
@@ -361,6 +365,7 @@ struct ext2_dir_entry_2 * ext2_find_entr
 	struct page *page = NULL;
 	struct ext2_inode_info *ei = EXT2_I(dir);
 	ext2_dirent * de;
+	int dir_has_error = 0;
 
 	if (npages == 0)
 		goto out;
@@ -374,7 +379,7 @@ struct ext2_dir_entry_2 * ext2_find_entr
 	n = start;
 	do {
 		char *kaddr;
-		page = ext2_get_page(dir, n);
+		page = ext2_get_page(dir, n, dir_has_error);
 		if (!IS_ERR(page)) {
 			kaddr = page_address(page);
 			de = (ext2_dirent *) kaddr;
@@ -391,7 +396,9 @@ struct ext2_dir_entry_2 * ext2_find_entr
 				de = ext2_next_entry(de);
 			}
 			ext2_put_page(page);
-		}
+		} else
+			dir_has_error = 1;
+
 		if (++n >= npages)
 			n = 0;
 		/* next page is past the blocks we've got */
@@ -414,7 +421,7 @@ found:
 
 struct ext2_dir_entry_2 * ext2_dotdot (struct inode *dir, struct page **p)
 {
-	struct page *page = ext2_get_page(dir, 0);
+	struct page *page = ext2_get_page(dir, 0, 0);
 	ext2_dirent *de = NULL;
 
 	if (!IS_ERR(page)) {
@@ -487,7 +494,7 @@ int ext2_add_link (struct dentry *dentry
 	for (n = 0; n <= npages; n++) {
 		char *dir_end;
 
-		page = ext2_get_page(dir, n);
+		page = ext2_get_page(dir, n, 0);
 		err = PTR_ERR(page);
 		if (IS_ERR(page))
 			goto out;
@@ -655,14 +662,17 @@ int ext2_empty_dir (struct inode * inode
 {
 	struct page *page = NULL;
 	unsigned long i, npages = dir_pages(inode);
+	int dir_has_error = 0;
 
 	for (i = 0; i < npages; i++) {
 		char *kaddr;
 		ext2_dirent * de;
-		page = ext2_get_page(inode, i);
+		page = ext2_get_page(inode, i, dir_has_error);
 
-		if (IS_ERR(page))
+		if (IS_ERR(page)) {
+			dir_has_error = 1;
 			continue;
+		}
 
 		kaddr = page_address(page);
 		de = (ext2_dirent *)kaddr;
fs/ext3/dir.c +7 -3
@@ -102,6 +102,7 @@ static int ext3_readdir(struct file * fi
 	int err;
 	struct inode *inode = filp->f_path.dentry->d_inode;
 	int ret = 0;
+	int dir_has_error = 0;
 
 	sb = inode->i_sb;
 
@@ -148,9 +149,12 @@ static int ext3_readdir(struct file * fi
 		 * of recovering data when there's a bad sector
 		 */
 		if (!bh) {
-			ext3_error (sb, "ext3_readdir",
-				"directory #%lu contains a hole at offset %lu",
-				inode->i_ino, (unsigned long)filp->f_pos);
+			if (!dir_has_error) {
+				ext3_error(sb, __func__, "directory #%lu "
+					"contains a hole at offset %lld",
+					inode->i_ino, filp->f_pos);
+				dir_has_error = 1;
+			}
 			/* corrupt size?  Maybe no more blocks to read */
 			if (filp->f_pos > inode->i_blocks << 9)
 				break;
fs/ext4/dir.c +8 -3
@@ -102,6 +102,7 @@ static int ext4_readdir(struct file * fi
 	int err;
 	struct inode *inode = filp->f_path.dentry->d_inode;
 	int ret = 0;
+	int dir_has_error = 0;
 
 	sb = inode->i_sb;
 
@@ -148,9 +149,13 @@ static int ext4_readdir(struct file * fi
 		 * of recovering data when there's a bad sector
 		 */
 		if (!bh) {
-			ext4_error (sb, "ext4_readdir",
-				"directory #%lu contains a hole at offset %lu",
-				inode->i_ino, (unsigned long)filp->f_pos);
+			if (!dir_has_error) {
+				ext4_error(sb, __func__, "directory #%lu "
+					   "contains a hole at offset %Lu",
+					   inode->i_ino,
+					   (unsigned long long) filp->f_pos);
+				dir_has_error = 1;
+			}
 			/* corrupt size?  Maybe no more blocks to read */
 			if (filp->f_pos > inode->i_blocks << 9)
 				break;
author
#19 lore raw

PATCH 16/27 netfilter: xt_iprange: fix range inversion match

In reply to Greg KH

2.6.27-stable review patch. If anyone has any objections, please let us know.

------------------
From: Alexey Dobriyan <[email protected]>

netfilter: xt_iprange: fix range inversion match

Upstream commit 6def1eb48:

Inverted IPv4 v1 and IPv6 v0 matches don't match anything since 2.6.25-rc1!

---
 net/netfilter/xt_iprange.c |    8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
net/netfilter/xt_iprange.c +4 -4
@@ -67,7 +67,7 @@ iprange_mt4(const struct sk_buff *skb, c
 	if (info->flags & IPRANGE_SRC) {
 		m  = ntohl(iph->saddr) < ntohl(info->src_min.ip);
 		m |= ntohl(iph->saddr) > ntohl(info->src_max.ip);
-		m ^= info->flags & IPRANGE_SRC_INV;
+		m ^= !!(info->flags & IPRANGE_SRC_INV);
 		if (m) {
 			pr_debug("src IP " NIPQUAD_FMT " NOT in range %s"
 			         NIPQUAD_FMT "-" NIPQUAD_FMT "\n",
@@ -81,7 +81,7 @@ iprange_mt4(const struct sk_buff *skb, c
 	if (info->flags & IPRANGE_DST) {
 		m  = ntohl(iph->daddr) < ntohl(info->dst_min.ip);
 		m |= ntohl(iph->daddr) > ntohl(info->dst_max.ip);
-		m ^= info->flags & IPRANGE_DST_INV;
+		m ^= !!(info->flags & IPRANGE_DST_INV);
 		if (m) {
 			pr_debug("dst IP " NIPQUAD_FMT " NOT in range %s"
 			         NIPQUAD_FMT "-" NIPQUAD_FMT "\n",
@@ -123,14 +123,14 @@ iprange_mt6(const struct sk_buff *skb, c
 	if (info->flags & IPRANGE_SRC) {
 		m  = iprange_ipv6_sub(&iph->saddr, &info->src_min.in6) < 0;
 		m |= iprange_ipv6_sub(&iph->saddr, &info->src_max.in6) > 0;
-		m ^= info->flags & IPRANGE_SRC_INV;
+		m ^= !!(info->flags & IPRANGE_SRC_INV);
 		if (m)
 			return false;
 	}
 	if (info->flags & IPRANGE_DST) {
 		m  = iprange_ipv6_sub(&iph->daddr, &info->dst_min.in6) < 0;
 		m |= iprange_ipv6_sub(&iph->daddr, &info->dst_max.in6) > 0;
-		m ^= info->flags & IPRANGE_DST_INV;
+		m ^= !!(info->flags & IPRANGE_DST_INV);
 		if (m)
 			return false;
 	}
author
#20 lore raw

PATCH 17/27 netfilter: snmp nat leaks memory in case of failure

In reply to Greg KH

2.6.27-stable review patch. If anyone has any objections, please let us know.

------------------
From: Ilpo J�rvinen <[email protected]>

netfilter: snmp nat leaks memory in case of failure

Upstream commit 311670f3e:

---
 net/ipv4/netfilter/nf_nat_snmp_basic.c |    1 +
 1 file changed, 1 insertion(+)
net/ipv4/netfilter/nf_nat_snmp_basic.c +1 -0
@@ -742,6 +742,7 @@ static unsigned char snmp_object_decode(
 			*obj = kmalloc(sizeof(struct snmp_object) + len,
 				       GFP_ATOMIC);
 			if (*obj == NULL) {
+				kfree(p);
 				kfree(id);
 				if (net_ratelimit())
 					printk("OOM in bsalg (%d)\n", __LINE__);
Signature · 4 lines
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
author
#21 lore raw

PATCH 18/27 netfilter: restore lost ifdef guarding defrag exception

In reply to Greg KH

2.6.27-stable review patch. If anyone has any objections, please let us know.

------------------
From: Patrick McHardy <[email protected]>

netfilter: restore lost #ifdef guarding defrag exception

Upstream commit 38f7ac3eb:

Nir Tzachar <[email protected]> reported a warning when sending fragments over loopback with NAT:

[ 6658.338121] WARNING: at net/ipv4/netfilter/nf_nat_standalone.c:89 nf_nat_fn+0x33/0x155()

The reason is that defragmentation is skipped for already tracked connections. This is wrong in combination with NAT and ip_conntrack actually had some ifdefs to avoid this behaviour when NAT is compiled in.

The entire "optimization" may seem a bit silly, for now simply restoring the lost #ifdef is the easiest solution until we can come up with something better.

---
 net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c |    2 ++
 1 file changed, 2 insertions(+)
net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +2 -0
@@ -150,10 +150,12 @@ static unsigned int ipv4_conntrack_defra
 					  const struct net_device *out,
 					  int (*okfn)(struct sk_buff *))
 {
+#if !defined(CONFIG_NF_NAT) && !defined(CONFIG_NF_NAT_MODULE)
 	/* Previously seen (loopback)?  Ignore.  Do this before
 	   fragment check. */
 	if (skb->nfct)
 		return NF_ACCEPT;
+#endif
 
 	/* Gather fragments. */
 	if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
author
#1 lore raw

PATCH 1/27 gpiolib: fix oops in gpio_get_value_cansleep()

In reply to Greg KH

2.6.27-stable review patch. If anyone has any objections, please let us know.

------------------

From: David Brownell <[email protected]>

commit 978ccaa8ea5d8c7bf6b676209f2fc126eae6355b upstream

We can get the following oops from gpio_get_value_cansleep() when a GPIO controller doesn't provide a get() callback:

 Unable to handle kernel paging request for instruction fetch
 Faulting instruction address: 0x00000000
 Oops: Kernel access of bad area, sig: 11 [#1]
 [...]
 NIP [00000000] 0x0
 LR [c0182fb0] gpio_get_value_cansleep+0x40/0x50
 Call Trace:
 [c7b79e80] [c0183f28] gpio_value_show+0x5c/0x94
 [c7b79ea0] [c01a584c] dev_attr_show+0x30/0x7c
 [c7b79eb0] [c00d6b48] fill_read_buffer+0x68/0xe0
 [c7b79ed0] [c00d6c54] sysfs_read_file+0x94/0xbc
 [c7b79ef0] [c008f24c] vfs_read+0xb4/0x16c
 [c7b79f10] [c008f580] sys_read+0x4c/0x90
 [c7b79f40] [c0013a14] ret_from_syscall+0x0/0x38

It's OK to request the value of *any* GPIO; most GPIOs are bidirectional, so configuring them as outputs just enables an output driver and doesn't disable the input logic.

So the problem is that gpio_get_value_cansleep() isn't making the same sanity check that gpio_get_value() does: making sure this GPIO isn't one of the atypical "no input logic" cases.

---
 drivers/gpio/gpiolib.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpio/gpiolib.c +1 -1
@@ -1020,7 +1020,7 @@ int gpio_get_value_cansleep(unsigned gpi
 
 	might_sleep_if(extra_checks);
 	chip = gpio_to_chip(gpio);
-	return chip->get(chip, gpio - chip->base);
+	return chip->get ? chip->get(chip, gpio - chip->base) : 0;
 }
 EXPORT_SYMBOL_GPL(gpio_get_value_cansleep);
 
author
#2 lore raw

PATCH 2/27 edac cell: fix incorrect edac_mode

In reply to Greg KH

2.6.27-stable review patch. If anyone has any objections, please let us know.

------------------
From: Benjamin Herrenschmidt <[email protected]>

commit 3b274f44d2ca05f719fe39947b6a5293a2dbd8fd upstream

The cell_edac driver is setting the edac_mode field of the csrow's to an incorrect value, causing the sysfs show routine for that field to go out of an array bound and Oopsing the kernel when used.

---
 drivers/edac/cell_edac.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/edac/cell_edac.c +1 -1
@@ -142,7 +142,7 @@ static void __devinit cell_edac_init_csr
 		csrow->nr_pages = (r.end - r.start + 1) >> PAGE_SHIFT;
 		csrow->last_page = csrow->first_page + csrow->nr_pages - 1;
 		csrow->mtype = MEM_XDR;
-		csrow->edac_mode = EDAC_FLAG_EC | EDAC_FLAG_SECDED;
+		csrow->edac_mode = EDAC_SECDED;
 		dev_dbg(mci->dev,
 			"Initialized on node %d, chanmask=0x%x,"
 			" first_page=0x%lx, nr_pages=0x%x\n",
author
#3 lore raw

PATCH 3/27 x86 ACPI: fix breakage of resume on 64-bit UP systems with SMP kernel

In reply to Greg KH

2.6.27-stable review patch. If anyone has any objections, please let us know.

------------------
From: Rafael J. Wysocki <[email protected]>

commit 3038edabf48f01421c621cb77a712b446d3a5d67 upstream

x86 ACPI: Fix breakage of resume on 64-bit UP systems with SMP kernel

We are now using per CPU GDT tables in head_64.S and the original early_gdt_descr.address is invalidated after boot by setup_per_cpu_areas(). This breaks resume from suspend to RAM on x86_64 UP systems using SMP kernels, because this part of head_64.S is also executed during the resume and the invalid GDT address causes the system to crash. It doesn't break on 'true' SMP systems, because early_gdt_descr.address is modified every time native_cpu_up() runs. However, during resume it should point to the GDT of the boot CPU rather than to another CPU's GDT.

For this reason, during suspend to RAM always make early_gdt_descr.address point to the boot CPU's GDT.

This fixes http://bugzilla.kernel.org/show_bug.cgi?id=11568, which is a regression from 2.6.26.

---
 arch/x86/kernel/acpi/sleep.c |    3 +++
 1 file changed, 3 insertions(+)
arch/x86/kernel/acpi/sleep.c +3 -0
@@ -10,6 +10,7 @@
 #include <linux/dmi.h>
 #include <linux/cpumask.h>
 #include <asm/segment.h>
+#include <asm/desc.h>
 
 #include "realmode/wakeup.h"
 #include "sleep.h"
@@ -98,6 +99,8 @@ int acpi_save_state_mem(void)
 	header->trampoline_segment = setup_trampoline() >> 4;
 #ifdef CONFIG_SMP
 	stack_start.sp = temp_stack + 4096;
+	early_gdt_descr.address =
+			(unsigned long)get_cpu_gdt_table(smp_processor_id());
 #endif
 	initial_code = (unsigned long)wakeup_long64;
 	saved_magic = 0x123456789abcdef0;
author
#4 lore raw

PATCH 4/27 sched: fix the wrong mask_len

In reply to Greg KH

2.6.27-stable review patch. If anyone has any objections, please let us know.

------------------
From: Miao Xie <[email protected]>

commit c851c8676bd7ae456e9b3af8e6bb2c434eddcc75 upstream

If NR_CPUS isn't a multiple of 32, we get a truncated string of sched domains by catting /proc/schedstat. This is caused by the wrong mask_len.

This patch fixes it.

---
 kernel/sched_stats.h |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/sched_stats.h +1 -1
@@ -9,7 +9,7 @@
 static int show_schedstat(struct seq_file *seq, void *v)
 {
 	int cpu;
-	int mask_len = NR_CPUS/32 * 9;
+	int mask_len = (NR_CPUS/32 + 1) * 9;
 	char *mask_str = kmalloc(mask_len, GFP_KERNEL);
 
 	if (mask_str == NULL)
author
#5 lore raw

PATCH 5/27 USB: cdc-wdm: make module autoload work

In reply to Greg KH

2.6.27-stable review patch. If anyone has any objections, please let us know.

------------------
From: Oliver Neukum <[email protected]>

commit aa5380b904e7f896db0931320160bdea93e41f6a upstream

this fixes an omission that led to no alias being computed for the cdc-wdm module.

---
 drivers/usb/class/cdc-wdm.c |    2 ++
 1 file changed, 2 insertions(+)
drivers/usb/class/cdc-wdm.c +2 -0
@@ -42,6 +42,8 @@ static struct usb_device_id wdm_ids[] = 
 	{ }
 };
 
+MODULE_DEVICE_TABLE (usb, wdm_ids);
+
 #define WDM_MINOR_BASE	176
 
 
author
#6 lore raw

PATCH 6/27 USB: dont rebind drivers after failed resume or reset

In reply to Greg KH

2.6.27-stable review patch. If anyone has any objections, please let us know.

------------------
From: Alan Stern <[email protected]>

commit 6c6409459a18a825ce12ecb003d5686af61f7a2f upstream

This patch (as1152) may help prevent some problems associated with the new policy of unbinding drivers that don't support suspend/resume or pre_reset/post_reset. If for any reason the resume or reset fails, and the device is logically disconnected, there's no point in trying to rebind the driver. So the patch checks for success before carrying out the unbind/rebind.

There was a report from one user that this fixed a problem he was experiencing, but the details never became fully clear. In any case, adding these tests can't hurt.

---
 drivers/usb/core/driver.c |    3 ++-
 drivers/usb/core/hub.c    |    2 +-
 2 files changed, 3 insertions(+), 2 deletions(-)
drivers/usb/core/driver.c +2 -1
@@ -1609,7 +1609,8 @@ int usb_external_resume_device(struct us
 	status = usb_resume_both(udev);
 	udev->last_busy = jiffies;
 	usb_pm_unlock(udev);
-	do_unbind_rebind(udev, DO_REBIND);
+	if (status == 0)
+		do_unbind_rebind(udev, DO_REBIND);
 
 	/* Now that the device is awake, we can start trying to autosuspend
 	 * it again. */
drivers/usb/core/hub.c +1 -1
@@ -3424,7 +3424,7 @@ int usb_reset_device(struct usb_device *
 						USB_INTERFACE_BOUND)
 					rebind = 1;
 			}
-			if (rebind)
+			if (ret == 0 && rebind)
 				usb_rebind_intf(cintf);
 		}
 	}
author
#7 lore raw

PATCH 7/27 USB: fix memory leak in cdc-acm

In reply to Greg KH

2.6.27-stable review patch. If anyone has any objections, please let us know.

------------------
From: Oliver Neukum <[email protected]>

commit a496c64f1363ec4d67ebdc1e1f619ad6372a574c upstream

This fixes a memory leak on disconnect in cdc-acm

Thanks to 施金前 for finding it.

---
 drivers/usb/class/cdc-acm.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/usb/class/cdc-acm.c +2 -1
@@ -849,9 +849,10 @@ static void acm_write_buffers_free(struc
 {
 	int i;
 	struct acm_wb *wb;
+	struct usb_device *usb_dev = interface_to_usbdev(acm->control);
 
 	for (wb = &acm->wb[0], i = 0; i < ACM_NW; i++, wb++) {
-		usb_buffer_free(acm->dev, acm->writesize, wb->buf, wb->dmah);
+		usb_buffer_free(usb_dev, acm->writesize, wb->buf, wb->dmah);
 	}
 }
 
author
#8 lore raw

PATCH 8/27 USB: Speedtouch: add pre_reset and post_reset routines

In reply to Greg KH

2.6.27-stable review patch. If anyone has any objections, please let us know.

------------------
From: Alan Stern <[email protected]>

commit 8fc7aeab3851ed8c3ecf28901ca2c6f0400955c7 upstream

This patch (as1150) fixes a problem in the speedtch driver. When it resets the modem during probe it will be unbound from the other interfaces it has claimed, because it doesn't define a pre_reset and a post_reset method.

The patch defines "do-nothing" methods. This fixes Bugzilla #11767.

---
 drivers/usb/atm/speedtch.c |   12 ++++++++++++
 1 file changed, 12 insertions(+)
drivers/usb/atm/speedtch.c +12 -0
@@ -722,6 +722,16 @@ static void speedtch_atm_stop(struct usb
 	flush_scheduled_work();
 }
 
+static int speedtch_pre_reset(struct usb_interface *intf)
+{
+	return 0;
+}
+
+static int speedtch_post_reset(struct usb_interface *intf)
+{
+	return 0;
+}
+
 
 /**********
 **  USB  **
@@ -740,6 +750,8 @@ static struct usb_driver speedtch_usb_dr
 	.name		= speedtch_driver_name,
 	.probe		= speedtch_usb_probe,
 	.disconnect	= usbatm_usb_disconnect,
+	.pre_reset	= speedtch_pre_reset,
+	.post_reset	= speedtch_post_reset,
 	.id_table	= speedtch_usb_ids
 };
 
author
#9 lore raw

PATCH 9/27 dm kcopyd: avoid queue shuffle

In reply to Greg KH

2.6.27-stable review patch. If anyone has any objections, please let us know.

------------------
From: Kazuo Ito <[email protected]>

commit b673c3a8192e28f13e2050a4b82c1986be92cc15 upstream

Write throughput to LVM snapshot origin volume is an order of magnitude slower than those to LV without snapshots or snapshot target volumes, especially in the case of sequential writes with O_SYNC on.

The following patch originally written by Kevin Jamieson and Jan Blunck and slightly modified for the current RCs by myself tries to improve the performance by modifying the behaviour of kcopyd, so that it pushes back an I/O job to the head of the job queue instead of the tail as process_jobs() currently does when it has to wait for free pages. This way, write requests aren't shuffled to cause extra seeks.

I tested the patch against 2.6.27-rc5 and got the following results. The test is a dd command writing to snapshot origin followed by fsync to the file just created/updated. A couple of filesystem benchmarks gave me similar results in case of sequential writes, while random writes didn't suffer much.

dd if=/dev/zero of=<somewhere on snapshot origin> bs=4096 count=...
[conv=notrunc when updating]

1) linux 2.6.27-rc5 without the patch, write to snapshot origin, average throughput (MB/s)

                     10M     100M    1000M

create,dd 511.46 610.72 11.81
create,dd+fsync 7.10 6.77 8.13
update,dd 431.63 917.41 12.75
update,dd+fsync 7.79 7.43 8.12

compared with write throughput to LV without any snapshots, all dd+fsync and 1000 MiB writes perform very poorly.

                     10M     100M    1000M
create,dd         555.03   608.98   123.29
create,dd+fsync   114.27    72.78    76.65
update,dd         152.34  1267.27   124.04
update,dd+fsync   130.56    77.81    77.84

2) linux 2.6.27-rc5 with the patch, write to snapshot origin, average throughput (MB/s)

                     10M     100M    1000M
create,dd         537.06   589.44    46.21
create,dd+fsync    31.63    29.19    29.23
update,dd         487.59   897.65    37.76
update,dd+fsync    34.12    30.07    26.85

Although still not on par with plain LV performance - cannot be avoided because it's copy on write anyway - this simple patch successfully improves throughtput of dd+fsync while not affecting the rest.

---
 drivers/md/dm-kcopyd.c |   13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)
drivers/md/dm-kcopyd.c +12 -1
@@ -268,6 +268,17 @@ static void push(struct list_head *jobs,
 	spin_unlock_irqrestore(&kc->job_lock, flags);
 }
 
+
+static void push_head(struct list_head *jobs, struct kcopyd_job *job)
+{
+	unsigned long flags;
+	struct dm_kcopyd_client *kc = job->kc;
+
+	spin_lock_irqsave(&kc->job_lock, flags);
+	list_add(&job->list, jobs);
+	spin_unlock_irqrestore(&kc->job_lock, flags);
+}
+
 /*
  * These three functions process 1 item from the corresponding
  * job list.
@@ -398,7 +409,7 @@ static int process_jobs(struct list_head
 			 * We couldn't service this job ATM, so
 			 * push this job back onto the list.
 			 */
-			push(jobs, job);
+			push_head(jobs, job);
 			break;
 		}
 
author
#10 lore raw

PATCH 10/27 dm snapshot: fix primary_pe race

In reply to Greg KH

2.6.27-stable review patch. If anyone has any objections, please let us know.

------------------
From: Mikulas Patocka <[email protected]>

commit 7c5f78b9d7f21937e46c26db82976df4b459c95c upstream

Fix a race condition with primary_pe ref_count handling.

put_pending_exception runs under dm_snapshot->lock, it does atomic_dec_and_test on primary_pe->ref_count, and later does atomic_read primary_pe->ref_count.

__origin_write does atomic_dec_and_test on primary_pe->ref_count without holding dm_snapshot->lock.

This opens the following race condition:
Assume two CPUs, CPU1 is executing put_pending_exception (and holding dm_snapshot->lock). CPU2 is executing __origin_write in parallel. primary_pe->ref_count == 2.

CPU1:
if (primary_pe && atomic_dec_and_test(&primary_pe->ref_count))

	origin_bios = bio_list_get(&primary_pe->origin_bios);

.. decrements primary_pe->ref_count to 1. Doesn't load origin_bios

CPU2:

if (first && atomic_dec_and_test(&primary_pe->ref_count)) {
	flush_bios(bio_list_get(&primary_pe->origin_bios));
	free_pending_exception(primary_pe);
	/* If we got here, pe_queue is necessarily empty. */
	return r;
}

.. decrements primary_pe->ref_count to 0, submits pending bios, frees primary_pe.

CPU1:
if (!primary_pe || primary_pe != pe)

	free_pending_exception(pe);
.. this has no effect.
if (primary_pe && !atomic_read(&primary_pe->ref_count))
	free_pending_exception(primary_pe);

.. sees ref_count == 0 (written by CPU 2), does double free !!

This bug can happen only if someone is simultaneously writing to both the origin and the snapshot.

If someone is writing only to the origin, __origin_write will submit kcopyd request after it decrements primary_pe->ref_count (so it can't happen that the finished copy races with primary_pe->ref_count decrementation).

If someone is writing only to the snapshot, __origin_write isn't invoked at all and the race can't happen.

The race happens when someone writes to the snapshot --- this creates pending_exception with primary_pe == NULL and starts copying. Then, someone writes to the same chunk in the snapshot, and __origin_write races with termination of already submitted request in pending_complete (that calls put_pending_exception).

This race may be reason for bugs:
http://bugzilla.kernel.org/show_bug.cgi?id=11636
https://bugzilla.redhat.com/show_bug.cgi?id=465825

The patch fixes the code to make sure that:
1. If atomic_dec_and_test(&primary_pe->ref_count) returns false, the process must no longer dereference primary_pe (because someone else may free it under us).
2. If atomic_dec_and_test(&primary_pe->ref_count) returns true, the process is responsible for freeing primary_pe.

---
 drivers/md/dm-snap.c |   10 +++-------
 1 file changed, 3 insertions(+), 7 deletions(-)
drivers/md/dm-snap.c +3 -7
@@ -824,8 +824,10 @@ static struct bio *put_pending_exception
 	 * the bios for the original write to the origin.
 	 */
 	if (primary_pe &&
-	    atomic_dec_and_test(&primary_pe->ref_count))
+	    atomic_dec_and_test(&primary_pe->ref_count)) {
 		origin_bios = bio_list_get(&primary_pe->origin_bios);
+		free_pending_exception(primary_pe);
+	}
 
 	/*
 	 * Free the pe if it's not linked to an origin write or if
@@ -834,12 +836,6 @@ static struct bio *put_pending_exception
 	if (!primary_pe || primary_pe != pe)
 		free_pending_exception(pe);
 
-	/*
-	 * Free the primary pe if nothing references it.
-	 */
-	if (primary_pe && !atomic_read(&primary_pe->ref_count))
-		free_pending_exception(primary_pe);
-
 	return origin_bios;
 }
 
author
#11 lore raw

PATCH 11/27 dm exception store: refactor zero_area

In reply to Greg KH

2.6.27-stable review patch. If anyone has any objections, please let us know.

------------------
From: Alasdair G Kergon <[email protected]>

commit 7c9e6c17325fab380fbe9c9787680ff7d4a51abd upstream

Use a separate buffer for writing zeroes to the on-disk snapshot exception store, make the updating of ps->current_area explicit and refactor the code in preparation for the fix in the next patch.

No functional change.

---
 drivers/md/dm-exception-store.c |  103 ++++++++++++++++++++++++++--------------
 1 file changed, 69 insertions(+), 34 deletions(-)
drivers/md/dm-exception-store.c +69 -34
@@ -105,6 +105,11 @@ struct pstore {
 	void *area;
 
 	/*
+	 * An area of zeros used to clear the next area.
+	 */
+	void *zero_area;
+
+	/*
 	 * Used to keep track of which metadata area the data in
 	 * 'chunk' refers to.
 	 */
@@ -149,6 +154,13 @@ static int alloc_area(struct pstore *ps)
 	if (!ps->area)
 		return r;
 
+	ps->zero_area = vmalloc(len);
+	if (!ps->zero_area) {
+		vfree(ps->area);
+		return r;
+	}
+	memset(ps->zero_area, 0, len);
+
 	return 0;
 }
 
@@ -156,6 +168,8 @@ static void free_area(struct pstore *ps)
 {
 	vfree(ps->area);
 	ps->area = NULL;
+	vfree(ps->zero_area);
+	ps->zero_area = NULL;
 }
 
 struct mdata_req {
@@ -212,13 +226,13 @@ static int chunk_io(struct pstore *ps, u
  * Read or write a metadata area.  Remembering to skip the first
  * chunk which holds the header.
  */
-static int area_io(struct pstore *ps, uint32_t area, int rw)
+static int area_io(struct pstore *ps, int rw)
 {
 	int r;
 	uint32_t chunk;
 
 	/* convert a metadata area index to a chunk index */
-	chunk = 1 + ((ps->exceptions_per_area + 1) * area);
+	chunk = area_location(ps, ps->current_area);
 
 	r = chunk_io(ps, chunk, rw, 0);
 	if (r)
@@ -228,10 +242,27 @@ static int area_io(struct pstore *ps, ui
 	return 0;
 }
 
-static int zero_area(struct pstore *ps, uint32_t area)
+static void zero_memory_area(struct pstore *ps)
 {
 	memset(ps->area, 0, ps->snap->chunk_size << SECTOR_SHIFT);
-	return area_io(ps, area, WRITE);
+}
+
+static int zero_disk_area(struct pstore *ps, chunk_t area)
+{
+	struct dm_io_region where = {
+		.bdev = ps->snap->cow->bdev,
+		.sector = ps->snap->chunk_size * area_location(ps, area),
+		.count = ps->snap->chunk_size,
+	};
+	struct dm_io_request io_req = {
+		.bi_rw = WRITE,
+		.mem.type = DM_IO_VMA,
+		.mem.ptr.vma = ps->zero_area,
+		.client = ps->io_client,
+		.notify.fn = NULL,
+	};
+
+	return dm_io(&io_req, 1, &where, NULL);
 }
 
 static int read_header(struct pstore *ps, int *new_snapshot)
@@ -404,15 +435,14 @@ static int insert_exceptions(struct psto
 
 static int read_exceptions(struct pstore *ps)
 {
-	uint32_t area;
 	int r, full = 1;
 
 	/*
 	 * Keeping reading chunks and inserting exceptions until
 	 * we find a partially full area.
 	 */
-	for (area = 0; full; area++) {
-		r = area_io(ps, area, READ);
+	for (ps->current_area = 0; full; ps->current_area++) {
+		r = area_io(ps, READ);
 		if (r)
 			return r;
 
@@ -421,6 +451,8 @@ static int read_exceptions(struct pstore
 			return r;
 	}
 
+	ps->current_area--;
+
 	return 0;
 }
 
@@ -479,12 +511,13 @@ static int persistent_read_metadata(stru
 			return r;
 		}
 
-		r = zero_area(ps, 0);
+		ps->current_area = 0;
+		zero_memory_area(ps);
+		r = zero_disk_area(ps, 0);
 		if (r) {
-			DMWARN("zero_area(0) failed");
+			DMWARN("zero_disk_area(0) failed");
 			return r;
 		}
-
 	} else {
 		/*
 		 * Sanity checks.
@@ -542,7 +575,6 @@ static void persistent_commit(struct exc
 			      void (*callback) (void *, int success),
 			      void *callback_context)
 {
-	int r;
 	unsigned int i;
 	struct pstore *ps = get_info(store);
 	struct disk_exception de;
@@ -563,33 +595,36 @@ static void persistent_commit(struct exc
 	cb->context = callback_context;
 
 	/*
-	 * If there are no more exceptions in flight, or we have
-	 * filled this metadata area we commit the exceptions to
-	 * disk.
-	 */
-	if (atomic_dec_and_test(&ps->pending_count) ||
-	    (ps->current_committed == ps->exceptions_per_area)) {
-		r = area_io(ps, ps->current_area, WRITE);
-		if (r)
-			ps->valid = 0;
+	 * If there are exceptions in flight and we have not yet
+	 * filled this metadata area there's nothing more to do.
+	 */
+	if (!atomic_dec_and_test(&ps->pending_count) &&
+	    (ps->current_committed != ps->exceptions_per_area))
+		return;
 
-		/*
-		 * Have we completely filled the current area ?
-		 */
-		if (ps->current_committed == ps->exceptions_per_area) {
-			ps->current_committed = 0;
-			r = zero_area(ps, ps->current_area + 1);
-			if (r)
-				ps->valid = 0;
-		}
+	/*
+	 * Commit exceptions to disk.
+	 */
+	if (area_io(ps, WRITE))
+		ps->valid = 0;
 
-		for (i = 0; i < ps->callback_count; i++) {
-			cb = ps->callbacks + i;
-			cb->callback(cb->context, r == 0 ? 1 : 0);
-		}
+	/*
+	 * Advance to the next area if this one is full.
+	 */
+	if (ps->current_committed == ps->exceptions_per_area) {
+		if (zero_disk_area(ps, ps->current_area + 1))
+			ps->valid = 0;
+		ps->current_committed = 0;
+		ps->current_area++;
+		zero_memory_area(ps);
+	}
 
-		ps->callback_count = 0;
+	for (i = 0; i < ps->callback_count; i++) {
+		cb = ps->callbacks + i;
+		cb->callback(cb->context, ps->valid);
 	}
+
+	ps->callback_count = 0;
 }
 
 static void persistent_drop(struct exception_store *store)
author
#15 lore raw

PATCH 12/27 dm exception store: fix misordered writes

In reply to Greg KH

2.6.27-stable review patch. If anyone has any objections, please let us know.

------------------
From: Mikulas Patocka <[email protected]>

commit 7acedc5b98a2fcff64f00c21110aae7d3ac2f7df upstream

We must zero the next chunk on disk *before* writing out the current chunk, not after. Otherwise if the machine crashes at the wrong time, the "end of metadata" marker may be missing.

---
 drivers/md/dm-exception-store.c |   11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)
drivers/md/dm-exception-store.c +8 -3
@@ -603,17 +603,22 @@ static void persistent_commit(struct exc
 		return;
 
 	/*
+	 * If we completely filled the current area, then wipe the next one.
+	 */
+	if ((ps->current_committed == ps->exceptions_per_area) &&
+	     zero_disk_area(ps, ps->current_area + 1))
+		ps->valid = 0;
+
+	/*
 	 * Commit exceptions to disk.
 	 */
-	if (area_io(ps, WRITE))
+	if (ps->valid && area_io(ps, WRITE))
 		ps->valid = 0;
 
 	/*
 	 * Advance to the next area if this one is full.
 	 */
 	if (ps->current_committed == ps->exceptions_per_area) {
-		if (zero_disk_area(ps, ps->current_area + 1))
-			ps->valid = 0;
 		ps->current_committed = 0;
 		ps->current_area++;
 		zero_memory_area(ps);
author
#16 lore raw

PATCH 13/27 amd_iommu: fix nasty bug that caused ILLEGAL_DEVICE_TABLE_ENTRY errors

In reply to Greg KH

2.6.27-stable review patch. If anyone has any objections, please let us know.

------------------
From: Andreas Herrmann <[email protected]>

commit f609891f428e1c20e270e7c350daf8c93cc459d7 upstream

We are on 64-bit so better use u64 instead of u32 to deal with addresses:

static void __init iommu_set_device_table(struct amd_iommu *iommu)

{
        u64 entry;
  ...
        entry = virt_to_phys(amd_iommu_dev_table);

...

(I am wondering why gcc 4.2.x did not warn about the assignment between u32 and unsigned long.)

---
 arch/x86/kernel/amd_iommu_init.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/kernel/amd_iommu_init.c +1 -1
@@ -210,7 +210,7 @@ static void __init iommu_set_exclusion_r
 /* Programs the physical address of the device table into the IOMMU hardware */
 static void __init iommu_set_device_table(struct amd_iommu *iommu)
 {
-	u32 entry;
+	u64 entry;
 
 	BUG_ON(iommu->mmio_base == NULL);
 
author
#17 lore raw

PATCH 14/27 CIFS: fix saving of resume key before CIFSFindNext

In reply to Greg KH

2.6.27-stable review patch. If anyone has any objections, please let us know.

------------------
From: Jeff Layton <[email protected]>

commit a364bc0b37f14ffd66c1f982af42990a9d77fa43 upstream

We recently fixed the cifs readdir code so that it saves the resume key before calling CIFSFindNext. Unfortunately, this assumes that we have just done a CIFSFindFirst (or FindNext) and have resume info to save. This isn't necessarily the case. Fix the code to save resume info if we had to reinitiate the search, and after a FindNext.

This fixes connectathon basic test6 against NetApp filers.

---
 fs/cifs/readdir.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
fs/cifs/readdir.c +2 -1
@@ -762,14 +762,15 @@ static int find_cifs_entry(const int xid
 				 rc));
 			return rc;
 		}
+		cifs_save_resume_key(cifsFile->srch_inf.last_entry, cifsFile);
 	}
 
 	while ((index_to_find >= cifsFile->srch_inf.index_of_last_entry) &&
 	      (rc == 0) && !cifsFile->srch_inf.endOfSearch) {
 		cFYI(1, ("calling findnext2"));
-		cifs_save_resume_key(cifsFile->srch_inf.last_entry, cifsFile);
 		rc = CIFSFindNext(xid, pTcon, cifsFile->netfid,
 				  &cifsFile->srch_inf);
+		cifs_save_resume_key(cifsFile->srch_inf.last_entry, cifsFile);
 		if (rc)
 			return -ENOENT;
 	}
author
#22 lore raw

PATCH 19/27 anon_vma_prepare: properly lock even newly allocated entries

In reply to Greg KH

2.6.27-stable review patch. If anyone has any objections, please let us know.

------------------
From: Linus Torvalds <[email protected]>

commit d9d332e0874f46b91d8ac4604b68ee42b8a7a2c6 upstream

The anon_vma code is very subtle, and we end up doing optimistic lookups of anon_vmas under RCU in page_lock_anon_vma() with no locking. Other CPU's can also see the newly allocated entry immediately after we've exposed it by setting "vma->anon_vma" to the new value.

We protect against the anon_vma being destroyed by having the SLAB marked as SLAB_DESTROY_BY_RCU, so the RCU lookup can depend on the allocation not being destroyed - but it might still be free'd and re-allocated here to a new vma.

As a result, we should not do the anon_vma list ops on a newly allocated vma without proper locking.

---
 mm/rmap.c |   42 ++++++++++++++++++++++++++++++++----------
 1 file changed, 32 insertions(+), 10 deletions(-)
mm/rmap.c +32 -10
@@ -55,7 +55,33 @@
 
 struct kmem_cache *anon_vma_cachep;
 
-/* This must be called under the mmap_sem. */
+/**
+ * anon_vma_prepare - attach an anon_vma to a memory region
+ * @vma: the memory region in question
+ *
+ * This makes sure the memory mapping described by 'vma' has
+ * an 'anon_vma' attached to it, so that we can associate the
+ * anonymous pages mapped into it with that anon_vma.
+ *
+ * The common case will be that we already have one, but if
+ * if not we either need to find an adjacent mapping that we
+ * can re-use the anon_vma from (very common when the only
+ * reason for splitting a vma has been mprotect()), or we
+ * allocate a new one.
+ *
+ * Anon-vma allocations are very subtle, because we may have
+ * optimistically looked up an anon_vma in page_lock_anon_vma()
+ * and that may actually touch the spinlock even in the newly
+ * allocated vma (it depends on RCU to make sure that the
+ * anon_vma isn't actually destroyed).
+ *
+ * As a result, we need to do proper anon_vma locking even
+ * for the new allocation. At the same time, we do not want
+ * to do any locking for the common case of already having
+ * an anon_vma.
+ *
+ * This must be called with the mmap_sem held for reading.
+ */
 int anon_vma_prepare(struct vm_area_struct *vma)
 {
 	struct anon_vma *anon_vma = vma->anon_vma;
@@ -63,20 +89,17 @@ int anon_vma_prepare(struct vm_area_stru
 	might_sleep();
 	if (unlikely(!anon_vma)) {
 		struct mm_struct *mm = vma->vm_mm;
-		struct anon_vma *allocated, *locked;
+		struct anon_vma *allocated;
 
 		anon_vma = find_mergeable_anon_vma(vma);
-		if (anon_vma) {
-			allocated = NULL;
-			locked = anon_vma;
-			spin_lock(&locked->lock);
-		} else {
+		allocated = NULL;
+		if (!anon_vma) {
 			anon_vma = anon_vma_alloc();
 			if (unlikely(!anon_vma))
 				return -ENOMEM;
 			allocated = anon_vma;
-			locked = NULL;
 		}
+		spin_lock(&anon_vma->lock);
 
 		/* page_table_lock to protect against threads */
 		spin_lock(&mm->page_table_lock);
@@ -87,8 +110,7 @@ int anon_vma_prepare(struct vm_area_stru
 		}
 		spin_unlock(&mm->page_table_lock);
 
-		if (locked)
-			spin_unlock(&locked->lock);
+		spin_unlock(&anon_vma->lock);
 		if (unlikely(allocated))
 			anon_vma_free(allocated);
 	}
author
#27 lore raw

PATCH 24/27 proc: fix vma display mismatch between /proc/pid/{maps,smaps}

In reply to Greg KH

2.6.27-stable review patch. If anyone has any objections, please let us know.

------------------
From: Joe Korty <[email protected]>

[ backport of 7c88db0cb589df980acfb2f73c3595a0653004ec to 2.7.27.3 by Joe Korty <[email protected] ]

proc: fix vma display mismatch between /proc/pid/{maps,smaps}

Commit 4752c369789250eafcd7813e11c8fb689235b0d2 aka
"maps4: simplify interdependence of maps and smaps" broke /proc/pid/smaps, causing it to display some vmas twice and other vmas not at all. For example:

    grep .- /proc/1/smaps >/tmp/smaps; diff /proc/1/maps /tmp/smaps

    1  25d24
    2  < 7fd7e23aa000-7fd7e23ac000 rw-p 7fd7e23aa000 00:00 0
    3  28a28
    4  > ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0  [vsyscall]

The bug has something to do with setting m->version before all the seq_printf's have been performed. show_map was doing this correctly, but show_smap was doing this in the middle of its seq_printf sequence. This patch arranges things so that the setting of m->version in show_smap is also done at the end of its seq_printf sequence.

Testing: in addition to the above grep test, for each process I summed up the 'Rss' fields of /proc/pid/smaps and compared that to the 'VmRSS' field of /proc/pid/status. All matched except for Xorg (which has a /dev/mem mapping which Rss accounts for but VmRSS does not). This result gives us some confidence that neither /proc/pid/maps nor /proc/pid/smaps are any longer skipping or double-counting vmas.

---
 fs/proc/task_mmu.c |   34 ++++++++++++++++++++++------------
 1 file changed, 22 insertions(+), 12 deletions(-)
fs/proc/task_mmu.c +22 -12
@@ -198,11 +198,8 @@ static int do_maps_open(struct inode *in
 	return ret;
 }
 
-static int show_map(struct seq_file *m, void *v)
+static void show_map_vma(struct seq_file *m, struct vm_area_struct *vma)
 {
-	struct proc_maps_private *priv = m->private;
-	struct task_struct *task = priv->task;
-	struct vm_area_struct *vma = v;
 	struct mm_struct *mm = vma->vm_mm;
 	struct file *file = vma->vm_file;
 	int flags = vma->vm_flags;
@@ -210,9 +207,6 @@ static int show_map(struct seq_file *m, 
 	dev_t dev = 0;
 	int len;
 
-	if (maps_protect && !ptrace_may_access(task, PTRACE_MODE_READ))
-		return -EACCES;
-
 	if (file) {
 		struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
 		dev = inode->i_sb->s_dev;
@@ -257,6 +251,18 @@ static int show_map(struct seq_file *m, 
 		}
 	}
 	seq_putc(m, '\n');
+}
+
+static int show_map(struct seq_file *m, void *v)
+{
+	struct vm_area_struct *vma = v;
+	struct proc_maps_private *priv = m->private;
+	struct task_struct *task = priv->task;
+
+	if (maps_protect && !ptrace_may_access(task, PTRACE_MODE_READ))
+		return -EACCES;
+
+	show_map_vma(m, vma);
 
 	if (m->count < m->size)  /* vma is copied successfully */
 		m->version = (vma != get_gate_vma(task))? vma->vm_start: 0;
@@ -367,23 +373,25 @@ static int smaps_pte_range(pmd_t *pmd, u
 
 static int show_smap(struct seq_file *m, void *v)
 {
+	struct proc_maps_private *priv = m->private;
+	struct task_struct *task = priv->task;
 	struct vm_area_struct *vma = v;
 	struct mem_size_stats mss;
-	int ret;
 	struct mm_walk smaps_walk = {
 		.pmd_entry = smaps_pte_range,
 		.mm = vma->vm_mm,
 		.private = &mss,
 	};
 
+	if (maps_protect && !ptrace_may_access(task, PTRACE_MODE_READ))
+		return -EACCES;
+
 	memset(&mss, 0, sizeof mss);
 	mss.vma = vma;
 	if (vma->vm_mm && !is_vm_hugetlb_page(vma))
 		walk_page_range(vma->vm_start, vma->vm_end, &smaps_walk);
 
-	ret = show_map(m, v);
-	if (ret)
-		return ret;
+	show_map_vma(m, vma);
 
 	seq_printf(m,
 		   "Size:           %8lu kB\n"
@@ -405,7 +413,9 @@ static int show_smap(struct seq_file *m,
 		   mss.referenced >> 10,
 		   mss.swap >> 10);
 
-	return ret;
+	if (m->count < m->size)  /* vma is copied successfully */
+		m->version = (vma != get_gate_vma(task)) ? vma->vm_start : 0;
+	return 0;
 }
 
 static const struct seq_operations proc_pid_smaps_op = {
author
#26 lore raw

PATCH 23/27 ACPI suspend: Always use the 32-bit waking vector

In reply to Greg KH

2.6.27-stable review patch. If anyone has any objections, please let us know.

------------------
From: Rafael J. Wysocki <[email protected]>

commit a6629105dd03d370fcb31e97bddf223fa4bb651e upstream.

According to the ACPI specification 2.0c and later, the 64-bit waking vector should be cleared and the 32-bit waking vector should be used, unless we want the wake-up code to be called by the BIOS in Protected Mode. Moreover, some systems (for example HP dv5-1004nr) are known to fail to resume if the 64-bit waking vector is used. Therefore, modify the code to clear the 64-bit waking vector, for FACS version 1 or greater, and set the 32-bit one before suspend.

http://bugzilla.kernel.org/show_bug.cgi?id=11368

---
 drivers/acpi/hardware/hwsleep.c |   37 +++++++++++--------------------------
 1 file changed, 11 insertions(+), 26 deletions(-)
drivers/acpi/hardware/hwsleep.c +11 -26
@@ -78,19 +78,17 @@ acpi_set_firmware_waking_vector(acpi_phy
 		return_ACPI_STATUS(status);
 	}
 
-	/* Set the vector */
+	/*
+	 * According to the ACPI specification 2.0c and later, the 64-bit
+	 * waking vector should be cleared and the 32-bit waking vector should
+	 * be used, unless we want the wake-up code to be called by the BIOS in
+	 * Protected Mode.  Some systems (for example HP dv5-1004nr) are known
+	 * to fail to resume if the 64-bit vector is used.
+	 */
+	if (facs->version >= 1)
+		facs->xfirmware_waking_vector = 0;
 
-	if ((facs->length < 32) || (!(facs->xfirmware_waking_vector))) {
-		/*
-		 * ACPI 1.0 FACS or short table or optional X_ field is zero
-		 */
-		facs->firmware_waking_vector = (u32) physical_address;
-	} else {
-		/*
-		 * ACPI 2.0 FACS with valid X_ field
-		 */
-		facs->xfirmware_waking_vector = physical_address;
-	}
+	facs->firmware_waking_vector = (u32)physical_address;
 
 	return_ACPI_STATUS(AE_OK);
 }
@@ -134,20 +132,7 @@ acpi_get_firmware_waking_vector(acpi_phy
 	}
 
 	/* Get the vector */
-
-	if ((facs->length < 32) || (!(facs->xfirmware_waking_vector))) {
-		/*
-		 * ACPI 1.0 FACS or short table or optional X_ field is zero
-		 */
-		*physical_address =
-		    (acpi_physical_address) facs->firmware_waking_vector;
-	} else {
-		/*
-		 * ACPI 2.0 FACS with valid X_ field
-		 */
-		*physical_address =
-		    (acpi_physical_address) facs->xfirmware_waking_vector;
-	}
+	*physical_address = (acpi_physical_address)facs->firmware_waking_vector;
 
 	return_ACPI_STATUS(AE_OK);
 }
author
#25 lore raw

PATCH 22/27 ACPI suspend: Blacklist HP xw4600 Workstation for old code ordering

In reply to Greg KH

2.6.27-stable review patch. If anyone has any objections, please let us know.

------------------
From: Rafael J. Wysocki <[email protected]>

commit 4fb507b6b764195bb7821cf2baa988f6eb677d30 upstream

HP xw4600 Workstation is known to require the "old" (ie. compatible with ACPI 1.0) suspend code ordering, so blacklist it for this purpose.

---
 drivers/acpi/sleep/main.c |    8 ++++++++
 1 file changed, 8 insertions(+)
drivers/acpi/sleep/main.c +8 -0
@@ -298,6 +298,14 @@ static struct dmi_system_id __initdata a
 		DMI_MATCH(DMI_BOARD_NAME, "KN9 Series(NF-CK804)"),
 		},
 	},
+	{
+	.callback = init_old_suspend_ordering,
+	.ident = "HP xw4600 Workstation",
+	.matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+		DMI_MATCH(DMI_PRODUCT_NAME, "HP xw4600 Workstation"),
+		},
+	},
 	{},
 };
 #endif /* CONFIG_SUSPEND */
author
#28 lore raw

PATCH 25/27 SCSI: scsi_dh: add Dell product information into rdac device handler

In reply to Greg KH

2.6.27-stable review patch. If anyone has any objections, please let us know.

------------------
From: [email protected] <[email protected]>

commit 650849d71ca05d55a1553fe42fb21af9dce5612b upstream.

Add Dell Powervault storage arrays into device list of rdac device handler.

---
 drivers/scsi/device_handler/scsi_dh_rdac.c |    2 ++
 1 file changed, 2 insertions(+)
drivers/scsi/device_handler/scsi_dh_rdac.c +2 -0
@@ -590,6 +590,8 @@ static const struct scsi_dh_devlist rdac
 	{"STK", "OPENstorage D280"},
 	{"SUN", "CSM200_R"},
 	{"SUN", "LCSM100_F"},
+	{"DELL", "MD3000"},
+	{"DELL", "MD3000i"},
 	{NULL, NULL},
 };
 
author
#29 lore raw

PATCH 26/27 PCI hotplug: cpqphp: fix kernel NULL pointer dereference

In reply to Greg KH

2.6.27-stable review patch. If anyone has any objections, please let us know.

------------------
From: Kenji Kaneshige <[email protected]>

commit d2174c3c07adad88dd9ba37a731e0b00b746822a upstream

The following patch fixes the regression in 2.6.27 that causes kernel NULL pointer dereference at cpqphp driver probe time. This patch should be backported to the .27 stable series.

Seems to have been introduced by
f46753c5e354b857b20ab8e0fe7b2579831dc369.

The root cause of this problem seems that cpqphp driver calls pci_hp_register() wrongly. In current implementation, cpqphp driver passes 'ctrl->pci_dev->subordinate' as a second parameter for pci_hp_register(). But because hotplug slots and it's hotplug controller (exists as a pci funcion) are on the same bus, it should be 'ctrl->pci_dev->bus' instead.

---
 drivers/pci/hotplug/cpqphp_core.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/pci/hotplug/cpqphp_core.c +1 -1
@@ -435,7 +435,7 @@ static int ctrl_slot_setup(struct contro
 				slot->number, ctrl->slot_device_offset,
 				slot_number);
 		result = pci_hp_register(hotplug_slot,
-					 ctrl->pci_dev->subordinate,
+					 ctrl->pci_dev->bus,
 					 slot->device);
 		if (result) {
 			err("pci_hp_register failed with error %d\n", result);
author
#30 lore raw

PATCH 27/27 ath5k: fix suspend-related oops on rmmod

In reply to Greg KH

2.6.27-stable review patch. If anyone has any objections, please let us know.

------------------
From: Bob Copeland <[email protected]>

commit 8bdd5b9c6bd53add260756b6673a0545fbdbba21 upstream

Based on a patch by Elias Oltmanns, we call ath5k_init in resume even if we didn't previously open the device. Besides starting up the device unnecessarily, this also causes an oops on rmmod because mac80211 will not invoke ath5k_stop and softirqs are left running after the module has been unloaded. Add a new state bit, ATH_STAT_STARTED, to indicate that we have been started up.

---
 drivers/net/wireless/ath5k/base.c |   28 ++++++++++++++++++++--------
 drivers/net/wireless/ath5k/base.h |    3 ++-
 2 files changed, 22 insertions(+), 9 deletions(-)
drivers/net/wireless/ath5k/base.c +20 -8
@@ -294,9 +294,9 @@ static inline u64 ath5k_extend_tsf(struc
 }
 
 /* Interrupt handling */
-static int 	ath5k_init(struct ath5k_softc *sc);
+static int 	ath5k_init(struct ath5k_softc *sc, bool is_resume);
 static int 	ath5k_stop_locked(struct ath5k_softc *sc);
-static int 	ath5k_stop_hw(struct ath5k_softc *sc);
+static int 	ath5k_stop_hw(struct ath5k_softc *sc, bool is_suspend);
 static irqreturn_t ath5k_intr(int irq, void *dev_id);
 static void 	ath5k_tasklet_reset(unsigned long data);
 
@@ -584,7 +584,7 @@ ath5k_pci_suspend(struct pci_dev *pdev, 
 
 	ath5k_led_off(sc);
 
-	ath5k_stop_hw(sc);
+	ath5k_stop_hw(sc, true);
 
 	free_irq(pdev->irq, sc);
 	pci_save_state(pdev);
@@ -621,7 +621,7 @@ ath5k_pci_resume(struct pci_dev *pdev)
 		goto err_no_irq;
 	}
 
-	err = ath5k_init(sc);
+	err = ath5k_init(sc, true);
 	if (err)
 		goto err_irq;
 	ath5k_led_enable(sc);
@@ -2197,12 +2197,17 @@ ath5k_beacon_config(struct ath5k_softc *
 \********************/
 
 static int
-ath5k_init(struct ath5k_softc *sc)
+ath5k_init(struct ath5k_softc *sc, bool is_resume)
 {
 	int ret;
 
 	mutex_lock(&sc->lock);
 
+	if (is_resume && !test_bit(ATH_STAT_STARTED, sc->status))
+		goto out_ok;
+
+	__clear_bit(ATH_STAT_STARTED, sc->status);
+
 	ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "mode %d\n", sc->opmode);
 
 	/*
@@ -2250,12 +2255,16 @@ ath5k_init(struct ath5k_softc *sc)
 		AR5K_INT_MIB;
 
 	ath5k_hw_set_intr(sc->ah, sc->imask);
+
+	__set_bit(ATH_STAT_STARTED, sc->status);
+
 	/* Set ack to be sent at low bit-rates */
 	ath5k_hw_set_ack_bitrate_high(sc->ah, false);
 
 	mod_timer(&sc->calib_tim, round_jiffies(jiffies +
 			msecs_to_jiffies(ath5k_calinterval * 1000)));
 
+out_ok:
 	ret = 0;
 done:
 	mmiowb();
@@ -2310,7 +2319,7 @@ ath5k_stop_locked(struct ath5k_softc *sc
  * stop is preempted).
  */
 static int
-ath5k_stop_hw(struct ath5k_softc *sc)
+ath5k_stop_hw(struct ath5k_softc *sc, bool is_suspend)
 {
 	int ret;
 
@@ -2341,6 +2350,9 @@ ath5k_stop_hw(struct ath5k_softc *sc)
 		}
 	}
 	ath5k_txbuf_free(sc, sc->bbuf);
+	if (!is_suspend)
+		__clear_bit(ATH_STAT_STARTED, sc->status);
+
 	mmiowb();
 	mutex_unlock(&sc->lock);
 
@@ -2719,12 +2731,12 @@ err:
 
 static int ath5k_start(struct ieee80211_hw *hw)
 {
-	return ath5k_init(hw->priv);
+	return ath5k_init(hw->priv, false);
 }
 
 static void ath5k_stop(struct ieee80211_hw *hw)
 {
-	ath5k_stop_hw(hw->priv);
+	ath5k_stop_hw(hw->priv, false);
 }
 
 static int ath5k_add_interface(struct ieee80211_hw *hw,
drivers/net/wireless/ath5k/base.h +2 -1
@@ -132,11 +132,12 @@ struct ath5k_softc {
 	size_t			desc_len;	/* size of TX/RX descriptors */
 	u16			cachelsz;	/* cache line size */
 
-	DECLARE_BITMAP(status, 4);
+	DECLARE_BITMAP(status, 5);
 #define ATH_STAT_INVALID	0		/* disable hardware accesses */
 #define ATH_STAT_MRRETRY	1		/* multi-rate retry support */
 #define ATH_STAT_PROMISC	2
 #define ATH_STAT_LEDSOFT	3		/* enable LED gpio status */
+#define ATH_STAT_STARTED	4		/* opened & irqs enabled */
 
 	unsigned int		filter_flags;	/* HW flags, AR5K_RX_FILTER_* */
 	unsigned int		curmode;	/* current phy mode */
author
#24 lore raw

PATCH 21/27 ACPI Suspend: Enable ACPI during resume if SCI_EN is not set

In reply to Greg KH

2.6.27-stable review patch. If anyone has any objections, please let us know.

------------------
From: Rafael J. Wysocki <[email protected]>

commit d0c71fe7ebc180f1b7bc7da1d39a07fc19eec768 upstream.

On some machines, like for example MSI Wind U100, the BIOS doesn't enable ACPI before returning control to the OS, which sometimes causes resume to fail. This is against the ACPI specification, which clearly states that "When the platform is waking from an S1, S2 or S3 state, OSPM assumes the hardware is already in the ACPI mode and will not issue an ACPI_ENABLE", but it won't hurt to check the SCI_EN bit and enable ACPI during resume from S3 if this bit is not set.

Fortunately, we already have acpi_enable() for that, so use it in the resume code path, before executing _BFS, in analogy with the resume-from-hibernation code path.

NOTE: We aren't supposed to set SCI_EN directly, because it's owned by the hardware.

---
 drivers/acpi/sleep/main.c |    2 ++
 1 file changed, 2 insertions(+)
drivers/acpi/sleep/main.c +2 -0
@@ -200,6 +200,8 @@ static int acpi_suspend_enter(suspend_st
 		break;
 	}
 
+	/* If ACPI is not enabled by the BIOS, we need to enable it here. */
+	acpi_enable();
 	/* Reprogram control registers and execute _BFS */
 	acpi_leave_sleep_state_prep(acpi_state);
 
author
#23 lore raw

PATCH 20/27 hvc_console: Fix free_irq in spinlocked section

In reply to Greg KH

2.6.27-stable review patch. If anyone has any objections, please let us know.

------------------
From: Christian Borntraeger <[email protected]>

commit eef2622a9fcfa964073333ea72c7c9cd20ad45e6 upstream

hvc_console: Fix free_irq in spinlocked section

commit 611e097d7707741a336a0677d9d69bec40f29f3d
Author: Christian Borntraeger <[email protected]>
hvc_console: rework setup to replace irq functions with callbacks introduced a spinlock recursion problem. The notifier_del is called with a lock held, and in turns calls free_irq which then complains when manipulating procfs. This fixes it by moving the call to the notifier to outside of the locked section.

---
 drivers/char/hvc_console.c |   10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)
drivers/char/hvc_console.c +5 -5
@@ -367,13 +367,13 @@ static void hvc_close(struct tty_struct 
 	spin_lock_irqsave(&hp->lock, flags);
 
 	if (--hp->count == 0) {
-		if (hp->ops->notifier_del)
-			hp->ops->notifier_del(hp, hp->data);
-
 		/* We are done with the tty pointer now. */
 		hp->tty = NULL;
 		spin_unlock_irqrestore(&hp->lock, flags);
 
+		if (hp->ops->notifier_del)
+			hp->ops->notifier_del(hp, hp->data);
+
 		/*
 		 * Chain calls chars_in_buffer() and returns immediately if
 		 * there is no buffered data otherwise sleeps on a wait queue
@@ -416,11 +416,11 @@ static void hvc_hangup(struct tty_struct
 	hp->n_outbuf = 0;
 	hp->tty = NULL;
 
+	spin_unlock_irqrestore(&hp->lock, flags);
+
 	if (hp->ops->notifier_del)
 			hp->ops->notifier_del(hp, hp->data);
 
-	spin_unlock_irqrestore(&hp->lock, flags);
-
 	while(temp_open_count) {
 		--temp_open_count;
 		kref_put(&hp->kref, destroy_hvc_struct);
#12 lore raw

Re: [patch 11/27] dm exception store: refactor zero_area

In reply to Greg KH
Quoted 14 lines · Greg KH

2.6.27-stable review patch. If anyone has any objections, please let us know.

------------------
From: Alasdair G Kergon <[email protected]>

commit 7c9e6c17325fab380fbe9c9787680ff7d4a51abd upstream

Use a separate buffer for writing zeroes to the on-disk snapshot exception store, make the updating of ps->current_area explicit and refactor the code in preparation for the fix in the next patch.

No functional change.

Quoted 7 lines
---
 drivers/md/dm-exception-store.c |  103 ++++++++++++++++++++++++++--------------
 1 file changed, 69 insertions(+), 34 deletions(-)

Oops, this patch causes a build error:

drivers/md/dm-exception-store.c:235: error: implicit declaration of function 'area_location' drivers/md/dm-exception-store.c:241: error: 'area' undeclared (first use in this function) drivers/md/dm-exception-store.c:241: error: (Each undeclared identifier is reported only once drivers/md/dm-exception-store.c:241: error: for each function it appears in.)

I'll drop this one, and the follow-on dm-exception-store.c patch as well, as that was the only reason this patch was added.

If you want to redo these two patches, and get them into the 2.6.27-stable tree, please do so and send them to [email protected].

thanks,

greg k-h

#34 lore raw
In reply to Greg KH
Quoted 3 lines · Greg KH

The whole patch series can be found in one patch at:

	kernel.org/pub/linux/kernel/v2.6/stable-review/patch-2.6.27.4-rc1.gz

and the diffstat can be found below.

There was a build error in this release, so I've now put up a -rc2 version at:

	kernel.org/pub/linux/kernel/v2.6/stable-review/patch-2.6.27.4-rc2.gz

and the diffstat is below.

thanks,

greg k-h

 Makefile                                       |    2 
 arch/x86/kernel/acpi/sleep.c                   |    3 +
 arch/x86/kernel/amd_iommu_init.c               |    2 
 drivers/acpi/hardware/hwsleep.c                |   37 ++++-----------
 drivers/acpi/sleep/main.c                      |   10 ++++
 drivers/char/hvc_console.c                     |   10 ++--
 drivers/edac/cell_edac.c                       |    2 
 drivers/gpio/gpiolib.c                         |    2 
 drivers/md/dm-kcopyd.c                         |   13 +++++
 drivers/md/dm-snap.c                           |   10 +---
 drivers/net/wireless/ath5k/base.c              |   28 ++++++++---
 drivers/net/wireless/ath5k/base.h              |    3 -
 drivers/pci/hotplug/cpqphp_core.c              |    2 
 drivers/scsi/device_handler/scsi_dh_rdac.c     |    2 
 drivers/usb/atm/speedtch.c                     |   12 +++++
 drivers/usb/class/cdc-acm.c                    |    3 -
 drivers/usb/class/cdc-wdm.c                    |    2 
 drivers/usb/core/driver.c                      |    3 -
 drivers/usb/core/hub.c                         |    2 
 fs/cifs/readdir.c                              |    3 -
 fs/ext2/dir.c                                  |   60 ++++++++++++++-----------
 fs/ext3/dir.c                                  |   10 ++--
 fs/ext4/dir.c                                  |   11 +++-
 fs/proc/task_mmu.c                             |   34 +++++++++-----
 kernel/sched_stats.h                           |    2 
 mm/rmap.c                                      |   42 +++++++++++++----
 net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c |    2 
 net/ipv4/netfilter/nf_nat_snmp_basic.c         |    1 
 net/netfilter/xt_iprange.c                     |    8 +--
 29 files changed, 206 insertions(+), 115 deletions(-)
#31 lore raw

Re: [patch 27/27] ath5k: fix suspend-related oops on rmmod

In reply to Greg KH
Quoted 15 lines · Greg KH

2.6.27-stable review patch. If anyone has any objections, please let us know.

------------------
From: Bob Copeland <[email protected]>

commit 8bdd5b9c6bd53add260756b6673a0545fbdbba21 upstream

Based on a patch by Elias Oltmanns, we call ath5k_init in resume even if we didn't previously open the device. Besides starting up the device unnecessarily, this also causes an oops on rmmod because mac80211 will not invoke ath5k_stop and softirqs are left running after the module has been unloaded. Add a new state bit, ATH_STAT_STARTED, to indicate that we have been started up.

Quoted 5 lines

I've done some more testing and I'm ashamed to say that this patch is incomplete and does indeed introduce a regression itself. Having only just sent the fix to John, I'm afraid this patch has to be deferred for the next stable release since the required fix is not likely to hit Linus' tree in time. Anyway, I'm adding my patch and the changelog entry by way of explanation.

Regards,

Elias

From: Elias Oltmanns <[email protected]>
Subject: [PATCH] ath5k: Reset key cache on interface up, thus fixing resume

After a s2ram / resume cycle, resetting the key cache does not work unless it is deferred until after the hardware has been reinitialised by a call to ath5k_hw_reset(). This fixes a regression introduced in commit 8bdd5b9c6bd53add260756b6673a0545fbdbba21 (ath5k: fix suspend-related oops on rmmod).

---

 base.c |   29 ++++++++++-------------------
 1 file changed, 10 insertions(+), 19 deletions(-)
drivers/net/wireless/ath5k/base.c +10 -19
index 0f1d6bd..8acf0ce 100644
@@ -688,16 +688,6 @@ ath5k_pci_resume(struct pci_dev *pdev)
 		goto err_irq;
 	ath5k_led_enable(sc);
 
-	/*
-	 * Reset the key cache since some parts do not
-	 * reset the contents on initial power up or resume.
-	 *
-	 * FIXME: This may need to be revisited when mac80211 becomes
-	 *        aware of suspend/resume.
-	 */
-	for (i = 0; i < AR5K_KEYTABLE_SIZE; i++)
-		ath5k_hw_reset_key(ah, i);
-
 	return 0;
 err_irq:
 	free_irq(pdev->irq, sc);
@@ -737,13 +727,6 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
 		__set_bit(ATH_STAT_MRRETRY, sc->status);
 
 	/*
-	 * Reset the key cache since some parts do not
-	 * reset the contents on initial power up.
-	 */
-	for (i = 0; i < AR5K_KEYTABLE_SIZE; i++)
-		ath5k_hw_reset_key(ah, i);
-
-	/*
 	 * Collect the channel list.  The 802.11 layer
 	 * is resposible for filtering this list based
 	 * on settings like the phy mode and regulatory
@@ -2202,7 +2185,8 @@ ath5k_beacon_config(struct ath5k_softc *sc)
 static int
 ath5k_init(struct ath5k_softc *sc, bool is_resume)
 {
-	int ret;
+	struct ath5k_hw *ah = sc->ah;
+	int ret, i;
 
 	mutex_lock(&sc->lock);
 
@@ -2235,10 +2219,17 @@ ath5k_init(struct ath5k_softc *sc, bool is_resume)
 	if (ret)
 		goto done;
 
+	/*
+	 * Reset the key cache since some parts do not reset the
+	 * contents on initial power up or resume from suspend.
+	 */
+	for (i = 0; i < AR5K_KEYTABLE_SIZE; i++)
+		ath5k_hw_reset_key(ah, i);
+
 	__set_bit(ATH_STAT_STARTED, sc->status);
 
 	/* Set ack to be sent at low bit-rates */
-	ath5k_hw_set_ack_bitrate_high(sc->ah, false);
+	ath5k_hw_set_ack_bitrate_high(ah, false);
 
 	mod_timer(&sc->calib_tim, round_jiffies(jiffies +
 			msecs_to_jiffies(ath5k_calinterval * 1000)));
#32 lore raw

Re: [patch 27/27] ath5k: fix suspend-related oops on rmmod

On Fri, 24 Oct 2008 22:36:24 +0200, Elias Oltmanns wrote

Quoted 5 lines

I've done some more testing and I'm ashamed to say that this patch is incomplete and does indeed introduce a regression itself. Having only just sent the fix to John, I'm afraid this patch has to be deferred for the next stable release since the required fix is not likely to hit Linus' tree in time.

Yeah, let's drop the patch from stable since it resets the key cache even in the not-opened resume case.

Note, ath5k_set_key is a no-op right now so we can just elide that whole section of code.

Signature · 1 line
Bob Copeland %% www.bobcopeland.com
author
#33 lore raw

Re: [patch 27/27] ath5k: fix suspend-related oops on rmmod

In reply to Elias Oltmanns
Quoted 22 lines · Elias Oltmanns
Quoted 15 lines · Greg KH

2.6.27-stable review patch. If anyone has any objections, please let us know.

------------------
From: Bob Copeland <[email protected]>

commit 8bdd5b9c6bd53add260756b6673a0545fbdbba21 upstream

Based on a patch by Elias Oltmanns, we call ath5k_init in resume even if we didn't previously open the device. Besides starting up the device unnecessarily, this also causes an oops on rmmod because mac80211 will not invoke ath5k_stop and softirqs are left running after the module has been unloaded. Add a new state bit, ATH_STAT_STARTED, to indicate that we have been started up.

Quoted 5 lines
Quoted 6 lines

I've done some more testing and I'm ashamed to say that this patch is incomplete and does indeed introduce a regression itself. Having only just sent the fix to John, I'm afraid this patch has to be deferred for the next stable release since the required fix is not likely to hit Linus' tree in time. Anyway, I'm adding my patch and the changelog entry by way of explanation.

Ok, I've dropped this from the 2.6.27-stable queue now, thanks for letting me know.

greg k-h

#35 lore raw
In reply to Greg KH
Quoted 8 lines · Greg KH
Quoted 3 lines · Greg KH

The whole patch series can be found in one patch at:

	kernel.org/pub/linux/kernel/v2.6/stable-review/patch-2.6.27.4-rc1.gz

and the diffstat can be found below.

There was a build error in this release, so I've now put up a -rc2 version at:

	kernel.org/pub/linux/kernel/v2.6/stable-review/patch-2.6.27.4-rc2.gz

And there was an error in this release as well, the ath5k patch was dropped as it was found to cause regressions itself.

Also a pvrusb2 patch was added to let the device work again with the 2.6.27 kernel, which is always a nice thing to have. I'll follow up this message with that patch.

I've now put up a -rc3 version at:

	kernel.org/pub/linux/kernel/v2.6/stable-review/patch-2.6.27.4-rc3.gz

and the diffstat is below.

thanks,

greg k-h

 Makefile                                       |    2 
 arch/x86/kernel/acpi/sleep.c                   |    3 +
 arch/x86/kernel/amd_iommu_init.c               |    2 
 drivers/acpi/hardware/hwsleep.c                |   37 ++++-----------
 drivers/acpi/sleep/main.c                      |   10 ++++
 drivers/char/hvc_console.c                     |   10 ++--
 drivers/edac/cell_edac.c                       |    2 
 drivers/gpio/gpiolib.c                         |    2 
 drivers/md/dm-kcopyd.c                         |   13 +++++
 drivers/md/dm-snap.c                           |   10 +---
 drivers/media/video/pvrusb2/pvrusb2-hdw.c      |    6 --
 drivers/pci/hotplug/cpqphp_core.c              |    2 
 drivers/scsi/device_handler/scsi_dh_rdac.c     |    2 
 drivers/usb/atm/speedtch.c                     |   12 +++++
 drivers/usb/class/cdc-acm.c                    |    3 -
 drivers/usb/class/cdc-wdm.c                    |    2 
 drivers/usb/core/driver.c                      |    3 -
 drivers/usb/core/hub.c                         |    2 
 fs/cifs/readdir.c                              |    3 -
 fs/ext2/dir.c                                  |   60 ++++++++++++++-----------
 fs/ext3/dir.c                                  |   10 ++--
 fs/ext4/dir.c                                  |   11 +++-
 fs/proc/task_mmu.c                             |   34 +++++++++-----
 kernel/sched_stats.h                           |    2 
 mm/rmap.c                                      |   42 +++++++++++++----
 net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c |    2 
 net/ipv4/netfilter/nf_nat_snmp_basic.c         |    1 
 net/netfilter/xt_iprange.c                     |    8 +--
 28 files changed, 184 insertions(+), 112 deletions(-)
#36 lore raw

[patch 28/27] V4L/DVB (9300): pvrusb2: Fix deadlock problem

2.6.27-stable patch

---------------------

From: Mike Isely <[email protected]>

commit c82732a42896364296599b0f73f01c5e3fd781ae upstream

Fix deadlock problem in 2.6.27 caused by new USB core behavior in response to a USB device reset request. With older kernels, the USB device reset was "in line"; the reset simply took place and the driver retained its association with the hardware. However now this reset triggers a disconnect, and worse still the disconnect callback happens in the context of the caller who asked for the device reset. This results in an attempt by the pvrusb2 driver to recursively take a mutex it already has, which deadlocks the driver's worker thread. (Even if the disconnect callback were to happen on a different thread we'd still have problems however - because while the driver should survive and correctly disconnect / reconnect, it will then trigger another device reset during the repeated initialization, which will then cause another disconect, etc, forever.) The fix here is simply to not attempt the device reset (it was of marginal value anyway).

---
 drivers/media/video/pvrusb2/pvrusb2-hdw.c |    6 ------
 1 file changed, 6 deletions(-)
drivers/media/video/pvrusb2/pvrusb2-hdw.c +0 -6
@@ -60,7 +60,6 @@ static struct pvr2_hdw *unit_pointers[PV
 static DEFINE_MUTEX(pvr2_unit_mtx);
 
 static int ctlchg;
-static int initusbreset = 1;
 static int procreload;
 static int tuner[PVR_NUM] = { [0 ... PVR_NUM-1] = -1 };
 static int tolerance[PVR_NUM] = { [0 ... PVR_NUM-1] = 0 };
@@ -71,8 +70,6 @@ module_param(ctlchg, int, S_IRUGO|S_IWUS
 MODULE_PARM_DESC(ctlchg, "0=optimize ctl change 1=always accept new ctl value");
 module_param(init_pause_msec, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(init_pause_msec, "hardware initialization settling delay");
-module_param(initusbreset, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(initusbreset, "Do USB reset device on probe");
 module_param(procreload, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(procreload,
 		 "Attempt init failure recovery with firmware reload");
@@ -1698,9 +1695,6 @@ static void pvr2_hdw_setup_low(struct pv
 	}
 	hdw->fw1_state = FW1_STATE_OK;
 
-	if (initusbreset) {
-		pvr2_hdw_device_reset(hdw);
-	}
 	if (!pvr2_hdw_dev_ok(hdw)) return;
 
 	for (idx = 0; idx < hdw->hdw_desc->client_modules.cnt; idx++) {
maintainer
#13 lore raw

Re: [patch 11/27] dm exception store: refactor zero_area

In reply to Greg KH
Quoted 33 lines · Greg KH
Quoted 14 lines · Greg KH

2.6.27-stable review patch. If anyone has any objections, please let us know.

------------------
From: Alasdair G Kergon <[email protected]>

commit 7c9e6c17325fab380fbe9c9787680ff7d4a51abd upstream

Use a separate buffer for writing zeroes to the on-disk snapshot exception store, make the updating of ps->current_area explicit and refactor the code in preparation for the fix in the next patch.

No functional change.

Quoted 7 lines
---
 drivers/md/dm-exception-store.c |  103 ++++++++++++++++++++++++++--------------
 1 file changed, 69 insertions(+), 34 deletions(-)

Oops, this patch causes a build error:

drivers/md/dm-exception-store.c:235: error: implicit declaration of function 'area_location' drivers/md/dm-exception-store.c:241: error: 'area' undeclared (first use in this function) drivers/md/dm-exception-store.c:241: error: (Each undeclared identifier is reported only once drivers/md/dm-exception-store.c:241: error: for each function it appears in.)

I'll drop this one, and the follow-on dm-exception-store.c patch as well, as that was the only reason this patch was added.

Quoted 6 lines

If you want to redo these two patches, and get them into the 2.6.27-stable tree, please do so and send them to [email protected].

thanks,

greg k-h

You should apply this one patch before:
ftp://ftp.kernel.org/pub/linux/kernel/people/agk/patches/2.6/editing/dm-exception-store-introduce-area_location-function.patch

Mikulas

#14 lore raw

Re: [patch 11/27] dm exception store: refactor zero_area

Quoted 40 lines · Mikulas Patocka
Quoted 36 lines · Greg KH
Quoted 14 lines · Greg KH

2.6.27-stable review patch. If anyone has any objections, please let us know.

------------------
From: Alasdair G Kergon <[email protected]>

commit 7c9e6c17325fab380fbe9c9787680ff7d4a51abd upstream

Use a separate buffer for writing zeroes to the on-disk snapshot exception store, make the updating of ps->current_area explicit and refactor the code in preparation for the fix in the next patch.

No functional change.

Quoted 7 lines
---
 drivers/md/dm-exception-store.c |  103 ++++++++++++++++++++++++++--------------
 1 file changed, 69 insertions(+), 34 deletions(-)

Oops, this patch causes a build error:

drivers/md/dm-exception-store.c:235: error: implicit declaration of function 'area_location' drivers/md/dm-exception-store.c:241: error: 'area' undeclared (first use in this function) drivers/md/dm-exception-store.c:241: error: (Each undeclared identifier is reported only once drivers/md/dm-exception-store.c:241: error: for each function it appears in.)

I'll drop this one, and the follow-on dm-exception-store.c patch as well, as that was the only reason this patch was added.

If you want to redo these two patches, and get them into the 2.6.27-stable tree, please do so and send them to [email protected].

Quoted 6 lines
Quoted 3 lines

thanks,

greg k-h

You should apply this one patch before:
ftp://ftp.kernel.org/pub/linux/kernel/people/agk/patches/2.6/editing/dm-exception-store-introduce-area_location-function.patch

Hm, so we need 2 "cleanup" patches to get one tiny fix in a third patch? Is it worth it? If so, care to resend these three to [email protected] or possibly, just backport what you really need in the third one, with the needed first 2 patches merged into it in one patch to get it all in a simpler way?

thanks,

greg k-h