On Thu, Mar 28, 2024 at 04:39:04PM -0400, Stefan Hajnoczi wrote: > Run the tests with: > > $ make TARGETS=block_seek_hole -C tools/selftests run_tests > > Signed-off-by: Stefan Hajnoczi <stefanha@xxxxxxxxxx> > --- > tools/testing/selftests/Makefile | 1 + > .../selftests/block_seek_hole/Makefile | 17 +++ > .../testing/selftests/block_seek_hole/config | 1 + > .../selftests/block_seek_hole/map_holes.py | 37 +++++++ > .../testing/selftests/block_seek_hole/test.py | 103 ++++++++++++++++++ > 5 files changed, 159 insertions(+) > create mode 100644 tools/testing/selftests/block_seek_hole/Makefile > create mode 100644 tools/testing/selftests/block_seek_hole/config > create mode 100755 tools/testing/selftests/block_seek_hole/map_holes.py > create mode 100755 tools/testing/selftests/block_seek_hole/test.py > > + > +def map_holes(fd): > + end = os.lseek(fd, 0, os.SEEK_END) > + offset = 0 > + > + print('TYPE START END SIZE') > + > + while offset < end: > + contents = 'DATA' > + new_offset = os.lseek(fd, offset, os.SEEK_HOLE) > + if new_offset == offset: > + contents = 'HOLE' > + try: > + new_offset = os.lseek(fd, offset, os.SEEK_DATA) > + except OSError as err: > + if err.errno == errno.ENXIO: > + new_offset = end > + else: > + raise err > + assert new_offset != offset > + print(f'{contents} {offset} {new_offset} {new_offset - offset}') > + offset = new_offset Over the years, I've seen various SEEK_HOLE implementation bugs where things work great on the initial boundary, but fail when requested on an offset not aligned to the start of the extent boundary. It would probably be worth enhancing the test to prove that: if lseek(fd, offset, SEEK_HOLE) == offset: new_offset = lseek(fd, offset, SEEK_DATA) assert new_offset > offset assert lseek(fd, new_offset - 1, SEEK_HOLE) == new_offset - 1 else: assert lseek(fd, offset, SEEK_DATA) == offset new_offset = lseek(fd, offset, SEEK_HOLE) assert new_offset > offset assert lseek(fd, new_offset - 1, SEEK_DATA) == new_offset - 1 Among other things, this would prove that even though block devices generally operate on a minimum granularity of a sector, lseek() still gives byte-accurate results for a random offset that falls in the middle of a sector, and doesn't accidentally round down reporting an offset less than the value passed in to the request. -- Eric Blake, Principal Software Engineer Red Hat, Inc. Virtualization: qemu.org | libguestfs.org