2009-09-05 00:33:47

by Greg KH

[permalink] [raw]
Subject: [patch 00/71] 2.6.30.6-stable review

This is the start of the stable review cycle for the 2.6.30.6 release.
There are 71 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, Sept 6, 21:00:00 UTC. Anything
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.30.6-rc1.gz
and the diffstat can be found below.

thanks,

greg k-h

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

Makefile | 2 +-
arch/ia64/kernel/pci-dma.c | 5 -
arch/powerpc/platforms/ps3/time.c | 4 +
arch/x86/include/asm/kvm_host.h | 3 +
arch/x86/include/asm/kvm_x86_emulate.h | 6 +
arch/x86/kernel/apic/ipi.c | 3 +
arch/x86/kernel/cpu/amd.c | 2 +-
arch/x86/kvm/mmu.c | 85 ++++++++++++-----
arch/x86/kvm/svm.c | 31 ++++++-
arch/x86/kvm/vmx.c | 42 +++++++--
arch/x86/kvm/x86.c | 70 +++++++++++++--
arch/x86/kvm/x86_emulate.c | 20 ++++
arch/x86/mm/tlb.c | 21 ++--
drivers/acpi/processor_thermal.c | 6 +-
drivers/acpi/processor_throttling.c | 26 +++---
drivers/ata/libata-core.c | 3 +
drivers/media/video/gspca/ov534.c | 4 +-
drivers/net/ehea/ehea.h | 2 +-
drivers/net/ehea/ehea_main.c | 3 +
drivers/net/wireless/ar9170/main.c | 5 +-
drivers/net/wireless/iwlwifi/iwl-rfkill.c | 26 +++--
drivers/net/wireless/iwlwifi/iwl-sta.c | 12 +++
drivers/net/wireless/rt2x00/rt2x00.h | 6 +-
drivers/platform/x86/wmi.c | 8 +-
drivers/scsi/mpt2sas/mpt2sas_base.c | 98 ++++++++++++++------
drivers/scsi/mpt2sas/mpt2sas_base.h | 2 +
drivers/scsi/mpt2sas/mpt2sas_config.c | 91 +++++-------------
drivers/scsi/mpt2sas/mpt2sas_scsih.c | 124 ++++++++++++++++++-------
drivers/usb/core/hcd.h | 4 +
drivers/usb/core/hub.c | 40 +++++---
drivers/usb/core/hub.h | 6 +-
drivers/usb/host/ehci-au1xxx.c | 2 +
drivers/usb/host/ehci-fsl.c | 2 +
drivers/usb/host/ehci-hcd.c | 5 +-
drivers/usb/host/ehci-ixp4xx.c | 2 +
drivers/usb/host/ehci-orion.c | 2 +
drivers/usb/host/ehci-pci.c | 2 +
drivers/usb/host/ehci-ppc-of.c | 2 +
drivers/usb/host/ehci-ps3.c | 2 +
drivers/usb/host/ehci-q.c | 97 ++++++++++++++-----
drivers/usb/host/ehci.h | 2 +
drivers/video/xen-fbfront.c | 8 +-
fs/buffer.c | 7 +-
fs/exec.c | 4 +-
fs/hugetlbfs/inode.c | 20 +++--
fs/inode.c | 40 +++++---
fs/ocfs2/aops.c | 66 ++++++++++----
fs/select.c | 1 +
fs/xfs/xfs_iget.c | 142 +++++++++++++++--------------
fs/xfs/xfs_inode.h | 17 ----
fs/xfs/xfs_log.c | 2 +-
include/acpi/processor.h | 5 +-
include/linux/bitmap.h | 18 ++--
include/linux/cpumask.h | 20 ++--
include/linux/fs.h | 5 +-
include/linux/hugetlb.h | 6 +-
include/linux/kvm_host.h | 1 +
init/main.c | 7 +-
ipc/shm.c | 8 +-
kernel/fork.c | 20 +---
kernel/kthread.c | 2 +-
kernel/signal.c | 15 ++--
lib/bitmap.c | 12 ++-
mm/page_alloc.c | 4 +-
net/appletalk/ddp.c | 1 +
net/can/raw.c | 1 +
net/econet/af_econet.c | 1 +
net/ipv4/ip_output.c | 2 +
net/ipv6/af_inet6.c | 4 +-
net/irda/af_irda.c | 1 +
net/llc/af_llc.c | 1 +
net/mac80211/agg-tx.c | 8 ++
net/netrom/af_netrom.c | 1 +
net/rose/af_rose.c | 1 +
net/sunrpc/clnt.c | 1 +
security/integrity/ima/ima_crypto.c | 6 +-
sound/core/pcm_lib.c | 39 ++------
sound/pci/hda/patch_realtek.c | 34 ++++---
virt/kvm/irq_comm.c | 4 +-
virt/kvm/kvm_main.c | 4 +
80 files changed, 896 insertions(+), 521 deletions(-)


2009-09-05 00:20:30

by Greg KH

[permalink] [raw]
Subject: [patch 01/71] ehea: Fix napi list corruption on ifconfig down

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

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

commit 357eb46d8f275b4e8484541234ea3ba06065e258 upstream.

This patch fixes the napi list handling when an ehea interface is shut
down to avoid corruption of the napi list.

Signed-off-by: Hannes Hering <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
drivers/net/ehea/ehea.h | 2 +-
drivers/net/ehea/ehea_main.c | 3 +++
2 files changed, 4 insertions(+), 1 deletion(-)

--- a/drivers/net/ehea/ehea.h
+++ b/drivers/net/ehea/ehea.h
@@ -40,7 +40,7 @@
#include <asm/io.h>

#define DRV_NAME "ehea"
-#define DRV_VERSION "EHEA_0101"
+#define DRV_VERSION "EHEA_0102"

/* eHEA capability flags */
#define DLPAR_PORT_ADD_REM 1
--- a/drivers/net/ehea/ehea_main.c
+++ b/drivers/net/ehea/ehea_main.c
@@ -1545,6 +1545,9 @@ static int ehea_clean_portres(struct ehe
{
int ret, i;

+ if (pr->qp)
+ netif_napi_del(&pr->napi);
+
ret = ehea_destroy_qp(pr->qp);

if (!ret) {

2009-09-05 00:20:33

by Greg KH

[permalink] [raw]
Subject: [patch 02/71] poll/select: initialize triggered field of struct poll_wqueues

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

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

commit b2add73dbf93fd50f00564d7abc3e2b9aa9dd20c upstream.

The triggered field of struct poll_wqueues introduced in commit
5f820f648c92a5ecc771a96b3c29aa6e90013bba ("poll: allow f_op->poll to
sleep").

It was first set to 1 in pollwake() (now __pollwake() ), tested and
later set to 0 in poll_schedule_timeout(), but not initialized before.

As a result when the process needs to sleep, triggered was likely to be
non-zero even if pollwake() is not called before the first
poll_schedule_timeout(), meaning schedule_hrtimeout_range() would not be
called and an extra loop calling all ->poll() would be done.

This patch initialize triggered to 0 in poll_initwait() so the ->poll()
are not called twice before the process goes to sleep when it needs to.

Signed-off-by: Guillaume Knispel <[email protected]>
Acked-by: Thomas Gleixner <[email protected]>
Acked-by: Tejun Heo <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
fs/select.c | 1 +
1 file changed, 1 insertion(+)

--- a/fs/select.c
+++ b/fs/select.c
@@ -110,6 +110,7 @@ void poll_initwait(struct poll_wqueues *
{
init_poll_funcptr(&pwq->pt, __pollwait);
pwq->polling_task = current;
+ pwq->triggered = 0;
pwq->error = 0;
pwq->table = NULL;
pwq->inline_index = 0;

2009-09-05 00:34:39

by Greg KH

[permalink] [raw]
Subject: [patch 03/71] Make bitmask and operators return a result code

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

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

commit f4b0373b26567cafd421d91101852ed7a34e9e94 upstream.

When 'and'ing two bitmasks (where 'andnot' is a variation on it), some
cases want to know whether the result is the empty set or not. In
particular, the TLB IPI sending code wants to do cpumask operations and
determine if there are any CPU's left in the final set.

So this just makes the bitmask (and cpumask) functions return a boolean
for whether the result has any bits set.

Signed-off-by: Linus Torvalds <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
include/linux/bitmap.h | 18 ++++++++----------
include/linux/cpumask.h | 20 ++++++++++----------
lib/bitmap.c | 12 ++++++++----
3 files changed, 26 insertions(+), 24 deletions(-)

--- a/include/linux/bitmap.h
+++ b/include/linux/bitmap.h
@@ -94,13 +94,13 @@ extern void __bitmap_shift_right(unsigne
const unsigned long *src, int shift, int bits);
extern void __bitmap_shift_left(unsigned long *dst,
const unsigned long *src, int shift, int bits);
-extern void __bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
+extern int __bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
const unsigned long *bitmap2, int bits);
extern void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
const unsigned long *bitmap2, int bits);
extern void __bitmap_xor(unsigned long *dst, const unsigned long *bitmap1,
const unsigned long *bitmap2, int bits);
-extern void __bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1,
+extern int __bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1,
const unsigned long *bitmap2, int bits);
extern int __bitmap_intersects(const unsigned long *bitmap1,
const unsigned long *bitmap2, int bits);
@@ -171,13 +171,12 @@ static inline void bitmap_copy(unsigned
}
}

-static inline void bitmap_and(unsigned long *dst, const unsigned long *src1,
+static inline int bitmap_and(unsigned long *dst, const unsigned long *src1,
const unsigned long *src2, int nbits)
{
if (small_const_nbits(nbits))
- *dst = *src1 & *src2;
- else
- __bitmap_and(dst, src1, src2, nbits);
+ return (*dst = *src1 & *src2) != 0;
+ return __bitmap_and(dst, src1, src2, nbits);
}

static inline void bitmap_or(unsigned long *dst, const unsigned long *src1,
@@ -198,13 +197,12 @@ static inline void bitmap_xor(unsigned l
__bitmap_xor(dst, src1, src2, nbits);
}

-static inline void bitmap_andnot(unsigned long *dst, const unsigned long *src1,
+static inline int bitmap_andnot(unsigned long *dst, const unsigned long *src1,
const unsigned long *src2, int nbits)
{
if (small_const_nbits(nbits))
- *dst = *src1 & ~(*src2);
- else
- __bitmap_andnot(dst, src1, src2, nbits);
+ return (*dst = *src1 & ~(*src2)) != 0;
+ return __bitmap_andnot(dst, src1, src2, nbits);
}

static inline void bitmap_complement(unsigned long *dst, const unsigned long *src,
--- a/include/linux/cpumask.h
+++ b/include/linux/cpumask.h
@@ -43,10 +43,10 @@
* int cpu_isset(cpu, mask) true iff bit 'cpu' set in mask
* int cpu_test_and_set(cpu, mask) test and set bit 'cpu' in mask
*
- * void cpus_and(dst, src1, src2) dst = src1 & src2 [intersection]
+ * int cpus_and(dst, src1, src2) dst = src1 & src2 [intersection]
* void cpus_or(dst, src1, src2) dst = src1 | src2 [union]
* void cpus_xor(dst, src1, src2) dst = src1 ^ src2
- * void cpus_andnot(dst, src1, src2) dst = src1 & ~src2
+ * int cpus_andnot(dst, src1, src2) dst = src1 & ~src2
* void cpus_complement(dst, src) dst = ~src
*
* int cpus_equal(mask1, mask2) Does mask1 == mask2?
@@ -179,10 +179,10 @@ static inline int __cpu_test_and_set(int
}

#define cpus_and(dst, src1, src2) __cpus_and(&(dst), &(src1), &(src2), NR_CPUS)
-static inline void __cpus_and(cpumask_t *dstp, const cpumask_t *src1p,
+static inline int __cpus_and(cpumask_t *dstp, const cpumask_t *src1p,
const cpumask_t *src2p, int nbits)
{
- bitmap_and(dstp->bits, src1p->bits, src2p->bits, nbits);
+ return bitmap_and(dstp->bits, src1p->bits, src2p->bits, nbits);
}

#define cpus_or(dst, src1, src2) __cpus_or(&(dst), &(src1), &(src2), NR_CPUS)
@@ -201,10 +201,10 @@ static inline void __cpus_xor(cpumask_t

#define cpus_andnot(dst, src1, src2) \
__cpus_andnot(&(dst), &(src1), &(src2), NR_CPUS)
-static inline void __cpus_andnot(cpumask_t *dstp, const cpumask_t *src1p,
+static inline int __cpus_andnot(cpumask_t *dstp, const cpumask_t *src1p,
const cpumask_t *src2p, int nbits)
{
- bitmap_andnot(dstp->bits, src1p->bits, src2p->bits, nbits);
+ return bitmap_andnot(dstp->bits, src1p->bits, src2p->bits, nbits);
}

#define cpus_complement(dst, src) __cpus_complement(&(dst), &(src), NR_CPUS)
@@ -738,11 +738,11 @@ static inline void cpumask_clear(struct
* @src1p: the first input
* @src2p: the second input
*/
-static inline void cpumask_and(struct cpumask *dstp,
+static inline int cpumask_and(struct cpumask *dstp,
const struct cpumask *src1p,
const struct cpumask *src2p)
{
- bitmap_and(cpumask_bits(dstp), cpumask_bits(src1p),
+ return bitmap_and(cpumask_bits(dstp), cpumask_bits(src1p),
cpumask_bits(src2p), nr_cpumask_bits);
}

@@ -779,11 +779,11 @@ static inline void cpumask_xor(struct cp
* @src1p: the first input
* @src2p: the second input
*/
-static inline void cpumask_andnot(struct cpumask *dstp,
+static inline int cpumask_andnot(struct cpumask *dstp,
const struct cpumask *src1p,
const struct cpumask *src2p)
{
- bitmap_andnot(cpumask_bits(dstp), cpumask_bits(src1p),
+ return bitmap_andnot(cpumask_bits(dstp), cpumask_bits(src1p),
cpumask_bits(src2p), nr_cpumask_bits);
}

--- a/lib/bitmap.c
+++ b/lib/bitmap.c
@@ -179,14 +179,16 @@ void __bitmap_shift_left(unsigned long *
}
EXPORT_SYMBOL(__bitmap_shift_left);

-void __bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
+int __bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
const unsigned long *bitmap2, int bits)
{
int k;
int nr = BITS_TO_LONGS(bits);
+ unsigned long result = 0;

for (k = 0; k < nr; k++)
- dst[k] = bitmap1[k] & bitmap2[k];
+ result |= (dst[k] = bitmap1[k] & bitmap2[k]);
+ return result != 0;
}
EXPORT_SYMBOL(__bitmap_and);

@@ -212,14 +214,16 @@ void __bitmap_xor(unsigned long *dst, co
}
EXPORT_SYMBOL(__bitmap_xor);

-void __bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1,
+int __bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1,
const unsigned long *bitmap2, int bits)
{
int k;
int nr = BITS_TO_LONGS(bits);
+ unsigned long result = 0;

for (k = 0; k < nr; k++)
- dst[k] = bitmap1[k] & ~bitmap2[k];
+ result |= (dst[k] = bitmap1[k] & ~bitmap2[k]);
+ return result != 0;
}
EXPORT_SYMBOL(__bitmap_andnot);


2009-09-05 00:33:45

by Greg KH

[permalink] [raw]
Subject: [patch 04/71] x86: dont send an IPI to the empty set of CPUs

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

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

commit 83d349f35e1ae72268c5104dbf9ab2ae635425d4 upstream.

The default_send_IPI_mask_logical() function uses the "flat" APIC mode
to send an IPI to a set of CPU's at once, but if that set happens to be
empty, some older local APIC's will apparently be rather unhappy. So
just warn if a caller gives us an empty mask, and ignore it.

This fixes a regression in 2.6.30.x, due to commit 4595f9620 ("x86:
change flush_tlb_others to take a const struct cpumask"), documented
here:

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

which causes a silent lock-up. It only seems to happen on PPro, P2, P3
and Athlon XP cores. Most developers sadly (or not so sadly, if you're
a developer..) have more modern CPU's. Also, on x86-64 we don't use the
flat APIC mode, so it would never trigger there even if the APIC didn't
like sending an empty IPI mask.

Reported-by: Pavel Vilim <[email protected]>
Reported-and-tested-by: Thomas Björnell <[email protected]>
Reported-and-tested-by: Martin Rogge <[email protected]>
Cc: Mike Travis <[email protected]>
Cc: Ingo Molnar <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
arch/x86/kernel/apic/ipi.c | 3 +++
1 file changed, 3 insertions(+)

--- a/arch/x86/kernel/apic/ipi.c
+++ b/arch/x86/kernel/apic/ipi.c
@@ -106,6 +106,9 @@ void default_send_IPI_mask_logical(const
unsigned long mask = cpumask_bits(cpumask)[0];
unsigned long flags;

+ if (WARN_ONCE(!mask, "empty IPI mask"))
+ return;
+
local_irq_save(flags);
WARN_ON(mask & ~cpumask_bits(cpu_online_mask)[0]);
__default_send_IPI_dest_field(mask, vector, apic->dest_logical);

2009-09-05 00:33:51

by Greg KH

[permalink] [raw]
Subject: [patch 05/71] x86: dont call ->send_IPI_mask() with an empty mask

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

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

commit b04e6373d694e977c95ae0ae000e2c1e2cf92d73 upstream.

As noted in 83d349f35e1ae72268c5104dbf9ab2ae635425d4 ("x86: don't send
an IPI to the empty set of CPU's"), some APIC's will be very unhappy
with an empty destination mask. That commit added a WARN_ON() for that
case, and avoided the resulting problem, but didn't fix the underlying
reason for why those empty mask cases happened.

This fixes that, by checking the result of 'cpumask_andnot()' of the
current CPU actually has any other CPU's left in the set of CPU's to be
sent a TLB flush, and not calling down to the IPI code if the mask is
empty.

The reason this started happening at all is that we started passing just
the CPU mask pointers around in commit 4595f9620 ("x86: change
flush_tlb_others to take a const struct cpumask"), and when we did that,
the cpumask was no longer thread-local.

Before that commit, flush_tlb_mm() used to create it's own copy of
'mm->cpu_vm_mask' and pass that copy down to the low-level flush
routines after having tested that it was not empty. But after changing
it to just pass down the CPU mask pointer, the lower level TLB flush
routines would now get a pointer to that 'mm->cpu_vm_mask', and that
could still change - and become empty - after the test due to other
CPU's having flushed their own TLB's.

See

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

for details.

Tested-by: Thomas Björnell <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
arch/x86/mm/tlb.c | 21 ++++++++++-----------
1 file changed, 10 insertions(+), 11 deletions(-)

--- a/arch/x86/mm/tlb.c
+++ b/arch/x86/mm/tlb.c
@@ -183,18 +183,17 @@ static void flush_tlb_others_ipi(const s

f->flush_mm = mm;
f->flush_va = va;
- cpumask_andnot(to_cpumask(f->flush_cpumask),
- cpumask, cpumask_of(smp_processor_id()));
+ if (cpumask_andnot(to_cpumask(f->flush_cpumask), cpumask, cpumask_of(smp_processor_id()))) {
+ /*
+ * We have to send the IPI only to
+ * CPUs affected.
+ */
+ apic->send_IPI_mask(to_cpumask(f->flush_cpumask),
+ INVALIDATE_TLB_VECTOR_START + sender);

- /*
- * We have to send the IPI only to
- * CPUs affected.
- */
- apic->send_IPI_mask(to_cpumask(f->flush_cpumask),
- INVALIDATE_TLB_VECTOR_START + sender);
-
- while (!cpumask_empty(to_cpumask(f->flush_cpumask)))
- cpu_relax();
+ while (!cpumask_empty(to_cpumask(f->flush_cpumask)))
+ cpu_relax();
+ }

f->flush_mm = NULL;
f->flush_va = 0;

2009-09-05 00:34:10

by Greg KH

[permalink] [raw]
Subject: [patch 06/71] mm: build_zonelists(): move clear node_load[] to __build_all_zonelists()

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

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

commit 7f9cfb31030737a7fc9a1cbca3fd01bec184c849 upstream.

If node_load[] is cleared everytime build_zonelists() is
called,node_load[] will have no help to find the next node that should
appear in the given node's fallback list.

Because of the bug, zonelist's node_order is not calculated as expected.
This bug affects on big machine, which has asynmetric node distance.

[synmetric NUMA's node distance]
0 1 2
0 10 12 12
1 12 10 12
2 12 12 10

[asynmetric NUMA's node distance]
0 1 2
0 10 12 20
1 12 10 14
2 20 14 10

This (my bug) is very old but no one has reported this for a long time.
Maybe because the number of asynmetric NUMA is very small and they use
cpuset for customizing node memory allocation fallback.

[[email protected]: fix CONFIG_NUMA=n build]
Signed-off-by: Bo Liu <[email protected]>
Reviewed-by: KAMEZAWA Hiroyuki <[email protected]>
Cc: Mel Gorman <[email protected]>
Cc: Christoph Lameter <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
mm/page_alloc.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)

--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -2342,7 +2342,6 @@ static void build_zonelists(pg_data_t *p
prev_node = local_node;
nodes_clear(used_mask);

- memset(node_load, 0, sizeof(node_load));
memset(node_order, 0, sizeof(node_order));
j = 0;

@@ -2451,6 +2450,9 @@ static int __build_all_zonelists(void *d
{
int nid;

+#ifdef CONFIG_NUMA
+ memset(node_load, 0, sizeof(node_load));
+#endif
for_each_online_node(nid) {
pg_data_t *pgdat = NODE_DATA(nid);


2009-09-05 00:33:18

by Greg KH

[permalink] [raw]
Subject: [patch 07/71] rt2x00: fix memory corruption in rf cache, add a sanity check

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

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

commit 6b26dead3ce97d016b57724b01974d5ca5c84bd5 upstream.

Change rt2x00_rf_read() and rt2x00_rf_write() to subtract 1 from the rf
register number. This is needed because the rf registers are enumerated
starting with one. The size of the rf register cache is just enough to
hold all registers, so writing to the highest register was corrupting
memory. Add a check to make sure that the rf register number is valid.

Signed-off-by: Pavel Roskin <[email protected]>
Acked-by: Ivo van Doorn <[email protected]>
Signed-off-by: John W. Linville <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
drivers/net/wireless/rt2x00/rt2x00.h | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)

--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -814,13 +814,15 @@ struct rt2x00_dev {
static inline void rt2x00_rf_read(struct rt2x00_dev *rt2x00dev,
const unsigned int word, u32 *data)
{
- *data = rt2x00dev->rf[word];
+ BUG_ON(word < 1 || word > rt2x00dev->ops->rf_size / sizeof(u32));
+ *data = rt2x00dev->rf[word - 1];
}

static inline void rt2x00_rf_write(struct rt2x00_dev *rt2x00dev,
const unsigned int word, u32 data)
{
- rt2x00dev->rf[word] = data;
+ BUG_ON(word < 1 || word > rt2x00dev->ops->rf_size / sizeof(u32));
+ rt2x00dev->rf[word - 1] = data;
}

/*

2009-09-05 00:20:44

by Greg KH

[permalink] [raw]
Subject: [patch 08/71] mac80211: fix panic when splicing unprepared TIDs

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

------------------
From: Luis R. Rodriguez <[email protected]>

commit 416fbdff2137e8d8cc8f23f517bee3a26b11526f upstream.

We splice skbs from the pending queue for a TID
onto the local pending queue when tearing down a
block ack request. This is not necessary unless we
actually have received a request to start a block ack
request (rate control, for example). If we never received
that request we should not be splicing the tid pending
queue as it would be null, causing a panic.

Not sure yet how exactly we allowed through a call when the
tid state does not have at least HT_ADDBA_REQUESTED_MSK set,
that will require some further review as it is not quite
obvious.

For more information see the bug report:

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

This fixes this oops:

BUG: unable to handle kernel NULL pointer dereference at 00000030
IP: [<f8806c70>] ieee80211_agg_splice_packets+0x40/0xc0 [mac80211]
*pdpt = 0000000002d1e001 *pde = 0000000000000000
Thread overran stack, or stack corrupted
Oops: 0000 [#1] SMP
last sysfs file: /sys/module/aes_generic/initstate
Modules linked in: <bleh>

Pid: 0, comm: swapper Not tainted (2.6.31-rc5-wl #2) Dell DV051
EIP: 0060:[<f8806c70>] EFLAGS: 00010292 CPU: 0
EIP is at ieee80211_agg_splice_packets+0x40/0xc0 [mac80211]
EAX: 00000030 EBX: 0000004c ECX: 00000003 EDX: 00000000
ESI: c1c98000 EDI: f745a1c0 EBP: c076be58 ESP: c076be38
DS: 007b ES: 007b FS: 00d8 GS: 0000 SS: 0068
Process swapper (pid: 0, ti=c076a000 task=c0709160 task.ti=c076a000)
Stack: <bleh2>
Call Trace:
[<f8806edb>] ? ieee80211_stop_tx_ba_cb+0xab/0x150 [mac80211]
[<f8802f1e>] ? ieee80211_tasklet_handler+0xce/0x110 [mac80211]
[<c04862ff>] ? net_rx_action+0xef/0x1d0
[<c0149378>] ? tasklet_action+0x58/0xc0
[<c014a0f2>] ? __do_softirq+0xc2/0x190
[<c018eb48>] ? handle_IRQ_event+0x58/0x140
[<c01205fe>] ? ack_apic_level+0x7e/0x270
[<c014a1fd>] ? do_softirq+0x3d/0x40
[<c014a345>] ? irq_exit+0x65/0x90
[<c010a6af>] ? do_IRQ+0x4f/0xc0
[<c014a35d>] ? irq_exit+0x7d/0x90
[<c011d547>] ? smp_apic_timer_interrupt+0x57/0x90
[<c01094a9>] ? common_interrupt+0x29/0x30
[<c010fd9e>] ? mwait_idle+0xbe/0x100
[<c0107e42>] ? cpu_idle+0x52/0x90
[<c054b1a5>] ? rest_init+0x55/0x60
[<c077492d>] ? start_kernel+0x315/0x37d
[<c07743ce>] ? unknown_bootoption+0x0/0x1f9
[<c0774099>] ? i386_start_kernel+0x79/0x81
Code: <bleh3>
EIP: [<f8806c70>] ieee80211_agg_splice_packets+0x40/0xc0 [mac80211] SS:ESP 0068:c076be38
CR2: 0000000000000030

Testedy-by: Jack Lau <[email protected]>
Signed-off-by: Luis R. Rodriguez <[email protected]>
Signed-off-by: John W. Linville <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
net/mac80211/agg-tx.c | 8 ++++++++
1 file changed, 8 insertions(+)

--- a/net/mac80211/agg-tx.c
+++ b/net/mac80211/agg-tx.c
@@ -376,6 +376,14 @@ static void ieee80211_agg_splice_packets
&local->hw, queue,
IEEE80211_QUEUE_STOP_REASON_AGGREGATION);

+ if (!(sta->ampdu_mlme.tid_state_tx[tid] & HT_ADDBA_REQUESTED_MSK))
+ return;
+
+ if (WARN(!sta->ampdu_mlme.tid_tx[tid],
+ "TID %d gone but expected when splicing aggregates from"
+ "the pending queue\n", tid))
+ return;
+
if (!skb_queue_empty(&sta->ampdu_mlme.tid_tx[tid]->pending)) {
spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
/* mark queue as pending, it is stopped already */

2009-09-05 00:20:42

by Greg KH

[permalink] [raw]
Subject: [patch 09/71] Re-introduce page mapping check in mark_buffer_dirty()

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

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

commit 8e9d78edea3ce5c0036f85b93091483f2f15443a upstream.

In commit a8e7d49aa7be728c4ae241a75a2a124cdcabc0c5 ("Fix race in
create_empty_buffers() vs __set_page_dirty_buffers()"), I removed a test
for a NULL page mapping unintentionally when some of the code inside
__set_page_dirty() was moved to the callers.

That removal generally didn't matter, since a filesystem would serialize
truncation (which clears the page mapping) against writing (which marks
the buffer dirty), so locking at a higher level (either per-page or an
inode at a time) should mean that the buffer page would be stable. And
indeed, nothing bad seemed to happen.

Except it turns out that apparently reiserfs does something odd when
under load and writing out the journal, and we have a number of bugzilla
entries that look similar:

http://bugzilla.kernel.org/show_bug.cgi?id=13556
http://bugzilla.kernel.org/show_bug.cgi?id=13756
http://bugzilla.kernel.org/show_bug.cgi?id=13876

and it looks like reiserfs depended on that check (the common theme
seems to be "data=journal", and a journal writeback during a truncate).

I suspect reiserfs should have some additional locking, but in the
meantime this should get us back to the pre-2.6.29 behavior.

Pattern-pointed-out-by: Roland Kletzing <[email protected]>
Cc: Jeff Mahoney <[email protected]>
Cc: Nick Piggin <[email protected]>
Cc: Al Viro <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
fs/buffer.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)

--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -1165,8 +1165,11 @@ void mark_buffer_dirty(struct buffer_hea

if (!test_set_buffer_dirty(bh)) {
struct page *page = bh->b_page;
- if (!TestSetPageDirty(page))
- __set_page_dirty(page, page_mapping(page), 0);
+ if (!TestSetPageDirty(page)) {
+ struct address_space *mapping = page_mapping(page);
+ if (mapping)
+ __set_page_dirty(page, mapping, 0);
+ }
}
}


2009-09-05 00:20:51

by Greg KH

[permalink] [raw]
Subject: [patch 10/71] mm: fix hugetlb bug due to user_shm_unlock call

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

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

commit 353d5c30c666580347515da609dd74a2b8e9b828 upstream.

2.6.30's commit 8a0bdec194c21c8fdef840989d0d7b742bb5d4bc removed
user_shm_lock() calls in hugetlb_file_setup() but left the
user_shm_unlock call in shm_destroy().

In detail:
Assume that can_do_hugetlb_shm() returns true and hence user_shm_lock()
is not called in hugetlb_file_setup(). However, user_shm_unlock() is
called in any case in shm_destroy() and in the following
atomic_dec_and_lock(&up->__count) in free_uid() is executed and if
up->__count gets zero, also cleanup_user_struct() is scheduled.

Note that sched_destroy_user() is empty if CONFIG_USER_SCHED is not set.
However, the ref counter up->__count gets unexpectedly non-positive and
the corresponding structs are freed even though there are live
references to them, resulting in a kernel oops after a lots of
shmget(SHM_HUGETLB)/shmctl(IPC_RMID) cycles and CONFIG_USER_SCHED set.

Hugh changed Stefan's suggested patch: can_do_hugetlb_shm() at the
time of shm_destroy() may give a different answer from at the time
of hugetlb_file_setup(). And fixed newseg()'s no_id error path,
which has missed user_shm_unlock() ever since it came in 2.6.9.

Reported-by: Stefan Huber <[email protected]>
Signed-off-by: Hugh Dickins <[email protected]>
Tested-by: Stefan Huber <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
fs/hugetlbfs/inode.c | 20 ++++++++++++--------
include/linux/hugetlb.h | 6 ++++--
ipc/shm.c | 8 +++++---
3 files changed, 21 insertions(+), 13 deletions(-)

--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -934,26 +934,28 @@ static int can_do_hugetlb_shm(void)
return capable(CAP_IPC_LOCK) || in_group_p(sysctl_hugetlb_shm_group);
}

-struct file *hugetlb_file_setup(const char *name, size_t size, int acctflag)
+struct file *hugetlb_file_setup(const char *name, size_t size, int acctflag,
+ struct user_struct **user)
{
int error = -ENOMEM;
- int unlock_shm = 0;
struct file *file;
struct inode *inode;
struct dentry *dentry, *root;
struct qstr quick_string;
- struct user_struct *user = current_user();

+ *user = NULL;
if (!hugetlbfs_vfsmount)
return ERR_PTR(-ENOENT);

if (!can_do_hugetlb_shm()) {
- if (user_shm_lock(size, user)) {
- unlock_shm = 1;
+ *user = current_user();
+ if (user_shm_lock(size, *user)) {
WARN_ONCE(1,
"Using mlock ulimits for SHM_HUGETLB deprecated\n");
- } else
+ } else {
+ *user = NULL;
return ERR_PTR(-EPERM);
+ }
}

root = hugetlbfs_vfsmount->mnt_root;
@@ -994,8 +996,10 @@ out_inode:
out_dentry:
dput(dentry);
out_shm_unlock:
- if (unlock_shm)
- user_shm_unlock(size, user);
+ if (*user) {
+ user_shm_unlock(size, *user);
+ *user = NULL;
+ }
return ERR_PTR(error);
}

--- a/include/linux/hugetlb.h
+++ b/include/linux/hugetlb.h
@@ -10,6 +10,7 @@
#include <asm/tlbflush.h>

struct ctl_table;
+struct user_struct;

static inline int is_vm_hugetlb_page(struct vm_area_struct *vma)
{
@@ -139,7 +140,8 @@ static inline struct hugetlbfs_sb_info *

extern const struct file_operations hugetlbfs_file_operations;
extern struct vm_operations_struct hugetlb_vm_ops;
-struct file *hugetlb_file_setup(const char *name, size_t, int);
+struct file *hugetlb_file_setup(const char *name, size_t size, int acct,
+ struct user_struct **user);
int hugetlb_get_quota(struct address_space *mapping, long delta);
void hugetlb_put_quota(struct address_space *mapping, long delta);

@@ -161,7 +163,7 @@ static inline void set_file_hugepages(st

#define is_file_hugepages(file) 0
#define set_file_hugepages(file) BUG()
-#define hugetlb_file_setup(name,size,acctflag) ERR_PTR(-ENOSYS)
+#define hugetlb_file_setup(name,size,acct,user) ERR_PTR(-ENOSYS)

#endif /* !CONFIG_HUGETLBFS */

--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -174,7 +174,7 @@ static void shm_destroy(struct ipc_names
shm_unlock(shp);
if (!is_file_hugepages(shp->shm_file))
shmem_lock(shp->shm_file, 0, shp->mlock_user);
- else
+ else if (shp->mlock_user)
user_shm_unlock(shp->shm_file->f_path.dentry->d_inode->i_size,
shp->mlock_user);
fput (shp->shm_file);
@@ -369,8 +369,8 @@ static int newseg(struct ipc_namespace *
/* hugetlb_file_setup applies strict accounting */
if (shmflg & SHM_NORESERVE)
acctflag = VM_NORESERVE;
- file = hugetlb_file_setup(name, size, acctflag);
- shp->mlock_user = current_user();
+ file = hugetlb_file_setup(name, size, acctflag,
+ &shp->mlock_user);
} else {
/*
* Do not allow no accounting for OVERCOMMIT_NEVER, even
@@ -411,6 +411,8 @@ static int newseg(struct ipc_namespace *
return error;

no_id:
+ if (shp->mlock_user) /* shmflg & SHM_HUGETLB case */
+ user_shm_unlock(size, shp->mlock_user);
fput(file);
no_file:
security_shm_free(shp);

2009-09-05 00:32:31

by Greg KH

[permalink] [raw]
Subject: [patch 11/71] ima: hashing large files bug fix

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

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

commit 16bfa38b1936212428cb38fbfbbb8f6c62b8d81f upstream.

Hashing files larger than INT_MAX causes process to loop.
Dependent on redefining kernel_read() offset type to loff_t.

(http://bugzilla.kernel.org/show_bug.cgi?id=13909)

Signed-off-by: Mimi Zohar <[email protected]>
Signed-off-by: James Morris <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
security/integrity/ima/ima_crypto.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)

--- a/security/integrity/ima/ima_crypto.c
+++ b/security/integrity/ima/ima_crypto.c
@@ -45,9 +45,9 @@ int ima_calc_hash(struct file *file, cha
{
struct hash_desc desc;
struct scatterlist sg[1];
- loff_t i_size;
+ loff_t i_size, offset = 0;
char *rbuf;
- int rc, offset = 0;
+ int rc;

rc = init_desc(&desc);
if (rc != 0)
@@ -67,6 +67,8 @@ int ima_calc_hash(struct file *file, cha
rc = rbuf_len;
break;
}
+ if (rbuf_len == 0)
+ break;
offset += rbuf_len;
sg_init_one(sg, rbuf, rbuf_len);


2009-09-05 00:32:04

by Greg KH

[permalink] [raw]
Subject: [patch 12/71] kernel_read: redefine offset type

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

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

commit 6777d773a463ac045d333b989d4e44660f8d92ad upstream.

vfs_read() offset is defined as loff_t, but kernel_read()
offset is only defined as unsigned long. Redefine
kernel_read() offset as loff_t.

Signed-off-by: Mimi Zohar <[email protected]>
Signed-off-by: James Morris <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
fs/exec.c | 4 ++--
include/linux/fs.h | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)

--- a/fs/exec.c
+++ b/fs/exec.c
@@ -677,8 +677,8 @@ exit:
}
EXPORT_SYMBOL(open_exec);

-int kernel_read(struct file *file, unsigned long offset,
- char *addr, unsigned long count)
+int kernel_read(struct file *file, loff_t offset,
+ char *addr, unsigned long count)
{
mm_segment_t old_fs;
loff_t pos = offset;
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2121,7 +2121,7 @@ extern struct file *do_filp_open(int dfd
int open_flag, int mode, int acc_mode);
extern int may_open(struct path *, int, int);

-extern int kernel_read(struct file *, unsigned long, char *, unsigned long);
+extern int kernel_read(struct file *, loff_t, char *, unsigned long);
extern struct file * open_exec(const char *);

/* fs/dcache.c -- generic fs support functions */

2009-09-05 00:20:57

by Greg KH

[permalink] [raw]
Subject: [patch 13/71] tracing: Fix too large stack usage in do_one_initcall()

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

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

commit 4a683bf94b8a10e2bb0da07aec3ac0a55e5de61f upstream.

One of my testboxes triggered this nasty stack overflow crash
during SCSI probing:

[ 5.874004] sd 0:0:0:0: [sda] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
[ 5.875004] device: 'sda': device_add
[ 5.878004] BUG: unable to handle kernel NULL pointer dereference at 00000a0c
[ 5.878004] IP: [<b1008321>] print_context_stack+0x81/0x110
[ 5.878004] *pde = 00000000
[ 5.878004] Thread overran stack, or stack corrupted
[ 5.878004] Oops: 0000 [#1] PREEMPT SMP DEBUG_PAGEALLOC
[ 5.878004] last sysfs file:
[ 5.878004]
[ 5.878004] Pid: 1, comm: swapper Not tainted (2.6.31-rc6-tip-01272-g9919e28-dirty #5685)
[ 5.878004] EIP: 0060:[<b1008321>] EFLAGS: 00010083 CPU: 0
[ 5.878004] EIP is at print_context_stack+0x81/0x110
[ 5.878004] EAX: cf8a3000 EBX: cf8a3fe4 ECX: 00000049 EDX: 00000000
[ 5.878004] ESI: b1cfce84 EDI: 00000000 EBP: cf8a3018 ESP: cf8a2ff4
[ 5.878004] DS: 007b ES: 007b FS: 00d8 GS: 0000 SS: 0068
[ 5.878004] Process swapper (pid: 1, ti=cf8a2000 task=cf8a8000 task.ti=cf8a3000)
[ 5.878004] Stack:
[ 5.878004] b1004867 fffff000 cf8a3ffc
[ 5.878004] Call Trace:
[ 5.878004] [<b1004867>] ? kernel_thread_helper+0x7/0x10
[ 5.878004] BUG: unable to handle kernel NULL pointer dereference at 00000a0c
[ 5.878004] IP: [<b1008321>] print_context_stack+0x81/0x110
[ 5.878004] *pde = 00000000
[ 5.878004] Thread overran stack, or stack corrupted
[ 5.878004] Oops: 0000 [#2] PREEMPT SMP DEBUG_PAGEALLOC

The oops did not reveal any more details about the real stack
that we have and the system got into an infinite loop of
recursive pagefaults.

So i booted with CONFIG_STACK_TRACER=y and the 'stacktrace' boot
parameter. The box did not crash (timings/conditions probably
changed a tiny bit to trigger the catastrophic crash), but the
/debug/tracing/stack_trace file was rather revealing:

Depth Size Location (72 entries)
----- ---- --------
0) 3704 52 __change_page_attr+0xb8/0x290
1) 3652 24 __change_page_attr_set_clr+0x43/0x90
2) 3628 60 kernel_map_pages+0x108/0x120
3) 3568 40 prep_new_page+0x7d/0x130
4) 3528 84 get_page_from_freelist+0x106/0x420
5) 3444 116 __alloc_pages_nodemask+0xd7/0x550
6) 3328 36 allocate_slab+0xb1/0x100
7) 3292 36 new_slab+0x1c/0x160
8) 3256 36 __slab_alloc+0x133/0x2b0
9) 3220 4 kmem_cache_alloc+0x1bb/0x1d0
10) 3216 108 create_object+0x28/0x250
11) 3108 40 kmemleak_alloc+0x81/0xc0
12) 3068 24 kmem_cache_alloc+0x162/0x1d0
13) 3044 52 scsi_pool_alloc_command+0x29/0x70
14) 2992 20 scsi_host_alloc_command+0x22/0x70
15) 2972 24 __scsi_get_command+0x1b/0x90
16) 2948 28 scsi_get_command+0x35/0x90
17) 2920 24 scsi_setup_blk_pc_cmnd+0xd4/0x100
18) 2896 128 sd_prep_fn+0x332/0xa70
19) 2768 36 blk_peek_request+0xe7/0x1d0
20) 2732 56 scsi_request_fn+0x54/0x520
21) 2676 12 __generic_unplug_device+0x2b/0x40
22) 2664 24 blk_execute_rq_nowait+0x59/0x80
23) 2640 172 blk_execute_rq+0x6b/0xb0
24) 2468 32 scsi_execute+0xe0/0x140
25) 2436 64 scsi_execute_req+0x152/0x160
26) 2372 60 scsi_vpd_inquiry+0x6c/0x90
27) 2312 44 scsi_get_vpd_page+0x112/0x160
28) 2268 52 sd_revalidate_disk+0x1df/0x320
29) 2216 92 rescan_partitions+0x98/0x330
30) 2124 52 __blkdev_get+0x309/0x350
31) 2072 8 blkdev_get+0xf/0x20
32) 2064 44 register_disk+0xff/0x120
33) 2020 36 add_disk+0x6e/0xb0
34) 1984 44 sd_probe_async+0xfb/0x1d0
35) 1940 44 __async_schedule+0xf4/0x1b0
36) 1896 8 async_schedule+0x12/0x20
37) 1888 60 sd_probe+0x305/0x360
38) 1828 44 really_probe+0x63/0x170
39) 1784 36 driver_probe_device+0x5d/0x60
40) 1748 16 __device_attach+0x49/0x50
41) 1732 32 bus_for_each_drv+0x5b/0x80
42) 1700 24 device_attach+0x6b/0x70
43) 1676 16 bus_attach_device+0x47/0x60
44) 1660 76 device_add+0x33d/0x400
45) 1584 52 scsi_sysfs_add_sdev+0x6a/0x2c0
46) 1532 108 scsi_add_lun+0x44b/0x460
47) 1424 116 scsi_probe_and_add_lun+0x182/0x4e0
48) 1308 36 __scsi_add_device+0xd9/0xe0
49) 1272 44 ata_scsi_scan_host+0x10b/0x190
50) 1228 24 async_port_probe+0x96/0xd0
51) 1204 44 __async_schedule+0xf4/0x1b0
52) 1160 8 async_schedule+0x12/0x20
53) 1152 48 ata_host_register+0x171/0x1d0
54) 1104 60 ata_pci_sff_activate_host+0xf3/0x230
55) 1044 44 ata_pci_sff_init_one+0xea/0x100
56) 1000 48 amd_init_one+0xb2/0x190
57) 952 8 local_pci_probe+0x13/0x20
58) 944 32 pci_device_probe+0x68/0x90
59) 912 44 really_probe+0x63/0x170
60) 868 36 driver_probe_device+0x5d/0x60
61) 832 20 __driver_attach+0x89/0xa0
62) 812 32 bus_for_each_dev+0x5b/0x80
63) 780 12 driver_attach+0x1e/0x20
64) 768 72 bus_add_driver+0x14b/0x2d0
65) 696 36 driver_register+0x6e/0x150
66) 660 20 __pci_register_driver+0x53/0xc0
67) 640 8 amd_init+0x14/0x16
68) 632 572 do_one_initcall+0x2b/0x1d0
69) 60 12 do_basic_setup+0x56/0x6a
70) 48 20 kernel_init+0x84/0xce
71) 28 28 kernel_thread_helper+0x7/0x10

There's a lot of fat functions on that stack trace, but
the largest of all is do_one_initcall(). This is due to
the boot trace entry variables being on the stack.

Fixing this is relatively easy, initcalls are fundamentally
serialized, so we can move the local variables to file scope.

Note that this large stack footprint was present for a
couple of months already - what pushed my system over
the edge was the addition of kmemleak to the call-chain:

6) 3328 36 allocate_slab+0xb1/0x100
7) 3292 36 new_slab+0x1c/0x160
8) 3256 36 __slab_alloc+0x133/0x2b0
9) 3220 4 kmem_cache_alloc+0x1bb/0x1d0
10) 3216 108 create_object+0x28/0x250
11) 3108 40 kmemleak_alloc+0x81/0xc0
12) 3068 24 kmem_cache_alloc+0x162/0x1d0
13) 3044 52 scsi_pool_alloc_command+0x29/0x70

This pushes the total to ~3800 bytes, only a tiny bit
more was needed to corrupt the on-kernel-stack thread_info.

The fix reduces the stack footprint from 572 bytes
to 28 bytes.

Cc: Peter Zijlstra <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Steven Rostedt <[email protected]>
Cc: Catalin Marinas <[email protected]>
Cc: Jens Axboe <[email protected]>
Cc: Linus Torvalds <[email protected]>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
init/main.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)

--- a/init/main.c
+++ b/init/main.c
@@ -702,13 +702,14 @@ asmlinkage void __init start_kernel(void
int initcall_debug;
core_param(initcall_debug, initcall_debug, bool, 0644);

+static char msgbuf[64];
+static struct boot_trace_call call;
+static struct boot_trace_ret ret;
+
int do_one_initcall(initcall_t fn)
{
int count = preempt_count();
ktime_t calltime, delta, rettime;
- char msgbuf[64];
- struct boot_trace_call call;
- struct boot_trace_ret ret;

if (initcall_debug) {
call.caller = task_pid_nr(current);

2009-09-05 00:21:01

by Greg KH

[permalink] [raw]
Subject: [patch 14/71] sound: pcm_lib: fix unsorted list constraint handling

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

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

commit b1ddaf681e362ed453182ddee1699d7487069a16 upstream.

snd_interval_list() expected a sorted list but did not document this, so
there are drivers that give it an unsorted list. To fix this, change
the algorithm to work with any list.

This fixes the "Slave PCM not usable" error with USB devices that have
multiple alternate settings with sample rates in decreasing order, such
as the Philips Askey VC010 WebCam.

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

Reported-and-tested-by: Andrzej <[email protected]>
Signed-off-by: Clemens Ladisch <[email protected]>
Signed-off-by: Takashi Iwai <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
sound/core/pcm_lib.c | 39 ++++++++-------------------------------
1 file changed, 8 insertions(+), 31 deletions(-)

--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -876,47 +876,24 @@ static int snd_interval_ratden(struct sn
int snd_interval_list(struct snd_interval *i, unsigned int count, unsigned int *list, unsigned int mask)
{
unsigned int k;
- int changed = 0;
+ struct snd_interval list_range;

if (!count) {
i->empty = 1;
return -EINVAL;
}
+ snd_interval_any(&list_range);
+ list_range.min = UINT_MAX;
+ list_range.max = 0;
for (k = 0; k < count; k++) {
if (mask && !(mask & (1 << k)))
continue;
- if (i->min == list[k] && !i->openmin)
- goto _l1;
- if (i->min < list[k]) {
- i->min = list[k];
- i->openmin = 0;
- changed = 1;
- goto _l1;
- }
- }
- i->empty = 1;
- return -EINVAL;
- _l1:
- for (k = count; k-- > 0;) {
- if (mask && !(mask & (1 << k)))
+ if (!snd_interval_test(i, list[k]))
continue;
- if (i->max == list[k] && !i->openmax)
- goto _l2;
- if (i->max > list[k]) {
- i->max = list[k];
- i->openmax = 0;
- changed = 1;
- goto _l2;
- }
+ list_range.min = min(list_range.min, list[k]);
+ list_range.max = max(list_range.max, list[k]);
}
- i->empty = 1;
- return -EINVAL;
- _l2:
- if (snd_interval_checkempty(i)) {
- i->empty = 1;
- return -EINVAL;
- }
- return changed;
+ return snd_interval_refine(i, &list_range);
}

EXPORT_SYMBOL(snd_interval_list);

2009-09-05 00:33:16

by Greg KH

[permalink] [raw]
Subject: [patch 15/71] clone(): fix race between copy_process() and de_thread()

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

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

commit 4ab6c08336535f8c8e42cf45d7adeda882eff06e upstream.

Spotted by Hiroshi Shimamoto who also provided the test-case below.

copy_process() uses signal->count as a reference counter, but it is not.
This test case

#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <pthread.h>

void *null_thread(void *p)
{
for (;;)
sleep(1);

return NULL;
}

void *exec_thread(void *p)
{
execl("/bin/true", "/bin/true", NULL);

return null_thread(p);
}

int main(int argc, char **argv)
{
for (;;) {
pid_t pid;
int ret, status;

pid = fork();
if (pid < 0)
break;

if (!pid) {
pthread_t tid;

pthread_create(&tid, NULL, exec_thread, NULL);
for (;;)
pthread_create(&tid, NULL, null_thread, NULL);
}

do {
ret = waitpid(pid, &status, 0);
} while (ret == -1 && errno == EINTR);
}

return 0;
}

quickly creates an unkillable task.

If copy_process(CLONE_THREAD) races with de_thread()
copy_signal()->atomic(signal->count) breaks the signal->notify_count
logic, and the execing thread can hang forever in kernel space.

Change copy_process() to increment count/live only when we know for sure
we can't fail. In this case the forked thread will take care of its
reference to signal correctly.

If copy_process() fails, check CLONE_THREAD flag. If it it set - do
nothing, the counters were not changed and current belongs to the same
thread group. If it is not set, ->signal must be released in any case
(and ->count must be == 1), the forked child is the only thread in the
thread group.

We need more cleanups here, in particular signal->count should not be used
by de_thread/__exit_signal at all. This patch only fixes the bug.

Reported-by: Hiroshi Shimamoto <[email protected]>
Tested-by: Hiroshi Shimamoto <[email protected]>
Signed-off-by: Oleg Nesterov <[email protected]>
Acked-by: Roland McGrath <[email protected]>
Cc: KAMEZAWA Hiroyuki <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
kernel/fork.c | 20 +++++---------------
1 file changed, 5 insertions(+), 15 deletions(-)

--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -816,11 +816,8 @@ static int copy_signal(unsigned long clo
{
struct signal_struct *sig;

- if (clone_flags & CLONE_THREAD) {
- atomic_inc(&current->signal->count);
- atomic_inc(&current->signal->live);
+ if (clone_flags & CLONE_THREAD)
return 0;
- }

sig = kmem_cache_alloc(signal_cachep, GFP_KERNEL);
tsk->signal = sig;
@@ -878,16 +875,6 @@ void __cleanup_signal(struct signal_stru
kmem_cache_free(signal_cachep, sig);
}

-static void cleanup_signal(struct task_struct *tsk)
-{
- struct signal_struct *sig = tsk->signal;
-
- atomic_dec(&sig->live);
-
- if (atomic_dec_and_test(&sig->count))
- __cleanup_signal(sig);
-}
-
static void copy_flags(unsigned long clone_flags, struct task_struct *p)
{
unsigned long new_flags = p->flags;
@@ -1237,6 +1224,8 @@ static struct task_struct *copy_process(
}

if (clone_flags & CLONE_THREAD) {
+ atomic_inc(&current->signal->count);
+ atomic_inc(&current->signal->live);
p->group_leader = current->group_leader;
list_add_tail_rcu(&p->thread_group, &p->group_leader->thread_group);
}
@@ -1281,7 +1270,8 @@ bad_fork_cleanup_mm:
if (p->mm)
mmput(p->mm);
bad_fork_cleanup_signal:
- cleanup_signal(p);
+ if (!(clone_flags & CLONE_THREAD))
+ __cleanup_signal(p->signal);
bad_fork_cleanup_sighand:
__cleanup_sighand(p->sighand);
bad_fork_cleanup_fs:

2009-09-05 00:32:52

by Greg KH

[permalink] [raw]
Subject: [patch 16/71] wmi: fix kernel panic when stack protection enabled.

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

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

commit f3d83e2415445e5b157bef404d38674e9e8de169 upstream.

Summary:
Kernel panic arise when stack protection is enabled, since strncat will
add a null terminating byte '\0'; So in functions
like this one (wmi_query_block):
char wc[4]="WC";
....
strncat(method, block->object_id, 2);
...
the length of wc should be n+1 (wc[5]) or stack protection
fault will arise. This is not noticeable when stack protection is
disabled,but , isn't good either.
Config used: [CONFIG_CC_STACKPROTECTOR_ALL=y,
CONFIG_CC_STACKPROTECTOR=y]

Panic Trace
------------
.... stack-protector: kernel stack corrupted in : fa7b182c
2.6.30-rc8-obelisco-generic
call_trace:
[<c04a6c40>] ? panic+0x45/0xd9
[<c012925d>] ? __stack_chk_fail+0x1c/0x40
[<fa7b182c>] ? wmi_query_block+0x15a/0x162 [wmi]
[<fa7b182c>] ? wmi_query_block+0x15a/0x162 [wmi]
[<fa7e7000>] ? acer_wmi_init+0x00/0x61a [acer_wmi]
[<fa7e7135>] ? acer_wmi_init+0x135/0x61a [acer_wmi]
[<c0101159>] ? do_one_initcall+0x50+0x126

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

Signed-off-by: Costantino Leandro <[email protected]>
Signed-off-by: Carlos Corbacho <[email protected]>
Cc: Len Brown <[email protected]>
Cc: Bjorn Helgaas <[email protected]>
Cc: "Rafael J. Wysocki" <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
drivers/platform/x86/wmi.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)

--- a/drivers/platform/x86/wmi.c
+++ b/drivers/platform/x86/wmi.c
@@ -270,7 +270,7 @@ u32 method_id, const struct acpi_buffer
acpi_status status;
struct acpi_object_list input;
union acpi_object params[3];
- char method[4] = "WM";
+ char method[5] = "WM";

if (!find_guid(guid_string, &wblock))
return AE_ERROR;
@@ -328,8 +328,8 @@ struct acpi_buffer *out)
acpi_status status, wc_status = AE_ERROR;
struct acpi_object_list input, wc_input;
union acpi_object wc_params[1], wq_params[1];
- char method[4];
- char wc_method[4] = "WC";
+ char method[5];
+ char wc_method[5] = "WC";

if (!guid_string || !out)
return AE_BAD_PARAMETER;
@@ -410,7 +410,7 @@ const struct acpi_buffer *in)
acpi_handle handle;
struct acpi_object_list input;
union acpi_object params[2];
- char method[4] = "WS";
+ char method[5] = "WS";

if (!guid_string || !in)
return AE_BAD_DATA;

2009-09-05 00:32:47

by Greg KH

[permalink] [raw]
Subject: [patch 17/71] SUNRPC: Fix rpc_task_force_reencode

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

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

commit 2574cc9f4ffc6c681c9177111357efe5b76f0e36 upstream.

This patch fixes the bug that was reported in
http://bugzilla.kernel.org/show_bug.cgi?id=14053

If we're in the case where we need to force a reencode and then resend of
the RPC request, due to xprt_transmit failing with a networking error, then
we _must_ retransmit the entire request.

Signed-off-by: Trond Myklebust <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
net/sunrpc/clnt.c | 1 +
1 file changed, 1 insertion(+)

--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -876,6 +876,7 @@ static inline void
rpc_task_force_reencode(struct rpc_task *task)
{
task->tk_rqstp->rq_snd_buf.len = 0;
+ task->tk_rqstp->rq_bytes_sent = 0;
}

static inline void

2009-09-05 00:31:05

by Greg KH

[permalink] [raw]
Subject: [patch 18/71] ALSA: hda - Fix MacBookPro 3,1/4,1 quirk with ALC889A

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

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

commit a3f730af7e33cea10ea66f05b2565fde1f9512df upstream.

This patch fixes the wrong headphone output routing for MacBookPro 3,1/4,1
quirk with ALC889A codec, which caused the silent headphone output.
Also, this gives the individual Headphone and Speaker volume controls.

Reference: kernel bug#14078
http://bugzilla.kernel.org/show_bug.cgi?id=14078

Signed-off-by: Takashi Iwai <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
sound/pci/hda/patch_realtek.c | 34 ++++++++++++++++++++--------------
1 file changed, 20 insertions(+), 14 deletions(-)

--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -6186,9 +6186,9 @@ static struct hda_verb alc885_mbp_ch2_in
};

/*
- * 6ch mode
+ * 4ch mode
*/
-static struct hda_verb alc885_mbp_ch6_init[] = {
+static struct hda_verb alc885_mbp_ch4_init[] = {
{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
{ 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
@@ -6197,9 +6197,9 @@ static struct hda_verb alc885_mbp_ch6_in
{ } /* end */
};

-static struct hda_channel_mode alc885_mbp_6ch_modes[2] = {
+static struct hda_channel_mode alc885_mbp_4ch_modes[2] = {
{ 2, alc885_mbp_ch2_init },
- { 6, alc885_mbp_ch6_init },
+ { 4, alc885_mbp_ch4_init },
};


@@ -6232,10 +6232,11 @@ static struct snd_kcontrol_new alc882_ba
};

static struct snd_kcontrol_new alc885_mbp3_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
- HDA_BIND_MUTE ("Front Playback Switch", 0x0c, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE ("Speaker Playback Switch", 0x14, 0x00, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Line-Out Playback Volume", 0x0d, 0x00, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
+ HDA_BIND_MUTE ("Speaker Playback Switch", 0x0c, 0x02, HDA_INPUT),
+ HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0e, 0x00, HDA_OUTPUT),
+ HDA_BIND_MUTE ("Headphone Playback Switch", 0x0e, 0x02, HDA_INPUT),
+ HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT),
HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x00, HDA_INPUT),
@@ -6481,14 +6482,18 @@ static struct hda_verb alc885_mbp3_init_
{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ /* HP mixer */
+ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
/* Front Pin: output 0 (0x0c) */
{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
- /* HP Pin: output 0 (0x0d) */
+ /* HP Pin: output 0 (0x0e) */
{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc4},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
+ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x15, AC_VERB_SET_CONNECT_SEL, 0x02},
{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
/* Mic (rear) pin: input vref at 80% */
{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
@@ -6885,10 +6890,11 @@ static struct alc_config_preset alc882_p
.mixers = { alc885_mbp3_mixer, alc882_chmode_mixer },
.init_verbs = { alc885_mbp3_init_verbs,
alc880_gpio1_init_verbs },
- .num_dacs = ARRAY_SIZE(alc882_dac_nids),
+ .num_dacs = 2,
.dac_nids = alc882_dac_nids,
- .channel_mode = alc885_mbp_6ch_modes,
- .num_channel_mode = ARRAY_SIZE(alc885_mbp_6ch_modes),
+ .hp_nid = 0x04,
+ .channel_mode = alc885_mbp_4ch_modes,
+ .num_channel_mode = ARRAY_SIZE(alc885_mbp_4ch_modes),
.input_mux = &alc882_capture_source,
.dig_out_nid = ALC882_DIGOUT_NID,
.dig_in_nid = ALC882_DIGIN_NID,

2009-09-05 00:31:01

by Greg KH

[permalink] [raw]
Subject: [patch 19/71] KVM: take mmu_lock when updating a deleted slot


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

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

(cherry picked from commit b43b1901ad282aeb74161837fb403927102687a1)

kvm_handle_hva relies on mmu_lock protection to safely access
the memslot structures.

Signed-off-by: Marcelo Tosatti <[email protected]>
Signed-off-by: Avi Kivity <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
virt/kvm/kvm_main.c | 2 ++
1 file changed, 2 insertions(+)

--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -1055,8 +1055,10 @@ int __kvm_set_memory_region(struct kvm *

kvm_free_physmem_slot(&old, npages ? &new : NULL);
/* Slot deletion case: we have to update the current slot */
+ spin_lock(&kvm->mmu_lock);
if (!npages)
*memslot = old;
+ spin_unlock(&kvm->mmu_lock);
#ifdef CONFIG_DMAR
/* map the pages in iommu page table */
r = kvm_iommu_map_pages(kvm, base_gfn, npages);

2009-09-05 00:21:12

by Greg KH

[permalink] [raw]
Subject: [patch 20/71] KVM: x86: check for cr3 validity in mmu_alloc_roots


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

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

(cherry picked from commit 8986ecc0ef58c96eec48d8502c048f3ab67fd8e2)

Verify the cr3 address stored in vcpu->arch.cr3 points to an existant
memslot. If not, inject a triple fault.

Signed-off-by: Marcelo Tosatti <[email protected]>
Signed-off-by: Avi Kivity <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
arch/x86/kvm/mmu.c | 27 +++++++++++++++++++++++----
arch/x86/kvm/x86.c | 1 +
2 files changed, 24 insertions(+), 4 deletions(-)

--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -1942,7 +1942,19 @@ static void mmu_free_roots(struct kvm_vc
vcpu->arch.mmu.root_hpa = INVALID_PAGE;
}

-static void mmu_alloc_roots(struct kvm_vcpu *vcpu)
+static int mmu_check_root(struct kvm_vcpu *vcpu, gfn_t root_gfn)
+{
+ int ret = 0;
+
+ if (!kvm_is_visible_gfn(vcpu->kvm, root_gfn)) {
+ set_bit(KVM_REQ_TRIPLE_FAULT, &vcpu->requests);
+ ret = 1;
+ }
+
+ return ret;
+}
+
+static int mmu_alloc_roots(struct kvm_vcpu *vcpu)
{
int i;
gfn_t root_gfn;
@@ -1957,13 +1969,15 @@ static void mmu_alloc_roots(struct kvm_v
ASSERT(!VALID_PAGE(root));
if (tdp_enabled)
direct = 1;
+ if (mmu_check_root(vcpu, root_gfn))
+ return 1;
sp = kvm_mmu_get_page(vcpu, root_gfn, 0,
PT64_ROOT_LEVEL, direct,
ACC_ALL, NULL);
root = __pa(sp->spt);
++sp->root_count;
vcpu->arch.mmu.root_hpa = root;
- return;
+ return 0;
}
direct = !is_paging(vcpu);
if (tdp_enabled)
@@ -1980,6 +1994,8 @@ static void mmu_alloc_roots(struct kvm_v
root_gfn = vcpu->arch.pdptrs[i] >> PAGE_SHIFT;
} else if (vcpu->arch.mmu.root_level == 0)
root_gfn = 0;
+ if (mmu_check_root(vcpu, root_gfn))
+ return 1;
sp = kvm_mmu_get_page(vcpu, root_gfn, i << 30,
PT32_ROOT_LEVEL, direct,
ACC_ALL, NULL);
@@ -1988,6 +2004,7 @@ static void mmu_alloc_roots(struct kvm_v
vcpu->arch.mmu.pae_root[i] = root | PT_PRESENT_MASK;
}
vcpu->arch.mmu.root_hpa = __pa(vcpu->arch.mmu.pae_root);
+ return 0;
}

static void mmu_sync_roots(struct kvm_vcpu *vcpu)
@@ -2006,7 +2023,7 @@ static void mmu_sync_roots(struct kvm_vc
for (i = 0; i < 4; ++i) {
hpa_t root = vcpu->arch.mmu.pae_root[i];

- if (root) {
+ if (root && VALID_PAGE(root)) {
root &= PT64_BASE_ADDR_MASK;
sp = page_header(root);
mmu_sync_children(vcpu, sp);
@@ -2290,9 +2307,11 @@ int kvm_mmu_load(struct kvm_vcpu *vcpu)
goto out;
spin_lock(&vcpu->kvm->mmu_lock);
kvm_mmu_free_some_pages(vcpu);
- mmu_alloc_roots(vcpu);
+ r = mmu_alloc_roots(vcpu);
mmu_sync_roots(vcpu);
spin_unlock(&vcpu->kvm->mmu_lock);
+ if (r)
+ goto out;
kvm_x86_ops->set_cr3(vcpu, vcpu->arch.mmu.root_hpa);
kvm_mmu_flush_tlb(vcpu);
out:
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -4433,6 +4433,7 @@ int kvm_arch_set_memory_region(struct kv
void kvm_arch_flush_shadow(struct kvm *kvm)
{
kvm_mmu_zap_all(kvm);
+ kvm_reload_remote_mmus(kvm);
}

int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu)

2009-09-05 00:21:16

by Greg KH

[permalink] [raw]
Subject: [patch 21/71] KVM: MMU: protect kvm_mmu_change_mmu_pages with mmu_lock


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

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

(cherry picked from commit 7c8a83b75a38a807d37f5a4398eca2a42c8cf513)

kvm_handle_hva, called by MMU notifiers, manipulates mmu data only with
the protection of mmu_lock.

Update kvm_mmu_change_mmu_pages callers to take mmu_lock, thus protecting
against kvm_handle_hva.

Signed-off-by: Marcelo Tosatti <[email protected]>
Signed-off-by: Avi Kivity <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
arch/x86/kvm/mmu.c | 2 --
arch/x86/kvm/x86.c | 6 ++++++
2 files changed, 6 insertions(+), 2 deletions(-)

--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -2729,7 +2729,6 @@ void kvm_mmu_slot_remove_write_access(st
{
struct kvm_mmu_page *sp;

- spin_lock(&kvm->mmu_lock);
list_for_each_entry(sp, &kvm->arch.active_mmu_pages, link) {
int i;
u64 *pt;
@@ -2744,7 +2743,6 @@ void kvm_mmu_slot_remove_write_access(st
pt[i] &= ~PT_WRITABLE_MASK;
}
kvm_flush_remote_tlbs(kvm);
- spin_unlock(&kvm->mmu_lock);
}

void kvm_mmu_zap_all(struct kvm *kvm)
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1608,10 +1608,12 @@ static int kvm_vm_ioctl_set_nr_mmu_pages
return -EINVAL;

down_write(&kvm->slots_lock);
+ spin_lock(&kvm->mmu_lock);

kvm_mmu_change_mmu_pages(kvm, kvm_nr_mmu_pages);
kvm->arch.n_requested_mmu_pages = kvm_nr_mmu_pages;

+ spin_unlock(&kvm->mmu_lock);
up_write(&kvm->slots_lock);
return 0;
}
@@ -1787,7 +1789,9 @@ int kvm_vm_ioctl_get_dirty_log(struct kv

/* If nothing is dirty, don't bother messing with page tables. */
if (is_dirty) {
+ spin_lock(&kvm->mmu_lock);
kvm_mmu_slot_remove_write_access(kvm, log->slot);
+ spin_unlock(&kvm->mmu_lock);
kvm_flush_remote_tlbs(kvm);
memslot = &kvm->memslots[log->slot];
n = ALIGN(memslot->npages, BITS_PER_LONG) / 8;
@@ -4419,12 +4423,14 @@ int kvm_arch_set_memory_region(struct kv
}
}

+ spin_lock(&kvm->mmu_lock);
if (!kvm->arch.n_requested_mmu_pages) {
unsigned int nr_mmu_pages = kvm_mmu_calculate_mmu_pages(kvm);
kvm_mmu_change_mmu_pages(kvm, nr_mmu_pages);
}

kvm_mmu_slot_remove_write_access(kvm, mem->slot);
+ spin_unlock(&kvm->mmu_lock);
kvm_flush_remote_tlbs(kvm);

return 0;

2009-09-05 00:29:00

by Greg KH

[permalink] [raw]
Subject: [patch 22/71] KVM: MMU: do not free active mmu pages in free_mmu_pages()


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

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

(cherry picked from commit f00be0cae4e6ad0a8c7be381c6d9be3586800b3e)

free_mmu_pages() should only undo what alloc_mmu_pages() does.
Free mmu pages from the generic VM destruction function, kvm_destroy_vm().

Signed-off-by: Gleb Natapov <[email protected]>
Signed-off-by: Avi Kivity <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
arch/x86/kvm/mmu.c | 8 --------
virt/kvm/kvm_main.c | 2 ++
2 files changed, 2 insertions(+), 8 deletions(-)

--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -2657,14 +2657,6 @@ EXPORT_SYMBOL_GPL(kvm_disable_tdp);

static void free_mmu_pages(struct kvm_vcpu *vcpu)
{
- struct kvm_mmu_page *sp;
-
- while (!list_empty(&vcpu->kvm->arch.active_mmu_pages)) {
- sp = container_of(vcpu->kvm->arch.active_mmu_pages.next,
- struct kvm_mmu_page, link);
- kvm_mmu_zap_page(vcpu->kvm, sp);
- cond_resched();
- }
free_page((unsigned long)vcpu->arch.mmu.pae_root);
}

--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -881,6 +881,8 @@ static void kvm_destroy_vm(struct kvm *k
#endif
#if defined(CONFIG_MMU_NOTIFIER) && defined(KVM_ARCH_WANT_MMU_NOTIFIER)
mmu_notifier_unregister(&kvm->mmu_notifier, kvm->mm);
+#else
+ kvm_arch_flush_shadow(kvm);
#endif
kvm_arch_destroy_vm(kvm);
mmdrop(mm);

2009-09-05 00:32:12

by Greg KH

[permalink] [raw]
Subject: [patch 23/71] KVM: Introduce {set/get}_interrupt_shadow()


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

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

This patch introduces set/get_interrupt_shadow(), that does exactly
what the name suggests. It also replaces open code that explicitly does
it with the now existent functions. It differs slightly from upstream,
because upstream merged it after gleb's interrupt rework, that we don't
ship.

Just for reference, upstream changelog is
(2809f5d2c4cfad171167b131bb2a21ab65eba40f):

This patch replaces drop_interrupt_shadow with the more
general set_interrupt_shadow, that can either drop or raise
it, depending on its parameter. It also adds ->get_interrupt_shadow()
for future use.

Signed-off-by: Glauber Costa <[email protected]>
Signed-off-by: Avi Kivity <[email protected]>
Signed-off-by: Marcelo Tosatti <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
arch/x86/include/asm/kvm_host.h | 2 +
arch/x86/include/asm/kvm_x86_emulate.h | 3 ++
arch/x86/kvm/svm.c | 25 ++++++++++++++++++-
arch/x86/kvm/vmx.c | 42 +++++++++++++++++++++++++--------
4 files changed, 62 insertions(+), 10 deletions(-)

--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -513,6 +513,8 @@ struct kvm_x86_ops {
void (*run)(struct kvm_vcpu *vcpu, struct kvm_run *run);
int (*handle_exit)(struct kvm_run *run, struct kvm_vcpu *vcpu);
void (*skip_emulated_instruction)(struct kvm_vcpu *vcpu);
+ void (*set_interrupt_shadow)(struct kvm_vcpu *vcpu, int mask);
+ u32 (*get_interrupt_shadow)(struct kvm_vcpu *vcpu, int mask);
void (*patch_hypercall)(struct kvm_vcpu *vcpu,
unsigned char *hypercall_addr);
int (*get_irq)(struct kvm_vcpu *vcpu);
--- a/arch/x86/include/asm/kvm_x86_emulate.h
+++ b/arch/x86/include/asm/kvm_x86_emulate.h
@@ -143,6 +143,9 @@ struct decode_cache {
struct fetch_cache fetch;
};

+#define X86_SHADOW_INT_MOV_SS 1
+#define X86_SHADOW_INT_STI 2
+
struct x86_emulate_ctxt {
/* Register state before/after emulation. */
struct kvm_vcpu *vcpu;
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -227,6 +227,27 @@ static int is_external_interrupt(u32 inf
return info == (SVM_EVTINJ_VALID | SVM_EVTINJ_TYPE_INTR);
}

+static u32 svm_get_interrupt_shadow(struct kvm_vcpu *vcpu, int mask)
+{
+ struct vcpu_svm *svm = to_svm(vcpu);
+ u32 ret = 0;
+
+ if (svm->vmcb->control.int_state & SVM_INTERRUPT_SHADOW_MASK)
+ ret |= X86_SHADOW_INT_STI | X86_SHADOW_INT_MOV_SS;
+ return ret & mask;
+}
+
+static void svm_set_interrupt_shadow(struct kvm_vcpu *vcpu, int mask)
+{
+ struct vcpu_svm *svm = to_svm(vcpu);
+
+ if (mask == 0)
+ svm->vmcb->control.int_state &= ~SVM_INTERRUPT_SHADOW_MASK;
+ else
+ svm->vmcb->control.int_state |= SVM_INTERRUPT_SHADOW_MASK;
+
+}
+
static void skip_emulated_instruction(struct kvm_vcpu *vcpu)
{
struct vcpu_svm *svm = to_svm(vcpu);
@@ -240,7 +261,7 @@ static void skip_emulated_instruction(st
__func__, kvm_rip_read(vcpu), svm->next_rip);

kvm_rip_write(vcpu, svm->next_rip);
- svm->vmcb->control.int_state &= ~SVM_INTERRUPT_SHADOW_MASK;
+ svm_set_interrupt_shadow(vcpu, 0);

vcpu->arch.interrupt_window_open = (svm->vcpu.arch.hflags & HF_GIF_MASK);
}
@@ -2667,6 +2688,8 @@ static struct kvm_x86_ops svm_x86_ops =
.run = svm_vcpu_run,
.handle_exit = handle_exit,
.skip_emulated_instruction = skip_emulated_instruction,
+ .set_interrupt_shadow = svm_set_interrupt_shadow,
+ .get_interrupt_shadow = svm_get_interrupt_shadow,
.patch_hypercall = svm_patch_hypercall,
.get_irq = svm_get_irq,
.set_irq = svm_set_irq,
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -732,23 +732,45 @@ static void vmx_set_rflags(struct kvm_vc
vmcs_writel(GUEST_RFLAGS, rflags);
}

+static u32 vmx_get_interrupt_shadow(struct kvm_vcpu *vcpu, int mask)
+{
+ u32 interruptibility = vmcs_read32(GUEST_INTERRUPTIBILITY_INFO);
+ int ret = 0;
+
+ if (interruptibility & GUEST_INTR_STATE_STI)
+ ret |= X86_SHADOW_INT_STI;
+ if (interruptibility & GUEST_INTR_STATE_MOV_SS)
+ ret |= X86_SHADOW_INT_MOV_SS;
+
+ return ret & mask;
+}
+
+static void vmx_set_interrupt_shadow(struct kvm_vcpu *vcpu, int mask)
+{
+ u32 interruptibility_old = vmcs_read32(GUEST_INTERRUPTIBILITY_INFO);
+ u32 interruptibility = interruptibility_old;
+
+ interruptibility &= ~(GUEST_INTR_STATE_STI | GUEST_INTR_STATE_MOV_SS);
+
+ if (mask & X86_SHADOW_INT_MOV_SS)
+ interruptibility |= GUEST_INTR_STATE_MOV_SS;
+ if (mask & X86_SHADOW_INT_STI)
+ interruptibility |= GUEST_INTR_STATE_STI;
+
+ if ((interruptibility != interruptibility_old))
+ vmcs_write32(GUEST_INTERRUPTIBILITY_INFO, interruptibility);
+}
+
static void skip_emulated_instruction(struct kvm_vcpu *vcpu)
{
unsigned long rip;
- u32 interruptibility;

rip = kvm_rip_read(vcpu);
rip += vmcs_read32(VM_EXIT_INSTRUCTION_LEN);
kvm_rip_write(vcpu, rip);

- /*
- * We emulated an instruction, so temporary interrupt blocking
- * should be removed, if set.
- */
- interruptibility = vmcs_read32(GUEST_INTERRUPTIBILITY_INFO);
- if (interruptibility & 3)
- vmcs_write32(GUEST_INTERRUPTIBILITY_INFO,
- interruptibility & ~3);
+ /* skipping an emulated instruction also counts */
+ vmx_set_interrupt_shadow(vcpu, 0);
vcpu->arch.interrupt_window_open = 1;
}

@@ -3738,6 +3760,8 @@ static struct kvm_x86_ops vmx_x86_ops =
.run = vmx_vcpu_run,
.handle_exit = kvm_handle_exit,
.skip_emulated_instruction = skip_emulated_instruction,
+ .set_interrupt_shadow = vmx_set_interrupt_shadow,
+ .get_interrupt_shadow = vmx_get_interrupt_shadow,
.patch_hypercall = vmx_patch_hypercall,
.get_irq = vmx_get_irq,
.set_irq = vmx_inject_irq,

2009-09-05 00:26:14

by Greg KH

[permalink] [raw]
Subject: [patch 24/71] KVM: Deal with interrupt shadow state for emulated instructions


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

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

(cherry picked from commit 310b5d306c1aee7ebe32f702c0e33e7988d50646)

We currently unblock shadow interrupt state when we skip an instruction,
but failing to do so when we actually emulate one. This blocks interrupts
in key instruction blocks, in particular sti; hlt; sequences

If the instruction emulated is an sti, we have to block shadow interrupts.
The same goes for mov ss. pop ss also needs it, but we don't currently
emulate it.

Without this patch, I cannot boot gpxe option roms at vmx machines.
This is described at https://bugzilla.redhat.com/show_bug.cgi?id=494469

Signed-off-by: Glauber Costa <[email protected]>
CC: H. Peter Anvin <[email protected]>
CC: Gleb Natapov <[email protected]>
Signed-off-by: Avi Kivity <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
arch/x86/include/asm/kvm_x86_emulate.h | 3 +++
arch/x86/kvm/x86.c | 6 +++++-
arch/x86/kvm/x86_emulate.c | 20 ++++++++++++++++++++
3 files changed, 28 insertions(+), 1 deletion(-)

--- a/arch/x86/include/asm/kvm_x86_emulate.h
+++ b/arch/x86/include/asm/kvm_x86_emulate.h
@@ -155,6 +155,9 @@ struct x86_emulate_ctxt {
int mode;
u32 cs_base;

+ /* interruptibility state, as a result of execution of STI or MOV SS */
+ int interruptibility;
+
/* decode cache */
struct decode_cache decode;
};
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -2366,7 +2366,7 @@ int emulate_instruction(struct kvm_vcpu
u16 error_code,
int emulation_type)
{
- int r;
+ int r, shadow_mask;
struct decode_cache *c;

kvm_clear_exception_queue(vcpu);
@@ -2415,6 +2415,10 @@ int emulate_instruction(struct kvm_vcpu
}

r = x86_emulate_insn(&vcpu->arch.emulate_ctxt, &emulate_ops);
+ shadow_mask = vcpu->arch.emulate_ctxt.interruptibility;
+
+ if (r == 0)
+ kvm_x86_ops->set_interrupt_shadow(vcpu, shadow_mask);

if (vcpu->arch.pio.string)
return EMULATE_DO_MMIO;
--- a/arch/x86/kvm/x86_emulate.c
+++ b/arch/x86/kvm/x86_emulate.c
@@ -1349,6 +1349,20 @@ static inline int writeback(struct x86_e
return 0;
}

+void toggle_interruptibility(struct x86_emulate_ctxt *ctxt, u32 mask)
+{
+ u32 int_shadow = kvm_x86_ops->get_interrupt_shadow(ctxt->vcpu, mask);
+ /*
+ * an sti; sti; sequence only disable interrupts for the first
+ * instruction. So, if the last instruction, be it emulated or
+ * not, left the system with the INT_STI flag enabled, it
+ * means that the last instruction is an sti. We should not
+ * leave the flag on in this case. The same goes for mov ss
+ */
+ if (!(int_shadow & mask))
+ ctxt->interruptibility = mask;
+}
+
int
x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
{
@@ -1360,6 +1374,8 @@ x86_emulate_insn(struct x86_emulate_ctxt
int io_dir_in;
int rc = 0;

+ ctxt->interruptibility = 0;
+
/* Shadow copy of register state. Committed on successful emulation.
* NOTE: we can copy them from vcpu as x86_decode_insn() doesn't
* modify them.
@@ -1609,6 +1625,9 @@ special_insn:
int err;

sel = c->src.val;
+ if (c->modrm_reg == VCPU_SREG_SS)
+ toggle_interruptibility(ctxt, X86_SHADOW_INT_MOV_SS);
+
if (c->modrm_reg <= 5) {
type_bits = (c->modrm_reg == 1) ? 9 : 1;
err = kvm_load_segment_descriptor(ctxt->vcpu, sel,
@@ -1865,6 +1884,7 @@ special_insn:
c->dst.type = OP_NONE; /* Disable writeback. */
break;
case 0xfb: /* sti */
+ toggle_interruptibility(ctxt, X86_SHADOW_INT_STI);
ctxt->eflags |= X86_EFLAGS_IF;
c->dst.type = OP_NONE; /* Disable writeback. */
break;

2009-09-05 00:27:25

by Greg KH

[permalink] [raw]
Subject: [patch 25/71] KVM: MMU: Use different shadows when EFER.NXE changes


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

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

(cherry picked from commit 9645bb56b31a1b70ab9e470387b5264cafc04aa9)

A pte that is shadowed when the guest EFER.NXE=1 is not valid when
EFER.NXE=0; if bit 63 is set, the pte should cause a fault, and since the
shadow EFER always has NX enabled, this won't happen.

Fix by using a different shadow page table for different EFER.NXE bits. This
allows vcpus to run correctly with different values of EFER.NXE, and for
transitions on this bit to be handled correctly without requiring a full
flush.

Signed-off-by: Avi Kivity <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
arch/x86/include/asm/kvm_host.h | 1 +
arch/x86/kvm/x86.c | 3 +++
2 files changed, 4 insertions(+)

--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -185,6 +185,7 @@ union kvm_mmu_page_role {
unsigned access:3;
unsigned invalid:1;
unsigned cr4_pge:1;
+ unsigned nxe:1;
};
};

--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -523,6 +523,9 @@ static void set_efer(struct kvm_vcpu *vc
efer |= vcpu->arch.shadow_efer & EFER_LMA;

vcpu->arch.shadow_efer = efer;
+
+ vcpu->arch.mmu.base_role.nxe = (efer & EFER_NX) && !tdp_enabled;
+ kvm_mmu_reset_context(vcpu);
}

void kvm_enable_efer_bits(u64 mask)

2009-09-05 00:21:19

by Greg KH

[permalink] [raw]
Subject: [patch 26/71] KVM: x86: Ignore reads to EVNTSEL MSRs


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

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

(cherry picked from commit 7fe29e0faacb650d31b9e9f538203a157bec821d)

We ignore writes to the performance counters and performance event
selector registers already. Kaspersky antivirus reads the eventsel
MSR causing it to crash with the current behaviour.

Return 0 as data when the eventsel registers are read to stop the
crash.

Signed-off-by: Amit Shah <[email protected]>
Signed-off-by: Avi Kivity <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
arch/x86/kvm/x86.c | 2 ++
1 file changed, 2 insertions(+)

--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -898,6 +898,8 @@ int kvm_get_msr_common(struct kvm_vcpu *
case MSR_IA32_LASTINTFROMIP:
case MSR_IA32_LASTINTTOIP:
case MSR_VM_HSAVE_PA:
+ case MSR_P6_EVNTSEL0:
+ case MSR_P6_EVNTSEL1:
data = 0;
break;
case MSR_MTRRcap:

2009-09-05 00:21:25

by Greg KH

[permalink] [raw]
Subject: [patch 27/71] KVM: Ignore reads to K7 EVNTSEL MSRs


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

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

(cherry picked from commit 9e6996240afcbe61682eab8eeaeb65c34333164d)

In commit 7fe29e0faacb650d31b9e9f538203a157bec821d we ignored the
reads to the P6 EVNTSEL MSRs. That fixed crashes on Intel machines.

Ignore the reads to K7 EVNTSEL MSRs as well to fix this on AMD
hosts.

This fixes Kaspersky antivirus crashing Windows guests on AMD hosts.

Signed-off-by: Amit Shah <[email protected]>
Signed-off-by: Avi Kivity <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
arch/x86/kvm/x86.c | 1 +
1 file changed, 1 insertion(+)

--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -900,6 +900,7 @@ int kvm_get_msr_common(struct kvm_vcpu *
case MSR_VM_HSAVE_PA:
case MSR_P6_EVNTSEL0:
case MSR_P6_EVNTSEL1:
+ case MSR_K7_EVNTSEL0:
data = 0;
break;
case MSR_MTRRcap:

2009-09-05 00:28:04

by Greg KH

[permalink] [raw]
Subject: [patch 28/71] KVM: Fix cpuid feature misreporting


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

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

(cherry picked from commit 8d753f369bd28fff1706ffe9fb9fea4fd88cf85b)

MTRR, PAT, MCE, and MCA are all supported (to some extent) but not reported.
Vista requires these features, so if userspace relies on kernel cpuid
reporting, it loses support for Vista.

Signed-off-by: Avi Kivity <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
arch/x86/kvm/x86.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)

--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1256,9 +1256,12 @@ static void do_cpuid_ent(struct kvm_cpui
bit(X86_FEATURE_VME) | bit(X86_FEATURE_DE) |
bit(X86_FEATURE_PSE) | bit(X86_FEATURE_TSC) |
bit(X86_FEATURE_MSR) | bit(X86_FEATURE_PAE) |
+ bit(X86_FEATURE_MCE) |
bit(X86_FEATURE_CX8) | bit(X86_FEATURE_APIC) |
- bit(X86_FEATURE_SEP) | bit(X86_FEATURE_PGE) |
- bit(X86_FEATURE_CMOV) | bit(X86_FEATURE_PSE36) |
+ bit(X86_FEATURE_SEP) | bit(X86_FEATURE_MTRR) |
+ bit(X86_FEATURE_PGE) | bit(X86_FEATURE_MCA) |
+ bit(X86_FEATURE_CMOV) | bit(X86_FEATURE_PAT) |
+ bit(X86_FEATURE_PSE36) |
bit(X86_FEATURE_CLFLSH) | bit(X86_FEATURE_MMX) |
bit(X86_FEATURE_FXSR) | bit(X86_FEATURE_XMM) |
bit(X86_FEATURE_XMM2) | bit(X86_FEATURE_SELFSNOOP);

2009-09-05 00:26:57

by Greg KH

[permalink] [raw]
Subject: [patch 29/71] KVM: x86: verify MTRR/PAT validity

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

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

(cherry picked from commit d6289b9365c3f622a8cfe62c4fb054bb70b5061a)

Do not allow invalid memory types in MTRR/PAT (generating a #GP
otherwise).

Signed-off-by: Marcelo Tosatti <[email protected]>
Signed-off-by: Avi Kivity <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
arch/x86/kvm/x86.c | 39 ++++++++++++++++++++++++++++++++++++++-
1 file changed, 38 insertions(+), 1 deletion(-)

--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -706,11 +706,48 @@ static bool msr_mtrr_valid(unsigned msr)
return false;
}

+static bool valid_pat_type(unsigned t)
+{
+ return t < 8 && (1 << t) & 0xf3; /* 0, 1, 4, 5, 6, 7 */
+}
+
+static bool valid_mtrr_type(unsigned t)
+{
+ return t < 8 && (1 << t) & 0x73; /* 0, 1, 4, 5, 6 */
+}
+
+static bool mtrr_valid(struct kvm_vcpu *vcpu, u32 msr, u64 data)
+{
+ int i;
+
+ if (!msr_mtrr_valid(msr))
+ return false;
+
+ if (msr == MSR_IA32_CR_PAT) {
+ for (i = 0; i < 8; i++)
+ if (!valid_pat_type((data >> (i * 8)) & 0xff))
+ return false;
+ return true;
+ } else if (msr == MSR_MTRRdefType) {
+ if (data & ~0xcff)
+ return false;
+ return valid_mtrr_type(data & 0xff);
+ } else if (msr >= MSR_MTRRfix64K_00000 && msr <= MSR_MTRRfix4K_F8000) {
+ for (i = 0; i < 8 ; i++)
+ if (!valid_mtrr_type((data >> (i * 8)) & 0xff))
+ return false;
+ return true;
+ }
+
+ /* variable MTRRs */
+ return valid_mtrr_type(data & 0xff);
+}
+
static int set_msr_mtrr(struct kvm_vcpu *vcpu, u32 msr, u64 data)
{
u64 *p = (u64 *)&vcpu->arch.mtrr_state.fixed_ranges;

- if (!msr_mtrr_valid(msr))
+ if (!mtrr_valid(vcpu, msr, data))
return 1;

if (msr == MSR_MTRRdefType) {

2009-09-05 00:25:47

by Greg KH

[permalink] [raw]
Subject: [patch 30/71] KVM: SVM: force new asid on vcpu migration

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

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

(cherry picked from commit 4b656b1202498184a0ecef86b3b89ff613b9c6ab)

If a migrated vcpu matches the asid_generation value of the target pcpu,
there will be no TLB flush via TLB_CONTROL_FLUSH_ALL_ASID.

The check for vcpu.cpu in pre_svm_run is meaningless since svm_vcpu_load
already updated it on schedule in.

Such vcpu will VMRUN with stale TLB entries.

Based on original patch from Joerg Roedel (http://patchwork.kernel.org/patch/10021/)

Signed-off-by: Marcelo Tosatti <[email protected]>
Acked-by: Joerg Roedel <[email protected]>
Signed-off-by: Avi Kivity <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
arch/x86/kvm/svm.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)

--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -736,6 +736,7 @@ static void svm_vcpu_load(struct kvm_vcp
svm->vmcb->control.tsc_offset += delta;
vcpu->cpu = cpu;
kvm_migrate_timers(vcpu);
+ svm->asid_generation = 0;
}

for (i = 0; i < NR_HOST_SAVE_USER_MSRS; i++)
@@ -1046,7 +1047,6 @@ static void new_asid(struct vcpu_svm *sv
svm->vmcb->control.tlb_ctl = TLB_CONTROL_FLUSH_ALL_ASID;
}

- svm->vcpu.cpu = svm_data->cpu;
svm->asid_generation = svm_data->asid_generation;
svm->vmcb->control.asid = svm_data->next_asid++;
}
@@ -2258,8 +2258,8 @@ static void pre_svm_run(struct vcpu_svm
struct svm_cpu_data *svm_data = per_cpu(svm_data, cpu);

svm->vmcb->control.tlb_ctl = TLB_CONTROL_DO_NOTHING;
- if (svm->vcpu.cpu != cpu ||
- svm->asid_generation != svm_data->asid_generation)
+ /* FIXME: handle wraparound of asid_generation */
+ if (svm->asid_generation != svm_data->asid_generation)
new_asid(svm, svm_data);
}


2009-09-05 00:31:40

by Greg KH

[permalink] [raw]
Subject: [patch 31/71] KVM: MMU: handle n_free_mmu_pages > n_alloc_mmu_pages in kvm_mmu_change_mmu_pages

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

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

(cherry picked from commit 025dbbf36a7680bffe54d9dcbf0a8bc01a7cbd10)

kvm_mmu_change_mmu_pages mishandles the case where n_alloc_mmu_pages is
smaller then n_free_mmu_pages, by not checking if the result of
the subtraction is negative.

Its a valid condition which can happen if a large number of pages has
been recently freed.

Signed-off-by: Marcelo Tosatti <[email protected]>
Signed-off-by: Avi Kivity <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
arch/x86/kvm/mmu.c | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)

--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -1417,24 +1417,25 @@ static int kvm_mmu_zap_page(struct kvm *
*/
void kvm_mmu_change_mmu_pages(struct kvm *kvm, unsigned int kvm_nr_mmu_pages)
{
+ int used_pages;
+
+ used_pages = kvm->arch.n_alloc_mmu_pages - kvm->arch.n_free_mmu_pages;
+ used_pages = max(0, used_pages);
+
/*
* If we set the number of mmu pages to be smaller be than the
* number of actived pages , we must to free some mmu pages before we
* change the value
*/

- if ((kvm->arch.n_alloc_mmu_pages - kvm->arch.n_free_mmu_pages) >
- kvm_nr_mmu_pages) {
- int n_used_mmu_pages = kvm->arch.n_alloc_mmu_pages
- - kvm->arch.n_free_mmu_pages;
-
- while (n_used_mmu_pages > kvm_nr_mmu_pages) {
+ if (used_pages > kvm_nr_mmu_pages) {
+ while (used_pages > kvm_nr_mmu_pages) {
struct kvm_mmu_page *page;

page = container_of(kvm->arch.active_mmu_pages.prev,
struct kvm_mmu_page, link);
kvm_mmu_zap_page(kvm, page);
- n_used_mmu_pages--;
+ used_pages--;
}
kvm->arch.n_free_mmu_pages = 0;
}

2009-09-05 00:21:31

by Greg KH

[permalink] [raw]
Subject: [patch 32/71] [stable] [PATCH 14/16] KVM: MMU: limit rmap chain length

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

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

(cherry picked from commit 53a27b39ff4d2492f84b1fdc2f0047175f0b0b93)

Otherwise the host can spend too long traversing an rmap chain, which
happens under a spinlock.

Signed-off-by: Marcelo Tosatti <[email protected]>
Signed-off-by: Avi Kivity <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
arch/x86/kvm/mmu.c | 33 ++++++++++++++++++++++++++++-----
1 file changed, 28 insertions(+), 5 deletions(-)

--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -490,16 +490,20 @@ static unsigned long *gfn_to_rmap(struct
*
* If rmapp bit zero is one, (then rmap & ~1) points to a struct kvm_rmap_desc
* containing more mappings.
+ *
+ * Returns the number of rmap entries before the spte was added or zero if
+ * the spte was not added.
+ *
*/
-static void rmap_add(struct kvm_vcpu *vcpu, u64 *spte, gfn_t gfn, int lpage)
+static int rmap_add(struct kvm_vcpu *vcpu, u64 *spte, gfn_t gfn, int lpage)
{
struct kvm_mmu_page *sp;
struct kvm_rmap_desc *desc;
unsigned long *rmapp;
- int i;
+ int i, count = 0;

if (!is_rmap_pte(*spte))
- return;
+ return count;
gfn = unalias_gfn(vcpu->kvm, gfn);
sp = page_header(__pa(spte));
sp->gfns[spte - sp->spt] = gfn;
@@ -516,8 +520,10 @@ static void rmap_add(struct kvm_vcpu *vc
} else {
rmap_printk("rmap_add: %p %llx many->many\n", spte, *spte);
desc = (struct kvm_rmap_desc *)(*rmapp & ~1ul);
- while (desc->shadow_ptes[RMAP_EXT-1] && desc->more)
+ while (desc->shadow_ptes[RMAP_EXT-1] && desc->more) {
desc = desc->more;
+ count += RMAP_EXT;
+ }
if (desc->shadow_ptes[RMAP_EXT-1]) {
desc->more = mmu_alloc_rmap_desc(vcpu);
desc = desc->more;
@@ -526,6 +532,7 @@ static void rmap_add(struct kvm_vcpu *vc
;
desc->shadow_ptes[i] = spte;
}
+ return count;
}

static void rmap_desc_remove_entry(unsigned long *rmapp,
@@ -755,6 +762,19 @@ static int kvm_age_rmapp(struct kvm *kvm
return young;
}

+#define RMAP_RECYCLE_THRESHOLD 1000
+
+static void rmap_recycle(struct kvm_vcpu *vcpu, gfn_t gfn, int lpage)
+{
+ unsigned long *rmapp;
+
+ gfn = unalias_gfn(vcpu->kvm, gfn);
+ rmapp = gfn_to_rmap(vcpu->kvm, gfn, lpage);
+
+ kvm_unmap_rmapp(vcpu->kvm, rmapp);
+ kvm_flush_remote_tlbs(vcpu->kvm);
+}
+
int kvm_age_hva(struct kvm *kvm, unsigned long hva)
{
return kvm_handle_hva(kvm, hva, kvm_age_rmapp);
@@ -1771,6 +1791,7 @@ static void mmu_set_spte(struct kvm_vcpu
{
int was_rmapped = 0;
int was_writeble = is_writeble_pte(*shadow_pte);
+ int rmap_count;

pgprintk("%s: spte %llx access %x write_fault %d"
" user_fault %d gfn %lx\n",
@@ -1812,9 +1833,11 @@ static void mmu_set_spte(struct kvm_vcpu

page_header_update_slot(vcpu->kvm, shadow_pte, gfn);
if (!was_rmapped) {
- rmap_add(vcpu, shadow_pte, gfn, largepage);
+ rmap_count = rmap_add(vcpu, shadow_pte, gfn, largepage);
if (!is_rmap_pte(*shadow_pte))
kvm_release_pfn_clean(pfn);
+ if (rmap_count > RMAP_RECYCLE_THRESHOLD)
+ rmap_recycle(vcpu, gfn, largepage);
} else {
if (was_writeble)
kvm_release_pfn_dirty(pfn);

2009-09-05 00:25:06

by Greg KH

[permalink] [raw]
Subject: [patch 33/71] KVM: fix ack not being delivered when msi present


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

------------------
From: Michael S. Tsirkin <[email protected]>

(cherry picked from commit 5116d8f6b977970ebefc1932c0f313163a6ec91f)

kvm_notify_acked_irq does not check irq type, so that it sometimes
interprets msi vector as irq. As a result, ack notifiers are not
called, which typially hangs the guest. The fix is to track and
check irq type.

Signed-off-by: Michael S. Tsirkin <[email protected]>
Signed-off-by: Avi Kivity <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
include/linux/kvm_host.h | 1 +
virt/kvm/irq_comm.c | 4 +++-
2 files changed, 4 insertions(+), 1 deletion(-)

--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -110,6 +110,7 @@ struct kvm_memory_slot {

struct kvm_kernel_irq_routing_entry {
u32 gsi;
+ u32 type;
int (*set)(struct kvm_kernel_irq_routing_entry *e,
struct kvm *kvm, int level);
union {
--- a/virt/kvm/irq_comm.c
+++ b/virt/kvm/irq_comm.c
@@ -141,7 +141,8 @@ void kvm_notify_acked_irq(struct kvm *kv
unsigned gsi = pin;

list_for_each_entry(e, &kvm->irq_routing, link)
- if (e->irqchip.irqchip == irqchip &&
+ if (e->type == KVM_IRQ_ROUTING_IRQCHIP &&
+ e->irqchip.irqchip == irqchip &&
e->irqchip.pin == pin) {
gsi = e->gsi;
break;
@@ -240,6 +241,7 @@ static int setup_routing_entry(struct kv
int delta;

e->gsi = ue->gsi;
+ e->type = ue->type;
switch (ue->type) {
case KVM_IRQ_ROUTING_IRQCHIP:
delta = 0;

2009-09-05 00:21:35

by Greg KH

[permalink] [raw]
Subject: [patch 34/71] KVM: Fix KVM_GET_MSR_INDEX_LIST

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

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

commit e125e7b6944898831b56739a5448e705578bf7e2 upstream.

So far, KVM copied the emulated_msrs (only MSR_IA32_MISC_ENABLE) to a
wrong address in user space due to broken pointer arithmetic. This
caused subtle corruption up there (missing MSR_IA32_MISC_ENABLE had
probably no practical relevance). Moreover, the size check for the
user-provided kvm_msr_list forgot about emulated MSRs.

Signed-off-by: Jan Kiszka <[email protected]>
Signed-off-by: Avi Kivity <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
arch/x86/kvm/x86.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)

--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1117,14 +1117,13 @@ long kvm_arch_dev_ioctl(struct file *fil
if (copy_to_user(user_msr_list, &msr_list, sizeof msr_list))
goto out;
r = -E2BIG;
- if (n < num_msrs_to_save)
+ if (n < msr_list.nmsrs)
goto out;
r = -EFAULT;
if (copy_to_user(user_msr_list->indices, &msrs_to_save,
num_msrs_to_save * sizeof(u32)))
goto out;
- if (copy_to_user(user_msr_list->indices
- + num_msrs_to_save * sizeof(u32),
+ if (copy_to_user(user_msr_list->indices + num_msrs_to_save,
&emulated_msrs,
ARRAY_SIZE(emulated_msrs) * sizeof(u32)))
goto out;

2009-09-05 00:29:56

by Greg KH

[permalink] [raw]
Subject: [patch 35/71] iwl3945: fix rfkill switch

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

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

(Not needed upstream, due to the major rewrite in 2.6.31)

Due to rfkill and iwlwifi mishmash of SW / HW killswitch representation,
we have race conditions which make unable turn wifi radio on, after enable
and disable again killswitch. I can observe this problem on my laptop
with iwl3945 device.

In rfkill core HW switch and SW switch are separate 'states'. Device can
be only in one of 3 states: RFKILL_STATE_SOFT_BLOCKED, RFKILL_STATE_UNBLOCKED,
RFKILL_STATE_HARD_BLOCKED. Whereas in iwlwifi driver we have separate bits
STATUS_RF_KILL_HW and STATUS_RF_KILL_SW for HW and SW switches - radio can be
turned on, only if both bits are cleared.

In this particular race conditions, radio can not be turned on if in driver
STATUS_RF_KILL_SW bit is set, and rfkill core is in state
RFKILL_STATE_HARD_BLOCKED, because rfkill core is unable to call
rfkill->toggle_radio(). This situation can be entered in case:

- killswitch is turned on
- rfkill core 'see' button change first and move to RFKILL_STATE_SOFT_BLOCKED
also call ->toggle_radio() and STATE_RF_KILL_SW in driver is set
- iwl3945 get info about button from hardware to set STATUS_RF_KILL_HW bit and
force rfkill to move to RFKILL_STATE_HARD_BLOCKED
- killsiwtch is turend off
- driver clear STATUS_RF_KILL_HW
- rfkill core is unable to clear STATUS_RF_KILL_SW in driver

Additionally call to rfkill_epo() when STATUS_RF_KILL_HW in driver is set
cause move to the same situation.

In 2.6.31 this problem is fixed due to _total_ rewrite of rfkill subsystem.
This is a quite small fix for 2.6.30.x in iwlwifi driver. We are changing
internal rfkill state to always have below relations true:

STATUS_RF_KILL_HW=1 STATUS_RF_KILL_SW=1 <-> RFKILL_STATUS_SOFT_BLOCKED
STATUS_RF_KILL_HW=0 STATUS_RF_KILL_SW=1 <-> RFKILL_STATUS_SOFT_BLOCKED
STATUS_RF_KILL_HW=1 STATUS_RF_KILL_SW=0 <-> RFKILL_STATUS_HARD_BLOCKED
STATUS_RF_KILL_HW=0 STATUS_RF_KILL_SW=0 <-> RFKILL_STATUS_UNBLOCKED

Signed-off-by: Stanislaw Gruszka <[email protected]>
Acked-by: Reinette Chatre <[email protected]>
Acked-by: John W. Linville <[email protected]>


---
drivers/net/wireless/iwlwifi/iwl-rfkill.c | 26 ++++++++++++++++----------
1 file changed, 16 insertions(+), 10 deletions(-)

--- a/drivers/net/wireless/iwlwifi/iwl-rfkill.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.c
@@ -53,22 +53,31 @@ static int iwl_rfkill_soft_rf_kill(void
switch (state) {
case RFKILL_STATE_UNBLOCKED:
if (iwl_is_rfkill_hw(priv)) {
+ /* pass error to rfkill core, make it state HARD
+ * BLOCKED (rfkill->mutex taken) and disable
+ * software kill switch */
err = -EBUSY;
- goto out_unlock;
+ priv->rfkill->state = RFKILL_STATE_HARD_BLOCKED;
}
iwl_radio_kill_sw_enable_radio(priv);
break;
case RFKILL_STATE_SOFT_BLOCKED:
iwl_radio_kill_sw_disable_radio(priv);
+ /* rfkill->mutex is taken */
+ if (priv->rfkill->state == RFKILL_STATE_HARD_BLOCKED) {
+ /* force rfkill core state to be SOFT BLOCKED,
+ * otherwise core will be unable to disable software
+ * kill switch */
+ priv->rfkill->state = RFKILL_STATE_SOFT_BLOCKED;
+ }
break;
default:
IWL_WARN(priv, "we received unexpected RFKILL state %d\n",
state);
break;
}
-out_unlock:
- mutex_unlock(&priv->mutex);

+ mutex_unlock(&priv->mutex);
return err;
}

@@ -132,14 +141,11 @@ void iwl_rfkill_set_hw_state(struct iwl_
if (!priv->rfkill)
return;

- if (iwl_is_rfkill_hw(priv)) {
+ if (iwl_is_rfkill_sw(priv))
+ rfkill_force_state(priv->rfkill, RFKILL_STATE_SOFT_BLOCKED);
+ else if (iwl_is_rfkill_hw(priv))
rfkill_force_state(priv->rfkill, RFKILL_STATE_HARD_BLOCKED);
- return;
- }
-
- if (!iwl_is_rfkill_sw(priv))
- rfkill_force_state(priv->rfkill, RFKILL_STATE_UNBLOCKED);
else
- rfkill_force_state(priv->rfkill, RFKILL_STATE_SOFT_BLOCKED);
+ rfkill_force_state(priv->rfkill, RFKILL_STATE_UNBLOCKED);
}
EXPORT_SYMBOL(iwl_rfkill_set_hw_state);

2009-09-05 00:23:12

by Greg KH

[permalink] [raw]
Subject: [patch 36/71] iwlagn: do not send key clear commands when rfkill enabled

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

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

commit 99f1b01562b7dcae75b043114f76163fbf84fcab upstream.

Do all key clearing except sending sommands to device when rfkill
enabled. When rfkill enabled the interface is brought down and will
be brought back up correctly after rfkill is enabled again.

Same change is not needed for iwl3945 as it ignores return code when
sending key clearing command to device.

This fixes http://bugzilla.kernel.org/show_bug.cgi?id=13742

Signed-off-by: Reinette Chatre <[email protected]>
Tested-by: Frans Pop <[email protected]>
Signed-off-by: John W. Linville <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
drivers/net/wireless/iwlwifi/iwl-sta.c | 12 ++++++++++++
1 file changed, 12 insertions(+)

--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -560,6 +560,8 @@ int iwl_remove_default_wep_key(struct iw
unsigned long flags;

spin_lock_irqsave(&priv->sta_lock, flags);
+ IWL_DEBUG_WEP(priv, "Removing default WEP key: idx=%d\n",
+ keyconf->keyidx);

if (!test_and_clear_bit(keyconf->keyidx, &priv->ucode_key_table))
IWL_ERR(priv, "index %d not used in uCode key table.\n",
@@ -567,6 +569,11 @@ int iwl_remove_default_wep_key(struct iw

priv->default_wep_key--;
memset(&priv->wep_keys[keyconf->keyidx], 0, sizeof(priv->wep_keys[0]));
+ if (iwl_is_rfkill(priv)) {
+ IWL_DEBUG_WEP(priv, "Not sending REPLY_WEPKEY command due to RFKILL.\n");
+ spin_unlock_irqrestore(&priv->sta_lock, flags);
+ return 0;
+ }
ret = iwl_send_static_wepkey_cmd(priv, 1);
IWL_DEBUG_WEP(priv, "Remove default WEP key: idx=%d ret=%d\n",
keyconf->keyidx, ret);
@@ -847,6 +854,11 @@ int iwl_remove_dynamic_key(struct iwl_pr
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;

+ if (iwl_is_rfkill(priv)) {
+ IWL_DEBUG_WEP(priv, "Not sending REPLY_ADD_STA command because RFKILL enabled. \n");
+ spin_unlock_irqrestore(&priv->sta_lock, flags);
+ return 0;
+ }
ret = iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
spin_unlock_irqrestore(&priv->sta_lock, flags);
return ret;

2009-09-05 00:23:28

by Greg KH

[permalink] [raw]
Subject: [patch 37/71] libata: OCZ Vertex cant do HPA

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

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

commit 7831387bda72af3059be48d39846d3eb6d8ce2f6 upstream.

OCZ Vertex SSD can't do HPA and not in a usual way. It reports HPA,
allows unlocking but then fails all IOs which fall in the unlocked
area. Quirk it so that HPA unlocking is not used for the device.

Reported by Daniel Perup in bnc#522414.

https://bugzilla.novell.com/show_bug.cgi?id=522414

Signed-off-by: Tejun Heo <[email protected]>
Reported-by: Daniel Perup <[email protected]>
Signed-off-by: Jeff Garzik <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
drivers/ata/libata-core.c | 3 +++
1 file changed, 3 insertions(+)

--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -4271,6 +4271,9 @@ static const struct ata_blacklist_entry
{ "WDC WD2500JD-00HBB0", "WD-WMAL71490727", ATA_HORKAGE_BROKEN_HPA },
{ "MAXTOR 6L080L4", "A93.0500", ATA_HORKAGE_BROKEN_HPA },

+ /* this one allows HPA unlocking but fails IOs on the area */
+ { "OCZ-VERTEX", "1.30", ATA_HORKAGE_BROKEN_HPA },
+
/* Devices which report 1 sector over size HPA */
{ "ST340823A", NULL, ATA_HORKAGE_HPA_SIZE, },
{ "ST320413A", NULL, ATA_HORKAGE_HPA_SIZE, },

2009-09-05 00:21:39

by Greg KH

[permalink] [raw]
Subject: [patch 38/71] SCSI: mpt2sas: Introduced check for enclosure_handle to avoid crash

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

------------------
From: Kashyap, Desai <[email protected]>

commit 15052c9e85bf0cdadcb69eb89623bf12bad8b4f8 upstream.

Kernel panic is seen because of enclosure_handle received from FW is zero.
Check is introduced before calling mpt2sas_config_get_enclosure_pg0.

Signed-off-by: Kashyap Desai <[email protected]>
Signed-off-by: James Bottomley <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
drivers/scsi/mpt2sas/mpt2sas_scsih.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)

--- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
@@ -3442,12 +3442,11 @@ _scsih_add_device(struct MPT2SAS_ADAPTER
sas_device->hidden_raid_component = is_pd;

/* get enclosure_logical_id */
- if (!(mpt2sas_config_get_enclosure_pg0(ioc, &mpi_reply, &enclosure_pg0,
- MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE,
- sas_device->enclosure_handle))) {
+ if (sas_device->enclosure_handle && !(mpt2sas_config_get_enclosure_pg0(
+ ioc, &mpi_reply, &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE,
+ sas_device->enclosure_handle)))
sas_device->enclosure_logical_id =
le64_to_cpu(enclosure_pg0.EnclosureLogicalID);
- }

/* get device name */
sas_device->device_name = le64_to_cpu(sas_device_pg0.DeviceName);

2009-09-05 00:29:52

by Greg KH

[permalink] [raw]
Subject: [patch 39/71] SCSI: mpt2sas: Expander fix oops saying "Already part of another port"

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

------------------
From: Kashyap, Desai <[email protected]>

commit 20f5895d55d9281830bfb7819c5c5b70b05297a6 upstream.

Kernel panic is seen because driver did not tear down the port which should
be dnoe using mpt2sas_transport_port_remove(). without this fix When expander
is added back we would oops inside sas_port_add_phy.

Signed-off-by: Kashyap Desai <[email protected]>
Signed-off-by: James Bottomley <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
drivers/scsi/mpt2sas/mpt2sas_scsih.c | 21 +++++++++++++++------
1 file changed, 15 insertions(+), 6 deletions(-)

--- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
@@ -3205,7 +3205,7 @@ _scsih_expander_add(struct MPT2SAS_ADAPT
__le64 sas_address;
int i;
unsigned long flags;
- struct _sas_port *mpt2sas_port;
+ struct _sas_port *mpt2sas_port = NULL;
int rc = 0;

if (!handle)
@@ -3297,12 +3297,20 @@ _scsih_expander_add(struct MPT2SAS_ADAPT
&expander_pg1, i, handle))) {
printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
ioc->name, __FILE__, __LINE__, __func__);
- continue;
+ rc = -1;
+ goto out_fail;
}
sas_expander->phy[i].handle = handle;
sas_expander->phy[i].phy_id = i;
- mpt2sas_transport_add_expander_phy(ioc, &sas_expander->phy[i],
- expander_pg1, sas_expander->parent_dev);
+
+ if ((mpt2sas_transport_add_expander_phy(ioc,
+ &sas_expander->phy[i], expander_pg1,
+ sas_expander->parent_dev))) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ rc = -1;
+ goto out_fail;
+ }
}

if (sas_expander->enclosure_handle) {
@@ -3319,8 +3327,9 @@ _scsih_expander_add(struct MPT2SAS_ADAPT

out_fail:

- if (sas_expander)
- kfree(sas_expander->phy);
+ if (mpt2sas_port)
+ mpt2sas_transport_port_remove(ioc, sas_expander->sas_address,
+ sas_expander->parent_handle);
kfree(sas_expander);
return rc;
}

2009-09-05 00:30:29

by Greg KH

[permalink] [raw]
Subject: [patch 40/71] SCSI: mpt2sas: Raid 10 Value is showing as Raid 1E in /va/log/messages

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

------------------
From: Kashyap, Desai <[email protected]>

commit 62727a7ba43c0abf2673e3877079c136a9721792 upstream.

When a volume is activated, the driver will recieve a pair of ir config change
events to remove the foreign volume, then add the native.
In the process of the removal event, the hidden raid componet is removed from
the parent.When the disks is added back, the adding of the port fails becuase
there is no instance of the device in its parent.
To fix this issue, the driver needs to call mpt2sas_transport_update_links()
prior to calling _scsih_add_device. In addition, we added sanity checks on
volume add and removal to ignore events for foreign volumes.

Signed-off-by: Kashyap Desai <[email protected]>
Signed-off-by: James Bottomley <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
drivers/scsi/mpt2sas/mpt2sas_scsih.c | 90 ++++++++++++++++++++++++-----------
1 file changed, 64 insertions(+), 26 deletions(-)

--- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
@@ -4037,12 +4037,6 @@ _scsih_sas_volume_add(struct MPT2SAS_ADA
u16 handle = le16_to_cpu(element->VolDevHandle);
int rc;

-#if 0 /* RAID_HACKS */
- if (le32_to_cpu(event_data->Flags) &
- MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG)
- return;
-#endif
-
mpt2sas_config_get_volume_wwid(ioc, handle, &wwid);
if (!wwid) {
printk(MPT2SAS_ERR_FMT
@@ -4097,12 +4091,6 @@ _scsih_sas_volume_delete(struct MPT2SAS_
unsigned long flags;
struct MPT2SAS_TARGET *sas_target_priv_data;

-#if 0 /* RAID_HACKS */
- if (le32_to_cpu(event_data->Flags) &
- MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG)
- return;
-#endif
-
spin_lock_irqsave(&ioc->raid_device_lock, flags);
raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
@@ -4215,14 +4203,38 @@ _scsih_sas_pd_add(struct MPT2SAS_ADAPTER
struct _sas_device *sas_device;
unsigned long flags;
u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
+ Mpi2ConfigReply_t mpi_reply;
+ Mpi2SasDevicePage0_t sas_device_pg0;
+ u32 ioc_status;

spin_lock_irqsave(&ioc->sas_device_lock, flags);
sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
- if (sas_device)
+ if (sas_device) {
sas_device->hidden_raid_component = 1;
- else
- _scsih_add_device(ioc, handle, 0, 1);
+ return;
+ }
+
+ if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
+ MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ return;
+ }
+
+ ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+ MPI2_IOCSTATUS_MASK;
+ if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ return;
+ }
+
+ _scsih_link_change(ioc,
+ le16_to_cpu(sas_device_pg0.ParentDevHandle),
+ handle, sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5);
+
+ _scsih_add_device(ioc, handle, 0, 1);
}

#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
@@ -4322,12 +4334,15 @@ _scsih_sas_ir_config_change_event(struct
{
Mpi2EventIrConfigElement_t *element;
int i;
+ u8 foreign_config;

#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
_scsih_sas_ir_config_change_event_debug(ioc, event_data);

#endif
+ foreign_config = (le32_to_cpu(event_data->Flags) &
+ MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) ? 1 : 0;

element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
for (i = 0; i < event_data->NumElements; i++, element++) {
@@ -4335,11 +4350,13 @@ _scsih_sas_ir_config_change_event(struct
switch (element->ReasonCode) {
case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED:
case MPI2_EVENT_IR_CHANGE_RC_ADDED:
- _scsih_sas_volume_add(ioc, element);
+ if (!foreign_config)
+ _scsih_sas_volume_add(ioc, element);
break;
case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED:
case MPI2_EVENT_IR_CHANGE_RC_REMOVED:
- _scsih_sas_volume_delete(ioc, element);
+ if (!foreign_config)
+ _scsih_sas_volume_delete(ioc, element);
break;
case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED:
_scsih_sas_pd_hide(ioc, element);
@@ -4458,6 +4475,9 @@ _scsih_sas_ir_physical_disk_event(struct
u32 state;
struct _sas_device *sas_device;
unsigned long flags;
+ Mpi2ConfigReply_t mpi_reply;
+ Mpi2SasDevicePage0_t sas_device_pg0;
+ u32 ioc_status;

if (event_data->ReasonCode != MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED)
return;
@@ -4474,22 +4494,40 @@ _scsih_sas_ir_physical_disk_event(struct
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);

switch (state) {
-#if 0
- case MPI2_RAID_PD_STATE_OFFLINE:
- if (sas_device)
- _scsih_remove_device(ioc, handle);
- break;
-#endif
case MPI2_RAID_PD_STATE_ONLINE:
case MPI2_RAID_PD_STATE_DEGRADED:
case MPI2_RAID_PD_STATE_REBUILDING:
case MPI2_RAID_PD_STATE_OPTIMAL:
- if (sas_device)
+ if (sas_device) {
sas_device->hidden_raid_component = 1;
- else
- _scsih_add_device(ioc, handle, 0, 1);
+ return;
+ }
+
+ if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply,
+ &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
+ handle))) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ return;
+ }
+
+ ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+ MPI2_IOCSTATUS_MASK;
+ if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ return;
+ }
+
+ _scsih_link_change(ioc,
+ le16_to_cpu(sas_device_pg0.ParentDevHandle),
+ handle, sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5);
+
+ _scsih_add_device(ioc, handle, 0, 1);
+
break;

+ case MPI2_RAID_PD_STATE_OFFLINE:
case MPI2_RAID_PD_STATE_NOT_CONFIGURED:
case MPI2_RAID_PD_STATE_NOT_COMPATIBLE:
case MPI2_RAID_PD_STATE_HOT_SPARE:

2009-09-05 00:29:49

by Greg KH

[permalink] [raw]
Subject: [patch 41/71] SCSI: mpt2sas: Excessive log info causes sas iounit page time out

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

------------------
From: Kashyap, Desai <[email protected]>

commit be9e8cd75ce8d94ae4aab721fdcc337fa78a9090 upstream.

Inhibit 0x3117 loginfos - during cable pull, there are too many printks going
to the syslog, this is have impact on how fast the interrupt routine can handle
keeping up with command completions; this was the root cause to the config
pages timeouts.

Signed-off-by: Kashyap Desai <[email protected]>
Signed-off-by: James Bottomley <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
drivers/scsi/mpt2sas/mpt2sas_base.c | 4 ++++
drivers/scsi/mpt2sas/mpt2sas_scsih.c | 4 ++++
2 files changed, 8 insertions(+)

--- a/drivers/scsi/mpt2sas/mpt2sas_base.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.c
@@ -440,6 +440,10 @@ _base_sas_log_info(struct MPT2SAS_ADAPTE
if (sas_loginfo.dw.bus_type != 3 /*SAS*/)
return;

+ /* each nexus loss loginfo */
+ if (log_info == 0x31170000)
+ return;
+
/* eat the loginfos associated with task aborts */
if (ioc->ignore_loginfos && (log_info == 30050000 || log_info ==
0x31140000 || log_info == 0x31130000))
--- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
@@ -2560,6 +2560,10 @@ _scsih_scsi_ioc_info(struct MPT2SAS_ADAP
char *desc_ioc_state = NULL;
char *desc_scsi_status = NULL;
char *desc_scsi_state = ioc->tmp_string;
+ u32 log_info = le32_to_cpu(mpi_reply->IOCLogInfo);
+
+ if (log_info == 0x31170000)
+ return;

switch (ioc_status) {
case MPI2_IOCSTATUS_SUCCESS:

2009-09-05 00:29:09

by Greg KH

[permalink] [raw]
Subject: [patch 42/71] SCSI: mpt2sas: fix infinite loop inside config request

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

------------------
From: Kashyap, Desai <[email protected]>

commit 6bd4e1e4d6023f4da069fd68729c502cc4e6dfd0 upstream.

This restriction is introduced just to avoid loop of
config_request. Retry must be limited so we have restricted
config request to maximum 2 times.

Signed-off-by: Kashyap Desai <[email protected]>
Signed-off-by: James Bottomley <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

diff --git a/drivers/scsi/mpt2sas/mpt2sas_config.c b/drivers/scsi/mpt2sas/mpt2sas_config.c
index 58cfb97..1c6658c 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_config.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_config.c
@@ -247,6 +247,12 @@ _config_request(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigRequest_t
retry_count = 0;

retry_config:
+ if (retry_count) {
+ if (retry_count > 2) /* attempt only 2 retries */
+ return -EFAULT;
+ printk(MPT2SAS_INFO_FMT "%s: attempting retry (%d)\n",
+ ioc->name, __func__, retry_count);
+ }
wait_state_count = 0;
ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {

2009-09-05 00:29:26

by Greg KH

[permalink] [raw]
Subject: [patch 43/71] SCSI: mpt2sas: fix crash due to Watchdog is active while OS in standby mode

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

------------------
From: Kashyap, Desai <[email protected]>

commit e4750c989f732555fca86dd73d488c79972362db upstream.

Fix oops ocurring at hibernation time. This oops was due to the firmware fault
watchdog timer still running after we freed resources. To fix the issue we need
to terminate the watchdog timer at hibernation time.

Signed-off-by: Kashyap Desai <[email protected]>
Signed-off-by: James Bottomley <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
drivers/scsi/mpt2sas/mpt2sas_base.c | 88 +++++++++++++++++++++++------------
drivers/scsi/mpt2sas/mpt2sas_base.h | 2
drivers/scsi/mpt2sas/mpt2sas_scsih.c | 2
3 files changed, 64 insertions(+), 28 deletions(-)

--- a/drivers/scsi/mpt2sas/mpt2sas_base.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.c
@@ -119,6 +119,64 @@ _base_fault_reset_work(struct work_struc
spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
}

+/**
+ * mpt2sas_base_start_watchdog - start the fault_reset_work_q
+ * @ioc: pointer to scsi command object
+ * Context: sleep.
+ *
+ * Return nothing.
+ */
+void
+mpt2sas_base_start_watchdog(struct MPT2SAS_ADAPTER *ioc)
+{
+ unsigned long flags;
+
+ if (ioc->fault_reset_work_q)
+ return;
+
+ /* initialize fault polling */
+ INIT_DELAYED_WORK(&ioc->fault_reset_work, _base_fault_reset_work);
+ snprintf(ioc->fault_reset_work_q_name,
+ sizeof(ioc->fault_reset_work_q_name), "poll_%d_status", ioc->id);
+ ioc->fault_reset_work_q =
+ create_singlethread_workqueue(ioc->fault_reset_work_q_name);
+ if (!ioc->fault_reset_work_q) {
+ printk(MPT2SAS_ERR_FMT "%s: failed (line=%d)\n",
+ ioc->name, __func__, __LINE__);
+ return;
+ }
+ spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
+ if (ioc->fault_reset_work_q)
+ queue_delayed_work(ioc->fault_reset_work_q,
+ &ioc->fault_reset_work,
+ msecs_to_jiffies(FAULT_POLLING_INTERVAL));
+ spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+}
+
+/**
+ * mpt2sas_base_stop_watchdog - stop the fault_reset_work_q
+ * @ioc: pointer to scsi command object
+ * Context: sleep.
+ *
+ * Return nothing.
+ */
+void
+mpt2sas_base_stop_watchdog(struct MPT2SAS_ADAPTER *ioc)
+{
+ unsigned long flags;
+ struct workqueue_struct *wq;
+
+ spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
+ wq = ioc->fault_reset_work_q;
+ ioc->fault_reset_work_q = NULL;
+ spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+ if (wq) {
+ if (!cancel_delayed_work(&ioc->fault_reset_work))
+ flush_workqueue(wq);
+ destroy_workqueue(wq);
+ }
+}
+
#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
/**
* _base_sas_ioc_info - verbose translation of the ioc status
@@ -3209,7 +3267,6 @@ int
mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)
{
int r, i;
- unsigned long flags;

dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
__func__));
@@ -3292,23 +3349,7 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPT
if (r)
goto out_free_resources;

- /* initialize fault polling */
- INIT_DELAYED_WORK(&ioc->fault_reset_work, _base_fault_reset_work);
- snprintf(ioc->fault_reset_work_q_name,
- sizeof(ioc->fault_reset_work_q_name), "poll_%d_status", ioc->id);
- ioc->fault_reset_work_q =
- create_singlethread_workqueue(ioc->fault_reset_work_q_name);
- if (!ioc->fault_reset_work_q) {
- printk(MPT2SAS_ERR_FMT "%s: failed (line=%d)\n",
- ioc->name, __func__, __LINE__);
- goto out_free_resources;
- }
- spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
- if (ioc->fault_reset_work_q)
- queue_delayed_work(ioc->fault_reset_work_q,
- &ioc->fault_reset_work,
- msecs_to_jiffies(FAULT_POLLING_INTERVAL));
- spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+ mpt2sas_base_start_watchdog(ioc);
return 0;

out_free_resources:
@@ -3341,20 +3382,11 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPT
void
mpt2sas_base_detach(struct MPT2SAS_ADAPTER *ioc)
{
- unsigned long flags;
- struct workqueue_struct *wq;

dexitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
__func__));

- spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
- wq = ioc->fault_reset_work_q;
- ioc->fault_reset_work_q = NULL;
- spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
- if (!cancel_delayed_work(&ioc->fault_reset_work))
- flush_workqueue(wq);
- destroy_workqueue(wq);
-
+ mpt2sas_base_stop_watchdog(ioc);
mpt2sas_base_free_resources(ioc);
_base_release_memory_pools(ioc);
kfree(ioc->pfacts);
--- a/drivers/scsi/mpt2sas/mpt2sas_base.h
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.h
@@ -672,6 +672,8 @@ typedef void (*MPT_CALLBACK)(struct MPT2

/* base shared API */
extern struct list_head mpt2sas_ioc_list;
+void mpt2sas_base_start_watchdog(struct MPT2SAS_ADAPTER *ioc);
+void mpt2sas_base_stop_watchdog(struct MPT2SAS_ADAPTER *ioc);

int mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc);
void mpt2sas_base_detach(struct MPT2SAS_ADAPTER *ioc);
--- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
@@ -5599,6 +5599,7 @@ scsih_suspend(struct pci_dev *pdev, pm_m
struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
u32 device_state;

+ mpt2sas_base_stop_watchdog(ioc);
flush_scheduled_work();
scsi_block_requests(shost);
device_state = pci_choose_state(pdev, state);
@@ -5641,6 +5642,7 @@ scsih_resume(struct pci_dev *pdev)

mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, SOFT_RESET);
scsi_unblock_requests(shost);
+ mpt2sas_base_start_watchdog(ioc);
return 0;
}
#endif /* CONFIG_PM */

2009-09-05 00:29:02

by Greg KH

[permalink] [raw]
Subject: [patch 44/71] SCSI: mpt2sas: fix oops because drv data points to NULL on resume from hibernate

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

------------------
From: Kashyap, Desai <[email protected]>

commit fcfe6392d18283df3c561b5ef59c330d485ff8ca upstream.

Fix another ocurring when the system resumes. This oops was due to driver
setting the pci drvdata to NULL on the prior hibernation. Becuase it was
set to NULL, upon resmume we assume the pci drvdata is non-zero, and we oops.
To fix the ooops, we don't set pci drvdata to NULL at hibernation time.

Signed-off-by: Kashyap Desai <[email protected]>
Signed-off-by: James Bottomley <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
drivers/scsi/mpt2sas/mpt2sas_base.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)

--- a/drivers/scsi/mpt2sas/mpt2sas_base.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.c
@@ -1171,7 +1171,6 @@ mpt2sas_base_map_resources(struct MPT2SA
}
}

- pci_set_drvdata(pdev, ioc->shost);
_base_mask_interrupts(ioc);
r = _base_enable_msix(ioc);
if (r)
@@ -1194,7 +1193,6 @@ mpt2sas_base_map_resources(struct MPT2SA
ioc->pci_irq = -1;
pci_release_selected_regions(ioc->pdev, ioc->bars);
pci_disable_device(pdev);
- pci_set_drvdata(pdev, NULL);
return r;
}

@@ -3253,7 +3251,6 @@ mpt2sas_base_free_resources(struct MPT2S
ioc->chip_phys = 0;
pci_release_selected_regions(ioc->pdev, ioc->bars);
pci_disable_device(pdev);
- pci_set_drvdata(pdev, NULL);
return;
}

@@ -3275,6 +3272,7 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPT
if (r)
return r;

+ pci_set_drvdata(ioc->pdev, ioc->shost);
r = _base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET);
if (r)
goto out_free_resources;
@@ -3357,6 +3355,7 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPT
ioc->remove_host = 1;
mpt2sas_base_free_resources(ioc);
_base_release_memory_pools(ioc);
+ pci_set_drvdata(ioc->pdev, NULL);
kfree(ioc->tm_cmds.reply);
kfree(ioc->transport_cmds.reply);
kfree(ioc->config_cmds.reply);
@@ -3389,6 +3388,7 @@ mpt2sas_base_detach(struct MPT2SAS_ADAPT
mpt2sas_base_stop_watchdog(ioc);
mpt2sas_base_free_resources(ioc);
_base_release_memory_pools(ioc);
+ pci_set_drvdata(ioc->pdev, NULL);
kfree(ioc->pfacts);
kfree(ioc->ctl_cmds.reply);
kfree(ioc->base_cmds.reply);

2009-09-05 00:28:27

by Greg KH

[permalink] [raw]
Subject: [patch 45/71] [SCSI] mpt2sas: fix config request and diag reset deadlock

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

------------------
From: Kashyap, Desai <[email protected]>

commit 388ce4beb7135722c584b0af18f215e3ec657adf upstream.

Moving the setting and clearing of the mutex's to
_config_request. There was a mutex deadlock when diag reset is called from
inside _config_request, so diag reset was moved to outside the mutexs.

Signed-off-by: James Bottomley <[email protected]>
Signed-off-by: Kashyap Desai <[email protected]>
Signed-off-by: Eric Moore <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
drivers/scsi/mpt2sas/mpt2sas_config.c | 85 ++++++++--------------------------
1 file changed, 20 insertions(+), 65 deletions(-)

--- a/drivers/scsi/mpt2sas/mpt2sas_config.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_config.c
@@ -236,12 +236,14 @@ _config_request(struct MPT2SAS_ADAPTER *
Mpi2ConfigRequest_t *config_request;
int r;
u8 retry_count;
- u8 issue_reset;
+ u8 issue_host_reset = 0;
u16 wait_state_count;

+ mutex_lock(&ioc->config_cmds.mutex);
if (ioc->config_cmds.status != MPT2_CMD_NOT_USED) {
printk(MPT2SAS_ERR_FMT "%s: config_cmd in use\n",
ioc->name, __func__);
+ mutex_unlock(&ioc->config_cmds.mutex);
return -EAGAIN;
}
retry_count = 0;
@@ -260,8 +262,8 @@ _config_request(struct MPT2SAS_ADAPTER *
printk(MPT2SAS_ERR_FMT
"%s: failed due to ioc not operational\n",
ioc->name, __func__);
- ioc->config_cmds.status = MPT2_CMD_NOT_USED;
- return -EFAULT;
+ r = -EFAULT;
+ goto out;
}
ssleep(1);
ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
@@ -277,8 +279,8 @@ _config_request(struct MPT2SAS_ADAPTER *
if (!smid) {
printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
ioc->name, __func__);
- ioc->config_cmds.status = MPT2_CMD_NOT_USED;
- return -EAGAIN;
+ r = -EAGAIN;
+ goto out;
}

r = 0;
@@ -298,9 +300,15 @@ _config_request(struct MPT2SAS_ADAPTER *
ioc->name, __func__);
_debug_dump_mf(mpi_request,
sizeof(Mpi2ConfigRequest_t)/4);
- if (!(ioc->config_cmds.status & MPT2_CMD_RESET))
- issue_reset = 1;
- goto issue_host_reset;
+ retry_count++;
+ if (ioc->config_cmds.smid == smid)
+ mpt2sas_base_free_smid(ioc, smid);
+ if ((ioc->shost_recovery) ||
+ (ioc->config_cmds.status & MPT2_CMD_RESET))
+ goto retry_config;
+ issue_host_reset = 1;
+ r = -EFAULT;
+ goto out;
}
if (ioc->config_cmds.status & MPT2_CMD_REPLY_VALID)
memcpy(mpi_reply, ioc->config_cmds.reply,
@@ -308,21 +316,13 @@ _config_request(struct MPT2SAS_ADAPTER *
if (retry_count)
printk(MPT2SAS_INFO_FMT "%s: retry completed!!\n",
ioc->name, __func__);
+out:
ioc->config_cmds.status = MPT2_CMD_NOT_USED;
- return r;
-
- issue_host_reset:
- if (issue_reset)
+ mutex_unlock(&ioc->config_cmds.mutex);
+ if (issue_host_reset)
mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
FORCE_BIG_HAMMER);
- ioc->config_cmds.status = MPT2_CMD_NOT_USED;
- if (!retry_count) {
- printk(MPT2SAS_INFO_FMT "%s: attempting retry\n",
- ioc->name, __func__);
- retry_count++;
- goto retry_config;
- }
- return -EFAULT;
+ return r;
}

/**
@@ -381,7 +381,6 @@ mpt2sas_config_get_manufacturing_pg0(str
int r;
struct config_request mem;

- mutex_lock(&ioc->config_cmds.mutex);
memset(config_page, 0, sizeof(Mpi2ManufacturingPage0_t));
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -423,7 +422,6 @@ mpt2sas_config_get_manufacturing_pg0(str
_config_free_config_dma_memory(ioc, &mem);

out:
- mutex_unlock(&ioc->config_cmds.mutex);
return r;
}

@@ -444,7 +442,6 @@ mpt2sas_config_get_bios_pg2(struct MPT2S
int r;
struct config_request mem;

- mutex_lock(&ioc->config_cmds.mutex);
memset(config_page, 0, sizeof(Mpi2BiosPage2_t));
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -486,7 +483,6 @@ mpt2sas_config_get_bios_pg2(struct MPT2S
_config_free_config_dma_memory(ioc, &mem);

out:
- mutex_unlock(&ioc->config_cmds.mutex);
return r;
}

@@ -507,7 +503,6 @@ mpt2sas_config_get_bios_pg3(struct MPT2S
int r;
struct config_request mem;

- mutex_lock(&ioc->config_cmds.mutex);
memset(config_page, 0, sizeof(Mpi2BiosPage3_t));
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -549,7 +544,6 @@ mpt2sas_config_get_bios_pg3(struct MPT2S
_config_free_config_dma_memory(ioc, &mem);

out:
- mutex_unlock(&ioc->config_cmds.mutex);
return r;
}

@@ -570,7 +564,6 @@ mpt2sas_config_get_iounit_pg0(struct MPT
int r;
struct config_request mem;

- mutex_lock(&ioc->config_cmds.mutex);
memset(config_page, 0, sizeof(Mpi2IOUnitPage0_t));
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -612,7 +605,6 @@ mpt2sas_config_get_iounit_pg0(struct MPT
_config_free_config_dma_memory(ioc, &mem);

out:
- mutex_unlock(&ioc->config_cmds.mutex);
return r;
}

@@ -633,7 +625,6 @@ mpt2sas_config_get_iounit_pg1(struct MPT
int r;
struct config_request mem;

- mutex_lock(&ioc->config_cmds.mutex);
memset(config_page, 0, sizeof(Mpi2IOUnitPage1_t));
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -675,7 +666,6 @@ mpt2sas_config_get_iounit_pg1(struct MPT
_config_free_config_dma_memory(ioc, &mem);

out:
- mutex_unlock(&ioc->config_cmds.mutex);
return r;
}

@@ -696,7 +686,6 @@ mpt2sas_config_set_iounit_pg1(struct MPT
int r;
struct config_request mem;

- mutex_lock(&ioc->config_cmds.mutex);
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
mpi_request.Function = MPI2_FUNCTION_CONFIG;
mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
@@ -738,7 +727,6 @@ mpt2sas_config_set_iounit_pg1(struct MPT
_config_free_config_dma_memory(ioc, &mem);

out:
- mutex_unlock(&ioc->config_cmds.mutex);
return r;
}

@@ -759,7 +747,6 @@ mpt2sas_config_get_ioc_pg8(struct MPT2SA
int r;
struct config_request mem;

- mutex_lock(&ioc->config_cmds.mutex);
memset(config_page, 0, sizeof(Mpi2IOCPage8_t));
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -801,7 +788,6 @@ mpt2sas_config_get_ioc_pg8(struct MPT2SA
_config_free_config_dma_memory(ioc, &mem);

out:
- mutex_unlock(&ioc->config_cmds.mutex);
return r;
}

@@ -824,7 +810,6 @@ mpt2sas_config_get_sas_device_pg0(struct
int r;
struct config_request mem;

- mutex_lock(&ioc->config_cmds.mutex);
memset(config_page, 0, sizeof(Mpi2SasDevicePage0_t));
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -869,7 +854,6 @@ mpt2sas_config_get_sas_device_pg0(struct
_config_free_config_dma_memory(ioc, &mem);

out:
- mutex_unlock(&ioc->config_cmds.mutex);
return r;
}

@@ -892,7 +876,6 @@ mpt2sas_config_get_sas_device_pg1(struct
int r;
struct config_request mem;

- mutex_lock(&ioc->config_cmds.mutex);
memset(config_page, 0, sizeof(Mpi2SasDevicePage1_t));
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -937,7 +920,6 @@ mpt2sas_config_get_sas_device_pg1(struct
_config_free_config_dma_memory(ioc, &mem);

out:
- mutex_unlock(&ioc->config_cmds.mutex);
return r;
}

@@ -959,7 +941,6 @@ mpt2sas_config_get_number_hba_phys(struc
Mpi2ConfigReply_t mpi_reply;
Mpi2SasIOUnitPage0_t config_page;

- mutex_lock(&ioc->config_cmds.mutex);
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
mpi_request.Function = MPI2_FUNCTION_CONFIG;
mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
@@ -1008,7 +989,6 @@ mpt2sas_config_get_number_hba_phys(struc
_config_free_config_dma_memory(ioc, &mem);

out:
- mutex_unlock(&ioc->config_cmds.mutex);
return r;
}

@@ -1032,8 +1012,6 @@ mpt2sas_config_get_sas_iounit_pg0(struct
Mpi2ConfigRequest_t mpi_request;
int r;
struct config_request mem;
-
- mutex_lock(&ioc->config_cmds.mutex);
memset(config_page, 0, sz);
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -1076,7 +1054,6 @@ mpt2sas_config_get_sas_iounit_pg0(struct
_config_free_config_dma_memory(ioc, &mem);

out:
- mutex_unlock(&ioc->config_cmds.mutex);
return r;
}

@@ -1101,7 +1078,6 @@ mpt2sas_config_get_sas_iounit_pg1(struct
int r;
struct config_request mem;

- mutex_lock(&ioc->config_cmds.mutex);
memset(config_page, 0, sz);
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -1144,7 +1120,6 @@ mpt2sas_config_get_sas_iounit_pg1(struct
_config_free_config_dma_memory(ioc, &mem);

out:
- mutex_unlock(&ioc->config_cmds.mutex);
return r;
}

@@ -1167,7 +1142,6 @@ mpt2sas_config_get_expander_pg0(struct M
int r;
struct config_request mem;

- mutex_lock(&ioc->config_cmds.mutex);
memset(config_page, 0, sizeof(Mpi2ExpanderPage0_t));
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -1212,7 +1186,6 @@ mpt2sas_config_get_expander_pg0(struct M
_config_free_config_dma_memory(ioc, &mem);

out:
- mutex_unlock(&ioc->config_cmds.mutex);
return r;
}

@@ -1236,7 +1209,6 @@ mpt2sas_config_get_expander_pg1(struct M
int r;
struct config_request mem;

- mutex_lock(&ioc->config_cmds.mutex);
memset(config_page, 0, sizeof(Mpi2ExpanderPage1_t));
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -1283,7 +1255,6 @@ mpt2sas_config_get_expander_pg1(struct M
_config_free_config_dma_memory(ioc, &mem);

out:
- mutex_unlock(&ioc->config_cmds.mutex);
return r;
}

@@ -1306,7 +1277,6 @@ mpt2sas_config_get_enclosure_pg0(struct
int r;
struct config_request mem;

- mutex_lock(&ioc->config_cmds.mutex);
memset(config_page, 0, sizeof(Mpi2SasEnclosurePage0_t));
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -1351,7 +1321,6 @@ mpt2sas_config_get_enclosure_pg0(struct
_config_free_config_dma_memory(ioc, &mem);

out:
- mutex_unlock(&ioc->config_cmds.mutex);
return r;
}

@@ -1373,7 +1342,6 @@ mpt2sas_config_get_phy_pg0(struct MPT2SA
int r;
struct config_request mem;

- mutex_lock(&ioc->config_cmds.mutex);
memset(config_page, 0, sizeof(Mpi2SasPhyPage0_t));
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -1419,7 +1387,6 @@ mpt2sas_config_get_phy_pg0(struct MPT2SA
_config_free_config_dma_memory(ioc, &mem);

out:
- mutex_unlock(&ioc->config_cmds.mutex);
return r;
}

@@ -1441,7 +1408,6 @@ mpt2sas_config_get_phy_pg1(struct MPT2SA
int r;
struct config_request mem;

- mutex_lock(&ioc->config_cmds.mutex);
memset(config_page, 0, sizeof(Mpi2SasPhyPage1_t));
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -1487,7 +1453,6 @@ mpt2sas_config_get_phy_pg1(struct MPT2SA
_config_free_config_dma_memory(ioc, &mem);

out:
- mutex_unlock(&ioc->config_cmds.mutex);
return r;
}

@@ -1511,7 +1476,6 @@ mpt2sas_config_get_raid_volume_pg1(struc
int r;
struct config_request mem;

- mutex_lock(&ioc->config_cmds.mutex);
memset(config_page, 0, sizeof(Mpi2RaidVolPage1_t));
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -1554,7 +1518,6 @@ mpt2sas_config_get_raid_volume_pg1(struc
_config_free_config_dma_memory(ioc, &mem);

out:
- mutex_unlock(&ioc->config_cmds.mutex);
return r;
}

@@ -1578,7 +1541,6 @@ mpt2sas_config_get_number_pds(struct MPT
struct config_request mem;
u16 ioc_status;

- mutex_lock(&ioc->config_cmds.mutex);
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
*num_pds = 0;
mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -1626,7 +1588,6 @@ mpt2sas_config_get_number_pds(struct MPT
_config_free_config_dma_memory(ioc, &mem);

out:
- mutex_unlock(&ioc->config_cmds.mutex);
return r;
}

@@ -1651,7 +1612,6 @@ mpt2sas_config_get_raid_volume_pg0(struc
int r;
struct config_request mem;

- mutex_lock(&ioc->config_cmds.mutex);
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
memset(config_page, 0, sz);
mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -1693,7 +1653,6 @@ mpt2sas_config_get_raid_volume_pg0(struc
_config_free_config_dma_memory(ioc, &mem);

out:
- mutex_unlock(&ioc->config_cmds.mutex);
return r;
}

@@ -1717,7 +1676,6 @@ mpt2sas_config_get_phys_disk_pg0(struct
int r;
struct config_request mem;

- mutex_lock(&ioc->config_cmds.mutex);
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
memset(config_page, 0, sizeof(Mpi2RaidPhysDiskPage0_t));
mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -1760,7 +1718,6 @@ mpt2sas_config_get_phys_disk_pg0(struct
_config_free_config_dma_memory(ioc, &mem);

out:
- mutex_unlock(&ioc->config_cmds.mutex);
return r;
}

@@ -1784,7 +1741,6 @@ mpt2sas_config_get_volume_handle(struct
struct config_request mem;
u16 ioc_status;

- mutex_lock(&ioc->config_cmds.mutex);
*volume_handle = 0;
memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -1848,7 +1804,6 @@ mpt2sas_config_get_volume_handle(struct
_config_free_config_dma_memory(ioc, &mem);

out:
- mutex_unlock(&ioc->config_cmds.mutex);
return r;
}


2009-09-05 00:28:09

by Greg KH

[permalink] [raw]
Subject: [patch 46/71] do_sigaltstack: avoid copying stack_t as a structure to user space

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

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

commit 0083fc2c50e6c5127c2802ad323adf8143ab7856 upstream.

Ulrich Drepper correctly points out that there is generally padding in
the structure on 64-bit hosts, and that copying the structure from
kernel to user space can leak information from the kernel stack in those
padding bytes.

Avoid the whole issue by just copying the three members one by one
instead, which also means that the function also can avoid the need for
a stack frame. This also happens to match how we copy the new structure
from user space, so it all even makes sense.

[ The obvious solution of adding a memset() generates horrid code, gcc
does really stupid things. ]

Reported-by: Ulrich Drepper <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
kernel/signal.c | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)

--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -2414,11 +2414,9 @@ do_sigaltstack (const stack_t __user *us
stack_t oss;
int error;

- if (uoss) {
- oss.ss_sp = (void __user *) current->sas_ss_sp;
- oss.ss_size = current->sas_ss_size;
- oss.ss_flags = sas_ss_flags(sp);
- }
+ oss.ss_sp = (void __user *) current->sas_ss_sp;
+ oss.ss_size = current->sas_ss_size;
+ oss.ss_flags = sas_ss_flags(sp);

if (uss) {
void __user *ss_sp;
@@ -2461,13 +2459,16 @@ do_sigaltstack (const stack_t __user *us
current->sas_ss_size = ss_size;
}

+ error = 0;
if (uoss) {
error = -EFAULT;
- if (copy_to_user(uoss, &oss, sizeof(oss)))
+ if (!access_ok(VERIFY_WRITE, uoss, sizeof(*uoss)))
goto out;
+ error = __put_user(oss.ss_sp, &uoss->ss_sp) |
+ __put_user(oss.ss_size, &uoss->ss_size) |
+ __put_user(oss.ss_flags, &uoss->ss_flags);
}

- error = 0;
out:
return error;
}

2009-09-05 00:28:12

by Greg KH

[permalink] [raw]
Subject: [patch 47/71] Bug Fix arch/ia64/kernel/pci-dma.c: fix recursive dma_supported() call in iommu_dma_supported()

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

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

commit 51b89f7a6615eca184aa0b85db5781d931e9c8d1 upstream.

In commit 160c1d8e40866edfeae7d68816b7005d70acf391,
dma_ops->dma_supported = iommu_dma_supported;

This dma_ops->dma_supported is first called in platform_dma_init() during kernel
boot. Then dma_ops->dma_supported will be called recursively in
iommu_dma_supported.

Kernel can not boot because kernel can not get out of iommu_dma_supported until
it runs out of stack memory.

Signed-off-by: Fenghua Yu <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
arch/ia64/kernel/pci-dma.c | 5 -----
1 file changed, 5 deletions(-)

--- a/arch/ia64/kernel/pci-dma.c
+++ b/arch/ia64/kernel/pci-dma.c
@@ -67,11 +67,6 @@ iommu_dma_init(void)

int iommu_dma_supported(struct device *dev, u64 mask)
{
- struct dma_map_ops *ops = platform_dma_get_ops(dev);
-
- if (ops->dma_supported)
- return ops->dma_supported(dev, mask);
-
/* Copied from i386. Doesn't make much sense, because it will
only work for pci_alloc_coherent.
The caller just has to use GFP_DMA in this case. */

2009-09-05 00:22:58

by Greg KH

[permalink] [raw]
Subject: [patch 48/71] x86, amd: Dont probe for extended APIC ID if APICs are disabled

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

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

commit 2cb078603abb612e3bcd428fb8122c3d39e08832 upstream.

If we've logically disabled apics, don't probe the PCI space for the
AMD extended APIC ID.

[ Impact: prevent boot crash under Xen. ]

Signed-off-by: Jeremy Fitzhardinge <[email protected]>
Reported-by: Bastian Blank <[email protected]>
Signed-off-by: H. Peter Anvin <[email protected]>
Cc: Andreas Herrmann <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
arch/x86/kernel/cpu/amd.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -356,7 +356,7 @@ static void __cpuinit early_init_amd(str
#endif
#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_PCI)
/* check CPU config space for extended APIC ID */
- if (c->x86 >= 0xf) {
+ if (cpu_has_apic && c->x86 >= 0xf) {
unsigned int val;
val = read_pci_config(0, 24, 0, 0x68);
if ((val & ((1 << 17) | (1 << 18))) == ((1 << 17) | (1 << 18)))

2009-09-05 00:28:47

by Greg KH

[permalink] [raw]
Subject: [patch 49/71] ocfs2: Initialize the cluster were writing to in a non-sparse extend

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

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

commit e7432675f8ca868a4af365759a8d4c3779a3d922 upstream.

In a non-sparse extend, we correctly allocate (and zero) the clusters between
the old_i_size and pos, but we don't zero the portions of the cluster we're
writing to outside of pos<->len.

It handles clustersize > pagesize and blocksize < pagesize.

[Cleaned up by Joel Becker.]

Signed-off-by: Sunil Mushran <[email protected]>
Signed-off-by: Joel Becker <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
fs/ocfs2/aops.c | 66 +++++++++++++++++++++++++++++++++++++++-----------------
1 file changed, 47 insertions(+), 19 deletions(-)

--- a/fs/ocfs2/aops.c
+++ b/fs/ocfs2/aops.c
@@ -894,18 +894,17 @@ struct ocfs2_write_cluster_desc {
*/
unsigned c_new;
unsigned c_unwritten;
+ unsigned c_needs_zero;
};

-static inline int ocfs2_should_zero_cluster(struct ocfs2_write_cluster_desc *d)
-{
- return d->c_new || d->c_unwritten;
-}
-
struct ocfs2_write_ctxt {
/* Logical cluster position / len of write */
u32 w_cpos;
u32 w_clen;

+ /* First cluster allocated in a nonsparse extend */
+ u32 w_first_new_cpos;
+
struct ocfs2_write_cluster_desc w_desc[OCFS2_MAX_CLUSTERS_PER_PAGE];

/*
@@ -983,6 +982,7 @@ static int ocfs2_alloc_write_ctxt(struct
return -ENOMEM;

wc->w_cpos = pos >> osb->s_clustersize_bits;
+ wc->w_first_new_cpos = UINT_MAX;
cend = (pos + len - 1) >> osb->s_clustersize_bits;
wc->w_clen = cend - wc->w_cpos + 1;
get_bh(di_bh);
@@ -1217,20 +1217,18 @@ out:
*/
static int ocfs2_write_cluster(struct address_space *mapping,
u32 phys, unsigned int unwritten,
+ unsigned int should_zero,
struct ocfs2_alloc_context *data_ac,
struct ocfs2_alloc_context *meta_ac,
struct ocfs2_write_ctxt *wc, u32 cpos,
loff_t user_pos, unsigned user_len)
{
- int ret, i, new, should_zero = 0;
+ int ret, i, new;
u64 v_blkno, p_blkno;
struct inode *inode = mapping->host;
struct ocfs2_extent_tree et;

new = phys == 0 ? 1 : 0;
- if (new || unwritten)
- should_zero = 1;
-
if (new) {
u32 tmp_pos;

@@ -1341,7 +1339,9 @@ static int ocfs2_write_cluster_by_desc(s
local_len = osb->s_clustersize - cluster_off;

ret = ocfs2_write_cluster(mapping, desc->c_phys,
- desc->c_unwritten, data_ac, meta_ac,
+ desc->c_unwritten,
+ desc->c_needs_zero,
+ data_ac, meta_ac,
wc, desc->c_cpos, pos, local_len);
if (ret) {
mlog_errno(ret);
@@ -1391,14 +1391,14 @@ static void ocfs2_set_target_boundaries(
* newly allocated cluster.
*/
desc = &wc->w_desc[0];
- if (ocfs2_should_zero_cluster(desc))
+ if (desc->c_needs_zero)
ocfs2_figure_cluster_boundaries(osb,
desc->c_cpos,
&wc->w_target_from,
NULL);

desc = &wc->w_desc[wc->w_clen - 1];
- if (ocfs2_should_zero_cluster(desc))
+ if (desc->c_needs_zero)
ocfs2_figure_cluster_boundaries(osb,
desc->c_cpos,
NULL,
@@ -1466,13 +1466,28 @@ static int ocfs2_populate_write_desc(str
phys++;
}

+ /*
+ * If w_first_new_cpos is < UINT_MAX, we have a non-sparse
+ * file that got extended. w_first_new_cpos tells us
+ * where the newly allocated clusters are so we can
+ * zero them.
+ */
+ if (desc->c_cpos >= wc->w_first_new_cpos) {
+ BUG_ON(phys == 0);
+ desc->c_needs_zero = 1;
+ }
+
desc->c_phys = phys;
if (phys == 0) {
desc->c_new = 1;
+ desc->c_needs_zero = 1;
*clusters_to_alloc = *clusters_to_alloc + 1;
}
- if (ext_flags & OCFS2_EXT_UNWRITTEN)
+
+ if (ext_flags & OCFS2_EXT_UNWRITTEN) {
desc->c_unwritten = 1;
+ desc->c_needs_zero = 1;
+ }

num_clusters--;
}
@@ -1632,10 +1647,13 @@ static int ocfs2_expand_nonsparse_inode(
if (newsize <= i_size_read(inode))
return 0;

- ret = ocfs2_extend_no_holes(inode, newsize, newsize - len);
+ ret = ocfs2_extend_no_holes(inode, newsize, pos);
if (ret)
mlog_errno(ret);

+ wc->w_first_new_cpos =
+ ocfs2_clusters_for_bytes(inode->i_sb, i_size_read(inode));
+
return ret;
}

@@ -1644,7 +1662,7 @@ int ocfs2_write_begin_nolock(struct addr
struct page **pagep, void **fsdata,
struct buffer_head *di_bh, struct page *mmap_page)
{
- int ret, credits = OCFS2_INODE_UPDATE_CREDITS;
+ int ret, cluster_of_pages, credits = OCFS2_INODE_UPDATE_CREDITS;
unsigned int clusters_to_alloc, extents_to_split;
struct ocfs2_write_ctxt *wc;
struct inode *inode = mapping->host;
@@ -1722,8 +1740,19 @@ int ocfs2_write_begin_nolock(struct addr

}

- ocfs2_set_target_boundaries(osb, wc, pos, len,
- clusters_to_alloc + extents_to_split);
+ /*
+ * We have to zero sparse allocated clusters, unwritten extent clusters,
+ * and non-sparse clusters we just extended. For non-sparse writes,
+ * we know zeros will only be needed in the first and/or last cluster.
+ */
+ if (clusters_to_alloc || extents_to_split ||
+ wc->w_desc[0].c_needs_zero ||
+ wc->w_desc[wc->w_clen - 1].c_needs_zero)
+ cluster_of_pages = 1;
+ else
+ cluster_of_pages = 0;
+
+ ocfs2_set_target_boundaries(osb, wc, pos, len, cluster_of_pages);

handle = ocfs2_start_trans(osb, credits);
if (IS_ERR(handle)) {
@@ -1756,8 +1785,7 @@ int ocfs2_write_begin_nolock(struct addr
* extent.
*/
ret = ocfs2_grab_pages_for_write(mapping, wc, wc->w_cpos, pos,
- clusters_to_alloc + extents_to_split,
- mmap_page);
+ cluster_of_pages, mmap_page);
if (ret) {
mlog_errno(ret);
goto out_quota;

2009-09-05 00:27:27

by Greg KH

[permalink] [raw]
Subject: [patch 50/71] ACPI processor: force throttling state when BIOS returns incorrect value

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

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

commit 2a908002c7b1b666616103e9df2419b38d7c6f1f upstream.

If the BIOS reports an invalid throttling state (which seems to be
fairly common after system boot), a reset is done to state T0.
Because of a check in acpi_processor_get_throttling_ptc(), the reset
never actually gets executed, which results in the error reoccurring
on every access of for example /proc/acpi/processor/CPU0/throttling.

Add a 'force' option to acpi_processor_set_throttling() to ensure
the reset really takes effect.

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

This patch, together with the next one, fixes a regression introduced in
2.6.30, listed on the regression list. They have been available for 2.5
months now in bugzilla, but have not been picked up, despite various
reminders and without any reason given.

Google shows that numerous people are hitting this issue. The issue is in
itself relatively minor, but the bug in the code is clear.

The patches have been in all my kernels and today testing has shown that
throttling works correctly with the patches applied when the system
overheats (http://bugzilla.kernel.org/show_bug.cgi?id=13918#c14).

Signed-off-by: Frans Pop <[email protected]>
Acked-by: Zhang Rui <[email protected]>
Cc: Len Brown <[email protected]>
Cc: "Rafael J. Wysocki" <[email protected]>
Cc: Rusty Russell <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
drivers/acpi/processor_thermal.c | 6 +++---
drivers/acpi/processor_throttling.c | 26 ++++++++++++++------------
include/acpi/processor.h | 5 +++--
3 files changed, 20 insertions(+), 17 deletions(-)

--- a/drivers/acpi/processor_thermal.c
+++ b/drivers/acpi/processor_thermal.c
@@ -66,7 +66,7 @@ static int acpi_processor_apply_limit(st
if (pr->limit.thermal.tx > tx)
tx = pr->limit.thermal.tx;

- result = acpi_processor_set_throttling(pr, tx);
+ result = acpi_processor_set_throttling(pr, tx, false);
if (result)
goto end;
}
@@ -421,12 +421,12 @@ processor_set_cur_state(struct thermal_c

if (state <= max_pstate) {
if (pr->flags.throttling && pr->throttling.state)
- result = acpi_processor_set_throttling(pr, 0);
+ result = acpi_processor_set_throttling(pr, 0, false);
cpufreq_set_cur_state(pr->id, state);
} else {
cpufreq_set_cur_state(pr->id, max_pstate);
result = acpi_processor_set_throttling(pr,
- state - max_pstate);
+ state - max_pstate, false);
}
return result;
}
--- a/drivers/acpi/processor_throttling.c
+++ b/drivers/acpi/processor_throttling.c
@@ -62,7 +62,8 @@ struct throttling_tstate {
#define THROTTLING_POSTCHANGE (2)

static int acpi_processor_get_throttling(struct acpi_processor *pr);
-int acpi_processor_set_throttling(struct acpi_processor *pr, int state);
+int acpi_processor_set_throttling(struct acpi_processor *pr,
+ int state, bool force);

static int acpi_processor_update_tsd_coord(void)
{
@@ -361,7 +362,7 @@ int acpi_processor_tstate_has_changed(st
*/
target_state = throttling_limit;
}
- return acpi_processor_set_throttling(pr, target_state);
+ return acpi_processor_set_throttling(pr, target_state, false);
}

/*
@@ -842,7 +843,7 @@ static int acpi_processor_get_throttling
ACPI_WARNING((AE_INFO,
"Invalid throttling state, reset"));
state = 0;
- ret = acpi_processor_set_throttling(pr, state);
+ ret = acpi_processor_set_throttling(pr, state, true);
if (ret)
return ret;
}
@@ -915,7 +916,7 @@ static int acpi_processor_get_fadt_info(
}

static int acpi_processor_set_throttling_fadt(struct acpi_processor *pr,
- int state)
+ int state, bool force)
{
u32 value = 0;
u32 duty_mask = 0;
@@ -930,7 +931,7 @@ static int acpi_processor_set_throttling
if (!pr->flags.throttling)
return -ENODEV;

- if (state == pr->throttling.state)
+ if (!force && (state == pr->throttling.state))
return 0;

if (state < pr->throttling_platform_limit)
@@ -988,7 +989,7 @@ static int acpi_processor_set_throttling
}

static int acpi_processor_set_throttling_ptc(struct acpi_processor *pr,
- int state)
+ int state, bool force)
{
int ret;
acpi_integer value;
@@ -1002,7 +1003,7 @@ static int acpi_processor_set_throttling
if (!pr->flags.throttling)
return -ENODEV;

- if (state == pr->throttling.state)
+ if (!force && (state == pr->throttling.state))
return 0;

if (state < pr->throttling_platform_limit)
@@ -1018,7 +1019,8 @@ static int acpi_processor_set_throttling
return 0;
}

-int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
+int acpi_processor_set_throttling(struct acpi_processor *pr,
+ int state, bool force)
{
cpumask_var_t saved_mask;
int ret = 0;
@@ -1070,7 +1072,7 @@ int acpi_processor_set_throttling(struct
/* FIXME: use work_on_cpu() */
set_cpus_allowed_ptr(current, cpumask_of(pr->id));
ret = p_throttling->acpi_processor_set_throttling(pr,
- t_state.target_state);
+ t_state.target_state, force);
} else {
/*
* When the T-state coordination is SW_ALL or HW_ALL,
@@ -1103,7 +1105,7 @@ int acpi_processor_set_throttling(struct
set_cpus_allowed_ptr(current, cpumask_of(i));
ret = match_pr->throttling.
acpi_processor_set_throttling(
- match_pr, t_state.target_state);
+ match_pr, t_state.target_state, force);
}
}
/*
@@ -1201,7 +1203,7 @@ int acpi_processor_get_throttling_info(s
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Disabling throttling (was T%d)\n",
pr->throttling.state));
- result = acpi_processor_set_throttling(pr, 0);
+ result = acpi_processor_set_throttling(pr, 0, false);
if (result)
goto end;
}
@@ -1307,7 +1309,7 @@ static ssize_t acpi_processor_write_thro
if (strcmp(tmpbuf, charp) != 0)
return -EINVAL;

- result = acpi_processor_set_throttling(pr, state_val);
+ result = acpi_processor_set_throttling(pr, state_val, false);
if (result)
return result;

--- a/include/acpi/processor.h
+++ b/include/acpi/processor.h
@@ -174,7 +174,7 @@ struct acpi_processor_throttling {
cpumask_var_t shared_cpu_map;
int (*acpi_processor_get_throttling) (struct acpi_processor * pr);
int (*acpi_processor_set_throttling) (struct acpi_processor * pr,
- int state);
+ int state, bool force);

u32 address;
u8 duty_offset;
@@ -320,7 +320,8 @@ static inline int acpi_processor_ppc_has
/* in processor_throttling.c */
int acpi_processor_tstate_has_changed(struct acpi_processor *pr);
int acpi_processor_get_throttling_info(struct acpi_processor *pr);
-extern int acpi_processor_set_throttling(struct acpi_processor *pr, int state);
+extern int acpi_processor_set_throttling(struct acpi_processor *pr,
+ int state, bool force);
extern const struct file_operations acpi_processor_throttling_fops;
extern void acpi_processor_throttling_init(void);
/* in processor_idle.c */

2009-09-05 00:27:46

by Greg KH

[permalink] [raw]
Subject: [patch 51/71] vfs: fix inode_init_always calling convention

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

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

backport of upstream commit 54e346215e4fe2ca8c94c54e546cc61902060510

Currently inode_init_always calls into ->destroy_inode if the additional
initialization fails. That's not only counter-intuitive because
inode_init_always did not allocate the inode structure, but in case of
XFS it's actively harmful as ->destroy_inode might delete the inode from
a radix-tree that has never been added. This in turn might end up
deleting the inode for the same inum that has been instanciated by
another process and cause lots of cause subtile problems.

Also in the case of re-initializing a reclaimable inode in XFS it would
free an inode we still want to keep alive.

Signed-off-by: Christoph Hellwig <[email protected]>
Reviewed-by: Eric Sandeen <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
fs/inode.c | 30 +++++++++++++++++-------------
fs/xfs/xfs_iget.c | 17 +++++------------
include/linux/fs.h | 2 +-
3 files changed, 23 insertions(+), 26 deletions(-)

--- a/fs/inode.c
+++ b/fs/inode.c
@@ -118,12 +118,11 @@ static void wake_up_inode(struct inode *
* These are initializations that need to be done on every inode
* allocation as the fields are not initialised by slab allocation.
*/
-struct inode *inode_init_always(struct super_block *sb, struct inode *inode)
+int inode_init_always(struct super_block *sb, struct inode *inode)
{
static const struct address_space_operations empty_aops;
static struct inode_operations empty_iops;
static const struct file_operations empty_fops;
-
struct address_space *const mapping = &inode->i_data;

inode->i_sb = sb;
@@ -150,7 +149,7 @@ struct inode *inode_init_always(struct s
inode->dirtied_when = 0;

if (security_inode_alloc(inode))
- goto out_free_inode;
+ goto out;

/* allocate and initialize an i_integrity */
if (ima_inode_alloc(inode))
@@ -189,16 +188,12 @@ struct inode *inode_init_always(struct s
inode->i_private = NULL;
inode->i_mapping = mapping;

- return inode;
+ return 0;

out_free_security:
security_inode_free(inode);
-out_free_inode:
- if (inode->i_sb->s_op->destroy_inode)
- inode->i_sb->s_op->destroy_inode(inode);
- else
- kmem_cache_free(inode_cachep, (inode));
- return NULL;
+out:
+ return -ENOMEM;
}
EXPORT_SYMBOL(inode_init_always);

@@ -211,9 +206,18 @@ static struct inode *alloc_inode(struct
else
inode = kmem_cache_alloc(inode_cachep, GFP_KERNEL);

- if (inode)
- return inode_init_always(sb, inode);
- return NULL;
+ if (!inode)
+ return NULL;
+
+ if (unlikely(inode_init_always(sb, inode))) {
+ if (inode->i_sb->s_op->destroy_inode)
+ inode->i_sb->s_op->destroy_inode(inode);
+ else
+ kmem_cache_free(inode_cachep, inode);
+ return NULL;
+ }
+
+ return inode;
}

void destroy_inode(struct inode *inode)
--- a/fs/xfs/xfs_iget.c
+++ b/fs/xfs/xfs_iget.c
@@ -63,6 +63,10 @@ xfs_inode_alloc(
ip = kmem_zone_alloc(xfs_inode_zone, KM_SLEEP);
if (!ip)
return NULL;
+ if (inode_init_always(mp->m_super, VFS_I(ip))) {
+ kmem_zone_free(xfs_inode_zone, ip);
+ return NULL;
+ }

ASSERT(atomic_read(&ip->i_iocount) == 0);
ASSERT(atomic_read(&ip->i_pincount) == 0);
@@ -104,17 +108,6 @@ xfs_inode_alloc(
#ifdef XFS_DIR2_TRACE
ip->i_dir_trace = ktrace_alloc(XFS_DIR2_KTRACE_SIZE, KM_NOFS);
#endif
- /*
- * Now initialise the VFS inode. We do this after the xfs_inode
- * initialisation as internal failures will result in ->destroy_inode
- * being called and that will pass down through the reclaim path and
- * free the XFS inode. This path requires the XFS inode to already be
- * initialised. Hence if this call fails, the xfs_inode has already
- * been freed and we should not reference it at all in the error
- * handling.
- */
- if (!inode_init_always(mp->m_super, VFS_I(ip)))
- return NULL;

/* prevent anyone from using this yet */
VFS_I(ip)->i_state = I_NEW|I_LOCK;
@@ -166,7 +159,7 @@ xfs_iget_cache_hit(
* errors cleanly, then tag it so it can be set up correctly
* later.
*/
- if (!inode_init_always(mp->m_super, VFS_I(ip))) {
+ if (inode_init_always(mp->m_super, VFS_I(ip))) {
error = ENOMEM;
goto out_error;
}
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2135,7 +2135,7 @@ extern loff_t default_llseek(struct file

extern loff_t vfs_llseek(struct file *file, loff_t offset, int origin);

-extern struct inode * inode_init_always(struct super_block *, struct inode *);
+extern int inode_init_always(struct super_block *, struct inode *);
extern void inode_init_once(struct inode *);
extern void inode_add_to_lists(struct super_block *, struct inode *);
extern void iput(struct inode *);

2009-09-05 00:27:04

by Greg KH

[permalink] [raw]
Subject: [patch 52/71] vfs: add __destroy_inode

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

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

backport of upstream commit 2e00c97e2c1d2ffc9e26252ca26b237678b0b772

When we want to tear down an inode that lost the add to the cache race
in XFS we must not call into ->destroy_inode because that would delete
the inode that won the race from the inode cache radix tree.

This patch provides the __destroy_inode helper needed to fix this,
the actual fix will be in th next patch. As XFS was the only reason
destroy_inode was exported we shift the export to the new __destroy_inode.

Signed-off-by: Christoph Hellwig <[email protected]>
Reviewed-by: Eric Sandeen <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
fs/inode.c | 10 +++++++---
include/linux/fs.h | 1 +
2 files changed, 8 insertions(+), 3 deletions(-)

--- a/fs/inode.c
+++ b/fs/inode.c
@@ -220,18 +220,22 @@ static struct inode *alloc_inode(struct
return inode;
}

-void destroy_inode(struct inode *inode)
+void __destroy_inode(struct inode *inode)
{
BUG_ON(inode_has_buffers(inode));
ima_inode_free(inode);
security_inode_free(inode);
+}
+EXPORT_SYMBOL(__destroy_inode);
+
+void destroy_inode(struct inode *inode)
+{
+ __destroy_inode(inode);
if (inode->i_sb->s_op->destroy_inode)
inode->i_sb->s_op->destroy_inode(inode);
else
kmem_cache_free(inode_cachep, (inode));
}
-EXPORT_SYMBOL(destroy_inode);
-

/*
* These are initializations that only need to be done
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2162,6 +2162,7 @@ extern void __iget(struct inode * inode)
extern void iget_failed(struct inode *);
extern void clear_inode(struct inode *);
extern void destroy_inode(struct inode *);
+extern void __destroy_inode(struct inode *);
extern struct inode *new_inode(struct super_block *);
extern int should_remove_suid(struct dentry *);
extern int file_remove_suid(struct file *);

2009-09-05 00:26:31

by Greg KH

[permalink] [raw]
Subject: [patch 53/71] xfs: fix freeing of inodes not yet added to the inode cache

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

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

upstream commit b36ec0428a06fcbdb67d61e9e664154e5dd9a8c7

When freeing an inode that lost race getting added to the inode cache we
must not call into ->destroy_inode, because that would delete the inode
that won the race from the inode cache radix tree.

This patch uses splits a new xfs_inode_free helper out of xfs_ireclaim
and uses that plus __destroy_inode to make sure we really only free
the memory allocted for the inode that lost the race, and not mess with
the inode cache state.

Signed-off-by: Christoph Hellwig <[email protected]>
Reviewed-by: Eric Sandeen <[email protected]>
Reported-by: Alex Samad <[email protected]>
Reported-by: Andrew Randrianasulu <[email protected]>
Reported-by: Stephane <[email protected]>
Reported-by: Tommy <[email protected]>
Reported-by: Miah Gregory <[email protected]>
Reported-by: Gabriel Barazer <[email protected]>
Reported-by: Leandro Lucarella <[email protected]>
Reported-by: Daniel Burr <[email protected]>
Reported-by: Nickolay <[email protected]>
Reported-by: Michael Guntsche <[email protected]>
Reported-by: Dan Carley <[email protected]>
Reported-by: Michael Ole Olsen <[email protected]>
Reported-by: Michael Weissenbacher <[email protected]>
Reported-by: Martin Spott <[email protected]>
Reported-by: Christian Kujau <[email protected]>
Tested-by: Michael Guntsche <[email protected]>
Tested-by: Dan Carley <[email protected]>
Tested-by: Christian Kujau <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
fs/xfs/xfs_iget.c | 125 ++++++++++++++++++++++++++++-------------------------
fs/xfs/xfs_inode.h | 17 -------
2 files changed, 68 insertions(+), 74 deletions(-)

--- a/fs/xfs/xfs_iget.c
+++ b/fs/xfs/xfs_iget.c
@@ -115,6 +115,71 @@ xfs_inode_alloc(
return ip;
}

+STATIC void
+xfs_inode_free(
+ struct xfs_inode *ip)
+{
+ switch (ip->i_d.di_mode & S_IFMT) {
+ case S_IFREG:
+ case S_IFDIR:
+ case S_IFLNK:
+ xfs_idestroy_fork(ip, XFS_DATA_FORK);
+ break;
+ }
+
+ if (ip->i_afp)
+ xfs_idestroy_fork(ip, XFS_ATTR_FORK);
+
+#ifdef XFS_INODE_TRACE
+ ktrace_free(ip->i_trace);
+#endif
+#ifdef XFS_BMAP_TRACE
+ ktrace_free(ip->i_xtrace);
+#endif
+#ifdef XFS_BTREE_TRACE
+ ktrace_free(ip->i_btrace);
+#endif
+#ifdef XFS_RW_TRACE
+ ktrace_free(ip->i_rwtrace);
+#endif
+#ifdef XFS_ILOCK_TRACE
+ ktrace_free(ip->i_lock_trace);
+#endif
+#ifdef XFS_DIR2_TRACE
+ ktrace_free(ip->i_dir_trace);
+#endif
+
+ if (ip->i_itemp) {
+ /*
+ * Only if we are shutting down the fs will we see an
+ * inode still in the AIL. If it is there, we should remove
+ * it to prevent a use-after-free from occurring.
+ */
+ xfs_log_item_t *lip = &ip->i_itemp->ili_item;
+ struct xfs_ail *ailp = lip->li_ailp;
+
+ ASSERT(((lip->li_flags & XFS_LI_IN_AIL) == 0) ||
+ XFS_FORCED_SHUTDOWN(ip->i_mount));
+ if (lip->li_flags & XFS_LI_IN_AIL) {
+ spin_lock(&ailp->xa_lock);
+ if (lip->li_flags & XFS_LI_IN_AIL)
+ xfs_trans_ail_delete(ailp, lip);
+ else
+ spin_unlock(&ailp->xa_lock);
+ }
+ xfs_inode_item_destroy(ip);
+ ip->i_itemp = NULL;
+ }
+
+ /* asserts to verify all state is correct here */
+ ASSERT(atomic_read(&ip->i_iocount) == 0);
+ ASSERT(atomic_read(&ip->i_pincount) == 0);
+ ASSERT(!spin_is_locked(&ip->i_flags_lock));
+ ASSERT(completion_done(&ip->i_flush));
+
+ kmem_zone_free(xfs_inode_zone, ip);
+}
+
/*
* Check the validity of the inode we just found it the cache
*/
@@ -291,7 +356,8 @@ out_preload_end:
if (lock_flags)
xfs_iunlock(ip, lock_flags);
out_destroy:
- xfs_destroy_inode(ip);
+ __destroy_inode(VFS_I(ip));
+ xfs_inode_free(ip);
return error;
}

@@ -499,62 +565,7 @@ xfs_ireclaim(
XFS_QM_DQDETACH(ip->i_mount, ip);
xfs_iunlock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);

- switch (ip->i_d.di_mode & S_IFMT) {
- case S_IFREG:
- case S_IFDIR:
- case S_IFLNK:
- xfs_idestroy_fork(ip, XFS_DATA_FORK);
- break;
- }
-
- if (ip->i_afp)
- xfs_idestroy_fork(ip, XFS_ATTR_FORK);
-
-#ifdef XFS_INODE_TRACE
- ktrace_free(ip->i_trace);
-#endif
-#ifdef XFS_BMAP_TRACE
- ktrace_free(ip->i_xtrace);
-#endif
-#ifdef XFS_BTREE_TRACE
- ktrace_free(ip->i_btrace);
-#endif
-#ifdef XFS_RW_TRACE
- ktrace_free(ip->i_rwtrace);
-#endif
-#ifdef XFS_ILOCK_TRACE
- ktrace_free(ip->i_lock_trace);
-#endif
-#ifdef XFS_DIR2_TRACE
- ktrace_free(ip->i_dir_trace);
-#endif
- if (ip->i_itemp) {
- /*
- * Only if we are shutting down the fs will we see an
- * inode still in the AIL. If it is there, we should remove
- * it to prevent a use-after-free from occurring.
- */
- xfs_log_item_t *lip = &ip->i_itemp->ili_item;
- struct xfs_ail *ailp = lip->li_ailp;
-
- ASSERT(((lip->li_flags & XFS_LI_IN_AIL) == 0) ||
- XFS_FORCED_SHUTDOWN(ip->i_mount));
- if (lip->li_flags & XFS_LI_IN_AIL) {
- spin_lock(&ailp->xa_lock);
- if (lip->li_flags & XFS_LI_IN_AIL)
- xfs_trans_ail_delete(ailp, lip);
- else
- spin_unlock(&ailp->xa_lock);
- }
- xfs_inode_item_destroy(ip);
- ip->i_itemp = NULL;
- }
- /* asserts to verify all state is correct here */
- ASSERT(atomic_read(&ip->i_iocount) == 0);
- ASSERT(atomic_read(&ip->i_pincount) == 0);
- ASSERT(!spin_is_locked(&ip->i_flags_lock));
- ASSERT(completion_done(&ip->i_flush));
- kmem_zone_free(xfs_inode_zone, ip);
+ xfs_inode_free(ip);
}

/*
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -309,23 +309,6 @@ static inline struct inode *VFS_I(struct
}

/*
- * Get rid of a partially initialized inode.
- *
- * We have to go through destroy_inode to make sure allocations
- * from init_inode_always like the security data are undone.
- *
- * We mark the inode bad so that it takes the short cut in
- * the reclaim path instead of going through the flush path
- * which doesn't make sense for an inode that has never seen the
- * light of day.
- */
-static inline void xfs_destroy_inode(struct xfs_inode *ip)
-{
- make_bad_inode(VFS_I(ip));
- return destroy_inode(VFS_I(ip));
-}
-
-/*
* i_flags helper functions
*/
static inline void

2009-09-05 00:26:21

by Greg KH

[permalink] [raw]
Subject: [patch 54/71] xfs: fix spin_is_locked assert on uni-processor builds

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

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

upstream commit a8914f3a6d72c97328597a556a99daaf5cc288ae

Without SMP or preemption spin_is_locked always returns false,
so we can't do an assert with it. Instead use assert_spin_locked,
which does the right thing on all builds.


Signed-off-by: Christoph Hellwig <[email protected]>
Reviewed-by: Eric Sandeen <[email protected]>
Reported-by: Johannes Engel <[email protected]>
Tested-by: Johannes Engel <[email protected]>
Signed-off-by: Felix Blyakher <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
fs/xfs/xfs_log.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -3180,7 +3180,7 @@ try_again:
STATIC void
xlog_state_want_sync(xlog_t *log, xlog_in_core_t *iclog)
{
- ASSERT(spin_is_locked(&log->l_icloglock));
+ assert_spin_locked(&log->l_icloglock);

if (iclog->ic_state == XLOG_STATE_ACTIVE) {
xlog_state_switch_iclogs(log, iclog, 0);

2009-09-05 00:26:16

by Greg KH

[permalink] [raw]
Subject: [patch 55/71] gspca - ov534: Fix ov772x

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

------------------
From: Jean-Francois Moine <[email protected]>

The scan of the image packets of the sensor ov772x was broken when
the sensor ov965x was added.

[ Based on upstream c874f3aa, modified slightly for v2.6.30.5 ]

Signed-off-by: Jim Paris <[email protected]>
Acked-by: Jean-Francois Moine <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
drivers/media/video/gspca/ov534.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)

--- a/drivers/media/video/gspca/ov534.c
+++ b/drivers/media/video/gspca/ov534.c
@@ -832,9 +832,11 @@ static void sd_pkt_scan(struct gspca_dev
__u32 this_pts;
u16 this_fid;
int remaining_len = len;
+ int payload_len;

+ payload_len = (sd->sensor == SENSOR_OV772X) ? 2048 : 2040;
do {
- len = min(remaining_len, 2040); /*fixme: was 2048*/
+ len = min(remaining_len, payload_len);

/* Payloads are prefixed with a UVC-style header. We
consider a frame to start when the FID toggles, or the PTS

2009-09-05 00:25:52

by Greg KH

[permalink] [raw]
Subject: [patch 56/71] kthreads: fix kthread_create() vs kthread_stop() race

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

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

The bug should be "accidently" fixed by recent changes in 2.6.31,
all kernels <= 2.6.30 need the fix. The problem was never noticed before,
it was found because it causes mysterious failures with GFS mount/umount.

Credits to Robert Peterson. He blaimed kthread.c from the very beginning.
But, despite my promise, I forgot to inspect the old implementation until
he did a lot of testing and reminded me. This led to huge delay in fixing
this bug.

kthread_stop() does put_task_struct(k) before it clears kthread_stop_info.k.
This means another kthread_create() can re-use this task_struct, but the
new kthread can still see kthread_should_stop() == T and exit even without
calling threadfn().

Reported-by: Robert Peterson <[email protected]>
Tested-by: Robert Peterson <[email protected]>
Signed-off-by: Oleg Nesterov <[email protected]>
Acked-by: Rusty Russell <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
kernel/kthread.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

--- a/kernel/kthread.c
+++ b/kernel/kthread.c
@@ -216,12 +216,12 @@ int kthread_stop(struct task_struct *k)
/* Now set kthread_should_stop() to true, and wake it up. */
kthread_stop_info.k = k;
wake_up_process(k);
- put_task_struct(k);

/* Once it dies, reset stop ptr, gather result and we're done. */
wait_for_completion(&kthread_stop_info.done);
kthread_stop_info.k = NULL;
ret = kthread_stop_info.err;
+ put_task_struct(k);
mutex_unlock(&kthread_stop_lock);

trace_sched_kthread_stop_ret(ret);

2009-09-05 00:25:26

by Greg KH

[permalink] [raw]
Subject: [patch 57/71] ipv6: Fix commit 63d9950b08184e6531adceb65f64b429909cc101 (ipv6: Make v4-mapped bindings consistent with IPv4)

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

------------------
From: Bruno Prémont <[email protected]>

commit ca6982b858e1d08010c1d29d8e8255b2ac2ad70a upstream.

Commit 63d9950b08184e6531adceb65f64b429909cc101
(ipv6: Make v4-mapped bindings consistent with IPv4)
changes behavior of inet6_bind() for v4-mapped addresses so it should
behave the same way as inet_bind().

During this change setting of err to -EADDRNOTAVAIL got lost:

af_inet.c:469 inet_bind()
err = -EADDRNOTAVAIL;
if (!sysctl_ip_nonlocal_bind &&
!(inet->freebind || inet->transparent) &&
addr->sin_addr.s_addr != htonl(INADDR_ANY) &&
chk_addr_ret != RTN_LOCAL &&
chk_addr_ret != RTN_MULTICAST &&
chk_addr_ret != RTN_BROADCAST)
goto out;


af_inet6.c:463 inet6_bind()
if (addr_type == IPV6_ADDR_MAPPED) {
int chk_addr_ret;

/* Binding to v4-mapped address on a v6-only socket
* makes no sense
*/
if (np->ipv6only) {
err = -EINVAL;
goto out;
}

/* Reproduce AF_INET checks to make the bindings consitant */
v4addr = addr->sin6_addr.s6_addr32[3];
chk_addr_ret = inet_addr_type(net, v4addr);
if (!sysctl_ip_nonlocal_bind &&
!(inet->freebind || inet->transparent) &&
v4addr != htonl(INADDR_ANY) &&
chk_addr_ret != RTN_LOCAL &&
chk_addr_ret != RTN_MULTICAST &&
chk_addr_ret != RTN_BROADCAST)
goto out;
} else {


Signed-off-by: Bruno Prémont <[email protected]>
Signed-off-by: David S. Miller <[email protected]>

---
net/ipv6/af_inet6.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)

--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -294,8 +294,10 @@ int inet6_bind(struct socket *sock, stru
v4addr != htonl(INADDR_ANY) &&
chk_addr_ret != RTN_LOCAL &&
chk_addr_ret != RTN_MULTICAST &&
- chk_addr_ret != RTN_BROADCAST)
+ chk_addr_ret != RTN_BROADCAST) {
+ err = -EADDRNOTAVAIL;
goto out;
+ }
} else {
if (addr_type != IPV6_ADDR_ANY) {
struct net_device *dev = NULL;

2009-09-05 00:25:11

by Greg KH

[permalink] [raw]
Subject: [patch 58/71] USB: fix the clear_tt_buffer interface

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

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

commit cb88a1b887bb8908f6e00ce29e893ea52b074940 upstream.

This patch (as1255) updates the interface for calling
usb_hub_clear_tt_buffer(). Even the name of the function is changed!

When an async URB (i.e., Control or Bulk) going through a high-speed
hub to a non-high-speed device is cancelled or fails, the hub's
Transaction Translator buffer may be left busy still trying to
complete the transaction. The buffer has to be cleared; that's what
usb_hub_clear_tt_buffer() does.

It isn't safe to send any more URBs to the same endpoint until the TT
buffer is fully clear. Therefore the HCD needs to be told when the
Clear-TT-Buffer request has finished. This patch adds a callback
method to struct hc_driver for that purpose, and makes the hub driver
invoke the callback at the proper time.

The patch also changes a couple of names; "hub_tt_kevent" and
"tt.kevent" now look rather antiquated.

Signed-off-by: Alan Stern <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
drivers/usb/core/hcd.h | 4 ++++
drivers/usb/core/hub.c | 40 ++++++++++++++++++++++++++--------------
drivers/usb/core/hub.h | 6 ++++--
drivers/usb/host/ehci-q.c | 2 +-
4 files changed, 35 insertions(+), 17 deletions(-)

--- a/drivers/usb/core/hcd.h
+++ b/drivers/usb/core/hcd.h
@@ -224,6 +224,10 @@ struct hc_driver {
void (*relinquish_port)(struct usb_hcd *, int);
/* has a port been handed over to a companion? */
int (*port_handed_over)(struct usb_hcd *, int);
+
+ /* CLEAR_TT_BUFFER completion callback */
+ void (*clear_tt_buffer_complete)(struct usb_hcd *,
+ struct usb_host_endpoint *);
};

extern int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb);
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -448,10 +448,10 @@ hub_clear_tt_buffer (struct usb_device *
* talking to TTs must queue control transfers (not just bulk and iso), so
* both can talk to the same hub concurrently.
*/
-static void hub_tt_kevent (struct work_struct *work)
+static void hub_tt_work(struct work_struct *work)
{
struct usb_hub *hub =
- container_of(work, struct usb_hub, tt.kevent);
+ container_of(work, struct usb_hub, tt.clear_work);
unsigned long flags;
int limit = 100;

@@ -460,6 +460,7 @@ static void hub_tt_kevent (struct work_s
struct list_head *temp;
struct usb_tt_clear *clear;
struct usb_device *hdev = hub->hdev;
+ const struct hc_driver *drv;
int status;

temp = hub->tt.clear_list.next;
@@ -469,21 +470,25 @@ static void hub_tt_kevent (struct work_s
/* drop lock so HCD can concurrently report other TT errors */
spin_unlock_irqrestore (&hub->tt.lock, flags);
status = hub_clear_tt_buffer (hdev, clear->devinfo, clear->tt);
- spin_lock_irqsave (&hub->tt.lock, flags);
-
if (status)
dev_err (&hdev->dev,
"clear tt %d (%04x) error %d\n",
clear->tt, clear->devinfo, status);
+
+ /* Tell the HCD, even if the operation failed */
+ drv = clear->hcd->driver;
+ if (drv->clear_tt_buffer_complete)
+ (drv->clear_tt_buffer_complete)(clear->hcd, clear->ep);
+
kfree(clear);
+ spin_lock_irqsave(&hub->tt.lock, flags);
}
spin_unlock_irqrestore (&hub->tt.lock, flags);
}

/**
- * usb_hub_tt_clear_buffer - clear control/bulk TT state in high speed hub
- * @udev: the device whose split transaction failed
- * @pipe: identifies the endpoint of the failed transaction
+ * usb_hub_clear_tt_buffer - clear control/bulk TT state in high speed hub
+ * @urb: an URB associated with the failed or incomplete split transaction
*
* High speed HCDs use this to tell the hub driver that some split control or
* bulk transaction failed in a way that requires clearing internal state of
@@ -493,8 +498,10 @@ static void hub_tt_kevent (struct work_s
* It may not be possible for that hub to handle additional full (or low)
* speed transactions until that state is fully cleared out.
*/
-void usb_hub_tt_clear_buffer (struct usb_device *udev, int pipe)
+int usb_hub_clear_tt_buffer(struct urb *urb)
{
+ struct usb_device *udev = urb->dev;
+ int pipe = urb->pipe;
struct usb_tt *tt = udev->tt;
unsigned long flags;
struct usb_tt_clear *clear;
@@ -506,7 +513,7 @@ void usb_hub_tt_clear_buffer (struct usb
if ((clear = kmalloc (sizeof *clear, GFP_ATOMIC)) == NULL) {
dev_err (&udev->dev, "can't save CLEAR_TT_BUFFER state\n");
/* FIXME recover somehow ... RESET_TT? */
- return;
+ return -ENOMEM;
}

/* info that CLEAR_TT_BUFFER needs */
@@ -518,14 +525,19 @@ void usb_hub_tt_clear_buffer (struct usb
: (USB_ENDPOINT_XFER_BULK << 11);
if (usb_pipein (pipe))
clear->devinfo |= 1 << 15;
-
+
+ /* info for completion callback */
+ clear->hcd = bus_to_hcd(udev->bus);
+ clear->ep = urb->ep;
+
/* tell keventd to clear state for this TT */
spin_lock_irqsave (&tt->lock, flags);
list_add_tail (&clear->clear_list, &tt->clear_list);
- schedule_work (&tt->kevent);
+ schedule_work(&tt->clear_work);
spin_unlock_irqrestore (&tt->lock, flags);
+ return 0;
}
-EXPORT_SYMBOL_GPL(usb_hub_tt_clear_buffer);
+EXPORT_SYMBOL_GPL(usb_hub_clear_tt_buffer);

/* If do_delay is false, return the number of milliseconds the caller
* needs to delay.
@@ -816,7 +828,7 @@ static void hub_quiesce(struct usb_hub *
if (hub->has_indicators)
cancel_delayed_work_sync(&hub->leds);
if (hub->tt.hub)
- cancel_work_sync(&hub->tt.kevent);
+ cancel_work_sync(&hub->tt.clear_work);
}

/* caller has locked the hub device */
@@ -933,7 +945,7 @@ static int hub_configure(struct usb_hub

spin_lock_init (&hub->tt.lock);
INIT_LIST_HEAD (&hub->tt.clear_list);
- INIT_WORK (&hub->tt.kevent, hub_tt_kevent);
+ INIT_WORK(&hub->tt.clear_work, hub_tt_work);
switch (hdev->descriptor.bDeviceProtocol) {
case 0:
break;
--- a/drivers/usb/core/hub.h
+++ b/drivers/usb/core/hub.h
@@ -185,16 +185,18 @@ struct usb_tt {
/* for control/bulk error recovery (CLEAR_TT_BUFFER) */
spinlock_t lock;
struct list_head clear_list; /* of usb_tt_clear */
- struct work_struct kevent;
+ struct work_struct clear_work;
};

struct usb_tt_clear {
struct list_head clear_list;
unsigned tt;
u16 devinfo;
+ struct usb_hcd *hcd;
+ struct usb_host_endpoint *ep;
};

-extern void usb_hub_tt_clear_buffer(struct usb_device *dev, int pipe);
+extern int usb_hub_clear_tt_buffer(struct urb *urb);
extern void usb_ep0_reinit(struct usb_device *);

#endif /* __LINUX_HUB_H */
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -215,7 +215,7 @@ static int qtd_copy_status (
/* REVISIT ARC-derived cores don't clear the root
* hub TT buffer in this way...
*/
- usb_hub_tt_clear_buffer (urb->dev, urb->pipe);
+ usb_hub_clear_tt_buffer(urb);
}
}


2009-09-05 00:21:50

by Greg KH

[permalink] [raw]
Subject: [patch 59/71] USB: EHCI: use the new clear_tt_buffer interface

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

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

commit 914b701280a76f96890ad63eb0fa99bf204b961c upstream.

This patch (as1256) changes ehci-hcd and all the other drivers in the
EHCI family to make use of the new clear_tt_buffer callbacks. When a
Clear-TT-Buffer request is in progress for a QH, the QH is not allowed
to be linked into the async schedule until the request is finished.
At that time, if there are any URBs queued for the QH, it is linked
into the async schedule.

Signed-off-by: Alan Stern <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
drivers/usb/host/ehci-au1xxx.c | 2
drivers/usb/host/ehci-fsl.c | 2
drivers/usb/host/ehci-hcd.c | 2
drivers/usb/host/ehci-ixp4xx.c | 2
drivers/usb/host/ehci-orion.c | 2
drivers/usb/host/ehci-pci.c | 2
drivers/usb/host/ehci-ppc-of.c | 2
drivers/usb/host/ehci-ps3.c | 2
drivers/usb/host/ehci-q.c | 91 ++++++++++++++++++++++++++++++-----------
drivers/usb/host/ehci.h | 2
10 files changed, 86 insertions(+), 23 deletions(-)

--- a/drivers/usb/host/ehci-au1xxx.c
+++ b/drivers/usb/host/ehci-au1xxx.c
@@ -112,6 +112,8 @@ static const struct hc_driver ehci_au1xx
.bus_resume = ehci_bus_resume,
.relinquish_port = ehci_relinquish_port,
.port_handed_over = ehci_port_handed_over,
+
+ .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
};

static int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev)
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -324,6 +324,8 @@ static const struct hc_driver ehci_fsl_h
.bus_resume = ehci_bus_resume,
.relinquish_port = ehci_relinquish_port,
.port_handed_over = ehci_port_handed_over,
+
+ .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
};

static int ehci_fsl_drv_probe(struct platform_device *pdev)
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -353,7 +353,9 @@ struct ehci_qh {
unsigned short period; /* polling interval */
unsigned short start; /* where polling starts */
#define NO_FRAME ((unsigned short)~0) /* pick new start */
+
struct usb_device *dev; /* access to TT */
+ unsigned clearing_tt:1; /* Clear-TT-Buf in progress */
} __attribute__ ((aligned (32)));

/*-------------------------------------------------------------------------*/
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1003,6 +1003,8 @@ idle_timeout:
schedule_timeout_uninterruptible(1);
goto rescan;
case QH_STATE_IDLE: /* fully unlinked */
+ if (qh->clearing_tt)
+ goto idle_timeout;
if (list_empty (&qh->qtd_list)) {
qh_put (qh);
break;
--- a/drivers/usb/host/ehci-ixp4xx.c
+++ b/drivers/usb/host/ehci-ixp4xx.c
@@ -60,6 +60,8 @@ static const struct hc_driver ixp4xx_ehc
#endif
.relinquish_port = ehci_relinquish_port,
.port_handed_over = ehci_port_handed_over,
+
+ .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
};

static int ixp4xx_ehci_probe(struct platform_device *pdev)
--- a/drivers/usb/host/ehci-orion.c
+++ b/drivers/usb/host/ehci-orion.c
@@ -164,6 +164,8 @@ static const struct hc_driver ehci_orion
.bus_resume = ehci_bus_resume,
.relinquish_port = ehci_relinquish_port,
.port_handed_over = ehci_port_handed_over,
+
+ .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
};

static void __init
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -408,6 +408,8 @@ static const struct hc_driver ehci_pci_h
.bus_resume = ehci_bus_resume,
.relinquish_port = ehci_relinquish_port,
.port_handed_over = ehci_port_handed_over,
+
+ .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
};

/*-------------------------------------------------------------------------*/
--- a/drivers/usb/host/ehci-ppc-of.c
+++ b/drivers/usb/host/ehci-ppc-of.c
@@ -78,6 +78,8 @@ static const struct hc_driver ehci_ppc_o
#endif
.relinquish_port = ehci_relinquish_port,
.port_handed_over = ehci_port_handed_over,
+
+ .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
};


--- a/drivers/usb/host/ehci-ps3.c
+++ b/drivers/usb/host/ehci-ps3.c
@@ -74,6 +74,8 @@ static const struct hc_driver ps3_ehci_h
#endif
.relinquish_port = ehci_relinquish_port,
.port_handed_over = ehci_port_handed_over,
+
+ .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
};

static int ps3_ehci_probe(struct ps3_system_bus_device *dev)
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -139,6 +139,55 @@ qh_refresh (struct ehci_hcd *ehci, struc

/*-------------------------------------------------------------------------*/

+static void qh_link_async(struct ehci_hcd *ehci, struct ehci_qh *qh);
+
+static void ehci_clear_tt_buffer_complete(struct usb_hcd *hcd,
+ struct usb_host_endpoint *ep)
+{
+ struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+ struct ehci_qh *qh = ep->hcpriv;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ehci->lock, flags);
+ qh->clearing_tt = 0;
+ if (qh->qh_state == QH_STATE_IDLE && !list_empty(&qh->qtd_list)
+ && HC_IS_RUNNING(hcd->state))
+ qh_link_async(ehci, qh);
+ spin_unlock_irqrestore(&ehci->lock, flags);
+}
+
+static void ehci_clear_tt_buffer(struct ehci_hcd *ehci, struct ehci_qh *qh,
+ struct urb *urb, u32 token)
+{
+
+ /* If an async split transaction gets an error or is unlinked,
+ * the TT buffer may be left in an indeterminate state. We
+ * have to clear the TT buffer.
+ *
+ * Note: this routine is never called for Isochronous transfers.
+ */
+ if (urb->dev->tt && !usb_pipeint(urb->pipe) && !qh->clearing_tt) {
+#ifdef DEBUG
+ struct usb_device *tt = urb->dev->tt->hub;
+ dev_dbg(&tt->dev,
+ "clear tt buffer port %d, a%d ep%d t%08x\n",
+ urb->dev->ttport, urb->dev->devnum,
+ usb_pipeendpoint(urb->pipe), token);
+#endif /* DEBUG */
+ if (!ehci_is_TDI(ehci)
+ || urb->dev->tt->hub !=
+ ehci_to_hcd(ehci)->self.root_hub) {
+ if (usb_hub_clear_tt_buffer(urb) == 0)
+ qh->clearing_tt = 1;
+ } else {
+
+ /* REVISIT ARC-derived cores don't clear the root
+ * hub TT buffer in this way...
+ */
+ }
+ }
+}
+
static int qtd_copy_status (
struct ehci_hcd *ehci,
struct urb *urb,
@@ -195,28 +244,6 @@ static int qtd_copy_status (
usb_pipeendpoint (urb->pipe),
usb_pipein (urb->pipe) ? "in" : "out",
token, status);
-
- /* if async CSPLIT failed, try cleaning out the TT buffer */
- if (status != -EPIPE
- && urb->dev->tt
- && !usb_pipeint(urb->pipe)
- && ((token & QTD_STS_MMF) != 0
- || QTD_CERR(token) == 0)
- && (!ehci_is_TDI(ehci)
- || urb->dev->tt->hub !=
- ehci_to_hcd(ehci)->self.root_hub)) {
-#ifdef DEBUG
- struct usb_device *tt = urb->dev->tt->hub;
- dev_dbg (&tt->dev,
- "clear tt buffer port %d, a%d ep%d t%08x\n",
- urb->dev->ttport, urb->dev->devnum,
- usb_pipeendpoint (urb->pipe), token);
-#endif /* DEBUG */
- /* REVISIT ARC-derived cores don't clear the root
- * hub TT buffer in this way...
- */
- usb_hub_clear_tt_buffer(urb);
- }
}

return status;
@@ -407,9 +434,16 @@ qh_completions (struct ehci_hcd *ehci, s
/* qh unlinked; token in overlay may be most current */
if (state == QH_STATE_IDLE
&& cpu_to_hc32(ehci, qtd->qtd_dma)
- == qh->hw_current)
+ == qh->hw_current) {
token = hc32_to_cpu(ehci, qh->hw_token);

+ /* An unlink may leave an incomplete
+ * async transaction in the TT buffer.
+ * We have to clear it.
+ */
+ ehci_clear_tt_buffer(ehci, qh, urb, token);
+ }
+
/* force halt for unlinked or blocked qh, so we'll
* patch the qh later and so that completions can't
* activate it while we "know" it's stopped.
@@ -435,6 +469,13 @@ halt:
&& (qtd->hw_alt_next
& EHCI_LIST_END(ehci)))
last_status = -EINPROGRESS;
+
+ /* As part of low/full-speed endpoint-halt processing
+ * we must clear the TT buffer (11.17.5).
+ */
+ if (unlikely(last_status != -EINPROGRESS &&
+ last_status != -EREMOTEIO))
+ ehci_clear_tt_buffer(ehci, qh, urb, token);
}

/* if we're removing something not at the queue head,
@@ -864,6 +905,10 @@ static void qh_link_async (struct ehci_h
__hc32 dma = QH_NEXT(ehci, qh->qh_dma);
struct ehci_qh *head;

+ /* Don't link a QH if there's a Clear-TT-Buffer pending */
+ if (unlikely(qh->clearing_tt))
+ return;
+
/* (re)start the async schedule? */
head = ehci->async;
timer_action_done (ehci, TIMER_ASYNC_OFF);

2009-09-05 00:24:29

by Greg KH

[permalink] [raw]
Subject: [patch 60/71] USB: EHCI: fix two new bugs related to Clear-TT-Buffer

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

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

commit 7a0f0d951273eee889c2441846842348ebc00a2a upstream.

This patch (as1273) fixes two(!) bugs introduced by the new
Clear-TT-Buffer implementation in ehci-hcd.

It is now possible for an idle QH to have some URBs on its
queue -- this will happen if a Clear-TT-Buffer is pending for
the QH's endpoint. Consequently we should not issue a warning
when someone tries to unlink an URB from an idle QH; instead
we should process the request immediately.

The refcounts for QHs could get messed up, because
submit_async() would increment the refcount when calling
qh_link_async() and qh_link_async() would then refuse to link
the QH into the schedule if a Clear-TT-Buffer was pending.
Instead we should increment the refcount only when the QH
actually is added to the schedule. The current code tries to
be clever by leaving the refcount alone if an unlink is
immediately followed by a relink; the patch changes this to an
unconditional decrement and increment (although they occur in
the opposite order).

Signed-off-by: Alan Stern <[email protected]>
CC: David Brownell <[email protected]>
Tested-by: Manuel Lauss <[email protected]>
Tested-by: Matthijs Kooijman <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
drivers/usb/host/ehci-hcd.c | 3 ++-
drivers/usb/host/ehci-q.c | 6 +++---
2 files changed, 5 insertions(+), 4 deletions(-)

--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -903,7 +903,8 @@ static int ehci_urb_dequeue(struct usb_h
/* already started */
break;
case QH_STATE_IDLE:
- WARN_ON(1);
+ /* QH might be waiting for a Clear-TT-Buffer */
+ qh_completions(ehci, qh);
break;
}
break;
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -938,6 +938,7 @@ static void qh_link_async (struct ehci_h
head->qh_next.qh = qh;
head->hw_next = dma;

+ qh_get(qh);
qh->xacterrs = QH_XACTERR_MAX;
qh->qh_state = QH_STATE_LINKED;
/* qtd completions reported later by interrupt */
@@ -1078,7 +1079,7 @@ submit_async (
* the HC and TT handle it when the TT has a buffer ready.
*/
if (likely (qh->qh_state == QH_STATE_IDLE))
- qh_link_async (ehci, qh_get (qh));
+ qh_link_async(ehci, qh);
done:
spin_unlock_irqrestore (&ehci->lock, flags);
if (unlikely (qh == NULL))
@@ -1113,8 +1114,6 @@ static void end_unlink_async (struct ehc
&& HC_IS_RUNNING (ehci_to_hcd(ehci)->state))
qh_link_async (ehci, qh);
else {
- qh_put (qh); // refcount from async list
-
/* it's not free to turn the async schedule on/off; leave it
* active but idle for a while once it empties.
*/
@@ -1122,6 +1121,7 @@ static void end_unlink_async (struct ehc
&& ehci->async->qh_next.qh == NULL)
timer_action (ehci, TIMER_ASYNC_OFF);
}
+ qh_put(qh); /* refcount from async list */

if (next) {
ehci->reclaim = NULL;

2009-09-05 00:21:43

by Greg KH

[permalink] [raw]
Subject: [patch 61/71] powerpc/ps3: Add missing check for PS3 to rtc-ps3 platform device registration

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

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

commit 7b6a09f3d6aedeaac923824af2a5df30300b56e9 upstream.

On non-PS3, we get:

| kernel BUG at drivers/rtc/rtc-ps3.c:36!

because the rtc-ps3 platform device is registered unconditionally in a kernel
with builtin support for PS3.

Reported-by: Sachin Sant <[email protected]>
Signed-off-by: Geert Uytterhoeven <[email protected]>
Acked-by: Geoff Levand <[email protected]>
Signed-off-by: Benjamin Herrenschmidt <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

--- a/arch/powerpc/platforms/ps3/time.c
+++ b/arch/powerpc/platforms/ps3/time.c
@@ -21,6 +21,7 @@
#include <linux/kernel.h>
#include <linux/platform_device.h>

+#include <asm/firmware.h>
#include <asm/rtc.h>
#include <asm/lv1call.h>
#include <asm/ps3.h>
@@ -84,6 +85,9 @@ static int __init ps3_rtc_init(void)
{
struct platform_device *pdev;

+ if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
+ return -ENODEV;
+
pdev = platform_device_register_simple("rtc-ps3", -1, NULL, 0);
if (IS_ERR(pdev))
return PTR_ERR(pdev);

2009-09-05 00:24:31

by Greg KH

[permalink] [raw]
Subject: [patch 62/71] ipv4: make ip_append_data() handle NULL routing table

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

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

commit 788d908f2879a17e5f80924f3da2e23f1034482d upstream.

Add a check in ip_append_data() for NULL *rtp to prevent future bugs in
callers from being exploitable.

Signed-off-by: Julien Tinnes <[email protected]>
Signed-off-by: Tavis Ormandy <[email protected]>
Acked-by: David S. Miller <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
net/ipv4/ip_output.c | 2 ++
1 file changed, 2 insertions(+)

--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -814,6 +814,8 @@ int ip_append_data(struct sock *sk,
inet->cork.addr = ipc->addr;
}
rt = *rtp;
+ if (unlikely(!rt))
+ return -EFAULT;
/*
* We steal reference to this route, caller should not release it
*/

2009-09-05 00:24:54

by Greg KH

[permalink] [raw]
Subject: [patch 63/71] ar9170: fix read & write outside array bounds

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

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

commit e9d126cdfa60b575f1b5b02024c4faee27dccf07 upstream.

Backport done by Christian Lamparter <[email protected]>

queue == __AR9170_NUM_TXQ would cause a bug on the next line.

found by Smatch ( http://repo.or.cz/w/smatch.git ).

Reported-by: Dan Carpenter <[email protected]>
Signed-off-by: Dan Carpenter <[email protected]>
Signed-off-by: Christian Lamparter <[email protected]>
Signed-off-by: John W. Linville <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
drivers/net/wireless/ar9170/main.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)

--- a/drivers/net/wireless/ar9170/main.c
+++ b/drivers/net/wireless/ar9170/main.c
@@ -1486,13 +1486,14 @@ static int ar9170_conf_tx(struct ieee802
int ret;

mutex_lock(&ar->mutex);
- if ((param) && !(queue > ar->hw->queues)) {
+ if (queue < __AR9170_NUM_TXQ) {
memcpy(&ar->edcf[ar9170_qos_hwmap[queue]],
param, sizeof(*param));

ret = ar9170_set_qos(ar);
- } else
+ } else {
ret = -EINVAL;
+ }

mutex_unlock(&ar->mutex);
return ret;

2009-09-05 00:24:24

by Greg KH

[permalink] [raw]
Subject: [patch 64/71] xenfb: connect to backend before registering fb

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

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

commit 0a80fb10239b04c45e5e80aad8d4b2ca5ac407b2 upstream.

As soon as the framebuffer is registered, our methods may be called by the
kernel. This leads to a crash as xenfb_refresh() gets called before we have
the irq.

Connect to the backend before registering our framebuffer with the kernel.

[ Fixes bug http://bugzilla.kernel.org/show_bug.cgi?id=14059 ]

Signed-off-by: Michal Schmidt <[email protected]>
Signed-off-by: Jeremy Fitzhardinge <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
drivers/video/xen-fbfront.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)

--- a/drivers/video/xen-fbfront.c
+++ b/drivers/video/xen-fbfront.c
@@ -454,6 +454,10 @@ static int __devinit xenfb_probe(struct

xenfb_init_shared_page(info, fb_info);

+ ret = xenfb_connect_backend(dev, info);
+ if (ret < 0)
+ goto error;
+
ret = register_framebuffer(fb_info);
if (ret) {
fb_deferred_io_cleanup(fb_info);
@@ -464,10 +468,6 @@ static int __devinit xenfb_probe(struct
}
info->fb_info = fb_info;

- ret = xenfb_connect_backend(dev, info);
- if (ret < 0)
- goto error;
-
xenfb_make_preferred_console();
return 0;


2009-09-05 00:23:42

by Greg KH

[permalink] [raw]
Subject: [patch 65/71] can: Fix raw_getname() leak

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

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

commit e84b90ae5eb3c112d1f208964df1d8156a538289 upstream.

raw_getname() can leak 10 bytes of kernel memory to user

(two bytes hole between can_family and can_ifindex,
8 bytes at the end of sockaddr_can structure)

Signed-off-by: Eric Dumazet <[email protected]>
Acked-by: Oliver Hartkopp <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
net/can/raw.c | 1 +
1 file changed, 1 insertion(+)

--- a/net/can/raw.c
+++ b/net/can/raw.c
@@ -397,6 +397,7 @@ static int raw_getname(struct socket *so
if (peer)
return -EOPNOTSUPP;

+ memset(addr, 0, sizeof(*addr));
addr->can_family = AF_CAN;
addr->can_ifindex = ro->ifindex;


2009-09-05 00:23:58

by Greg KH

[permalink] [raw]
Subject: [patch 66/71] irda: Fix irda_getname() leak

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

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

commit 09384dfc76e526c3993c09c42e016372dc9dd22c upstream.

irda_getname() can leak kernel memory to user.

Signed-off-by: Eric Dumazet <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
net/irda/af_irda.c | 1 +
1 file changed, 1 insertion(+)

--- a/net/irda/af_irda.c
+++ b/net/irda/af_irda.c
@@ -714,6 +714,7 @@ static int irda_getname(struct socket *s
struct sock *sk = sock->sk;
struct irda_sock *self = irda_sk(sk);

+ memset(&saddr, 0, sizeof(saddr));
if (peer) {
if (sk->sk_state != TCP_ESTABLISHED)
return -ENOTCONN;

2009-09-05 00:23:30

by Greg KH

[permalink] [raw]
Subject: [patch 67/71] appletalk: fix atalk_getname() leak

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

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

commit 3d392475c873c10c10d6d96b94d092a34ebd4791 upstream.

atalk_getname() can leak 8 bytes of kernel memory to user

Signed-off-by: Eric Dumazet <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
net/appletalk/ddp.c | 1 +
1 file changed, 1 insertion(+)

--- a/net/appletalk/ddp.c
+++ b/net/appletalk/ddp.c
@@ -1242,6 +1242,7 @@ static int atalk_getname(struct socket *
return -ENOBUFS;

*uaddr_len = sizeof(struct sockaddr_at);
+ memset(&sat.sat_zero, 0, sizeof(sat.sat_zero));

if (peer) {
if (sk->sk_state != TCP_ESTABLISHED)

2009-09-05 00:22:24

by Greg KH

[permalink] [raw]
Subject: [patch 68/71] netrom: Fix nr_getname() leak

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

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

commit f6b97b29513950bfbf621a83d85b6f86b39ec8db upstream.

nr_getname() can leak kernel memory to user.

Signed-off-by: Eric Dumazet <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
net/netrom/af_netrom.c | 1 +
1 file changed, 1 insertion(+)

--- a/net/netrom/af_netrom.c
+++ b/net/netrom/af_netrom.c
@@ -848,6 +848,7 @@ static int nr_getname(struct socket *soc
sax->fsa_ax25.sax25_family = AF_NETROM;
sax->fsa_ax25.sax25_ndigis = 1;
sax->fsa_ax25.sax25_call = nr->user_addr;
+ memset(sax->fsa_digipeater, 0, sizeof(sax->fsa_digipeater));
sax->fsa_digipeater[0] = nr->dest_addr;
*uaddr_len = sizeof(struct full_sockaddr_ax25);
} else {

2009-09-05 00:21:48

by Greg KH

[permalink] [raw]
Subject: [patch 69/71] econet: Fix econet_getname() leak

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

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

commit 80922bbb12a105f858a8f0abb879cb4302d0ecaa upstream.

econet_getname() can leak kernel memory to user.

Signed-off-by: Eric Dumazet <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
net/econet/af_econet.c | 1 +
1 file changed, 1 insertion(+)

--- a/net/econet/af_econet.c
+++ b/net/econet/af_econet.c
@@ -520,6 +520,7 @@ static int econet_getname(struct socket
if (peer)
return -EOPNOTSUPP;

+ memset(sec, 0, sizeof(*sec));
mutex_lock(&econet_mutex);

sk = sock->sk;

2009-09-05 00:22:01

by Greg KH

[permalink] [raw]
Subject: [patch 70/71] rose: Fix rose_getname() leak

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

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

commit 17ac2e9c58b69a1e25460a568eae1b0dc0188c25 upstream.

rose_getname() can leak kernel memory to user.

Signed-off-by: Eric Dumazet <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
net/rose/af_rose.c | 1 +
1 file changed, 1 insertion(+)

--- a/net/rose/af_rose.c
+++ b/net/rose/af_rose.c
@@ -957,6 +957,7 @@ static int rose_getname(struct socket *s
struct rose_sock *rose = rose_sk(sk);
int n;

+ memset(srose, 0, sizeof(*srose));
if (peer != 0) {
if (sk->sk_state != TCP_ESTABLISHED)
return -ENOTCONN;

2009-09-05 00:22:47

by Greg KH

[permalink] [raw]
Subject: [patch 71/71] NET: llc, zero sockaddr_llc struct

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

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

commit 28e9fc592cb8c7a43e4d3147b38be6032a0e81bc upstream.

sllc_arphrd member of sockaddr_llc might not be changed. Zero sllc
before copying to the above layer's structure.

Signed-off-by: Jiri Slaby <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
net/llc/af_llc.c | 1 +
1 file changed, 1 insertion(+)

--- a/net/llc/af_llc.c
+++ b/net/llc/af_llc.c
@@ -914,6 +914,7 @@ static int llc_ui_getname(struct socket
struct llc_sock *llc = llc_sk(sk);
int rc = 0;

+ memset(&sllc, 0, sizeof(sllc));
lock_sock(sk);
if (sock_flag(sk, SOCK_ZAPPED))
goto out;

2009-09-05 05:01:30

by Grant Coady

[permalink] [raw]
Subject: Re: [patch 00/71] 2.6.30.6-stable review

On Fri, 4 Sep 2009 17:18:24 -0700, you wrote:

>This is the start of the stable review cycle for the 2.6.30.6 release.
>There are 71 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, Sept 6, 21:00:00 UTC. Anything
>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.30.6-rc1.gz

Hi Greg,

'Snot there yet.

Grant.
--
http://bugsplatter.id.au

2009-09-05 14:53:10

by Greg KH

[permalink] [raw]
Subject: Re: [patch 00/71] 2.6.30.6-stable review

On Sat, Sep 05, 2009 at 02:54:58PM +1000, Grant Coady wrote:
> On Fri, 4 Sep 2009 17:18:24 -0700, you wrote:
>
> >This is the start of the stable review cycle for the 2.6.30.6 release.
> >There are 71 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, Sept 6, 21:00:00 UTC. Anything
> >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.30.6-rc1.gz
>
> Hi Greg,
>
> 'Snot there yet.

Doh, sorry about that, is there now.

thanks,

greg k-h

2009-09-08 19:23:47

by Luis R. Rodriguez

[permalink] [raw]
Subject: Re: [Stable-review] [patch 00/71] 2.6.30.6-stable review

On Fri, Sep 4, 2009 at 5:18 PM, Greg KH<[email protected]> wrote:
> This is the start of the stable review cycle for the 2.6.30.6 release.
> There are 71 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.

I think this automated message needs some updated to reflect the fact
that a mailman list is used now, and redirect people to help
themselves to help us by subscribing to:

http://linux.kernel.org/mailman/listinfo/stable-review

> If you want to be off the reviewer list,
> also email us.

This seems to not be required any more.

> Responses should be made by Sunday, Sept 6, 21:00:00 UTC.  Anything
> Anything received after that time might be too late.

I'm a bit too late, but oh well.

> The whole patch series can be found in one patch at:
>        kernel.org/pub/linux/kernel/v2.6/stable-review/patch-2.6.30.6-rc1.gz
> and the diffstat can be found below.
>
> thanks,
>
> greg k-h
>
> ------------
>

>  drivers/net/wireless/ar9170/main.c        |    5 +-
>  drivers/net/wireless/iwlwifi/iwl-rfkill.c |   26 +++--
>  drivers/net/wireless/iwlwifi/iwl-sta.c    |   12 +++
>  drivers/net/wireless/rt2x00/rt2x00.h      |    6 +-

>  net/mac80211/agg-tx.c                     |    8 ++

These look good.

Reviewed-by: Luis R. Rodriguez <[email protected]>

Luis

2009-09-09 23:54:52

by Greg KH

[permalink] [raw]
Subject: Re: [Stable-review] [patch 00/71] 2.6.30.6-stable review

On Tue, Sep 08, 2009 at 12:23:29PM -0700, Luis R. Rodriguez wrote:
> On Fri, Sep 4, 2009 at 5:18 PM, Greg KH<[email protected]> wrote:
> > This is the start of the stable review cycle for the 2.6.30.6 release.
> > There are 71 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.
>
> I think this automated message needs some updated to reflect the fact
> that a mailman list is used now, and redirect people to help
> themselves to help us by subscribing to:
>
> http://linux.kernel.org/mailman/listinfo/stable-review
>
> > If you want to be off the reviewer list,
> > also email us.
>
> This seems to not be required any more.

True. Care to send a patch against the stable-queue where this message
is:
http://git.kernel.org/?p=linux/kernel/git/chrisw/stable-queue.git;a=summary

thanks,

greg k-h

2009-09-10 00:21:53

by Luis R. Rodriguez

[permalink] [raw]
Subject: Re: [Stable-review] [patch 00/71] 2.6.30.6-stable review

On Wed, Sep 9, 2009 at 3:44 PM, Greg KH <[email protected]> wrote:
> On Tue, Sep 08, 2009 at 12:23:29PM -0700, Luis R. Rodriguez wrote:
>> On Fri, Sep 4, 2009 at 5:18 PM, Greg KH<[email protected]> wrote:
>> > This is the start of the stable review cycle for the 2.6.30.6 release.
>> > There are 71 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.
>>
>> I think this automated message needs some updated to reflect the fact
>> that a mailman list is used now, and redirect people to help
>> themselves to help us by subscribing to:
>>
>> http://linux.kernel.org/mailman/listinfo/stable-review
>>
>> > If you want to be off the reviewer list,
>> > also email us.
>>
>> This seems to not be required any more.
>
> True.  Care to send a patch against the stable-queue where this message
> is:
>        http://git.kernel.org/?p=linux/kernel/git/chrisw/stable-queue.git;a=summary

Sure, that hasn't been updated since 2006, is that the right tree?

Luis

2009-09-10 03:04:12

by Greg KH

[permalink] [raw]
Subject: Re: [Stable-review] [patch 00/71] 2.6.30.6-stable review

On Wed, Sep 09, 2009 at 05:21:34PM -0700, Luis R. Rodriguez wrote:
> On Wed, Sep 9, 2009 at 3:44 PM, Greg KH <[email protected]> wrote:
> > On Tue, Sep 08, 2009 at 12:23:29PM -0700, Luis R. Rodriguez wrote:
> >> On Fri, Sep 4, 2009 at 5:18 PM, Greg KH<[email protected]> wrote:
> >> > This is the start of the stable review cycle for the 2.6.30.6 release.
> >> > There are 71 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.
> >>
> >> I think this automated message needs some updated to reflect the fact
> >> that a mailman list is used now, and redirect people to help
> >> themselves to help us by subscribing to:
> >>
> >> http://linux.kernel.org/mailman/listinfo/stable-review
> >>
> >> > If you want to be off the reviewer list,
> >> > also email us.
> >>
> >> This seems to not be required any more.
> >
> > True. ?Care to send a patch against the stable-queue where this message
> > is:
> > ? ? ? ?http://git.kernel.org/?p=linux/kernel/git/chrisw/stable-queue.git;a=summary
>
> Sure, that hasn't been updated since 2006, is that the right tree?

Bah, no, it isn't, use the one in the git/stable/stable-queue.git
location, sorry about that.

Chris, you might want to delete this old one :)

thanks,

greg k-h