The balloon holds filesystem space that never carries data, but its
blocks are allocated, so FITRIM walks past them, and inflating the
balloon is a plain fallocate() that does not discard either. Once the
balloon is inflated over the blocks of removed files, e.g. on an online
shrink of a Container disk, the ploop or qcow2 image keeps those
clusters mapped for good, and compaction, which is FITRIM, does not
give them back (VSTOR-153590).

This series makes FITRIM discard the unwritten extents of the balloon
after the free space, on ext4 (patch 2) and xfs (patch 3). The walk
holds the inode locks of the balloon exclusively, after waiting for
direct I/O and flushing its page cache, as punch hole does, so no block
can be freed, reused or written under the discard. Physically adjacent
extents are merged, so that the device below gets whole clusters, and
a long run is discarded in interruptible chunks. A balloon inflated
before this series is released by the next FITRIM, no userspace change
is needed. Patch 1 fixes an inode reference leak in xfs_balloon_get()
that FITRIM would now hit too.

The ploop side is openvz/ploop.ovz PR 519: tests for this, and fixes of
the ploop-balloon discard options found on the way:
https://bitbucket.org/openvz/ploop.ovz/pull-requests/519

Changes since v1
(https://lore.virtuozzo.com/kernel/[email protected]/):
- take the balloon inode locks exclusively, wait for direct I/O and
  flush the page cache before the walk; v1 held the shared lock, which
  did not keep writeback and direct I/O from converting an extent the
  walk had seen unwritten (Sashiko);
- walk to the end of the file instead of i_size, as fallocate() with
  FALLOC_FL_KEEP_SIZE can leave unwritten extents past it (Sashiko);
- discard a merged run in chunks aligned to the discard granularity,
  checking for fatal signals and freezing between them;
- drop the read-only mount skip: ploop does not set balloon_ino on a
  read-only mount, and the free space pass does not skip one either;
- ext4: do not count the balloon in the trimmed length, so fstrim -v no
  longer reports it as freed on every call; no 64-bit division on
  i_size any more (Sashiko);
- xfs: fail FITRIM on an error reading the balloon inode, use
  GFP_KERNEL, and fix the xfs_balloon_get() leak in patch 1 (Sashiko);
- every FITRIM still discards the balloon again: neither filesystem
  bumps a counter on fallocate() of the balloon that a skip could rely
  on, and a wrong skip would leave clusters mapped for good, while a
  repeated discard of unmapped clusters is cheap.

Tested on 6.12.0-211.52.1.22.19.vz10 rebuilt with this series and the
VSTOR-154159 max_discard_segments fixes:
- ploop and qcow2 images with ext4 and xfs: write 2G, remove it without
  a trim, inflate the balloon over the free space, ploop-balloon
  discard. Stock: the image keeps mapping the removed 2G. Patched: the
  image maps about as much as when it was created, a kept file is
  intact, fsck and ploop check / qemu-img check are clean;
- 16G removed under a balloon of about 38G: a full fstrim takes under
  3 seconds, a SIGKILL one second into it ends fstrim at once, a
  repeated fstrim takes a fraction of a second, fsck is clean;
- test_ploop_balloon.py from PR 519: green on ploop and qcow2. On the
  stock kernel only the tests for the space under the balloon fail.

Not covered: ext4 bigalloc, a realtime xfs balloon (skipped). On ploop1
discard works on whole clusters, so up to two clusters at the ends of
each contiguous piece of the balloon stay mapped, as do pieces shorter
than the FITRIM minimum length.

Denis V. Lunev (3):
  xfs: release the balloon inode when xfs_balloon_get() refuses it
  ext4: discard the balloon on FITRIM
  xfs: discard the balloon on FITRIM

 fs/ext4/mballoc.c    | 126 +++++++++++++++++++++++++++++++++++++
 fs/xfs/xfs_discard.c | 144 +++++++++++++++++++++++++++++++++++++++++++
 fs/xfs/xfs_super.c   |   4 +-
 3 files changed, 273 insertions(+), 1 deletion(-)

-- 
2.53.0

_______________________________________________
Devel mailing list
[email protected]
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to