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