Skip to contentSkip to conversation

2.6.27-stable review

PATCH New Greg KH 1 participant 61 messages Jun 10, 2009

Subsystems (26)
lore
Share & tools
lore

Greg KH

author
#0 lore raw

cover 2.6.27-stable review

This is the start of the stable review cycle for the 2.6.27.25 release. There are 60 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 June 11 09:00:00 UTC. Anything received after that time might be too late.

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

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

and the diffstat can be found below.

thanks,

greg k-h

 Documentation/filesystems/ext4.txt    |    5 +-
 Makefile                              |    2 +-
 arch/sparc/include/asm/pil.h          |    1 +
 arch/sparc/include/asm/tlb_64.h       |    4 +-
 arch/sparc/kernel/of_device.c         |   21 ++++++-
 arch/sparc64/kernel/irq.c             |   29 ++++++---
 arch/sparc64/kernel/kgdb.c            |    2 +-
 arch/sparc64/kernel/of_device.c       |   21 ++++++-
 arch/sparc64/kernel/pci_common.c      |    2 +-
 arch/sparc64/kernel/smp.c             |    8 +-
 arch/sparc64/kernel/ttable.S          |    8 ++-
 arch/sparc64/mm/ultra.S               |   24 +-------
 arch/x86/kernel/setup.c               |    5 +-
 arch/x86/mm/hugetlbpage.c             |    6 ++-
 arch/x86/mm/pageattr.c                |   11 ++++
 arch/x86/pci/mmconfig-shared.c        |    6 +-
 drivers/acpi/processor_idle.c         |    8 ++-
 drivers/char/random.c                 |   19 ++++--
 drivers/char/tpm/tpm_bios.c           |    3 +-
 drivers/hwmon/lm78.c                  |    2 +-
 drivers/media/video/cx88/cx88-input.c |   25 ++------
 drivers/net/bnx2.c                    |    2 +
 drivers/net/bonding/bond_alb.c        |    8 +--
 drivers/net/e1000/e1000_main.c        |    5 +-
 drivers/net/igb/igb_ethtool.c         |    4 +
 drivers/net/macvlan.c                 |    3 +-
 drivers/net/myri10ge/myri10ge.c       |    1 +
 drivers/scsi/3w-xxxx.c                |    5 +-
 drivers/scsi/3w-xxxx.h                |    2 +-
 drivers/serial/icom.c                 |    2 +-
 drivers/serial/mpc52xx_uart.c         |    2 +-
 drivers/usb/host/isp1760-hcd.c        |   24 +++++++-
 fs/ext4/ext4.h                        |   28 +++++++++
 fs/ext4/extents.c                     |   25 ++++++--
 fs/ext4/file.c                        |    7 ++-
 fs/ext4/ialloc.c                      |   31 +++++-----
 fs/ext4/inode.c                       |  105 +++++++++++++++++++++++++++++++--
 fs/ext4/ioctl.c                       |   17 +++++-
 fs/ext4/mballoc.c                     |   17 ++++--
 fs/ext4/namei.c                       |   17 +++++-
 fs/jbd2/revoke.c                      |   24 ++++++--
 fs/nfs/dir.c                          |    3 +-
 mm/hugetlb.c                          |   26 ++++----
 net/core/pktgen.c                     |    2 +-
 net/core/skbuff.c                     |    2 +-
 net/ipv4/tcp_input.c                  |    3 +
 net/mac80211/rc80211_pid_algo.c       |   71 ++++++++++++----------
 security/selinux/hooks.c              |    2 +-
 sound/usb/usbaudio.c                  |    2 +-
 sound/usb/usbaudio.h                  |    2 +-
 sound/usb/usbmidi.c                   |   12 ++++-
 sound/usb/usbquirks.h                 |    2 +-
 52 files changed, 474 insertions(+), 194 deletions(-)
author
#1 lore raw

PATCH 1/60 icom: fix rmmod crash

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

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

From: Breno Leitao <[email protected]>

commit 95caa0a9bdaf93607bd0cc8932f53112496f2f22 upstream.

Actually the icom driver is crashing when is being removed because the driver is kfreeing the adapter structure before calling pci_release_regions(), which result in the following error:

  Unable to handle kernel paging request for data at address 0x6b6b6b6b6b6b6d33
  Faulting instruction address: 0xc000000000246b80
  Oops: Kernel access of bad area, sig: 11 [#1]
  ....
  [c000000012d436a0] [c0000000001002d0] .kfree+0x120/0x34c (unreliable)
  [c000000012d43730] [c000000000246d60] .pci_release_selected_regions+0x3c/0x68
  [c000000012d437c0] [d000000002d54700] .icom_kref_release+0xf4/0x118 [icom]
  [c000000012d43850] [c000000000232e50] .kref_put+0x74/0x94
  [c000000012d438d0] [d000000002d56c58] .icom_remove+0x40/0xa4 [icom]
  [c000000012d43960] [c000000000249e48] .pci_device_remove+0x50/0x90
  [c000000012d439e0] [c0000000002d68d8] .__device_release_driver+0x94/0xd4
  [c000000012d43a70] [c0000000002d7104] .driver_detach+0xf8/0x12c
  [c000000012d43b00] [c0000000002d549c] .bus_remove_driver+0xbc/0x11c
  [c000000012d43b90] [c0000000002d71dc] .driver_unregister+0x60/0x80
  [c000000012d43c20] [c00000000024a07c] .pci_unregister_driver+0x44/0xe8
  [c000000012d43cb0] [d000000002d56bf4] .icom_exit+0x1c/0x40 [icom]
  [c000000012d43d30] [c000000000095fa8] .SyS_delete_module+0x214/0x2a8
  [c000000012d43e30] [c00000000000852c] syscall_exit+0x0/0x40
---
 drivers/serial/icom.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/serial/icom.c +1 -1
@@ -1482,8 +1482,8 @@ static void icom_remove_adapter(struct i
 
 	free_irq(icom_adapter->pci_dev->irq, (void *) icom_adapter);
 	iounmap(icom_adapter->base_addr);
-	icom_free_adapter(icom_adapter);
 	pci_release_regions(icom_adapter->pci_dev);
+	icom_free_adapter(icom_adapter);
 }
 
 static void icom_kref_release(struct kref *kref)
author
#2 lore raw

PATCH 2/60 nfs: Fix NFS v4 client handling of MAY_EXEC in nfs_permission.

In reply to Greg KH

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

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

commit 7ee2cb7f32b299c2b06a31fde155457203e4b7dd upstream.

The problem is that permission checking is skipped if atomic open is possible, but when exec opens a file, it just opens it O_READONLY which means EXEC permission will not be checked at that time.

This problem is observed by the following sequence (executed as root):

mount -t nfs4 server:/ /mnt4
echo "ls" >/mnt4/foo
chmod 744 /mnt4/foo
su guest -c "mnt4/foo"

---
 fs/nfs/dir.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
fs/nfs/dir.c +2 -1
@@ -1925,7 +1925,8 @@ int nfs_permission(struct inode *inode, 
 		case S_IFREG:
 			/* NFSv4 has atomic_open... */
 			if (nfs_server_capable(inode, NFS_CAP_ATOMIC_OPEN)
-					&& (mask & MAY_OPEN))
+					&& (mask & MAY_OPEN)
+					&& !(mask & MAY_EXEC))
 				goto out;
 			break;
 		case S_IFDIR:
author
#3 lore raw

PATCH 3/60 TPM: get_event_name stack corruption

In reply to Greg KH

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

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

commit fbaa58696cef848de818768783ef185bd3f05158 upstream.

get_event_name uses sprintf to fill a buffer declared on the stack. It fills the buffer 2 bytes at a time. What the code doesn't take into account is that sprintf(buf, "%02x", data) actually writes 3 bytes. 2 bytes for the data and then it nul terminates the string. Since we declare buf to be 40 characters long and then we write 40 bytes of data into buf sprintf is going to write 41 characters. The fix is to leave room in buf for the nul terminator.

---
 drivers/char/tpm/tpm_bios.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/char/tpm/tpm_bios.c +2 -1
@@ -214,7 +214,8 @@ static int get_event_name(char *dest, st
 			unsigned char * event_entry)
 {
 	const char *name = "";
-	char data[40] = "";
+	/* 41 so there is room for 40 data and 1 nul */
+	char data[41] = "";
 	int i, n_len = 0, d_len = 0;
 	struct tcpa_pc_event *pc_event;
 
author
#4 lore raw

PATCH 4/60 sparc64: Fix smp_callin() locking.

In reply to Greg KH

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

------------------
From: David S. Miller <[email protected]>

[ Upstream commit 8e255baa449df3049a8827a7f1f4f12b6921d0d1 ]

Interrupts must be disabled when taking the IPI lock.

Caught by lockdep.

---
 arch/sparc64/kernel/smp.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
arch/sparc64/kernel/smp.c +2 -2
@@ -118,9 +118,9 @@ void __cpuinit smp_callin(void)
 	while (!cpu_isset(cpuid, smp_commenced_mask))
 		rmb();
 
-	ipi_call_lock();
+	ipi_call_lock_irq();
 	cpu_set(cpuid, cpu_online_map);
-	ipi_call_unlock();
+	ipi_call_unlock_irq();
 
 	/* idle thread is expected to have preempt disabled */
 	preempt_disable();
author
#5 lore raw

PATCH 5/60 sparc: Fix bus type probing for ESP and LE devices.

In reply to Greg KH

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

------------------
From: David S. Miller <[email protected]>

If there is a dummy "espdma" or "ledma" parent device above ESP scsi or LE ethernet device nodes, we have to match the bus as SBUS.

Otherwise the address and size cell counts are wrong and we don't calculate the final physical device resource values correctly at all.

Commit 5280267c1dddb8d413595b87dc406624bb497946 ("sparc: Fix handling of LANCE and ESP parent nodes in of_device.c") was meant to fix this problem, but that only influences the inner loop of build_device_resources(). We need this logic to also kick in at the beginning of build_device_resources() as well, when we make the first attempt to determine the device's immediate parent bus type for 'reg' property element extraction.

Based almost entirely upon a patch by Friedrich Oslage.

---
 arch/sparc/kernel/of_device.c   |   21 +++++++++++++++++++--
 arch/sparc64/kernel/of_device.c |   21 +++++++++++++++++++--
 2 files changed, 38 insertions(+), 4 deletions(-)
arch/sparc64/kernel/of_device.c +19 -2
@@ -278,8 +278,25 @@ static unsigned long of_bus_pci_get_flag
 
 static int of_bus_sbus_match(struct device_node *np)
 {
-	return !strcmp(np->name, "sbus") ||
-		!strcmp(np->name, "sbi");
+	struct device_node *dp = np;
+
+	while (dp) {
+		if (!strcmp(dp->name, "sbus") ||
+		    !strcmp(dp->name, "sbi"))
+			return 1;
+
+		/* Have a look at use_1to1_mapping().  We're trying
+		 * to match SBUS if that's the top-level bus and we
+		 * don't have some intervening real bus that provides
+		 * ranges based translations.
+		 */
+		if (of_find_property(dp, "ranges", NULL) != NULL)
+			break;
+
+		dp = dp->parent;
+	}
+
+	return 0;
 }
 
 static void of_bus_sbus_count_cells(struct device_node *child,
arch/sparc/kernel/of_device.c +19 -2
@@ -223,8 +223,25 @@ static unsigned long of_bus_pci_get_flag
 
 static int of_bus_sbus_match(struct device_node *np)
 {
-	return !strcmp(np->name, "sbus") ||
-		!strcmp(np->name, "sbi");
+	struct device_node *dp = np;
+
+	while (dp) {
+		if (!strcmp(dp->name, "sbus") ||
+		    !strcmp(dp->name, "sbi"))
+			return 1;
+
+		/* Have a look at use_1to1_mapping().  We're trying
+		 * to match SBUS if that's the top-level bus and we
+		 * don't have some intervening real bus that provides
+		 * ranges based translations.
+		 */
+		if (of_find_property(dp, "ranges", NULL) != NULL)
+			break;
+
+		dp = dp->parent;
+	}
+
+	return 0;
 }
 
 static void of_bus_sbus_count_cells(struct device_node *child,
author
#6 lore raw

PATCH 6/60 sparc64: Fix MM refcount check in smp_flush_tlb_pending().

In reply to Greg KH

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

------------------
From: David S. Miller <[email protected]>

[ Upstream commit f9384d41c02408dd404aa64d66d0ef38adcf6479 ]

As explained by Benjamin Herrenschmidt:

Quoted 15 lines

CPU 0 is running the context, task->mm == task->active_mm == your context. The CPU is in userspace happily churning things.

CPU 1 used to run it, not anymore, it's now running fancyfsd which is a kernel thread, but current->active_mm still points to that same context.

Because there's only one "real" user, mm_users is 1 (but mm_count is elevated, it's just that the presence on CPU 1 as active_mm has no effect on mm_count().

At this point, fancyfsd decides to invalidate a mapping currently mapped by that context, for example because a networked file has changed remotely or something like that, using unmap_mapping_ranges().

Quoted 5 lines

So CPU 1 goes into the zapping code, which eventually ends up calling flush_tlb_pending(). Your test will succeed, as current->active_mm is indeed the target mm for the flush, and mm_users is indeed 1. So you will -not- send an IPI to the other CPU, and CPU 0 will continue happily accessing the pages that should have been unmapped.

To fix this problem, check ->mm instead of ->active_mm, and this means:

Quoted 6 lines

So if you test current->mm, you effectively account for mm_users == 1, so the only way the mm can be active on another processor is as a lazy mm for a kernel thread. So your test should work properly as long as you don't have a HW that will do speculative TLB reloads into the TLB on that other CPU (and even if you do, you flush-on-switch-in should get rid of any crap here).

And therefore we should be OK.

---
 arch/sparc64/kernel/smp.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
arch/sparc64/kernel/smp.c +2 -2
@@ -1031,7 +1031,7 @@ void smp_fetch_global_regs(void)
  *    If the address space is non-shared (ie. mm->count == 1) we avoid
  *    cross calls when we want to flush the currently running process's
  *    tlb state.  This is done by clearing all cpu bits except the current
- *    processor's in current->active_mm->cpu_vm_mask and performing the
+ *    processor's in current->mm->cpu_vm_mask and performing the
  *    flush locally only.  This will force any subsequent cpus which run
  *    this task to flush the context from the local tlb if the process
  *    migrates to another cpu (again).
@@ -1074,7 +1074,7 @@ void smp_flush_tlb_pending(struct mm_str
 	u32 ctx = CTX_HWBITS(mm->context);
 	int cpu = get_cpu();
 
-	if (mm == current->active_mm && atomic_read(&mm->mm_users) == 1)
+	if (mm == current->mm && atomic_read(&mm->mm_users) == 1)
 		mm->cpu_vm_mask = cpumask_of_cpu(cpu);
 	else
 		smp_cross_call_masked(&xcall_flush_tlb_pending,
author
#7 lore raw

PATCH 7/60 sparc64: Flush TLB before releasing pages.

In reply to Greg KH

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

------------------
From: David S. Miller <[email protected]>

[ Upstream commit 86ee79c3dbd48d7430fd81edc1da3516c9f6dabc ]

tlb_flush_mmu() needs to flush pending TLB entries before processing the mmu_gather ->pages list.

Noticed by Benjamin Herrenschmidt.

---
 arch/sparc/include/asm/tlb_64.h |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
arch/sparc/include/asm/tlb_64.h +2 -2
@@ -58,6 +58,8 @@ static inline struct mmu_gather *tlb_gat
 static inline void tlb_flush_mmu(struct mmu_gather *mp)
 {
 	if (mp->need_flush) {
+		if (!mp->fullmm)
+			flush_tlb_pending();
 		free_pages_and_swap_cache(mp->pages, mp->pages_nr);
 		mp->pages_nr = 0;
 		mp->need_flush = 0;
@@ -78,8 +80,6 @@ static inline void tlb_finish_mmu(struct
 
 	if (mp->fullmm)
 		mp->fullmm = 0;
-	else
-		flush_tlb_pending();
 
 	/* keep the page table cache within bounds */
 	check_pgt_cache();
author
#8 lore raw

PATCH 8/60 sparc64: Fix crash with /proc/iomem

In reply to Greg KH

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

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

[ Upstream commit 192d7a4667c6d11d1a174ec4cad9a3c5d5f9043c ]

When you compile kernel on Sparc64 with heap memory checking and type "cat /proc/iomem", you get a crash, because pointers in struct resource are uninitialized.

Most code fills struct resource with zeros, so I assume that it is responsibility of the caller of request_resource to initialized it, not the responsibility of request_resource functuion.

After 2.6.29 is out, there could be a check for uninitialized fields added to request_resource to avoid crashes like this.

---
 arch/sparc64/kernel/pci_common.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/sparc64/kernel/pci_common.c +1 -1
@@ -368,7 +368,7 @@ static void pci_register_iommu_region(st
 	const u32 *vdma = of_get_property(pbm->prom_node, "virtual-dma", NULL);
 
 	if (vdma) {
-		struct resource *rp = kmalloc(sizeof(*rp), GFP_KERNEL);
+		struct resource *rp = kzalloc(sizeof(*rp), GFP_KERNEL);
 
 		if (!rp) {
 			prom_printf("Cannot allocate IOMMU resource.\n");
author
#9 lore raw

PATCH 9/60 sparc64: Fix lost interrupts on sun4u.

In reply to Greg KH

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

------------------
From: David S. Miller <[email protected]>

[ Upstream commit d0cac39e4ec8097e4c7099d291b1fdcc0fe56b58 ]

Based upon a report by Meelis Roos.

Sparc64 SBUS and PCI controllers use a combination of IMAP and ICLR registers to manage device interrupts.

The IMAP register contains the "valid" enable bit as well as CPU targetting information. Whereas the ICLR register is written with zero at the end of handling an interrupt to reset the state machine for that interrupt to IDLE so it can be sent again.

For PCI slot and SBUS slot devices we can have multiple interrupts sharing the same IMAP register. There are individual ICLR registers but only one IMAP register for managing those.

We represent each shared case with individual virtual IRQs so the generic IRQ layer thinks there is only one user of the IRQ instance.

In such shared IMAP cases this is wrong, so if there are multiple active users then a free_irq() call will prematurely turn off the interrupt by clearing the Valid bit in the IMAP register even though there are other active users.

Fix this by simply doing nothing in sun4u_disable_irq() and checking IRQF_DISABLED during IRQ dispatch.

This situation doesn't exist in the hypervisor sun4v cases, so I left those alone.

---
 arch/sparc64/kernel/irq.c |   29 +++++++++++++++++++----------
 1 file changed, 19 insertions(+), 10 deletions(-)
arch/sparc64/kernel/irq.c +19 -10
@@ -318,17 +318,25 @@ static void sun4u_set_affinity(unsigned 
 	sun4u_irq_enable(virt_irq);
 }
 
+/* Don't do anything.  The desc->status check for IRQ_DISABLED in
+ * handler_irq() will skip the handler call and that will leave the
+ * interrupt in the sent state.  The next ->enable() call will hit the
+ * ICLR register to reset the state machine.
+ *
+ * This scheme is necessary, instead of clearing the Valid bit in the
+ * IMAP register, to handle the case of IMAP registers being shared by
+ * multiple INOs (and thus ICLR registers).  Since we use a different
+ * virtual IRQ for each shared IMAP instance, the generic code thinks
+ * there is only one user so it prematurely calls ->disable() on
+ * free_irq().
+ *
+ * We have to provide an explicit ->disable() method instead of using
+ * NULL to get the default.  The reason is that if the generic code
+ * sees that, it also hooks up a default ->shutdown method which
+ * invokes ->mask() which we do not want.  See irq_chip_set_defaults().
+ */
 static void sun4u_irq_disable(unsigned int virt_irq)
 {
-	struct irq_handler_data *data = get_irq_chip_data(virt_irq);
-
-	if (likely(data)) {
-		unsigned long imap = data->imap;
-		unsigned long tmp = upa_readq(imap);
-
-		tmp &= ~IMAP_VALID;
-		upa_writeq(tmp, imap);
-	}
 }
 
 static void sun4u_irq_eoi(unsigned int virt_irq)
@@ -739,7 +747,8 @@ void handler_irq(int irq, struct pt_regs
 
 		desc = irq_desc + virt_irq;
 
-		desc->handle_irq(virt_irq, desc);
+		if (!(desc->status & IRQ_DISABLED))
+			desc->handle_irq(virt_irq, desc);
 
 		bucket_pa = next_pa;
 	}
author
#10 lore raw

PATCH 10/60 sparc64: Reschedule KGDB capture to a software interrupt.

In reply to Greg KH

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

------------------
From: David S. Miller <[email protected]>

[ Upstream commit 42cc77c861e8e850e86252bb5b1e12e006261973 ]

Otherwise it might interrupt switch_to() midstream and use half-cooked register window state.

---
 arch/sparc/include/asm/pil.h |    1 +
 arch/sparc64/kernel/kgdb.c   |    2 +-
 arch/sparc64/kernel/ttable.S |    8 +++++++-
 arch/sparc64/mm/ultra.S      |   24 ++----------------------
 4 files changed, 11 insertions(+), 24 deletions(-)
arch/sparc64/kernel/kgdb.c +1 -1
@@ -108,7 +108,7 @@ void gdb_regs_to_pt_regs(unsigned long *
 }
 
 #ifdef CONFIG_SMP
-void smp_kgdb_capture_client(struct pt_regs *regs)
+void smp_kgdb_capture_client(int irq, struct pt_regs *regs)
 {
 	unsigned long flags;
 
arch/sparc64/kernel/ttable.S +7 -1
@@ -63,7 +63,13 @@ tl0_irq6:	TRAP_IRQ(smp_call_function_sin
 #else
 tl0_irq6:	BTRAP(0x46)
 #endif
-tl0_irq7:	BTRAP(0x47) BTRAP(0x48) BTRAP(0x49)
+tl0_irq7:	BTRAP(0x47)
+#ifdef CONFIG_KGDB
+tl0_irq8:	TRAP_IRQ(smp_kgdb_capture_client, 8)
+#else
+tl0_irq8:	BTRAP(0x48)
+#endif
+tl0_irq9:	BTRAP(0x49)
 tl0_irq10:	BTRAP(0x4a) BTRAP(0x4b) BTRAP(0x4c) BTRAP(0x4d)
 tl0_irq14:	TRAP_IRQ(timer_interrupt, 14)
 tl0_irq15:	TRAP_IRQ(handler_irq, 15)
arch/sparc64/mm/ultra.S +2 -22
@@ -681,28 +681,8 @@ xcall_new_mmu_context_version:
 #ifdef CONFIG_KGDB
 	.globl		xcall_kgdb_capture
 xcall_kgdb_capture:
-661:	rdpr		%pstate, %g2
-	wrpr		%g2, PSTATE_IG | PSTATE_AG, %pstate
-	.section	.sun4v_2insn_patch, "ax"
-	.word		661b
-	nop
-	nop
-	.previous
-
-	rdpr		%pil, %g2
-	wrpr		%g0, 15, %pil
-	sethi		%hi(109f), %g7
-	ba,pt		%xcc, etrap_irq
-109:	 or		%g7, %lo(109b), %g7
-#ifdef CONFIG_TRACE_IRQFLAGS
-	call		trace_hardirqs_off
-	 nop
-#endif
-	call		smp_kgdb_capture_client
-	 add		%sp, PTREGS_OFF, %o0
-	/* Has to be a non-v9 branch due to the large distance. */
-	ba		rtrap_xcall
-	 ldx		[%sp + PTREGS_OFF + PT_V9_TSTATE], %l1
+	wr		%g0, (1 << PIL_KGDB_CAPTURE), %set_softint
+	retry
 #endif
 
 #endif /* CONFIG_SMP */
arch/sparc/include/asm/pil.h +1 -0
@@ -18,5 +18,6 @@
 #define PIL_SMP_CTX_NEW_VERSION	4
 #define PIL_DEVICE_IRQ		5
 #define PIL_SMP_CALL_FUNC_SNGL	6
+#define PIL_KGDB_CAPTURE	8
 
 #endif /* !(_SPARC64_PIL_H) */
author
#11 lore raw

PATCH 11/60 bonding: fix alb mode locking regression

In reply to Greg KH

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

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

[ Upstream commit 815bcc2719c12b6f5b511706e2d19728e07f0b02 ]

Fix locking issue in alb MAC address management; removed incorrect locking and replaced with correct locking. This bug was introduced in commit 059fe7a578fba5bbb0fdc0365bfcf6218fa25eb0 ("bonding: Convert locks to _bh, rework alb locking for new locking")

Bug reported by Paul Smith <[email protected]>, who also
tested the fix.

---
 drivers/net/bonding/bond_alb.c |    8 ++------
 1 file changed, 2 insertions(+), 6 deletions(-)
drivers/net/bonding/bond_alb.c +2 -6
@@ -1716,9 +1716,6 @@ int bond_alb_set_mac_address(struct net_
 		}
 	}
 
-	write_unlock_bh(&bond->curr_slave_lock);
-	read_unlock(&bond->lock);
-
 	if (swap_slave) {
 		alb_swap_mac_addr(bond, swap_slave, bond->curr_active_slave);
 		alb_fasten_mac_swap(bond, swap_slave, bond->curr_active_slave);
@@ -1726,16 +1723,15 @@ int bond_alb_set_mac_address(struct net_
 		alb_set_slave_mac_addr(bond->curr_active_slave, bond_dev->dev_addr,
 				       bond->alb_info.rlb_enabled);
 
+		read_lock(&bond->lock);
 		alb_send_learning_packets(bond->curr_active_slave, bond_dev->dev_addr);
 		if (bond->alb_info.rlb_enabled) {
 			/* inform clients mac address has changed */
 			rlb_req_update_slave_clients(bond, bond->curr_active_slave);
 		}
+		read_unlock(&bond->lock);
 	}
 
-	read_lock(&bond->lock);
-	write_lock_bh(&bond->curr_slave_lock);
-
 	return 0;
 }
 
author
#12 lore raw

PATCH 12/60 vlan/macvlan: fix NULL pointer dereferences in ethtool handlers

In reply to Greg KH

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

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

[ Upstream commit 7816a0a862d851d0b05710e7d94bfe390f3180e2 ]

Check whether the underlying device provides a set of ethtool ops before checking for individual handlers to avoid NULL pointer dereferences.

---
 drivers/net/macvlan.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/net/macvlan.c +2 -1
@@ -328,7 +328,8 @@ static u32 macvlan_ethtool_get_rx_csum(s
 	const struct macvlan_dev *vlan = netdev_priv(dev);
 	struct net_device *lowerdev = vlan->lowerdev;
 
-	if (lowerdev->ethtool_ops->get_rx_csum == NULL)
+	if (lowerdev->ethtool_ops == NULL ||
+	    lowerdev->ethtool_ops->get_rx_csum == NULL)
 		return 0;
 	return lowerdev->ethtool_ops->get_rx_csum(lowerdev);
 }
author
#13 lore raw

PATCH 13/60 myr10ge: again fix lro_gen_skb() alignment

In reply to Greg KH

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

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

[ Upstream commit 636d2f68a0814d84de26c021b2c15e3b4ffa29de ]

Add LRO alignment initially committed in 621544eb8c3beaa859c75850f816dd9b056a00a3 ("[LRO]: fix lro_gen_skb() alignment") and removed in 0dcffac1a329be69bab0ac604bf7283737108e68 ("myri10ge: add multislices support") during conversion to multi-slice.

---
 drivers/net/myri10ge/myri10ge.c |    1 +
 1 file changed, 1 insertion(+)
drivers/net/myri10ge/myri10ge.c +1 -0
@@ -2379,6 +2379,7 @@ static int myri10ge_open(struct net_devi
 		lro_mgr->lro_arr = ss->rx_done.lro_desc;
 		lro_mgr->get_frag_header = myri10ge_get_frag_header;
 		lro_mgr->max_aggr = myri10ge_lro_max_pkts;
+		lro_mgr->frag_align_pad = 2;
 		if (lro_mgr->max_aggr > MAX_SKB_FRAGS)
 			lro_mgr->max_aggr = MAX_SKB_FRAGS;
 
author
#14 lore raw

PATCH 14/60 pktgen: do not access flows[] beyond its length

In reply to Greg KH

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

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

[ Upstream commit 5b5f792a6a9a2f9ae812d151ed621f72e99b1725 ]

typo -- pkt_dev->nflows is for stats only, the number of concurrent flows is stored in cflows.

---
 net/core/pktgen.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
net/core/pktgen.c +1 -1
@@ -2449,7 +2449,7 @@ static inline void free_SAs(struct pktge
 	if (pkt_dev->cflows) {
 		/* let go of the SAs if we have them */
 		int i = 0;
-		for (;  i < pkt_dev->nflows; i++){
+		for (;  i < pkt_dev->cflows; i++) {
 			struct xfrm_state *x = pkt_dev->flows[i].x;
 			if (x) {
 				xfrm_state_put(x);
author
#15 lore raw

PATCH 15/60 net: fix skb_seq_read returning wrong offset/length for page frag data

In reply to Greg KH

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

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

[ Upstream commit 995b337952cdf7e05d288eede580257b632a8343 ]

When called with a consumed value that is less than skb_headlen(skb) bytes into a page frag, skb_seq_read() incorrectly returns an offset/length relative to skb->data. Ensure that data which should come from a page frag does.

---
 net/core/skbuff.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
net/core/skbuff.c +1 -1
@@ -1992,7 +1992,7 @@ unsigned int skb_seq_read(unsigned int c
 next_skb:
 	block_limit = skb_headlen(st->cur_skb) + st->stepped_offset;
 
-	if (abs_offset < block_limit) {
+	if (abs_offset < block_limit && !st->frag_data) {
 		*data = st->cur_skb->data + (abs_offset - st->stepped_offset);
 		return block_limit - abs_offset;
 	}
author
#16 lore raw

PATCH 16/60 tcp: fix >2 iw selection

In reply to Greg KH

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

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

[ Upstream commit 86bcebafc5e7f5163ccf828792fe694b112ed6fa ]

A long-standing feature in tcp_init_metrics() is such that any of its goto reset prevents call to tcp_init_cwnd().

---
 net/ipv4/tcp_input.c |    3 +++
 1 file changed, 3 insertions(+)
net/ipv4/tcp_input.c +3 -0
@@ -931,6 +931,8 @@ static void tcp_init_metrics(struct sock
 	tcp_bound_rto(sk);
 	if (inet_csk(sk)->icsk_rto < TCP_TIMEOUT_INIT && !tp->rx_opt.saw_tstamp)
 		goto reset;
+
+cwnd:
 	tp->snd_cwnd = tcp_init_cwnd(tp, dst);
 	tp->snd_cwnd_stamp = tcp_time_stamp;
 	return;
@@ -945,6 +947,7 @@ reset:
 		tp->mdev = tp->mdev_max = tp->rttvar = TCP_TIMEOUT_INIT;
 		inet_csk(sk)->icsk_rto = TCP_TIMEOUT_INIT;
 	}
+	goto cwnd;
 }
 
 static void tcp_update_reordering(struct sock *sk, const int metric,
author
#17 lore raw

PATCH 17/60 x86: work around Fedora-11 x86-32 kernel failures on Intel Atom CPUs

In reply to Greg KH

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

------------------
From: Ingo Molnar <[email protected]>
commit 211b3d03c7400f48a781977a50104c9d12f4e229 upstream

[Trivial backport to 2.6.27 by [email protected]]

x86: work around Fedora-11 x86-32 kernel failures on Intel Atom CPUs

Impact: work around boot crash

Work around Intel Atom erratum AAH41 (probabilistically) - it's triggering in the field.

---

---
 arch/x86/mm/pageattr.c |   11 +++++++++++
 1 file changed, 11 insertions(+)
arch/x86/mm/pageattr.c +11 -0
@@ -565,6 +565,17 @@ static int split_large_page(pte_t *kpte,
 	ref_prot = pte_pgprot(pte_mkexec(pte_clrhuge(*kpte)));
 	pgprot_val(ref_prot) |= _PAGE_PRESENT;
 	__set_pmd_pte(kpte, address, mk_pte(base, ref_prot));
+
+	/*
+	 * Intel Atom errata AAH41 workaround.
+	 *
+	 * The real fix should be in hw or in a microcode update, but
+	 * we also probabilistically try to reduce the window of having
+	 * a large TLB mixed with 4K TLBs while instruction fetches are
+	 * going on.
+	 */
+	__flush_tlb_all();
+
 	base = NULL;
 
 out_unlock:
author
#18 lore raw

PATCH 18/60 3w-xxxx: scsi_dma_unmap fix

In reply to Greg KH

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

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

commit 7b14f58ad65f9d74e4273fb45360cfea824495aa upstream.

This patch fixes the following regression that occurred during the scsi_dma_map()/unmap()
changes when compiling with CONFIG_DMA_API_DEBUG=y :

WARNING: at lib/dma-debug.c:496 check_unmap+0x142/0x542()

Hardware name:
3w-xxxx 0000:02:02.0: DMA-API: device driver tries to free DMA memory it has not allocated [device address=0x0000000000000000] [size=36 bytes]

---
 drivers/scsi/3w-xxxx.c |    5 +++--
 drivers/scsi/3w-xxxx.h |    2 +-
 2 files changed, 4 insertions(+), 3 deletions(-)
drivers/scsi/3w-xxxx.c +3 -2
@@ -6,7 +6,7 @@
    		     Arnaldo Carvalho de Melo <[email protected]>
                      Brad Strand <[email protected]>
 
-   Copyright (C) 1999-2007 3ware Inc.
+   Copyright (C) 1999-2009 3ware Inc.
 
    Kernel compatiblity By: 	Andre Hedrick <[email protected]>
    Non-Copyright (C) 2000	Andre Hedrick <[email protected]>
@@ -1294,7 +1294,8 @@ static void tw_unmap_scsi_data(struct pc
 {
 	dprintk(KERN_WARNING "3w-xxxx: tw_unmap_scsi_data()\n");
 
-	scsi_dma_unmap(cmd);
+	if (cmd->SCp.phase == TW_PHASE_SGLIST)
+		scsi_dma_unmap(cmd);
 } /* End tw_unmap_scsi_data() */
 
 /* This function will reset a device extension */
drivers/scsi/3w-xxxx.h +1 -1
@@ -6,7 +6,7 @@
    		     Arnaldo Carvalho de Melo <[email protected]>
                      Brad Strand <[email protected]>
 
-   Copyright (C) 1999-2007 3ware Inc.
+   Copyright (C) 1999-2009 3ware Inc.
 
    Kernel compatiblity By:	Andre Hedrick <[email protected]>
    Non-Copyright (C) 2000	Andre Hedrick <[email protected]>
author
#19 lore raw

PATCH 19/60 bnx2: Fix panic in bnx2_poll_work().

In reply to Greg KH

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

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

commit 581daf7e00c5e766f26aff80a61a860a17b0d75a upstream.

Add barrier() to bnx2_get_hw_{tx|rx}_cons() to fix this issue:

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

This issue was reported by multiple i386 users. Without barrier(), the compiled code looks like the following where %eax contains the address of the tx_cons or rx_cons in the DMA status block. The status block contents can change between the cmpb and the movzwl instruction. The driver would crash if the value was not 0xff during the cmpb instruction, but changed to 0xff during the movzwl instruction.

6828: 80 38 ff cmpb $0xff,(%eax)
682b: 0f b7 10 movzwl (%eax),%edx

With the added barrier(), the compiled code now looks correct:

683d:	0f b7 10             	movzwl (%eax),%edx
6840:	0f b6 c2             	movzbl %dl,%eax
6843:	3d ff 00 00 00       	cmp    $0xff,%eax

Thanks to Pascal de Bruijn <[email protected]> for reporting the problem and Holger Noefer <[email protected]> for patiently testing test patches for us.

[greg - took out version change]

---
 drivers/net/bnx2.c |    2 ++
 1 file changed, 2 insertions(+)
drivers/net/bnx2.c +2 -0
@@ -2574,6 +2574,7 @@ bnx2_get_hw_tx_cons(struct bnx2_napi *bn
 	/* Tell compiler that status block fields can change. */
 	barrier();
 	cons = *bnapi->hw_tx_cons_ptr;
+	barrier();
 	if (unlikely((cons & MAX_TX_DESC_CNT) == MAX_TX_DESC_CNT))
 		cons++;
 	return cons;
@@ -2849,6 +2850,7 @@ bnx2_get_hw_rx_cons(struct bnx2_napi *bn
 	/* Tell compiler that status block fields can change. */
 	barrier();
 	cons = *bnapi->hw_rx_cons_ptr;
+	barrier();
 	if (unlikely((cons & MAX_RX_DESC_CNT) == MAX_RX_DESC_CNT))
 		cons++;
 	return cons;
author
#20 lore raw

PATCH 20/60 cpuidle: fix AMD C1E suspend hang

In reply to Greg KH

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

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

commit 7d60e8ab0d5507229dfbdf456501cc378610fa01 upstream.

When AMD C1E is enabled, local APIC timer will stop even in C1. To avoid suspend/resume hang, this patch removes C1 and replace it with a cpu_relax() in suspend/resume path. This hasn't any impact in runtime path.

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

[ impact: avoid suspend/resume hang in AMD CPU with C1E enabled ]

---
 drivers/acpi/processor_idle.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/acpi/processor_idle.c +1 -1
@@ -1468,8 +1468,8 @@ static int acpi_idle_enter_c1(struct cpu
 
 	/* Do not access any ACPI IO ports in suspend path */
 	if (acpi_idle_suspend) {
-		acpi_safe_halt();
 		local_irq_enable();
+		cpu_relax();
 		return 0;
 	}
 
author
#21 lore raw

PATCH 21/60 cpuidle: make AMC C1E work in processor_idle

In reply to Greg KH

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

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

commit 87ad57bacb25c3f24c54f142ef445f68277705f0 upstream

When AMD C1E is enabled, local APIC timer will stop even in C1. This patch uses broadcast ipi to replace local APIC timer in C1.

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

[ impact: avoid boot hang in AMD CPU with C1E enabled ]

---
 drivers/acpi/processor_idle.c |    6 ++++++
 1 file changed, 6 insertions(+)
drivers/acpi/processor_idle.c +6 -0
@@ -303,6 +303,9 @@ static void acpi_timer_check_state(int s
 	struct acpi_processor_power *pwr = &pr->power;
 	u8 type = local_apic_timer_c2_ok ? ACPI_STATE_C3 : ACPI_STATE_C2;
 
+	if (boot_cpu_has(X86_FEATURE_AMDC1E))
+		type = ACPI_STATE_C1;
+
 	/*
 	 * Check, if one of the previous states already marked the lapic
 	 * unstable
@@ -1154,6 +1157,7 @@ static int acpi_processor_power_verify(s
 		switch (cx->type) {
 		case ACPI_STATE_C1:
 			cx->valid = 1;
+			acpi_timer_check_state(i, pr, cx);
 			break;
 
 		case ACPI_STATE_C2:
@@ -1476,12 +1480,14 @@ static int acpi_idle_enter_c1(struct cpu
 	if (pr->flags.bm_check)
 		acpi_idle_update_bm_rld(pr, cx);
 
+	acpi_state_timer_broadcast(pr, cx, 1);
 	t1 = inl(acpi_gbl_FADT.xpm_timer_block.address);
 	acpi_idle_do_entry(cx);
 	t2 = inl(acpi_gbl_FADT.xpm_timer_block.address);
 
 	local_irq_enable();
 	cx->usage++;
+	acpi_state_timer_broadcast(pr, cx, 0);
 
 	return ticks_elapsed_in_us(t1, t2);
 }
author
#22 lore raw

PATCH 22/60 drivers/serial/mpc52xx_uart.c: fix array overindexing check

In reply to Greg KH

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

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

commit b898f4f869da5b9d41f297fff87aca4cd42d80b3 upstream.

The check for an overindexing of mpc52xx_uart_{ports,nodes} has an off-by-one.

---
 drivers/serial/mpc52xx_uart.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/serial/mpc52xx_uart.c +1 -1
@@ -1000,7 +1000,7 @@ mpc52xx_console_setup(struct console *co
 	pr_debug("mpc52xx_console_setup co=%p, co->index=%i, options=%s\n",
 		 co, co->index, options);
 
-	if ((co->index < 0) || (co->index > MPC52xx_PSC_MAXNUM)) {
+	if ((co->index < 0) || (co->index >= MPC52xx_PSC_MAXNUM)) {
 		pr_debug("PSC%x out of range\n", co->index);
 		return -EINVAL;
 	}
author
#23 lore raw

PATCH 23/60 e1000: add missing length check to e1000 receive routine

In reply to Greg KH

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

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

commit ea30e11970a96cfe5e32c03a29332554573b4a10 upstream.

Patch to fix bad length checking in e1000. E1000 by default does two
things:

1) Spans rx descriptors for packets that don't fit into 1 skb on recieve
2) Strips the crc from a frame by subtracting 4 bytes from the length prior to doing an skb_put

Since the e1000 driver isn't written to support receiving packets that span multiple rx buffers, it checks the End of Packet bit of every frame, and discards it if its not set. This places us in a situation where, if we have a spanning packet, the first part is discarded, but the second part is not (since it is the end of packet, and it passes the EOP bit test). If the second part of the frame is small (4 bytes or less), we subtract 4 from it to remove its crc, underflow the length, and wind up in skb_over_panic, when we try to skb_put a huge number of bytes into the skb. This amounts to a remote DOS attack through careful selection of frame size in relation to interface MTU. The fix for this is already in the e1000e driver, as well as the e1000 sourceforge driver, but no one ever pushed it to e1000. This is lifted straight from e1000e, and prevents small frames from causing the underflow described above

---
 drivers/net/e1000/e1000_main.c |    5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/net/e1000/e1000_main.c +3 -2
@@ -4133,8 +4133,9 @@ static bool e1000_clean_rx_irq(struct e1
 		                 PCI_DMA_FROMDEVICE);
 
 		length = le16_to_cpu(rx_desc->length);
-
-		if (unlikely(!(status & E1000_RXD_STAT_EOP))) {
+		/* !EOP means multiple descriptors were used to store a single
+		 * packet, also make sure the frame isn't just CRC only */
+		if (unlikely(!(status & E1000_RXD_STAT_EOP) || (length <= 4))) {
 			/* All receives must fit into a single buffer */
 			E1000_DBG("%s: Receive packet consumed multiple"
 				  " buffers\n", netdev->name);
author
#24 lore raw

PATCH 24/60 hwmon: (lm78) Add missing __devexit_p()

In reply to Greg KH

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

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

commit 39d8bbedb9571a89d638f5b05358f26ab503d7a6 upstream.

The remove function uses __devexit, so the .remove assignment needs __devexit_p() to fix a build error with hotplug disabled.

---
 drivers/hwmon/lm78.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/hwmon/lm78.c +1 -1
@@ -178,7 +178,7 @@ static struct platform_driver lm78_isa_d
 		.name	= "lm78",
 	},
 	.probe		= lm78_isa_probe,
-	.remove		= lm78_isa_remove,
+	.remove		= __devexit_p(lm78_isa_remove),
 };
 
 
author
#25 lore raw

PATCH 25/60 igb: fix LRO warning

In reply to Greg KH

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

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

This fix is only needed for 2.6.29.y tree, since in 2.6.30 and later IGB has moved to using GRO instead of LRO.

igb supports LRO, but was not setting any hooks to the ->set_flags ethtool_ops function. This would trigger warnings if the user tried to enable or disable LRO.

Based on the patch provided by Stephen Hemminger <[email protected]>

---
 drivers/net/igb/igb_ethtool.c |    4 ++++
 1 file changed, 4 insertions(+)
drivers/net/igb/igb_ethtool.c +4 -0
@@ -2029,6 +2029,10 @@ static struct ethtool_ops igb_ethtool_op
 	.get_ethtool_stats      = igb_get_ethtool_stats,
 	.get_coalesce           = igb_get_coalesce,
 	.set_coalesce           = igb_set_coalesce,
+	.get_flags              = ethtool_op_get_flags,
+#ifdef CONFIG_IGB_LRO
+	.set_flags              = ethtool_op_set_flags,
+#endif
 };
 
 void igb_set_ethtool_ops(struct net_device *netdev)
author
#26 lore raw

PATCH 26/60 mm: account for MAP_SHARED mappings using VM_MAYSHARE and not VM_SHARED in hugetlbfs

In reply to Greg KH

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

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

commit f83a275dbc5ca1721143698e844243fcadfabf6a upstream.

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

hugetlbfs reserves huge pages but does not fault them at mmap() time to ensure that future faults succeed. The reservation behaviour differs depending on whether the mapping was mapped MAP_SHARED or MAP_PRIVATE. For MAP_SHARED mappings, hugepages are reserved when mmap() is first called and are tracked based on information associated with the inode. Other processes mapping MAP_SHARED use the same reservation. MAP_PRIVATE track the reservations based on the VMA created as part of the mmap() operation. Each process mapping MAP_PRIVATE must make its own reservation.

hugetlbfs currently checks if a VMA is MAP_SHARED with the VM_SHARED flag and not VM_MAYSHARE. For file-backed mappings, such as hugetlbfs, VM_SHARED is set only if the mapping is MAP_SHARED and the file was opened read-write. If a shared memory mapping was mapped shared-read-write for populating of data and mapped shared-read-only by other processes, then hugetlbfs would account for the mapping as if it was MAP_PRIVATE. This causes processes to fail to map the file MAP_SHARED even though it should succeed as the reservation is there.

This patch alters mm/hugetlb.c and replaces VM_SHARED with VM_MAYSHARE when the intent of the code was to check whether the VMA was mapped MAP_SHARED or MAP_PRIVATE.

Cc Hugh Dickins <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Lee Schermerhorn <[email protected]>
Cc KOSAKI Motohiro <[email protected]>
Cc Eric B Munson <[email protected]>
Cc Adam Litke <[email protected]>
Cc Andy Whitcroft <[email protected]>
---
 mm/hugetlb.c |   26 +++++++++++++-------------
 1 file changed, 13 insertions(+), 13 deletions(-)
mm/hugetlb.c +13 -13
@@ -286,7 +286,7 @@ void resv_map_release(struct kref *ref)
 static struct resv_map *vma_resv_map(struct vm_area_struct *vma)
 {
 	VM_BUG_ON(!is_vm_hugetlb_page(vma));
-	if (!(vma->vm_flags & VM_SHARED))
+	if (!(vma->vm_flags & VM_MAYSHARE))
 		return (struct resv_map *)(get_vma_private_data(vma) &
 							~HPAGE_RESV_MASK);
 	return 0;
@@ -295,7 +295,7 @@ static struct resv_map *vma_resv_map(str
 static void set_vma_resv_map(struct vm_area_struct *vma, struct resv_map *map)
 {
 	VM_BUG_ON(!is_vm_hugetlb_page(vma));
-	VM_BUG_ON(vma->vm_flags & VM_SHARED);
+	VM_BUG_ON(vma->vm_flags & VM_MAYSHARE);
 
 	set_vma_private_data(vma, (get_vma_private_data(vma) &
 				HPAGE_RESV_MASK) | (unsigned long)map);
@@ -304,7 +304,7 @@ static void set_vma_resv_map(struct vm_a
 static void set_vma_resv_flags(struct vm_area_struct *vma, unsigned long flags)
 {
 	VM_BUG_ON(!is_vm_hugetlb_page(vma));
-	VM_BUG_ON(vma->vm_flags & VM_SHARED);
+	VM_BUG_ON(vma->vm_flags & VM_MAYSHARE);
 
 	set_vma_private_data(vma, get_vma_private_data(vma) | flags);
 }
@@ -323,7 +323,7 @@ static void decrement_hugepage_resv_vma(
 	if (vma->vm_flags & VM_NORESERVE)
 		return;
 
-	if (vma->vm_flags & VM_SHARED) {
+	if (vma->vm_flags & VM_MAYSHARE) {
 		/* Shared mappings always use reserves */
 		h->resv_huge_pages--;
 	} else if (is_vma_resv_set(vma, HPAGE_RESV_OWNER)) {
@@ -339,14 +339,14 @@ static void decrement_hugepage_resv_vma(
 void reset_vma_resv_huge_pages(struct vm_area_struct *vma)
 {
 	VM_BUG_ON(!is_vm_hugetlb_page(vma));
-	if (!(vma->vm_flags & VM_SHARED))
+	if (!(vma->vm_flags & VM_MAYSHARE))
 		vma->vm_private_data = (void *)0;
 }
 
 /* Returns true if the VMA has associated reserve pages */
 static int vma_has_reserves(struct vm_area_struct *vma)
 {
-	if (vma->vm_flags & VM_SHARED)
+	if (vma->vm_flags & VM_MAYSHARE)
 		return 1;
 	if (is_vma_resv_set(vma, HPAGE_RESV_OWNER))
 		return 1;
@@ -890,7 +890,7 @@ static int vma_needs_reservation(struct 
 	struct address_space *mapping = vma->vm_file->f_mapping;
 	struct inode *inode = mapping->host;
 
-	if (vma->vm_flags & VM_SHARED) {
+	if (vma->vm_flags & VM_MAYSHARE) {
 		pgoff_t idx = vma_hugecache_offset(h, vma, addr);
 		return region_chg(&inode->i_mapping->private_list,
 							idx, idx + 1);
@@ -915,7 +915,7 @@ static void vma_commit_reservation(struc
 	struct address_space *mapping = vma->vm_file->f_mapping;
 	struct inode *inode = mapping->host;
 
-	if (vma->vm_flags & VM_SHARED) {
+	if (vma->vm_flags & VM_MAYSHARE) {
 		pgoff_t idx = vma_hugecache_offset(h, vma, addr);
 		region_add(&inode->i_mapping->private_list, idx, idx + 1);
 
@@ -1862,7 +1862,7 @@ retry_avoidcopy:
 	 * at the time of fork() could consume its reserves on COW instead
 	 * of the full address range.
 	 */
-	if (!(vma->vm_flags & VM_SHARED) &&
+	if (!(vma->vm_flags & VM_MAYSHARE) &&
 			is_vma_resv_set(vma, HPAGE_RESV_OWNER) &&
 			old_page != pagecache_page)
 		outside_reserve = 1;
@@ -1969,7 +1969,7 @@ retry:
 		clear_huge_page(page, address, huge_page_size(h));
 		__SetPageUptodate(page);
 
-		if (vma->vm_flags & VM_SHARED) {
+		if (vma->vm_flags & VM_MAYSHARE) {
 			int err;
 			struct inode *inode = mapping->host;
 
@@ -2073,7 +2073,7 @@ int hugetlb_fault(struct mm_struct *mm, 
 			goto out_unlock;
 		}
 
-		if (!(vma->vm_flags & VM_SHARED))
+		if (!(vma->vm_flags & VM_MAYSHARE))
 			pagecache_page = hugetlbfs_pagecache_page(h,
 								vma, address);
 	}
@@ -2223,7 +2223,7 @@ int hugetlb_reserve_pages(struct inode *
 	 * to reserve the full area even if read-only as mprotect() may be
 	 * called to make the mapping read-write. Assume !vma is a shm mapping
 	 */
-	if (!vma || vma->vm_flags & VM_SHARED)
+	if (!vma || vma->vm_flags & VM_MAYSHARE)
 		chg = region_chg(&inode->i_mapping->private_list, from, to);
 	else {
 		struct resv_map *resv_map = resv_map_alloc();
@@ -2246,7 +2246,7 @@ int hugetlb_reserve_pages(struct inode *
 		hugetlb_put_quota(inode->i_mapping, chg);
 		return ret;
 	}
-	if (!vma || vma->vm_flags & VM_SHARED)
+	if (!vma || vma->vm_flags & VM_MAYSHARE)
 		region_add(&inode->i_mapping->private_list, from, to);
 	return 0;
 }
author
#27 lore raw

PATCH 27/60 random: make get_random_int() more random

In reply to Greg KH

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

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

commit 8a0a9bd4db63bc45e3017bedeafbd88d0eb84d02 upstream.

It's a really simple patch that basically just open-codes the current "secure_ip_id()" call, but when open-coding it we now use a _static_ hashing area, so that it gets updated every time.

And to make sure somebody can't just start from the same original seed of all-zeroes, and then do the "half_md4_transform()" over and over until they get the same sequence as the kernel has, each iteration also mixes in the same old "current->pid + jiffies" we used - so we should now have a regular strong pseudo-number generator, but we also have one that doesn't have a single seed.

Note: the "pid + jiffies" is just meant to be a tiny tiny bit of noise. It has no real meaning. It could be anything. I just picked the previous seed, it's just that now we keep the state in between calls and that will feed into the next result, and that should make all the difference.

I made that hash be a per-cpu data just to avoid cache-line ping-pong:
having multiple CPU's write to the same data would be fine for randomness, and add yet another layer of chaos to it, but since get_random_int() is supposed to be a fast interface I did it that way instead. I considered using "__raw_get_cpu_var()" to avoid any preemption overhead while still getting the hash be _mostly_ ping-pong free, but in the end good taste won out.

---
 drivers/char/random.c |   19 ++++++++++++-------
 1 file changed, 12 insertions(+), 7 deletions(-)
drivers/char/random.c +12 -7
@@ -1626,15 +1626,20 @@ EXPORT_SYMBOL(secure_dccp_sequence_numbe
  * value is not cryptographically secure but for several uses the cost of
  * depleting entropy is too high
  */
+DEFINE_PER_CPU(__u32 [4], get_random_int_hash);
 unsigned int get_random_int(void)
 {
-	/*
-	 * Use IP's RNG. It suits our purpose perfectly: it re-keys itself
-	 * every second, from the entropy pool (and thus creates a limited
-	 * drain on it), and uses halfMD4Transform within the second. We
-	 * also mix it with jiffies and the PID:
-	 */
-	return secure_ip_id((__force __be32)(current->pid + jiffies));
+	struct keydata *keyptr;
+	__u32 *hash = get_cpu_var(get_random_int_hash);
+	int ret;
+
+	keyptr = get_keyptr();
+	hash[0] += current->pid + jiffies + get_cycles() + (int)(long)&ret;
+
+	ret = half_md4_transform(hash, keyptr->secret);
+	put_cpu_var(get_random_int_hash);
+
+	return ret;
 }
 
 /*
author
#28 lore raw

PATCH 28/60 Avoid ICE in get_random_int() with gcc-3.4.5

In reply to Greg KH

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

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

commit 26a9a418237c0b06528941bca693c49c8d97edbe upstream.

Martin Knoblauch reports that trying to build 2.6.30-rc6-git3 with RHEL4.3 userspace (gcc (GCC) 3.4.5 20051201 (Red Hat 3.4.5-2)) causes an internal compiler error (ICE):

    drivers/char/random.c: In function `get_random_int':
    drivers/char/random.c:1672: error: unrecognizable insn:
    (insn 202 148 150 0 /scratch/build/linux-2.6.30-rc6-git3/arch/x86/include/asm/tsc.h:23 (set (reg:SI 0 ax [91])
            (subreg:SI (plus:DI (plus:DI (reg:DI 0 ax [88])
                        (subreg:DI (reg:SI 6 bp) 0))
                    (const_int -4 [0xfffffffffffffffc])) 0)) -1 (nil)
        (nil))
    drivers/char/random.c:1672: internal compiler error: in extract_insn, at recog.c:2083

and after some debugging it turns out that it's due to the code trying to figure out the rough value of the current stack pointer by taking an address of an uninitialized variable and casting that to an integer.

This is clearly a compiler bug, but it's not worth fighting - while the current stack kernel pointer might be somewhat hard to predict in user space, it's also not generally going to change for a lot of the call chains for a particular process.

So just drop it, and mumble some incoherent curses at the compiler.

---
 drivers/char/random.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/char/random.c +1 -1
@@ -1634,7 +1634,7 @@ unsigned int get_random_int(void)
 	int ret;
 
 	keyptr = get_keyptr();
-	hash[0] += current->pid + jiffies + get_cycles() + (int)(long)&ret;
+	hash[0] += current->pid + jiffies + get_cycles();
 
 	ret = half_md4_transform(hash, keyptr->secret);
 	put_cpu_var(get_random_int_hash);
author
#29 lore raw

PATCH 29/60 SELinux: BUG in SELinux compat_net code

In reply to Greg KH

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

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

This patch is not applicable to Linus's tree as the code in question has been removed for 2.6.30. I'm sending in case any of the stable maintainers would like to push to their branches (which I think anything pre 2.6.30 would like to do).

Ubuntu users were experiencing a kernel panic when they enabled SELinux due to an old bug in our handling of the compatibility mode network controls, introduced Jan 1 2008 effad8df44261031a882e1a895415f7186a5098e Most distros have not used the compat_net code since the new code was introduced and so noone has hit this problem before. Ubuntu is the only distro I know that enabled that legacy cruft by default. But, I was ask to look at it and found that the above patch changed a call to avc_has_perm from if(send_perm) to if(!send_perm) in selinux_ip_postroute_iptables_compat(). The result is that users who turn on SELinux and have compat_net set can (and oftern will) BUG() in avc_has_perm_noaudit since they are requesting 0 permissions.

This patch corrects that accidental bug introduction.

---
 security/selinux/hooks.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
security/selinux/hooks.c +1 -1
@@ -4477,7 +4477,7 @@ static int selinux_ip_postroute_iptables
 	if (err)
 		return err;
 
-	if (send_perm != 0)
+	if (!send_perm)
 		return 0;
 
 	err = sel_netport_sid(sk->sk_protocol,
author
#30 lore raw

PATCH 30/60 sound: usb-audio: make the MotU Fastlane work again

In reply to Greg KH

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

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

commit 55de5ef970c680d8d75f2a9aa7e4f172140dbd9c upstream.

Kernel 2.6.18 broke the MotU Fastlane, which uses duplicate endpoint numbers in a manner that is not only illegal but also confuses the kernel's endpoint descriptor caching mechanism. To work around this, we have to add a separate usb_set_interface() call to guide the USB core to the correct descriptors.

---
 sound/usb/usbaudio.c  |    2 +-
 sound/usb/usbaudio.h  |    2 +-
 sound/usb/usbmidi.c   |   12 +++++++++++-
 sound/usb/usbquirks.h |    2 +-
 4 files changed, 14 insertions(+), 4 deletions(-)
sound/usb/usbaudio.c +1 -1
@@ -3367,7 +3367,7 @@ static int snd_usb_create_quirk(struct s
 		[QUIRK_MIDI_YAMAHA] = snd_usb_create_midi_interface,
 		[QUIRK_MIDI_MIDIMAN] = snd_usb_create_midi_interface,
 		[QUIRK_MIDI_NOVATION] = snd_usb_create_midi_interface,
-		[QUIRK_MIDI_RAW] = snd_usb_create_midi_interface,
+		[QUIRK_MIDI_FASTLANE] = snd_usb_create_midi_interface,
 		[QUIRK_MIDI_EMAGIC] = snd_usb_create_midi_interface,
 		[QUIRK_MIDI_CME] = snd_usb_create_midi_interface,
 		[QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_audio_quirk,
sound/usb/usbaudio.h +1 -1
@@ -153,7 +153,7 @@ enum quirk_type {
 	QUIRK_MIDI_YAMAHA,
 	QUIRK_MIDI_MIDIMAN,
 	QUIRK_MIDI_NOVATION,
-	QUIRK_MIDI_RAW,
+	QUIRK_MIDI_FASTLANE,
 	QUIRK_MIDI_EMAGIC,
 	QUIRK_MIDI_CME,
 	QUIRK_AUDIO_STANDARD_INTERFACE,
sound/usb/usbmidi.c +11 -1
@@ -1733,8 +1733,18 @@ int snd_usb_create_midi_interface(struct
 		umidi->usb_protocol_ops = &snd_usbmidi_novation_ops;
 		err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints);
 		break;
-	case QUIRK_MIDI_RAW:
+	case QUIRK_MIDI_FASTLANE:
 		umidi->usb_protocol_ops = &snd_usbmidi_raw_ops;
+		/*
+		 * Interface 1 contains isochronous endpoints, but with the same
+		 * numbers as in interface 0.  Since it is interface 1 that the
+		 * USB core has most recently seen, these descriptors are now
+		 * associated with the endpoint numbers.  This will foul up our
+		 * attempts to submit bulk/interrupt URBs to the endpoints in
+		 * interface 0, so we have to make sure that the USB core looks
+		 * again at interface 0 by calling usb_set_interface() on it.
+		 */
+		usb_set_interface(umidi->chip->dev, 0, 0);
 		err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints);
 		break;
 	case QUIRK_MIDI_EMAGIC:
sound/usb/usbquirks.h +1 -1
@@ -1756,7 +1756,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
 		.data = & (const struct snd_usb_audio_quirk[]) {
 			{
 				.ifnum = 0,
-				.type = QUIRK_MIDI_RAW
+				.type = QUIRK_MIDI_FASTLANE
 			},
 			{
 				.ifnum = 1,
author
#31 lore raw

PATCH 31/60 USB: isp1760: urb_dequeue doesnt always find the urbs

In reply to Greg KH

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

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

commit 0afb20e00b5053170c85298fed842b32d20b4ea9 upstream.

The option driver (and presumably others) allocates several URBs when it opens and tries to free them when it closes. The isp1760_urb_dequeue function gets called, but the packet being dequeued is not necessarily at the
front of one of the 32 queues. If not, the isp1760_urb_done function doesn't get called for the URB and the process trying to free it hangs forever on a wait_queue. This patch does two things. If the URB being dequeued has others queued behind it, it re-queues them. And it searches the queues looking for the URB being dequeued rather than just looking at the one at the front of the queue.

[bigeasy@linutronix] whitespace fixes, reformating

---
 drivers/usb/host/isp1760-hcd.c |   24 ++++++++++++++++++++++--
 1 file changed, 22 insertions(+), 2 deletions(-)
drivers/usb/host/isp1760-hcd.c +22 -2
@@ -1645,6 +1645,7 @@ static int isp1760_urb_dequeue(struct us
 	u32 reg_base, or_reg, skip_reg;
 	unsigned long flags;
 	struct ptd ptd;
+	packet_enqueue *pe;
 
 	switch (usb_pipetype(urb->pipe)) {
 	case PIPE_ISOCHRONOUS:
@@ -1656,6 +1657,7 @@ static int isp1760_urb_dequeue(struct us
 		reg_base = INT_REGS_OFFSET;
 		or_reg = HC_INT_IRQ_MASK_OR_REG;
 		skip_reg = HC_INT_PTD_SKIPMAP_REG;
+		pe = enqueue_an_INT_packet;
 		break;
 
 	default:
@@ -1663,6 +1665,7 @@ static int isp1760_urb_dequeue(struct us
 		reg_base = ATL_REGS_OFFSET;
 		or_reg = HC_ATL_IRQ_MASK_OR_REG;
 		skip_reg = HC_ATL_PTD_SKIPMAP_REG;
+		pe =  enqueue_an_ATL_packet;
 		break;
 	}
 
@@ -1674,6 +1677,7 @@ static int isp1760_urb_dequeue(struct us
 			u32 skip_map;
 			u32 or_map;
 			struct isp1760_qtd *qtd;
+			struct isp1760_qh *qh = ints->qh;
 
 			skip_map = isp1760_readl(hcd->regs + skip_reg);
 			skip_map |= 1 << i;
@@ -1686,8 +1690,7 @@ static int isp1760_urb_dequeue(struct us
 			priv_write_copy(priv, (u32 *)&ptd, hcd->regs + reg_base
 					+ i * sizeof(ptd), sizeof(ptd));
 			qtd = ints->qtd;
-
-			clean_up_qtdlist(qtd);
+			qtd = clean_up_qtdlist(qtd);
 
 			free_mem(priv, ints->payload);
 
@@ -1698,7 +1701,24 @@ static int isp1760_urb_dequeue(struct us
 			ints->payload = 0;
 
 			isp1760_urb_done(priv, urb, status);
+			if (qtd)
+				pe(hcd, qh, qtd);
 			break;
+
+		} else if (ints->qtd) {
+			struct isp1760_qtd *qtd, *prev_qtd = ints->qtd;
+
+			for (qtd = ints->qtd->hw_next; qtd; qtd = qtd->hw_next) {
+				if (qtd->urb == urb) {
+					prev_qtd->hw_next = clean_up_qtdlist(qtd);
+					isp1760_urb_done(priv, urb, status);
+					break;
+				}
+				prev_qtd = qtd;
+			}
+			/* we found the urb before the end of the list */
+			if (qtd)
+				break;
 		}
 		ints++;
 	}
author
#32 lore raw

PATCH 32/60 x86: ignore VM_LOCKED when determining if hugetlb-backed page tables can be shared or not

In reply to Greg KH

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

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

commit 32b154c0b0bae2879bf4e549d861caf1759a3546 upstream.

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

On x86 and x86-64, it is possible that page tables are shared beween shared mappings backed by hugetlbfs. As part of this, page_table_shareable() checks a pair of vma->vm_flags and they must match if they are to be shared. All VMA flags are taken into account, including VM_LOCKED.

The problem is that VM_LOCKED is cleared on fork(). When a process with a shared memory segment forks() to exec() a helper, there will be shared VMAs with different flags. The impact is that the shared segment is sometimes considered shareable and other times not, depending on what process is checking.

What happens is that the segment page tables are being shared but the count is inaccurate depending on the ordering of events. As the page tables are freed with put_page(), bad pmd's are found when some of the children exit. The hugepage counters also get corrupted and the Total and Free count will no longer match even when all the hugepage-backed regions are freed. This requires a reboot of the machine to "fix".

This patch addresses the problem by comparing all flags except VM_LOCKED when deciding if pagetables should be shared or not for hugetlbfs-backed mapping.

---
 arch/x86/mm/hugetlbpage.c |    6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)
arch/x86/mm/hugetlbpage.c +5 -1
@@ -26,12 +26,16 @@ static unsigned long page_table_shareabl
 	unsigned long sbase = saddr & PUD_MASK;
 	unsigned long s_end = sbase + PUD_SIZE;
 
+	/* Allow segments to share if only one is marked locked */
+	unsigned long vm_flags = vma->vm_flags & ~VM_LOCKED;
+	unsigned long svm_flags = svma->vm_flags & ~VM_LOCKED;
+
 	/*
 	 * match the virtual addresses, permission and the alignment of the
 	 * page table page.
 	 */
 	if (pmd_index(addr) != pmd_index(saddr) ||
-	    vma->vm_flags != svma->vm_flags ||
+	    vm_flags != svm_flags ||
 	    sbase < svma->vm_start || svma->vm_end < s_end)
 		return 0;
 
author
#33 lore raw

PATCH 33/60 x86/pci: fix mmconfig detection with 32bit near 4g

In reply to Greg KH

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

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

commit 75e613cdc7bb2ba3795b1bc3ddf19476c767ba68 upstream.

Pascal reported and bisected a commit:
| x86/PCI: don't call e820_all_mapped with -1 in the mmconfig case

which broke one system system.

ACPI: Using IOAPIC for interrupt routing
PCI: MCFG configuration 0: base f0000000 segment 0 buses 0 - 255
PCI: MCFG area at f0000000 reserved in ACPI motherboard resources
PCI: Using MMCONFIG for extended config space

it didn't have
PCI: updated MCFG configuration 0: base f0000000 segment 0 buses 0 - 63 anymore, and try to use 0xf000000 - 0xffffffff for mmconfig

For 32bit, mcfg_res->end could be 32bit only (if 64 resources aren't used) So use end - 1 to pass the value in mcfg->end to avoid overflow.

We don't need to worry about the e820 path, they are always 64 bit.

---
 arch/x86/pci/mmconfig-shared.c |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
arch/x86/pci/mmconfig-shared.c +3 -3
@@ -255,7 +255,7 @@ static acpi_status __init check_mcfg_res
 		if (!fixmem32)
 			return AE_OK;
 		if ((mcfg_res->start >= fixmem32->address) &&
-		    (mcfg_res->end <= (fixmem32->address +
+		    (mcfg_res->end < (fixmem32->address +
 				      fixmem32->address_length))) {
 			mcfg_res->flags = 1;
 			return AE_CTRL_TERMINATE;
@@ -272,7 +272,7 @@ static acpi_status __init check_mcfg_res
 		return AE_OK;
 
 	if ((mcfg_res->start >= address.minimum) &&
-	    (mcfg_res->end <= (address.minimum + address.address_length))) {
+	    (mcfg_res->end < (address.minimum + address.address_length))) {
 		mcfg_res->flags = 1;
 		return AE_CTRL_TERMINATE;
 	}
@@ -298,7 +298,7 @@ static int __init is_acpi_reserved(u64 s
 	struct resource mcfg_res;
 
 	mcfg_res.start = start;
-	mcfg_res.end = end;
+	mcfg_res.end = end - 1;
 	mcfg_res.flags = 0;
 
 	acpi_get_devices("PNP0C01", find_mboard_resource, &mcfg_res, NULL);
author
#34 lore raw

PATCH 34/60 V4L/DVB (10943): cx88: Prevent general protection fault on rmmod

In reply to Greg KH

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

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

commit 569b7ec73abf576f9a9e4070d213aadf2cce73cb upstream.

V4L/DVB (10943): cx88: Prevent general protection fault on rmmod

When unloading the cx8800 driver I sometimes get a general protection fault. Analysis revealed a race in cx88_ir_stop(). It can be solved by using a delayed work instead of a timer for infrared input polling.

---
 drivers/media/video/cx88/cx88-input.c |   25 +++++++------------------
 1 file changed, 7 insertions(+), 18 deletions(-)
drivers/media/video/cx88/cx88-input.c +7 -18
@@ -48,8 +48,7 @@ struct cx88_IR {
 
 	/* poll external decoder */
 	int polling;
-	struct work_struct work;
-	struct timer_list timer;
+	struct delayed_work work;
 	u32 gpio_addr;
 	u32 last_gpio;
 	u32 mask_keycode;
@@ -143,27 +142,19 @@ static void cx88_ir_handle_key(struct cx
 	}
 }
 
-static void ir_timer(unsigned long data)
-{
-	struct cx88_IR *ir = (struct cx88_IR *)data;
-
-	schedule_work(&ir->work);
-}
-
 static void cx88_ir_work(struct work_struct *work)
 {
-	struct cx88_IR *ir = container_of(work, struct cx88_IR, work);
+	struct cx88_IR *ir = container_of(work, struct cx88_IR, work.work);
 
 	cx88_ir_handle_key(ir);
-	mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling));
+	schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling));
 }
 
 void cx88_ir_start(struct cx88_core *core, struct cx88_IR *ir)
 {
 	if (ir->polling) {
-		setup_timer(&ir->timer, ir_timer, (unsigned long)ir);
-		INIT_WORK(&ir->work, cx88_ir_work);
-		schedule_work(&ir->work);
+		INIT_DELAYED_WORK(&ir->work, cx88_ir_work);
+		schedule_delayed_work(&ir->work, 0);
 	}
 	if (ir->sampling) {
 		core->pci_irqmask |= PCI_INT_IR_SMPINT;
@@ -179,10 +170,8 @@ void cx88_ir_stop(struct cx88_core *core
 		core->pci_irqmask &= ~PCI_INT_IR_SMPINT;
 	}
 
-	if (ir->polling) {
-		del_timer_sync(&ir->timer);
-		flush_scheduled_work();
-	}
+	if (ir->polling)
+		cancel_delayed_work_sync(&ir->work);
 }
 
 /* ---------------------------------------------------------------------- */
author
#35 lore raw

PATCH 35/60 x86: fix DMI on EFI

In reply to Greg KH

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

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

commit ff0c0874905fb312ca1491bbdac2653b0b48c20b upstream.

Impact: reactivate DMI quirks on EFI hardware

DMI tables are loaded by EFI, so the dmi calls must happen after efi_init() and not before.

Currently Apple hardware uses DMI to determine the framebuffer mappings for efifb. Without DMI working you also have no video on MacBook Pro.

This patch resolves the DMI issue for EFI hardware (DMI is now properly detected at boot), and additionally efifb now loads on Apple hardware (i.e. video works).

LKML-Reference: <[email protected]>

---
 arch/x86/kernel/setup.c |    5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
arch/x86/kernel/setup.c +3 -2
@@ -730,6 +730,9 @@ void __init setup_arch(char **cmdline_p)
 
 	finish_e820_parsing();
 
+	if (efi_enabled)
+		efi_init();
+
 	dmi_scan_machine();
 
 	dmi_check_system(bad_bios_dmi_table);
@@ -743,8 +746,6 @@ void __init setup_arch(char **cmdline_p)
 	insert_resource(&iomem_resource, &data_resource);
 	insert_resource(&iomem_resource, &bss_resource);
 
-	if (efi_enabled)
-		efi_init();
 
 #ifdef CONFIG_X86_32
 	if (ppro_with_ram_bug()) {
author
#36 lore raw

PATCH 36/60 mac80211: pid, fix memory corruption

In reply to Greg KH

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

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

commit a8659597bf744b0f8d2560e2a734b5c941569e0e upstream

pid doesn't count with some band having more bitrates than the one associated the first time.
Fix that by counting the maximal available bitrate count and allocate big enough space.

Secondly, fix touching uninitialized memory which causes panics. Index sucked from this random memory points to the hell. The fix is to sort the rates on each band change.

Also remove a comment which is wrong now.

This version also contains half of
mac80211: avoid NULL ptr deref when finding max_rates in PID and minstrel patch by John W. Linville, which is namely:
- if (sband->n_bitrates > max_rates)
+ if (sband && sband->n_bitrates > max_rates)
to fix oopses on one band devices.

---
 net/mac80211/rc80211_pid_algo.c |   71 +++++++++++++++++++++-------------------
 1 file changed, 39 insertions(+), 32 deletions(-)
net/mac80211/rc80211_pid_algo.c +39 -32
@@ -367,8 +367,40 @@ static void rate_control_pid_rate_init(v
 	 * Until that method is implemented, we will use the lowest supported
 	 * rate as a workaround. */
 	struct ieee80211_supported_band *sband;
+	struct rc_pid_info *pinfo = priv;
+	struct rc_pid_rateinfo *rinfo = pinfo->rinfo;
+	int i, j, tmp;
+	bool s;
 
 	sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
+
+	/* Sort the rates. This is optimized for the most common case (i.e.
+	 * almost-sorted CCK+OFDM rates). Kind of bubble-sort with reversed
+	 * mapping too. */
+	for (i = 0; i < sband->n_bitrates; i++) {
+		rinfo[i].index = i;
+		rinfo[i].rev_index = i;
+		if (RC_PID_FAST_START)
+			rinfo[i].diff = 0;
+		else
+			rinfo[i].diff = i * pinfo->norm_offset;
+	}
+	for (i = 1; i < sband->n_bitrates; i++) {
+		s = 0;
+		for (j = 0; j < sband->n_bitrates - i; j++)
+			if (unlikely(sband->bitrates[rinfo[j].index].bitrate >
+				     sband->bitrates[rinfo[j + 1].index].bitrate)) {
+				tmp = rinfo[j].index;
+				rinfo[j].index = rinfo[j + 1].index;
+				rinfo[j + 1].index = tmp;
+				rinfo[rinfo[j].index].rev_index = j;
+				rinfo[rinfo[j + 1].index].rev_index = j + 1;
+				s = 1;
+			}
+		if (!s)
+			break;
+	}
+
 	sta->txrate_idx = rate_lowest_index(local, sband, sta);
 	sta->fail_avg = 0;
 }
@@ -378,21 +410,23 @@ static void *rate_control_pid_alloc(stru
 	struct rc_pid_info *pinfo;
 	struct rc_pid_rateinfo *rinfo;
 	struct ieee80211_supported_band *sband;
-	int i, j, tmp;
-	bool s;
+	int i, max_rates = 0;
 #ifdef CONFIG_MAC80211_DEBUGFS
 	struct rc_pid_debugfs_entries *de;
 #endif
 
-	sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
-
 	pinfo = kmalloc(sizeof(*pinfo), GFP_ATOMIC);
 	if (!pinfo)
 		return NULL;
 
+	for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
+		sband = local->hw.wiphy->bands[i];
+		if (sband && sband->n_bitrates > max_rates)
+			max_rates = sband->n_bitrates;
+	}
 	/* We can safely assume that sband won't change unless we get
 	 * reinitialized. */
-	rinfo = kmalloc(sizeof(*rinfo) * sband->n_bitrates, GFP_ATOMIC);
+	rinfo = kmalloc(sizeof(*rinfo) * max_rates, GFP_ATOMIC);
 	if (!rinfo) {
 		kfree(pinfo);
 		return NULL;
@@ -410,33 +444,6 @@ static void *rate_control_pid_alloc(stru
 	pinfo->rinfo = rinfo;
 	pinfo->oldrate = 0;
 
-	/* Sort the rates. This is optimized for the most common case (i.e.
-	 * almost-sorted CCK+OFDM rates). Kind of bubble-sort with reversed
-	 * mapping too. */
-	for (i = 0; i < sband->n_bitrates; i++) {
-		rinfo[i].index = i;
-		rinfo[i].rev_index = i;
-		if (RC_PID_FAST_START)
-			rinfo[i].diff = 0;
-		else
-			rinfo[i].diff = i * pinfo->norm_offset;
-	}
-	for (i = 1; i < sband->n_bitrates; i++) {
-		s = 0;
-		for (j = 0; j < sband->n_bitrates - i; j++)
-			if (unlikely(sband->bitrates[rinfo[j].index].bitrate >
-				     sband->bitrates[rinfo[j + 1].index].bitrate)) {
-				tmp = rinfo[j].index;
-				rinfo[j].index = rinfo[j + 1].index;
-				rinfo[j + 1].index = tmp;
-				rinfo[rinfo[j].index].rev_index = j;
-				rinfo[rinfo[j + 1].index].rev_index = j + 1;
-				s = 1;
-			}
-		if (!s)
-			break;
-	}
-
 #ifdef CONFIG_MAC80211_DEBUGFS
 	de = &pinfo->dentries;
 	de->dir = debugfs_create_dir("rc80211_pid",
author
#37 lore raw

PATCH 37/60 ext4: fix ext4_free_inode() vs. ext4_claim_inode() race

In reply to Greg KH

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

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

(cherry picked from commit 7ce9d5d1f3c8736511daa413c64985a05b2feee3)

I was seeing fsck errors on inode bitmaps after a 4 thread dbench run on a 4 cpu machine:

Inode bitmap differences: -50736 -(50752--50753) etc...

I believe that this is because ext4_free_inode() uses atomic bitops, and although ext4_new_inode() *used* to also use atomic bitops for synchronization, commit 393418676a7602e1d7d3f6e560159c65c8cbd50e changed this to use the sb_bgl_lock, so that we could also synchronize against read_inode_bitmap and initialization of uninit inode tables.

However, that change left ext4_free_inode using atomic bitops, which I think leaves no synchronization between setting & unsetting bits in the inode table.

The below patch fixes it for me, although I wonder if we're getting at all heavy-handed with this spinlock...

---
 fs/ext4/ialloc.c |   12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)
fs/ext4/ialloc.c +7 -5
@@ -188,7 +188,7 @@ void ext4_free_inode (handle_t *handle, 
 	struct ext4_group_desc * gdp;
 	struct ext4_super_block * es;
 	struct ext4_sb_info *sbi;
-	int fatal = 0, err;
+	int fatal = 0, err, cleared;
 	ext4_group_t flex_group;
 
 	if (atomic_read(&inode->i_count) > 1) {
@@ -242,10 +242,12 @@ void ext4_free_inode (handle_t *handle, 
 		goto error_return;
 
 	/* Ok, now we can actually update the inode bitmaps.. */
-	if (!ext4_clear_bit_atomic(sb_bgl_lock(sbi, block_group),
-					bit, bitmap_bh->b_data))
-		ext4_error (sb, "ext4_free_inode",
-			      "bit already cleared for inode %lu", ino);
+	spin_lock(sb_bgl_lock(sbi, block_group));
+	cleared = ext4_clear_bit(bit, bitmap_bh->b_data);
+	spin_unlock(sb_bgl_lock(sbi, block_group));
+	if (!cleared)
+		ext4_error(sb, "ext4_free_inode",
+			   "bit already cleared for inode %lu", ino);
 	else {
 		gdp = ext4_get_group_desc (sb, block_group, &bh2);
 
author
#38 lore raw

PATCH 38/60 ext4: fix header check in ext4_ext_search_right() for deep extent trees.

In reply to Greg KH

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

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

(cherry picked from commit 395a87bfefbc400011417e9eaae33169f9f036c0)

The ext4_ext_search_right() function is confusing; it uses a "depth" variable which is 0 at the root and maximum at the leaves, but the on-disk metadata uses a "depth" (actually eh_depth) which is opposite: maximum at the root, and 0 at the leaves.

The ext4_ext_check_header() function is given a depth and checks the header agaisnt that depth; it expects the on-disk semantics, but we are giving it the opposite in the while loop in this function. We should be giving it the on-disk notion of "depth" which we can get from (p_depth - depth) - and if you look, the last (more commonly hit) call to ext4_ext_check_header() does just this.

Sending in the wrong depth results in (incorrect) messages about corruption:

EXT4-fs error (device sdb1): ext4_ext_search_right: bad header in inode #2621457: unexpected eh_depth - magic f30a, entries 340, max 340(0), depth 1(2)

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

---
 fs/ext4/extents.c |    6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
fs/ext4/extents.c +4 -2
@@ -1118,7 +1118,8 @@ ext4_ext_search_right(struct inode *inod
 	struct ext4_extent_idx *ix;
 	struct ext4_extent *ex;
 	ext4_fsblk_t block;
-	int depth, ee_len;
+	int depth;	/* Note, NOT eh_depth; depth from top of tree */
+	int ee_len;
 
 	BUG_ON(path == NULL);
 	depth = path->p_depth;
@@ -1177,7 +1178,8 @@ ext4_ext_search_right(struct inode *inod
 		if (bh == NULL)
 			return -EIO;
 		eh = ext_block_hdr(bh);
-		if (ext4_ext_check_header(inode, eh, depth)) {
+		/* subtract from p_depth to get proper eh_depth */
+		if (ext4_ext_check_header(inode, eh, path->p_depth - depth)) {
 			put_bh(bh);
 			return -EIO;
 		}
author
#39 lore raw

PATCH 39/60 ext4: Print the find_group_flex() warning only once

In reply to Greg KH

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

------------------
From: "Theodore Ts'o" <[email protected]>

(cherry picked from commit 2842c3b5449f31470b61db716f1926b594fb6156)

This is a short-term warning, and even printk_ratelimit() can result in too much noise in system logs. So only print it once as a warning.

---
 fs/ext4/ialloc.c |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
fs/ext4/ialloc.c +3 -1
@@ -687,6 +687,7 @@ struct inode *ext4_new_inode(handle_t *h
 	struct inode *ret;
 	ext4_group_t i;
 	int free = 0;
+	static int once = 1;
 	ext4_group_t flex_group;
 
 	/* Cannot create files in a deleted directory */
@@ -706,7 +707,8 @@ struct inode *ext4_new_inode(handle_t *h
 		ret2 = find_group_flex(sb, dir, &group);
 		if (ret2 == -1) {
 			ret2 = find_group_other(sb, dir, &group);
-			if (ret2 == 0 && printk_ratelimit())
+			if (ret2 == 0 && once)
+				once = 0;
 				printk(KERN_NOTICE "ext4: find_group_flex "
 				       "failed, fallback succeeded dir %lu\n",
 				       dir->i_ino);
author
#40 lore raw

PATCH 40/60 ext4: fix bogus BUG_ONs in in mballoc code

In reply to Greg KH

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

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

(cherry picked from commit 8d03c7a0c550e7ab24cadcef5e66656bfadec8b9)

Thiemo Nagel reported that:

# dd if=/dev/zero of=image.ext4 bs=1M count=2
# mkfs.ext4 -v -F -b 1024 -m 0 -g 512 -G 4 -I 128 -N 1 \
  -O large_file,dir_index,flex_bg,extent,sparse_super image.ext4
# mount -o loop image.ext4 mnt/
# dd if=/dev/zero of=mnt/file

oopsed, with a BUG_ON in ext4_mb_normalize_request because size == EXT4_BLOCKS_PER_GROUP

It appears to me (esp. after talking to Andreas) that the BUG_ON is bogus; a request of exactly EXT4_BLOCKS_PER_GROUP should be allowed, though larger sizes do indicate a problem.

Fix that an another (apparently rare) codepath with a similar check.

---
 fs/ext4/mballoc.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
fs/ext4/mballoc.c +2 -2
@@ -1450,7 +1450,7 @@ static void ext4_mb_measure_extent(struc
 	struct ext4_free_extent *gex = &ac->ac_g_ex;
 
 	BUG_ON(ex->fe_len <= 0);
-	BUG_ON(ex->fe_len >= EXT4_BLOCKS_PER_GROUP(ac->ac_sb));
+	BUG_ON(ex->fe_len > EXT4_BLOCKS_PER_GROUP(ac->ac_sb));
 	BUG_ON(ex->fe_start >= EXT4_BLOCKS_PER_GROUP(ac->ac_sb));
 	BUG_ON(ac->ac_status != AC_STATUS_CONTINUE);
 
@@ -3400,7 +3400,7 @@ ext4_mb_normalize_request(struct ext4_al
 	}
 	BUG_ON(start + size <= ac->ac_o_ex.fe_logical &&
 			start > ac->ac_o_ex.fe_logical);
-	BUG_ON(size <= 0 || size >= EXT4_BLOCKS_PER_GROUP(ac->ac_sb));
+	BUG_ON(size <= 0 || size > EXT4_BLOCKS_PER_GROUP(ac->ac_sb));
 
 	/* now prepare goal request */
 
author
#41 lore raw

PATCH 41/60 ext4: fix bb_prealloc_list corruption due to wrong group locking

In reply to Greg KH

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

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

(cherry-picked from commit d33a1976fbee1ee321d6f014333d8f03a39d526c)

This is for Red Hat bug 490026: EXT4 panic, list corruption in ext4_mb_new_inode_pa

ext4_lock_group(sb, group) is supposed to protect this list for each group, and a common code flow to remove an album is like this:

    ext4_get_group_no_and_offset(sb, pa->pa_pstart, &grp, NULL);
    ext4_lock_group(sb, grp);
    list_del(&pa->pa_group_list);
    ext4_unlock_group(sb, grp);

so it's critical that we get the right group number back for this prealloc context, to lock the right group (the one associated with this pa) and prevent concurrent list manipulation.

however, ext4_mb_put_pa() passes in (pa->pa_pstart - 1) with a comment, "-1 is to protect from crossing allocation group".

This makes sense for the group_pa, where pa_pstart is advanced by the length which has been used (in ext4_mb_release_context()), and when the entire length has been used, pa_pstart has been advanced to the first block of the next group.

However, for inode_pa, pa_pstart is never advanced; it's just set once to the first block in the group and not moved after that. So in this case, if we subtract one in ext4_mb_put_pa(), we are actually locking the *previous* group, and opening the race with the other threads which do not subtract off the extra block.

---
 fs/ext4/mballoc.c |    9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)
fs/ext4/mballoc.c +7 -2
@@ -3698,6 +3698,7 @@ static void ext4_mb_put_pa(struct ext4_a
 			struct super_block *sb, struct ext4_prealloc_space *pa)
 {
 	unsigned long grp;
+	ext4_fsblk_t grp_blk;
 
 	if (!atomic_dec_and_test(&pa->pa_count) || pa->pa_free != 0)
 		return;
@@ -3712,8 +3713,12 @@ static void ext4_mb_put_pa(struct ext4_a
 	pa->pa_deleted = 1;
 	spin_unlock(&pa->pa_lock);
 
-	/* -1 is to protect from crossing allocation group */
-	ext4_get_group_no_and_offset(sb, pa->pa_pstart - 1, &grp, NULL);
+	grp_blk = pa->pa_pstart;
+	/* If linear, pa_pstart may be in the next group when pa is used up */
+	if (pa->pa_linear)
+		grp_blk--;
+
+	ext4_get_group_no_and_offset(sb, grp_blk, &grp, NULL);
 
 	/*
 	 * possible race:
author
#42 lore raw

PATCH 42/60 ext4: dont inherit inappropriate inode flags from parent

In reply to Greg KH

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

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

(cherry picked from commit 8fa43a81b97853fc69417bb6054182e78f95cbeb)

At present INDEX and EXTENTS are the only flags that new ext4 inodes do NOT inherit from their parent. In addition prevent the flags DIRTY, ECOMPR, IMAGIC, TOPDIR, HUGE_FILE and EXT_MIGRATE from being inherited. List inheritable flags explicitly to prevent future flags from accidentally being inherited.

This fixes the TOPDIR flag inheritance bug reported at
http://bugzilla.kernel.org/show_bug.cgi?id=9866.

---
 fs/ext4/ext4.h   |    7 +++++++
 fs/ext4/ialloc.c |    2 +-
 2 files changed, 8 insertions(+), 1 deletion(-)
fs/ext4/ext4.h +7 -0
@@ -248,6 +248,13 @@ struct flex_groups {
 #define EXT4_FL_USER_VISIBLE		0x000BDFFF /* User visible flags */
 #define EXT4_FL_USER_MODIFIABLE		0x000380FF /* User modifiable flags */
 
+/* Flags that should be inherited by new inodes from their parent. */
+#define EXT4_FL_INHERITED (EXT4_SECRM_FL | EXT4_UNRM_FL | EXT4_COMPR_FL |\
+			   EXT4_SYNC_FL | EXT4_IMMUTABLE_FL | EXT4_APPEND_FL |\
+			   EXT4_NODUMP_FL | EXT4_NOATIME_FL |\
+			   EXT4_NOCOMPR_FL | EXT4_JOURNAL_DATA_FL |\
+			   EXT4_NOTAIL_FL | EXT4_DIRSYNC_FL)
+
 /*
  * Inode dynamic state flags
  */
fs/ext4/ialloc.c +1 -1
@@ -869,7 +869,7 @@ got:
 	 * newly created directory and file only if -o extent mount option is
 	 * specified
 	 */
-	ei->i_flags = EXT4_I(dir)->i_flags & ~(EXT4_INDEX_FL|EXT4_EXTENTS_FL);
+	ei->i_flags = EXT4_I(dir)->i_flags & EXT4_FL_INHERITED;
 	if (S_ISLNK(mode))
 		ei->i_flags &= ~(EXT4_IMMUTABLE_FL|EXT4_APPEND_FL);
 	/* dirsync only applies to directories */
author
#43 lore raw

PATCH 43/60 ext4: tighten restrictions on inode flags

In reply to Greg KH

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

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

(cherry picked from commit 2dc6b0d48ca0599837df21b14bb8393d0804af57)

At the moment there are few restrictions on which flags may be set on which inodes. Specifically DIRSYNC may only be set on directories and IMMUTABLE and APPEND may not be set on links. Tighten that to disallow TOPDIR being set on non-directories and only NODUMP and NOATIME to be set on non-regular file, non-directories.

Introduces a flags masking function which masks flags based on mode and use it during inode creation and when flags are set via the ioctl to facilitate future consistency.

---
 fs/ext4/ext4.h   |   17 +++++++++++++++++
 fs/ext4/ialloc.c |   14 +++++---------
 fs/ext4/ioctl.c  |    3 +--
 3 files changed, 23 insertions(+), 11 deletions(-)
fs/ext4/ext4.h +17 -0
@@ -255,6 +255,23 @@ struct flex_groups {
 			   EXT4_NOCOMPR_FL | EXT4_JOURNAL_DATA_FL |\
 			   EXT4_NOTAIL_FL | EXT4_DIRSYNC_FL)
 
+/* Flags that are appropriate for regular files (all but dir-specific ones). */
+#define EXT4_REG_FLMASK (~(EXT4_DIRSYNC_FL | EXT4_TOPDIR_FL))
+
+/* Flags that are appropriate for non-directories/regular files. */
+#define EXT4_OTHER_FLMASK (EXT4_NODUMP_FL | EXT4_NOATIME_FL)
+
+/* Mask out flags that are inappropriate for the given type of inode. */
+static inline __u32 ext4_mask_flags(umode_t mode, __u32 flags)
+{
+	if (S_ISDIR(mode))
+		return flags;
+	else if (S_ISREG(mode))
+		return flags & EXT4_REG_FLMASK;
+	else
+		return flags & EXT4_OTHER_FLMASK;
+}
+
 /*
  * Inode dynamic state flags
  */
fs/ext4/ialloc.c +5 -9
@@ -865,16 +865,12 @@ got:
 	ei->i_disksize = 0;
 
 	/*
-	 * Don't inherit extent flag from directory. We set extent flag on
-	 * newly created directory and file only if -o extent mount option is
-	 * specified
+	 * Don't inherit extent flag from directory, amongst others. We set
+	 * extent flag on newly created directory and file only if -o extent
+	 * mount option is specified
 	 */
-	ei->i_flags = EXT4_I(dir)->i_flags & EXT4_FL_INHERITED;
-	if (S_ISLNK(mode))
-		ei->i_flags &= ~(EXT4_IMMUTABLE_FL|EXT4_APPEND_FL);
-	/* dirsync only applies to directories */
-	if (!S_ISDIR(mode))
-		ei->i_flags &= ~EXT4_DIRSYNC_FL;
+	ei->i_flags =
+		ext4_mask_flags(mode, EXT4_I(dir)->i_flags & EXT4_FL_INHERITED);
 	ei->i_file_acl = 0;
 	ei->i_dtime = 0;
 	ei->i_block_alloc_info = NULL;
fs/ext4/ioctl.c +1 -2
@@ -49,8 +49,7 @@ long ext4_ioctl(struct file *filp, unsig
 		if (err)
 			return err;
 
-		if (!S_ISDIR(inode->i_mode))
-			flags &= ~EXT4_DIRSYNC_FL;
+		flags = ext4_mask_flags(inode->i_mode, flags);
 
 		err = -EPERM;
 		mutex_lock(&inode->i_mutex);
author
#44 lore raw

PATCH 44/60 ext4: return -EIO not -ESTALE on directory traversal through deleted inode

In reply to Greg KH

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

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

(cherry picked from commit e6f009b0b45220c004672d41a58865e94946104d)

ext4_iget() returns -ESTALE if invoked on a deleted inode, in order to report errors to NFS properly. However, in ext4_lookup(), this -ESTALE can be propagated to userspace if the filesystem is corrupted such that a directory entry references a deleted inode. This leads to a misleading error message - "Stale NFS file handle" - and confusion on the part of the admin.

The bug can be easily reproduced by creating a new filesystem, making a link to an unused inode using debugfs, then mounting and attempting to ls -l said link.

This patch thus changes ext4_lookup to return -EIO if it receives -ESTALE from ext4_iget(), as ext4 does for other filesystem metadata corruption; and also invokes the appropriate ext*_error functions when this case is detected.

---
 fs/ext4/namei.c |   12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)
fs/ext4/namei.c +10 -2
@@ -1055,8 +1055,16 @@ static struct dentry *ext4_lookup(struct
 			return ERR_PTR(-EIO);
 		}
 		inode = ext4_iget(dir->i_sb, ino);
-		if (IS_ERR(inode))
-			return ERR_CAST(inode);
+		if (unlikely(IS_ERR(inode))) {
+			if (PTR_ERR(inode) == -ESTALE) {
+				ext4_error(dir->i_sb, __func__,
+						"deleted inode referenced: %u",
+						ino);
+				return ERR_PTR(-EIO);
+			} else {
+				return ERR_CAST(inode);
+			}
+		}
 	}
 	return d_splice_alias(inode, dentry);
 }
author
#45 lore raw

PATCH 45/60 ext4: Add fine print for the 32000 subdirectory limit

In reply to Greg KH

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

------------------
From: "Theodore Ts'o" <[email protected]>

(cherry picked from commit 722bde6875bfb49a0c84e5601eb82dd7ac02d27c)

Some poeple are reading the ext4 feature list too literally and create dubious test cases involving very long filenames and 1k blocksize and then complain when they run into an htree-imposed limit. So add fine print to the "fix 32000 subdirectory limit" ext4 feature.

---
 Documentation/filesystems/ext4.txt |    5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
Documentation/filesystems/ext4.txt +4 -1
@@ -73,7 +73,7 @@ Mailing list: [email protected]
 * extent format more robust in face of on-disk corruption due to magics,
 * internal redunancy in tree
 * improved file allocation (multi-block alloc)
-* fix 32000 subdirectory limit
+* lift 32000 subdirectory limit imposed by i_links_count[1]
 * nsec timestamps for mtime, atime, ctime, create time
 * inode version field on disk (NFSv4, Lustre)
 * reduced e2fsck time via uninit_bg feature
@@ -88,6 +88,9 @@ Mailing list: [email protected]
 * efficent new ordered mode in JBD2 and ext4(avoid using buffer head to force
   the ordering)
 
+[1] Filesystems with a block size of 1k may see a limit imposed by the
+directory hash tree having a maximum depth of two.
+
 2.2 Candidate features for future inclusion
 
 * Online defrag (patches available but not well tested)
author
#46 lore raw

PATCH 46/60 ext4: add EXT4_IOC_ALLOC_DA_BLKS ioctl

In reply to Greg KH

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

------------------
From: "Theodore Ts'o" <[email protected]>

(cherry picked from commit ccd2506bd43113659aa904d5bea5d1300605e2a6)

Add an ioctl which forces all of the delay allocated blocks to be allocated. This also provides a function ext4_alloc_da_blocks() which will be used by the following commits to force files to be fully allocated to preserve application-expected ext3 behaviour.

---
 fs/ext4/ext4.h  |    3 +++
 fs/ext4/inode.c |   42 ++++++++++++++++++++++++++++++++++++++++++
 fs/ext4/ioctl.c |   14 ++++++++++++++
 3 files changed, 59 insertions(+)
fs/ext4/ext4.h +3 -0
@@ -326,7 +326,9 @@ struct ext4_new_group_data {
 #define EXT4_IOC_GROUP_EXTEND		_IOW('f', 7, unsigned long)
 #define EXT4_IOC_GROUP_ADD		_IOW('f', 8, struct ext4_new_group_input)
 #define EXT4_IOC_MIGRATE		_IO('f', 9)
+ /* note ioctl 10 reserved for an early version of the FIEMAP ioctl */
  /* note ioctl 11 reserved for filesystem-independent FIEMAP ioctl */
+#define EXT4_IOC_ALLOC_DA_BLKS		_IO('f', 12)
 
 /*
  * ioctl commands in 32 bit emulation
@@ -1102,6 +1104,7 @@ extern int ext4_can_truncate(struct inod
 extern void ext4_truncate (struct inode *);
 extern void ext4_set_inode_flags(struct inode *);
 extern void ext4_get_inode_flags(struct ext4_inode_info *);
+extern int ext4_alloc_da_blocks(struct inode *inode);
 extern void ext4_set_aops(struct inode *inode);
 extern int ext4_writepage_trans_blocks(struct inode *);
 extern int ext4_meta_trans_blocks(struct inode *, int nrblocks, int idxblocks);
fs/ext4/inode.c +42 -0

48 lines not on this page · raw message

fs/ext4/ioctl.c +14 -0
@@ -287,6 +287,20 @@ setversion_out:
 		return err;
 	}
 
+	case EXT4_IOC_ALLOC_DA_BLKS:
+	{
+		int err;
+		if (!is_owner_or_cap(inode))
+			return -EACCES;
+
+		err = mnt_want_write(filp->f_path.mnt);
+		if (err)
+			return err;
+		err = ext4_alloc_da_blocks(inode);
+		mnt_drop_write(filp->f_path.mnt);
+		return err;
+	}
+
 	default:
 		return -ENOTTY;
 	}
author
#47 lore raw

PATCH 47/60 ext4: Automatically allocate delay allocated blocks on close

In reply to Greg KH

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

------------------
From: "Theodore Ts'o" <[email protected]>

(cherry picked from commit 7d8f9f7d150dded7b68e61ca6403a1f166fb4edf)

When closing a file that had been previously truncated, force any delay allocated blocks that to be allocated so that if the filesystem is mounted with data=ordered, the data blocks will be pushed out to disk along with the journal commit. Many application programs expect this, so we do this to avoid zero length files if the system crashes unexpectedly.

---
 fs/ext4/ext4.h  |    1 +
 fs/ext4/file.c  |    4 ++++
 fs/ext4/inode.c |    3 +++
 3 files changed, 8 insertions(+)
fs/ext4/ext4.h +1 -0
@@ -279,6 +279,7 @@ static inline __u32 ext4_mask_flags(umod
 #define EXT4_STATE_NEW			0x00000002 /* inode is newly created */
 #define EXT4_STATE_XATTR		0x00000004 /* has in-inode xattrs */
 #define EXT4_STATE_NO_EXPAND		0x00000008 /* No space for expansion */
+#define EXT4_STATE_DA_ALLOC_CLOSE	0x00000010 /* Alloc DA blks on close */
 
 /* Used to pass group descriptor data when online resize is done */
 struct ext4_new_group_input {
fs/ext4/file.c +4 -0
@@ -33,6 +33,10 @@
  */
 static int ext4_release_file (struct inode * inode, struct file * filp)
 {
+	if (EXT4_I(inode)->i_state & EXT4_STATE_DA_ALLOC_CLOSE) {
+		ext4_alloc_da_blocks(inode);
+		EXT4_I(inode)->i_state &= ~EXT4_STATE_DA_ALLOC_CLOSE;
+	}
 	/* if we are the last writer on the inode, drop the block reservation */
 	if ((filp->f_mode & FMODE_WRITE) &&
 			(atomic_read(&inode->i_writecount) == 1))
fs/ext4/inode.c +3 -0
@@ -3636,6 +3636,9 @@ void ext4_truncate(struct inode *inode)
 	if (!ext4_can_truncate(inode))
 		return;
 
+	if (inode->i_size == 0)
+		ei->i_state |= EXT4_STATE_DA_ALLOC_CLOSE;
+
 	if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL) {
 		ext4_ext_truncate(inode);
 		return;
author
#48 lore raw

PATCH 48/60 ext4: Automatically allocate delay allocated blocks on rename

In reply to Greg KH

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

------------------
From: "Theodore Ts'o" <[email protected]>

(cherry picked from commit 8750c6d5fcbd3342b3d908d157f81d345c5325a7)

When renaming a file such that a link to another inode is overwritten, force any delay allocated blocks that to be allocated so that if the filesystem is mounted with data=ordered, the data blocks will be pushed out to disk along with the journal commit. Many application programs expect this, so we do this to avoid zero length files if the system crashes unexpectedly.

---
 fs/ext4/namei.c |    5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
fs/ext4/namei.c +4 -1
@@ -2314,7 +2314,7 @@ static int ext4_rename (struct inode * o
 	struct inode * old_inode, * new_inode;
 	struct buffer_head * old_bh, * new_bh, * dir_bh;
 	struct ext4_dir_entry_2 * old_de, * new_de;
-	int retval;
+	int retval, force_da_alloc = 0;
 
 	old_bh = new_bh = dir_bh = NULL;
 
@@ -2452,6 +2452,7 @@ static int ext4_rename (struct inode * o
 		ext4_mark_inode_dirty(handle, new_inode);
 		if (!new_inode->i_nlink)
 			ext4_orphan_add(handle, new_inode);
+		force_da_alloc = 1;
 	}
 	retval = 0;
 
@@ -2460,6 +2461,8 @@ end_rename:
 	brelse (old_bh);
 	brelse (new_bh);
 	ext4_journal_stop(handle);
+	if (retval == 0 && force_da_alloc)
+		ext4_alloc_da_blocks(old_inode);
 	return retval;
 }
 
author
#49 lore raw

PATCH 49/60 ext4: Fix discard of inode prealloc space with delayed allocation.

In reply to Greg KH

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

------------------
From: Aneesh Kumar K.V <[email protected]>

(cherry picked from commit d6014301b5599fba395c42a1e96a7fe86f7d0b2d)

With delayed allocation we should not/cannot discard inode prealloc space during file close. We would still have dirty pages for which we haven't allocated blocks yet. With this fix after each get_blocks request we check whether we have zero reserved blocks and if yes and we don't have any writers on the file we discard inode prealloc space.

---
 fs/ext4/file.c  |    3 ++-
 fs/ext4/inode.c |    8 ++++++++
 2 files changed, 10 insertions(+), 1 deletion(-)
fs/ext4/file.c +2 -1
@@ -39,7 +39,8 @@ static int ext4_release_file (struct ino
 	}
 	/* if we are the last writer on the inode, drop the block reservation */
 	if ((filp->f_mode & FMODE_WRITE) &&
-			(atomic_read(&inode->i_writecount) == 1))
+			(atomic_read(&inode->i_writecount) == 1) &&
+		        !EXT4_I(inode)->i_reserved_data_blocks)
 	{
 		down_write(&EXT4_I(inode)->i_data_sem);
 		ext4_discard_reservation(inode);
fs/ext4/inode.c +8 -0
@@ -1046,6 +1046,14 @@ static void ext4_da_update_reserve_space
 	EXT4_I(inode)->i_reserved_meta_blocks = mdb;
 	EXT4_I(inode)->i_allocated_meta_blocks = 0;
 	spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
+
+	/*
+	 * If we have done all the pending block allocations and if
+	 * there aren't any writers on the inode, we can discard the
+	 * inode's preallocations.
+	 */
+	if (!total && (atomic_read(&inode->i_writecount) == 0))
+		ext4_discard_reservation(inode);
 }
 
 /*
author
#50 lore raw

PATCH 50/60 ext4: Check for an valid i_mode when reading the inode from disk

In reply to Greg KH

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

------------------
From: "Theodore Ts'o" <[email protected]>

(cherry picked from commit 563bdd61fe4dbd6b58cf7eb06f8d8f14479ae1dc)

---
 fs/ext4/inode.c |   10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)
fs/ext4/inode.c +9 -1
@@ -4129,7 +4129,8 @@ struct inode *ext4_iget(struct super_blo
 			inode->i_op = &ext4_symlink_inode_operations;
 			ext4_set_aops(inode);
 		}
-	} else {
+	} else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) ||
+	      S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) {
 		inode->i_op = &ext4_special_inode_operations;
 		if (raw_inode->i_block[0])
 			init_special_inode(inode, inode->i_mode,
@@ -4137,6 +4138,13 @@ struct inode *ext4_iget(struct super_blo
 		else
 			init_special_inode(inode, inode->i_mode,
 			   new_decode_dev(le32_to_cpu(raw_inode->i_block[1])));
+	} else {
+		brelse(bh);
+		ret = -EIO;
+		ext4_error(inode->i_sb, __func__,
+			   "bogus i_mode (%o) for inode=%lu",
+			   inode->i_mode, inode->i_ino);
+		goto bad_inode;
 	}
 	brelse (iloc.bh);
 	ext4_set_inode_flags(inode);
author
#51 lore raw

PATCH 51/60 jbd2: Update locking coments

In reply to Greg KH

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

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

(cherry picked from commit 86db97c87f744364d5889ca8a4134ca2048b8f83)

Update information about locking in JBD2 revoke code. Inconsistency in comments found by Lin Tan <[email protected]>

---
 fs/jbd2/revoke.c |   24 +++++++++++++++++++-----
 1 file changed, 19 insertions(+), 5 deletions(-)
fs/jbd2/revoke.c +19 -4
@@ -55,6 +55,25 @@
  *			need do nothing.
  * RevokeValid set, Revoked set:
  *			buffer has been revoked.
+ *
+ * Locking rules:
+ * We keep two hash tables of revoke records. One hashtable belongs to the
+ * running transaction (is pointed to by journal->j_revoke), the other one
+ * belongs to the committing transaction. Accesses to the second hash table
+ * happen only from the kjournald and no other thread touches this table.  Also
+ * journal_switch_revoke_table() which switches which hashtable belongs to the
+ * running and which to the committing transaction is called only from
+ * kjournald. Therefore we need no locks when accessing the hashtable belonging
+ * to the committing transaction.
+ *
+ * All users operating on the hash table belonging to the running transaction
+ * have a handle to the transaction. Therefore they are safe from kjournald
+ * switching hash tables under them. For operations on the lists of entries in
+ * the hash table j_revoke_lock is used.
+ *
+ * Finally, also replay code uses the hash tables but at this moment noone else
+ * can touch them (filesystem isn't mounted yet) and hence no locking is
+ * needed.
  */
 
 #ifndef __KERNEL__
@@ -401,8 +420,6 @@ int jbd2_journal_revoke(handle_t *handle
  * the second time we would still have a pending revoke to cancel.  So,
  * do not trust the Revoked bit on buffers unless RevokeValid is also
  * set.
- *
- * The caller must have the journal locked.
  */
 int jbd2_journal_cancel_revoke(handle_t *handle, struct journal_head *jh)
 {
@@ -480,10 +497,7 @@ void jbd2_journal_switch_revoke_table(jo
 /*
  * Write revoke records to the journal for all entries in the current
  * revoke hash, deleting the entries as we go.
- *
- * Called with the journal lock held.
  */
author
#52 lore raw

PATCH 52/60 ext4: fix typo which causes a memory leak on error path

In reply to Greg KH

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

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

upstream commit: a7b19448ddbdc34b2b8fedc048ba154ca798667b

This was found by smatch (http://repo.or.cz/w/smatch.git/)

---
 fs/ext4/mballoc.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
fs/ext4/mballoc.c +1 -1
@@ -2698,7 +2698,7 @@ int ext4_mb_init(struct super_block *sb,
 	sbi->s_mb_maxs = kmalloc(i, GFP_KERNEL);
 	if (sbi->s_mb_maxs == NULL) {
 		clear_opt(sbi->s_mount_opt, MBALLOC);
-		kfree(sbi->s_mb_maxs);
+		kfree(sbi->s_mb_offsets);
 		return -ENOMEM;
 	}
 
author
#53 lore raw

PATCH 53/60 ext4: fix locking typo in mballoc which could cause soft lockup hangs

In reply to Greg KH

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

------------------
From: "Theodore Ts'o" <[email protected]>

upstream commit: e7c9e3e99adf6c49c5d593a51375916acc039d1e

Smatch (http://repo.or.cz/w/smatch.git/) complains about the locking in ext4_mb_add_n_trim() from fs/ext4/mballoc.c

  4438          list_for_each_entry_rcu(tmp_pa, &lg->lg_prealloc_list[order],
  4439                                                  pa_inode_list) {
  4440                  spin_lock(&tmp_pa->pa_lock);
  4441                  if (tmp_pa->pa_deleted) {
  4442                          spin_unlock(&pa->pa_lock);
  4443                          continue;
  4444                  }

Brown paper bag time...

---
 fs/ext4/mballoc.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
fs/ext4/mballoc.c +1 -1
@@ -4532,7 +4532,7 @@ static void ext4_mb_add_n_trim(struct ex
 						pa_inode_list) {
 		spin_lock(&tmp_pa->pa_lock);
 		if (tmp_pa->pa_deleted) {
-			spin_unlock(&pa->pa_lock);
+			spin_unlock(&tmp_pa->pa_lock);
 			continue;
 		}
 		if (!added && pa->pa_free < tmp_pa->pa_free) {
author
#54 lore raw

PATCH 54/60 ext4: really print the find_group_flex fallback warning only once

In reply to Greg KH

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

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

(cherry picked from commit 6b82f3cb2d480b7714eb0ff61aee99c22160389e)

Missing braces caused the warning to print more than once.

---
 fs/ext4/ialloc.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
fs/ext4/ialloc.c +2 -1
@@ -707,11 +707,12 @@ struct inode *ext4_new_inode(handle_t *h
 		ret2 = find_group_flex(sb, dir, &group);
 		if (ret2 == -1) {
 			ret2 = find_group_other(sb, dir, &group);
-			if (ret2 == 0 && once)
+			if (ret2 == 0 && once) {
 				once = 0;
 				printk(KERN_NOTICE "ext4: find_group_flex "
 				       "failed, fallback succeeded dir %lu\n",
 				       dir->i_ino);
+			}
 		}
 		goto got_group;
 	}
author
#55 lore raw

PATCH 55/60 ext4: Fix softlockup caused by illegal i_file_acl value in on-disk inode

In reply to Greg KH

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

------------------
From: "Theodore Ts'o" <[email protected]>

(cherry picked from commit 485c26ec70f823f2a9cf45982b724893e53a859e)

If the block containing external extended attributes (which is stored in i_file_acl and i_file_acl_high) is larger than the on-disk filesystem, the process which tried to access the extended attributes will endlessly issue kernel printks complaining that "__find_get_block_slow() failed", locking up that CPU until the system is forcibly rebooted.

So when we read in the inode, make sure the i_file_acl value is legal, and if not, flag the filesystem as being corrupted.

---
 fs/ext4/inode.c |   12 ++++++++++++
 1 file changed, 12 insertions(+)
fs/ext4/inode.c +12 -0
@@ -4115,6 +4115,18 @@ struct inode *ext4_iget(struct super_blo
 			(__u64)(le32_to_cpu(raw_inode->i_version_hi)) << 32;
 	}
 
+	if (ei->i_file_acl &&
+	    ((ei->i_file_acl <
+	      (le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block) +
+	       EXT4_SB(sb)->s_gdb_count)) ||
+	     (ei->i_file_acl >= ext4_blocks_count(EXT4_SB(sb)->s_es)))) {
+		ext4_error(sb, __func__,
+			   "bad extended attribute block %llu in inode #%lu",
+			   ei->i_file_acl, inode->i_ino);
+		ret = -EIO;
+		goto bad_inode;
+	}
+
 	if (S_ISREG(inode->i_mode)) {
 		inode->i_op = &ext4_file_inode_operations;
 		inode->i_fop = &ext4_file_operations;
author
#56 lore raw

PATCH 56/60 ext4: Ignore i_file_acl_high unless EXT4_FEATURE_INCOMPAT_64BIT is present

In reply to Greg KH

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

------------------
From: "Theodore Ts'o" <[email protected]>

(cherry picked from commit a9e817425dc0baede8ebe5fbc9984a640257432b)

Don't try to look at i_file_acl_high unless the INCOMPAT_64BIT feature bit is set. The field is normally zero, but older versions of e2fsck didn't automatically check to make sure of this, so in the spirit of "be liberal in what you accept", don't look at i_file_acl_high unless we are using a 64-bit filesystem.

---
 fs/ext4/inode.c |    4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)
fs/ext4/inode.c +1 -3
@@ -4064,11 +4064,9 @@ struct inode *ext4_iget(struct super_blo
 	ei->i_flags = le32_to_cpu(raw_inode->i_flags);
 	inode->i_blocks = ext4_inode_blocks(raw_inode, ei);
 	ei->i_file_acl = le32_to_cpu(raw_inode->i_file_acl_lo);
-	if (EXT4_SB(inode->i_sb)->s_es->s_creator_os !=
-	    cpu_to_le32(EXT4_OS_HURD)) {
+	if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_64BIT))
 		ei->i_file_acl |=
 			((__u64)le16_to_cpu(raw_inode->i_file_acl_high)) << 32;
-	}
 	inode->i_size = ext4_isize(raw_inode);
 	ei->i_disksize = inode->i_size;
 	inode->i_generation = le32_to_cpu(raw_inode->i_generation);
author
#57 lore raw

PATCH 57/60 ext4: Fix sub-block zeroing for writes into preallocated extents

In reply to Greg KH

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

------------------
From: Aneesh Kumar K.V <[email protected]>

(cherry picked from commit 9c1ee184a30394e54165fa4c15923cabd952c106)

We need to mark the buffer_head mapping preallocated space as new during write_begin. Otherwise we don't zero out the page cache content properly for a partial write. This will cause file corruption with preallocation.

Now that we mark the buffer_head new we also need to have a valid buffer_head blocknr so that unmap_underlying_metadata() unmaps the correct block.

---
 fs/ext4/extents.c |    2 ++
 fs/ext4/inode.c   |    7 +++++++
 2 files changed, 9 insertions(+)
fs/ext4/extents.c +2 -0
@@ -2670,6 +2670,8 @@ int ext4_ext_get_blocks(handle_t *handle
 				if (allocated > max_blocks)
 					allocated = max_blocks;
 				set_buffer_unwritten(bh_result);
+				bh_result->b_bdev = inode->i_sb->s_bdev;
+				bh_result->b_blocknr = newblock;
 				goto out2;
 			}
 
fs/ext4/inode.c +7 -0
@@ -2131,6 +2131,13 @@ static int ext4_da_get_block_prep(struct
 		set_buffer_delay(bh_result);
 	} else if (ret > 0) {
 		bh_result->b_size = (ret << inode->i_blkbits);
+		/*
+		 * With sub-block writes into unwritten extents
+		 * we also need to mark the buffer as new so that
+		 * the unwritten parts of the buffer gets correctly zeroed.
+		 */
+		if (buffer_unwritten(bh_result))
+			set_buffer_new(bh_result);
 		ret = 0;
 	}
 
author
#58 lore raw

PATCH 58/60 ext4: Use a fake block number for delayed new buffer_head

In reply to Greg KH

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

------------------
From: Aneesh Kumar K.V <[email protected]>

(cherry picked from commit 33b9817e2ae097c7b8d256e3510ac6c54fc6d9d0)

Use a very large unsigned number (~0xffff) as as the fake block number for the delayed new buffer. The VFS should never try to write out this number, but if it does, this will make it obvious.

---
 fs/ext4/inode.c |    6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)
fs/ext4/inode.c +5 -1
@@ -2105,6 +2105,10 @@ static int ext4_da_get_block_prep(struct
 				  struct buffer_head *bh_result, int create)
 {
 	int ret = 0;
+	sector_t invalid_block = ~((sector_t) 0xffff);
+
+	if (invalid_block < ext4_blocks_count(EXT4_SB(inode->i_sb)->s_es))
+		invalid_block = ~0;
 
 	BUG_ON(create == 0);
 	BUG_ON(bh_result->b_size != inode->i_sb->s_blocksize);
@@ -2126,7 +2130,7 @@ static int ext4_da_get_block_prep(struct
 			/* not enough space to reserve */
 			return ret;
 
-		map_bh(bh_result, inode->i_sb, 0);
+		map_bh(bh_result, inode->i_sb, invalid_block);
 		set_buffer_new(bh_result);
 		set_buffer_delay(bh_result);
 	} else if (ret > 0) {
author
#59 lore raw

PATCH 59/60 ext4: Clear the unwritten buffer_head flag after the extent is initialized

In reply to Greg KH

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

------------------
From: Aneesh Kumar K.V <[email protected]>

(cherry picked from commit 2a8964d63d50dd2d65d71d342bc7fb6ef4117614)

The BH_Unwritten flag indicates that the buffer is allocated on disk but has not been written; that is, the disk was part of a persistent preallocation area. That flag should only be set when a get_blocks() function is looking up a inode's logical to physical block mapping.

When ext4_get_blocks_wrap() is called with create=1, the uninitialized extent is converted into an initialized one, so the BH_Unwritten flag is no longer appropriate. Hence, we need to make sure the BH_Unwritten is not left set, since the combination of BH_Mapped and BH_Unwritten is not allowed; among other things, it will result ext4's get_block() to be called over and over again during the write_begin phase of write(2).

---
 fs/ext4/inode.c |   13 +++++++++++++
 1 file changed, 13 insertions(+)
fs/ext4/inode.c +13 -0
@@ -1085,6 +1085,7 @@ int ext4_get_blocks_wrap(handle_t *handl
 	int retval;
 
 	clear_buffer_mapped(bh);
+	clear_buffer_unwritten(bh);
 
 	/*
 	 * Try to see if we can get  the block without requesting
@@ -1115,6 +1116,18 @@ int ext4_get_blocks_wrap(handle_t *handl
 		return retval;
 
 	/*
+	 * When we call get_blocks without the create flag, the
+	 * BH_Unwritten flag could have gotten set if the blocks
+	 * requested were part of a uninitialized extent.  We need to
+	 * clear this flag now that we are committed to convert all or
+	 * part of the uninitialized extent to be an initialized
+	 * extent.  This is because we need to avoid the combination
+	 * of BH_Unwritten and BH_Mapped flags being simultaneously
+	 * set on the buffer_head.
+	 */
+	clear_buffer_unwritten(bh);
+
+	/*
 	 * New blocks allocate and/or writing to uninitialized extent
 	 * will possibly result in updating i_data, so we take
 	 * the write lock of i_data_sem, and call get_blocks()
author
#60 lore raw

PATCH 60/60 ext4: Fix race in ext4_inode_info.i_cached_extent

In reply to Greg KH

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

------------------
From: "Theodore Ts'o" <[email protected]>

(cherry picked from commit 2ec0ae3acec47f628179ee95fe2c4da01b5e9fc4)

If two CPU's simultaneously call ext4_ext_get_blocks() at the same time, there is nothing protecting the i_cached_extent structure from being used and updated at the same time. This could potentially cause the wrong location on disk to be read or written to, including potentially causing the corruption of the block group descriptors and/or inode table.

This bug has been in the ext4 code since almost the very beginning of ext4's development. Fortunately once the data is stored in the page cache cache, ext4_get_blocks() doesn't need to be called, so trying to replicate this problem to the point where we could identify its root cause was *extremely* difficult. Many thanks to Kevin Shanahan for working over several months to be able to reproduce this easily so we could finally nail down the cause of the corruption.

---
 fs/ext4/extents.c |   17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)
fs/ext4/extents.c +9 -2
@@ -1633,11 +1633,13 @@ ext4_ext_put_in_cache(struct inode *inod
 {
 	struct ext4_ext_cache *cex;
 	BUG_ON(len == 0);
+	spin_lock(&EXT4_I(inode)->i_block_reservation_lock);
 	cex = &EXT4_I(inode)->i_cached_extent;
 	cex->ec_type = type;
 	cex->ec_block = block;
 	cex->ec_len = len;
 	cex->ec_start = start;
+	spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
 }
 
 /*
@@ -1694,12 +1696,17 @@ ext4_ext_in_cache(struct inode *inode, e
 			struct ext4_extent *ex)
 {
 	struct ext4_ext_cache *cex;
+	int ret = EXT4_EXT_CACHE_NO;
 
+	/*
+	 * We borrow i_block_reservation_lock to protect i_cached_extent
+	 */
+	spin_lock(&EXT4_I(inode)->i_block_reservation_lock);
 	cex = &EXT4_I(inode)->i_cached_extent;
 
 	/* has cache valid data? */
 	if (cex->ec_type == EXT4_EXT_CACHE_NO)
-		return EXT4_EXT_CACHE_NO;
+		goto errout;
 
 	BUG_ON(cex->ec_type != EXT4_EXT_CACHE_GAP &&
 			cex->ec_type != EXT4_EXT_CACHE_EXTENT);
@@ -1710,11 +1717,11 @@ ext4_ext_in_cache(struct inode *inode, e
 		ext_debug("%u cached by %u:%u:%llu\n",
 				block,
 				cex->ec_block, cex->ec_len, cex->ec_start);
-		return cex->ec_type;
+		ret = cex->ec_type;
 	}