Skip to contentSkip to conversation

2.6.20.16 -stable review

PATCH In review Willy Tarreau 3 participants 29 messages Aug 11, 2007 – Aug 12, 2007

Subsystems (12)
lore
Share & tools
lore
#0 lore raw

cover 2.6.20.16 -stable review

I proposed Chris and Greg to continue issuing a few more 2.6.20 releases during the time needed for 2.6.21 and 2.6.22 to show a significant drop in their patch rates, which hopefully will be just a matter of a few releases.

My goal is *not* to do all the hard work they do, but just to backport from their patches those which are meaningful for 2.6.20. For this reason, 2.6.20 releases will always be slightly late and should not contain patches not merged in more recent releases.

My intent with this version is to catch up with 2.6.21.7. Other patches are already pending for future releases, but one thing at a time. I'm trying to follow the same review/release process, so 28 patches will be posted for review in response to this message.

If some people think it's useless to repost individual patches that have already been reviewed in more recent versions, I'm open to adapting the process (eg: switch to one mail for -rc and one for release like Adrian does with 2.6.16).

The rolled up patch can be found here :
ftp.kernel.org/pub/linux/kernel/v2.6/stable-review/patch-2.6.20.16-rc1.gz

Responses should be made by August 13, 2007, 20:00:00 UTC. Anything received after that time might be too late.

Thanks,
Willy

--

#1 lore raw

PATCH 1/28 i386: Fix K8/core2 oprofile on multiple CPUs

Only try to allocate MSRs once instead of for every CPU.

This assumes the MSRs are the same on all CPUs which is currently true. P4-HT is a special case for different SMT threads, but the code always saves/restores all MSRs so it works identical.

---
 arch/i386/oprofile/nmi_int.c |    9 ++++++++-
 1 files changed, 8 insertions(+), 1 deletions(-)
arch/i386/oprofile/nmi_int.c +8 -1
index 3700eef..be4a9a8 100644
@@ -131,7 +131,6 @@ static void nmi_save_registers(void * dummy)
 {
 	int cpu = smp_processor_id();
 	struct op_msrs * msrs = &cpu_msrs[cpu];
-	model->fill_in_addresses(msrs);
 	nmi_cpu_save_registers(msrs);
 }
 
@@ -195,6 +194,7 @@ static struct notifier_block profile_exceptions_nb = {
 static int nmi_setup(void)
 {
 	int err=0;
+	int cpu;
 
 	if (!allocate_msrs())
 		return -ENOMEM;
@@ -207,6 +207,13 @@ static int nmi_setup(void)
 	/* We need to serialize save and setup for HT because the subset
 	 * of msrs are distinct for save and setup operations
 	 */
+
+	/* Assume saved/restored counters are the same on all CPUs */
+	model->fill_in_addresses(&cpu_msrs[0]);
+	for_each_possible_cpu (cpu) {
+		if (cpu != 0)
+			cpu_msrs[cpu] = cpu_msrs[0];
+	}
 	on_each_cpu(nmi_save_registers, NULL, 0, 1);
 	on_each_cpu(nmi_cpu_setup, NULL, 0, 1);
 	nmi_enabled = 1;
Signature · 3 lines
1.5.2.4

-- 
#2 lore raw

PATCH 2/28 md: Avoid overflow in raid0 calculation with large components.

In reply to Willy Tarreau

If a raid0 has a component device larger than 4TB, and is accessed on a 32bit machines, then as 'chunk' is unsigned lock,
chunk << chunksize_bits
can overflow (this can be as high as the size of the device in KB). chunk itself will not overflow (without triggering a BUG).

So change 'chunk' to be 'sector_t, and get rid of the 'BUG' as it becomes impossible to hit.

---
 drivers/md/raid0.c |    3 +--
 1 files changed, 1 insertions(+), 2 deletions(-)
drivers/md/raid0.c +1 -2
index dfe3214..2c404f7 100644
@@ -415,7 +415,7 @@ static int raid0_make_request (request_queue_t *q, struct bio *bio)
 	raid0_conf_t *conf = mddev_to_conf(mddev);
 	struct strip_zone *zone;
 	mdk_rdev_t *tmp_dev;
-	unsigned long chunk;
+	sector_t chunk;
 	sector_t block, rsect;
 	const int rw = bio_data_dir(bio);
 
@@ -470,7 +470,6 @@ static int raid0_make_request (request_queue_t *q, struct bio *bio)
 
 		sector_div(x, zone->nb_dev);
 		chunk = x;
-		BUG_ON(x != (sector_t)chunk);
 
 		x = block >> chunksize_bits;
 		tmp_dev = zone->dev[sector_div(x, zone->nb_dev)];
Signature · 3 lines
1.5.2.4

-- 
#3 lore raw

PATCH 3/28 md: Dont write more than is required of the last page of a bitmap

In reply to Willy Tarreau

It is possible that real data or metadata follows the bitmap without full page alignment.
So limit the last write to be only the required number of bytes, rounded up to the hard sector size of the device.

---
 drivers/md/bitmap.c         |   17 ++++++++++++-----
 include/linux/raid/bitmap.h |    1 +
 2 files changed, 13 insertions(+), 5 deletions(-)
drivers/md/bitmap.c +12 -5
index cef1287..550ac72 100644
@@ -255,19 +255,25 @@ static struct page *read_sb_page(mddev_t *mddev, long offset, unsigned long inde
 
 }
 
-static int write_sb_page(mddev_t *mddev, long offset, struct page *page, int wait)
+static int write_sb_page(struct bitmap *bitmap, struct page *page, int wait)
 {
 	mdk_rdev_t *rdev;
 	struct list_head *tmp;
+	mddev_t *mddev = bitmap->mddev;
 
 	ITERATE_RDEV(mddev, rdev, tmp)
 		if (test_bit(In_sync, &rdev->flags)
-		    && !test_bit(Faulty, &rdev->flags))
+		    && !test_bit(Faulty, &rdev->flags)) {
+			int size = PAGE_SIZE;
+			if (page->index == bitmap->file_pages-1)
+				size = roundup(bitmap->last_page_size,
+					       bdev_hardsect_size(rdev->bdev));
 			md_super_write(mddev, rdev,
-				       (rdev->sb_offset<<1) + offset
+				       (rdev->sb_offset<<1) + bitmap->offset
 				       + page->index * (PAGE_SIZE/512),
-				       PAGE_SIZE,
+				       size,
 				       page);
+		}
 
 	if (wait)
 		md_super_wait(mddev);
@@ -282,7 +288,7 @@ static int write_page(struct bitmap *bitmap, struct page *page, int wait)
 	struct buffer_head *bh;
 
 	if (bitmap->file == NULL)
-		return write_sb_page(bitmap->mddev, bitmap->offset, page, wait);
+		return write_sb_page(bitmap, page, wait);
 
 	bh = page_buffers(page);
 
@@ -923,6 +929,7 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
 			}
 
 			bitmap->filemap[bitmap->file_pages++] = page;
+			bitmap->last_page_size = count;
 		}
 		paddr = kmap_atomic(page, KM_USER0);
 		if (bitmap->flags & BITMAP_HOSTENDIAN)
include/linux/raid/bitmap.h +1 -0
index 6db9a4c..dd5a05d 100644
@@ -232,6 +232,7 @@ struct bitmap {
 	struct page **filemap; /* list of cache pages for the file */
 	unsigned long *filemap_attr; /* attributes associated w/ filemap pages */
 	unsigned long file_pages; /* number of pages in the file */
+	int last_page_size; /* bytes in the last page */
 
 	unsigned long flags;
 
Signature · 3 lines
1.5.2.4

-- 
#4 lore raw

PATCH 4/28 make freezeable workqueues singlethread

In reply to Willy Tarreau

It is a known fact that freezeable multithreaded workqueues doesn't like CPU_DEAD. We keep them only for the incoming CPU-hotplug rework.

Sadly, we can't just kill create_freezeable_workqueue() right now, make them singlethread.

---
 include/linux/workqueue.h |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
include/linux/workqueue.h +1 -1
index 2a7b38d..1a76bda 100644
@@ -162,7 +162,7 @@ extern struct workqueue_struct *__create_workqueue(const char *name,
 						    int singlethread,
 						    int freezeable);
 #define create_workqueue(name) __create_workqueue((name), 0, 0)
-#define create_freezeable_workqueue(name) __create_workqueue((name), 0, 1)
+#define create_freezeable_workqueue(name) __create_workqueue((name), 1, 1)
 #define create_singlethread_workqueue(name) __create_workqueue((name), 1, 0)
 
 extern void destroy_workqueue(struct workqueue_struct *wq);
Signature · 3 lines
1.5.2.4

-- 
#5 lore raw

PATCH 5/28 Char: cyclades, fix deadlock

In reply to Willy Tarreau

An omitted unlock.

---
 drivers/char/cyclades.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)
drivers/char/cyclades.c +1 -0
index 3ffa080..e4e0ccb 100644
@@ -1102,6 +1102,7 @@ static void cyy_intr_chip(struct cyclades_card *cinfo, int chip,
 
 				if (data & info->ignore_status_mask) {
 					info->icount.rx++;
+					spin_unlock(&cinfo->card_lock);
 					return;
 				}
 				if (tty_buffer_request_room(tty, 1)) {
Signature · 3 lines
1.5.2.4

-- 
#6 lore raw

PATCH 6/28 e1000: disable polling before registering netdevice

In reply to Willy Tarreau

To assure the symmetry of poll enable/disable in up/down, we should initialize the netdevice to be poll_disabled at load time. Doing this after register_netdevice leaves us open to another race, so lets move all the netif_* calls above register_netdevice so the stack starts out how we expect it to be.

---
 drivers/net/e1000/e1000_main.c |   11 +++++++----
 1 files changed, 7 insertions(+), 4 deletions(-)
drivers/net/e1000/e1000_main.c +7 -4
index c6259c7..40bdcf9 100644
@@ -1157,13 +1157,16 @@ e1000_probe(struct pci_dev *pdev,
 	    !e1000_check_mng_mode(&adapter->hw))
 		e1000_get_hw_control(adapter);
 
-	strcpy(netdev->name, "eth%d");
-	if ((err = register_netdev(netdev)))
-		goto err_register;
-
 	/* tell the stack to leave us alone until e1000_open() is called */
 	netif_carrier_off(netdev);
 	netif_stop_queue(netdev);
+#ifdef CONFIG_E1000_NAPI
+	netif_poll_disable(netdev);
+#endif
+
+	strcpy(netdev->name, "eth%d");
+	if ((err = register_netdev(netdev)))
+		goto err_register;
 
 	DPRINTK(PROBE, INFO, "Intel(R) PRO/1000 Network Connection

");

Signature · 3 lines
1.5.2.4

-- 
#7 lore raw

PATCH 8/28 x86_64: allocate sparsemem memmap above 4G

In reply to Willy Tarreau

On systems with huge amount of physical memory, VFS cache and memory memmap may eat all available system memory under 4G, then the system may fail to allocate swiotlb bounce buffer.

There was a fix for this issue in arch/x86_64/mm/numa.c, but that fix dose not cover sparsemem model.

This patch add fix to sparsemem model by first try to allocate memmap above 4G.

---
 arch/x86_64/mm/init.c   |    6 ++++++
 include/linux/bootmem.h |    1 +
 mm/sparse.c             |   11 +++++++++++
 3 files changed, 18 insertions(+), 0 deletions(-)
arch/x86_64/mm/init.c +6 -0
index 2968b90..2489aa7 100644
@@ -766,3 +766,9 @@ int in_gate_area_no_task(unsigned long addr)
 {
 	return (addr >= VSYSCALL_START) && (addr < VSYSCALL_END);
 }
+
+void *alloc_bootmem_high_node(pg_data_t *pgdat, unsigned long size)
+{
+	return __alloc_bootmem_core(pgdat->bdata, size,
+			SMP_CACHE_BYTES, (4UL*1024*1024*1024), 0);
+}
include/linux/bootmem.h +1 -0
index 2275f27..8f820e4 100644
@@ -59,6 +59,7 @@ extern void *__alloc_bootmem_core(struct bootmem_data *bdata,
 				  unsigned long align,
 				  unsigned long goal,
 				  unsigned long limit);
+extern void *alloc_bootmem_high_node(pg_data_t *pgdat, unsigned long size);
 
 #ifndef CONFIG_HAVE_ARCH_BOOTMEM_NODE
 extern void reserve_bootmem(unsigned long addr, unsigned long size);
mm/sparse.c +11 -0
index ac26eb0..faa08e2 100644
@@ -209,6 +209,12 @@ static int sparse_init_one_section(struct mem_section *ms,
 	return 1;
 }
 
+__attribute__((weak))
+void *alloc_bootmem_high_node(pg_data_t *pgdat, unsigned long size)
+{
+	return NULL;
+}
+
 static struct page *sparse_early_mem_map_alloc(unsigned long pnum)
 {
 	struct page *map;
@@ -219,6 +225,11 @@ static struct page *sparse_early_mem_map_alloc(unsigned long pnum)
 	if (map)
 		return map;
 
+  	map = alloc_bootmem_high_node(NODE_DATA(nid),
+                       sizeof(struct page) * PAGES_PER_SECTION);
+	if (map)
+		return map;
+
 	map = alloc_bootmem_node(NODE_DATA(nid),
 			sizeof(struct page) * PAGES_PER_SECTION);
 	if (map)
Signature · 3 lines
1.5.2.4

-- 
#8 lore raw

Re: [2.6.20.16 review 08/28] x86_64: allocate sparsemem memmap above 4G

Quoted 6 lines · Willy Tarreau

On systems with huge amount of physical memory, VFS cache and memory memmap may eat all available system memory under 4G, then the system may fail to allocate swiotlb bounce buffer.

There was a fix for this issue in arch/x86_64/mm/numa.c, but that fix dose not cover sparsemem model.

Have you checked if sparsemem even worked in 2.6.20? Irc it was quite unstable a couple of releases ago. There were times where it rarely booted on x86-64 because so few people test it.
If not the patch is not needed, although relatively harmless too.

-Andi

#9 lore raw

Re: [2.6.20.16 review 08/28] x86_64: allocate sparsemem memmap above 4G

Hi Andi,

Quoted 9 lines · Andi Kleen
Quoted 6 lines · Willy Tarreau

On systems with huge amount of physical memory, VFS cache and memory memmap may eat all available system memory under 4G, then the system may fail to allocate swiotlb bounce buffer.

There was a fix for this issue in arch/x86_64/mm/numa.c, but that fix dose not cover sparsemem model.

Have you checked if sparsemem even worked in 2.6.20?

No, unfortunately I'm not equipped for that.

Quoted 4 lines

Irc it was quite
unstable a couple of releases ago. There were times where it rarely booted on x86-64 because so few people test it.
If not the patch is not needed, although relatively harmless too.

OK. So I'd propose the following :
- if someone can confirm that it did not work anyway, I remove the patch which becomes useless.
- but if we get no confirmation, assuming that in doubt, some people _may_ be relying on it and that it does not affect other ones, we'd keep it.

are you OK with this ?

Thanks,
Willy

#10 lore raw

PATCH 9/28 sparsemem: fix oops in x86_64 show_mem

In reply to Willy Tarreau

We aren't sampling for holes in memory. Thus we encounter a section hole with empty section map pointer for SPARSEMEM and OOPs for show_mem. This issue has been seen in 2.6.21, current git and current mm. This patch is for 2.6.21 stable. It was tested against sparsemem.

Previous to commit f0a5a58aa812b31fd9f197c4ba48245942364eae memory_present was called for node_start_pfn to node_end_pfn. This would cover the hole(s) with reserved pages and valid sections. Most SPARSEMEM supported arches do a pfn_valid check in show_mem before computing the page structure address.

This issue was brought to my attention on IRC by Arnaldo Carvalho de Melo at [email protected]. Thanks to Arnaldo for testing.

---
 arch/x86_64/mm/init.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)
arch/x86_64/mm/init.c +2 -0
index 2489aa7..e67cc4f 100644
@@ -72,6 +72,8 @@ void show_mem(void)
 
 	for_each_online_pgdat(pgdat) {
                for (i = 0; i < pgdat->node_spanned_pages; ++i) {
+			if (!pfn_valid(pgdat->node_start_pfn + i))
+				continue;
 			page = pfn_to_page(pgdat->node_start_pfn + i);
 			total++;
 			if (PageReserved(page))
Signature · 3 lines
1.5.2.4

-- 
#11 lore raw

PATCH 10/28 rt-mutex: Fix stale return value

In reply to Willy Tarreau

Alexey Kuznetsov found some problems in the pi-futex code.

The major problem is a stale return value in rt_mutex_slowlock():

When the pi chain walk returns -EDEADLK, but the waiter was woken up during the phases where the locks were dropped, the rtmutex could be acquired, but due to the stale return value -EDEADLK returned to the caller.

Reset the return value in the woken up path.

---
 kernel/rtmutex.c |   11 +++++++++--
 1 files changed, 9 insertions(+), 2 deletions(-)
kernel/rtmutex.c +9 -2
index 4ab17da..9b08847 100644
@@ -659,9 +659,16 @@ rt_mutex_slowlock(struct rt_mutex *lock, int state,
 			 * all over without going into schedule to try
 			 * to get the lock now:
 			 */
-			if (unlikely(!waiter.task))
+			if (unlikely(!waiter.task)) {
+				/*
+				 * Reset the return value. We might
+				 * have returned with -EDEADLK and the
+				 * owner released the lock while we
+				 * were walking the pi chain.
+				 */
+				ret = 0;
 				continue;
-
+			}
 			if (unlikely(ret))
 				break;
 		}
Signature · 3 lines
1.5.2.4

-- 
#12 lore raw

PATCH 11/28 rt-mutex: Fix chain walk early wakeup bug

In reply to Willy Tarreau

Alexey Kuznetsov found some problems in the pi-futex code.

One of the root causes is:

When a wakeup happens, we do not to stop the chain walk so we we follow a non existing locking chain.

Drop out when this happens.

---
 kernel/rtmutex.c |   13 +++++++++++++
 1 files changed, 13 insertions(+), 0 deletions(-)
kernel/rtmutex.c +13 -0
index 9b08847..dd5feae 100644
@@ -212,6 +212,19 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task,
 	if (!waiter || !waiter->task)
 		goto out_unlock_pi;
 
+	/*
+	 * Check the orig_waiter state. After we dropped the locks,
+	 * the previous owner of the lock might have released the lock
+	 * and made us the pending owner:
+	 */
+	if (orig_waiter && !orig_waiter->task)
+		goto out_unlock_pi;
+
+	/*
+	 * Drop out, when the task has no waiters. Note,
+	 * top_waiter can be NULL, when we are in the deboosting
+	 * mode!
+	 */
 	if (top_waiter && (!task_has_pi_waiters(task) ||
 			   top_waiter != task_top_pi_waiter(task)))
 		goto out_unlock_pi;
Signature · 3 lines
1.5.2.4

-- 
#13 lore raw

PATCH 13/28 md: Fix two raid10 bugs.

In reply to Willy Tarreau

1/ When resyncing a degraded raid10 which has more than 2 copies of each block,
garbage can get synced on top of good data.

2/ We round the wrong way in part of the device size calculation, which
can cause confusion.

---
 drivers/md/raid10.c |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)
drivers/md/raid10.c +6 -0
index 82249a6..9eb66c1 100644
@@ -1867,6 +1867,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
 			int d = r10_bio->devs[i].devnum;
 			bio = r10_bio->devs[i].bio;
 			bio->bi_end_io = NULL;
+			clear_bit(BIO_UPTODATE, &bio->bi_flags);
 			if (conf->mirrors[d].rdev == NULL ||
 			    test_bit(Faulty, &conf->mirrors[d].rdev->flags))
 				continue;
@@ -2037,6 +2038,11 @@ static int run(mddev_t *mddev)
 	/* 'size' is now the number of chunks in the array */
 	/* calculate "used chunks per device" in 'stride' */
 	stride = size * conf->copies;
+
+	/* We need to round up when dividing by raid_disks to
+	 * get the stride size.
+	 */
+	stride += conf->raid_disks - 1;
 	sector_div(stride, conf->raid_disks);
 	mddev->size = stride  << (conf->chunk_shift-1);
 
Signature · 3 lines
1.5.2.4

-- 
#14 lore raw

PATCH 14/28 md: Fix bug in error handling during raid1 repair.

In reply to Willy Tarreau

If raid1/repair (which reads all block and fixes any differences it finds) hits a read error, it doesn't reset the bio for writing before writing correct data back, so the read error isn't fixed, and the device probably gets a zero-length write which it might complain about.

---
 drivers/md/raid1.c |   21 ++++++++++++++-------
 1 files changed, 14 insertions(+), 7 deletions(-)
drivers/md/raid1.c +14 -7
index 97ee870..b20c6e9 100644
@@ -1235,17 +1235,24 @@ static void sync_request_write(mddev_t *mddev, r1bio_t *r1_bio)
 			}
 		r1_bio->read_disk = primary;
 		for (i=0; i<mddev->raid_disks; i++)
-			if (r1_bio->bios[i]->bi_end_io == end_sync_read &&
-			    test_bit(BIO_UPTODATE, &r1_bio->bios[i]->bi_flags)) {
+			if (r1_bio->bios[i]->bi_end_io == end_sync_read) {
 				int j;
 				int vcnt = r1_bio->sectors >> (PAGE_SHIFT- 9);
 				struct bio *pbio = r1_bio->bios[primary];
 				struct bio *sbio = r1_bio->bios[i];
-				for (j = vcnt; j-- ; )
-					if (memcmp(page_address(pbio->bi_io_vec[j].bv_page),
-						   page_address(sbio->bi_io_vec[j].bv_page),
-						   PAGE_SIZE))
-						break;
+
+				if (test_bit(BIO_UPTODATE, &sbio->bi_flags)) {
+					for (j = vcnt; j-- ; ) {
+						struct page *p, *s;
+						p = pbio->bi_io_vec[j].bv_page;
+						s = sbio->bi_io_vec[j].bv_page;
+						if (memcmp(page_address(p),
+							   page_address(s),
+							   PAGE_SIZE))
+							break;
+					}
+				} else
+					j = 0;
 				if (j >= 0)
 					mddev->resync_mismatches += r1_bio->sectors;
 				if (j < 0 || test_bit(MD_RECOVERY_CHECK, &mddev->recovery)) {
Signature · 3 lines
1.5.2.4

-- 
#15 lore raw

PATCH 15/28 dm crypt: disable barriers

In reply to Willy Tarreau

Disable barriers in dm-crypt because of current workqueue processing can reorder requests.

This must be addresed later but for now disabling barriers is needed to prevent data corruption.

---
 drivers/md/dm-crypt.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)
drivers/md/dm-crypt.c +3 -0
index 4c2471e..f68677d 100644
@@ -954,6 +954,9 @@ static int crypt_map(struct dm_target *ti, struct bio *bio,
 	struct crypt_config *cc = ti->private;
 	struct crypt_io *io;
 
+	if (bio_barrier(bio))
+		return -EOPNOTSUPP;
+
 	io = mempool_alloc(cc->io_pool, GFP_NOIO);
 	io->target = ti;
 	io->base_bio = bio;
Signature · 3 lines
1.5.2.4

-- 
#16 lore raw

PATCH 16/28 dm crypt: fix call to clone_init

In reply to Willy Tarreau

Call clone_init early

We need to call clone_init as early as possible - at least before call bio_put(clone) in any error path. Otherwise, the destructor will try to dereference bi_private, which may still be NULL.

---
 drivers/md/dm-crypt.c |   12 +++++++-----
 1 files changed, 7 insertions(+), 5 deletions(-)
drivers/md/dm-crypt.c +7 -5
index f68677d..bffaf1c 100644
@@ -107,6 +107,8 @@ struct crypt_config {
 
 static struct kmem_cache *_crypt_io_pool;
 
+static void clone_init(struct crypt_io *, struct bio *);
+
 /*
  * Different IV generation algorithms:
  *
@@ -379,9 +381,10 @@ static int crypt_convert(struct crypt_config *cc,
  * May return a smaller bio when running out of pages
  */
 static struct bio *
-crypt_alloc_buffer(struct crypt_config *cc, unsigned int size,
+crypt_alloc_buffer(struct crypt_io *io, unsigned int size,
                    struct bio *base_bio, unsigned int *bio_vec_idx)
 {
+	struct crypt_config *cc = io->target->private;
 	struct bio *clone;
 	unsigned int nr_iovecs = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
 	gfp_t gfp_mask = GFP_NOIO | __GFP_HIGHMEM;
@@ -396,7 +399,7 @@ crypt_alloc_buffer(struct crypt_config *cc, unsigned int size,
 	if (!clone)
 		return NULL;
 
-	clone->bi_destructor = dm_crypt_bio_destructor;
+	clone_init(io, clone);
 
 	/* if the last bio was not complete, continue where that one ended */
 	clone->bi_idx = *bio_vec_idx;
@@ -562,6 +565,7 @@ static void clone_init(struct crypt_io *io, struct bio *clone)
 	clone->bi_end_io  = crypt_endio;
 	clone->bi_bdev    = cc->dev->bdev;
 	clone->bi_rw      = io->base_bio->bi_rw;
+	clone->bi_destructor = dm_crypt_bio_destructor;
 }
 
 static void process_read(struct crypt_io *io)
@@ -585,7 +589,6 @@ static void process_read(struct crypt_io *io)
 	}
 
 	clone_init(io, clone);
-	clone->bi_destructor = dm_crypt_bio_destructor;
 	clone->bi_idx = 0;
 	clone->bi_vcnt = bio_segments(base_bio);
 	clone->bi_size = base_bio->bi_size;
@@ -615,7 +618,7 @@ static void process_write(struct crypt_io *io)
 	 * so repeat the whole process until all the data can be handled.
 	 */
 	while (remaining) {
-		clone = crypt_alloc_buffer(cc, base_bio->bi_size,
+		clone = crypt_alloc_buffer(io, base_bio->bi_size,
 					   io->first_clone, &bvec_idx);
 		if (unlikely(!clone)) {
 			dec_pending(io, -ENOMEM);
@@ -631,7 +634,6 @@ static void process_write(struct crypt_io *io)
 			return;
 		}
 
-		clone_init(io, clone);
 		clone->bi_sector = cc->start + sector;
 
 		if (!io->first_clone) {
Signature · 3 lines
1.5.2.4

-- 
#17 lore raw

PATCH 17/28 dm crypt: fix avoid cloned bio ref after free

In reply to Willy Tarreau

Do not access the bio after generic_make_request

We should never access a bio after generic_make_request - there's no guarantee it still exists.

---
 drivers/md/dm-crypt.c |    5 ++++-
 1 files changed, 4 insertions(+), 1 deletions(-)
drivers/md/dm-crypt.c +4 -1
index bffaf1c..28831a9 100644
@@ -655,9 +655,12 @@ static void process_write(struct crypt_io *io)
 
 		generic_make_request(clone);
 
+		/* Do not reference clone after this - it
+		 * may be gone already. */
+
 		/* out of memory -> run queues */
 		if (remaining)
-			congestion_wait(bio_data_dir(clone), HZ/100);
+			congestion_wait(WRITE, HZ/100);
 	}
 }
 
Signature · 3 lines
1.5.2.4

-- 
#18 lore raw

PATCH 19/28 sched: fix next_interval determination in idle_balance()

In reply to Willy Tarreau

Fix massive SMP imbalance on NUMA nodes observed on 2.6.21.5 with CFS. (and later on reproduced without CFS as well).

The intervals of domains that do not have SD_BALANCE_NEWIDLE must be considered for the calculation of the time of the next balance. Otherwise we may defer rebalancing forever and nodes might stay idle for very long times.

Siddha also spotted that the conversion of the balance interval to jiffies is missing. Fix that to.

From: Srivatsa Vaddagiri <[email protected]>

also continue the loop if !(sd->flags & SD_LOAD_BALANCE).

It did in fact trigger under all three of mainline, CFS, and -rt including CFS -- see below for a couple of emails from last Friday giving results for these three on the AMD box (where it happened) and on a single-quad NUMA-Q system (where it did not, at least not with such severity).

---
 kernel/sched.c |   22 +++++++++++++---------
 1 files changed, 13 insertions(+), 9 deletions(-)
kernel/sched.c +13 -9
index 62db30c..907ab05 100644
@@ -2814,17 +2814,21 @@ static void idle_balance(int this_cpu, struct rq *this_rq)
 	unsigned long next_balance = jiffies + 60 *  HZ;
 
 	for_each_domain(this_cpu, sd) {
-		if (sd->flags & SD_BALANCE_NEWIDLE) {
+		unsigned long interval;
+
+		if (!(sd->flags & SD_LOAD_BALANCE))
+			continue;
+
+		if (sd->flags & SD_BALANCE_NEWIDLE)
 			/* If we've pulled tasks over stop searching: */
 			pulled_task = load_balance_newidle(this_cpu,
-							this_rq, sd);
-			if (time_after(next_balance,
-				  sd->last_balance + sd->balance_interval))
-				next_balance = sd->last_balance
-						+ sd->balance_interval;
-			if (pulled_task)
-				break;
-		}
+								this_rq, sd);
+
+		interval = msecs_to_jiffies(sd->balance_interval);
+		if (time_after(next_balance, sd->last_balance + interval))
+			next_balance = sd->last_balance + interval;
+		if (pulled_task)
+			break;
 	}
 	if (!pulled_task)
 		/*
Signature · 3 lines
1.5.2.4

-- 
#19 lore raw

PATCH 21/28 audit: fix oops removing watch if audit disabled

In reply to Willy Tarreau

Removing a watched file will oops if audit is disabled (auditctl -e 0).

To reproduce:
- auditctl -e 1
- touch /tmp/foo
- auditctl -w /tmp/foo
- auditctl -e 0
- rm /tmp/foo (or mv)

---
 kernel/auditfilter.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
kernel/auditfilter.c +1 -1
index 9c8c232..5a75657 100644
@@ -905,7 +905,7 @@ static void audit_update_watch(struct audit_parent *parent,
 
 		/* If the update involves invalidating rules, do the inode-based
 		 * filtering now, so we don't omit records. */
-		if (invalidating &&
+		if (invalidating && current->audit_context &&
 		    audit_filter_inodes(current, current->audit_context) == AUDIT_RECORD_CONTEXT)
 			audit_set_auditable(current->audit_context);
 
Signature · 3 lines
1.5.2.4

-- 
#20 lore raw

PATCH 22/28 POWERPC: Fix subtle FP state corruption bug in signal return on SMP

In reply to Willy Tarreau

This fixes a bug which can cause corruption of the floating-point state on return from a signal handler. If we have a signal handler that has used the floating-point registers, and it happens to context-switch to another task while copying the interrupted floating-point state from the user stack into the thread struct (e.g. because of a page fault, or because it gets preempted), the context switch code will think that the FP registers contain valid FP state that needs to be copied into the thread_struct, and will thus overwrite the values that the signal return code has put into the thread_struct.

This can occur because we clear the MSR bits that indicate the presence of valid FP state after copying the state into the thread_struct. To fix this we just move the clearing of the MSR bits to before the copy. A similar potential problem also occurs with the Altivec state, and this fixes that in the same way.

---
 arch/powerpc/kernel/signal_64.c |   10 +++++++---
 1 files changed, 7 insertions(+), 3 deletions(-)
arch/powerpc/kernel/signal_64.c +7 -3
index f72e8e8..a84304e 100644
@@ -177,6 +177,13 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig,
 	 */
 	discard_lazy_cpu_state();
 
+	/*
+	 * Force reload of FP/VEC.
+	 * This has to be done before copying stuff into current->thread.fpr/vr
+	 * for the reasons explained in the previous comment.
+	 */
+	regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1 | MSR_VEC);
+
 	err |= __copy_from_user(&current->thread.fpr, &sc->fp_regs, FP_REGS_SIZE);
 
 #ifdef CONFIG_ALTIVEC
@@ -198,9 +205,6 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig,
 		current->thread.vrsave = 0;
 #endif /* CONFIG_ALTIVEC */
 
-	/* Force reload of FP/VEC */
-	regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1 | MSR_VEC);
-
 	return err;
 }
 
Signature · 3 lines
1.5.2.4

-- 
#21 lore raw

PATCH 23/28 mm: kill validate_anon_vma to avoid mapcount BUG

In reply to Willy Tarreau

validate_anon_vma gave a useful check on the integrity of the anon_vma list when Andrea was developing obj rmap; but it was not enabled in SLES9 itself, nor in mainline, until Nick changed commented-out RMAP_DEBUG to configurable CONFIG_DEBUG_VM in 2.6.17. Now Petr Vandrovec reports that its BUG_ON(mapcount > 100000) can easily crash a CONFIG_DEBUG_VM=y system.

That limit was just an arbitrary number to protect against an infinite loop. We could raise it to something enormous (depending on sizeof struct vma and size of memory?); but I rather think validate_anon_vma has outlived its usefulness, and is better just removed - which gives a magnificent performance boost to anything like Petr's test program ;)

Of course, a very long anon_vma list is bad news for preemption latency, and I believe there has been one recent report of such: let's not forget that, but validate_anon_vma only makes it worse not better.

---
 mm/rmap.c |   24 +-----------------------
 1 files changed, 1 insertions(+), 23 deletions(-)
mm/rmap.c +1 -23
index 7ce69c1..c30781c 100644
@@ -53,24 +53,6 @@
 
 struct kmem_cache *anon_vma_cachep;
 
-static inline void validate_anon_vma(struct vm_area_struct *find_vma)
-{
-#ifdef CONFIG_DEBUG_VM
-	struct anon_vma *anon_vma = find_vma->anon_vma;
-	struct vm_area_struct *vma;
-	unsigned int mapcount = 0;
-	int found = 0;
-
-	list_for_each_entry(vma, &anon_vma->head, anon_vma_node) {
-		mapcount++;
-		BUG_ON(mapcount > 100000);
-		if (vma == find_vma)
-			found = 1;
-	}
-	BUG_ON(!found);
-#endif
-}
-
 /* This must be called under the mmap_sem. */
 int anon_vma_prepare(struct vm_area_struct *vma)
 {
@@ -121,10 +103,8 @@ void __anon_vma_link(struct vm_area_struct *vma)
 {
 	struct anon_vma *anon_vma = vma->anon_vma;
 
-	if (anon_vma) {
+	if (anon_vma)
 		list_add_tail(&vma->anon_vma_node, &anon_vma->head);
-		validate_anon_vma(vma);
-	}
 }
 
 void anon_vma_link(struct vm_area_struct *vma)
@@ -134,7 +114,6 @@ void anon_vma_link(struct vm_area_struct *vma)
 	if (anon_vma) {
 		spin_lock(&anon_vma->lock);
 		list_add_tail(&vma->anon_vma_node, &anon_vma->head);
-		validate_anon_vma(vma);
 		spin_unlock(&anon_vma->lock);
 	}
 }
@@ -148,7 +127,6 @@ void anon_vma_unlink(struct vm_area_struct *vma)
 		return;
 
 	spin_lock(&anon_vma->lock);
-	validate_anon_vma(vma);
 	list_del(&vma->anon_vma_node);
 
 	/* We must garbage collect the anon_vma if it's empty */
Signature · 3 lines
1.5.2.4

-- 
#22 lore raw

PATCH 24/28 saa7134: fix thread shutdown handling

In reply to Willy Tarreau

This patch changes the test for the thread pid from >= 0 to > 0.

When the saa7134 driver initialization fails after a certain point, it goes through the complete shutdown process for the driver. Part of shutting it down includes tearing down the thread for tv audio.

The test for tearing down the thread tests for >= 0. Since the dev structure is kzalloc'd, the test will always be true if we haven't tried to start the thread yet. We end up waiting on pid 0 to complete, which will never happen, so we lock up.

This bug was observed in Novell Bugzilla 284718, when request_irq() failed.

---
 drivers/media/video/saa7134/saa7134-tvaudio.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/media/video/saa7134/saa7134-tvaudio.c +1 -1
index dd759d6..36b3fa3 100644
@@ -1006,7 +1006,7 @@ int saa7134_tvaudio_init2(struct saa7134_dev *dev)
 int saa7134_tvaudio_fini(struct saa7134_dev *dev)
 {
 	/* shutdown tvaudio thread */
-	if (dev->thread.pid >= 0) {
+	if (dev->thread.pid > 0) {
 		dev->thread.shutdown = 1;
 		wake_up_interruptible(&dev->thread.wq);
 		wait_for_completion(&dev->thread.exit);
Signature · 3 lines
1.5.2.4

-- 
#23 lore raw

PATCH 25/28 serial: clear proper MPSC interrupt cause bits

In reply to Willy Tarreau

The interrupt clearing code in mpsc_sdma_intr_ack() mistakenly clears the interrupt for both controllers instead of just the one its supposed to. This can result in the other controller appearing to hang because its interrupt was effectively lost.

So, don't clear the interrupt cause bits for both MPSC controllers when clearing the interrupt for one of them. Just clear the one that is supposed to be cleared.

---
 drivers/serial/mpsc.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)
drivers/serial/mpsc.c +2 -1
index 3d2fcc5..64ed5ef 100644
@@ -502,7 +502,8 @@ mpsc_sdma_intr_ack(struct mpsc_port_info *pi)
 
 	if (pi->mirror_regs)
 		pi->shared_regs->SDMA_INTR_CAUSE_m = 0;
-	writel(0, pi->shared_regs->sdma_intr_base + SDMA_INTR_CAUSE);
+	writeb(0x00, pi->shared_regs->sdma_intr_base + SDMA_INTR_CAUSE +
+	       pi->port.line);
 	return;
 }
 
Signature · 3 lines
1.5.2.4

-- 
#24 lore raw

PATCH 26/28 i386: fix infinite loop with singlestep int80 syscalls

In reply to Willy Tarreau

The commit 635cf99a80f4ebee59d70eb64bb85ce829e4591f introduced a regression. Executing a ptrace single step after certain int80 accesses will infinitely loop and never advance the PC.

The TIF_SINGLESTEP check should be done on the return from the syscall and not before it.

The new test case is below:

/* Test whether singlestep through an int80 syscall works.
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <asm/user.h>
#include <string.h>

static int child, status;
static struct user_regs_struct regs;

static void do_child()

{
	char str[80] = "child: int80 test

";

	ptrace(PTRACE_TRACEME, 0, 0, 0);
	kill(getpid(), SIGUSR1);
	write(fileno(stdout),str,strlen(str));
	asm ("int $0x80" : : "a" (20)); /* getpid */
}

static void do_parent()

{
	unsigned long eip, expected = 0;
again:
	waitpid(child, &status, 0);
	if (WIFEXITED(status) || WIFSIGNALED(status))
		return;

	if (WIFSTOPPED(status)) {
		ptrace(PTRACE_GETREGS, child, 0, &regs);
		eip = regs.eip;
		if (expected)
			fprintf(stderr, "child stop @ %08lx, expected %08lx %s
",
					eip, expected,
					eip == expected ? "" : " <== ERROR");

		if (*(unsigned short *)eip == 0x80cd) {
			fprintf(stderr, "int 0x80 at %08x
", (unsigned int)eip);
			expected = eip + 2;
		} else
			expected = 0;

		ptrace(PTRACE_SINGLESTEP, child, NULL, NULL);
	}
	goto again;
}

int main(int argc, char * const argv[])

{
	child = fork();
	if (child)
		do_parent();
	else
		do_child();
	return 0;
}
---
 arch/i386/kernel/entry.S |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)
arch/i386/kernel/entry.S +4 -4
index 5e47683..9bf056e 100644
@@ -367,10 +367,6 @@ ENTRY(system_call)
 	CFI_ADJUST_CFA_OFFSET 4
 	SAVE_ALL
 	GET_THREAD_INFO(%ebp)
-	testl $TF_MASK,PT_EFLAGS(%esp)
-	jz no_singlestep
-	orl $_TIF_SINGLESTEP,TI_flags(%ebp)
-no_singlestep:
 					# system call tracing in operation / emulation
 	/* Note, _TIF_SECCOMP is bit number 8, and so it needs testw and not testb */
 	testw $(_TIF_SYSCALL_EMU|_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
@@ -385,6 +381,10 @@ syscall_exit:
 					# setting need_resched or sigpending
 					# between sampling and the iret
 	TRACE_IRQS_OFF
+	testl $TF_MASK,PT_EFLAGS(%esp)	# If tracing set singlestep flag on exit
+	jz no_singlestep
+	orl $_TIF_SINGLESTEP,TI_flags(%ebp)
+no_singlestep:
 	movl TI_flags(%ebp), %ecx
 	testw $_TIF_ALLWORK_MASK, %cx	# current->work
 	jne syscall_exit_work
Signature · 3 lines
1.5.2.4

-- 
#25 lore raw

PATCH 27/28 NTP: remove clock_was_set() call to prevent deadlock

In reply to Willy Tarreau

The clock_was_set() call in seconds_overflow() which happens only when leap seconds are inserted / deleted is wrong in two aspects:

1. it results in a call to on_each_cpu() with interrupts disabled
2. it is potential deadlock source vs. call_lock in smp_call_function()

The only possible side effect of the removal might be, that an absolute CLOCK_REALTIME timer fires 1 second too late, in the rare case of leap second deletion and an absolute CLOCK_REALTIME timer which expires in the affected time frame. It will never fire too early.

This was probably observed by the reporter of a June 30th -> July 1st
hang: http://lkml.org/lkml/2007/7/3/

A similar problem was observed by Dave Jones, who provided a screen shot with a lockdep back trace, which allowed to analyse the problem.

---
 kernel/time/ntp.c |    2 --
 1 files changed, 0 insertions(+), 2 deletions(-)
kernel/time/ntp.c +0 -1
index 3afeaa3..64744bb 100644
@@ -116,7 +116,6 @@ void second_overflow(void)
 			 */
 			time_interpolator_update(-NSEC_PER_SEC);
 			time_state = TIME_OOP;
-			clock_was_set();
 			printk(KERN_NOTICE "Clock: inserting leap second "
 					"23:59:60 UTC

");
}
@@ -131,7 +130,6 @@ void second_overflow(void)
*/
time_interpolator_update(NSEC_PER_SEC); time_state = TIME_WAIT;
- clock_was_set();
printk(KERN_NOTICE "Clock: deleting leap second "
"23:59:59 UTC
");
}

Signature · 3 lines
1.5.2.4

-- 
#26 lore raw

Re: [2.6.20.16 review 27/28] NTP: remove clock_was_set() call to prevent deadlock

Quoted 5 lines · Willy Tarreau

The clock_was_set() call in seconds_overflow() which happens only when leap seconds are inserted / deleted is wrong in two aspects:

1. it results in a call to on_each_cpu() with interrupts disabled
2. it is potential deadlock source vs. call_lock in smp_call_function()

clock_was_set() is a no-op in 2.6.20, so this one looks unnecessary (but harmless). Thankfully the "hang every Linux box on the planet simultaneously" regression (okay, that's *slight* hyperbole) was limited to 2.6.21.

#27 lore raw

Re: [2.6.20.16 review 27/28] NTP: remove clock_was_set() call to prevent deadlock

Quoted 11 lines · Jason Uhlenkott
Quoted 5 lines · Willy Tarreau

The clock_was_set() call in seconds_overflow() which happens only when leap seconds are inserted / deleted is wrong in two aspects:

1. it results in a call to on_each_cpu() with interrupts disabled
2. it is potential deadlock source vs. call_lock in smp_call_function()

clock_was_set() is a no-op in 2.6.20, so this one looks unnecessary (but harmless). Thankfully the "hang every Linux box on the planet simultaneously" regression (okay, that's *slight* hyperbole) was limited to 2.6.21.

OK, patch removed.

Thanks for your help,
Willy

#28 lore raw

PATCH 28/28 sky2: workaround for lost IRQ

In reply to Willy Tarreau

This patch restores a couple of workarounds from 2.6.16:
* restart transmit moderation timer in case it expires during IRQ routine
* default to having 10 HZ watchdog timer.
At this point it more important not to hang than to worry about the power cost.

---
 drivers/net/sky2.c |    9 ++++++++-
 1 files changed, 8 insertions(+), 1 deletions(-)
drivers/net/sky2.c +8 -1
index 38e75cf..aec8c59 100644
@@ -95,7 +95,7 @@ static int disable_msi = 0;
 module_param(disable_msi, int, 0);
 MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)");
 
-static int idle_timeout = 0;
+static int idle_timeout = 100;
 module_param(idle_timeout, int, 0);
 MODULE_PARM_DESC(idle_timeout, "Watchdog timer for lost interrupts (ms)");
 
@@ -2341,6 +2341,13 @@ static int sky2_poll(struct net_device *dev0, int *budget)
 
 	work_done = sky2_status_intr(hw, work_limit);
 	if (work_done < work_limit) {
+		/* Bug/Errata workaround?
+		 * Need to kick the TX irq moderation timer.
+		 */
+		if (sky2_read8(hw, STAT_TX_TIMER_CTRL) == TIM_START) {
+			sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP);
+			sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START);
+		}
 		netif_rx_complete(dev0);
 
 		sky2_read32(hw, B0_Y2_SP_LISR);
Signature · 3 lines
1.5.2.4

--