| From 7f556567036cb7f89aabe2f0954b08566b4efb53 Mon Sep 17 00:00:00 2001 |
| From: Hugh Dickins <hughd@google.com> |
| Date: Sun, 10 Jul 2016 16:46:32 -0700 |
| Subject: tmpfs: fix regression hang in fallocate undo |
| |
| From: Hugh Dickins <hughd@google.com> |
| |
| commit 7f556567036cb7f89aabe2f0954b08566b4efb53 upstream. |
| |
| The well-spotted fallocate undo fix is good in most cases, but not when |
| fallocate failed on the very first page. index 0 then passes lend -1 |
| to shmem_undo_range(), and that has two bad effects: (a) that it will |
| undo every fallocation throughout the file, unrestricted by the current |
| range; but more importantly (b) it can cause the undo to hang, because |
| lend -1 is treated as truncation, which makes it keep on retrying until |
| every page has gone, but those already fully instantiated will never go |
| away. Big thank you to xfstests generic/269 which demonstrates this. |
| |
| Fixes: b9b4bb26af01 ("tmpfs: don't undo fallocate past its last page") |
| Signed-off-by: Hugh Dickins <hughd@google.com> |
| Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| mm/shmem.c | 8 +++++--- |
| 1 file changed, 5 insertions(+), 3 deletions(-) |
| |
| --- a/mm/shmem.c |
| +++ b/mm/shmem.c |
| @@ -2153,9 +2153,11 @@ static long shmem_fallocate(struct file |
| NULL); |
| if (error) { |
| /* Remove the !PageUptodate pages we added */ |
| - shmem_undo_range(inode, |
| - (loff_t)start << PAGE_CACHE_SHIFT, |
| - ((loff_t)index << PAGE_CACHE_SHIFT) - 1, true); |
| + if (index > start) { |
| + shmem_undo_range(inode, |
| + (loff_t)start << PAGE_CACHE_SHIFT, |
| + ((loff_t)index << PAGE_CACHE_SHIFT) - 1, true); |
| + } |
| goto undone; |
| } |
| |