
On 04/04/2014 02:54 AM, Peter Krempa wrote:
On 04/04/14 06:32, Eric Blake wrote:
I'm about to add fields to virStorageFileMetadata, which means also adding fields to the testFileData struct in virstoragetest. Alas, adding even one pointer on an x86_64 machine gave me a dreaded compiler error:
virstoragetest.c:712:1: error: the frame size of 4208 bytes is larger than 4096 bytes [-Werror=frame-larger-than=]
After some experimentation, I realized that each test was creating yet another testChainData (which contains testFileData) on the stack; forcing the reuse of one of these structures instead of creating a fresh one each time drastically reduces the size requirements. While at it, I also got rid of a lot of intermediate structs, with some macro magic that lets me directly build up the destination chains inline.
Unfortunately it's not completely trivial to understand what's happening on the first glance.
I'll expand the commit message before pushing. Basically,
-#define TEST_ONE_CHAIN(id, start, format, chain, flags) \ +#define TEST_ONE_CHAIN(id, start, format, flags, ...) \ do { \ - struct testChainData data = { \ - start, format, chain, ARRAY_CARDINALITY(chain), flags, \
the old code was populating data.files = chain, where 'chain' was an intermediate variable and files is a testFileData*
+ size_t i; \ + memset(&data, 0, sizeof(data)); \ + data = (struct testChainData){ \ + start, format, { __VA_ARGS__ }, 0, flags, \ }; \
while the new code is populating data.files = { ptr, ptr, ... }, with no intermediate chain variable, and where files is now an array of testFileData*.
+ for (i = 0; i < ARRAY_CARDINALITY(data.files); i++) \ + if (data.files[i]) \ + data.nfiles++; \
Pre-patch, counting the number of files was done by the size of the 'chain' intermediate variable. Post-patch, it is done by counting the number of non-NULL pointers in the 'files' array.
+ TEST_ONE_CHAIN(#id "a", relstart, format, flags1, \ + VIR_FLATTEN_1(chain1)); \
Here, VIR_FLATTEN_1 is macro magic that takes a single macro argument in the form '(a, b, c)' and turns it into multiple arguments 'a, b, c' to TEST_ONE_CHAIN's use of '...'
/* Raw image, whether with right format or no specified format */ - const testFileData chain1[] = { raw }; TEST_CHAIN(1, "raw", absraw, VIR_STORAGE_FILE_RAW, - chain1, EXP_PASS, - chain1, ALLOW_PROBE | EXP_PASS, - chain1, EXP_PASS, - chain1, ALLOW_PROBE | EXP_PASS); + (&raw), EXP_PASS, + (&raw), ALLOW_PROBE | EXP_PASS, + (&raw), EXP_PASS, + (&raw), ALLOW_PROBE | EXP_PASS);
Then for each test, I replaced uses of 'chain1' (the intermediate variable)' with '(contents of chain1)' as a direct argument to TEST_CHAIN.
As it's test code: ACK
Yes, we have that going for us - if it compiles and still passes the testsuite, it was probably correct :) -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org