aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorJens Axboe <axboe@suse.de>2006-05-02 09:03:27 -0400
committerJens Axboe <axboe@suse.de>2006-05-02 09:03:27 -0400
commita893b99be71f1d669b74f840e3a683dd077d007b (patch)
tree79591f70b57ef4504dc5c9584b7d8fcaa04faede /fs
parent7591489a8fbee83f19bacc75756989a6a4d0389c (diff)
[PATCH] splice: fix page LRU accounting
Currently we rely on the PIPE_BUF_FLAG_LRU flag being set correctly to know whether we need to fiddle with page LRU state after stealing it, however for some origins we just don't know if the page is on the LRU list or not. So remove PIPE_BUF_FLAG_LRU and do this check/add manually in pipe_to_file() instead. Signed-off-by: Jens Axboe <axboe@suse.de>
Diffstat (limited to 'fs')
-rw-r--r--fs/splice.c31
1 files changed, 21 insertions, 10 deletions
diff --git a/fs/splice.c b/fs/splice.c
index b0c157d7694..3318b965c10 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -78,7 +78,6 @@ static int page_cache_pipe_buf_steal(struct pipe_inode_info *info,
78 return 1; 78 return 1;
79 } 79 }
80 80
81 buf->flags |= PIPE_BUF_FLAG_LRU;
82 return 0; 81 return 0;
83} 82}
84 83
@@ -86,8 +85,6 @@ static void page_cache_pipe_buf_release(struct pipe_inode_info *info,
86 struct pipe_buffer *buf) 85 struct pipe_buffer *buf)
87{ 86{
88 page_cache_release(buf->page); 87 page_cache_release(buf->page);
89 buf->page = NULL;
90 buf->flags &= ~PIPE_BUF_FLAG_LRU;
91} 88}
92 89
93static int page_cache_pipe_buf_pin(struct pipe_inode_info *info, 90static int page_cache_pipe_buf_pin(struct pipe_inode_info *info,
@@ -570,22 +567,36 @@ static int pipe_to_file(struct pipe_inode_info *info, struct pipe_buffer *buf,
570 if ((sd->flags & SPLICE_F_MOVE) && this_len == PAGE_CACHE_SIZE) { 567 if ((sd->flags & SPLICE_F_MOVE) && this_len == PAGE_CACHE_SIZE) {
571 /* 568 /*
572 * If steal succeeds, buf->page is now pruned from the vm 569 * If steal succeeds, buf->page is now pruned from the vm
573 * side (LRU and page cache) and we can reuse it. The page 570 * side (page cache) and we can reuse it. The page will also
574 * will also be looked on successful return. 571 * be locked on successful return.
575 */ 572 */
576 if (buf->ops->steal(info, buf)) 573 if (buf->ops->steal(info, buf))
577 goto find_page; 574 goto find_page;
578 575
579 page = buf->page; 576 page = buf->page;
577 page_cache_get(page);
578
579 /*
580 * page must be on the LRU for adding to the pagecache.
581 * Check this without grabbing the zone lock, if it isn't
582 * the do grab the zone lock, recheck, and add if necessary.
583 */
584 if (!PageLRU(page)) {
585 struct zone *zone = page_zone(page);
586
587 spin_lock_irq(&zone->lru_lock);
588 if (!PageLRU(page)) {
589 SetPageLRU(page);
590 add_page_to_inactive_list(zone, page);
591 }
592 spin_unlock_irq(&zone->lru_lock);
593 }
594
580 if (add_to_page_cache(page, mapping, index, gfp_mask)) { 595 if (add_to_page_cache(page, mapping, index, gfp_mask)) {
596 page_cache_release(page);
581 unlock_page(page); 597 unlock_page(page);
582 goto find_page; 598 goto find_page;
583 } 599 }
584
585 page_cache_get(page);
586
587 if (!(buf->flags & PIPE_BUF_FLAG_LRU))
588 lru_cache_add(page);
589 } else { 600 } else {
590find_page: 601find_page:
591 page = find_lock_page(mapping, index); 602 page = find_lock_page(mapping, index);