Skip to contentSkip to conversation

2.6.22-stable review

PATCH In review Greg KH 5 participants 59 messages Sep 24, 2007 – Sep 25, 2007

Subsystems (29)
lore
Share & tools
lore

Greg KH

author
#0 lore raw

cover 2.6.22-stable review

This is the start of the stable review cycle for the 2.6.22.8 release. There are 50 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 Wed September 26, 2007, 16:00:00 UTC. Anything received after that time might be too late.

thanks,

greg k-h

author
#1 lore raw

PATCH 1/50 V4L: ivtv: fix VIDIOC_S_FBUF: new OSD values were never set

From: Hans Verkuil <[email protected]>

cherry picked from commit c3624f99a8c06cfe75e0b06f23a7f7cea9d2d5ff

ivtv: fix VIDIOC_S_FBUF support: new OSD values were never actually set.

The values set with VIDIOC_S_FBUF were not actually used until the next VIDIOC_S_FMT. Fixed.

---
 drivers/media/video/ivtv/ivtv-ioctl.c |    1 +
 1 file changed, 1 insertion(+)
drivers/media/video/ivtv/ivtv-ioctl.c +1 -0
@@ -1183,6 +1183,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, s
 		itv->osd_global_alpha_state = (fb->flags & V4L2_FBUF_FLAG_GLOBAL_ALPHA) != 0;
 		itv->osd_local_alpha_state = (fb->flags & V4L2_FBUF_FLAG_LOCAL_ALPHA) != 0;
 		itv->osd_color_key_state = (fb->flags & V4L2_FBUF_FLAG_CHROMAKEY) != 0;
+		ivtv_set_osd_alpha(itv);
 		break;
 	}
 
author
#2 lore raw

PATCH 2/50 DVB: get_dvb_firmware: update script for new location of sp8870 firmware

In reply to Greg KH

From: Michael Krufky <[email protected]>

cherry picked from commit 302170a4b47e869372974abd885dd11d5536b64a

get_dvb_firmware: update script for new location of sp8870 firmware

This url is no longer valid:
http://www.technotrend.de/new/217g/tt_Premium_217g.zip

Replace with:
http://www.softwarepatch.pl/9999ccd06a4813cb827dbb0005071c71/tt_Premium_217g.zip

Thanks-to: Tobias Stoeber <[email protected]>

---
 Documentation/dvb/get_dvb_firmware |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
Documentation/dvb/get_dvb_firmware +1 -1
@@ -56,7 +56,7 @@ syntax();
 
 sub sp8870 {
     my $sourcefile = "tt_Premium_217g.zip";
-    my $url = "http://www.technotrend.de/new/217g/$sourcefile";
+    my $url = "http://www.softwarepatch.pl/9999ccd06a4813cb827dbb0005071c71/$sourcefile";
     my $hash = "53970ec17a538945a6d8cb608a7b3899";
     my $outfile = "dvb-fe-sp8870.fw";
     my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1);
author
#3 lore raw

PATCH 3/50 DVB: get_dvb_firmware: update script for new location of tda10046 firmware

In reply to Greg KH

From: Andreas Arens <[email protected]>

cherry picked from commit c545d6adbcacd296f7457bd992556feb055379de

Update get_dvb_firmware script for the new location of the tda10046 firmware.

The old location doesn't work anymore.

---
 Documentation/dvb/get_dvb_firmware |   24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)
Documentation/dvb/get_dvb_firmware +12 -12
@@ -110,21 +110,21 @@ sub tda10045 {
 }
 
 sub tda10046 {
-    my $sourcefile = "tt_budget_217g.zip";
-    my $url = "http://www.technotrend.de/new/217g/$sourcefile";
-    my $hash = "6a7e1e2f2644b162ff0502367553c72d";
-    my $outfile = "dvb-fe-tda10046.fw";
-    my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1);
+	my $sourcefile = "TT_PCI_2.19h_28_11_2006.zip";
+	my $url = "http://technotrend-online.com/download/software/219/$sourcefile";
+	my $hash = "6a7e1e2f2644b162ff0502367553c72d";
+	my $outfile = "dvb-fe-tda10046.fw";
+	my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1);
 
-    checkstandard();
+	checkstandard();
 
-    wgetfile($sourcefile, $url);
-    unzip($sourcefile, $tmpdir);
-    extract("$tmpdir/software/OEM/PCI/App/ttlcdacc.dll", 0x3f731, 24478, "$tmpdir/fwtmp");
-    verify("$tmpdir/fwtmp", $hash);
-    copy("$tmpdir/fwtmp", $outfile);
+	wgetfile($sourcefile, $url);
+	unzip($sourcefile, $tmpdir);
+	extract("$tmpdir/TT_PCI_2.19h_28_11_2006/software/OEM/PCI/App/ttlcdacc.dll", 0x65389, 24478, "$tmpdir/fwtmp");
+	verify("$tmpdir/fwtmp", $hash);
+	copy("$tmpdir/fwtmp", $outfile);
 
-    $outfile;
+	$outfile;
 }
 
 sub tda10046lifeview {
author
#4 lore raw

PATCH 4/50 DVB: b2c2-flexcop: fix Airstar HD5000 tuning regression

In reply to Greg KH

From: Trent Piepho <[email protected]>

cherry picked from commit 6175e487e314385e37f06448847e4c46c20edb44

b2c2-flexcop: fix Airstar HD5000 tuning regression

Git changeset 6bdcc6e6dbab8daffd05e5026486f34ba41a6c72 dropped the stand-alone lgh06xf module, whose functionality was absorbed into the dvb-pll module. However, there was a minor difference between the code in lgh06xf and dvb-pll, which caused a regression in b2c2-flexcop devices using the LG-H06xF NIM.

dvb-pll will probe for the presence of an i2c pll chip by performing a single byte read, the lgh06xf driver did not do this. Unfortunately, the code in flexcop-i2c.c does not currently support 1 byte or 0 byte reads as a probe. Such probes with the current code will always fail.

In order to work around this problem, and restore proper functionality of the Airstar HD5000 device, this hack was created to make the probe appear to succeed. The single byte read in dvb_pll_attach is the only place where such a probe would ever occur, so this change is safe, and will not affect any other devices.

Of course, if one knew how to actually perform the read operation, it would be better to go that route. In the meantime, however, we must apply this workaround, in order to prevent the regression that causes tuning to fail on the Airstar HD5000 ATSC device.

Thanks to Jarod Wilson, who had originally reported this regression, and to Geoffrey Hausheer, whose original workaround patch led us to find the actual cause of the problem.

---
 drivers/media/dvb/b2c2/flexcop-i2c.c |    7 +++++++
 1 file changed, 7 insertions(+)
drivers/media/dvb/b2c2/flexcop-i2c.c +7 -0
@@ -135,6 +135,13 @@ static int flexcop_master_xfer(struct i2
 	struct flexcop_device *fc = i2c_get_adapdata(i2c_adap);
 	int i, ret = 0;
 
+	/* Some drivers use 1 byte or 0 byte reads as probes, which this
+	 * driver doesn't support.  These probes will always fail, so this
+	 * hack makes them always succeed.  If one knew how, it would of
+	 * course be better to actually do the read.  */
+	if (num == 1 && msgs[0].flags == I2C_M_RD && msgs[0].len <= 1)
+		return 1;
+
 	if (mutex_lock_interruptible(&fc->i2c_mutex))
 		return -ERESTARTSYS;
 
author
#5 lore raw

PATCH 5/50 setpgid(child) fails if the child was forked by sub-thread

In reply to Greg KH

From: Oleg Nesterov <[email protected]>

commit b07e35f94a7b6a059f889b904529ee907dc0634d in mainline tree

Spotted by Marcin Kowalczyk <[email protected]>.

sys_setpgid(child) fails if the child was forked by sub-thread.

Fix the "is it our child" check. The previous commit ee0acf90d320c29916ba8c5c1b2e908d81f5057d was not complete.

(this patch asks for the new same_thread_group() helper, but mainline doesn't
have it yet).

---
 kernel/sys.c |    3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)
kernel/sys.c +1 -2
@@ -1428,7 +1428,6 @@ asmlinkage long sys_times(struct tms __u
  * Auch. Had to add the 'did_exec' flag to conform completely to POSIX.
  * LBT 04.03.94
  */
-
 asmlinkage long sys_setpgid(pid_t pid, pid_t pgid)
 {
 	struct task_struct *p;
@@ -1456,7 +1455,7 @@ asmlinkage long sys_setpgid(pid_t pid, p
 	if (!thread_group_leader(p))
 		goto out;
 
-	if (p->real_parent == group_leader) {
+	if (p->real_parent->tgid == group_leader->tgid) {
 		err = -EPERM;
 		if (task_session(p) != task_session(group_leader))
 			goto out;
author
#6 lore raw

PATCH 6/50 sigqueue_free: fix the race with collect_signal()

In reply to Greg KH

From: Oleg Nesterov <[email protected]>

commit 60187d2708caa870f0825d753df1612ea688eb9e in mainline.

Spotted by taoyue <[email protected]> and Jeremy Katz <[email protected]>.

collect_signal: sigqueue_free:

	list_del_init(&first->list);
						if (!list_empty(&q->list)) {
							// not taken
						}
						q->flags &= ~SIGQUEUE_PREALLOC;

	__sigqueue_free(first);			__sigqueue_free(q);

Now, __sigqueue_free() is called twice on the same "struct sigqueue" with the obviously bad implications.

In particular, this double free breaks the array_cache->avail logic, so the same sigqueue could be "allocated" twice, and the bug can manifest itself via the "impossible" BUG_ON(!SIGQUEUE_PREALLOC) in sigqueue_free/send_sigqueue.

Hopefully this can explain these mysterious bug-reports, see

	http://marc.info/?t=118766926500003
	http://marc.info/?t=118466273000005

Alexey Dobriyan reports this patch makes the difference for the testcase, but nobody has an access to the application which opened the problems originally.

Also, this patch removes tasklist lock/unlock, ->siglock is enough.

Cc taoyue <[email protected]>
Cc Jeremy Katz <[email protected]>
Cc Sukadev Bhattiprolu <[email protected]>
Cc Alexey Dobriyan <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Roland McGrath <[email protected]>
---
 kernel/signal.c |   19 +++++++++----------
 1 file changed, 9 insertions(+), 10 deletions(-)
kernel/signal.c +9 -10
@@ -1259,20 +1259,19 @@ struct sigqueue *sigqueue_alloc(void)
 void sigqueue_free(struct sigqueue *q)
 {
 	unsigned long flags;
+	spinlock_t *lock = &current->sighand->siglock;
+
 	BUG_ON(!(q->flags & SIGQUEUE_PREALLOC));
 	/*
 	 * If the signal is still pending remove it from the
-	 * pending queue.
+	 * pending queue. We must hold ->siglock while testing
+	 * q->list to serialize with collect_signal().
 	 */
-	if (unlikely(!list_empty(&q->list))) {
-		spinlock_t *lock = &current->sighand->siglock;
-		read_lock(&tasklist_lock);
-		spin_lock_irqsave(lock, flags);
-		if (!list_empty(&q->list))
-			list_del_init(&q->list);
-		spin_unlock_irqrestore(lock, flags);
-		read_unlock(&tasklist_lock);
-	}
+	spin_lock_irqsave(lock, flags);
+	if (!list_empty(&q->list))
+		list_del_init(&q->list);
+	spin_unlock_irqrestore(lock, flags);
+
 	q->flags &= ~SIGQUEUE_PREALLOC;
 	__sigqueue_free(q);
 }
author
#7 lore raw

PATCH 7/50 kconfig: oldconfig shall not set symbols if it does not need to

In reply to Greg KH

From: Roman Zippel <[email protected]>

commit f82f3f9422d4da1eeec6f6cf3e64c6c34c4fe19b in mainline.

Avoid setting the value if the symbol doesn't need to be changed or can't be changed. Later choices may change the dependencies and thus the possible input range.

make oldconfig from a 2.6.22 .config with CONFIG_HOTPLUG_CPU not set was in some configurations setting CONFIG_HOTPLUG_CPU=y without asking, even when there was no actual requirement for CONFIG_HOTPLUG_CPU. This was triggered by SUSPEND_SMP that does a select HOTPLUG_CPU.

---
 scripts/kconfig/conf.c |   21 ++++++++++++---------
 1 file changed, 12 insertions(+), 9 deletions(-)
scripts/kconfig/conf.c +12 -9
@@ -64,7 +64,7 @@ static void check_stdin(void)
 	}
 }
 
-static void conf_askvalue(struct symbol *sym, const char *def)
+static int conf_askvalue(struct symbol *sym, const char *def)
 {
 	enum symbol_type type = sym_get_type(sym);
 	tristate val;
@@ -79,7 +79,7 @@ static void conf_askvalue(struct symbol 
 		printf("%s\n", def);
 		line[0] = '\n';
 		line[1] = 0;
-		return;
+		return 0;
 	}
 
 	switch (input_mode) {
@@ -89,23 +89,23 @@ static void conf_askvalue(struct symbol 
 	case set_random:
 		if (sym_has_value(sym)) {
 			printf("%s\n", def);
-			return;
+			return 0;
 		}
 		break;
 	case ask_new:
 	case ask_silent:
 		if (sym_has_value(sym)) {
 			printf("%s\n", def);
-			return;
+			return 0;
 		}
 		check_stdin();
 	case ask_all:
 		fflush(stdout);
 		fgets(line, 128, stdin);
-		return;
+		return 1;
 	case set_default:
 		printf("%s\n", def);
-		return;
+		return 1;
 	default:
 		break;
 	}
@@ -115,7 +115,7 @@ static void conf_askvalue(struct symbol 
 	case S_HEX:
 	case S_STRING:
 		printf("%s\n", def);
-		return;
+		return 1;
 	default:
 		;
 	}
@@ -166,6 +166,7 @@ static void conf_askvalue(struct symbol 
 		break;
 	}
 	printf("%s", line);
+	return 1;
 }
 
 int conf_string(struct menu *menu)
@@ -179,7 +180,8 @@ int conf_string(struct menu *menu)
 		def = sym_get_string_value(sym);
 		if (sym_get_string_value(sym))
 			printf("[%s] ", def);
-		conf_askvalue(sym, def);
+		if (!conf_askvalue(sym, def))
+			return 0;
 		switch (line[0]) {
 		case '\n':
 			break;
@@ -236,7 +238,8 @@ static int conf_sym(struct menu *menu)
 		if (sym->help)
 			printf("/?");
 		printf("] ");
-		conf_askvalue(sym, sym_get_string_value(sym));
+		if (!conf_askvalue(sym, sym_get_string_value(sym)))
+			return 0;
 		strip(line);
 
 		switch (line[0]) {
author
#8 lore raw

PATCH 8/50 MTD: Makefile fix for mtdsuper

In reply to Greg KH

From: Satyam Sharma <[email protected]>

commit bec494775600b1cd7c144d31a09e1f46df9c6324 in mainline.

We want drivers/mtd/{mtdcore, mtdsuper, mtdpart}.c to be built and linked into the same mtd.ko module. Fix the Makefile to ensure this, and remove duplicate MODULE_ declarations in mtdpart.c, as mtdcore.c already has them.

---
 drivers/mtd/Makefile  |    2 +-
 drivers/mtd/mtdpart.c |    4 ----
 2 files changed, 1 insertion(+), 5 deletions(-)
drivers/mtd/Makefile +1 -1
@@ -3,9 +3,9 @@
 #
 
 # Core functionality.
+obj-$(CONFIG_MTD)		+= mtd.o
 mtd-y				:= mtdcore.o mtdsuper.o
 mtd-$(CONFIG_MTD_PARTITIONS)	+= mtdpart.o
-obj-$(CONFIG_MTD)		+= $(mtd-y)
 
 obj-$(CONFIG_MTD_CONCAT)	+= mtdconcat.o
 obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o
drivers/mtd/mtdpart.c +0 -4
@@ -560,7 +560,3 @@ int parse_mtd_partitions(struct mtd_info
 EXPORT_SYMBOL_GPL(parse_mtd_partitions);
 EXPORT_SYMBOL_GPL(register_mtd_parser);
 EXPORT_SYMBOL_GPL(deregister_mtd_parser);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Nicolas Pitre <[email protected]>");
-MODULE_DESCRIPTION("Generic support for partitioning of MTD devices");
author
#9 lore raw

PATCH 9/50 USB: fix linked list insertion bugfix for usb core

In reply to Greg KH

From: Nathael Pajani <[email protected]>

commit e5dd01154c1e9ca2400f4682602d1a4fa54c25dd in mainline.

This patch fixes the order of list_add_tail() arguments in usb_store_new_id() so the list can have more than one single element.

---
 drivers/usb/core/driver.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/usb/core/driver.c +1 -1
@@ -58,7 +58,7 @@ ssize_t usb_store_new_id(struct usb_dyni
 	dynid->id.match_flags = USB_DEVICE_ID_MATCH_DEVICE;
 
 	spin_lock(&dynids->lock);
-	list_add_tail(&dynids->list, &dynid->node);
+	list_add_tail(&dynid->node, &dynids->list);
 	spin_unlock(&dynids->lock);
 
 	if (get_driver(driver)) {
author
#10 lore raw

PATCH 10/50 ACPI: Validate XSDT, use RSDT if XSDT fails

In reply to Greg KH

From: Zhao Yakui <[email protected]>

commit 9f3119b70cf189530f1b46a006a052e171a1622f in mainline.

ACPI 1.0 used an RSDT with 32-bit physical addresses. ACPI 2.0 adds an XSDT with 32-bit physical addresses. An ACPI 2.0 aware OS is supposed to use the XSDT (when present) instead of the RSDT.

However, several systems have failed because the XSDT contains NULL entries -- while it is missing pointers to needed tables, such as SSDTs.

When we find an XSDT with NULL entries, discard it and use the ACPI 1.0 RSDT instead.

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

---
 drivers/acpi/tables/tbutils.c |   71 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 71 insertions(+)
drivers/acpi/tables/tbutils.c +71 -0
@@ -51,6 +51,65 @@ ACPI_MODULE_NAME("tbutils")
 static acpi_physical_address
 acpi_tb_get_root_table_entry(u8 * table_entry,
 			     acpi_native_uint table_entry_size);
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_tb_check_xsdt
+ *
+ * PARAMETERS:  address                    - Pointer to the XSDT
+ *
+ * RETURN:      status
+ *		AE_OK - XSDT is okay
+ *		AE_NO_MEMORY - can't map XSDT
+ *		AE_INVALID_TABLE_LENGTH - invalid table length
+ *		AE_NULL_ENTRY - XSDT has NULL entry
+ *
+ * DESCRIPTION: validate XSDT
+******************************************************************************/
+
+static acpi_status
+acpi_tb_check_xsdt(acpi_physical_address address)
+{
+	struct acpi_table_header *table;
+	u32 length;
+	u64 xsdt_entry_address;
+	u8 *table_entry;
+	u32 table_count;
+	int i;
+
+	table = acpi_os_map_memory(address, sizeof(struct acpi_table_header));
+	if (!table)
+		return AE_NO_MEMORY;
+
+	length = table->length;
+	acpi_os_unmap_memory(table, sizeof(struct acpi_table_header));
+	if (length < sizeof(struct acpi_table_header))
+		return AE_INVALID_TABLE_LENGTH;
+
+	table = acpi_os_map_memory(address, length);
+	if (!table)
+		return AE_NO_MEMORY;
+
+	/* Calculate the number of tables described in XSDT */
+	table_count =
+		(u32) ((table->length -
+		sizeof(struct acpi_table_header)) / sizeof(u64));
+	table_entry =
+		ACPI_CAST_PTR(u8, table) + sizeof(struct acpi_table_header);
+	for (i = 0; i < table_count; i++) {
+		ACPI_MOVE_64_TO_64(&xsdt_entry_address, table_entry);
+		if (!xsdt_entry_address) {
+			/* XSDT has NULL entry */
+			break;
+		}
+		table_entry += sizeof(u64);
+	}
+	acpi_os_unmap_memory(table, length);
+
+	if (i < table_count)
+		return AE_NULL_ENTRY;
+	else
+		return AE_OK;
+}
 
 /*******************************************************************************
  *
@@ -341,6 +400,7 @@ acpi_tb_parse_root_table(acpi_physical_a
 	u32 table_count;
 	struct acpi_table_header *table;
 	acpi_physical_address address;
+	acpi_physical_address rsdt_address;
 	u32 length;
 	u8 *table_entry;
 	acpi_status status;
@@ -369,6 +429,8 @@ acpi_tb_parse_root_table(acpi_physical_a
 		 */
 		address = (acpi_physical_address) rsdp->xsdt_physical_address;
 		table_entry_size = sizeof(u64);
+		rsdt_address = (acpi_physical_address)
+					rsdp->rsdt_physical_address;
 	} else {
 		/* Root table is an RSDT (32-bit physical addresses) */
 
@@ -382,6 +444,15 @@ acpi_tb_parse_root_table(acpi_physical_a
 	 */
 	acpi_os_unmap_memory(rsdp, sizeof(struct acpi_table_rsdp));
 
+	if (table_entry_size == sizeof(u64)) {
+		if (acpi_tb_check_xsdt(address) == AE_NULL_ENTRY) {
+			/* XSDT has NULL entry, RSDT is used */
+			address = rsdt_address;
+			table_entry_size = sizeof(u32);
+			ACPI_WARNING((AE_INFO, "BIOS XSDT has NULL entry,"
+					"using RSDT"));
+		}
+	}
 	/* Map the RSDT/XSDT table header to get the full table length */
 
 	table = acpi_os_map_memory(address, sizeof(struct acpi_table_header));
author
#11 lore raw

PATCH 11/50 POWERPC: Flush registers to proper task context

In reply to Greg KH

From: Kumar Gala <[email protected]>

commit 0ee6c15e7ba7b36a217cdadb292eeaf32a057a59 in mainline.

When we flush register state for FP, Altivec, or SPE in flush_*_to_thread we need to respect the task_struct that the caller has passed to us.

Most cases we are called with current, however sometimes (ptrace) we may be passed a different task_struct.

This showed up when using gdbserver debugging a simple program that used floating point. When gdb tried to show the FP regs they all showed up as 0, because the child's FP registers were never properly flushed to memory.

---
 arch/powerpc/kernel/process.c |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
arch/powerpc/kernel/process.c +3 -3
@@ -83,7 +83,7 @@ void flush_fp_to_thread(struct task_stru
 			 */
 			BUG_ON(tsk != current);
 #endif
-			giveup_fpu(current);
+			giveup_fpu(tsk);
 		}
 		preempt_enable();
 	}
@@ -143,7 +143,7 @@ void flush_altivec_to_thread(struct task
 #ifdef CONFIG_SMP
 			BUG_ON(tsk != current);
 #endif
-			giveup_altivec(current);
+			giveup_altivec(tsk);
 		}
 		preempt_enable();
 	}
@@ -182,7 +182,7 @@ void flush_spe_to_thread(struct task_str
 #ifdef CONFIG_SMP
 			BUG_ON(tsk != current);
 #endif
-			giveup_spe(current);
+			giveup_spe(tsk);
 		}
 		preempt_enable();
 	}
author
#12 lore raw

PATCH 12/50 3w-9xxx: Fix dma mask setting

In reply to Greg KH

From: Adam Radford <[email protected]>

[SCSI] 3w-9xxx: Fix dma mask setting

Extracted from commit 0e78d158b67fba3977f577f293c323359d80dd0e

The attached patch updates the 3ware 9000 driver:

- Fix dma mask setting to fallback to 32-bit if 64-bit fails.

---
 drivers/scsi/3w-9xxx.c |   18 +++++++++++-------
 1 file changed, 11 insertions(+), 7 deletions(-)
drivers/scsi/3w-9xxx.c +11 -7
@@ -4,7 +4,7 @@
    Written By: Adam Radford <[email protected]>
    Modifications By: Tom Couch <[email protected]>
 
-   Copyright (C) 2004-2006 Applied Micro Circuits Corporation.
+   Copyright (C) 2004-2007 Applied Micro Circuits Corporation.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -69,6 +69,7 @@
    2.26.02.008 - Free irq handler in __twa_shutdown().
                  Serialize reset code.
                  Add support for 9650SE controllers.
+   2.26.02.009 - Fix dma mask setting to fallback to 32-bit if 64-bit fails.
 */
 
 #include <linux/module.h>
@@ -92,7 +93,7 @@
 #include "3w-9xxx.h"
 
 /* Globals */
-#define TW_DRIVER_VERSION "2.26.02.008"
+#define TW_DRIVER_VERSION "2.26.02.009"
 static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT];
 static unsigned int twa_device_extension_count;
 static int twa_major = -1;
@@ -2063,11 +2064,14 @@ static int __devinit twa_probe(struct pc
 
 	pci_set_master(pdev);
 
-	retval = pci_set_dma_mask(pdev, sizeof(dma_addr_t) > 4 ? DMA_64BIT_MASK : DMA_32BIT_MASK);
-	if (retval) {
-		TW_PRINTK(host, TW_DRIVER, 0x23, "Failed to set dma mask");
-		goto out_disable_device;
-	}
+	if (pci_set_dma_mask(pdev, DMA_64BIT_MASK)
+	    || pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK))
+		if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)
+		    || pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) {
+			TW_PRINTK(host, TW_DRIVER, 0x23, "Failed to set dma mask");
+			retval = -ENODEV;
+			goto out_disable_device;
+		}
 
 	host = scsi_host_alloc(&driver_template, sizeof(TW_Device_Extension));
 	if (!host) {
author
#13 lore raw

PATCH 13/50 MTD: Initialise s_flags in get_sb_mtd_aux()

In reply to Greg KH

From: David Howells <[email protected]>

changeset 48440e893d700fb8f0de95fa7d748b711d290365 from mainline.

Initialise s_flags in get_sb_mtd_aux() from the flags parameter.

---
 drivers/mtd/mtdsuper.c |    2 ++
 1 file changed, 2 insertions(+)
drivers/mtd/mtdsuper.c +2 -0
@@ -70,6 +70,8 @@ static int get_sb_mtd_aux(struct file_sy
 	DEBUG(1, "MTDSB: New superblock for device %d (\"%s\")\n",
 	      mtd->index, mtd->name);
 
+	sb->s_flags = flags;
+
 	ret = fill_super(sb, data, flags & MS_SILENT ? 1 : 0);
 	if (ret < 0) {
 		up_write(&sb->s_umount);
author
#14 lore raw

PATCH 14/50 JFFS2: fix write deadlock regression

In reply to Greg KH

From: Jason Lunz <[email protected]>

Changeset fc0e01974ccccc7530b7634a63ee3fcc57b845ea from mainline.

I've bisected the deadlock when many small appends are done on jffs2 down to this commit:

commit 6fe6900e1e5b6fa9e5c59aa5061f244fe3f467e2

Author: Nick Piggin <[email protected]>
Date:   Sun May 6 14:49:04 2007 -0700

mm: make read_cache_page synchronous

Ensure pages are uptodate after returning from read_cache_page, which allows us to cut out most of the filesystem-internal PageUptodate calls.

I didn't have a great look down the call chains, but this appears to fixes 7 possible use-before uptodate in hfs, 2 in hfsplus, 1 in jfs, a few in ecryptfs, 1 in jffs2, and a possible cleared data overwritten with readpage in block2mtd. All depending on whether the filler is async and/or can return with a !uptodate page.

It introduced a wait to read_cache_page, as well as a read_cache_page_async function equivalent to the old read_cache_page without any callers.

Switching jffs2_gc_fetch_page to read_cache_page_async for the old behavior makes the deadlocks go away, but maybe reintroduces the use-before-uptodate problem? I don't understand the mm/fs interaction well enough to say.

[It's fine. dwmw2.]

---
 fs/jffs2/fs.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
fs/jffs2/fs.c +1 -1
@@ -627,7 +627,7 @@ unsigned char *jffs2_gc_fetch_page(struc
 	struct inode *inode = OFNI_EDONI_2SFFJ(f);
 	struct page *pg;
 
-	pg = read_cache_page(inode->i_mapping, offset >> PAGE_CACHE_SHIFT,
+	pg = read_cache_page_async(inode->i_mapping, offset >> PAGE_CACHE_SHIFT,
 			     (void *)jffs2_do_readpage_unlock, inode);
 	if (IS_ERR(pg))
 		return (void *)pg;
author
#15 lore raw

PATCH 15/50 V4L: cx88: Avoid a NULL pointer dereference during mpeg_open()

In reply to Greg KH

From: Steven Toth <[email protected]>

(cherry picked from commit 48200baeab95fd39a7f4c4f3536c7142a64ac335)

[PATCH] V4L: cx88: Avoid a NULL pointer dereference during mpeg_open()

Bug: With a hardware encoder board installed as cx88[1] and a non-encoder boards installed as cx88[0], an OOPS is generated during cx8802_get_device() called from mpeg_open().

---
 drivers/media/video/cx88/cx88-mpeg.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/media/video/cx88/cx88-mpeg.c +1 -1
@@ -580,7 +580,7 @@ struct cx8802_dev * cx8802_get_device(st
 
 	list_for_each(list,&cx8802_devlist) {
 		h = list_entry(list, struct cx8802_dev, devlist);
-		if (h->mpeg_dev->minor == minor)
+		if (h->mpeg_dev && h->mpeg_dev->minor == minor)
 			return h;
 	}
 
author
#16 lore raw

PATCH 16/50 hwmon: End of I/O region off-by-one

In reply to Greg KH

From: Jean Delvare <[email protected]>

Fix an off-by-one error in the I/O region declaration of two hardware monitoring drivers (lm78 and w83781d.) We were requesting one extra port at the end of the region.

This is a regression in 2.6.22 and could prevent other drivers from loading properly.

Already applied to Linus' tree for 2.6.23:
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=15bde2f1a8e819213f54314505a5a0509673109b

---
 drivers/hwmon/lm78.c    |    2 +-
 drivers/hwmon/w83781d.c |    2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
drivers/hwmon/lm78.c +1 -1
@@ -882,7 +882,7 @@ static int __init lm78_isa_device_add(un
 {
 	struct resource res = {
 		.start	= address,
-		.end	= address + LM78_EXTENT,
+		.end	= address + LM78_EXTENT - 1,
 		.name	= "lm78",
 		.flags	= IORESOURCE_IO,
 	};
drivers/hwmon/w83781d.c +1 -1
@@ -1746,7 +1746,7 @@ w83781d_isa_device_add(unsigned short ad
 {
 	struct resource res = {
 		.start	= address,
-		.end	= address + W83781D_EXTENT,
+		.end	= address + W83781D_EXTENT - 1,
 		.name	= "w83781d",
 		.flags	= IORESOURCE_IO,
 	};
author
#17 lore raw

PATCH 17/50 Fix debug regression in video/pwc

In reply to Greg KH

From: Jean Delvare <[email protected]>

Commit 85237f202d46d55c1bffe0c5b1aa3ddc0f1dce4d introduced the
following warning:
drivers/media/video/pwc/pwc-if.c: In function "pwc_video_close":
drivers/media/video/pwc/pwc-if.c:1211: warning: "i" may be used uninitialized in this function

This is true, and can cause a broken debug message to be logged. Here's a fix.

Fix is already in Linus' tree for 2.6.23:
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=7b9fbc3e30f785412a26819aa4daf0b6c27f6c53

---
 drivers/media/video/pwc/pwc-if.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/media/video/pwc/pwc-if.c +1 -1
@@ -1243,7 +1243,7 @@ static int pwc_video_close(struct inode 
 				PWC_ERROR("Failed to power down camera (%d)\n", i);
 		}
 		pdev->vopen--;
-		PWC_DEBUG_OPEN("<< video_close() vopen=%d\n", i);
+		PWC_DEBUG_OPEN("<< video_close() vopen=%d\n", pdev->vopen);
 	} else {
 		pwc_cleanup(pdev);
 		/* Free memory (don't set pdev to 0 just yet) */
author
#18 lore raw

PATCH 18/50 splice: fix direct splice error handling

In reply to Greg KH

From: Jens Axboe <[email protected]>

This is a splice patch for 2.6.22 and 2.6.21 (and earlier, I did not check. Let me know if you still maintain older stable trees!). It fixes an infinite loop in do_splice_direct(), when there's either nothing to read or nothing to write and blocking doesn't help. It could be things like running out of disk space. We need to exit both for failure and zero return, or we could be going around forever.

This got fixed in 2.6.23-git with commit 51a92c0f6ce8fa85fa0e18ecda1d847e606e8066

Herbert Poetzl <[email protected]> noticed this bug in 2.6.22, and has verified that this minimal fix works.

---
 fs/splice.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
fs/splice.c +2 -2
@@ -1011,7 +1011,7 @@ long do_splice_direct(struct file *in, l
 		max_read_len = min(len, (size_t)(PIPE_BUFFERS*PAGE_SIZE));
 
 		ret = do_splice_to(in, ppos, pipe, max_read_len, flags);
-		if (unlikely(ret < 0))
+		if (unlikely(ret <= 0))
 			goto out_release;
 
 		read_len = ret;
@@ -1023,7 +1023,7 @@ long do_splice_direct(struct file *in, l
 		 */
 		ret = do_splice_from(pipe, out, &out_off, read_len,
 				     flags & ~SPLICE_F_NONBLOCK);
-		if (unlikely(ret < 0))
+		if (unlikely(ret <= 0))
 			goto out_release;
 
 		bytes += ret;
author
#19 lore raw

PATCH 19/50 rpc: fix garbage in printk in svc_tcp_accept()

In reply to Greg KH

From: Wolfgang Walter <[email protected]>

commit 9db619e66503494e41159de3c76fafabe80d016b in mainline.

we upgraded the kernel of a nfs-server from 2.6.17.11 to 2.6.22.6. Since then we get the message

lockd: too many open TCP sockets, consider increasing the number of nfsd threads
lockd: last TCP connect from ^\\236^\É^D

These random characters in the second line are caused by a bug in svc_tcp_accept.

(Note: there are two previous __svc_print_addr(sin, buf, sizeof(buf)) calls in this function, either of which would initialize buf correctly; but both are inside "if"'s and are not necessarily executed. This is less obvious in the second case, which is inside a dprintk(), which is a macro which expands to an if statement.)

---
 net/sunrpc/svcsock.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
net/sunrpc/svcsock.c +2 -1
@@ -1090,7 +1090,8 @@ svc_tcp_accept(struct svc_sock *svsk)
 						   serv->sv_name);
 				printk(KERN_NOTICE
 				       "%s: last TCP connect from %s\n",
-				       serv->sv_name, buf);
+				       serv->sv_name, __svc_print_addr(sin,
+							buf, sizeof(buf)));
 			}
 			/*
 			 * Always select the oldest socket. It's not fair,
author
#20 lore raw

PATCH 20/50 disable sys_timerfd()

In reply to Greg KH

From: Andrew Morton <[email protected]>

commit e42601973b1bce1d2987f82159c1ebeaccc6b310 in mainline.

There is still some confusion and disagreement over what this interface should actually do. So it is best that we disable it in 2.6.23 until we get that fully sorted out.

(sys_timerfd() was present in 2.6.22 but it was apparently broken, so here we assume that nobody is using it yet).

---
 init/Kconfig |    1 +
 1 file changed, 1 insertion(+)
init/Kconfig +1 -0
@@ -505,6 +505,7 @@ config SIGNALFD
 config TIMERFD
 	bool "Enable timerfd() system call" if EMBEDDED
 	depends on ANON_INODES
+	depends on BROKEN
 	default y
 	help
 	  Enable the timerfd() system call that allows to receive timer
author
#21 lore raw

PATCH 21/50 afs: mntput called before dput

In reply to Greg KH

From: Andreas Gruenbacher <[email protected]>

commit 1a1a1a758bf0107d1f78ff1d622f45987803d894 in mainline.

dput must be called before mntput here.

---
 fs/afs/mntpt.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
fs/afs/mntpt.c +1 -1
@@ -235,8 +235,8 @@ static void *afs_mntpt_follow_link(struc
 	err = do_add_mount(newmnt, nd, MNT_SHRINKABLE, &afs_vfsmounts);
 	switch (err) {
 	case 0:
-		mntput(nd->mnt);
 		dput(nd->dentry);
+		mntput(nd->mnt);
 		nd->mnt = newmnt;
 		nd->dentry = dget(newmnt->mnt_root);
 		schedule_delayed_work(&afs_mntpt_expiry_timer,
author
#22 lore raw

PATCH 22/50 Fix DAC960 driver on machines which dont support 64-bit DMA

In reply to Greg KH

From: Matthew Wilcox <[email protected]>

commit 868047fcbb85dbb44ddd98c336fef83236a2c06a in mainline.

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

Use PCI_DMA_* constants instead of own private definitions Fall back to 32-bit DMA mask if a 64-bit one fails

---
 drivers/block/DAC960.c |   17 ++++++++++-------
 drivers/block/DAC960.h |    7 -------
 2 files changed, 10 insertions(+), 14 deletions(-)
drivers/block/DAC960.c +10 -7
@@ -17,8 +17,8 @@
 */
 
 
-#define DAC960_DriverVersion			"2.5.48"
-#define DAC960_DriverDate			"14 May 2006"
+#define DAC960_DriverVersion			"2.5.49"
+#define DAC960_DriverDate			"21 Aug 2007"
 
 
 #include <linux/module.h>
@@ -1165,9 +1165,9 @@ static bool DAC960_V1_EnableMemoryMailbo
   int i;
 
   
-  if (pci_set_dma_mask(Controller->PCIDevice, DAC690_V1_PciDmaMask))
+  if (pci_set_dma_mask(Controller->PCIDevice, DMA_32BIT_MASK))
 	return DAC960_Failure(Controller, "DMA mask out of range");
-  Controller->BounceBufferLimit = DAC690_V1_PciDmaMask;
+  Controller->BounceBufferLimit = DMA_32BIT_MASK;
 
   if ((hw_type == DAC960_PD_Controller) || (hw_type == DAC960_P_Controller)) {
     CommandMailboxesSize =  0;
@@ -1368,9 +1368,12 @@ static bool DAC960_V2_EnableMemoryMailbo
   dma_addr_t	CommandMailboxDMA;
   DAC960_V2_CommandStatus_T CommandStatus;
 
-  if (pci_set_dma_mask(Controller->PCIDevice, DAC690_V2_PciDmaMask))
-	return DAC960_Failure(Controller, "DMA mask out of range");
-  Controller->BounceBufferLimit = DAC690_V2_PciDmaMask;
+	if (!pci_set_dma_mask(Controller->PCIDevice, DMA_64BIT_MASK))
+		Controller->BounceBufferLimit = DMA_64BIT_MASK;
+	else if (!pci_set_dma_mask(Controller->PCIDevice, DMA_32BIT_MASK))
+		Controller->BounceBufferLimit = DMA_32BIT_MASK;
+	else
+		return DAC960_Failure(Controller, "DMA mask out of range");
 
   /* This is a temporary dma mapping, used only in the scope of this function */
   CommandMailbox = pci_alloc_consistent(PCI_Device,
drivers/block/DAC960.h +0 -7
@@ -61,13 +61,6 @@
 #define DAC960_V2_MaxPhysicalDevices		272
 
 /*
-  Define the pci dma mask supported by DAC960 V1 and V2 Firmware Controlers
- */
-
-#define DAC690_V1_PciDmaMask	0xffffffff
-#define DAC690_V2_PciDmaMask	0xffffffffffffffffULL
-
-/*
   Define a 32/64 bit I/O Address data type.
 */
 
author
#23 lore raw

PATCH 23/50 Fix "Fix DAC960 driver on machines which dont support 64-bit DMA"

In reply to Greg KH

From: Andrew Morton <[email protected]>

commit 3558c9b3232b5f0fd9f32043a191eca20fca64c6 in mainline.

sparc32:

drivers/block/DAC960.c: In function 'DAC960_V1_EnableMemoryMailboxInterface':
drivers/block/DAC960.c:1168: error: 'DMA_32BIT_MASK' undeclared (first use in this function) drivers/block/DAC960.c:1168: error: (Each undeclared identifier is reported only

---
 drivers/block/DAC960.c |    1 +
 1 file changed, 1 insertion(+)
drivers/block/DAC960.c +1 -0
@@ -31,6 +31,7 @@
 #include <linux/genhd.h>
 #include <linux/hdreg.h>
 #include <linux/blkpg.h>
+#include <linux/dma-mapping.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/mm.h>
author
#24 lore raw

PATCH 24/50 firewire: fw-ohci: ignore failure of pci_set_power_state (fix suspend regression)

In reply to Greg KH

From: Stefan Richter <[email protected]>

Minor regression since 2.6.22-rc1: If the experimental firewire-ohci driver instead of ohci1394 was loaded, iBook G3 and older PowerBooks refused to suspend.

Same as commit 5511142870046a7bed947d51ec9b320856ee120a plus format string touch-ups from 8a8cea2734808522f02941ea16125810ee42c9c7, "firewire: missing newline in printk". Original patch description:

Fixes (papers over) "Sleep problems with kernels >= 2.6.21 on powerpc",
http://lkml.org/lkml/2007/8/25/155. The issue is that the FireWire controller's pci_dev.current_state of iBook G3 and presumably older PowerBooks is still in PCI_UNKNOWN instead of PCI_D0 when the firewire driver's .suspend method is called.

Like it was suggested earlier in http://lkml.org/lkml/2006/10/24/13, we do not fail .suspend anymore if pci_set_power_state failed.

---
 drivers/firewire/fw-ohci.c |   10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)
drivers/firewire/fw-ohci.c +4 -6
@@ -1934,14 +1934,12 @@ static int pci_suspend(struct pci_dev *p
 	free_irq(pdev->irq, ohci);
 	err = pci_save_state(pdev);
 	if (err) {
-		fw_error("pci_save_state failed with %d", err);
+		fw_error("pci_save_state failed with %d\n", err);
 		return err;
 	}
 	err = pci_set_power_state(pdev, pci_choose_state(pdev, state));
-	if (err) {
-		fw_error("pci_set_power_state failed with %d", err);
-		return err;
-	}
+	if (err)
+		fw_error("pci_set_power_state failed with %d\n", err);
 
 	return 0;
 }
@@ -1955,7 +1953,7 @@ static int pci_resume(struct pci_dev *pd
 	pci_restore_state(pdev);
 	err = pci_enable_device(pdev);
 	if (err) {
-		fw_error("pci_enable_device failed with %d", err);
+		fw_error("pci_enable_device failed with %d\n", err);
 		return err;
 	}
 
author
#25 lore raw

PATCH 25/50 futex_compat: fix list traversal bugs

In reply to Greg KH

From: Arnd Bergmann <[email protected]>

commit 179c85ea53bef807621f335767e41e23f86f01df in mainline.

The futex list traversal on the compat side appears to have a bug.

It's loop termination condition compares:

        while (compat_ptr(uentry) != &head->list)

But that can't be right because "uentry" has the special "pi" indicator bit still potentially set at bit 0. This is cleared by fetch_robust_entry() into the "entry" return value.

What this seems to mean is that the list won't terminate when list iteration gets back to the the head. And we'll also process the list head like a normal entry, which could cause all kinds of problems.

So we should check for equality with "entry". That pointer is of the non-compat type so we have to do a little casting to keep the compiler and sparse happy.

The same problem can in theory occur with the 'pending' variable, although that has not been reported from users so far.

Based on the original patch from David Miller.

---
 kernel/futex_compat.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
kernel/futex_compat.c +2 -2
@@ -61,10 +61,10 @@ void compat_exit_robust_list(struct task
 	if (fetch_robust_entry(&upending, &pending,
 			       &head->list_op_pending, &pip))
 		return;
-	if (upending)
+	if (pending)
 		handle_futex_death((void __user *)pending + futex_offset, curr, pip);
 
-	while (compat_ptr(uentry) != &head->list) {
+	while (entry != (struct robust_list __user *) &head->list) {
 		/*
 		 * A pending lock might already be on the list, so
 		 * dont process it twice:
author
#26 lore raw

PATCH 26/50 Leases can be hidden by flocks

In reply to Greg KH

From: Pavel Emelyanov <[email protected]>

commit 0e2f6db88a6900bc9db576d6b478b12ee60d61f7 in mainline.

The inode->i_flock list contains the leases, flocks and posix locks in the specified order. However, the flocks are added in the head of this list thus hiding the leases from F_GETLEASE command, from time_out_leases() and other code that expects the leases to come first.

The following example will demonstrate this:

#define _GNU_SOURCE

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/file.h>

static void show_lease(int fd)

{
        int res;

        res = fcntl(fd, F_GETLEASE);
        switch (res) {
                case F_RDLCK:
                        printf("Read lease\n");
                        break;
                case F_WRLCK:
                        printf("Write lease\n");
                        break;
                case F_UNLCK:
                        printf("No leases\n");
                        break;
                default:
                        printf("Some shit\n");
                        break;
        }
}

int main(int argc, char **argv)

{
        int fd, res;

        fd = open(argv[1], O_RDONLY);
        if (fd == -1) {
                perror("Can't open file");
                return 1;
        }

        res = fcntl(fd, F_SETLEASE, F_WRLCK);
        if (res == -1) {
                perror("Can't set lease");
                return 1;
        }

        show_lease(fd);

        if (flock(fd, LOCK_SH) == -1) {
                perror("Can't flock shared");
                return 1;
        }

        show_lease(fd);

        return 0;
}

The first call to show_lease() will show the write lease set, but the second will show no leases.

Fix the flock adding so that the leases always stay in the head of this list.

Found during making the flocks pid-namespaces aware.

---
 fs/locks.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
fs/locks.c +1 -1
@@ -786,7 +786,7 @@ find_conflict:
 	if (request->fl_flags & FL_ACCESS)
 		goto out;
 	locks_copy_lock(new_fl, request);
-	locks_insert_lock(&inode->i_flock, new_fl);
+	locks_insert_lock(before, new_fl);
 	new_fl = NULL;
 	error = 0;
 
author
#27 lore raw

PATCH 27/50 ext34: ensure do_split leaves enough free space in both blocks

In reply to Greg KH

From: Eric Sandeen <[email protected]>

commit ef2b02d3e617cb0400eedf2668f86215e1b0e6af in mainline.

The do_split() function for htree dir blocks is intended to split a leaf block to make room for a new entry. It sorts the entries in the original block by hash value, then moves the last half of the entries to the new block - without accounting for how much space this actually moves. (IOW, it moves half of the entry *count* not half of the entry *space*). If by chance we have both large & small entries, and we move only the smallest entries, and we have a large new entry to insert, we may not have created enough space for it.

The patch below stores each record size when calculating the dx_map, and then walks the hash-sorted dx_map, calculating how many entries must be moved to more evenly split the existing entries between the old block and the new block, guaranteeing enough space for the new entry.

The dx_map "offs" member is reduced to u16 so that the overall map size does not change - it is temporarily stored at the end of the new block, and if it grows too large it may be overwritten. By making offs and size both u16, we won't grow the map size.

Also add a few comments to the functions involved.

This fixes the testcase reported by [email protected] on the linux-ext4 list, "ext3 dir_index causes an error"

Thanks to Andreas Dilger for discussing the problem & solution with me.

---
 fs/ext3/namei.c |   39 +++++++++++++++++++++++++++++++++++----
 fs/ext4/namei.c |   39 +++++++++++++++++++++++++++++++++++----
 2 files changed, 70 insertions(+), 8 deletions(-)
fs/ext3/namei.c +35 -4
@@ -140,7 +140,8 @@ struct dx_frame
 struct dx_map_entry
 {
 	u32 hash;
-	u32 offs;
+	u16 offs;
+	u16 size;
 };
 
 #ifdef CONFIG_EXT3_INDEX
@@ -671,6 +672,10 @@ errout:
  * Directory block splitting, compacting
  */
 
+/*
+ * Create map of hash values, offsets, and sizes, stored at end of block.
+ * Returns number of entries mapped.
+ */
 static int dx_make_map (struct ext3_dir_entry_2 *de, int size,
 			struct dx_hash_info *hinfo, struct dx_map_entry *map_tail)
 {
@@ -684,7 +689,8 @@ static int dx_make_map (struct ext3_dir_
 			ext3fs_dirhash(de->name, de->name_len, &h);
 			map_tail--;
 			map_tail->hash = h.hash;
-			map_tail->offs = (u32) ((char *) de - base);
+			map_tail->offs = (u16) ((char *) de - base);
+			map_tail->size = le16_to_cpu(de->rec_len);
 			count++;
 			cond_resched();
 		}
@@ -694,6 +700,7 @@ static int dx_make_map (struct ext3_dir_
 	return count;
 }
 
+/* Sort map by hash value */
 static void dx_sort_map (struct dx_map_entry *map, unsigned count)
 {
         struct dx_map_entry *p, *q, *top = map + count - 1;
@@ -1081,6 +1088,10 @@ static inline void ext3_set_de_type(stru
 }
 
 #ifdef CONFIG_EXT3_INDEX
+/*
+ * Move count entries from end of map between two memory locations.
+ * Returns pointer to last entry moved.
+ */
 static struct ext3_dir_entry_2 *
 dx_move_dirents(char *from, char *to, struct dx_map_entry *map, int count)
 {
@@ -1099,6 +1110,10 @@ dx_move_dirents(char *from, char *to, st
 	return (struct ext3_dir_entry_2 *) (to - rec_len);
 }
 
+/*
+ * Compact each dir entry in the range to the minimal rec_len.
+ * Returns pointer to last entry in range.
+ */
 static struct ext3_dir_entry_2* dx_pack_dirents(char *base, int size)
 {
 	struct ext3_dir_entry_2 *next, *to, *prev, *de = (struct ext3_dir_entry_2 *) base;
@@ -1121,6 +1136,11 @@ static struct ext3_dir_entry_2* dx_pack_
 	return prev;
 }
 
+/*
+ * Split a full leaf block to make room for a new dir entry.
+ * Allocate a new block, and move entries so that they are approx. equally full.
+ * Returns pointer to de in block into which the new entry will be inserted.
+ */
 static struct ext3_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
 			struct buffer_head **bh,struct dx_frame *frame,
 			struct dx_hash_info *hinfo, int *error)
@@ -1132,7 +1152,7 @@ static struct ext3_dir_entry_2 *do_split
 	u32 hash2;
 	struct dx_map_entry *map;
 	char *data1 = (*bh)->b_data, *data2;
-	unsigned split;
+	unsigned split, move, size, i;
 	struct ext3_dir_entry_2 *de = NULL, *de2;
 	int	err = 0;
 
@@ -1160,8 +1180,19 @@ static struct ext3_dir_entry_2 *do_split
 	count = dx_make_map ((struct ext3_dir_entry_2 *) data1,
 			     blocksize, hinfo, map);
 	map -= count;
-	split = count/2; // need to adjust to actual middle
 	dx_sort_map (map, count);
+	/* Split the existing block in the middle, size-wise */
+	size = 0;
+	move = 0;
+	for (i = count-1; i >= 0; i--) {
+		/* is more than half of this entry in 2nd half of the block? */
+		if (size + map[i].size/2 > blocksize/2)
+			break;
+		size += map[i].size;
+		move++;
+	}
+	/* map index at which we will split */
+	split = count - move;
 	hash2 = map[split].hash;
 	continued = hash2 == map[split - 1].hash;
 	dxtrace(printk("Split block %i at %x, %i/%i\n",
fs/ext4/namei.c +35 -4
@@ -140,7 +140,8 @@ struct dx_frame
 struct dx_map_entry
 {
 	u32 hash;
-	u32 offs;
+	u16 offs;
+	u16 size;
 };
 
 #ifdef CONFIG_EXT4_INDEX
@@ -671,6 +672,10 @@ errout:
  * Directory block splitting, compacting
  */
 
+/*
+ * Create map of hash values, offsets, and sizes, stored at end of block.
+ * Returns number of entries mapped.
+ */
 static int dx_make_map (struct ext4_dir_entry_2 *de, int size,
 			struct dx_hash_info *hinfo, struct dx_map_entry *map_tail)
 {
@@ -684,7 +689,8 @@ static int dx_make_map (struct ext4_dir_
 			ext4fs_dirhash(de->name, de->name_len, &h);
 			map_tail--;
 			map_tail->hash = h.hash;
-			map_tail->offs = (u32) ((char *) de - base);
+			map_tail->offs = (u16) ((char *) de - base);
+			map_tail->size = le16_to_cpu(de->rec_len);
 			count++;
 			cond_resched();
 		}
@@ -694,6 +700,7 @@ static int dx_make_map (struct ext4_dir_
 	return count;
 }
 
+/* Sort map by hash value */
 static void dx_sort_map (struct dx_map_entry *map, unsigned count)
 {
 	struct dx_map_entry *p, *q, *top = map + count - 1;
@@ -1079,6 +1086,10 @@ static inline void ext4_set_de_type(stru
 }
 
 #ifdef CONFIG_EXT4_INDEX
+/*
+ * Move count entries from end of map between two memory locations.
+ * Returns pointer to last entry moved.
+ */
 static struct ext4_dir_entry_2 *
 dx_move_dirents(char *from, char *to, struct dx_map_entry *map, int count)
 {
@@ -1097,6 +1108,10 @@ dx_move_dirents(char *from, char *to, st
 	return (struct ext4_dir_entry_2 *) (to - rec_len);
 }
 
+/*
+ * Compact each dir entry in the range to the minimal rec_len.
+ * Returns pointer to last entry in range.
+ */
 static struct ext4_dir_entry_2* dx_pack_dirents(char *base, int size)
 {
 	struct ext4_dir_entry_2 *next, *to, *prev, *de = (struct ext4_dir_entry_2 *) base;
@@ -1119,6 +1134,11 @@ static struct ext4_dir_entry_2* dx_pack_
 	return prev;
 }
 
+/*
+ * Split a full leaf block to make room for a new dir entry.
+ * Allocate a new block, and move entries so that they are approx. equally full.
+ * Returns pointer to de in block into which the new entry will be inserted.
+ */
 static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
 			struct buffer_head **bh,struct dx_frame *frame,
 			struct dx_hash_info *hinfo, int *error)
@@ -1130,7 +1150,7 @@ static struct ext4_dir_entry_2 *do_split
 	u32 hash2;
 	struct dx_map_entry *map;
 	char *data1 = (*bh)->b_data, *data2;
-	unsigned split;
+	unsigned split, move, size, i;
 	struct ext4_dir_entry_2 *de = NULL, *de2;
 	int	err = 0;
 
@@ -1158,8 +1178,19 @@ static struct ext4_dir_entry_2 *do_split
 	count = dx_make_map ((struct ext4_dir_entry_2 *) data1,
 			     blocksize, hinfo, map);
 	map -= count;
-	split = count/2; // need to adjust to actual middle
 	dx_sort_map (map, count);
+	/* Split the existing block in the middle, size-wise */
+	size = 0;
+	move = 0;
+	for (i = count-1; i >= 0; i--) {
+		/* is more than half of this entry in 2nd half of the block? */
+		if (size + map[i].size/2 > blocksize/2)
+			break;
+		size += map[i].size;
+		move++;
+	}
+	/* map index at which we will split */
+	split = count - move;
 	hash2 = map[split].hash;
 	continued = hash2 == map[split - 1].hash;
 	dxtrace(printk("Split block %i at %x, %i/%i\n",
author
#28 lore raw

PATCH 28/50 nfs: fix oops re sysctls and V4 support

In reply to Greg KH

From: Alexey Dobriyan <[email protected]>

commit 49af7ee181f4f516ac99eba85d3f70ed42cabe76 in mainline.

NFS unregisters sysctls only if V4 support is compiled in. However, sysctl table is not V4 specific, so unregister it always.

Steps to reproduce:

[build nfs.ko with CONFIG_NFS_V4=n]
modrobe nfs
rmmod nfs
ls /proc/sys

Unable to handle kernel paging request at ffffffff880661c0 RIP:
 [<ffffffff802af8e3>] proc_sys_readdir+0xd3/0x350
PGD 203067 PUD 207063 PMD 7e216067 PTE 0
Oops: 0000 [1] SMP
CPU 1
Modules linked in: lockd nfs_acl sunrpc
Pid: 3335, comm: ls Not tainted 2.6.23-rc3-bloat #2
RIP: 0010:[<ffffffff802af8e3>]  [<ffffffff802af8e3>] proc_sys_readdir+0xd3/0x350
RSP: 0018:ffff81007fd93e78  EFLAGS: 00010286
RAX: ffffffff880661c0 RBX: ffffffff80466370 RCX: ffffffff880661c0
RDX: 00000000000014c0 RSI: ffff81007f3ad020 RDI: ffff81007efd8b40
RBP: 0000000000000018 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000001 R11: ffffffff802a8570 R12: ffffffff880661c0
R13: ffff81007e219640 R14: ffff81007efd8b40 R15: ffff81007ded7280
FS:  00002ba25ef03060(0000) GS:ffff81007ff81258(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
CR2: ffffffff880661c0 CR3: 000000007dfaf000 CR4: 00000000000006e0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
Process ls (pid: 3335, threadinfo ffff81007fd92000, task ffff81007d8a0000)
Stack:  ffff81007f3ad150 ffffffff80283f30 ffff81007fd93f48 ffff81007efd8b40
 ffff81007ee00440 0000000422222222 0000000200035593 ffffffff88037e9a
 2222222222222222 ffffffff80466500 ffff81007e416400 ffff81007e219640
Call Trace:
 [<ffffffff80283f30>] filldir+0x0/0xf0
 [<ffffffff80283f30>] filldir+0x0/0xf0
 [<ffffffff802840c7>] vfs_readdir+0xa7/0xc0
 [<ffffffff80284376>] sys_getdents+0x96/0xe0
 [<ffffffff8020bb3e>] system_call+0x7e/0x83

Code: 41 8b 14 24 85 d2 74 dc 49 8b 44 24 08 48 85 c0 74 e7 49 3b
RIP  [<ffffffff802af8e3>] proc_sys_readdir+0xd3/0x350
 RSP <ffff81007fd93e78>
CR2: ffffffff880661c0
Kernel panic - not syncing: Fatal exception

---

 fs/nfs/super.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
fs/nfs/super.c +1 -1
@@ -181,8 +181,8 @@ void __exit unregister_nfs_fs(void)
 		remove_shrinker(acl_shrinker);
 #ifdef CONFIG_NFS_V4
 	unregister_filesystem(&nfs4_fs_type);
-	nfs_unregister_sysctl();
 #endif
+	nfs_unregister_sysctl();
 	unregister_filesystem(&nfs_fs_type);
 }
 
author
#29 lore raw

PATCH 29/50 dir_index: error out instead of BUG on corrupt dx dirs

In reply to Greg KH

From: Eric Sandeen <[email protected]>

commit 3d82abae9523c33d4a16fdfdfd2bdde316d7b56a in mainline.

Convert asserts (BUGs) in dx_probe from bad on-disk data to recoverable errors with helpful warnings. With help catching other asserts from Duane Griffin <[email protected]>

---
 fs/ext3/namei.c |   34 ++++++++++++++++++++++++++++++----
 fs/ext4/namei.c |   34 ++++++++++++++++++++++++++++++----
 2 files changed, 60 insertions(+), 8 deletions(-)
fs/ext3/namei.c +30 -4
@@ -380,13 +380,28 @@ dx_probe(struct dentry *dentry, struct i
 
 	entries = (struct dx_entry *) (((char *)&root->info) +
 				       root->info.info_length);
-	assert(dx_get_limit(entries) == dx_root_limit(dir,
-						      root->info.info_length));
+
+	if (dx_get_limit(entries) != dx_root_limit(dir,
+						   root->info.info_length)) {
+		ext3_warning(dir->i_sb, __FUNCTION__,
+			     "dx entry: limit != root limit");
+		brelse(bh);
+		*err = ERR_BAD_DX_DIR;
+		goto fail;
+	}
+
 	dxtrace (printk("Look up %x", hash));
 	while (1)
 	{
 		count = dx_get_count(entries);
-		assert (count && count <= dx_get_limit(entries));
+		if (!count || count > dx_get_limit(entries)) {
+			ext3_warning(dir->i_sb, __FUNCTION__,
+				     "dx entry: no count or count > limit");
+			brelse(bh);
+			*err = ERR_BAD_DX_DIR;
+			goto fail2;
+		}
+
 		p = entries + 1;
 		q = entries + count - 1;
 		while (p <= q)
@@ -424,8 +439,15 @@ dx_probe(struct dentry *dentry, struct i
 		if (!(bh = ext3_bread (NULL,dir, dx_get_block(at), 0, err)))
 			goto fail2;
 		at = entries = ((struct dx_node *) bh->b_data)->entries;
-		assert (dx_get_limit(entries) == dx_node_limit (dir));
+		if (dx_get_limit(entries) != dx_node_limit (dir)) {
+			ext3_warning(dir->i_sb, __FUNCTION__,
+				     "dx entry: limit != node limit");
+			brelse(bh);
+			*err = ERR_BAD_DX_DIR;
+			goto fail2;
+		}
 		frame++;
+		frame->bh = NULL;
 	}
 fail2:
 	while (frame >= frame_in) {
@@ -433,6 +455,10 @@ fail2:
 		frame--;
 	}
 fail:
+	if (*err == ERR_BAD_DX_DIR)
+		ext3_warning(dir->i_sb, __FUNCTION__,
+			     "Corrupt dir inode %ld, running e2fsck is "
+			     "recommended.", dir->i_ino);
 	return NULL;
 }
 
fs/ext4/namei.c +30 -4
@@ -380,13 +380,28 @@ dx_probe(struct dentry *dentry, struct i
 
 	entries = (struct dx_entry *) (((char *)&root->info) +
 				       root->info.info_length);
-	assert(dx_get_limit(entries) == dx_root_limit(dir,
-						      root->info.info_length));
+
+	if (dx_get_limit(entries) != dx_root_limit(dir,
+						   root->info.info_length)) {
+		ext4_warning(dir->i_sb, __FUNCTION__,
+			     "dx entry: limit != root limit");
+		brelse(bh);
+		*err = ERR_BAD_DX_DIR;
+		goto fail;
+	}
+
 	dxtrace (printk("Look up %x", hash));
 	while (1)
 	{
 		count = dx_get_count(entries);
-		assert (count && count <= dx_get_limit(entries));
+		if (!count || count > dx_get_limit(entries)) {
+			ext4_warning(dir->i_sb, __FUNCTION__,
+				     "dx entry: no count or count > limit");
+			brelse(bh);
+			*err = ERR_BAD_DX_DIR;
+			goto fail2;
+		}
+
 		p = entries + 1;
 		q = entries + count - 1;
 		while (p <= q)
@@ -424,8 +439,15 @@ dx_probe(struct dentry *dentry, struct i
 		if (!(bh = ext4_bread (NULL,dir, dx_get_block(at), 0, err)))
 			goto fail2;
 		at = entries = ((struct dx_node *) bh->b_data)->entries;
-		assert (dx_get_limit(entries) == dx_node_limit (dir));
+		if (dx_get_limit(entries) != dx_node_limit (dir)) {
+			ext4_warning(dir->i_sb, __FUNCTION__,
+				     "dx entry: limit != node limit");
+			brelse(bh);
+			*err = ERR_BAD_DX_DIR;
+			goto fail2;
+		}
 		frame++;
+		frame->bh = NULL;
 	}
 fail2:
 	while (frame >= frame_in) {
@@ -433,6 +455,10 @@ fail2:
 		frame--;
 	}
 fail:
+	if (*err == ERR_BAD_DX_DIR)
+		ext4_warning(dir->i_sb, __FUNCTION__,
+			     "Corrupt dir inode %ld, running e2fsck is "
+			     "recommended.", dir->i_ino);
 	return NULL;
 }
 
author
#30 lore raw

PATCH 30/50 ieee1394: ohci1394: fix initialization if built non-modular

In reply to Greg KH

From: Stefan Richter <[email protected]>

Initialization of ohci1394 was broken according to one reporter if the driver was statically linked, i.e. not built as loadable module. Dmesg:

PCI: Device 0000:02:07.0 not available because of resource collisions
ohci1394: Failed to enable OHCI hardware.

This was reported for a Toshiba Satellite 5100-503. The cause is commit 8df4083c5291b3647e0381d3c69ab2196f5dd3b7 in Linux 2.6.19-rc1 which only served purposes of early remote debugging via FireWire. This functionality is better provided by the currently out-of-tree driver ohci1394_earlyinit. Reversal of the commit was OK'd by Andi Kleen.

Same as pre-2.6.23 commit be7963b7e7f08a149e247c0bf29a4abd174e0929.

---
 drivers/ieee1394/ieee1394_core.c |    2 +-
 drivers/ieee1394/ohci1394.c      |    4 +---
 2 files changed, 2 insertions(+), 4 deletions(-)
drivers/ieee1394/ieee1394_core.c +1 -1
@@ -1279,7 +1279,7 @@ static void __exit ieee1394_cleanup(void
 	unregister_chrdev_region(IEEE1394_CORE_DEV, 256);
 }
 
-fs_initcall(ieee1394_init); /* same as ohci1394 */
+module_init(ieee1394_init);
 module_exit(ieee1394_cleanup);
 
 /* Exported symbols */
drivers/ieee1394/ohci1394.c +1 -3
@@ -3773,7 +3773,5 @@ static int __init ohci1394_init(void)
 	return pci_register_driver(&ohci1394_pci_driver);
 }
 
-/* Register before most other device drivers.
- * Useful for remote debugging via physical DMA, e.g. using firescope. */
-fs_initcall(ohci1394_init);
+module_init(ohci1394_init);
 module_exit(ohci1394_cleanup);
author
#31 lore raw

PATCH 31/50 Correctly close old nfsd/lockd sockets.

In reply to Greg KH

From: Neil Brown <[email protected]>

commit 7a1fa065a0264f6b3d3003ba5635289f6583c478 in mainline.

Commit aaf68cfbf2241d24d46583423f6bff5c47e088b3 added a bias to sk_inuse, so this test for an unused socket now fails. So no sockets get closed because they are old (they might get closed if the client closed them).

This bug has existed since 2.6.21-rc1.

Thanks to Wolfgang Walter for finding and reporting the bug.

---
 net/sunrpc/svcsock.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
net/sunrpc/svcsock.c +2 -1
@@ -1573,7 +1573,8 @@ svc_age_temp_sockets(unsigned long closu
 
 		if (!test_and_set_bit(SK_OLD, &svsk->sk_flags))
 			continue;
-		if (atomic_read(&svsk->sk_inuse) || test_bit(SK_BUSY, &svsk->sk_flags))
+		if (atomic_read(&svsk->sk_inuse) > 1
+		    || test_bit(SK_BUSY, &svsk->sk_flags))
 			continue;
 		atomic_inc(&svsk->sk_inuse);
 		list_move(le, &to_be_aged);
author
#32 lore raw

PATCH 32/50 Fix race with shared tag queue maps

In reply to Greg KH

From: Jens Axboe <[email protected]>

The commit in Linus upstream git tree is
f3da54ba140c6427fa4a32913e1bf406f41b5dda.

Fix race with shared tag queue maps

There's a race condition in blk_queue_end_tag() for shared tag maps, users include stex (promise supertrak thingy) and qla2xxx. The former at least has reported bugs in this area, not sure why we haven't seen any for the latter. It could be because the window is narrow and that other conditions in the qla2xxx code hide this. It's a real bug, though, as the stex smp users can attest.

We need to ensure two things - the tag bit clearing needs to happen AFTER we cleared the tag pointer, as the tag bit clearing/setting is what protects this map. Secondly, we need to ensure that the visibility of the tag pointer and tag bit clear are ordered properly.

[ I removed the SMP barriers - "test_and_clear_bit()" already implies
all the required barriers. -- Linus ]

Also see http://bugzilla.kernel.org/show_bug.cgi?id=7842

---
 block/ll_rw_blk.c |   13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)
block/ll_rw_blk.c +7 -6
@@ -1081,12 +1081,6 @@ void blk_queue_end_tag(request_queue_t *
 		 */
 		return;
 
-	if (unlikely(!__test_and_clear_bit(tag, bqt->tag_map))) {
-		printk(KERN_ERR "%s: attempt to clear non-busy tag (%d)\n",
-		       __FUNCTION__, tag);
-		return;
-	}
-
 	list_del_init(&rq->queuelist);
 	rq->cmd_flags &= ~REQ_QUEUED;
 	rq->tag = -1;
@@ -1096,6 +1090,13 @@ void blk_queue_end_tag(request_queue_t *
 		       __FUNCTION__, tag);
 
 	bqt->tag_index[tag] = NULL;
+
+	if (unlikely(!test_and_clear_bit(tag, bqt->tag_map))) {
+		printk(KERN_ERR "%s: attempt to clear non-busy tag (%d)\n",
+		       __FUNCTION__, tag);
+		return;
+	}
+
 	bqt->busy--;
 }
 
author
#33 lore raw

PATCH 33/50 crypto: blkcipher_get_spot() handling of buffer at end of page

In reply to Greg KH

From: Herbert Xu <[email protected]>

This corresponds to upstream changesets
e4630f9fd8cdc14eb1caa08dafe649eb5ae09985 and
32528d0fbda1093eeeaa7d0a2c498bbb5154099d.

[CRYPTO] blkcipher: Fix handling of kmalloc page straddling

The function blkcipher_get_spot tries to return a buffer of the specified length that does not straddle a page. It has an off-by-one bug so it may advance a page unnecessarily.

What's worse, one of its callers doesn't provide a buffer that's sufficiently long for this operation.

This patch fixes both problems. Thanks to Bob Gilligan for diagnosing this problem and providing a fix.

---
 crypto/blkcipher.c |   11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)
crypto/blkcipher.c +7 -4
@@ -59,11 +59,13 @@ static inline void blkcipher_unmap_dst(s
 	scatterwalk_unmap(walk->dst.virt.addr, 1);
 }
 
+/* Get a spot of the specified length that does not straddle a page.
+ * The caller needs to ensure that there is enough space for this operation.
+ */
 static inline u8 *blkcipher_get_spot(u8 *start, unsigned int len)
 {
-	if (offset_in_page(start + len) < len)
-		return (u8 *)((unsigned long)(start + len) & PAGE_MASK);
-	return start;
+	u8 *end_page = (u8 *)(((unsigned long)(start + len - 1)) & PAGE_MASK);
+	return start > end_page ? start : end_page;
 }
 
 static inline unsigned int blkcipher_done_slow(struct crypto_blkcipher *tfm,
@@ -155,7 +157,8 @@ static inline int blkcipher_next_slow(st
 	if (walk->buffer)
 		goto ok;
 
-	n = bsize * 2 + (alignmask & ~(crypto_tfm_ctx_alignment() - 1));
+	n = bsize * 3 - (alignmask + 1) +
+	    (alignmask & ~(crypto_tfm_ctx_alignment() - 1));
 	walk->buffer = kmalloc(n, GFP_ATOMIC);
 	if (!walk->buffer)
 		return blkcipher_walk_done(desc, walk, -ENOMEM);
author
#34 lore raw

PATCH 34/50 fix realtek phy id in forcedeth

In reply to Greg KH

From: Willy Tarreau <[email protected]>

commit ba685fb2abd71162bea6895a99449c1071b01402 in mainline.

As noticed by Chuck Ebbert, commit c5e3ae8823693b260ce1f217adca8add1bc0b3de introduced a copy-paste typo, as realtek phy is 0x732 and not 0x1c1. Obvious fix below suggested by Ayaz Abdulla.

---
 drivers/net/forcedeth.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/forcedeth.c +1 -1
@@ -551,7 +551,7 @@ union ring_type {
 #define PHY_OUI_MARVELL	0x5043
 #define PHY_OUI_CICADA	0x03f1
 #define PHY_OUI_VITESSE	0x01c1
-#define PHY_OUI_REALTEK	0x01c1
+#define PHY_OUI_REALTEK	0x0732
 #define PHYID1_OUI_MASK	0x03ff
 #define PHYID1_OUI_SHFT	6
 #define PHYID2_OUI_MASK	0xfc00
author
#35 lore raw

PATCH 35/50 Fix decnet device address listing.

In reply to Greg KH

From: Patrick McHardy <[email protected]>

commit a2221f308dabb95abb914ad858d36c2462705558 in mainline.

Not all are listed, same as the IPV4 devinet bug.

---
 net/decnet/dn_dev.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
net/decnet/dn_dev.c +1 -1
@@ -815,7 +815,7 @@ static int dn_nl_dump_ifaddr(struct sk_b
 		for (ifa = dn_db->ifa_list, dn_idx = 0; ifa;
 		     ifa = ifa->ifa_next, dn_idx++) {
 			if (dn_idx < skip_naddr)
-				goto cont;
+				continue;
 
 			if (dn_nl_fill_ifaddr(skb, ifa, NETLINK_CB(cb->skb).pid,
 					      cb->nlh->nlmsg_seq, RTM_NEWADDR,
author
#36 lore raw

PATCH 36/50 Fix device address listing for ipv4.

In reply to Greg KH

From: Stephen Hemminger <[email protected]>

commit 596e41509550447b030f7b16adaeb0138ab585a8 in mainline

Not all ips are shown by "ip addr show" command when IPs number assigned to an interface is more than 60-80 (in fact it depends on broadcast/label etc presence on each address).

Steps to reproduce:
It's terribly simple to reproduce:

# for i in $(seq 1 100); do ip ad add 10.0.$i.1/24 dev eth10 ; done
# ip addr show

this will _not_ show all IPs.
Looks like the problem is in netlink/ipv4 message processing.

This is fix from bug submitter, it looks correct.

---
 net/ipv4/devinet.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
net/ipv4/devinet.c +1 -1
@@ -1194,7 +1194,7 @@ static int inet_dump_ifaddr(struct sk_bu
 		for (ifa = in_dev->ifa_list, ip_idx = 0; ifa;
 		     ifa = ifa->ifa_next, ip_idx++) {
 			if (ip_idx < s_ip_idx)
-				goto cont;
+				continue;
 			if (inet_fill_ifaddr(skb, ifa, NETLINK_CB(cb->skb).pid,
 					     cb->nlh->nlmsg_seq,
 					     RTM_NEWADDR, NLM_F_MULTI) <= 0)
author
#37 lore raw

PATCH 37/50 Fix inet_diag OOPS.

In reply to Greg KH

From: Patrick McHardy <[email protected]>

commit 0a9c73014415d2a84dac346c1e12169142a6ad37 in mainline

[INET_DIAG]: Fix oops in netlink_rcv_skb

netlink_run_queue() doesn't handle multiple processes processing the queue concurrently. Serialize queue processing in inet_diag to fix a oops in netlink_rcv_skb caused by netlink_run_queue passing a NULL for the skb.

BUG: unable to handle kernel NULL pointer dereference at virtual address 00000054
[349587.500454]  printing eip:
[349587.500457] c03318ae
[349587.500459] *pde = 00000000
[349587.500464] Oops: 0000 [#1]
[349587.500466] PREEMPT SMP
[349587.500474] Modules linked in: w83627hf hwmon_vid i2c_isa
[349587.500483] CPU:    0
[349587.500485] EIP:    0060:[<c03318ae>]    Not tainted VLI
[349587.500487] EFLAGS: 00010246   (2.6.22.3 #1)
[349587.500499] EIP is at netlink_rcv_skb+0xa/0x7e
[349587.500506] eax: 00000000   ebx: 00000000   ecx: c148d2a0   edx: c0398819
[349587.500510] esi: 00000000   edi: c0398819   ebp: c7a21c8c   esp: c7a21c80
[349587.500517] ds: 007b   es: 007b   fs: 00d8  gs: 0033  ss: 0068
[349587.500521] Process oidentd (pid: 17943, ti=c7a20000 task=cee231c0 task.ti=c7a20000)
[349587.500527] Stack: 00000000 c7a21cac f7c8ba78 c7a21ca4 c0331962 c0398819 f7c8ba00 0000004c
[349587.500542]        f736f000 c7a21cb4 c03988e3 00000001 f7c8ba00 c7a21cc4 c03312a5 0000004c
[349587.500558]        f7c8ba00 c7a21cd4 c0330681 f7c8ba00 e4695280 c7a21d00 c03307c6 7fffffff
[349587.500578] Call Trace:
[349587.500581]  [<c010361a>] show_trace_log_lvl+0x1c/0x33
[349587.500591]  [<c01036d4>] show_stack_log_lvl+0x8d/0xaa
[349587.500595]  [<c010390e>] show_registers+0x1cb/0x321
[349587.500604]  [<c0103bff>] die+0x112/0x1e1
[349587.500607]  [<c01132d2>] do_page_fault+0x229/0x565
[349587.500618]  [<c03c8d3a>] error_code+0x72/0x78
[349587.500625]  [<c0331962>] netlink_run_queue+0x40/0x76
[349587.500632]  [<c03988e3>] inet_diag_rcv+0x1f/0x2c
[349587.500639]  [<c03312a5>] netlink_data_ready+0x57/0x59
[349587.500643]  [<c0330681>] netlink_sendskb+0x24/0x45
[349587.500651]  [<c03307c6>] netlink_unicast+0x100/0x116
[349587.500656]  [<c0330f83>] netlink_sendmsg+0x1c2/0x280
[349587.500664]  [<c02fcce9>] sock_sendmsg+0xba/0xd5
[349587.500671]  [<c02fe4d1>] sys_sendmsg+0x17b/0x1e8
[349587.500676]  [<c02fe92d>] sys_socketcall+0x230/0x24d
[349587.500684]  [<c01028d2>] syscall_call+0x7/0xb
[349587.500691]  =======================
[349587.500693] Code: f0 ff 4e 18 0f 94 c0 84 c0 0f 84 66 ff ff ff 89 f0 e8 86 e2 fc ff e9 5a ff ff ff f0 ff 40 10 eb be 55 89 e5 57 89 d7 56 89 c6 53 <8b> 50 54 83 fa 10 72 55 8b 9e 9c 00 00 00 31 c9 8b 03 83 f8 0f

Reported by Athanasius <[email protected]>

---
 net/ipv4/inet_diag.c |    4 ++++
 1 file changed, 4 insertions(+)
net/ipv4/inet_diag.c +4 -0
@@ -836,12 +836,16 @@ static int inet_diag_rcv_msg(struct sk_b
 	return inet_diag_get_exact(skb, nlh);
 }
 
+static DEFINE_MUTEX(inet_diag_mutex);
+
 static void inet_diag_rcv(struct sock *sk, int len)
 {
 	unsigned int qlen = 0;
 
 	do {
+		mutex_lock(&inet_diag_mutex);
 		netlink_run_queue(sk, &qlen, &inet_diag_rcv_msg);
+		mutex_unlock(&inet_diag_mutex);
 	} while (qlen);
 }
 
#38 lore raw

Re: [37/50] Fix inet_diag OOPS.

Quoted 4 lines · Greg KH

netlink_run_queue() doesn't handle multiple processes processing the queue concurrently. Serialize queue processing in inet_diag to fix a oops in netlink_rcv_skb caused by netlink_run_queue passing a NULL for the skb.

I just got this one on 2.6.23-RC1, looks the same to me but posting the oops anyway to doublecheck.

(is it possible to get gmail not to mangle code/patches/oopses without attaching?)

[1015205.245213] Unable to handle kernel NULL pointer dereference at 0000000000000068 RIP: 
[1015205.245221]  [<ffffffff804eb6a5>] netlink_run_queue+0xb2/0x104
[1015205.245233] PGD a449067 PUD 2e803067 PMD 0 
[1015205.245237] Oops: 0000 [1] SMP 
[1015205.245240] CPU 1 
[1015205.245242] Modules linked in: tcp_diag inet_diag radeon drm iscsi_tcp libiscsi scsi_transport_iscsi ipv6 fuse eeprom tsdev usbhid ff_memless snd_intel8x0 snd_ac97_codec fan ac97_bus snd_pcm thermal i2c_nforce2 k8temp ohci1394 ehci_hcd snd_timer ohci_hcd serio_raw pcspkr rtc hwmon button processor snd snd_page_alloc usbcore i2c_core ide_generic
[1015205.245267] Pid: 26036, comm: identd Not tainted 2.6.23-rc3 #1
[1015205.245269] RIP: 0010:[<ffffffff804eb6a5>]  [<ffffffff804eb6a5>] netlink_run_queue+0xb2/0x104
[1015205.245274] RSP: 0018:ffff81002a1d5bf8  EFLAGS: 00010202
[1015205.245276] RAX: 0000000000000000 RBX: ffff81003d94f600 RCX: ffff81000c9fe3c0
[1015205.245278] RDX: 0000000000000009 RSI: 0000000000000202 RDI: ffff81003d91d0c4
[1015205.245281] RBP: 0000000000000000 R08: ffff8100059813c0 R09: ffff81003d91d000
[1015205.245283] R10: 000000007fffffff R11: ffff81000c9fe3c0 R12: ffff81002a1d5c44
[1015205.245286] R13: ffff81003d91d000 R14: ffff81003d91d0b0 R15: ffffffff8819aa95
[1015205.245289] FS:  0000000041001950(0063) GS:ffff81003faaaa40(0000) knlGS:00000000f7415a10
[1015205.245291] CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
[1015205.245294] CR2: 0000000000000068 CR3: 000000002c973000 CR4: 00000000000006e0
[1015205.245296] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[1015205.245298] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
[1015205.245301] Process identd (pid: 26036, threadinfo ffff81002a1d4000, task ffff81002a3d50c0)
[1015205.245303] Stack:  0000000000000000 ffff81003d91d000 000000000000004c ffff81001f219400
[1015205.245308]  ffff81003d94f600 ffff81002a1d5d60 0000000000000000 ffffffff8819a024
[1015205.245311]  0000000000000292 00000001804cffe4 ffff81003d91d000 ffffffff804ebb37
[1015205.245315] Call Trace:
[1015205.245323]  [<ffffffff8819a024>] :inet_diag:inet_diag_rcv+0x24/0x2f
[1015205.245328]  [<ffffffff804ebb37>] netlink_data_ready+0x12/0x50
[1015205.245331]  [<ffffffff804ea93d>] netlink_sendskb+0x23/0x3d
[1015205.245334]  [<ffffffff804ebb12>] netlink_sendmsg+0x2a9/0x2bc
[1015205.245342]  [<ffffffff8022841c>] __wake_up_common+0x3e/0x68
[1015205.245348]  [<ffffffff804ca69c>] sock_aio_write+0x110/0x128
[1015205.245357]  [<ffffffff802654bd>] __pagevec_lru_add_active+0xd1/0xe1
[1015205.245363]  [<ffffffff80284388>] do_sync_write+0xc9/0x10c
[1015205.245371]  [<ffffffff80243546>] autoremove_wake_function+0x0/0x2e
[1015205.245380]  [<ffffffff80284b60>] vfs_write+0xe1/0x157
[1015205.245385]  [<ffffffff802850ab>] sys_write+0x45/0x6e
[1015205.245390]  [<ffffffff8020b3ce>] system_call+0x7e/0x83
[1015205.245396] 
[1015205.245397] 
[1015205.245397] Code: 8b 55 68 83 fa 0f 77 93 48 89 ef e8 ad 50 fe ff 41 ff 0c 24 
[1015205.245405] RIP  [<ffffffff804eb6a5>] netlink_run_queue+0xb2/0x104
[1015205.245409]  RSP <ffff81002a1d5bf8>
[1015205.245410] CR2: 0000000000000068
#39 lore raw

Re: [37/50] Fix inet_diag OOPS.

Quoted 8 lines · Dan Merillat
Quoted 4 lines · Greg KH

netlink_run_queue() doesn't handle multiple processes processing the queue concurrently. Serialize queue processing in inet_diag to fix a oops in netlink_rcv_skb caused by netlink_run_queue passing a NULL for the skb.

Quoted 7 lines

I just got this one on 2.6.23-RC1, looks the same to me but posting the oops anyway to doublecheck.

[1015205.245269] RIP: 0010:[<ffffffff804eb6a5>]  [<ffffffff804eb6a5>] netlink_run_queue+0xb2/0x104
...
[1015205.245315] Call Trace:
[1015205.245323]  [<ffffffff8819a024>] :inet_diag:inet_diag_rcv+0x24/0x2f

Yes, this is the same oops. Its fixed in the current -rc.

author
#40 lore raw

PATCH 38/50 Fix IPV6 append OOPS.

In reply to Greg KH

From: YOSHIFUJI Hideaki <[email protected]>

commit e1f52208bb968291f7d9142eff60b62984b4a511 in mainline.

[IPv6]: Fix NULL pointer dereference in ip6_flush_pending_frames

Some of skbs in sk->write_queue do not have skb->dst because we do not fill skb->dst when we allocate new skb in append_data().

BTW, I think we may not need to (or we should not) increment some stats when using corking; if 100 sendmsg() (with MSG_MORE) result in 2 packets, how many should we increment?

If 100, we should set skb->dst for every queued skbs.

If 1 (or 2 (*)), we increment the stats for the first queued skb and we should just skip incrementing OutDiscards for the rest of queued skbs, adn we should also impelement this semantics in other places; e.g., we should increment other stats just once, not 100 times.

*: depends on the place we are discarding the datagram.

I guess should just increment by 1 (or 2).

---
 net/ipv6/ip6_output.c |    5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
net/ipv6/ip6_output.c +3 -2
@@ -1423,8 +1423,9 @@ void ip6_flush_pending_frames(struct soc
 	struct sk_buff *skb;
 
 	while ((skb = __skb_dequeue_tail(&sk->sk_write_queue)) != NULL) {
-		IP6_INC_STATS(ip6_dst_idev(skb->dst),
-			      IPSTATS_MIB_OUTDISCARDS);
+		if (skb->dst)
+			IP6_INC_STATS(ip6_dst_idev(skb->dst),
+				      IPSTATS_MIB_OUTDISCARDS);
 		kfree_skb(skb);
 	}
 
author
#41 lore raw

PATCH 39/50 Fix IPSEC AH4 options handling

In reply to Greg KH

From: Nick Bowler <[email protected]>

commit 8ee4f391831cb96916a8e8a05f04b1c1d7dd30d8 in mainline.

In testing our ESP/AH offload hardware, I discovered an issue with how AH handles mutable fields in IPv4. RFC 4302 (AH) states the following on the subject:

For IPv4, the entire option is viewed as a unit; so even though the type and length fields within most options are immutable in transit, if an option is classified as mutable, the entire option is zeroed for ICV computation purposes.

The current implementation does not zero the type and length fields, resulting in authentication failures when communicating with hosts that do (i.e. FreeBSD).

I have tested record route and timestamp options (ping -R and ping -T) on a small network involving Windows XP, FreeBSD 6.2, and Linux hosts, with one router. In the presence of these options, the FreeBSD and Linux hosts (with the patch or with the hardware) can communicate. The Windows XP host simply fails to accept these packets with or without the patch.

I have also been trying to test source routing options (using traceroute -g), but haven't had much luck getting this option to work *without* AH, let alone with.

---
 net/ipv4/ah4.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
net/ipv4/ah4.c +1 -1
@@ -46,7 +46,7 @@ static int ip_clear_mutable_options(stru
 			memcpy(daddr, optptr+optlen-4, 4);
 			/* Fall through */
 		default:
-			memset(optptr+2, 0, optlen-2);
+			memset(optptr, 0, optlen);
 		}
 		l -= optlen;
 		optptr += optlen;
author
#42 lore raw

PATCH 40/50 Fix ipv6 double-sock-release with MSG_CONFIRM

In reply to Greg KH

From: YOSHIFUJI Hideaki <[email protected]>

commit 3ef9d943d26dea764f4fecf3767001c90b778b0c in mainline

---
 net/ipv6/raw.c |    3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)
net/ipv6/raw.c +1 -2
@@ -858,11 +858,10 @@ back_from_confirm:
 			ip6_flush_pending_frames(sk);
 		else if (!(msg->msg_flags & MSG_MORE))
 			err = rawv6_push_pending_frames(sk, &fl, rp);
+		release_sock(sk);
 	}
 done:
 	dst_release(dst);
-	if (!inet->hdrincl)
-		release_sock(sk);
 out:
 	fl6_sock_release(flowlabel);
 	return err<0?err:len;
author
#43 lore raw

PATCH 41/50 : Fix IPV6 DAD handling

In reply to Greg KH

From: Denis V. Lunev <[email protected]>

commit 9e3be4b34364a670bd6e57d2e8c3caabdd8d89f8 in mainline

addrconf_dad_failure calls addrconf_dad_stop which takes referenced address and drops the count. So, in6_ifa_put perrformed at out: is extra. This results in message: "Freeing alive inet6 address" and not released dst entries.

---
 net/ipv6/ndisc.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
net/ipv6/ndisc.c +1 -1
@@ -736,7 +736,7 @@ static void ndisc_recv_ns(struct sk_buff
 				 * so fail our DAD process
 				 */
 				addrconf_dad_failure(ifp);
-				goto out;
+				return;
 			} else {
 				/*
 				 * This is not a dad solicitation.
author
#44 lore raw

PATCH 42/50 Fix ipv6 source address handling.

In reply to Greg KH

From: Jiri Kosina <[email protected]>

commit 6ae5f983cf8de769214d2d9e8a783c881eccd4cd in mainline

The commit 95c385 broke proper source address selection for cases in which there is a address which is makred 'deprecated'. The commit mistakenly changed ifa->flags to ifa_result->flags (probably copy/paste error from a few lines above) in the 'Rule 3' address selection code.

The patch restores the previous RFC-compliant behavior.

---
 net/ipv6/addrconf.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
net/ipv6/addrconf.c +1 -1
@@ -1021,7 +1021,7 @@ int ipv6_dev_get_saddr(struct net_device
 				hiscore.rule++;
 			}
 			if (ipv6_saddr_preferred(score.addr_type) ||
-			   (((ifa_result->flags &
+			   (((ifa->flags &
 			    (IFA_F_DEPRECATED|IFA_F_OPTIMISTIC)) == 0))) {
 				score.attrs |= IPV6_SADDR_SCORE_PREFERRED;
 				if (!(hiscore.attrs & IPV6_SADDR_SCORE_PREFERRED)) {
#45 lore raw

Re: [42/50] Fix ipv6 source address handling.

can't we also decrease the number of brackets here?

net/ipv6/addrconf.c +1 -1
@@ -1021,7 +1021,7 @@ int ipv6_dev_get_saddr(struct net_device
 				hiscore.rule++;
 			}
 			if (ipv6_saddr_preferred(score.addr_type) ||
-			   (((ifa_result->flags &
+			   (((ifa->flags &
 			    (IFA_F_DEPRECATED|IFA_F_OPTIMISTIC)) == 0))) {
 

make this like this
if (ipv6_saddr_preferred(score.addr_type) ||

			   (ifa->flags &

(IFA_F_DEPRECATED|IFA_F_OPTIMISTIC)) == 0) {

or even for clarity's sake:
if (ipv6_saddr_preferred(score.addr_type) ||

			   (ifa->flags & (IFA_F_DEPRECATED|IFA_F_OPTIMISTIC)) == 0) {
author
#46 lore raw

PATCH 43/50 Fix oops in vlan and bridging code

In reply to Greg KH

From: Evgeniy Polyakov <[email protected]>

commit 8c7b43a2e58baa24002fa2b266d9a5007bc52a40 in mainline

I tried to preserve bridging code as it was before, but logic is quite strange - I think we should free skb on error, since it is already unshared and thus will just leak.

Herbert Xu states:

Review

Quoted 2 lines
(quoted diff) +2 -0
+	if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
+		goto out;

If this happens it'll be a double-free on skb since we'll return NF_DROP which makes the caller free it too.

We could return NF_STOLEN to prevent that but I'm not sure whether that's correct netfilter semantics. Patrick, could you please make a call on this?

Patrick McHardy states:

NF_STOLEN should work fine here.

---
 net/8021q/vlan_dev.c      |   12 +++++++++++-
 net/bridge/br_netfilter.c |   12 +++++++-----
 2 files changed, 18 insertions(+), 6 deletions(-)
net/8021q/vlan_dev.c +11 -1
@@ -116,12 +116,22 @@ int vlan_skb_recv(struct sk_buff *skb, s
 		  struct packet_type* ptype, struct net_device *orig_dev)
 {
 	unsigned char *rawp = NULL;
-	struct vlan_hdr *vhdr = (struct vlan_hdr *)(skb->data);
+	struct vlan_hdr *vhdr;
 	unsigned short vid;
 	struct net_device_stats *stats;
 	unsigned short vlan_TCI;
 	__be16 proto;
 
+	if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
+		return -1;
+
+	if (unlikely(!pskb_may_pull(skb, VLAN_HLEN))) {
+		kfree_skb(skb);
+		return -1;
+	}
+
+	vhdr = (struct vlan_hdr *)(skb->data);
+
 	/* vlan_TCI = ntohs(get_unaligned(&vhdr->h_vlan_TCI)); */
 	vlan_TCI = ntohs(vhdr->h_vlan_TCI);
 
net/bridge/br_netfilter.c +7 -5
@@ -509,8 +509,14 @@ static unsigned int br_nf_pre_routing(un
 				      int (*okfn)(struct sk_buff *))
 {
 	struct iphdr *iph;
-	__u32 len;
 	struct sk_buff *skb = *pskb;
+	__u32 len = nf_bridge_encap_header_len(skb);
+
+	if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
+		return NF_STOLEN;
+
+	if (unlikely(!pskb_may_pull(skb, len)))
+		goto out;
 
 	if (skb->protocol == htons(ETH_P_IPV6) || IS_VLAN_IPV6(skb) ||
 	    IS_PPPOE_IPV6(skb)) {
@@ -518,8 +524,6 @@ static unsigned int br_nf_pre_routing(un
 		if (!brnf_call_ip6tables)
 			return NF_ACCEPT;
 #endif
-		if ((skb = skb_share_check(*pskb, GFP_ATOMIC)) == NULL)
-			goto out;
 		nf_bridge_pull_encap_header_rcsum(skb);
 		return br_nf_pre_routing_ipv6(hook, skb, in, out, okfn);
 	}
@@ -532,8 +536,6 @@ static unsigned int br_nf_pre_routing(un
 	    !IS_PPPOE_IP(skb))
 		return NF_ACCEPT;
 
-	if ((skb = skb_share_check(*pskb, GFP_ATOMIC)) == NULL)
-		goto out;
 	nf_bridge_pull_encap_header_rcsum(skb);
 
 	if (!pskb_may_pull(skb, sizeof(struct iphdr)))
author
#47 lore raw

PATCH 44/50 Fix tc_ematch kbuild

In reply to Greg KH

From: Stephen Hemminger <[email protected]>

commit 09d74cdd88a59a18f2ad7cfa0b6045ed1817b632 in mainline.

Subject: [44/50] [PATCH] [KBUILD]: Sanitize tc_ematch headers.

The headers in tc_ematch are used by iproute2, so these headers should be processed.

---
 include/linux/Kbuild |    1 +
 1 file changed, 1 insertion(+)
include/linux/Kbuild +1 -0
@@ -7,6 +7,7 @@ header-y += raid/
 header-y += spi/
 header-y += sunrpc/
 header-y += tc_act/
+header-y += tc_ematch/
 header-y += netfilter/
 header-y += netfilter_arp/
 header-y += netfilter_bridge/
author
#48 lore raw

PATCH 45/50 Handle snd_una in tcp_cwnd_down()

In reply to Greg KH

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

commit 6ee8009e38006da81d2a53da1aaa27365552553e in mainline

Subject: [45/50] [PATCH 1/1] [TCP]: Also handle snd_una changes in tcp_cwnd_down

tcp_cwnd_down must check for it too as it should be conservative in case of collapse stuff and also when receiver is trying to lie (though it wouldn't be successful anyway).

Note:
- Separated also is_dupack and do_lost in fast_retransalert
* Much cleaner look-and-feel now
* This time it really fixes cumulative ACK + many new SACK blocks recovery entry (I claimed this fixes with last patch but it wasn't). TCP will now call tcp_update_scoreboard regardless of is_dupack when in recovery as long as there is enough fackets_out.
- Introduce FLAG_SND_UNA_ADVANCED
* Some prior_snd_una arguments are unnecessary after it
- Added helper FLAG_ANY_PROGRESS to avoid long FLAG...|FLAG... constructs

This is a reduced version of a mainline patch.

---
 net/ipv4/tcp_input.c |   18 +++++++++++-------
 1 file changed, 11 insertions(+), 7 deletions(-)
net/ipv4/tcp_input.c +11 -7
@@ -102,11 +102,13 @@ int sysctl_tcp_abc __read_mostly;
 #define FLAG_DATA_LOST		0x80 /* SACK detected data lossage.		*/
 #define FLAG_SLOWPATH		0x100 /* Do not skip RFC checks for window update.*/
 #define FLAG_ONLY_ORIG_SACKED	0x200 /* SACKs only non-rexmit sent before RTO */
+#define FLAG_SND_UNA_ADVANCED	0x400 /* Snd_una was changed (!= FLAG_DATA_ACKED) */
 
 #define FLAG_ACKED		(FLAG_DATA_ACKED|FLAG_SYN_ACKED)
 #define FLAG_NOT_DUP		(FLAG_DATA|FLAG_WIN_UPDATE|FLAG_ACKED)
 #define FLAG_CA_ALERT		(FLAG_DATA_SACKED|FLAG_ECE)
 #define FLAG_FORWARD_PROGRESS	(FLAG_ACKED|FLAG_DATA_SACKED)
+#define FLAG_ANY_PROGRESS	(FLAG_FORWARD_PROGRESS|FLAG_SND_UNA_ADVANCED)
 
 #define IsReno(tp) ((tp)->rx_opt.sack_ok == 0)
 #define IsFack(tp) ((tp)->rx_opt.sack_ok & 2)
@@ -1856,7 +1858,7 @@ static void tcp_cwnd_down(struct sock *s
 	struct tcp_sock *tp = tcp_sk(sk);
 	int decr = tp->snd_cwnd_cnt + 1;
 
-	if ((flag&FLAG_FORWARD_PROGRESS) ||
+	if ((flag&FLAG_ANY_PROGRESS) ||
 	    (IsReno(tp) && !(flag&FLAG_NOT_DUP))) {
 		tp->snd_cwnd_cnt = decr&1;
 		decr >>= 1;
@@ -2112,10 +2114,9 @@ tcp_fastretrans_alert(struct sock *sk, u
 {
 	struct inet_connection_sock *icsk = inet_csk(sk);
 	struct tcp_sock *tp = tcp_sk(sk);
-	int is_dupack = (tp->snd_una == prior_snd_una &&
-			 (!(flag&FLAG_NOT_DUP) ||
-			  ((flag&FLAG_DATA_SACKED) &&
-			   (tp->fackets_out > tp->reordering))));
+	int is_dupack = !(flag&(FLAG_SND_UNA_ADVANCED|FLAG_NOT_DUP));
+	int do_lost = is_dupack || ((flag&FLAG_DATA_SACKED) &&
+				    (tp->fackets_out > tp->reordering));
 
 	/* Some technical things:
 	 * 1. Reno does not count dupacks (sacked_out) automatically. */
@@ -2199,7 +2200,7 @@ tcp_fastretrans_alert(struct sock *sk, u
 			int acked = prior_packets - tp->packets_out;
 			if (IsReno(tp))
 				tcp_remove_reno_sacks(sk, acked);
-			is_dupack = tcp_try_undo_partial(sk, acked);
+			do_lost = tcp_try_undo_partial(sk, acked);
 		}
 		break;
 	case TCP_CA_Loss:
@@ -2264,7 +2265,7 @@ tcp_fastretrans_alert(struct sock *sk, u
 		tcp_set_ca_state(sk, TCP_CA_Recovery);
 	}
 
-	if (is_dupack || tcp_head_timedout(sk))
+	if (do_lost || tcp_head_timedout(sk))
 		tcp_update_scoreboard(sk);
 	tcp_cwnd_down(sk, flag);
 	tcp_xmit_retransmit_queue(sk);
@@ -2774,6 +2775,9 @@ static int tcp_ack(struct sock *sk, stru
 	if (before(ack, prior_snd_una))
 		goto old_ack;
 
+	if (after(ack, prior_snd_una))
+		flag |= FLAG_SND_UNA_ADVANCED;
+
 	if (sysctl_tcp_abc) {
 		if (icsk->icsk_ca_state < TCP_CA_CWR)
 			tp->bytes_acked += ack - prior_snd_una;
author
#49 lore raw

PATCH 46/50 Fix TCP DSACK cwnd handling

In reply to Greg KH

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

commit 49ff4bb4cd4c04acf8f9e3d3ec2148305a1db445 in mainline.

[TCP]: DSACK signals data receival, be conservative

In case a DSACK is received, it's better to lower cwnd as it's a sign of data receival.

---
 net/ipv4/tcp_input.c |    5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
net/ipv4/tcp_input.c +4 -1
@@ -103,6 +103,7 @@ int sysctl_tcp_abc __read_mostly;
 #define FLAG_SLOWPATH		0x100 /* Do not skip RFC checks for window update.*/
 #define FLAG_ONLY_ORIG_SACKED	0x200 /* SACKs only non-rexmit sent before RTO */
 #define FLAG_SND_UNA_ADVANCED	0x400 /* Snd_una was changed (!= FLAG_DATA_ACKED) */
+#define FLAG_DSACKING_ACK	0x800 /* SACK blocks contained DSACK info */
 
 #define FLAG_ACKED		(FLAG_DATA_ACKED|FLAG_SYN_ACKED)
 #define FLAG_NOT_DUP		(FLAG_DATA|FLAG_WIN_UPDATE|FLAG_ACKED)
@@ -966,12 +967,14 @@ tcp_sacktag_write_queue(struct sock *sk,
 
 	/* Check for D-SACK. */
 	if (before(ntohl(sp[0].start_seq), TCP_SKB_CB(ack_skb)->ack_seq)) {
+		flag |= FLAG_DSACKING_ACK;
 		found_dup_sack = 1;
 		tp->rx_opt.sack_ok |= 4;
 		NET_INC_STATS_BH(LINUX_MIB_TCPDSACKRECV);
 	} else if (num_sacks > 1 &&
 			!after(ntohl(sp[0].end_seq), ntohl(sp[1].end_seq)) &&
 			!before(ntohl(sp[0].start_seq), ntohl(sp[1].start_seq))) {
+		flag |= FLAG_DSACKING_ACK;
 		found_dup_sack = 1;
 		tp->rx_opt.sack_ok |= 4;
 		NET_INC_STATS_BH(LINUX_MIB_TCPDSACKOFORECV);
@@ -1858,7 +1861,7 @@ static void tcp_cwnd_down(struct sock *s
 	struct tcp_sock *tp = tcp_sk(sk);
 	int decr = tp->snd_cwnd_cnt + 1;
 
-	if ((flag&FLAG_ANY_PROGRESS) ||
+	if ((flag&(FLAG_ANY_PROGRESS|FLAG_DSACKING_ACK)) ||
 	    (IsReno(tp) && !(flag&FLAG_NOT_DUP))) {
 		tp->snd_cwnd_cnt = decr&1;
 		decr >>= 1;
author
#50 lore raw

PATCH 47/50 Fix datagram recvmsg NULL iov handling regression.

In reply to Greg KH

From: Herbert Xu <[email protected]>

commit ef8aef55ce61fd0e2af798695f7386ac756ae1e7 in mainline

Subject: [47/50] [PATCH] [NET]: Do not dereference iov if length is zero

When msg_iovlen is zero we shouldn't try to dereference msg_iov. Right now the only thing that tries to do so is skb_copy_and_csum_datagram_iovec. Since the total length should also be zero if msg_iovlen is zero, it's sufficient to check the total length there and simply return if it's zero.

---
 net/core/datagram.c |    3 +++
 1 file changed, 3 insertions(+)
net/core/datagram.c +3 -0
@@ -450,6 +450,9 @@ int skb_copy_and_csum_datagram_iovec(str
 	__wsum csum;
 	int chunk = skb->len - hlen;
 
+	if (!chunk)
+		return 0;
+
 	/* Skip filled elements.
 	 * Pretty silly, look at memcpy_toiovec, though 8)
 	 */
author
#51 lore raw

PATCH 48/50 Fix pktgen src_mac handling.

In reply to Greg KH

From: Adit Ranadive <[email protected]>

commit ce5d0b47f13f83dfb9fbb8ac91adad7120747aaf in mainline

Subject: [48/50] [PATCH] [PKTGEN]: srcmac fix

---
 net/core/pktgen.c |   10 ++++++++++
 1 file changed, 10 insertions(+)
net/core/pktgen.c +10 -0
@@ -111,6 +111,9 @@
  *
  * 802.1Q/Q-in-Q support by Francesco Fondelli (FF) <[email protected]>
  *
+ * Fixed src_mac command to set source mac of packet to value specified in
+ * command by Adit Ranadive <[email protected]>
+ *
  */
 #include <linux/sys.h>
 #include <linux/types.h>
@@ -1415,8 +1418,11 @@ static ssize_t pktgen_if_write(struct fi
 	}
 	if (!strcmp(name, "src_mac")) {
 		char *v = valstr;
+		unsigned char old_smac[ETH_ALEN];
 		unsigned char *m = pkt_dev->src_mac;
 
+		memcpy(old_smac, pkt_dev->src_mac, ETH_ALEN);
+
 		len = strn_len(&user_buffer[i], sizeof(valstr) - 1);
 		if (len < 0) {
 			return len;
@@ -1445,6 +1451,10 @@ static ssize_t pktgen_if_write(struct fi
 			}
 		}
 
+		/* Set up Src MAC */
+		if (compare_ether_addr(old_smac, pkt_dev->src_mac))
+			memcpy(&(pkt_dev->hh[6]), pkt_dev->src_mac, ETH_ALEN);
+
 		sprintf(pg_result, "OK: srcmac");
 		return count;
 	}
author
#52 lore raw

PATCH 49/50 Fix sparc64 v100 platform booting.

In reply to Greg KH

From: David Miller <[email protected]>

commit 2cc7345ff71b27b5ac99e49ad7de39360042f601 in mainline

Subject: [49/50] [PATCH] [SPARC64]: Fix booting on V100 systems.

On the root PCI bus, the OBP device tree lists device 3 twice. Once as 'pm' and once as 'lomp'.

Everything goes downhill from there.

Ignore the second instance to workaround this.

Thanks to K�vedi_Kriszti�n for the bug report and
testing the fix.

---
 arch/sparc64/kernel/pci.c |   13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)
arch/sparc64/kernel/pci.c +12 -1
@@ -751,7 +751,7 @@ static void __devinit pci_of_scan_bus(st
 {
 	struct device_node *child;
 	const u32 *reg;
-	int reglen, devfn;
+	int reglen, devfn, prev_devfn;
 	struct pci_dev *dev;
 
 	if (ofpci_verbose)
@@ -759,14 +759,25 @@ static void __devinit pci_of_scan_bus(st
 		       node->full_name, bus->number);
 
 	child = NULL;
+	prev_devfn = -1;
 	while ((child = of_get_next_child(node, child)) != NULL) {
 		if (ofpci_verbose)
 			printk("  * %s\n", child->full_name);
 		reg = of_get_property(child, "reg", &reglen);
 		if (reg == NULL || reglen < 20)
 			continue;
+
 		devfn = (reg[0] >> 8) & 0xff;
 
+		/* This is a workaround for some device trees
+		 * which list PCI devices twice.  On the V100
+		 * for example, device number 3 is listed twice.
+		 * Once as "pm" and once again as "lomp".
+		 */
+		if (devfn == prev_devfn)
+			continue;
+		prev_devfn = devfn;
+
 		/* create a new pci_dev for this device */
 		dev = of_create_pci_dev(pbm, child, bus, devfn, 0);
 		if (!dev)
author
#53 lore raw

PATCH 50/50 bcm43xx: Fix cancellation of work queue crashes

In reply to Greg KH

From: Larry Finger <[email protected]>

port of 3f7086978fc0193eff24a77d8b57ac4debc088fa from mainline.

A crash upon booting that is caused by bcm43xx has been reported [1] and found to be due to a work queue being reinitialized while work on that queue is still pending. This fix modifies the shutdown of work queues and prevents periodic work from being requeued during shutdown. With this patch, no more crashes on reboot were observed by the original reporter. I do not get that particular failure on my system; however, when running a large number of ifdown/ifup sequences, my system would kernel panic with the 'caps lock' light blinking at roughly a 1 Hz rate. In addition, there were infrequent failures in the firmware that resulted in 'IRQ READY TIMEOUT' errors. With this patch, no more of the first type of failure occur, and incidence of the second type is greatly reduced.

[1] http://bugzilla.kernel.org/show_bug.cgi?id=8937

---
 drivers/net/wireless/bcm43xx/bcm43xx_main.c  |   28 +++++++++++++++++++--------
 drivers/net/wireless/bcm43xx/bcm43xx_main.h  |    2 -
 drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c |    2 -
 3 files changed, 22 insertions(+), 10 deletions(-)
drivers/net/wireless/bcm43xx/bcm43xx_main.c +20 -8
@@ -3183,6 +3183,9 @@ static void bcm43xx_periodic_work_handle
 	unsigned long orig_trans_start = 0;
 
 	mutex_lock(&bcm->mutex);
+	/* keep from doing and rearming periodic work if shutting down */
+	if (bcm43xx_status(bcm) == BCM43xx_STAT_UNINIT)
+		goto unlock_mutex;
 	if (unlikely(bcm->periodic_state % 60 == 0)) {
 		/* Periodic work will take a long time, so we want it to
 		 * be preemtible.
@@ -3228,14 +3231,10 @@ static void bcm43xx_periodic_work_handle
 	mmiowb();
 	bcm->periodic_state++;
 	spin_unlock_irqrestore(&bcm->irq_lock, flags);
+unlock_mutex:
 	mutex_unlock(&bcm->mutex);
 }
 
-void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm)
-{
-	cancel_rearming_delayed_work(&bcm->periodic_work);
-}
-
 void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm)
 {
 	struct delayed_work *work = &bcm->periodic_work;
@@ -3285,6 +3284,14 @@ static int bcm43xx_rng_init(struct bcm43
 	return err;
 }
 
+void bcm43xx_cancel_work(struct bcm43xx_private *bcm)
+{
+	/* The system must be unlocked when this routine is entered.
+	 * If not, the next 2 steps may deadlock */
+	cancel_work_sync(&bcm->restart_work);
+	cancel_rearming_delayed_work(&bcm->periodic_work);
+}
+
 static int bcm43xx_shutdown_all_wireless_cores(struct bcm43xx_private *bcm)
 {
 	int ret = 0;
@@ -3321,7 +3328,12 @@ static void bcm43xx_free_board(struct bc
 {
 	bcm43xx_rng_exit(bcm);
 	bcm43xx_sysfs_unregister(bcm);
-	bcm43xx_periodic_tasks_delete(bcm);
+
+	mutex_lock(&(bcm)->mutex);
+	bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT);
+	mutex_unlock(&(bcm)->mutex);
+
+	bcm43xx_cancel_work(bcm);
 
 	mutex_lock(&(bcm)->mutex);
 	bcm43xx_shutdown_all_wireless_cores(bcm);
@@ -4018,7 +4030,7 @@ static int bcm43xx_net_stop(struct net_d
 	err = bcm43xx_disable_interrupts_sync(bcm);
 	assert(!err);
 	bcm43xx_free_board(bcm);
-	flush_scheduled_work();
+	bcm43xx_cancel_work(bcm);
 
 	return 0;
 }
@@ -4150,9 +4162,9 @@ static void bcm43xx_chip_reset(struct wo
 	struct bcm43xx_phyinfo *phy;
 	int err = -ENODEV;
 
+	bcm43xx_cancel_work(bcm);
 	mutex_lock(&(bcm)->mutex);
 	if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
-		bcm43xx_periodic_tasks_delete(bcm);
 		phy = bcm43xx_current_phy(bcm);
 		err = bcm43xx_select_wireless_core(bcm, phy->type);
 		if (!err)
drivers/net/wireless/bcm43xx/bcm43xx_main.h +1 -1
@@ -122,7 +122,7 @@ void bcm43xx_wireless_core_reset(struct 
 void bcm43xx_mac_suspend(struct bcm43xx_private *bcm);
 void bcm43xx_mac_enable(struct bcm43xx_private *bcm);
 
-void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm);
+void bcm43xx_cancel_work(struct bcm43xx_private *bcm);
 void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm);
 
 void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason);
drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c +1 -1
@@ -327,7 +327,7 @@ static ssize_t bcm43xx_attr_phymode_stor
 		goto out;
 	}
 
-	bcm43xx_periodic_tasks_delete(bcm);
+	bcm43xx_cancel_work(bcm);
 	mutex_lock(&(bcm)->mutex);
 	err = bcm43xx_select_wireless_core(bcm, phytype);
 	if (!err)
author
#54 lore raw
In reply to Greg KH
Quoted 1 line · Greg KH

This is the start of the stable review cycle for the 2.6.22.8 release.

A tarball of the patches can be found at:

	kernel.org/pub/linux/kernel/v2.6/stable-testing/patch-2.6.22.8-rc1.gz

thanks,

greg k-h

#56 lore raw
Quoted 1 line

(to make it easier for people to click)

actually, it's not a tarball either... am I seeing something stale or perhaps the result of slow 'kernel.org replication?

author
#57 lore raw
Quoted 4 lines · Chris Wedgwood
Quoted 1 line

(to make it easier for people to click)

actually, it's not a tarball either... am I seeing something stale or perhaps the result of slow 'kernel.org replication?

It's not a tarball, just a gzip file. And it might be the kernel.org replication, I see the file correctly on the "master" site. Give it a bit of time...

thanks,

greg k-h

author
#58 lore raw
In reply to Chris Wedgwood
Quoted 7 lines · Chris Wedgwood
Quoted 2 lines · Greg KH

A tarball of the patches can be found at:

	kernel.org/pub/linux/kernel/v2.6/stable-testing/patch-2.6.22.8-rc1.gz
                                                ^^^^^^^

s/testing/review/

Argh, that's what I get for typing that from memory, thanks for correcting this.

greg k-h