[Devel] [PATCH RHEL7 COMMIT] ploop: fix accounting ploop_io_images_size

Konstantin Khorenko khorenko at odin.com
Mon May 18 21:26:54 PDT 2015


The commit is pushed to "branch-rh7-3.10.0-123.1.2-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-123.1.2.vz7.5.1
------>
commit 09fe781813a8c4e74ad6f9621cf26acb705424f4
Author: Andrey Smetanin <asmetanin at virtuozzo.com>
Date:   Tue May 19 08:26:54 2015 +0400

    ploop: fix accounting ploop_io_images_size
    
    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);



More information about the Devel mailing list