提交 9e0267c2 编写于 作者: J Jens Axboe

[PATCH] splice: fixup writeout path after ->map changes

Since ->map() no longer locks the page, we need to adjust the handling
of those pages (and stealing) a little. This now passes full regressions
again.
Signed-off-by: NJens Axboe <axboe@suse.de>
上级 a4514ebd
...@@ -50,7 +50,8 @@ static int page_cache_pipe_buf_steal(struct pipe_inode_info *info, ...@@ -50,7 +50,8 @@ static int page_cache_pipe_buf_steal(struct pipe_inode_info *info,
struct page *page = buf->page; struct page *page = buf->page;
struct address_space *mapping = page_mapping(page); struct address_space *mapping = page_mapping(page);
WARN_ON(!PageLocked(page)); lock_page(page);
WARN_ON(!PageUptodate(page)); WARN_ON(!PageUptodate(page));
/* /*
...@@ -65,8 +66,10 @@ static int page_cache_pipe_buf_steal(struct pipe_inode_info *info, ...@@ -65,8 +66,10 @@ static int page_cache_pipe_buf_steal(struct pipe_inode_info *info,
if (PagePrivate(page)) if (PagePrivate(page))
try_to_release_page(page, mapping_gfp_mask(mapping)); try_to_release_page(page, mapping_gfp_mask(mapping));
if (!remove_mapping(mapping, page)) if (!remove_mapping(mapping, page)) {
unlock_page(page);
return 1; return 1;
}
buf->flags |= PIPE_BUF_FLAG_STOLEN | PIPE_BUF_FLAG_LRU; buf->flags |= PIPE_BUF_FLAG_STOLEN | PIPE_BUF_FLAG_LRU;
return 0; return 0;
...@@ -507,14 +510,12 @@ static int pipe_to_file(struct pipe_inode_info *info, struct pipe_buffer *buf, ...@@ -507,14 +510,12 @@ static int pipe_to_file(struct pipe_inode_info *info, struct pipe_buffer *buf,
if (sd->flags & SPLICE_F_MOVE) { if (sd->flags & SPLICE_F_MOVE) {
/* /*
* If steal succeeds, buf->page is now pruned from the vm * If steal succeeds, buf->page is now pruned from the vm
* side (LRU and page cache) and we can reuse it. * side (LRU and page cache) and we can reuse it. The page
* will also be looked on successful return.
*/ */
if (buf->ops->steal(info, buf)) if (buf->ops->steal(info, buf))
goto find_page; goto find_page;
/*
* this will also set the page locked
*/
page = buf->page; page = buf->page;
if (add_to_page_cache(page, mapping, index, gfp_mask)) if (add_to_page_cache(page, mapping, index, gfp_mask))
goto find_page; goto find_page;
...@@ -523,15 +524,27 @@ static int pipe_to_file(struct pipe_inode_info *info, struct pipe_buffer *buf, ...@@ -523,15 +524,27 @@ static int pipe_to_file(struct pipe_inode_info *info, struct pipe_buffer *buf,
lru_cache_add(page); lru_cache_add(page);
} else { } else {
find_page: find_page:
ret = -ENOMEM; page = find_lock_page(mapping, index);
page = find_or_create_page(mapping, index, gfp_mask); if (!page) {
if (!page) ret = -ENOMEM;
goto out_nomem; page = page_cache_alloc_cold(mapping);
if (unlikely(!page))
goto out_nomem;
/*
* This will also lock the page
*/
ret = add_to_page_cache_lru(page, mapping, index,
gfp_mask);
if (unlikely(ret))
goto out;
}
/* /*
* If the page is uptodate, it is also locked. If it isn't * We get here with the page locked. If the page is also
* uptodate, we can mark it uptodate if we are filling the * uptodate, we don't need to do more. If it isn't, we
* full page. Otherwise we need to read it in first... * may need to bring it in if we are not going to overwrite
* the full page.
*/ */
if (!PageUptodate(page)) { if (!PageUptodate(page)) {
if (sd->len < PAGE_CACHE_SIZE) { if (sd->len < PAGE_CACHE_SIZE) {
...@@ -553,10 +566,8 @@ static int pipe_to_file(struct pipe_inode_info *info, struct pipe_buffer *buf, ...@@ -553,10 +566,8 @@ static int pipe_to_file(struct pipe_inode_info *info, struct pipe_buffer *buf,
ret = -EIO; ret = -EIO;
goto out; goto out;
} }
} else { } else
WARN_ON(!PageLocked(page));
SetPageUptodate(page); SetPageUptodate(page);
}
} }
} }
...@@ -585,10 +596,10 @@ static int pipe_to_file(struct pipe_inode_info *info, struct pipe_buffer *buf, ...@@ -585,10 +596,10 @@ static int pipe_to_file(struct pipe_inode_info *info, struct pipe_buffer *buf,
mark_page_accessed(page); mark_page_accessed(page);
balance_dirty_pages_ratelimited(mapping); balance_dirty_pages_ratelimited(mapping);
out: out:
if (!(buf->flags & PIPE_BUF_FLAG_STOLEN)) { if (!(buf->flags & PIPE_BUF_FLAG_STOLEN))
page_cache_release(page); page_cache_release(page);
unlock_page(page);
} unlock_page(page);
out_nomem: out_nomem:
buf->ops->unmap(info, buf); buf->ops->unmap(info, buf);
return ret; return ret;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册