[Devel] [RFC PATCH vz9 v5 38/49] dm-ploop: convert md page rw lock to spin lock

Alexander Atanasov alexander.atanasov at virtuozzo.com
Mon Nov 18 09:25:05 MSK 2024


Prepare locking for threads. Some operations require to lock bat data
(see next patch) and in some cases we need to lock  md page while hodling
bat spin lock but we can not take sleeping lock while holding a spin lock.
To address this use a spin lock for md pages instead of rwlock.

https://virtuozzo.atlassian.net/browse/VSTOR-91821
Signed-off-by: Alexander Atanasov <alexander.atanasov at virtuozzo.com>
---
 drivers/md/dm-ploop-bat.c |  6 +++---
 drivers/md/dm-ploop-cmd.c | 24 ++++++++++++------------
 drivers/md/dm-ploop-map.c | 23 +++++++++++------------
 drivers/md/dm-ploop.h     |  6 +++---
 4 files changed, 29 insertions(+), 30 deletions(-)

diff --git a/drivers/md/dm-ploop-bat.c b/drivers/md/dm-ploop-bat.c
index a6202720927f..efdc82a59abf 100644
--- a/drivers/md/dm-ploop-bat.c
+++ b/drivers/md/dm-ploop-bat.c
@@ -88,7 +88,7 @@ static struct md_page *ploop_alloc_md_page(u32 id)
 	md->page = page;
 	md->kmpage = kmap(page);
 	md->id = id;
-	rwlock_init(&md->lock);
+	spin_lock_init(&md->md_lock);
 	return md;
 err_page:
 	kfree(levels);
@@ -143,13 +143,13 @@ bool ploop_try_update_bat_entry(struct ploop *ploop, u32 clu, u8 level, u32 dst_
 
 	clu = ploop_bat_clu_idx_in_page(clu); /* relative offset */
 
-	write_lock_irqsave(&md->lock, flags);
+	spin_lock_irqsave(&md->md_lock, flags);
 	if (READ_ONCE(md->bat_levels[clu]) == level) {
 		bat_entries = md->kmpage;
 		WRITE_ONCE(bat_entries[clu], dst_clu);
 		ret = true;
 	}
-	write_unlock_irqrestore(&md->lock, flags);
+	spin_unlock_irqrestore(&md->md_lock, flags);
 
 	return ret;
 }
diff --git a/drivers/md/dm-ploop-cmd.c b/drivers/md/dm-ploop-cmd.c
index d4408cba5f0d..017250328ea3 100644
--- a/drivers/md/dm-ploop-cmd.c
+++ b/drivers/md/dm-ploop-cmd.c
@@ -46,7 +46,7 @@ static void ploop_advance_holes_bitmap(struct ploop *ploop,
 		ploop_init_be_iter(ploop, md->id, &i, &end);
 		bat_entries = md->kmpage;
 
-		read_lock_irqsave(&md->lock, flags);
+		spin_lock(&md->md_lock);
 		for (; i <= end; i++) {
 			if (!ploop_md_page_cluster_is_in_top_delta(ploop, md, i))
 				continue;
@@ -57,7 +57,7 @@ static void ploop_advance_holes_bitmap(struct ploop *ploop,
 				ploop_hole_clear_bit(dst_clu, ploop);
 			}
 		}
-		read_unlock_irqrestore(&md->lock, flags);
+		spin_unlock(&md->md_lock);
 	}
 	write_unlock_irq(&ploop->bat_rwlock);
 }
@@ -169,7 +169,7 @@ static u32 ploop_find_bat_entry(struct ploop *ploop, u32 dst_clu, bool *is_locke
 		ploop_init_be_iter(ploop, md->id, &i, &end);
 		bat_entries = md->kmpage;
 
-		read_lock_irqsave(&md->lock, flags);
+		spin_lock_irqsave(&md->md_lock, flags);
 		for (; i <= end; i++) {
 			if (READ_ONCE(bat_entries[i]) != dst_clu)
 				continue;
@@ -178,7 +178,7 @@ static u32 ploop_find_bat_entry(struct ploop *ploop, u32 dst_clu, bool *is_locke
 				break;
 			}
 		}
-		read_unlock_irqrestore(&md->lock, flags);
+		spin_unlock_irqrestore(&md->md_lock, flags);
 		if (clu != UINT_MAX)
 			break;
 	}
@@ -727,8 +727,8 @@ static void notify_delta_merged(struct ploop *ploop, u8 level,
 		bat_entries = md->kmpage;
 		d_bat_entries = d_md->kmpage;
 
-		write_lock_irqsave(&md->lock, flags);
-		write_lock(&d_md->lock);
+		spin_lock_irqsave(&md->md_lock, flags);
+		spin_lock(&d_md->md_lock);
 
 		for (; i <= end; i++) {
 			clu = ploop_page_clu_idx_to_bat_clu(md->id, i);
@@ -763,8 +763,8 @@ static void notify_delta_merged(struct ploop *ploop, u8 level,
 				WRITE_ONCE(md->bat_levels[i], level);
 		}
 
-		write_unlock(&d_md->lock);
-		write_unlock_irqrestore(&md->lock, flags);
+		spin_unlock(&d_md->md_lock);
+		spin_unlock_irqrestore(&md->md_lock, flags);
 
 		if (stop)
 			break;
@@ -1055,8 +1055,8 @@ static int ploop_check_delta_before_flip(struct ploop *ploop, struct file *file)
 		init_be_iter(nr_be, md->id, &i, &end);
 		d_bat_entries = d_md->kmpage;
 
-		read_lock_irqsave(&md->lock, flags);
-		read_lock(&d_md->lock);
+		spin_lock_irqsave(&md->md_lock, flags);
+		spin_lock(&d_md->md_lock);
 		for (; i <= end; i++) {
 			if (ploop_md_page_cluster_is_in_top_delta(ploop, md, i) &&
 			    d_bat_entries[i] != BAT_ENTRY_NONE) {
@@ -1065,8 +1065,8 @@ static int ploop_check_delta_before_flip(struct ploop *ploop, struct file *file)
 				goto unmap;
 			}
 		}
-		read_unlock(&d_md->lock);
-		read_unlock_irqrestore(&md->lock, flags);
+		spin_unlock(&d_md->md_lock);
+		spin_unlock_irqrestore(&md->md_lock, flags);
 
 		clu = ploop_page_clu_idx_to_bat_clu(md->id, i);
 		if (clu == nr_be - 1) {
diff --git a/drivers/md/dm-ploop-map.c b/drivers/md/dm-ploop-map.c
index 892174ba37f8..9bb96e2da783 100644
--- a/drivers/md/dm-ploop-map.c
+++ b/drivers/md/dm-ploop-map.c
@@ -395,14 +395,14 @@ static bool ploop_delay_if_md_busy(struct ploop *ploop, struct md_page *md,
 	WARN_ON_ONCE(!list_empty(&pio->list));
 
 	/* lock protects piwb */
-	read_lock_irqsave(&md->lock, flags);
+	spin_lock_irqsave(&md->md_lock, flags);
 	piwb = md->piwb;
 	if (piwb && (piwb->type != type || test_bit(MD_WRITEBACK, &md->status))) {
 		llist_add((struct llist_node *)(&pio->list), &md->wait_llist);
 		busy = true;
 		printk(KERN_ERR "p:%ld delay\n", pio->seqno);
 	}
-	read_unlock_irqrestore(&md->lock, flags);
+	spin_unlock_irqrestore(&md->md_lock, flags);
 
 	return busy;
 }
@@ -816,7 +816,7 @@ static void ploop_advance_local_after_bat_wb(struct ploop *ploop,
 
 	dst_clu = piwb->kmpage;
 
-	write_lock_irqsave(&md->lock, flags);
+	spin_lock(&md->md_lock);
 	if (piwb->type == PIWB_TYPE_ALLOC)
 		goto skip_apply;
 
@@ -841,7 +841,7 @@ static void ploop_advance_local_after_bat_wb(struct ploop *ploop,
 	WARN_ON_ONCE(!test_bit(MD_WRITEBACK, &md->status));
 	clear_bit(MD_WRITEBACK, &md->status);
 	md->piwb = NULL;
-	write_unlock_irqrestore(&md->lock, flags);
+	spin_unlock(&md->md_lock);
 
 	wait_llist_pending = llist_del_all(&md->wait_llist);
 	if (wait_llist_pending) {
@@ -979,15 +979,14 @@ static int ploop_prepare_bat_update(struct ploop *ploop, struct md_page *md,
 
 	bat_entries = md->kmpage;
 
-	write_lock_irq(&md->lock);
+	spin_lock_irq(&md->md_lock);
+	WARN_ON_ONCE(md->piwb);
 	md->piwb = piwb;
 	piwb->md = md;
-	write_unlock_irq(&md->lock);
 
 	piwb->page_id = page_id;
 	to = piwb->kmpage;
 
-	read_lock_irq(&md->lock);
 	memcpy((void *)to, bat_entries, PAGE_SIZE);
 
 	/* Absolute number of first index in page (negative for page#0) */
@@ -1012,7 +1011,7 @@ static int ploop_prepare_bat_update(struct ploop *ploop, struct md_page *md,
 		if (clu == BAT_ENTRY_NONE || level < ploop_top_level(ploop))
 			to[i] = 0;
 	}
-	read_unlock_irq(&md->lock);
+	spin_unlock_irq(&md->md_lock);
 
 	if (is_last_page) {
 	/* Fill tail of page with 0 */
@@ -1032,10 +1031,10 @@ void ploop_break_bat_update(struct ploop *ploop, struct md_page *md)
 	struct ploop_index_wb *piwb;
 	unsigned long flags;
 
-	write_lock_irqsave(&md->lock, flags);
+	spin_lock_irqsave(&md->md_lock, flags);
 	piwb = md->piwb;
 	md->piwb = NULL;
-	write_unlock_irqrestore(&md->lock, flags);
+	spin_unlock_irqrestore(&md->md_lock, flags);
 
 	ploop_free_piwb(piwb);
 }
@@ -1462,11 +1461,11 @@ static void ploop_submit_cow_index_wb(struct ploop_cow *cow)
 	WARN_ON(to[clu]);
 	WRITE_ONCE(to[clu], cow->dst_clu);
 
-	write_lock_irqsave(&md->lock, flags);
+	spin_lock_irqsave(&md->md_lock, flags);
 	to = md->kmpage;
 	WRITE_ONCE(to[clu], cow->dst_clu);
 	WRITE_ONCE(md->bat_levels[clu], ploop_top_level(ploop));
-	write_unlock_irqrestore(&md->lock, flags);
+	spin_unlock_irqrestore(&md->md_lock, flags);
 
 	ploop_md_up_prio(ploop, md);
 
diff --git a/drivers/md/dm-ploop.h b/drivers/md/dm-ploop.h
index 99b107db8767..265cd5371b7e 100644
--- a/drivers/md/dm-ploop.h
+++ b/drivers/md/dm-ploop.h
@@ -128,7 +128,7 @@ struct md_page {
 	struct list_head wb_link;
 	struct ploop_index_wb *piwb;
 
-	rwlock_t lock;
+	spinlock_t md_lock;
 
 	unsigned long dirty_timeout;
 };
@@ -449,7 +449,7 @@ static inline u32 ploop_bat_entries(struct ploop *ploop, u32 clu,
 	/* Cluster index related to the page[page_id] start */
 	clu = ploop_bat_clu_idx_in_page(clu);
 
-	read_lock_irqsave(&md->lock, flags);
+	spin_lock_irqsave(&md->md_lock, flags);
 	if (bat_level)
 		*bat_level = READ_ONCE(md->bat_levels[clu]);
 	if (md_ret)
@@ -457,7 +457,7 @@ static inline u32 ploop_bat_entries(struct ploop *ploop, u32 clu,
 
 	bat_entries = md->kmpage;
 	dst_clu = READ_ONCE(bat_entries[clu]);
-	read_unlock_irqrestore(&md->lock, flags);
+	spin_unlock_irqrestore(&md->md_lock, flags);
 
 	return dst_clu;
 }
-- 
2.43.0



More information about the Devel mailing list