[Devel] [PATCH rh7 01/38] ploop: fix accounting ploop_io_images_size

Andrey Smetanin asmetanin at virtuozzo.com
Fri May 15 09:48:02 PDT 2015


ploop_io_images_size is a global counter supposed to be total sum of io->size
for all io structs. However, actual size of image can be used by userspace.
E.g. when userspace grows lower delta for merge operartion. This means that
by the time ploop_dio_close() is called, actual size may differ slightly from
the size we initially accounted.

The patch fixes the problem by accurate accounting of images sizes: we can
subtruct from ploop_io_images_size only so many bytes as we actually added
earlier.

Another fix is for growing lower delta in userspace: we try to catch up
changes made by userspace when kernel merge starts and ploop_dio_upgrade
is being called.

https://jira.sw.ru/browse/PSBM-19906

Signed-off-by: Maxim V. Patlasov <MPatlasov at parallels.com>
---
 drivers/block/ploop/io_direct.c     | 12 +++++-------
 drivers/block/ploop/io_direct_map.c | 20 +++++++++++++++-----
 drivers/block/ploop/io_direct_map.h |  6 +++---
 3 files changed, 23 insertions(+), 15 deletions(-)

diff --git a/drivers/block/ploop/io_direct.c b/drivers/block/ploop/io_direct.c
index 8d716ca..cbb7edc 100644
--- a/drivers/block/ploop/io_direct.c
+++ b/drivers/block/ploop/io_direct.c
@@ -852,7 +852,7 @@ static void dio_destroy(struct ploop_io * io)
 		if (io->files.em_tree) {
 			io->files.em_tree = NULL;
 			mutex_lock(&io->files.inode->i_mutex);
-			ploop_dio_close(io->files.mapping, delta->flags & PLOOP_FMT_RDONLY);
+			ploop_dio_close(io, delta->flags & PLOOP_FMT_RDONLY);
 			(void)dio_invalidate_cache(io->files.mapping, io->files.bdev);
 			mutex_unlock(&io->files.inode->i_mutex);
 		}
@@ -910,7 +910,7 @@ static int dio_open(struct ploop_io * io)
 	dio_fsync(file);
 
 	mutex_lock(&io->files.inode->i_mutex);
-	em_tree = ploop_dio_open(io->files.file, (delta->flags & PLOOP_FMT_RDONLY));
+	em_tree = ploop_dio_open(io, (delta->flags & PLOOP_FMT_RDONLY));
 	err = PTR_ERR(em_tree);
 	if (IS_ERR(em_tree))
 		goto out;
@@ -920,7 +920,7 @@ static int dio_open(struct ploop_io * io)
 	err = dio_invalidate_cache(io->files.mapping, io->files.bdev);
 	if (err) {
 		io->files.em_tree = NULL;
-		ploop_dio_close(io->files.mapping, 0);
+		ploop_dio_close(io, 0);
 		goto out;
 	}
 
@@ -930,7 +930,7 @@ static int dio_open(struct ploop_io * io)
 						  delta->plo->index);
 		if (io->fsync_thread == NULL) {
 			io->files.em_tree = NULL;
-			ploop_dio_close(io->files.mapping, 0);
+			ploop_dio_close(io, 0);
 			goto out;
 		}
 		wake_up_process(io->fsync_thread);
@@ -938,8 +938,6 @@ static int dio_open(struct ploop_io * io)
 
 out:
 	mutex_unlock(&io->files.inode->i_mutex);
-	if (!err)
-		io->size = i_size_read(io->files.inode);
 	return err;
 }
 
@@ -1644,7 +1642,7 @@ static int dio_prepare_merge(struct ploop_io * io, struct ploop_snapdata *sd)
 		return err;
 	}
 
-	err = ploop_dio_upgrade(io->files.mapping);
+	err = ploop_dio_upgrade(io);
 	if (err) {
 		mutex_unlock(&io->files.inode->i_mutex);
 		fput(file);
diff --git a/drivers/block/ploop/io_direct_map.c b/drivers/block/ploop/io_direct_map.c
index 62984bf..2ddf93a 100644
--- a/drivers/block/ploop/io_direct_map.c
+++ b/drivers/block/ploop/io_direct_map.c
@@ -52,10 +52,11 @@ extern atomic_long_t ploop_io_images_size;
  */
 
 struct extent_map_tree *
-ploop_dio_open(struct file * file, int rdonly)
+ploop_dio_open(struct ploop_io * io, int rdonly)
 {
 	int err;
 	struct ploop_mapping *m, *pm;
+	struct file * file = io->files.file;
 	struct address_space * mapping = file->f_mapping;
 
 	pm = kzalloc(sizeof(struct ploop_mapping), GFP_KERNEL);
@@ -100,7 +101,8 @@ out_unlock:
 	pm->readers = rdonly ? 1 : -1;
 	list_add(&pm->list, &ploop_mappings);
 	mapping->host->i_flags |= S_SWAPFILE;
-	atomic_long_add(i_size_read(mapping->host), &ploop_io_images_size);
+	io->size = i_size_read(mapping->host);
+	atomic_long_add(io->size, &ploop_io_images_size);
 
 	pm->saved_gfp_mask = mapping_gfp_mask(mapping);
 	mapping_set_gfp_mask(mapping,
@@ -125,8 +127,9 @@ out_unlock:
 }
 
 int
-ploop_dio_close(struct address_space * mapping, int rdonly)
+ploop_dio_close(struct ploop_io * io, int rdonly)
 {
+	struct address_space * mapping = io->files.mapping;
 	struct ploop_mapping *m, *pm = NULL;
 
 	spin_lock(&ploop_mappings_lock);
@@ -140,8 +143,9 @@ ploop_dio_close(struct address_space * mapping, int rdonly)
 			}
 
 			if (m->readers == 0) {
-				atomic_long_sub(i_size_read(mapping->host),
+				atomic_long_sub(io->size,
 						&ploop_io_images_size);
+				io->size = 0;
 				mapping->host->i_flags &= ~S_SWAPFILE;
 				list_del(&m->list);
 				pm = m;
@@ -175,8 +179,9 @@ void ploop_dio_downgrade(struct address_space * mapping)
 	spin_unlock(&ploop_mappings_lock);
 }
 
-int ploop_dio_upgrade(struct address_space * mapping)
+int ploop_dio_upgrade(struct ploop_io * io)
 {
+	struct address_space * mapping = io->files.mapping;
 	struct ploop_mapping * m;
 	int err = -ESRCH;
 
@@ -185,6 +190,11 @@ int ploop_dio_upgrade(struct address_space * mapping)
 		if (m->mapping == mapping) {
 			err = -EBUSY;
 			if (m->readers == 1) {
+				loff_t new_size = i_size_read(io->files.inode);
+				atomic_long_add(new_size - io->size,
+						&ploop_io_images_size);
+				io->size = new_size;
+
 				m->readers = -1;
 				err = 0;
 			}
diff --git a/drivers/block/ploop/io_direct_map.h b/drivers/block/ploop/io_direct_map.h
index cb5804c..79e00e3 100644
--- a/drivers/block/ploop/io_direct_map.h
+++ b/drivers/block/ploop/io_direct_map.h
@@ -50,10 +50,10 @@ struct extent_map *map_extent_get_block(struct extent_map_tree *tree,
 					gfp_t gfp_mask, get_block_t get_block);
 void trim_extent_mappings(struct extent_map_tree *tree, sector_t start);
 
-int ploop_dio_close(struct address_space * mapping, int rdonly);
-struct extent_map_tree * ploop_dio_open(struct file * file, int rdonly);
+int ploop_dio_close(struct ploop_io * io, int rdonly);
+struct extent_map_tree * ploop_dio_open(struct ploop_io * io, int rdonly);
 void ploop_dio_downgrade(struct address_space * mapping);
-int ploop_dio_upgrade(struct address_space * mapping);
+int ploop_dio_upgrade(struct ploop_io * io);
 
 int __init extent_map_init(void);
 void extent_map_exit(void);
-- 
1.9.3




More information about the Devel mailing list