[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#394392: marked as done (msync() in recent kernels fails LSB)



Your message dated Wed, 24 Jan 2007 21:40:23 +0000
with message-id <E1H9pqx-0000HO-8u@ries.debian.org>
and subject line Bug#394392: fixed in linux-2.6 2.6.18.dfsg.1-9
has caused the attached Bug report to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what I am
talking about this indicates a serious mail system misconfiguration
somewhere.  Please contact me immediately.)

Debian bug tracking system administrator
(administrator, Debian Bugs database)

--- Begin Message ---
Package: linux-image-2.6.17-2-686
Version: 2.6.17-9
Severity: important

>From a recent run of the LSB 3.1 tests:

10|852 /tset/LSB.os/mfiles/msync_P/T.msync_P 22:58:49|TC Start, scenario ref 858-0
15|852 3.6-lite 9|TCM Start
400|852 7 1 22:59:13|IC Start
200|852 7 22:59:13|TP Start
520|852 7 00008662 1 1|msync() did not return -1, returned 0
220|852 7 1 22:59:13|FAIL
410|852 7 1 22:59:13|IC End
80|852 0 22:59:15|TC End, scenario ref 858-0

The test mmap()'s three pages from a large file read-write, munmap()'s
the middle page, and then tries to msync() the first two pages, both in
synchronous and asynchronous modes.  Both attempts should fail, because
one of the pages in the range is not mapped.  Starting with kernel
2.6.17, at least one of the msync() calls succeeded.  I've confirmed the
failure happens in 2.6.18 i386 kernels, and on powerpc and amd64 with
2.6.17 kernels.

I've been able to trace the bug to commit
707c21c848deeb0200ba3f07e4ba90e6dc419c2f in git.

FSG internal testing showed that Fedora Core 5's 2.6.18 kernel does not
fail in the same way.  I believe I've traced it to a backported change
from 2.6.19 development.  The specific commit touching msync() is
204ec841fbea3e5138168edbc3a76d46747cc987 in git; it relies on several
commits immediately preceding it.  I've built Linus's tree on amd64, and
it passes the test.  I have not, however, built a 2.6.18 kernel with
this patch and tested it, though it's the only patch in the Fedora
kernel which touches the msync() code.

The patch from the Fedora kernel is attached.  It is fairly high-impact,
though; if a less invasive patch is needed, please let me know.

Marked "important" because LSB 3.1 compatibility has been identified as
a release goal.

Date: Wed, 19 Jul 2006 00:03:33 +0200
From: Peter Zijlstra <pzijlstr@redhat.com>
Subject: Re: [RHEL5][PATCH 1/8] mm: tracking shared dirty pages

Respin against current Rawhide kernel.

The other patches apply with a little offset/fuzz but end up rightly.
It even compiles :-)

Don, is this enough, or would you like me to repost the whole series
(minus 8/8) fuzzless?

---


From: Peter Zijlstra <a.p.zijlstra@chello.nl>

Tracking of dirty pages in shared writeable mmap()s.

The idea is simple: write protect clean shared writeable pages, catch the
write-fault, make writeable and set dirty.  On page write-back clean all
the PTE dirty bits and write protect them once again.

The implementation is a tad harder, mainly because the default
backing_dev_info capabilities were too loosely maintained. Hence it is
not enough to test the backing_dev_info for cap_account_dirty.

The current heuristic is as follows, a VMA is eligible when:
 - its shared writeable
    (vm_flags & (VM_WRITE|VM_SHARED)) == (VM_WRITE|VM_SHARED)
 - it is not a 'special' mapping
    (vm_flags & (VM_PFNMAP|VM_INSERTPAGE)) == 0
 - the backing_dev_info is cap_account_dirty
    mapping_cap_account_dirty(vma->vm_file->f_mapping)
 - f_op->mmap() didn't change the default page protection

Page from remap_pfn_range() are explicitly excluded because their
COW semantics are already horrid enough (see vm_normal_page() in
do_wp_page()) and because they don't have a backing store anyway.

mprotect() is taught about the new behaviour as well. However it
fudges the last condition.

Cleaning the pages on write-back is done with page_mkclean() a new
rmap call. It cleans and wrprotects all PTEs of dirty accountable
pages.

Finally, in fs/buffers.c:try_to_free_buffers(); remove clear_page_dirty()
from under ->private_lock. This seems to be safe, since ->private_lock
is used to serialize access to the buffers, not the page itself.
This is needed because clear_page_dirty() will call into page_mkclean()
and would thereby violate locking order.

Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Hugh Dickins <hugh@veritas
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 fs/buffer.c          |    2 -
 include/linux/mm.h   |   34 ++++++++++++++++++++++++++
 include/linux/rmap.h |    8 ++++++
 mm/memory.c          |   29 ++++++++++++++++++----
 mm/mmap.c            |   10 +++----
 mm/mprotect.c        |   21 ++++++----------
 mm/page-writeback.c  |   17 ++++++++++---
 mm/rmap.c            |   65 +++++++++++++++++++++++++++++++++++++++++++++++++++
 8 files changed, 156 insertions(+), 30 deletions(-)

Index: latest/fs/buffer.c
===================================================================
--- latest.orig/fs/buffer.c
+++ latest/fs/buffer.c
@@ -2984,6 +2984,7 @@ int try_to_free_buffers(struct page *pag
 
 	spin_lock(&mapping->private_lock);
 	ret = drop_buffers(page, &buffers_to_free);
+	spin_unlock(&mapping->private_lock);
 	if (ret) {
 		/*
 		 * If the filesystem writes its buffers by hand (eg ext3)
@@ -2995,7 +2996,6 @@ int try_to_free_buffers(struct page *pag
 		 */
 		clear_page_dirty(page);
 	}
-	spin_unlock(&mapping->private_lock);
 out:
 	if (buffers_to_free) {
 		struct buffer_head *bh = buffers_to_free;
Index: latest/include/linux/mm.h
===================================================================
--- latest.orig/include/linux/mm.h
+++ latest/include/linux/mm.h
@@ -15,6 +15,7 @@
 #include <linux/fs.h>
 #include <linux/mutex.h>
 #include <linux/debug_locks.h>
+#include <linux/backing-dev.h>
 
 struct mempolicy;
 struct anon_vma;
@@ -801,6 +802,39 @@ struct shrinker;
 extern struct shrinker *set_shrinker(int, shrinker_t);
 extern void remove_shrinker(struct shrinker *shrinker);
 
+/*
+ * Some shared mappigns will want the pages marked read-only
+ * to track write events. If so, we'll downgrade vm_page_prot
+ * to the private version (using protection_map[] without the
+ * VM_SHARED bit).
+ */
+static inline int vma_wants_writenotify(struct vm_area_struct *vma)
+{
+	unsigned int vm_flags = vma->vm_flags;
+
+	/* If it was private or non-writable, the write bit is already clear */
+	if ((vm_flags & (VM_WRITE|VM_SHARED)) != ((VM_WRITE|VM_SHARED)))
+		return 0;
+
+	/* The backer wishes to know when pages are first written to? */
+	if (vma->vm_ops && vma->vm_ops->page_mkwrite)
+		return 1;
+
+	/* The open routine did something to the protections already? */
+	if (pgprot_val(vma->vm_page_prot) !=
+	    pgprot_val(protection_map[vm_flags &
+		    (VM_READ|VM_WRITE|VM_EXEC|VM_SHARED)]))
+		return 0;
+
+	/* Specialty mapping? */
+	if (vm_flags & (VM_PFNMAP|VM_INSERTPAGE))
+		return 0;
+
+	/* Can the mapping track the dirty pages? */
+	return vma->vm_file && vma->vm_file->f_mapping &&
+		mapping_cap_account_dirty(vma->vm_file->f_mapping);
+}
+
 extern pte_t *FASTCALL(get_locked_pte(struct mm_struct *mm, unsigned long addr, spinlock_t **ptl));
 
 int __pud_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long address);
Index: latest/include/linux/rmap.h
===================================================================
--- latest.orig/include/linux/rmap.h
+++ latest/include/linux/rmap.h
@@ -103,6 +103,14 @@ pte_t *page_check_address(struct page *,
  */
 unsigned long page_address_in_vma(struct page *, struct vm_area_struct *);
 
+/*
+ * Cleans the PTEs of shared mappings.
+ * (and since clean PTEs should also be readonly, write protects them too)
+ *
+ * returns the number of cleaned PTEs.
+ */
+int page_mkclean(struct page *);
+
 #else	/* !CONFIG_MMU */
 
 #define anon_vma_init()		do {} while (0)
Index: latest/mm/memory.c
===================================================================
--- latest.orig/mm/memory.c
+++ latest/mm/memory.c
@@ -1458,14 +1458,19 @@ static int do_wp_page(struct mm_struct *
 {
 	struct page *old_page, *new_page;
 	pte_t entry;
-	int reuse, ret = VM_FAULT_MINOR;
+	int reuse = 0, ret = VM_FAULT_MINOR;
+	struct page *dirty_page = NULL;
 
 	old_page = vm_normal_page(vma, address, orig_pte);
 	if (!old_page)
 		goto gotten;
 
-	if (unlikely((vma->vm_flags & (VM_SHARED|VM_WRITE)) ==
-				(VM_SHARED|VM_WRITE))) {
+	/*
+	 * Only catch write-faults on shared writable pages, read-only
+	 * shared pages can get COWed by get_user_pages(.write=1, .force=1).
+	 */
+	if (unlikely((vma->vm_flags & (VM_WRITE|VM_SHARED)) ==
+					(VM_WRITE|VM_SHARED))) {
 		if (vma->vm_ops && vma->vm_ops->page_mkwrite) {
 			/*
 			 * Notify the address space that the page is about to
@@ -1494,13 +1499,12 @@ static int do_wp_page(struct mm_struct *
 			if (!pte_same(*page_table, orig_pte))
 				goto unlock;
 		}
-
+		dirty_page = old_page;
+		get_page(dirty_page);
 		reuse = 1;
 	} else if (PageAnon(old_page) && !TestSetPageLocked(old_page)) {
 		reuse = can_share_swap_page(old_page);
 		unlock_page(old_page);
-	} else {
-		reuse = 0;
 	}
 
 	if (reuse) {
@@ -1566,6 +1570,10 @@ gotten:
 		page_cache_release(old_page);
 unlock:
 	pte_unmap_unlock(page_table, ptl);
+	if (dirty_page) {
+		set_page_dirty(dirty_page);
+		put_page(dirty_page);
+	}
 	return ret;
 oom:
 	if (old_page)
@@ -2098,6 +2106,7 @@ static int do_no_page(struct mm_struct *
 	unsigned int sequence = 0;
 	int ret = VM_FAULT_MINOR;
 	int anon = 0;
+	struct page *dirty_page = NULL;
 
 	pte_unmap(page_table);
 	BUG_ON(vma->vm_flags & VM_PFNMAP);
@@ -2192,6 +2201,10 @@ retry:
 		} else {
 			inc_mm_counter(mm, file_rss);
 			page_add_file_rmap(new_page);
+			if (write_access) {
+				dirty_page = new_page;
+				get_page(dirty_page);
+			}
 		}
 	} else {
 		/* One of our sibling threads was faster, back out. */
@@ -2204,6 +2217,10 @@ retry:
 	lazy_mmu_prot_update(entry);
 unlock:
 	pte_unmap_unlock(page_table, ptl);
+	if (dirty_page) {
+		set_page_dirty(dirty_page);
+		put_page(dirty_page);
+	}
 	return ret;
 oom:
 	page_cache_release(new_page);
Index: latest/mm/mmap.c
===================================================================
--- latest.orig/mm/mmap.c
+++ latest/mm/mmap.c
@@ -1097,12 +1097,6 @@ munmap_back:
 			goto free_vma;
 	}
 
-	/* Don't make the VMA automatically writable if it's shared, but the
-	 * backer wishes to know when pages are first written to */
-	if (vma->vm_ops && vma->vm_ops->page_mkwrite)
-		vma->vm_page_prot =
-			protection_map[vm_flags & (VM_READ|VM_WRITE|VM_EXEC)];
-
 	/* We set VM_ACCOUNT in a shared mapping's vm_flags, to inform
 	 * shmem_zero_setup (perhaps called through /dev/zero's ->mmap)
 	 * that memory reservation must be checked; but that reservation
@@ -1120,6 +1114,10 @@ munmap_back:
 	pgoff = vma->vm_pgoff;
 	vm_flags = vma->vm_flags;
 
+	if (vma_wants_writenotify(vma))
+		vma->vm_page_prot =
+			protection_map[vm_flags & (VM_READ|VM_WRITE|VM_EXEC)];
+
 	if (!file || !vma_merge(mm, prev, addr, vma->vm_end,
 			vma->vm_flags, NULL, file, pgoff, vma_policy(vma))) {
 		file = vma->vm_file;
Index: latest/mm/mprotect.c
===================================================================
--- latest.orig/mm/mprotect.c
+++ latest/mm/mprotect.c
@@ -124,8 +124,6 @@ mprotect_fixup(struct vm_area_struct *vm
 	unsigned long oldflags = vma->vm_flags;
 	long nrpages = (end - start) >> PAGE_SHIFT;
 	unsigned long charged = 0, old_end = vma->vm_end;
-	unsigned int mask;
-	pgprot_t newprot;
 	pgoff_t pgoff;
 	int error;
 
@@ -177,26 +175,23 @@ mprotect_fixup(struct vm_area_struct *vm
 	}
 
 success:
-	/* Don't make the VMA automatically writable if it's shared, but the
-	 * backer wishes to know when pages are first written to */
-	mask = VM_READ|VM_WRITE|VM_EXEC|VM_SHARED;
-	if (vma->vm_ops && vma->vm_ops->page_mkwrite)
-		mask &= ~VM_SHARED;
-
-	newprot = protection_map[newflags & mask];
-
 	/*
 	 * vm_flags and vm_page_prot are protected by the mmap_sem
 	 * held in write mode.
 	 */
 	vma->vm_flags = newflags;
-	vma->vm_page_prot = newprot;
 	if (oldflags & VM_EXEC)
 		arch_remove_exec_range(current->mm, old_end);
+	vma->vm_page_prot = protection_map[newflags &
+		(VM_READ|VM_WRITE|VM_EXEC|VM_SHARED)];
+	if (vma_wants_writenotify(vma))
+		vma->vm_page_prot = protection_map[newflags &
+			(VM_READ|VM_WRITE|VM_EXEC)];
+
 	if (is_vm_hugetlb_page(vma))
-		hugetlb_change_protection(vma, start, end, newprot);
+		hugetlb_change_protection(vma, start, end, vma->vm_page_prot);
 	else
-		change_protection(vma, start, end, newprot);
+		change_protection(vma, start, end, vma->vm_page_prot);
 	vm_stat_account(mm, oldflags, vma->vm_file, -nrpages);
 	vm_stat_account(mm, newflags, vma->vm_file, nrpages);
 	return 0;
Index: latest/mm/page-writeback.c
===================================================================
--- latest.orig/mm/page-writeback.c
+++ latest/mm/page-writeback.c
@@ -29,6 +29,7 @@
 #include <linux/sysctl.h>
 #include <linux/cpu.h>
 #include <linux/syscalls.h>
+#include <linux/rmap.h>
 
 /*
  * The maximum number of pages to writeout in a single bdflush/kupdate
@@ -550,7 +551,7 @@ int do_writepages(struct address_space *
 		return 0;
 	wbc->for_writepages = 1;
 	if (mapping->a_ops->writepages)
-		ret =  mapping->a_ops->writepages(mapping, wbc);
+		ret = mapping->a_ops->writepages(mapping, wbc);
 	else
 		ret = generic_writepages(mapping, wbc);
 	wbc->for_writepages = 0;
@@ -712,9 +713,15 @@ int test_clear_page_dirty(struct page *p
 			radix_tree_tag_clear(&mapping->page_tree,
 						page_index(page),
 						PAGECACHE_TAG_DIRTY);
-			if (mapping_cap_account_dirty(mapping))
-				__dec_zone_page_state(page, NR_FILE_DIRTY);
 			write_unlock_irqrestore(&mapping->tree_lock, flags);
+			/*
+			 * We can continue to use `mapping' here because the
+			 * page is locked, which pins the address_space
+			 */
+			if (mapping_cap_account_dirty(mapping)) {
+				page_mkclean(page);
+				dec_zone_page_state(page, NR_FILE_DIRTY);
+			}
 			return 1;
 		}
 		write_unlock_irqrestore(&mapping->tree_lock, flags);
@@ -744,8 +751,10 @@ int clear_page_dirty_for_io(struct page 
 
 	if (mapping) {
 		if (TestClearPageDirty(page)) {
-			if (mapping_cap_account_dirty(mapping))
+			if (mapping_cap_account_dirty(mapping)) {
+				page_mkclean(page);
 				dec_zone_page_state(page, NR_FILE_DIRTY);
+			}
 			return 1;
 		}
 		return 0;
Index: latest/mm/rmap.c
===================================================================
--- latest.orig/mm/rmap.c
+++ latest/mm/rmap.c
@@ -434,6 +434,71 @@ int page_referenced(struct page *page, i
 	return referenced;
 }
 
+static int page_mkclean_one(struct page *page, struct vm_area_struct *vma)
+{
+	struct mm_struct *mm = vma->vm_mm;
+	unsigned long address;
+	pte_t *pte, entry;
+	spinlock_t *ptl;
+	int ret = 0;
+
+	address = vma_address(page, vma);
+	if (address == -EFAULT)
+		goto out;
+
+	pte = page_check_address(page, mm, address, &ptl);
+	if (!pte)
+		goto out;
+
+	if (!pte_dirty(*pte) && !pte_write(*pte))
+		goto unlock;
+
+	entry = ptep_get_and_clear(mm, address, pte);
+	entry = pte_mkclean(entry);
+	entry = pte_wrprotect(entry);
+	ptep_establish(vma, address, pte, entry);
+	lazy_mmu_prot_update(entry);
+	ret = 1;
+
+unlock:
+	pte_unmap_unlock(pte, ptl);
+out:
+	return ret;
+}
+
+static int page_mkclean_file(struct address_space *mapping, struct page *page)
+{
+	pgoff_t pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT);
+	struct vm_area_struct *vma;
+	struct prio_tree_iter iter;
+	int ret = 0;
+
+	BUG_ON(PageAnon(page));
+
+	spin_lock(&mapping->i_mmap_lock);
+	vma_prio_tree_foreach(vma, &iter, &mapping->i_mmap, pgoff, pgoff) {
+		if (vma->vm_flags & VM_SHARED)
+			ret += page_mkclean_one(page, vma);
+	}
+	spin_unlock(&mapping->i_mmap_lock);
+	return ret;
+}
+
+int page_mkclean(struct page *page)
+{
+	int ret = 0;
+
+	BUG_ON(!PageLocked(page));
+
+	if (page_mapped(page)) {
+		struct address_space *mapping = page_mapping(page);
+		if (mapping)
+			ret = page_mkclean_file(mapping, page);
+	}
+
+	return ret;
+}
+
 /**
  * page_set_anon_rmap - setup new anonymous rmap
  * @page:	the page to add the mapping to
Date: Mon, 17 Jul 2006 20:32:34 +0200
From: pzijlstr@redhat.com
Subject: [RHEL5][PATCH 2/8] mm: balance dirty pages


From: Peter Zijlstra <a.p.zijlstra@chello.nl>

Now that we can detect writers of shared mappings, throttle them.  Avoids OOM
by surprise.

Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Hugh Dickins <hugh@veritas.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 include/linux/writeback.h |    1 +
 mm/memory.c               |    5 +++--
 mm/page-writeback.c       |   10 ++++++++++
 3 files changed, 14 insertions(+), 2 deletions(-)

Index: latest/include/linux/writeback.h
===================================================================
--- latest.orig/include/linux/writeback.h
+++ latest/include/linux/writeback.h
@@ -115,6 +115,7 @@ int sync_page_range(struct inode *inode,
 			loff_t pos, loff_t count);
 int sync_page_range_nolock(struct inode *inode, struct address_space *mapping,
 			   loff_t pos, loff_t count);
+void set_page_dirty_balance(struct page *page);
 
 /* pdflush.c */
 extern int nr_pdflush_threads;	/* Global so it can be exported to sysctl
Index: latest/mm/memory.c
===================================================================
--- latest.orig/mm/memory.c
+++ latest/mm/memory.c
@@ -49,6 +49,7 @@
 #include <linux/module.h>
 #include <linux/delayacct.h>
 #include <linux/init.h>
+#include <linux/writeback.h>
 
 #include <asm/pgalloc.h>
 #include <asm/uaccess.h>
@@ -1571,7 +1572,7 @@ gotten:
 unlock:
 	pte_unmap_unlock(page_table, ptl);
 	if (dirty_page) {
-		set_page_dirty(dirty_page);
+		set_page_dirty_balance(dirty_page);
 		put_page(dirty_page);
 	}
 	return ret;
@@ -2218,7 +2219,7 @@ retry:
 unlock:
 	pte_unmap_unlock(page_table, ptl);
 	if (dirty_page) {
-		set_page_dirty(dirty_page);
+		set_page_dirty_balance(dirty_page);
 		put_page(dirty_page);
 	}
 	return ret;
Index: latest/mm/page-writeback.c
===================================================================
--- latest.orig/mm/page-writeback.c
+++ latest/mm/page-writeback.c
@@ -244,6 +244,16 @@ static void balance_dirty_pages(struct a
 		pdflush_operation(background_writeout, 0);
 }
 
+void set_page_dirty_balance(struct page *page)
+{
+	if (set_page_dirty(page)) {
+		struct address_space *mapping = page_mapping(page);
+
+		if (mapping)
+			balance_dirty_pages_ratelimited(mapping);
+	}
+}
+
 /**
  * balance_dirty_pages_ratelimited_nr - balance dirty memory state
  * @mapping: address_space which was dirtied
Date: Mon, 17 Jul 2006 20:32:41 +0200
From: pzijlstr@redhat.com
Subject: [RHEL5][PATCH 3/8] mm: optimize the new mprotect code a bit


From: Peter Zijlstra <a.p.zijlstra@chello.nl>

mprotect() resets the page protections, which could result in extra write
faults for those pages whose dirty state we track using write faults
and are dirty already.

Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
---
 mm/mprotect.c |   31 ++++++++++++++++++++++---------
 1 file changed, 22 insertions(+), 9 deletions(-)

Index: latest/mm/mprotect.c
===================================================================
--- latest.orig/mm/mprotect.c
+++ latest/mm/mprotect.c
@@ -28,7 +28,8 @@
 #include <asm/tlbflush.h>
 
 static void change_pte_range(struct mm_struct *mm, pmd_t *pmd,
-		unsigned long addr, unsigned long end, pgprot_t newprot)
+		unsigned long addr, unsigned long end, pgprot_t newprot,
+		int dirty_accountable)
 {
 	pte_t *pte, oldpte;
 	spinlock_t *ptl;
@@ -43,7 +44,14 @@ static void change_pte_range(struct mm_s
 			 * bits by wiping the pte and then setting the new pte
 			 * into place.
 			 */
-			ptent = pte_modify(ptep_get_and_clear(mm, addr, pte), newprot);
+			ptent = ptep_get_and_clear(mm, addr, pte);
+			ptent = pte_modify(ptent, newprot);
+			/*
+			 * Avoid taking write faults for pages we know to be
+			 * dirty.
+			 */
+			if (dirty_accountable && pte_dirty(ptent))
+				ptent = pte_mkwrite(ptent);
 			set_pte_at(mm, addr, pte, ptent);
 			lazy_mmu_prot_update(ptent);
 #ifdef CONFIG_MIGRATION
@@ -67,7 +75,8 @@ static void change_pte_range(struct mm_s
 }
 
 static inline void change_pmd_range(struct mm_struct *mm, pud_t *pud,
-		unsigned long addr, unsigned long end, pgprot_t newprot)
+		unsigned long addr, unsigned long end, pgprot_t newprot,
+		int dirty_accountable)
 {
 	pmd_t *pmd;
 	unsigned long next;
@@ -77,12 +86,13 @@ static inline void change_pmd_range(stru
 		next = pmd_addr_end(addr, end);
 		if (pmd_none_or_clear_bad(pmd))
 			continue;
-		change_pte_range(mm, pmd, addr, next, newprot);
+		change_pte_range(mm, pmd, addr, next, newprot, dirty_accountable);
 	} while (pmd++, addr = next, addr != end);
 }
 
 static inline void change_pud_range(struct mm_struct *mm, pgd_t *pgd,
-		unsigned long addr, unsigned long end, pgprot_t newprot)
+		unsigned long addr, unsigned long end, pgprot_t newprot,
+		int dirty_accountable)
 {
 	pud_t *pud;
 	unsigned long next;
@@ -92,12 +102,13 @@ static inline void change_pud_range(stru
 		next = pud_addr_end(addr, end);
 		if (pud_none_or_clear_bad(pud))
 			continue;
-		change_pmd_range(mm, pud, addr, next, newprot);
+		change_pmd_range(mm, pud, addr, next, newprot, dirty_accountable);
 	} while (pud++, addr = next, addr != end);
 }
 
 static void change_protection(struct vm_area_struct *vma,
-		unsigned long addr, unsigned long end, pgprot_t newprot)
+		unsigned long addr, unsigned long end, pgprot_t newprot,
+		int dirty_accountable)
 {
 	struct mm_struct *mm = vma->vm_mm;
 	pgd_t *pgd;
@@ -111,7 +122,7 @@ static void change_protection(struct vm_
 		next = pgd_addr_end(addr, end);
 		if (pgd_none_or_clear_bad(pgd))
 			continue;
-		change_pud_range(mm, pgd, addr, next, newprot);
+		change_pud_range(mm, pgd, addr, next, newprot, dirty_accountable);
 	} while (pgd++, addr = next, addr != end);
 	flush_tlb_range(vma, start, end);
 }
@@ -126,6 +137,7 @@ mprotect_fixup(struct vm_area_struct *vm
 	unsigned long charged = 0, old_end = vma->vm_end;
 	pgoff_t pgoff;
 	int error;
+	int dirty_accountable = 0;
 
 	if (newflags == oldflags) {
 		*pprev = vma;
@@ -184,14 +196,16 @@ success:
 		arch_remove_exec_range(current->mm, old_end);
 	vma->vm_page_prot = protection_map[newflags &
 		(VM_READ|VM_WRITE|VM_EXEC|VM_SHARED)];
-	if (vma_wants_writenotify(vma))
+	if (vma_wants_writenotify(vma)) {
 		vma->vm_page_prot = protection_map[newflags &
 			(VM_READ|VM_WRITE|VM_EXEC)];
+		dirty_accountable = 1;
+	}
 
 	if (is_vm_hugetlb_page(vma))
 		hugetlb_change_protection(vma, start, end, vma->vm_page_prot);
 	else
-		change_protection(vma, start, end, vma->vm_page_prot);
+		change_protection(vma, start, end, vma->vm_page_prot, dirty_accountable);
 	vm_stat_account(mm, oldflags, vma->vm_file, -nrpages);
 	vm_stat_account(mm, newflags, vma->vm_file, nrpages);
 	return 0;
Date: Mon, 17 Jul 2006 20:32:49 +0200
From: pzijlstr@redhat.com
Subject: [RHEL5][PATCH 4/8] mm: small cleanup of install_page()


From: Peter Zijlstra <a.p.zijlstra@chello.nl>

Smallish cleanup to install_page(), could save a memory read (haven't checked
the asm output) and sure looks nicer.

Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Hugh Dickins <hugh@veritas.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 mm/fremap.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

Index: latest/mm/fremap.c
===================================================================
--- latest.orig/mm/fremap.c
+++ latest/mm/fremap.c
@@ -81,9 +81,9 @@ int install_page(struct mm_struct *mm, s
 		inc_mm_counter(mm, file_rss);
 
 	flush_icache_page(vma, page);
-	set_pte_at(mm, addr, pte, mk_pte(page, prot));
+	pte_val = mk_pte(page, prot);
+	set_pte_at(mm, addr, pte, pte_val);
 	page_add_file_rmap(page);
-	pte_val = *pte;
 	update_mmu_cache(vma, addr, pte_val);
 	lazy_mmu_prot_update(pte_val);
 	err = 0;
Date: Mon, 17 Jul 2006 20:32:56 +0200
From: pzijlstr@redhat.com
Subject: [RHEL5][PATCH 5/8] mm: fixup do_wp_page()


From: Peter Zijlstra <a.p.zijlstra@chello.nl>

Wrt. the recent modifications in do_wp_page() Hugh Dickins pointed out:

"I now realize it's right to the first
order (normal case) and to the second order (ptrace poke), but not
to the third order (ptrace poke anon page here to be COWed -
perhaps can't occur without intervening mprotects)."

This patch restores the old COW behaviour for anonymous pages.

Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Acked-by: Hugh Dickins <hugh@veritas.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 mm/memory.c |   19 +++++++++++++------
 1 files changed, 13 insertions(+), 6 deletions(-)

Index: latest/mm/memory.c
===================================================================
--- latest.orig/mm/memory.c
+++ latest/mm/memory.c
@@ -1467,11 +1467,21 @@ static int do_wp_page(struct mm_struct *
 		goto gotten;
 
 	/*
-	 * Only catch write-faults on shared writable pages, read-only
-	 * shared pages can get COWed by get_user_pages(.write=1, .force=1).
+	 * Take out anonymous pages first, anonymous shared vmas are
+	 * not dirty accountable.
 	 */
-	if (unlikely((vma->vm_flags & (VM_WRITE|VM_SHARED)) ==
+	if (PageAnon(old_page)) {
+		if (!TestSetPageLocked(old_page)) {
+			reuse = can_share_swap_page(old_page);
+			unlock_page(old_page);
+		}
+	} else if (unlikely((vma->vm_flags & (VM_WRITE|VM_SHARED)) ==
 					(VM_WRITE|VM_SHARED))) {
+		/*
+		 * Only catch write-faults on shared writable pages,
+		 * read-only shared pages can get COWed by
+		 * get_user_pages(.write=1, .force=1).
+		 */
 		if (vma->vm_ops && vma->vm_ops->page_mkwrite) {
 			/*
 			 * Notify the address space that the page is about to
@@ -1503,9 +1513,6 @@ static int do_wp_page(struct mm_struct *
 		dirty_page = old_page;
 		get_page(dirty_page);
 		reuse = 1;
-	} else if (PageAnon(old_page) && !TestSetPageLocked(old_page)) {
-		reuse = can_share_swap_page(old_page);
-		unlock_page(old_page);
 	}
 
 	if (reuse) {
Date: Mon, 17 Jul 2006 20:33:03 +0200
From: pzijlstr@redhat.com
Subject: [RHEL5][PATCH 6/8] mm: msync cleanup


From: Peter Zijlstra <a.p.zijlstra@chello.nl>

With the tracking of dirty pages properly done now, msync doesn't need to scan
the PTEs anymore to determine the dirty status.

From: Hugh Dickins <hugh@veritas.com>

In looking to do that, I made some other tidyups: can remove several
#includes, and sys_msync loop termination not quite right.

Most of those points are criticisms of the existing sys_msync, not of your
patch.  In particular, the loop termination errors were introduced in 2.6.17:
I did notice this shortly before it came out, but decided I was more likely to
get it wrong myself, and make matters worse if I tried to rush a last-minute
fix in.  And it's not terribly likely to go wrong, nor disastrous if it does
go wrong (may miss reporting an unmapped area; may also fsync file of a
following vma).

Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: Hugh Dickins <hugh@veritas.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 mm/msync.c |  196 ++++++++-------------------------------------------
 1 file changed, 33 insertions(+), 163 deletions(-)

Index: latest/mm/msync.c
===================================================================
--- latest.orig/mm/msync.c
+++ latest/mm/msync.c
@@ -7,149 +7,33 @@
 /*
  * The msync() system call.
  */
-#include <linux/slab.h>
-#include <linux/pagemap.h>
 #include <linux/fs.h>
 #include <linux/mm.h>
 #include <linux/mman.h>
-#include <linux/hugetlb.h>
-#include <linux/writeback.h>
 #include <linux/file.h>
 #include <linux/syscalls.h>
 
-#include <asm/pgtable.h>
-#include <asm/tlbflush.h>
-
-static unsigned long msync_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
-				unsigned long addr, unsigned long end)
-{
-	pte_t *pte;
-	spinlock_t *ptl;
-	int progress = 0;
-	unsigned long ret = 0;
-
-again:
-	pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
-	do {
-		struct page *page;
-
-		if (progress >= 64) {
-			progress = 0;
-			if (need_resched() || need_lockbreak(ptl))
-				break;
-		}
-		progress++;
-		if (!pte_present(*pte))
-			continue;
-		if (!pte_maybe_dirty(*pte))
-			continue;
-		page = vm_normal_page(vma, addr, *pte);
-		if (!page)
-			continue;
-		if (ptep_clear_flush_dirty(vma, addr, pte) ||
-				page_test_and_clear_dirty(page))
-			ret += set_page_dirty(page);
-		progress += 3;
-	} while (pte++, addr += PAGE_SIZE, addr != end);
-	pte_unmap_unlock(pte - 1, ptl);
-	cond_resched();
-	if (addr != end)
-		goto again;
-	return ret;
-}
-
-static inline unsigned long msync_pmd_range(struct vm_area_struct *vma,
-			pud_t *pud, unsigned long addr, unsigned long end)
-{
-	pmd_t *pmd;
-	unsigned long next;
-	unsigned long ret = 0;
-
-	pmd = pmd_offset(pud, addr);
-	do {
-		next = pmd_addr_end(addr, end);
-		if (pmd_none_or_clear_bad(pmd))
-			continue;
-		ret += msync_pte_range(vma, pmd, addr, next);
-	} while (pmd++, addr = next, addr != end);
-	return ret;
-}
-
-static inline unsigned long msync_pud_range(struct vm_area_struct *vma,
-			pgd_t *pgd, unsigned long addr, unsigned long end)
-{
-	pud_t *pud;
-	unsigned long next;
-	unsigned long ret = 0;
-
-	pud = pud_offset(pgd, addr);
-	do {
-		next = pud_addr_end(addr, end);
-		if (pud_none_or_clear_bad(pud))
-			continue;
-		ret += msync_pmd_range(vma, pud, addr, next);
-	} while (pud++, addr = next, addr != end);
-	return ret;
-}
-
-static unsigned long msync_page_range(struct vm_area_struct *vma,
-				unsigned long addr, unsigned long end)
-{
-	pgd_t *pgd;
-	unsigned long next;
-	unsigned long ret = 0;
-
-	/* For hugepages we can't go walking the page table normally,
-	 * but that's ok, hugetlbfs is memory based, so we don't need
-	 * to do anything more on an msync().
-	 */
-	if (vma->vm_flags & VM_HUGETLB)
-		return 0;
-
-	BUG_ON(addr >= end);
-	pgd = pgd_offset(vma->vm_mm, addr);
-	flush_cache_range(vma, addr, end);
-	do {
-		next = pgd_addr_end(addr, end);
-		if (pgd_none_or_clear_bad(pgd))
-			continue;
-		ret += msync_pud_range(vma, pgd, addr, next);
-	} while (pgd++, addr = next, addr != end);
-	return ret;
-}
-
 /*
  * MS_SYNC syncs the entire file - including mappings.
  *
- * MS_ASYNC does not start I/O (it used to, up to 2.5.67).  Instead, it just
- * marks the relevant pages dirty.  The application may now run fsync() to
+ * MS_ASYNC does not start I/O (it used to, up to 2.5.67).
+ * Nor does it marks the relevant pages dirty (it used to up to 2.6.17).
+ * Now it doesn't do anything, since dirty pages are properly tracked.
+ *
+ * The application may now run fsync() to
  * write out the dirty pages and wait on the writeout and check the result.
  * Or the application may run fadvise(FADV_DONTNEED) against the fd to start
  * async writeout immediately.
  * So by _not_ starting I/O in MS_ASYNC we provide complete flexibility to
  * applications.
  */
-static int msync_interval(struct vm_area_struct *vma, unsigned long addr,
-			unsigned long end, int flags,
-			unsigned long *nr_pages_dirtied)
-{
-	struct file *file = vma->vm_file;
-
-	if ((flags & MS_INVALIDATE) && (vma->vm_flags & VM_LOCKED))
-		return -EBUSY;
-
-	if (file && (vma->vm_flags & VM_SHARED))
-		*nr_pages_dirtied = msync_page_range(vma, addr, end);
-	return 0;
-}
-
 asmlinkage long sys_msync(unsigned long start, size_t len, int flags)
 {
 	unsigned long end;
+	struct mm_struct *mm = current->mm;
 	struct vm_area_struct *vma;
 	int unmapped_error = 0;
 	int error = -EINVAL;
-	int done = 0;
 
 	if (flags & ~(MS_ASYNC | MS_INVALIDATE | MS_SYNC))
 		goto out;
@@ -169,64 +53,50 @@ asmlinkage long sys_msync(unsigned long 
 	 * If the interval [start,end) covers some unmapped address ranges,
 	 * just ignore them, but return -ENOMEM at the end.
 	 */
-	down_read(&current->mm->mmap_sem);
-	vma = find_vma(current->mm, start);
-	if (!vma) {
-		error = -ENOMEM;
-		goto out_unlock;
-	}
-	do {
-		unsigned long nr_pages_dirtied = 0;
+	down_read(&mm->mmap_sem);
+	vma = find_vma(mm, start);
+	for (;;) {
 		struct file *file;
 
+		/* Still start < end. */
+		error = -ENOMEM;
+		if (!vma)
+			goto out_unlock;
 		/* Here start < vma->vm_end. */
 		if (start < vma->vm_start) {
-			unmapped_error = -ENOMEM;
 			start = vma->vm_start;
+			if (start >= end)
+				goto out_unlock;
+			unmapped_error = -ENOMEM;
 		}
 		/* Here vma->vm_start <= start < vma->vm_end. */
-		if (end <= vma->vm_end) {
-			if (start < end) {
-				error = msync_interval(vma, start, end, flags,
-							&nr_pages_dirtied);
-				if (error)
-					goto out_unlock;
-			}
-			error = unmapped_error;
-			done = 1;
-		} else {
-			/* Here vma->vm_start <= start < vma->vm_end < end. */
-			error = msync_interval(vma, start, vma->vm_end, flags,
-						&nr_pages_dirtied);
-			if (error)
-				goto out_unlock;
+		if ((flags & MS_INVALIDATE) &&
+				(vma->vm_flags & VM_LOCKED)) {
+			error = -EBUSY;
+			goto out_unlock;
 		}
 		file = vma->vm_file;
 		start = vma->vm_end;
-		if ((flags & MS_ASYNC) && file && nr_pages_dirtied) {
-			get_file(file);
-			up_read(&current->mm->mmap_sem);
-			balance_dirty_pages_ratelimited_nr(file->f_mapping,
-							nr_pages_dirtied);
-			fput(file);
-			down_read(&current->mm->mmap_sem);
-			vma = find_vma(current->mm, start);
-		} else if ((flags & MS_SYNC) && file &&
+		if ((flags & MS_SYNC) && file &&
 				(vma->vm_flags & VM_SHARED)) {
 			get_file(file);
-			up_read(&current->mm->mmap_sem);
+			up_read(&mm->mmap_sem);
 			error = do_fsync(file, 0);
 			fput(file);
-			down_read(&current->mm->mmap_sem);
-			if (error)
-				goto out_unlock;
-			vma = find_vma(current->mm, start);
+			if (error || start >= end)
+				goto out;
+			down_read(&mm->mmap_sem);
+			vma = find_vma(mm, start);
 		} else {
+			if (start >= end) {
+				error = 0;
+				goto out_unlock;
+			}
 			vma = vma->vm_next;
 		}
-	} while (vma && !done);
+	}
 out_unlock:
-	up_read(&current->mm->mmap_sem);
+	up_read(&mm->mmap_sem);
 out:
-	return error;
+	return error ? : unmapped_error;
 }
Date: Mon, 17 Jul 2006 20:33:11 +0200
From: pzijlstr@redhat.com
Subject: [RHEL5][PATCH 7/8] mm: tracking shared dirty pages checks


From: Andrew Morton <akpm@osdl.org>

Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 mm/page-writeback.c |    2 ++
 1 files changed, 2 insertions(+)

Index: latest/mm/page-writeback.c
===================================================================
--- latest.orig/mm/page-writeback.c
+++ latest/mm/page-writeback.c
@@ -717,6 +717,7 @@ int test_clear_page_dirty(struct page *p
 	struct address_space *mapping = page_mapping(page);
 	unsigned long flags;
 
+	WARN_ON_ONCE(!PageLocked(page));
 	if (mapping) {
 		write_lock_irqsave(&mapping->tree_lock, flags);
 		if (TestClearPageDirty(page)) {
@@ -759,6 +760,7 @@ int clear_page_dirty_for_io(struct page 
 {
 	struct address_space *mapping = page_mapping(page);
 
+	WARN_ON_ONCE(!PageLocked(page));
 	if (mapping) {
 		if (TestClearPageDirty(page)) {
 			if (mapping_cap_account_dirty(mapping)) {
Date: Mon, 17 Jul 2006 20:33:18 +0200
From: pzijlstr@redhat.com
Subject: [RHEL5][PATCH 8/8] mm: tracking shared dirty pages wimp.patch


From: Andrew Morton <akpm@osdl.org>

I'm not so sure, and if this is wrong, we wreck an -mm release.  Please don't
wreck -mm releases.

Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Hugh Dickins <hugh@veritas.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 mm/rmap.c |    2 +-
 1 files changed, 1 insertion(+), 1 deletion(-)

Index: latest/mm/rmap.c
===================================================================
--- latest.orig/mm/rmap.c
+++ latest/mm/rmap.c
@@ -488,7 +488,7 @@ int page_mkclean(struct page *page)
 {
 	int ret = 0;
 
-	BUG_ON(!PageLocked(page));
+	WARN_ON_ONCE(!PageLocked(page));
 
 	if (page_mapped(page)) {
 		struct address_space *mapping = page_mapping(page);

--- End Message ---
--- Begin Message ---
Source: linux-2.6
Source-Version: 2.6.18.dfsg.1-9

We believe that the bug you reported is fixed in the latest version of
linux-2.6, which is due to be installed in the Debian FTP archive:

linux-2.6_2.6.18.dfsg.1-9.diff.gz
  to pool/main/l/linux-2.6/linux-2.6_2.6.18.dfsg.1-9.diff.gz
linux-2.6_2.6.18.dfsg.1-9.dsc
  to pool/main/l/linux-2.6/linux-2.6_2.6.18.dfsg.1-9.dsc
linux-2.6_2.6.18.dfsg.1.orig.tar.gz
  to pool/main/l/linux-2.6/linux-2.6_2.6.18.dfsg.1.orig.tar.gz
linux-doc-2.6.18_2.6.18.dfsg.1-9_all.deb
  to pool/main/l/linux-2.6/linux-doc-2.6.18_2.6.18.dfsg.1-9_all.deb
linux-headers-2.6.18-4-all-powerpc_2.6.18.dfsg.1-9_powerpc.deb
  to pool/main/l/linux-2.6/linux-headers-2.6.18-4-all-powerpc_2.6.18.dfsg.1-9_powerpc.deb
linux-headers-2.6.18-4-all_2.6.18.dfsg.1-9_powerpc.deb
  to pool/main/l/linux-2.6/linux-headers-2.6.18-4-all_2.6.18.dfsg.1-9_powerpc.deb
linux-headers-2.6.18-4-powerpc-miboot_2.6.18.dfsg.1-9_powerpc.deb
  to pool/main/l/linux-2.6/linux-headers-2.6.18-4-powerpc-miboot_2.6.18.dfsg.1-9_powerpc.deb
linux-headers-2.6.18-4-powerpc-smp_2.6.18.dfsg.1-9_powerpc.deb
  to pool/main/l/linux-2.6/linux-headers-2.6.18-4-powerpc-smp_2.6.18.dfsg.1-9_powerpc.deb
linux-headers-2.6.18-4-powerpc64_2.6.18.dfsg.1-9_powerpc.deb
  to pool/main/l/linux-2.6/linux-headers-2.6.18-4-powerpc64_2.6.18.dfsg.1-9_powerpc.deb
linux-headers-2.6.18-4-powerpc_2.6.18.dfsg.1-9_powerpc.deb
  to pool/main/l/linux-2.6/linux-headers-2.6.18-4-powerpc_2.6.18.dfsg.1-9_powerpc.deb
linux-headers-2.6.18-4-prep_2.6.18.dfsg.1-9_powerpc.deb
  to pool/main/l/linux-2.6/linux-headers-2.6.18-4-prep_2.6.18.dfsg.1-9_powerpc.deb
linux-headers-2.6.18-4-vserver-powerpc64_2.6.18.dfsg.1-9_powerpc.deb
  to pool/main/l/linux-2.6/linux-headers-2.6.18-4-vserver-powerpc64_2.6.18.dfsg.1-9_powerpc.deb
linux-headers-2.6.18-4-vserver-powerpc_2.6.18.dfsg.1-9_powerpc.deb
  to pool/main/l/linux-2.6/linux-headers-2.6.18-4-vserver-powerpc_2.6.18.dfsg.1-9_powerpc.deb
linux-headers-2.6.18-4-vserver_2.6.18.dfsg.1-9_powerpc.deb
  to pool/main/l/linux-2.6/linux-headers-2.6.18-4-vserver_2.6.18.dfsg.1-9_powerpc.deb
linux-headers-2.6.18-4_2.6.18.dfsg.1-9_powerpc.deb
  to pool/main/l/linux-2.6/linux-headers-2.6.18-4_2.6.18.dfsg.1-9_powerpc.deb
linux-image-2.6.18-4-powerpc-miboot_2.6.18.dfsg.1-9_powerpc.deb
  to pool/main/l/linux-2.6/linux-image-2.6.18-4-powerpc-miboot_2.6.18.dfsg.1-9_powerpc.deb
linux-image-2.6.18-4-powerpc-smp_2.6.18.dfsg.1-9_powerpc.deb
  to pool/main/l/linux-2.6/linux-image-2.6.18-4-powerpc-smp_2.6.18.dfsg.1-9_powerpc.deb
linux-image-2.6.18-4-powerpc64_2.6.18.dfsg.1-9_powerpc.deb
  to pool/main/l/linux-2.6/linux-image-2.6.18-4-powerpc64_2.6.18.dfsg.1-9_powerpc.deb
linux-image-2.6.18-4-powerpc_2.6.18.dfsg.1-9_powerpc.deb
  to pool/main/l/linux-2.6/linux-image-2.6.18-4-powerpc_2.6.18.dfsg.1-9_powerpc.deb
linux-image-2.6.18-4-prep_2.6.18.dfsg.1-9_powerpc.deb
  to pool/main/l/linux-2.6/linux-image-2.6.18-4-prep_2.6.18.dfsg.1-9_powerpc.deb
linux-image-2.6.18-4-vserver-powerpc64_2.6.18.dfsg.1-9_powerpc.deb
  to pool/main/l/linux-2.6/linux-image-2.6.18-4-vserver-powerpc64_2.6.18.dfsg.1-9_powerpc.deb
linux-image-2.6.18-4-vserver-powerpc_2.6.18.dfsg.1-9_powerpc.deb
  to pool/main/l/linux-2.6/linux-image-2.6.18-4-vserver-powerpc_2.6.18.dfsg.1-9_powerpc.deb
linux-manual-2.6.18_2.6.18.dfsg.1-9_all.deb
  to pool/main/l/linux-2.6/linux-manual-2.6.18_2.6.18.dfsg.1-9_all.deb
linux-patch-debian-2.6.18_2.6.18.dfsg.1-9_all.deb
  to pool/main/l/linux-2.6/linux-patch-debian-2.6.18_2.6.18.dfsg.1-9_all.deb
linux-source-2.6.18_2.6.18.dfsg.1-9_all.deb
  to pool/main/l/linux-2.6/linux-source-2.6.18_2.6.18.dfsg.1-9_all.deb
linux-support-2.6.18-4_2.6.18.dfsg.1-9_all.deb
  to pool/main/l/linux-2.6/linux-support-2.6.18-4_2.6.18.dfsg.1-9_all.deb
linux-tree-2.6.18_2.6.18.dfsg.1-9_all.deb
  to pool/main/l/linux-2.6/linux-tree-2.6.18_2.6.18.dfsg.1-9_all.deb



A summary of the changes between this version and the previous one is
attached.

Thank you for reporting the bug, which will now be closed.  If you
have further comments please address them to 394392@bugs.debian.org,
and the maintainer will reopen the bug report if appropriate.

Debian distribution maintenance software
pp.
Bastian Blank <waldi@debian.org> (supplier of updated linux-2.6 package)

(This message was generated automatically at their request; if you
believe that there is a problem with it please contact the archive
administrators by mailing ftpmaster@debian.org)


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Format: 1.7
Date: Wed, 24 Jan 2007 13:21:51 +0100
Source: linux-2.6
Binary: linux-image-2.6.18-4-powerpc-miboot linux-headers-2.6.18-4-parisc-smp linux-modules-2.6.18-4-xen-vserver-amd64 linux-headers-2.6.18-4-vserver-amd64 linux-image-2.6.18-4-sparc64-smp linux-image-2.6.18-4-sparc32 linux-image-2.6.18-4-footbridge linux-headers-2.6.18-4-xen-vserver-686 linux-headers-2.6.18-4-powerpc linux-headers-2.6.18-4-all-i386 linux-image-2.6.18-4-alpha-legacy linux-headers-2.6.18-4-vserver-s390x linux-image-2.6.18-4-686 linux-headers-2.6.18-4-686-bigmem linux-headers-2.6.18-4-s3c2410 linux-headers-2.6.18-4-sb1a-bcm91480b linux-image-2.6.18-4-vserver-powerpc linux-manual-2.6.18 linux-headers-2.6.18-4-sb1-bcm91250a xen-linux-system-2.6.18-4-xen-vserver-686 linux-image-2.6.18-4-xen-vserver-amd64 linux-headers-2.6.18-4-all-s390 linux-image-2.6.18-4-prep linux-headers-2.6.18-4-vserver-alpha linux-headers-2.6.18-4-amd64 linux-headers-2.6.18-4-amiga linux-headers-2.6.18-4-mckinley linux-headers-2.6.18-4-parisc64-smp linux-image-2.6.18-4-mckinley linux-headers-2.6.18-4-vserver-686 linux-image-2.6.18-4-686-bigmem linux-image-2.6.18-4-s390-tape linux-headers-2.6.18-4-iop32x linux-headers-2.6.18-4 linux-headers-2.6.18-4-vserver-sparc64 linux-image-2.6.18-4-s390x linux-headers-2.6.18-4-parisc64 linux-headers-2.6.18-4-xen-vserver linux-headers-2.6.18-4-all-m68k linux-headers-2.6.18-4-all-ia64 linux-image-2.6.18-4-mac linux-headers-2.6.18-4-s390x linux-image-2.6.18-4-powerpc-smp linux-headers-2.6.18-4-all-amd64 linux-headers-2.6.18-4-686 linux-image-2.6.18-4-powerpc64 linux-headers-2.6.18-4-mac xen-linux-system-2.6.18-4-xen-amd64 linux-image-2.6.18-4-vserver-alpha linux-image-2.6.18-4-sb1-bcm91250a linux-modules-2.6.18-4-xen-amd64 linux-image-2.6.18-4-amiga linux-image-2.6.18-4-xen-vserver-686 linux-headers-2.6.18-4-powerpc64 linux-image-2.6.18-4-powerpc linux-headers-2.6.18-4-all linux-image-2.6.18-4-r5k-cobalt linux-headers-2.6.18-4-all-powerpc linux-headers-2.6.18-4-itanium linux-image-2.6.18-4-sparc64 linux-headers-2.6.18-4-alpha-legacy linux-image-2.6.18-4-rpc linux-headers-2.6.18-4-sparc64 linux-image-2.6.18-4-alpha-generic linux-image-2.6.18-4-ixp4xx linux-image-2.6.18-4-parisc64 linux-headers-2.6.18-4-footbridge linux-headers-2.6.18-4-xen-amd64 linux-headers-2.6.18-4-powerpc-miboot linux-headers-2.6.18-4-xen-686 linux-modules-2.6.18-4-xen-vserver-686 linux-image-2.6.18-4-s3c2410 linux-image-2.6.18-4-vserver-sparc64 linux-headers-2.6.18-4-atari linux-doc-2.6.18 linux-headers-2.6.18-4-all-alpha linux-image-2.6.18-4-vserver-s390x linux-headers-2.6.18-4-xen-vserver-amd64 linux-image-2.6.18-4-sb1a-bcm91480b linux-image-2.6.18-4-vserver-powerpc64 linux-image-2.6.18-4-alpha-smp linux-image-2.6.18-4-parisc64-smp linux-image-2.6.18-4-r3k-kn02 linux-support-2.6.18-4 linux-source-2.6.18 linux-headers-2.6.18-4-k7 linux-headers-2.6.18-4-vserver linux-modules-2.6.18-4-xen-686 linux-headers-2.6.18-4-r4k-kn04 linux-headers-2.6.18-4-all-mipsel linux-headers-2.6.18-4-vserver-k7 linux-headers-2.6.18-4-r3k-kn02 linux-headers-2.6.18-4-all-sparc linux-headers-2.6.18-4-rpc linux-headers-2.6.18-4-r5k-cobalt xen-linux-system-2.6.18-4-xen-686 linux-headers-2.6.18-4-sparc64-smp linux-image-2.6.18-4-s390 linux-image-2.6.18-4-486 linux-headers-2.6.18-4-vserver-powerpc64 linux-image-2.6.18-4-r4k-kn04 linux-headers-2.6.18-4-r5k-ip32 linux-image-2.6.18-4-iop32x linux-headers-2.6.18-4-all-mips linux-headers-2.6.18-4-ixp4xx linux-image-2.6.18-4-parisc-smp linux-headers-2.6.18-4-s390 linux-headers-2.6.18-4-vserver-powerpc linux-image-2.6.18-4-vserver-686 linux-headers-2.6.18-4-all-hppa linux-image-2.6.18-4-parisc linux-image-2.6.18-4-vserver-amd64 linux-image-2.6.18-4-vserver-k7 linux-headers-2.6.18-4-r4k-ip22 linux-image-2.6.18-4-xen-686 linux-image-2.6.18-4-r5k-ip32 linux-headers-2.6.18-4-sparc32 linux-image-2.6.18-4-r4k-ip22 linux-patch-debian-2.6.18 linux-headers-2.6.18-4-powerpc-smp linux-headers-2.6.18-4-alpha-smp linux-tree-2.6.18 xen-linux-system-2.6.18-4-xen-vserver-amd64 linux-image-2.6.18-4-k7 linux-image-2.6.18-4-qemu linux-headers-2.6.18-4-qemu linux-headers-2.6.18-4-xen linux-headers-2.6.18-4-alpha-generic linux-headers-2.6.18-4-parisc linux-image-2.6.18-4-amd64 linux-headers-2.6.18-4-prep linux-image-2.6.18-4-itanium linux-image-2.6.18-4-xen-amd64 linux-headers-2.6.18-4-486 linux-headers-2.6.18-4-all-arm linux-image-2.6.18-4-atari
Architecture: source powerpc all
Version: 2.6.18.dfsg.1-9
Distribution: unstable
Urgency: low
Maintainer: Debian Kernel Team <debian-kernel@lists.debian.org>
Changed-By: Bastian Blank <waldi@debian.org>
Description: 
 linux-doc-2.6.18 - Linux kernel specific documentation for version 2.6.18
 linux-headers-2.6.18-4 - Common header files for Linux 2.6.18
 linux-headers-2.6.18-4-all - All header files for Linux 2.6.18
 linux-headers-2.6.18-4-all-powerpc - All header files for Linux 2.6.18
 linux-headers-2.6.18-4-powerpc - Header files for Linux 2.6.18 on uniprocessor 32-bit PowerPC
 linux-headers-2.6.18-4-powerpc-miboot - Header files for Linux 2.6.18 on 32-bit PowerPC for miboot floppy
 linux-headers-2.6.18-4-powerpc-smp - Header files for Linux 2.6.18 on multiprocessor 32-bit PowerPC
 linux-headers-2.6.18-4-powerpc64 - Header files for Linux 2.6.18 on 64-bit PowerPC
 linux-headers-2.6.18-4-prep - Header files for Linux 2.6.18 on PReP PowerPC
 linux-headers-2.6.18-4-vserver - Common header files for Linux 2.6.18
 linux-headers-2.6.18-4-vserver-powerpc - Header files for Linux 2.6.18 on uniprocessor 32-bit PowerPC
 linux-headers-2.6.18-4-vserver-powerpc64 - Header files for Linux 2.6.18 on 64-bit PowerPC
 linux-image-2.6.18-4-powerpc - Linux 2.6.18 image on uniprocessor 32-bit PowerPC
 linux-image-2.6.18-4-powerpc-miboot - Linux 2.6.18 image on 32-bit PowerPC for miboot floppy
 linux-image-2.6.18-4-powerpc-smp - Linux 2.6.18 image on multiprocessor 32-bit PowerPC
 linux-image-2.6.18-4-powerpc64 - Linux 2.6.18 image on 64-bit PowerPC
 linux-image-2.6.18-4-prep - Linux 2.6.18 image on PReP PowerPC
 linux-image-2.6.18-4-vserver-powerpc - Linux 2.6.18 image on uniprocessor 32-bit PowerPC
 linux-image-2.6.18-4-vserver-powerpc64 - Linux 2.6.18 image on 64-bit PowerPC
 linux-manual-2.6.18 - Linux kernel API manual pages for version 2.6.18
 linux-patch-debian-2.6.18 - Debian patches to version 2.6.18 of the Linux kernel
 linux-source-2.6.18 - Linux kernel source for version 2.6.18 with Debian patches
 linux-support-2.6.18-4 - Support files for Linux 2.6.18
 linux-tree-2.6.18 - Linux kernel source tree for building Debian kernel images
Closes: 292318 334104 350482 378542 388870 390862 391867 392592 394392 394753 400524 401006 401187 401980 402253 402475 402707 402743 402787 402812 402876 403790 404216 404447 405085 405150 405196 405203 406124 406767 407671
Changes: 
 linux-2.6 (2.6.18.dfsg.1-9) unstable; urgency=low
 .
   [ Martin Michlmayr ]
   * arm/iop32x: Enable CONFIG_IP_NF_CONNTRACK_EVENTS and _NETLINK.
   * arm/ixp4xx: Enable some more I2C sensor modules.
   * arm/ixp4xx: Enable CONFIG_USB_NET_RNDIS_HOST.
   * arm/footbridge: Enable CONFIG_NATSEMI.
   * Revert mm/msync patches because they cause filesystem corruption
     (closes: #401006, #401980, #402707) ...
   * ... and add an alternative msync patch from Hugh Dickins that
     doesn't depend on the mm changes (closes: #394392).
   * mips: provide pci_get_legacy_ide_irq needed by some IDE drivers
     (see #404950).
   * arm: Implement flush_anon_page(), which is needed for FUSE
     (closes: #402876) and possibly dm-crypt/LUKS (see #403426).
   * arm: Turn off PCI burst on the Cyber2010, otherwise X11 on
     Netwinder will crash.
   * arm/iop32x: Enable CONFIG_IEEE80211_SOFTMAC and drivers based
     on it.
   * arm/ixp4xx: Upgrade to version 0.3.1 of the IXP4xx NPE Ethernet
     driver.  This version fixes stuck connections, e.g. with scp and
     NFS (closes: #404447).
   * arm/ixp4xx: Enable CONFIG_VIDEO_CPIA_USB.
   * arm/ixp4xx: Enable CONFIG_ISCSI_TCP.
   * arm/iop32x: Likewise.
 .
   [ Bastian Blank ]
   * Bump ABI to 4.
   * Update vserver patch to 2.0.2.2-rc9. (closes: #402743, #403790)
   * Update xen patch to changeset 36186 from Fedora 2.6.18 branch.
   * i386/xen: Build only the pae version. (closes: #390862)
   * hppa: Override host type when necessary.
   * Fix tg3 reset. (closes: #405085)
 .
   [ dann frazier ]
   * Fix potential fragmentation attacks in ip6_tables (CVE-2006-4572)
   * Backport a number of fixes for the cciss driver
     - Fix a bug with 1TB disks caused by converting total_size to an int
     - Claim devices that are of the HP RAID class and have a valid cciss sig
     - Make NR_CMDS a per-controller define - most can do 1024 commands, but
       the E200 family can only support 128
     - Change the SSID on the E500 as a workaround for a firmware bug
     - Disable prefetch on the P600 controller. An ASIC bug may result in
       prefetching beyond the end of physical memory
     - Increase blk_queue_max_sectors from 512 to 2048 to increase performance
     - Map out more memor for the PCI config table, required to reach offset
       0x214 to disable DMA on the P600
     - Set a default raid level on a volume that either does not support
       reading the geometry or reports an invalid geometry for whatever reason
       to avoid problems with buggy firmware
     - Revert change that replaed XFER_READ/XFER_WRITE macros with
       h->cciss_read/h->cciss_write that caused command timeouts on older
       controllers on ia32 (closes: #402787)
   * Fix mincore hang (CVE-2006-4814)
   * ia64: turn on IOC4 modules for SGI Altix systems. Thanks to Stephane Larose
     for suggesting this.
   * Add versioned build dep on findutils to make sure the system find command
     supports the -execdir action (closes: #405150)
   * Hardcode the output of the scripts under arch/ia64/scripts as executed
     in an etch environment so that we can build out of tree modules correctly
     (closes: #392592)
   * Update unusual_devs entry for ipod to fix an eject issue (closes: #406124)
   * Re-add verify_pmtmr_rate, resolving problems seen on older K6 ASUS
     boards where the ACPI PM timer runs too fast (closes: #394753)
   * Avoid condition where /proc/swaps header may not be printed
     (closes: #292318)
   * [hppa] disable XFS until it works (closes: #350482)
 .
   [ Norbert Tretkowski ]
   * libata: handle 0xff status properly. (closes: #391867)
   * alpha: enabled CONFIG_SCSI_ARCMSR. (closes: #401187)
   * removed BROKEN_ON_SMP dependency from I2C_ELEKTOR. (closes: #402253)
 .
   [ Christian T. Steigies ]
   * m68k/atari: enable keyboard, mouse and fb drivers
   * m68k/atari: fixes for ethernec and video driver by Michael Schmitz
   * m68k/atari: fixes for scsi driver by Michael Schmitz
   * m68k/mac: fixes for mace and cuda driver by Finn Thain
   * m68k/atari: fixes for ide driver by Michael Schmitz
   * m68k/atari: fixes for ide driver by Michael Schmitz
   * m68k/atari: fixes for ethernec and atakeyb driver by Michael Schmitz, build ethernec as module
   * m68k/mac: fixes for mace and adb driver by Finn Thain
 .
   [ maximilian attems ]
   * Add stable release 2.6.18.6:
     - EBTABLES: Fix wraparounds in ebt_entries verification.
     - EBTABLES: Verify that ebt_entries have zero ->distinguisher.
     - EBTABLES: Deal with the worst-case behaviour in loop checks.
     - EBTABLES: Prevent wraparounds in checks for entry components' sizes.
     - skip data conversion in compat_sys_mount when data_page is NULL
     - bonding: incorrect bonding state reported via ioctl
     - x86-64: Mark rdtsc as sync only for netburst, not for core2
       (closes: #406767)
     - dm crypt: Fix data corruption with dm-crypt over RAID5 (closes: #402812)
     - forcedeth: Disable INTx when enabling MSI in forcedeth
     - PKT_SCHED act_gact: division by zero
     - XFRM: Use output device disable_xfrm for forwarded packets
     - IPSEC: Fix inetpeer leak in ipv4 xfrm dst entries.
     - V4L: Fix broken TUNER_LG_NTSC_TAPE radio support
     - m32r: make userspace headers platform-independent
     - IrDA: Incorrect TTP header reservation
     - SUNHME: Fix for sunhme failures on x86
     - Bluetooth: Add packet size checks for CAPI messages (CVE-2006-6106)
     - softmac: remove netif_tx_disable when scanning
     - DVB: lgdt330x: fix signal / lock status detection bug
     - dm snapshot: fix freeing pending exception
     - NET_SCHED: policer: restore compatibility with old iproute binaries
     - NETFILTER: ip_tables: revision support for compat code
     - ARM: Add sys_*at syscalls
     - ieee1394: ohci1394: add PPC_PMAC platform code to driver probe
     - softirq: remove BUG_ONs which can incorrectly trigger
   * Hand-picked from stable release 2.6.16.30:
     - [PPPOE]: Advertise PPPoE MTU
   * Hand-picked from stable release 2.6.16.31:
     - [NETFILTER]: Fix ip6_tables extension header bypass bug (CVE-2006-4572)
     - fix RARP ic_servaddr breakage
   * Hand-picked from stable release 2.6.16.32:
     - drivers/telephony/ixj: fix an array overrun
     - flush D-cache in failure path
   * Hand-picked from stable release 2.6.16.33:
     - Add new PHY to sis900 supported list
     - ipmi_si_intf.c: fix "&& 0xff" typos
     - drivers/scsi/psi240i.c: fix an array overrun
   * Hand-picked from stable release 2.6.16.34:
     - [IPX]: Annotate and fix IPX checksum
     - [IGMP]: Fix IGMPV3_EXP() normalization bit shift value.
   * Hand-picked from stable release 2.6.16.35:
     - sgiioc4: Disable module unload
     - Fix a masking bug in the 6pack driver.
     - drivers/usb/input/ati_remote.c: fix cut'n'paste error
     - proper flags type of spin_lock_irqsave()
   * Hand-picked from stable release 2.6.16.37:
     - [CRYPTO] sha512: Fix sha384 block size
     - [SCSI] gdth: Fix && typos
     - Fix SUNRPC wakeup/execute race condition
   * Enable DEBUG_FS for usbmon in generic config. Don't disable it on alpha,
     amd64, hppa and ia64. (closes: 378542)
   * Backport a number of upstream fixes for the r8169 driver, needed for
     network performance (closes: 388870, 400524)
     - r8169: more alignment for the 0x8168
     - r8169: phy program update
     - r8169: more magic during initialization of the hardware
     - r8169: perform a PHY reset before any other operation at boot time
     - r8169: Fix iteration variable sign
     - r8169: remove extraneous Cmd{Tx/Rx}Enb write
   * sound: hda: detect ALC883 on MSI K9A Platinum motherboards (MS-7280)
     patch from Leonard Norrgard <leonard.norrgard@refactor.fi>
   * tulip: Add i386 specific patch to remove duplicate pci ids.
     Thanks Jurij Smakov <jurij@wooyd.org> (closes: #334104, #405203)
   * amd64, i386: Disable SK98LIN as SKGE is the modern capable driver.
     (closes: 405196)
   * Backout net-bcm43xx_netdev_watchdog.patch and push 2.6.18.2 fix.
     (closes: 402475)
 .
   [ Jurij Smakov ]
   * Add bugfix/sparc/isa-dev-no-reg.patch to make sure that
     isa_dev_get_resource() can deal with devices which do not have a 'reg'
     PROM property. Failure to handle such devices properly resulted in an
     oops during boot on Netra X1. Thanks to Richard Mortimer for debugging
     and patch. (closes: #404216)
   * Add bugfix/sparc/ehci-hub-contol-alignment.patch to prevent unaligned
     memory accesses in ehci-hub-control() by adding an alignment attribute
     to the tbuf array declaration. Thanks to David Miller for the patch.
 .
   [ Sven Luther ]
   * [powerpc] Enable CONFIG_PMAC_BACKLIGHT_LEGACY (Closes: #407671).
Files: 
 49d7b7efb8fdbd5934d540326511d039 5668 devel optional linux-2.6_2.6.18.dfsg.1-9.dsc
 6a1ab0948d6b5b453ea0fce0fcc29060 52225460 devel optional linux-2.6_2.6.18.dfsg.1.orig.tar.gz
 f9b4ce9c8858e60bff8df61320979058 1751644 devel optional linux-2.6_2.6.18.dfsg.1-9.diff.gz
 361727680d344dd0f54395ff0559c2d9 3599818 doc optional linux-doc-2.6.18_2.6.18.dfsg.1-9_all.deb
 d64023d9a6dcd48052ade816e83ac6b5 1077570 doc optional linux-manual-2.6.18_2.6.18.dfsg.1-9_all.deb
 c137d1ae26a25ed5abbc80ed7ed08a97 1381068 devel optional linux-patch-debian-2.6.18_2.6.18.dfsg.1-9_all.deb
 42bb1cfb596bd6943f7b470bad91a16a 41405074 devel optional linux-source-2.6.18_2.6.18.dfsg.1-9_all.deb
 ff81d2e0076a38e8c138ec6e6b8cdcbe 256914 devel optional linux-support-2.6.18-4_2.6.18.dfsg.1-9_all.deb
 523eedfb16eea3d54e4aadd39b5bea15 46704 devel optional linux-tree-2.6.18_2.6.18.dfsg.1-9_all.deb
 009c7593a4d7a7fdc920d03ac9f5063d 46324 devel optional linux-headers-2.6.18-4-all_2.6.18.dfsg.1-9_powerpc.deb
 c081769c0ee34f178bbcf295ae680334 46362 devel optional linux-headers-2.6.18-4-all-powerpc_2.6.18.dfsg.1-9_powerpc.deb
 7bfef65fb41af53c65bf04b49acb2e76 3384936 devel optional linux-headers-2.6.18-4_2.6.18.dfsg.1-9_powerpc.deb
 31802301a891fa8ca04c8243ebacb513 16624056 admin optional linux-image-2.6.18-4-powerpc_2.6.18.dfsg.1-9_powerpc.deb
 4d0567e8930f6f161aeb194bfa290c7f 244466 devel optional linux-headers-2.6.18-4-powerpc_2.6.18.dfsg.1-9_powerpc.deb
 7ca5ded0ed70b95e7e47b72d84574714 16962266 admin optional linux-image-2.6.18-4-powerpc-smp_2.6.18.dfsg.1-9_powerpc.deb
 3702c2d53014a43159727d028381e099 245074 devel optional linux-headers-2.6.18-4-powerpc-smp_2.6.18.dfsg.1-9_powerpc.deb
 7d738536a29475b610bd1ce813cf4162 15153182 admin optional linux-image-2.6.18-4-powerpc-miboot_2.6.18.dfsg.1-9_powerpc.deb
 5309f291ed7d7cfc4907a496fd69fe16 221424 devel optional linux-headers-2.6.18-4-powerpc-miboot_2.6.18.dfsg.1-9_powerpc.deb
 04ba8c1055666bbb7208634740e85f46 18286116 admin optional linux-image-2.6.18-4-powerpc64_2.6.18.dfsg.1-9_powerpc.deb
 5e79d913194cd37d829e42e4c614e46d 245508 devel optional linux-headers-2.6.18-4-powerpc64_2.6.18.dfsg.1-9_powerpc.deb
 ecd6445553c674876f4b3fe8e4b5182f 16397570 admin optional linux-image-2.6.18-4-prep_2.6.18.dfsg.1-9_powerpc.deb
 ea551ce3247794bfd5e54eb03b3d4ec8 238890 devel optional linux-headers-2.6.18-4-prep_2.6.18.dfsg.1-9_powerpc.deb
 382551eae1580ce294f11683a1ae5026 3407174 devel optional linux-headers-2.6.18-4-vserver_2.6.18.dfsg.1-9_powerpc.deb
 28b8bb4e11aa5c8100571967fc5f6d48 17002466 admin optional linux-image-2.6.18-4-vserver-powerpc_2.6.18.dfsg.1-9_powerpc.deb
 9ddd8711a8d0a5db35abd16ce843107e 245292 devel optional linux-headers-2.6.18-4-vserver-powerpc_2.6.18.dfsg.1-9_powerpc.deb
 a905785bc4181069af71222c60fce608 18340762 admin optional linux-image-2.6.18-4-vserver-powerpc64_2.6.18.dfsg.1-9_powerpc.deb
 d1a9db2cf82babebaadbd8f2631e9edb 245790 devel optional linux-headers-2.6.18-4-vserver-powerpc64_2.6.18.dfsg.1-9_powerpc.deb

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)

iEYEARECAAYFAkW3a90ACgkQLkAIIn9ODhGAYQCfeM36zDQjC4xPmsvT7rmEl0tl
BJwAn0yGab2sjAJQTofYGhHq8ZT4TZLs
=SOBi
-----END PGP SIGNATURE-----


--- End Message ---

Reply to: