All of lore.kernel.org
 help / color / mirror / Atom feed
From: angelo <angelo70@gmail.com>
To: linux-kernel@vger.kernel.org
Cc: linux-mm@kvack.org
Subject: [PATCH] mm: fix cpu hangs on truncating last page of a 16t sparse file
Date: Sun, 27 Sep 2015 01:02:16 +0200	[thread overview]
Message-ID: <560723F8.3010909@gmail.com> (raw)

Hi all,

running xfstests, generic 308 on whatever 32bit arch is possible
to observe cpu to hang near 100% on unlink.
The test removes a sparse file of length 16tera where only the last
4096 bytes block is mapped.
At line 265 of truncate.c there is a
if (index >= end)
     break;
But if index is, as in this case, a 4294967295, it match -1 used as
eof. Hence the cpu loops 100% just after.

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

On 32bit archs, with CONFIG_LBDAF=y, if truncating last page
of a 16tera file, "index" variable is set to 4294967295, and hence
matches with -1 used as EOF value. This result in an inifite loop
when unlink is executed on this file.

Signed-off-by: Angelo Dureghello <angelo@sysam.it>
---
  mm/truncate.c | 11 ++++++-----
  1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/mm/truncate.c b/mm/truncate.c
index 76e35ad..3751034 100644
--- a/mm/truncate.c
+++ b/mm/truncate.c
@@ -283,14 +283,15 @@ void truncate_inode_pages_range(struct 
address_space *mapping,
                 pagevec_remove_exceptionals(&pvec);
                 pagevec_release(&pvec);
                 cond_resched();
-               index++;
+               if (index < end)
+                       index++;
         }

         if (partial_start) {
                 struct page *page = find_lock_page(mapping, start - 1);
                 if (page) {
                         unsigned int top = PAGE_CACHE_SIZE;
-                       if (start > end) {
+                       if (start > end && end != -1) {
                                 /* Truncation within a single page */
                                 top = partial_end;
                                 partial_end = 0;
@@ -322,7 +323,7 @@ void truncate_inode_pages_range(struct address_space 
*mapping,
          * If the truncation happened within a single page no pages
          * will be released, just zeroed, so we can bail out now.
          */
-       if (start >= end)
+       if (start >= end && end != -1)
                 return;

         index = start;
@@ -337,7 +338,7 @@ void truncate_inode_pages_range(struct address_space 
*mapping,
                         index = start;
                         continue;
                 }
-               if (index == start && indices[0] >= end) {
+               if (index == start && (indices[0] >= end && end != -1)) {
                         /* All gone out of hole to be punched, we're 
done */
                         pagevec_remove_exceptionals(&pvec);
                         pagevec_release(&pvec);
@@ -348,7 +349,7 @@ void truncate_inode_pages_range(struct address_space 
*mapping,

                         /* We rely upon deletion not changing 
page->index */
                         index = indices[i];
-                       if (index >= end) {
+                       if (index >= end && (end != -1)) {
                                 /* Restart punch to make sure all gone */
                                 index = start - 1;
                                 break;
-- 
2.5.3









--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

WARNING: multiple messages have this Message-ID (diff)
From: angelo <angelo70@gmail.com>
To: linux-kernel@vger.kernel.org
Cc: linux-mm@kvack.org
Subject: [PATCH] mm: fix cpu hangs on truncating last page of a 16t sparse file
Date: Sun, 27 Sep 2015 01:02:16 +0200	[thread overview]
Message-ID: <560723F8.3010909@gmail.com> (raw)

Hi all,

running xfstests, generic 308 on whatever 32bit arch is possible
to observe cpu to hang near 100% on unlink.
The test removes a sparse file of length 16tera where only the last
4096 bytes block is mapped.
At line 265 of truncate.c there is a
if (index >= end)
     break;
But if index is, as in this case, a 4294967295, it match -1 used as
eof. Hence the cpu loops 100% just after.

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

On 32bit archs, with CONFIG_LBDAF=y, if truncating last page
of a 16tera file, "index" variable is set to 4294967295, and hence
matches with -1 used as EOF value. This result in an inifite loop
when unlink is executed on this file.

Signed-off-by: Angelo Dureghello <angelo@sysam.it>
---
  mm/truncate.c | 11 ++++++-----
  1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/mm/truncate.c b/mm/truncate.c
index 76e35ad..3751034 100644
--- a/mm/truncate.c
+++ b/mm/truncate.c
@@ -283,14 +283,15 @@ void truncate_inode_pages_range(struct 
address_space *mapping,
                 pagevec_remove_exceptionals(&pvec);
                 pagevec_release(&pvec);
                 cond_resched();
-               index++;
+               if (index < end)
+                       index++;
         }

         if (partial_start) {
                 struct page *page = find_lock_page(mapping, start - 1);
                 if (page) {
                         unsigned int top = PAGE_CACHE_SIZE;
-                       if (start > end) {
+                       if (start > end && end != -1) {
                                 /* Truncation within a single page */
                                 top = partial_end;
                                 partial_end = 0;
@@ -322,7 +323,7 @@ void truncate_inode_pages_range(struct address_space 
*mapping,
          * If the truncation happened within a single page no pages
          * will be released, just zeroed, so we can bail out now.
          */
-       if (start >= end)
+       if (start >= end && end != -1)
                 return;

         index = start;
@@ -337,7 +338,7 @@ void truncate_inode_pages_range(struct address_space 
*mapping,
                         index = start;
                         continue;
                 }
-               if (index == start && indices[0] >= end) {
+               if (index == start && (indices[0] >= end && end != -1)) {
                         /* All gone out of hole to be punched, we're 
done */
                         pagevec_remove_exceptionals(&pvec);
                         pagevec_release(&pvec);
@@ -348,7 +349,7 @@ void truncate_inode_pages_range(struct address_space 
*mapping,

                         /* We rely upon deletion not changing 
page->index */
                         index = indices[i];
-                       if (index >= end) {
+                       if (index >= end && (end != -1)) {
                                 /* Restart punch to make sure all gone */
                                 index = start - 1;
                                 break;
-- 
2.5.3










             reply	other threads:[~2015-09-26 23:02 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-09-26 23:02 angelo [this message]
2015-09-26 23:02 ` [PATCH] mm: fix cpu hangs on truncating last page of a 16t sparse file angelo
2015-09-27  1:36 ` Hugh Dickins
2015-09-27  1:36   ` Hugh Dickins
2015-09-27  2:14   ` angelo
2015-09-27  2:14     ` angelo
2015-09-27  2:21   ` angelo
2015-09-27  2:21     ` angelo
2015-09-27 17:59     ` Hugh Dickins
2015-09-27 17:59       ` Hugh Dickins
2015-09-27 23:26       ` Dave Chinner
2015-09-27 23:26         ` Dave Chinner
2015-09-27 23:56         ` Jeff Layton
2015-09-27 23:56           ` Jeff Layton
2015-09-28  1:06           ` Dave Chinner
2015-09-28  1:06             ` Dave Chinner
2015-09-28 17:03       ` Andi Kleen
2015-09-28 17:03         ` Andi Kleen
2015-09-28 18:08         ` Hugh Dickins
2015-09-28 18:08           ` Hugh Dickins

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=560723F8.3010909@gmail.com \
    --to=angelo70@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.