The way how we kept ploop_io_images_size up-to-date (should be always
equal to total number of bytes of all loaded image files) was very prone
to errors: first delta loaded kept actual io->size, then backup delta was
initialized with io->size=0; since then, if first delta was unloaded before
the second, unloading the second delta led to subtracting io->size=0 from
ploop_io_images_size. This is obviously incorrect.

The patch makes the accounting much more straightforward: the size of image
is actually the property of mapping, not a delta (because several deltas
may point to the same mapping). So, let's keep actual 'size' in ploop_mapping
structure and let every delta point to it.

No extra locking is needed because the image is either opened by several
device read-only, or one and only one device read-write.

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

Signed-off-by: Maxim Patlasov <mpatla...@parallels.com>
---
 drivers/block/ploop/io_direct.c     | 10 +++++-----
 drivers/block/ploop/io_direct_map.c | 16 ++++++++++------
 include/linux/ploop/ploop.h         |  2 +-
 3 files changed, 16 insertions(+), 12 deletions(-)

diff --git a/drivers/block/ploop/io_direct.c b/drivers/block/ploop/io_direct.c
index 17dbf6c..ab74849 100644
--- a/drivers/block/ploop/io_direct.c
+++ b/drivers/block/ploop/io_direct.c
@@ -31,7 +31,7 @@
 int max_extent_map_pages __read_mostly;
 int min_extent_map_entries __read_mostly;
 
-/* total sum of io->size for all io structs */
+/* total sum of m->size for all ploop_mapping structs */
 atomic_long_t ploop_io_images_size = ATOMIC_LONG_INIT(0);
 
 /* Direct IO from/to file.
@@ -436,8 +436,8 @@ try_again:
        mutex_unlock(&io->files.inode->i_mutex);
 
        new_size = i_size_read(io->files.inode);
-       atomic_long_add(new_size - io->size, &ploop_io_images_size);
-       io->size = new_size;
+       atomic_long_add(new_size - *io->size_ptr, &ploop_io_images_size);
+       *io->size_ptr = new_size;
 
        if (!err)
                err = filemap_fdatawrite(io->files.mapping);
@@ -1684,8 +1684,8 @@ static int dio_truncate(struct ploop_io * io, struct file 
* file,
        mutex_unlock(&io->files.inode->i_mutex);
 
        new_size = i_size_read(io->files.inode);
-       atomic_long_sub(io->size - new_size, &ploop_io_images_size);
-       io->size = new_size;
+       atomic_long_sub(*io->size_ptr - new_size, &ploop_io_images_size);
+       *io->size_ptr = new_size;
 
        if (!err)
                err = dio_fsync(file);
diff --git a/drivers/block/ploop/io_direct_map.c 
b/drivers/block/ploop/io_direct_map.c
index 6b0886c..b3cb04d 100644
--- a/drivers/block/ploop/io_direct_map.c
+++ b/drivers/block/ploop/io_direct_map.c
@@ -31,6 +31,7 @@ struct ploop_mapping
        struct address_space    * mapping;
        int                     readers;
        unsigned long           saved_gfp_mask;
+       loff_t                  size;
 
        struct extent_map_tree  extent_root;
 };
@@ -81,6 +82,8 @@ out_unlock:
                        spin_unlock(&ploop_mappings_lock);
                        if (pm)
                                kfree(pm);
+                       if (!err)
+                               io->size_ptr = &m->size;
                        return err ? ERR_PTR(err) : &m->extent_root;
                }
        }
@@ -101,8 +104,9 @@ out_unlock:
        pm->readers = rdonly ? 1 : -1;
        list_add(&pm->list, &ploop_mappings);
        mapping->host->i_flags |= S_SWAPFILE;
-       io->size = i_size_read(mapping->host);
-       atomic_long_add(io->size, &ploop_io_images_size);
+       io->size_ptr = &pm->size;
+       *io->size_ptr = i_size_read(mapping->host);
+       atomic_long_add(*io->size_ptr, &ploop_io_images_size);
 
        pm->saved_gfp_mask = mapping_gfp_mask(mapping);
        mapping_set_gfp_mask(mapping,
@@ -143,9 +147,9 @@ ploop_dio_close(struct ploop_io * io, int rdonly)
                        }
 
                        if (m->readers == 0) {
-                               atomic_long_sub(io->size,
+                               atomic_long_sub(*io->size_ptr,
                                                &ploop_io_images_size);
-                               io->size = 0;
+                               *io->size_ptr = 0;
                                mapping->host->i_flags &= ~S_SWAPFILE;
                                list_del(&m->list);
                                pm = m;
@@ -191,9 +195,9 @@ int ploop_dio_upgrade(struct ploop_io * io)
                        err = -EBUSY;
                        if (m->readers == 1) {
                                loff_t new_size = i_size_read(io->files.inode);
-                               atomic_long_add(new_size - io->size,
+                               atomic_long_add(new_size - *io->size_ptr,
                                                &ploop_io_images_size);
-                               io->size = new_size;
+                               *io->size_ptr = new_size;
 
                                m->readers = -1;
                                err = 0;
diff --git a/include/linux/ploop/ploop.h b/include/linux/ploop/ploop.h
index ea86ce6..d295cba 100644
--- a/include/linux/ploop/ploop.h
+++ b/include/linux/ploop/ploop.h
@@ -91,7 +91,7 @@ struct ploop_io
 {
        struct ploop_device     *plo;
 
-       loff_t                  size;
+       loff_t                 *size_ptr; /* NULL or points to ploop_mapping */
        loff_t                  prealloced_size;
        struct ploop_request   *prealloc_preq;  /* preq who does prealloc */
        loff_t                  max_size;       /* Infinity */
-- 
1.9.3

_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to