From patchwork Tue Sep 27 20:47:58 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ross Zwisler X-Patchwork-Id: 9352813 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id E3552600CB for ; Tue, 27 Sep 2016 20:48:23 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D3584291F2 for ; Tue, 27 Sep 2016 20:48:23 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id C7015291F7; Tue, 27 Sep 2016 20:48:23 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 Received: from ml01.01.org (ml01.01.org [198.145.21.10]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 4BC65291F8 for ; Tue, 27 Sep 2016 20:48:23 +0000 (UTC) Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 3BBB21A1E59; Tue, 27 Sep 2016 13:48:23 -0700 (PDT) X-Original-To: linux-nvdimm@lists.01.org Delivered-To: linux-nvdimm@lists.01.org Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) (using TLSv1 with cipher CAMELLIA256-SHA (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 1D1981A1E40 for ; Tue, 27 Sep 2016 13:48:20 -0700 (PDT) Received: from orsmga004.jf.intel.com ([10.7.209.38]) by fmsmga103.fm.intel.com with ESMTP; 27 Sep 2016 13:48:20 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.30,406,1470726000"; d="scan'208";a="14357685" Received: from theros.lm.intel.com ([10.232.112.77]) by orsmga004.jf.intel.com with ESMTP; 27 Sep 2016 13:48:19 -0700 From: Ross Zwisler To: linux-kernel@vger.kernel.org Subject: [PATCH v3 07/11] dax: coordinate locking for offsets in PMD range Date: Tue, 27 Sep 2016 14:47:58 -0600 Message-Id: <1475009282-9818-8-git-send-email-ross.zwisler@linux.intel.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1475009282-9818-1-git-send-email-ross.zwisler@linux.intel.com> References: <1475009282-9818-1-git-send-email-ross.zwisler@linux.intel.com> X-BeenThere: linux-nvdimm@lists.01.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: "Linux-nvdimm developer list." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Theodore Ts'o , Matthew Wilcox , Dave Chinner , linux-nvdimm@lists.01.org, Christoph Hellwig , linux-xfs@vger.kernel.org, linux-mm@kvack.org, Andreas Dilger , Alexander Viro , Jan Kara , linux-fsdevel@vger.kernel.org, linux-ext4@vger.kernel.org, Andrew Morton MIME-Version: 1.0 Errors-To: linux-nvdimm-bounces@lists.01.org Sender: "Linux-nvdimm" X-Virus-Scanned: ClamAV using ClamSMTP DAX radix tree locking currently locks entries based on the unique combination of the 'mapping' pointer and the pgoff_t 'index' for the entry. This works for PTEs, but as we move to PMDs we will need to have all the offsets within the range covered by the PMD to map to the same bit lock. To accomplish this, for ranges covered by a PMD entry we will instead lock based on the page offset of the beginning of the PMD entry. The 'mapping' pointer is still used in the same way. Signed-off-by: Ross Zwisler --- fs/dax.c | 37 ++++++++++++++++++++++++------------- include/linux/dax.h | 2 +- mm/filemap.c | 2 +- 3 files changed, 26 insertions(+), 15 deletions(-) diff --git a/fs/dax.c b/fs/dax.c index baef586..406feea 100644 --- a/fs/dax.c +++ b/fs/dax.c @@ -64,10 +64,17 @@ static int __init init_dax_wait_table(void) } fs_initcall(init_dax_wait_table); +static pgoff_t dax_entry_start(pgoff_t index, void *entry) +{ + if (RADIX_DAX_TYPE(entry) == RADIX_DAX_PMD) + index &= (PMD_MASK >> PAGE_SHIFT); + return index; +} + static wait_queue_head_t *dax_entry_waitqueue(struct address_space *mapping, - pgoff_t index) + pgoff_t entry_start) { - unsigned long hash = hash_long((unsigned long)mapping ^ index, + unsigned long hash = hash_long((unsigned long)mapping ^ entry_start, DAX_WAIT_TABLE_BITS); return wait_table + hash; } @@ -285,7 +292,7 @@ EXPORT_SYMBOL_GPL(dax_do_io); */ struct exceptional_entry_key { struct address_space *mapping; - unsigned long index; + pgoff_t entry_start; }; struct wait_exceptional_entry_queue { @@ -301,7 +308,7 @@ static int wake_exceptional_entry_func(wait_queue_t *wait, unsigned int mode, container_of(wait, struct wait_exceptional_entry_queue, wait); if (key->mapping != ewait->key.mapping || - key->index != ewait->key.index) + key->entry_start != ewait->key.entry_start) return 0; return autoremove_wake_function(wait, mode, sync, NULL); } @@ -359,12 +366,10 @@ static void *get_unlocked_mapping_entry(struct address_space *mapping, { void *entry, **slot; struct wait_exceptional_entry_queue ewait; - wait_queue_head_t *wq = dax_entry_waitqueue(mapping, index); + wait_queue_head_t *wq; init_wait(&ewait.wait); ewait.wait.func = wake_exceptional_entry_func; - ewait.key.mapping = mapping; - ewait.key.index = index; for (;;) { entry = __radix_tree_lookup(&mapping->page_tree, index, NULL, @@ -375,6 +380,11 @@ static void *get_unlocked_mapping_entry(struct address_space *mapping, *slotp = slot; return entry; } + + wq = dax_entry_waitqueue(mapping, + dax_entry_start(index, entry)); + ewait.key.mapping = mapping; + ewait.key.entry_start = dax_entry_start(index, entry); prepare_to_wait_exclusive(wq, &ewait.wait, TASK_UNINTERRUPTIBLE); spin_unlock_irq(&mapping->tree_lock); @@ -447,10 +457,11 @@ restart: return entry; } -void dax_wake_mapping_entry_waiter(struct address_space *mapping, +void dax_wake_mapping_entry_waiter(void *entry, struct address_space *mapping, pgoff_t index, bool wake_all) { - wait_queue_head_t *wq = dax_entry_waitqueue(mapping, index); + wait_queue_head_t *wq = dax_entry_waitqueue(mapping, + dax_entry_start(index, entry)); /* * Checking for locked entry and prepare_to_wait_exclusive() happens @@ -462,7 +473,7 @@ void dax_wake_mapping_entry_waiter(struct address_space *mapping, struct exceptional_entry_key key; key.mapping = mapping; - key.index = index; + key.entry_start = dax_entry_start(index, entry); __wake_up(wq, TASK_NORMAL, wake_all ? 0 : 1, &key); } } @@ -480,7 +491,7 @@ void dax_unlock_mapping_entry(struct address_space *mapping, pgoff_t index) } unlock_slot(mapping, slot); spin_unlock_irq(&mapping->tree_lock); - dax_wake_mapping_entry_waiter(mapping, index, false); + dax_wake_mapping_entry_waiter(entry, mapping, index, false); } static void put_locked_mapping_entry(struct address_space *mapping, @@ -505,7 +516,7 @@ static void put_unlocked_mapping_entry(struct address_space *mapping, return; /* We have to wake up next waiter for the radix tree entry lock */ - dax_wake_mapping_entry_waiter(mapping, index, false); + dax_wake_mapping_entry_waiter(entry, mapping, index, false); } /* @@ -532,7 +543,7 @@ int dax_delete_mapping_entry(struct address_space *mapping, pgoff_t index) radix_tree_delete(&mapping->page_tree, index); mapping->nrexceptional--; spin_unlock_irq(&mapping->tree_lock); - dax_wake_mapping_entry_waiter(mapping, index, true); + dax_wake_mapping_entry_waiter(entry, mapping, index, true); return 1; } diff --git a/include/linux/dax.h b/include/linux/dax.h index add6c4b..4065601 100644 --- a/include/linux/dax.h +++ b/include/linux/dax.h @@ -21,7 +21,7 @@ int iomap_dax_fault(struct vm_area_struct *vma, struct vm_fault *vmf, struct iomap_ops *ops); int dax_fault(struct vm_area_struct *, struct vm_fault *, get_block_t); int dax_delete_mapping_entry(struct address_space *mapping, pgoff_t index); -void dax_wake_mapping_entry_waiter(struct address_space *mapping, +void dax_wake_mapping_entry_waiter(void *entry, struct address_space *mapping, pgoff_t index, bool wake_all); #ifdef CONFIG_FS_DAX diff --git a/mm/filemap.c b/mm/filemap.c index 8a287df..35e880d 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -617,7 +617,7 @@ static int page_cache_tree_insert(struct address_space *mapping, if (node) workingset_node_pages_dec(node); /* Wakeup waiters for exceptional entry lock */ - dax_wake_mapping_entry_waiter(mapping, page->index, + dax_wake_mapping_entry_waiter(p, mapping, page->index, false); } }