[Devel] [PATCH RHEL7 COMMIT] ploop: fix trim_extent_mappings() locking
Konstantin Khorenko
khorenko at virtuozzo.com
Wed Dec 6 17:57:10 MSK 2017
The commit is pushed to "branch-rh7-3.10.0-693.11.1.vz7.39.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-693.11.1.vz7.39.1
------>
commit 841e91712b8697913ccb8a2b50c2bf27cf5c27a2
Author: Vasily Averin <vvs at virtuozzo.com>
Date: Wed Dec 6 17:57:10 2017 +0300
ploop: fix trim_extent_mappings() locking
trim_extent_mappings() must obey locking scheme that all other
callers of lookup_extent_mapping() and extent_lookup() follows: firstly
hold plo->lock.
Changed in v2:
- change locking in remove_extent_mapping() from write_lock_irq
to write_lock because its only caller disables irq now. Thanks
Vasily Averin for finding.
Changes in v3 (from vvs@):
- use read_lock_irqsave() in lookup_extent_mapping()
- added WARN_ON(!irqs_disabled()) in remove_extent_mapping()
https://jira.sw.ru/browse/PSBM-78538
https://jira.sw.ru/browse/PSBM-45999
Signed-off-by: Maxim Patlasov <mpatlasov at virtuozzo.com>
Signed-off-by: Vasily Averin <vvs at virtuozzo.com>
---
drivers/block/ploop/io_direct.c | 3 ++-
drivers/block/ploop/io_direct_map.c | 18 +++++++++++++-----
drivers/block/ploop/io_direct_map.h | 3 ++-
3 files changed, 17 insertions(+), 7 deletions(-)
diff --git a/drivers/block/ploop/io_direct.c b/drivers/block/ploop/io_direct.c
index d6b1118bf2a3..9fd2d8f67df9 100644
--- a/drivers/block/ploop/io_direct.c
+++ b/drivers/block/ploop/io_direct.c
@@ -1756,7 +1756,8 @@ static int dio_truncate(struct ploop_io * io, struct file * file,
mutex_lock(&io->files.inode->i_mutex);
if (io->files.em_tree)
- trim_extent_mappings(io->files.em_tree, newattrs.ia_size>>9);
+ trim_extent_mappings(io->plo, io->files.em_tree,
+ newattrs.ia_size>>9);
io->files.inode->i_flags &= ~S_SWAPFILE;
err = notify_change(F_DENTRY(file), &newattrs, NULL);
io->files.inode->i_flags |= S_SWAPFILE;
diff --git a/drivers/block/ploop/io_direct_map.c b/drivers/block/ploop/io_direct_map.c
index db1da7db3d00..bfc9325b72c6 100644
--- a/drivers/block/ploop/io_direct_map.c
+++ b/drivers/block/ploop/io_direct_map.c
@@ -542,8 +542,9 @@ lookup_extent_mapping(struct extent_map_tree *tree, sector_t start, sector_t len
{
struct extent_map *em;
struct rb_node *rb_node;
+ unsigned long flags;
- read_lock_irq(&tree->lock);
+ read_lock_irqsave(&tree->lock, flags);
rb_node = tree_search(&tree->map, start);
if (!rb_node) {
em = NULL;
@@ -557,25 +558,29 @@ lookup_extent_mapping(struct extent_map_tree *tree, sector_t start, sector_t len
atomic_inc(&em->refs);
out:
- read_unlock_irq(&tree->lock);
+ read_unlock_irqrestore(&tree->lock, flags);
return em;
}
/*
* removes an extent_map struct from the tree. No reference counts are
* dropped, and no checks are done to see if the range is in use
+ *
+ * caller called spin_lock_irq(plo->lock), so we needn't _irq locking
*/
static int remove_extent_mapping(struct extent_map_tree *tree, struct extent_map *em)
{
int ret;
- write_lock_irq(&tree->lock);
+ WARN_ON(!irqs_disabled());
+
+ write_lock(&tree->lock);
ret = tree_delete(&tree->map, em->start);
if (!ret) {
list_del_init(&em->lru_link);
tree->map_size--;
}
- write_unlock_irq(&tree->lock);
+ write_unlock(&tree->lock);
return ret;
}
@@ -834,10 +839,12 @@ static int drop_extent_map(struct extent_map_tree *tree)
return 0;
}
-void trim_extent_mappings(struct extent_map_tree *tree, sector_t start)
+void trim_extent_mappings(struct ploop_device *plo,
+ struct extent_map_tree *tree, sector_t start)
{
struct extent_map *em;
+ spin_lock_irq(&plo->lock);
while ((em = lookup_extent_mapping(tree, start, ((sector_t)(-1ULL)) - start))) {
remove_extent_mapping(tree, em);
WARN_ON(atomic_read(&em->refs) != 2);
@@ -847,6 +854,7 @@ void trim_extent_mappings(struct extent_map_tree *tree, sector_t start)
/* once for the tree */
ploop_extent_put(em);
}
+ spin_unlock_irq(&plo->lock);
}
diff --git a/drivers/block/ploop/io_direct_map.h b/drivers/block/ploop/io_direct_map.h
index c93b5ac396a1..3db809aa6188 100644
--- a/drivers/block/ploop/io_direct_map.h
+++ b/drivers/block/ploop/io_direct_map.h
@@ -55,7 +55,8 @@ struct extent_map *map_extent_get_block(struct ploop_io *io,
struct address_space *mapping,
sector_t start, sector_t len, int create,
gfp_t gfp_mask, get_block_t get_block);
-void trim_extent_mappings(struct extent_map_tree *tree, sector_t start);
+void trim_extent_mappings(struct ploop_device *plo,
+ struct extent_map_tree *tree, sector_t start);
int ploop_dio_close(struct ploop_io * io, int rdonly);
struct extent_map_tree * ploop_dio_open(struct ploop_io * io, int rdonly);
More information about the Devel
mailing list