On Fri, May 03, 2024 at 05:36:59PM -0300, Fabiano Rosas wrote: > Peter Xu <pet...@redhat.com> writes: > > > On Fri, Apr 26, 2024 at 11:20:36AM -0300, Fabiano Rosas wrote: > >> When doing file migration, QEMU accepts an offset that should be > >> skipped when writing the migration stream to the file. The purpose of > >> the offset is to allow the management layer to put its own metadata at > >> the start of the file. > >> > >> We have tests for this in migration-test, but only testing that the > >> migration stream starts at the correct offset and not that it actually > >> leaves the data intact. Unsurprisingly, there's been a bug in that > >> area that the tests didn't catch. > >> > >> Fix the tests to write some data to the offset region and check that > >> it's actually there after the migration. > >> > >> Fixes: 3dc35470c8 ("tests/qtest: migration-test: Add tests for file-based > >> migration") > >> Signed-off-by: Fabiano Rosas <faro...@suse.de> > >> --- > >> tests/qtest/migration-test.c | 70 +++++++++++++++++++++++++++++++++--- > >> 1 file changed, 65 insertions(+), 5 deletions(-) > >> > >> diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c > >> index 5d6d8cd634..7b177686b4 100644 > >> --- a/tests/qtest/migration-test.c > >> +++ b/tests/qtest/migration-test.c > >> @@ -2081,6 +2081,63 @@ static void test_precopy_file(void) > >> test_file_common(&args, true); > >> } > >> > >> +#ifndef _WIN32 > >> +static void file_dirty_offset_region(void) > >> +{ > >> +#if defined(__linux__) > > > > Hmm, what's the case to cover when !_WIN32 && __linux__? Can we remove one > > layer of ifdef? > > > > I'm also wondering why it can't work on win32? I thought win32 has all > > these stuff we used here, but I may miss something. > > > > __linux__ is because of mmap, !_WIN32 is because of the passing of > fds. We might be able to keep !_WIN32 only, I'll check. > > >> + g_autofree char *path = g_strdup_printf("%s/%s", tmpfs, > >> FILE_TEST_FILENAME); > >> + size_t size = FILE_TEST_OFFSET; > >> + uintptr_t *addr, *p; > >> + int fd; > >> + > >> + fd = open(path, O_CREAT | O_RDWR, 0660); > >> + g_assert(fd != -1); > >> + > >> + g_assert(!ftruncate(fd, size)); > >> + > >> + addr = mmap(NULL, size, PROT_WRITE, MAP_SHARED, fd, 0); > >> + g_assert(addr != MAP_FAILED); > >> + > >> + /* ensure the skipped offset contains some data */ > >> + p = addr; > >> + while (p < addr + FILE_TEST_OFFSET / sizeof(uintptr_t)) { > >> + *p = (unsigned long) FILE_TEST_FILENAME; > > > > This is fine, but not as clear what is assigned.. I think here we assigned > > is the pointer pointing to the binary's RO section (rather than the chars). > > Haha you're right, I was assigning the FILE_TEST_OFFSET previously and > just switched to the FILENAME without thinking. I'll fix it up. > > > Maybe using some random numbers would be more straightforward, but no > > strong opinions. > > > >> + p++; > >> + } > >> + > >> + munmap(addr, size); > >> + fsync(fd); > >> + close(fd); > >> +#endif > >> +}
Use of mmap and this loop looks like overkill to me, when we can do it in a fully portable manner with: g_autofree char *data = g_new0(char *, offset); memset(data, 0x44, offset); g_file_set_contents(path, data, offset, NULL); and I checked that g_file_set_contents' impl also takes care of fsync. With regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|