From patchwork Wed Apr 1 12:50:56 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christoph Hellwig X-Patchwork-Id: 6140111 Return-Path: X-Original-To: patchwork-linux-fsdevel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id D3673BF4A6 for ; Wed, 1 Apr 2015 12:51:03 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 1FB582027D for ; Wed, 1 Apr 2015 12:51:03 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 115E8202B8 for ; Wed, 1 Apr 2015 12:51:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753357AbbDAMvA (ORCPT ); Wed, 1 Apr 2015 08:51:00 -0400 Received: from bombadil.infradead.org ([198.137.202.9]:58933 "EHLO bombadil.infradead.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753213AbbDAMu7 (ORCPT ); Wed, 1 Apr 2015 08:50:59 -0400 Received: from hch by bombadil.infradead.org with local (Exim 4.80.1 #2 (Red Hat Linux)) id 1YdI6i-0006GS-WF; Wed, 01 Apr 2015 12:50:57 +0000 Date: Wed, 1 Apr 2015 05:50:56 -0700 From: Christoph Hellwig To: Jens Axboe , Miklos Szeredi Cc: linux-fsdevel@vger.kernel.org Subject: ->steal semantics on anon pages Message-ID: <20150401125056.GA5297@infradead.org> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.23 (2014-03-12) X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org See http://www.infradead.org/rpr.html Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, T_TVD_MIME_EPI, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP I've started looking into resurrecting splice F_MOVE support, and it seems ->steal for anon pages is completly bogus at the moment: - the page count check is incorrect - it doesn't isolate the mapping from the lru - it sets the PIPE_BUF_FLAG_LRU flag, which doesn't get the file added to the file lru Currently on fuse calls ->steal, but I'm not sure it could work on a vmspliced buffered at all. Below is a patch that attempts to fix / paper over ->steal, and the second is the unfinished F_MOVE resurrection patch which shows what additional workarouns we need for ->steal from anon pages. From 94958673ed6d0add7f5d95cc17fb0c9fa8f58c03 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 1 Apr 2015 14:28:50 +0200 Subject: fix ->steal for anon pages --- fs/splice.c | 20 ++++++++++++++++++-- include/linux/swap.h | 1 + mm/internal.h | 1 - 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/fs/splice.c b/fs/splice.c index 41cbb16..36aa4a9 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -145,11 +145,27 @@ const struct pipe_buf_operations page_cache_pipe_buf_ops = { static int user_page_pipe_buf_steal(struct pipe_inode_info *pipe, struct pipe_buffer *buf) { + struct page *page = buf->page; + if (!(buf->flags & PIPE_BUF_FLAG_GIFT)) return 1; - buf->flags |= PIPE_BUF_FLAG_LRU; - return generic_pipe_buf_steal(pipe, buf); + /* + * We should have three references to the page: gup, lru, and + * one for being mapped into page tables. + */ + if (page_count(page) != 3) + return 1; + + lock_page(page); + + if (!isolate_lru_page(page)) { + ClearPageActive(page); + ClearPageUnevictable(page); + page_cache_release(page); + } + + return 0; } static const struct pipe_buf_operations user_page_pipe_buf_ops = { diff --git a/include/linux/swap.h b/include/linux/swap.h index 7067eca..a3742f3 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -318,6 +318,7 @@ extern void lru_cache_add_active_or_unevictable(struct page *page, /* linux/mm/vmscan.c */ extern unsigned long try_to_free_pages(struct zonelist *zonelist, int order, gfp_t gfp_mask, nodemask_t *mask); +extern int isolate_lru_page(struct page *page); extern int __isolate_lru_page(struct page *page, isolate_mode_t mode); extern unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *memcg, unsigned long nr_pages, diff --git a/mm/internal.h b/mm/internal.h index a96da5b..48c5731 100644 --- a/mm/internal.h +++ b/mm/internal.h @@ -96,7 +96,6 @@ extern unsigned long highest_memmap_pfn; /* * in mm/vmscan.c: */ -extern int isolate_lru_page(struct page *page); extern void putback_lru_page(struct page *page); extern bool zone_reclaimable(struct zone *zone);