linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Matthew Wilcox <willy@infradead.org>
To: linux-kernel@vger.kernel.org
Cc: Matthew Wilcox <mawilcox@microsoft.com>,
	Ross Zwisler <ross.zwisler@linux.intel.com>,
	David Howells <dhowells@redhat.com>, Shaohua Li <shli@kernel.org>,
	Jens Axboe <axboe@kernel.dk>, Rehas Sachdeva <aquannie@gmail.com>,
	Marc Zyngier <marc.zyngier@arm.com>,
	linux-mm@kvack.org, linux-fsdevel@vger.kernel.org,
	linux-f2fs-devel@lists.sourceforge.net,
	linux-nilfs@vger.kernel.org, linux-btrfs@vger.kernel.org,
	linux-xfs@vger.kernel.org, linux-usb@vger.kernel.org,
	linux-raid@vger.kernel.org
Subject: [PATCH v5 76/78] md: Convert raid5-cache to XArray
Date: Fri, 15 Dec 2017 14:04:48 -0800	[thread overview]
Message-ID: <20171215220450.7899-77-willy@infradead.org> (raw)
In-Reply-To: <20171215220450.7899-1-willy@infradead.org>

From: Matthew Wilcox <mawilcox@microsoft.com>

This is the first user of the radix tree I've converted which was
storing numbers rather than pointers.  I'm fairly pleased with how
well it came out.  There's less boiler-plate involved than there was
with the radix tree, so that's a win.  It does use the advanced API,
and I think that's a signal that there needs to be a separate API for
using the XArray for only integers.

Signed-off-by: Matthew Wilcox <mawilcox@microsoft.com>
---
 drivers/md/raid5-cache.c | 119 ++++++++++++++++-------------------------------
 1 file changed, 40 insertions(+), 79 deletions(-)

diff --git a/drivers/md/raid5-cache.c b/drivers/md/raid5-cache.c
index 39f31f07ffe9..2c8ad0ed9b48 100644
--- a/drivers/md/raid5-cache.c
+++ b/drivers/md/raid5-cache.c
@@ -158,9 +158,8 @@ struct r5l_log {
 	/* to disable write back during in degraded mode */
 	struct work_struct disable_writeback_work;
 
-	/* to for chunk_aligned_read in writeback mode, details below */
-	spinlock_t tree_lock;
-	struct radix_tree_root big_stripe_tree;
+	/* for chunk_aligned_read in writeback mode, details below */
+	struct xarray big_stripe;
 };
 
 /*
@@ -170,9 +169,8 @@ struct r5l_log {
  * chunk contains 64 4kB-page, so this chunk contain 64 stripes). For
  * chunk_aligned_read, these stripes are grouped into one "big_stripe".
  * For each big_stripe, we count how many stripes of this big_stripe
- * are in the write back cache. These data are tracked in a radix tree
- * (big_stripe_tree). We use radix_tree item pointer as the counter.
- * r5c_tree_index() is used to calculate keys for the radix tree.
+ * are in the write back cache. This counter is tracked in an xarray
+ * (big_stripe). r5c_index() is used to calculate the index.
  *
  * chunk_aligned_read() calls r5c_big_stripe_cached() to look up
  * big_stripe of each chunk in the tree. If this big_stripe is in the
@@ -180,9 +178,9 @@ struct r5l_log {
  * rcu_read_lock().
  *
  * It is necessary to remember whether a stripe is counted in
- * big_stripe_tree. Instead of adding new flag, we reuses existing flags:
+ * big_stripe. Instead of adding new flag, we reuses existing flags:
  * STRIPE_R5C_PARTIAL_STRIPE and STRIPE_R5C_FULL_STRIPE. If either of these
- * two flags are set, the stripe is counted in big_stripe_tree. This
+ * two flags are set, the stripe is counted in big_stripe. This
  * requires moving set_bit(STRIPE_R5C_PARTIAL_STRIPE) to
  * r5c_try_caching_write(); and moving clear_bit of
  * STRIPE_R5C_PARTIAL_STRIPE and STRIPE_R5C_FULL_STRIPE to
@@ -190,23 +188,13 @@ struct r5l_log {
  */
 
 /*
- * radix tree requests lowest 2 bits of data pointer to be 2b'00.
- * So it is necessary to left shift the counter by 2 bits before using it
- * as data pointer of the tree.
- */
-#define R5C_RADIX_COUNT_SHIFT 2
-
-/*
- * calculate key for big_stripe_tree
+ * calculate key for big_stripe
  *
  * sect: align_bi->bi_iter.bi_sector or sh->sector
  */
-static inline sector_t r5c_tree_index(struct r5conf *conf,
-				      sector_t sect)
+static inline sector_t r5c_index(struct r5conf *conf, sector_t sect)
 {
-	sector_t offset;
-
-	offset = sector_div(sect, conf->chunk_sectors);
+	sector_div(sect, conf->chunk_sectors);
 	return sect;
 }
 
@@ -2646,10 +2634,6 @@ int r5c_try_caching_write(struct r5conf *conf,
 	int i;
 	struct r5dev *dev;
 	int to_cache = 0;
-	void **pslot;
-	sector_t tree_index;
-	int ret;
-	uintptr_t refcount;
 
 	BUG_ON(!r5c_is_writeback(log));
 
@@ -2697,39 +2681,29 @@ int r5c_try_caching_write(struct r5conf *conf,
 		}
 	}
 
-	/* if the stripe is not counted in big_stripe_tree, add it now */
+	/* if the stripe is not counted in big_stripe, add it now */
 	if (!test_bit(STRIPE_R5C_PARTIAL_STRIPE, &sh->state) &&
 	    !test_bit(STRIPE_R5C_FULL_STRIPE, &sh->state)) {
-		tree_index = r5c_tree_index(conf, sh->sector);
-		spin_lock(&log->tree_lock);
-		pslot = radix_tree_lookup_slot(&log->big_stripe_tree,
-					       tree_index);
-		if (pslot) {
-			refcount = (uintptr_t)radix_tree_deref_slot_protected(
-				pslot, &log->tree_lock) >>
-				R5C_RADIX_COUNT_SHIFT;
-			radix_tree_replace_slot(
-				&log->big_stripe_tree, pslot,
-				(void *)((refcount + 1) << R5C_RADIX_COUNT_SHIFT));
-		} else {
-			/*
-			 * this radix_tree_insert can fail safely, so no
-			 * need to call radix_tree_preload()
-			 */
-			ret = radix_tree_insert(
-				&log->big_stripe_tree, tree_index,
-				(void *)(1 << R5C_RADIX_COUNT_SHIFT));
-			if (ret) {
-				spin_unlock(&log->tree_lock);
-				r5c_make_stripe_write_out(sh);
-				return -EAGAIN;
-			}
+		XA_STATE(xas, &log->big_stripe, r5c_index(conf, sh->sector));
+		void *entry;
+
+		/* Caller would rather handle failures than supply GFP flags */
+		xas_lock(&xas);
+		entry = xas_create(&xas);
+		if (entry)
+			entry = xa_mk_value(xa_to_value(entry) + 1);
+		else
+			entry = xa_mk_value(1);
+		xas_store(&xas, entry);
+		xas_unlock(&xas);
+		if (xas_error(&xas)) {
+			r5c_make_stripe_write_out(sh);
+			return -EAGAIN;
 		}
-		spin_unlock(&log->tree_lock);
 
 		/*
 		 * set STRIPE_R5C_PARTIAL_STRIPE, this shows the stripe is
-		 * counted in the radix tree
+		 * counted in big_stripe
 		 */
 		set_bit(STRIPE_R5C_PARTIAL_STRIPE, &sh->state);
 		atomic_inc(&conf->r5c_cached_partial_stripes);
@@ -2812,9 +2786,6 @@ void r5c_finish_stripe_write_out(struct r5conf *conf,
 	struct r5l_log *log = conf->log;
 	int i;
 	int do_wakeup = 0;
-	sector_t tree_index;
-	void **pslot;
-	uintptr_t refcount;
 
 	if (!log || !test_bit(R5_InJournal, &sh->dev[sh->pd_idx].flags))
 		return;
@@ -2852,24 +2823,21 @@ void r5c_finish_stripe_write_out(struct r5conf *conf,
 	atomic_dec(&log->stripe_in_journal_count);
 	r5c_update_log_state(log);
 
-	/* stop counting this stripe in big_stripe_tree */
+	/* stop counting this stripe in big_stripe */
 	if (test_bit(STRIPE_R5C_PARTIAL_STRIPE, &sh->state) ||
 	    test_bit(STRIPE_R5C_FULL_STRIPE, &sh->state)) {
-		tree_index = r5c_tree_index(conf, sh->sector);
-		spin_lock(&log->tree_lock);
-		pslot = radix_tree_lookup_slot(&log->big_stripe_tree,
-					       tree_index);
-		BUG_ON(pslot == NULL);
-		refcount = (uintptr_t)radix_tree_deref_slot_protected(
-			pslot, &log->tree_lock) >>
-			R5C_RADIX_COUNT_SHIFT;
-		if (refcount == 1)
-			radix_tree_delete(&log->big_stripe_tree, tree_index);
+		XA_STATE(xas, &log->big_stripe, r5c_index(conf, sh->sector));
+		void *entry;
+
+		xas_lock(&xas);
+		entry = xas_load(&xas);
+		BUG_ON(!entry);
+		if (entry == xa_mk_value(1))
+			entry = NULL;
 		else
-			radix_tree_replace_slot(
-				&log->big_stripe_tree, pslot,
-				(void *)((refcount - 1) << R5C_RADIX_COUNT_SHIFT));
-		spin_unlock(&log->tree_lock);
+			entry = xa_mk_value(xa_to_value(entry) - 1);
+		xas_store(&xas, entry);
+		xas_unlock(&xas);
 	}
 
 	if (test_and_clear_bit(STRIPE_R5C_PARTIAL_STRIPE, &sh->state)) {
@@ -2949,16 +2917,10 @@ int r5c_cache_data(struct r5l_log *log, struct stripe_head *sh)
 bool r5c_big_stripe_cached(struct r5conf *conf, sector_t sect)
 {
 	struct r5l_log *log = conf->log;
-	sector_t tree_index;
-	void *slot;
 
 	if (!log)
 		return false;
-
-	WARN_ON_ONCE(!rcu_read_lock_held());
-	tree_index = r5c_tree_index(conf, sect);
-	slot = radix_tree_lookup(&log->big_stripe_tree, tree_index);
-	return slot != NULL;
+	return xa_load(&log->big_stripe, r5c_index(conf, sect)) != NULL;
 }
 
 static int r5l_load_log(struct r5l_log *log)
@@ -3112,8 +3074,7 @@ int r5l_init_log(struct r5conf *conf, struct md_rdev *rdev)
 	if (!log->meta_pool)
 		goto out_mempool;
 
-	spin_lock_init(&log->tree_lock);
-	INIT_RADIX_TREE(&log->big_stripe_tree, GFP_NOWAIT | __GFP_NOWARN);
+	xa_init(&log->big_stripe);
 
 	log->reclaim_thread = md_register_thread(r5l_reclaim_thread,
 						 log->rdev->mddev, "reclaim");
-- 
2.15.1

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

  parent reply	other threads:[~2017-12-15 22:04 UTC|newest]

Thread overview: 95+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-12-15 22:03 [PATCH v5 00/78] XArray v5 Matthew Wilcox
2017-12-15 22:03 ` [PATCH v5 01/78] xfs: Rename xa_ elements to ail_ Matthew Wilcox
2018-01-03  1:01   ` Darrick J. Wong
2017-12-15 22:03 ` [PATCH v5 02/78] fscache: Use appropriate radix tree accessors Matthew Wilcox
2017-12-15 22:03 ` [PATCH v5 03/78] xarray: Add the xa_lock to the radix_tree_root Matthew Wilcox
2017-12-26 16:54   ` Kirill A. Shutemov
2017-12-27  3:43     ` Matthew Wilcox
2017-12-27  3:58       ` Matthew Wilcox
2017-12-27 10:18         ` Kirill A. Shutemov
2018-01-02 18:01         ` Darrick J. Wong
2018-01-02 22:41           ` Matthew Wilcox
2017-12-27 10:17       ` Kirill A. Shutemov
2017-12-15 22:03 ` [PATCH v5 04/78] page cache: Use xa_lock Matthew Wilcox
2017-12-26 16:56   ` Kirill A. Shutemov
2017-12-15 22:03 ` [PATCH v5 05/78] xarray: Replace exceptional entries Matthew Wilcox
2017-12-26 17:15   ` Kirill A. Shutemov
2017-12-27  3:05     ` Matthew Wilcox
2017-12-27 10:24       ` Kirill A. Shutemov
2017-12-15 22:03 ` [PATCH v5 06/78] xarray: Change definition of sibling entries Matthew Wilcox
2017-12-26 17:21   ` Kirill A. Shutemov
2017-12-27  3:13     ` Matthew Wilcox
2017-12-27 10:26       ` Kirill A. Shutemov
2017-12-15 22:03 ` [PATCH v5 07/78] xarray: Add definition of struct xarray Matthew Wilcox
2017-12-15 22:03 ` [PATCH v5 08/78] xarray: Define struct xa_node Matthew Wilcox
2017-12-15 22:03 ` [PATCH v5 09/78] xarray: Add documentation Matthew Wilcox
2017-12-15 22:03 ` [PATCH v5 10/78] xarray: Add xa_load Matthew Wilcox
2017-12-15 22:03 ` [PATCH v5 11/78] xarray: Add xa_get_tag, xa_set_tag and xa_clear_tag Matthew Wilcox
2017-12-15 22:03 ` [PATCH v5 12/78] xarray: Add xa_store Matthew Wilcox
2017-12-15 22:03 ` [PATCH v5 13/78] xarray: Add xa_cmpxchg Matthew Wilcox
2017-12-15 22:03 ` [PATCH v5 14/78] xarray: Add xa_for_each Matthew Wilcox
2017-12-15 22:03 ` [PATCH v5 15/78] xarray: Add xas_for_each_tag Matthew Wilcox
2017-12-15 22:03 ` [PATCH v5 16/78] xarray: Add xa_get_entries, xa_get_tagged and xa_get_maybe_tag Matthew Wilcox
2017-12-15 22:03 ` [PATCH v5 17/78] xarray: Add xa_destroy Matthew Wilcox
2017-12-15 22:03 ` [PATCH v5 18/78] xarray: Add xas_next and xas_prev Matthew Wilcox
2017-12-15 22:03 ` [PATCH v5 19/78] xarray: Add xas_create_range Matthew Wilcox
2017-12-15 22:03 ` [PATCH v5 20/78] xarray: Add MAINTAINERS entry Matthew Wilcox
2017-12-15 22:03 ` [PATCH v5 21/78] xarray: Add ability to store errno values Matthew Wilcox
2017-12-15 22:03 ` [PATCH v5 22/78] idr: Convert to XArray Matthew Wilcox
2017-12-15 22:03 ` [PATCH v5 23/78] ida: " Matthew Wilcox
2017-12-15 22:03 ` [PATCH v5 24/78] page cache: Convert hole search " Matthew Wilcox
2017-12-15 22:03 ` [PATCH v5 25/78] page cache: Add page_cache_range_empty function Matthew Wilcox
2017-12-15 22:03 ` [PATCH v5 26/78] page cache: Add and replace pages using the XArray Matthew Wilcox
2017-12-15 22:03 ` [PATCH v5 27/78] page cache: Convert page deletion to XArray Matthew Wilcox
2017-12-15 22:04 ` [PATCH v5 28/78] page cache: Convert page cache lookups " Matthew Wilcox
2017-12-15 22:04 ` [PATCH v5 29/78] page cache: Convert delete_batch " Matthew Wilcox
2017-12-15 22:04 ` [PATCH v5 30/78] page cache: Remove stray radix comment Matthew Wilcox
2017-12-15 22:04 ` [PATCH v5 31/78] mm: Convert page-writeback to XArray Matthew Wilcox
2017-12-15 22:04 ` [PATCH v5 32/78] mm: Convert workingset " Matthew Wilcox
2017-12-15 22:04 ` [PATCH v5 33/78] mm: Convert truncate " Matthew Wilcox
2017-12-15 22:04 ` [PATCH v5 34/78] mm: Convert add_to_swap_cache " Matthew Wilcox
2017-12-15 22:04 ` [PATCH v5 35/78] mm: Convert delete_from_swap_cache " Matthew Wilcox
2017-12-15 22:04 ` [PATCH v5 36/78] mm: Convert __do_page_cache_readahead " Matthew Wilcox
2017-12-15 22:04 ` [PATCH v5 37/78] mm: Convert page migration " Matthew Wilcox
2017-12-15 22:04 ` [PATCH v5 38/78] mm: Convert huge_memory " Matthew Wilcox
2017-12-15 22:04 ` [PATCH v5 39/78] mm: Convert collapse_shmem " Matthew Wilcox
2017-12-15 22:04 ` [PATCH v5 40/78] mm: Convert khugepaged_scan_shmem " Matthew Wilcox
2017-12-15 22:04 ` [PATCH v5 41/78] pagevec: Use xa_tag_t Matthew Wilcox
2017-12-15 22:04 ` [PATCH v5 42/78] shmem: Convert replace to XArray Matthew Wilcox
2017-12-15 22:04 ` [PATCH v5 43/78] shmem: Convert shmem_confirm_swap " Matthew Wilcox
2017-12-15 22:04 ` [PATCH v5 44/78] shmem: Convert find_swap_entry " Matthew Wilcox
2017-12-15 22:04 ` [PATCH v5 45/78] shmem: Convert shmem_tag_pins " Matthew Wilcox
2017-12-15 22:04 ` [PATCH v5 46/78] shmem: Convert shmem_wait_for_pins " Matthew Wilcox
2017-12-15 22:04 ` [PATCH v5 47/78] shmem: Convert shmem_add_to_page_cache " Matthew Wilcox
2017-12-15 22:04 ` [PATCH v5 48/78] shmem: Convert shmem_alloc_hugepage " Matthew Wilcox
2017-12-15 22:04 ` [PATCH v5 49/78] shmem: Convert shmem_free_swap " Matthew Wilcox
2017-12-15 22:04 ` [PATCH v5 50/78] shmem: Convert shmem_partial_swap_usage " Matthew Wilcox
2017-12-15 22:04 ` [PATCH v5 51/78] shmem: Comment fixups Matthew Wilcox
2017-12-15 22:04 ` [PATCH v5 52/78] btrfs: Convert page cache to XArray Matthew Wilcox
2017-12-15 22:04 ` [PATCH v5 53/78] fs: Convert buffer " Matthew Wilcox
2017-12-15 22:04 ` [PATCH v5 54/78] fs: Convert writeback " Matthew Wilcox
2017-12-15 22:04 ` [PATCH v5 55/78] nilfs2: Convert " Matthew Wilcox
2017-12-15 22:04 ` [PATCH v5 56/78] f2fs: " Matthew Wilcox
2017-12-15 22:04 ` [PATCH v5 57/78] lustre: " Matthew Wilcox
2017-12-15 22:04 ` [PATCH v5 58/78] dax: Convert dax_unlock_mapping_entry " Matthew Wilcox
2017-12-15 22:04 ` [PATCH v5 59/78] dax: Convert lock_slot " Matthew Wilcox
2017-12-15 22:04 ` [PATCH v5 60/78] dax: More XArray conversion Matthew Wilcox
2017-12-15 22:04 ` [PATCH v5 61/78] dax: Convert __dax_invalidate_mapping_entry to XArray Matthew Wilcox
2017-12-15 22:04 ` [PATCH v5 62/78] dax: Convert dax_writeback_one " Matthew Wilcox
2017-12-15 22:04 ` [PATCH v5 63/78] dax: Convert dax_insert_pfn_mkwrite " Matthew Wilcox
2017-12-15 22:04 ` [PATCH v5 64/78] dax: Convert dax_insert_mapping_entry " Matthew Wilcox
2017-12-15 22:04 ` [PATCH v5 65/78] dax: Convert grab_mapping_entry " Matthew Wilcox
2017-12-15 22:04 ` [PATCH v5 66/78] dax: Fix sparse warning Matthew Wilcox
2017-12-15 22:04 ` [PATCH v5 67/78] page cache: Finish XArray conversion Matthew Wilcox
2017-12-15 22:04 ` [PATCH v5 68/78] mm: Convert cgroup writeback to XArray Matthew Wilcox
2017-12-15 22:04 ` [PATCH v5 69/78] vmalloc: Convert " Matthew Wilcox
2017-12-15 22:04 ` [PATCH v5 70/78] brd: " Matthew Wilcox
2017-12-15 22:04 ` [PATCH v5 71/78] xfs: Convert m_perag_tree " Matthew Wilcox
2017-12-15 22:04 ` [PATCH v5 72/78] xfs: Convert pag_ici_root " Matthew Wilcox
2017-12-15 22:04 ` [PATCH v5 73/78] xfs: Convert xfs dquot " Matthew Wilcox
2017-12-15 22:04 ` [PATCH v5 74/78] xfs: Convert mru cache " Matthew Wilcox
2017-12-15 22:04 ` [PATCH v5 75/78] usb: Convert xhci-mem " Matthew Wilcox
2017-12-15 22:04 ` Matthew Wilcox [this message]
2017-12-15 22:04 ` [PATCH v5 77/78] irqdomain: Convert " Matthew Wilcox
2017-12-16 10:51   ` Marc Zyngier
2017-12-15 22:04 ` [PATCH v5 78/78] fscache: " Matthew Wilcox

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20171215220450.7899-77-willy@infradead.org \
    --to=willy@infradead.org \
    --cc=aquannie@gmail.com \
    --cc=axboe@kernel.dk \
    --cc=dhowells@redhat.com \
    --cc=linux-btrfs@vger.kernel.org \
    --cc=linux-f2fs-devel@lists.sourceforge.net \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=linux-nilfs@vger.kernel.org \
    --cc=linux-raid@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=linux-xfs@vger.kernel.org \
    --cc=marc.zyngier@arm.com \
    --cc=mawilcox@microsoft.com \
    --cc=ross.zwisler@linux.intel.com \
    --cc=shli@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).