From patchwork Mon Jun 23 14:58:29 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pavel Shilovsky X-Patchwork-Id: 4403581 Return-Path: X-Original-To: patchwork-cifs-client@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id A7C0D9F433 for ; Mon, 23 Jun 2014 14:58:57 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 917752017E for ; Mon, 23 Jun 2014 14:58:56 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 5D15920211 for ; Mon, 23 Jun 2014 14:58:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754689AbaFWO6v (ORCPT ); Mon, 23 Jun 2014 10:58:51 -0400 Received: from mail-lb0-f176.google.com ([209.85.217.176]:39911 "EHLO mail-lb0-f176.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753954AbaFWO6v (ORCPT ); Mon, 23 Jun 2014 10:58:51 -0400 Received: by mail-lb0-f176.google.com with SMTP id w7so4602743lbi.7 for ; Mon, 23 Jun 2014 07:58:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:subject:date:message-id:in-reply-to:references; bh=20/n972Fng+2U8jrSJ2p0nBnZwUfcu++FvyDSdgv4ns=; b=LoFnTgEu8/ONKdC+Lkc9LkzhocfnY8Zop03kQwVcGw2tVTL+hYIJNM8oitSMkYXQlH CoZ6w1mFnWBVIbEBMjatMJ8zvtA0mu9hn5ZqtctEyD+gw07yZqzFVD7T869o8JltXdS7 i7urnrrEi2egppZH6zikIq0ZifoEj9LwsjmLEXLWcDHzjvUYarNPB9NU76k624TkKZfN fDnwHcsKJGn8bYNpZSn7FjENWgkSL1N1xU2b+8AOqFvY2VmQ1ghy03ssyAFN1dtkfOhF JBSp2blKMkfSfMBTQR+rzGUiYRybSDcmRfd6yPgxZuKPg2niu4ye0QjXQBctSTLfO1WR U/gA== X-Received: by 10.152.8.165 with SMTP id s5mr2030324laa.80.1403535529460; Mon, 23 Jun 2014 07:58:49 -0700 (PDT) Received: from localhost.localdomain ([92.43.3.32]) by mx.google.com with ESMTPSA id fb6sm7964060lac.40.2014.06.23.07.58.47 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 23 Jun 2014 07:58:48 -0700 (PDT) From: Pavel Shilovsky To: linux-cifs@vger.kernel.org Subject: [PATCH 1/9] CIFS: Separate page processing from writepages Date: Mon, 23 Jun 2014 18:58:29 +0400 Message-Id: <1403535517-8301-2-git-send-email-pshilovsky@samba.org> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1403535517-8301-1-git-send-email-pshilovsky@samba.org> References: <1403535517-8301-1-git-send-email-pshilovsky@samba.org> Sender: linux-cifs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-cifs@vger.kernel.org X-Spam-Status: No, score=-6.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID,T_RP_MATCHES_RCVD,UNPARSEABLE_RELAY autolearn=ham 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 Signed-off-by: Pavel Shilovsky --- fs/cifs/file.c | 154 ++++++++++++++++++++++++++++++-------------------------- 1 file changed, 83 insertions(+), 71 deletions(-) diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 208f56e..216959e 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -1878,6 +1878,86 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to) return rc; } +static unsigned int +wdata_prepare_pages(struct cifs_writedata *wdata, unsigned int found_pages, + struct address_space *mapping, + struct writeback_control *wbc, + pgoff_t end, pgoff_t *index, pgoff_t *next, bool *done) +{ + unsigned int nr_pages = 0, i; + struct page *page; + + for (i = 0; i < found_pages; i++) { + page = wdata->pages[i]; + /* + * At this point we hold neither mapping->tree_lock nor + * lock on the page itself: the page may be truncated or + * invalidated (changing page->mapping to NULL), or even + * swizzled back from swapper_space to tmpfs file + * mapping + */ + + if (nr_pages == 0) + lock_page(page); + else if (!trylock_page(page)) + break; + + if (unlikely(page->mapping != mapping)) { + unlock_page(page); + break; + } + + if (!wbc->range_cyclic && page->index > end) { + *done = true; + unlock_page(page); + break; + } + + if (*next && (page->index != *next)) { + /* Not next consecutive page */ + unlock_page(page); + break; + } + + if (wbc->sync_mode != WB_SYNC_NONE) + wait_on_page_writeback(page); + + if (PageWriteback(page) || + !clear_page_dirty_for_io(page)) { + unlock_page(page); + break; + } + + /* + * This actually clears the dirty bit in the radix tree. + * See cifs_writepage() for more commentary. + */ + set_page_writeback(page); + if (page_offset(page) >= i_size_read(mapping->host)) { + *done = true; + unlock_page(page); + end_page_writeback(page); + break; + } + + wdata->pages[i] = page; + *next = page->index + 1; + ++nr_pages; + } + + /* reset index to refind any pages skipped */ + if (nr_pages == 0) + *index = wdata->pages[0]->index + 1; + + /* put any pages we aren't going to use */ + for (i = nr_pages; i < found_pages; i++) { + page_cache_release(wdata->pages[i]); + wdata->pages[i] = NULL; + } + + return nr_pages; +} + static int cifs_writepages(struct address_space *mapping, struct writeback_control *wbc) { @@ -1886,7 +1966,6 @@ static int cifs_writepages(struct address_space *mapping, pgoff_t end, index; struct cifs_writedata *wdata; struct TCP_Server_Info *server; - struct page *page; int rc = 0; /* @@ -1908,7 +1987,7 @@ static int cifs_writepages(struct address_space *mapping, } retry: while (!done && index <= end) { - unsigned int i, nr_pages, found_pages; + unsigned int nr_pages, found_pages; pgoff_t next = 0, tofind; struct page **pages; @@ -1944,75 +2023,8 @@ retry: break; } - nr_pages = 0; - for (i = 0; i < found_pages; i++) { - page = wdata->pages[i]; - /* - * At this point we hold neither mapping->tree_lock nor - * lock on the page itself: the page may be truncated or - * invalidated (changing page->mapping to NULL), or even - * swizzled back from swapper_space to tmpfs file - * mapping - */ - - if (nr_pages == 0) - lock_page(page); - else if (!trylock_page(page)) - break; - - if (unlikely(page->mapping != mapping)) { - unlock_page(page); - break; - } - - if (!wbc->range_cyclic && page->index > end) { - done = true; - unlock_page(page); - break; - } - - if (next && (page->index != next)) { - /* Not next consecutive page */ - unlock_page(page); - break; - } - - if (wbc->sync_mode != WB_SYNC_NONE) - wait_on_page_writeback(page); - - if (PageWriteback(page) || - !clear_page_dirty_for_io(page)) { - unlock_page(page); - break; - } - - /* - * This actually clears the dirty bit in the radix tree. - * See cifs_writepage() for more commentary. - */ - set_page_writeback(page); - - if (page_offset(page) >= i_size_read(mapping->host)) { - done = true; - unlock_page(page); - end_page_writeback(page); - break; - } - - wdata->pages[i] = page; - next = page->index + 1; - ++nr_pages; - } - - /* reset index to refind any pages skipped */ - if (nr_pages == 0) - index = wdata->pages[0]->index + 1; - - /* put any pages we aren't going to use */ - for (i = nr_pages; i < found_pages; i++) { - page_cache_release(wdata->pages[i]); - wdata->pages[i] = NULL; - } + nr_pages = wdata_prepare_pages(wdata, found_pages, mapping, wbc, + end, &index, &next, &done); /* nothing to write? */ if (nr_pages == 0) {