]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
more patches queued up
authorGreg Kroah-Hartman <gregkh@suse.de>
Wed, 11 Apr 2007 21:41:18 +0000 (14:41 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Wed, 11 Apr 2007 21:41:18 +0000 (14:41 -0700)
queue-2.6.20/fix-page-leak-during-core-dump.patch [new file with mode: 0644]
queue-2.6.20/revert-retries-in-ext3_prepare_write-violate-ordering-requirements.patch [new file with mode: 0644]
queue-2.6.20/revert-retries-in-ext4_prepare_write-violate-ordering-requirements.patch [new file with mode: 0644]
queue-2.6.20/series

diff --git a/queue-2.6.20/fix-page-leak-during-core-dump.patch b/queue-2.6.20/fix-page-leak-during-core-dump.patch
new file mode 100644 (file)
index 0000000..e6d553b
--- /dev/null
@@ -0,0 +1,54 @@
+From stable-bounces@linux.kernel.org Sun Apr  1 23:50:55 2007
+From: Brian Pomerantz <bapper@piratehaven.org>
+Date: Sun, 01 Apr 2007 23:49:41 -0700
+Subject: fix page leak during core dump
+To: torvalds@linux-foundation.org
+Cc: nickpiggin@yahoo.com.au, bapper@mvista.com, bapper@piratehaven.org, dhowells@redhat.com, hugh@veritas.com, akpm@linux-foundation.org, stable@kernel.org
+Message-ID: <200704020649.l326nfGZ026528@shell0.pdx.osdl.net>
+
+
+From: Brian Pomerantz <bapper@piratehaven.org>
+
+When the dump cannot occur most likely because of a full file system and
+the page to be written is the zero page, the call to page_cache_release()
+is missed.
+
+Signed-off-by: Brian Pomerantz <bapper@mvista.com>
+Cc: Hugh Dickins <hugh@veritas.com>
+Cc: Nick Piggin <nickpiggin@yahoo.com.au>
+Cc: David Howells <dhowells@redhat.com>
+Cc: <stable@kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/binfmt_elf.c       |    5 ++++-
+ fs/binfmt_elf_fdpic.c |    2 +-
+ 2 files changed, 5 insertions(+), 2 deletions(-)
+
+--- a/fs/binfmt_elf.c
++++ b/fs/binfmt_elf.c
+@@ -1704,7 +1704,10 @@ static int elf_core_dump(long signr, str
+                               DUMP_SEEK(PAGE_SIZE);
+                       } else {
+                               if (page == ZERO_PAGE(addr)) {
+-                                      DUMP_SEEK(PAGE_SIZE);
++                                      if (!dump_seek(file, PAGE_SIZE)) {
++                                              page_cache_release(page);
++                                              goto end_coredump;
++                                      }
+                               } else {
+                                       void *kaddr;
+                                       flush_cache_page(vma, addr,
+--- a/fs/binfmt_elf_fdpic.c
++++ b/fs/binfmt_elf_fdpic.c
+@@ -1473,8 +1473,8 @@ static int elf_fdpic_dump_segments(struc
+                               DUMP_SEEK(file->f_pos + PAGE_SIZE);
+                       }
+                       else if (page == ZERO_PAGE(addr)) {
+-                              DUMP_SEEK(file->f_pos + PAGE_SIZE);
+                               page_cache_release(page);
++                              DUMP_SEEK(file->f_pos + PAGE_SIZE);
+                       }
+                       else {
+                               void *kaddr;
diff --git a/queue-2.6.20/revert-retries-in-ext3_prepare_write-violate-ordering-requirements.patch b/queue-2.6.20/revert-retries-in-ext3_prepare_write-violate-ordering-requirements.patch
new file mode 100644 (file)
index 0000000..e5dfdb2
--- /dev/null
@@ -0,0 +1,173 @@
+From stable-bounces@linux.kernel.org Sun Apr  1 23:51:13 2007
+From: Andrew Morton <akpm@linux-foundation.org>
+Date: Sun, 01 Apr 2007 23:49:43 -0700
+Subject: revert "retries in ext3_prepare_write() violate ordering requirements"
+To: torvalds@linux-foundation.org
+Cc: dev@openvz.org, stable@kernel.org, kenneth.w.chen@intel.com, saw@sw.ru, dmonakhov@openvz.org, akpm@linux-foundation.org, linux-ext4@vger.kernel.org, mingo@elte.hu
+Message-ID: <200704020649.l326nhD1026534@shell0.pdx.osdl.net>
+
+
+From: Andrew Morton <akpm@linux-foundation.org>
+
+Revert e92a4d595b464c4aae64be39ca61a9ffe9c8b278.
+
+Dmitry points out
+
+"When we block_prepare_write() failed while ext3_prepare_write() we jump to
+ "failure" label and call ext3_prepare_failure() witch search last mapped bh
+ and invoke commit_write untill it.  This is wrong!!  because some bh from
+ begining to the last mapped bh may be not uptodate.  As a result we commit to
+ disk not uptodate page content witch contains garbage from previous usage."
+
+and
+
+"Unexpected file size increasing."
+
+   Call trace the same as it was in first issue but result is different. 
+   For example we have file with i_size is zero.  we want write two blocks ,
+   but fs has only one free block.
+
+   ->ext3_prepare_write(...from == 0, to == 2048)
+     retry:
+     ->block_prepare_write() == -ENOSPC# we failed but allocated one block here.
+     ->ext3_prepare_failure()
+       ->commit_write( from == 0, to == 1024) # after this i_size becomes 1024 :)
+     if (ret == -ENOSPC && ext3_should_retry_alloc(inode->i_sb, &retries))
+        goto retry;
+
+   Finally when all retries will be spended ext3_prepare_failure return
+   -ENOSPC, but i_size was increased and later block trimm procedures can't
+   help here.
+
+We don't appear to have the horsepower to fix these issues, so let's put
+things back the way they were for now.
+
+Cc: Kirill Korotaev <dev@openvz.org>
+Cc: Ingo Molnar <mingo@elte.hu>
+Cc: Ken Chen <kenneth.w.chen@intel.com>
+Cc: Andrey Savochkin <saw@sw.ru>
+Cc: <linux-ext4@vger.kernel.org>
+Cc: Dmitriy Monakhov <dmonakhov@openvz.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+
+---
+ fs/ext3/inode.c |   85 ++++++--------------------------------------------------
+ 1 file changed, 10 insertions(+), 75 deletions(-)
+
+--- a/fs/ext3/inode.c
++++ b/fs/ext3/inode.c
+@@ -1148,102 +1148,37 @@ static int do_journal_get_write_access(h
+       return ext3_journal_get_write_access(handle, bh);
+ }
+-/*
+- * The idea of this helper function is following:
+- * if prepare_write has allocated some blocks, but not all of them, the
+- * transaction must include the content of the newly allocated blocks.
+- * This content is expected to be set to zeroes by block_prepare_write().
+- * 2006/10/14  SAW
+- */
+-static int ext3_prepare_failure(struct file *file, struct page *page,
+-                              unsigned from, unsigned to)
+-{
+-      struct address_space *mapping;
+-      struct buffer_head *bh, *head, *next;
+-      unsigned block_start, block_end;
+-      unsigned blocksize;
+-      int ret;
+-      handle_t *handle = ext3_journal_current_handle();
+-
+-      mapping = page->mapping;
+-      if (ext3_should_writeback_data(mapping->host)) {
+-              /* optimization: no constraints about data */
+-skip:
+-              return ext3_journal_stop(handle);
+-      }
+-
+-      head = page_buffers(page);
+-      blocksize = head->b_size;
+-      for (   bh = head, block_start = 0;
+-              bh != head || !block_start;
+-              block_start = block_end, bh = next)
+-      {
+-              next = bh->b_this_page;
+-              block_end = block_start + blocksize;
+-              if (block_end <= from)
+-                      continue;
+-              if (block_start >= to) {
+-                      block_start = to;
+-                      break;
+-              }
+-              if (!buffer_mapped(bh))
+-              /* prepare_write failed on this bh */
+-                      break;
+-              if (ext3_should_journal_data(mapping->host)) {
+-                      ret = do_journal_get_write_access(handle, bh);
+-                      if (ret) {
+-                              ext3_journal_stop(handle);
+-                              return ret;
+-                      }
+-              }
+-      /*
+-       * block_start here becomes the first block where the current iteration
+-       * of prepare_write failed.
+-       */
+-      }
+-      if (block_start <= from)
+-              goto skip;
+-
+-      /* commit allocated and zeroed buffers */
+-      return mapping->a_ops->commit_write(file, page, from, block_start);
+-}
+-
+ static int ext3_prepare_write(struct file *file, struct page *page,
+                             unsigned from, unsigned to)
+ {
+       struct inode *inode = page->mapping->host;
+-      int ret, ret2;
+-      int needed_blocks = ext3_writepage_trans_blocks(inode);
++      int ret, needed_blocks = ext3_writepage_trans_blocks(inode);
+       handle_t *handle;
+       int retries = 0;
+ retry:
+       handle = ext3_journal_start(inode, needed_blocks);
+-      if (IS_ERR(handle))
+-              return PTR_ERR(handle);
++      if (IS_ERR(handle)) {
++              ret = PTR_ERR(handle);
++              goto out;
++      }
+       if (test_opt(inode->i_sb, NOBH) && ext3_should_writeback_data(inode))
+               ret = nobh_prepare_write(page, from, to, ext3_get_block);
+       else
+               ret = block_prepare_write(page, from, to, ext3_get_block);
+       if (ret)
+-              goto failure;
++              goto prepare_write_failed;
+       if (ext3_should_journal_data(inode)) {
+               ret = walk_page_buffers(handle, page_buffers(page),
+                               from, to, NULL, do_journal_get_write_access);
+-              if (ret)
+-                      /* fatal error, just put the handle and return */
+-                      journal_stop(handle);
+       }
+-      return ret;
+-
+-failure:
+-      ret2 = ext3_prepare_failure(file, page, from, to);
+-      if (ret2 < 0)
+-              return ret2;
++prepare_write_failed:
++      if (ret)
++              ext3_journal_stop(handle);
+       if (ret == -ENOSPC && ext3_should_retry_alloc(inode->i_sb, &retries))
+               goto retry;
+-      /* retry number exceeded, or other error like -EDQUOT */
++out:
+       return ret;
+ }
diff --git a/queue-2.6.20/revert-retries-in-ext4_prepare_write-violate-ordering-requirements.patch b/queue-2.6.20/revert-retries-in-ext4_prepare_write-violate-ordering-requirements.patch
new file mode 100644 (file)
index 0000000..c83cf99
--- /dev/null
@@ -0,0 +1,141 @@
+From stable-bounces@linux.kernel.org Sun Apr  1 23:51:19 2007
+From: Andrew Morton <akpm@linux-foundation.org>
+Date: Sun, 01 Apr 2007 23:49:44 -0700
+Subject: revert "retries in ext4_prepare_write() violate ordering requirements"
+To: torvalds@linux-foundation.org
+Cc: dev@openvz.org, stable@kernel.org, kenneth.w.chen@intel.com, saw@sw.ru, dmonakhov@openvz.org, akpm@linux-foundation.org, linux-ext4@vger.kernel.org, mingo@elte.hu
+Message-ID: <200704020649.l326niVR026539@shell0.pdx.osdl.net>
+
+
+From: Andrew Morton <akpm@linux-foundation.org>
+
+Revert b46be05004abb419e303e66e143eed9f8a6e9f3f.  Same reasoning as for ext3.
+
+Cc: Kirill Korotaev <dev@openvz.org>
+Cc: Ingo Molnar <mingo@elte.hu>
+Cc: Ken Chen <kenneth.w.chen@intel.com>
+Cc: Andrey Savochkin <saw@sw.ru>
+Cc: <linux-ext4@vger.kernel.org>
+Cc: Dmitriy Monakhov <dmonakhov@openvz.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/ext4/inode.c |   85 ++++++--------------------------------------------------
+ 1 file changed, 10 insertions(+), 75 deletions(-)
+
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -1147,102 +1147,37 @@ static int do_journal_get_write_access(h
+       return ext4_journal_get_write_access(handle, bh);
+ }
+-/*
+- * The idea of this helper function is following:
+- * if prepare_write has allocated some blocks, but not all of them, the
+- * transaction must include the content of the newly allocated blocks.
+- * This content is expected to be set to zeroes by block_prepare_write().
+- * 2006/10/14  SAW
+- */
+-static int ext4_prepare_failure(struct file *file, struct page *page,
+-                              unsigned from, unsigned to)
+-{
+-      struct address_space *mapping;
+-      struct buffer_head *bh, *head, *next;
+-      unsigned block_start, block_end;
+-      unsigned blocksize;
+-      int ret;
+-      handle_t *handle = ext4_journal_current_handle();
+-
+-      mapping = page->mapping;
+-      if (ext4_should_writeback_data(mapping->host)) {
+-              /* optimization: no constraints about data */
+-skip:
+-              return ext4_journal_stop(handle);
+-      }
+-
+-      head = page_buffers(page);
+-      blocksize = head->b_size;
+-      for (   bh = head, block_start = 0;
+-              bh != head || !block_start;
+-              block_start = block_end, bh = next)
+-      {
+-              next = bh->b_this_page;
+-              block_end = block_start + blocksize;
+-              if (block_end <= from)
+-                      continue;
+-              if (block_start >= to) {
+-                      block_start = to;
+-                      break;
+-              }
+-              if (!buffer_mapped(bh))
+-              /* prepare_write failed on this bh */
+-                      break;
+-              if (ext4_should_journal_data(mapping->host)) {
+-                      ret = do_journal_get_write_access(handle, bh);
+-                      if (ret) {
+-                              ext4_journal_stop(handle);
+-                              return ret;
+-                      }
+-              }
+-      /*
+-       * block_start here becomes the first block where the current iteration
+-       * of prepare_write failed.
+-       */
+-      }
+-      if (block_start <= from)
+-              goto skip;
+-
+-      /* commit allocated and zeroed buffers */
+-      return mapping->a_ops->commit_write(file, page, from, block_start);
+-}
+-
+ static int ext4_prepare_write(struct file *file, struct page *page,
+                             unsigned from, unsigned to)
+ {
+       struct inode *inode = page->mapping->host;
+-      int ret, ret2;
+-      int needed_blocks = ext4_writepage_trans_blocks(inode);
++      int ret, needed_blocks = ext4_writepage_trans_blocks(inode);
+       handle_t *handle;
+       int retries = 0;
+ retry:
+       handle = ext4_journal_start(inode, needed_blocks);
+-      if (IS_ERR(handle))
+-              return PTR_ERR(handle);
++      if (IS_ERR(handle)) {
++              ret = PTR_ERR(handle);
++              goto out;
++      }
+       if (test_opt(inode->i_sb, NOBH) && ext4_should_writeback_data(inode))
+               ret = nobh_prepare_write(page, from, to, ext4_get_block);
+       else
+               ret = block_prepare_write(page, from, to, ext4_get_block);
+       if (ret)
+-              goto failure;
++              goto prepare_write_failed;
+       if (ext4_should_journal_data(inode)) {
+               ret = walk_page_buffers(handle, page_buffers(page),
+                               from, to, NULL, do_journal_get_write_access);
+-              if (ret)
+-                      /* fatal error, just put the handle and return */
+-                      ext4_journal_stop(handle);
+       }
+-      return ret;
+-
+-failure:
+-      ret2 = ext4_prepare_failure(file, page, from, to);
+-      if (ret2 < 0)
+-              return ret2;
++prepare_write_failed:
++      if (ret)
++              ext4_journal_stop(handle);
+       if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))
+               goto retry;
+-      /* retry number exceeded, or other error like -EDQUOT */
++out:
+       return ret;
+ }
index b1eb0c3881daff292e81fb3fe0122dbd5ec31f69..e44a4a501d5c95f83341b0412fc525cc4fd505a3 100644 (file)
@@ -25,3 +25,6 @@ libata-bugfix-preserve-lba-bit-for-hdio_drive_task.patch
 ahci.c-walkaround-for-sb600-sata-internal-error-issue.patch
 fix-lba48-bug-in-libata-fill_result_tf.patch
 libata-clear-tf-before-doing-request-sense.patch
+revert-retries-in-ext3_prepare_write-violate-ordering-requirements.patch
+revert-retries-in-ext4_prepare_write-violate-ordering-requirements.patch
+fix-page-leak-during-core-dump.patch