| From 473441720c8616dfaf4451f9c7ea14f0eb5e5d65 Mon Sep 17 00:00:00 2001 |
| From: Miklos Szeredi <mszeredi@redhat.com> |
| Date: Thu, 25 Nov 2021 14:05:18 +0100 |
| Subject: fuse: release pipe buf after last use |
| |
| From: Miklos Szeredi <mszeredi@redhat.com> |
| |
| commit 473441720c8616dfaf4451f9c7ea14f0eb5e5d65 upstream. |
| |
| Checking buf->flags should be done before the pipe_buf_release() is called |
| on the pipe buffer, since releasing the buffer might modify the flags. |
| |
| This is exactly what page_cache_pipe_buf_release() does, and which results |
| in the same VM_BUG_ON_PAGE(PageLRU(page)) that the original patch was |
| trying to fix. |
| |
| Reported-by: Justin Forbes <jmforbes@linuxtx.org> |
| Fixes: 712a951025c0 ("fuse: fix page stealing") |
| Cc: <stable@vger.kernel.org> # v2.6.35 |
| Signed-off-by: Miklos Szeredi <mszeredi@redhat.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| fs/fuse/dev.c | 10 +++++----- |
| 1 file changed, 5 insertions(+), 5 deletions(-) |
| |
| --- a/fs/fuse/dev.c |
| +++ b/fs/fuse/dev.c |
| @@ -922,6 +922,11 @@ static int fuse_try_move_page(struct fus |
| return err; |
| } |
| |
| + page_cache_get(newpage); |
| + |
| + if (!(buf->flags & PIPE_BUF_FLAG_LRU)) |
| + lru_cache_add_file(newpage); |
| + |
| /* |
| * Release while we have extra ref on stolen page. Otherwise |
| * anon_pipe_buf_release() might think the page can be reused. |
| @@ -929,11 +934,6 @@ static int fuse_try_move_page(struct fus |
| buf->ops->release(cs->pipe, buf); |
| buf->ops = NULL; |
| |
| - page_cache_get(newpage); |
| - |
| - if (!(buf->flags & PIPE_BUF_FLAG_LRU)) |
| - lru_cache_add_file(newpage); |
| - |
| err = 0; |
| spin_lock(&cs->req->waitq.lock); |
| if (test_bit(FR_ABORTED, &cs->req->flags)) |