Hi, Anatoly Pugachev wrote: > mator@chubaka:~$ md5sum /tmp/half_sparse /mnt/iso/half_sparse > 3e98c342558c453b379cf7699f98a108 /tmp/half_sparse > Segmentation fault
Hah ! The obvious bug about all-zero blocks has bitten. I would not have expected a memory fault, though. Rather some false output and maybe an i/o error at the end. > mator@chubaka:~$ md5sum /tmp/full_random /mnt/iso/full_random > 9014e927951d25e01aa89858ebb82ce6 /tmp/full_random > 9014e927951d25e01aa89858ebb82ce6 /mnt/iso/full_random I don't understand how this can work. If i am not totally mistaken, the code omits a pair of zlib_inflateEnd zlib_inflateInit when decompressing 2 consequtive zisofs blocks as one. If page size is <= 32 KiB, the code does for the two zisofs blocks: zlib_inflateInit zlib_inflate ... zlib_inflate zlib_inflateEnd zlib_inflateInit zlib_inflate ... zlib_inflate zlib_inflateEnd But with 64 KiB the same data get processed by a single: zlib_inflateInit zlib_inflate ... zlib_inflate zlib_inflateEnd Either zlib tolerates this by design or my assessment of this case in the code is wrong. (I prepare myself for more embarrassment ...) At least i have the triumph of the zero block bug. But i should better try to understand why it leads to a memory error. > Nov 12 19:28:50 chubaka kernel: NIP [c0000000000ad4b0] .memset+0x68/0x104 > [...] .zisofs_readpage+0x470/0xd90 [isofs] (unreliable) > [...] .read_pages+0x2f8/0x390 > [...] .page_cache_readahead_unbounded+0x224/0x2f0 > [...] .generic_file_buffered_read+0x704/0xcf0 > [...] .new_sync_read+0x13c/0x1e0 > [...] .vfs_read+0x1a0/0x210 There are two occasions of memset() underneath zisofs_readpage(). One of them, in zisofs_fill_pages(), already cought my attention because it plays with a potentially invalid memory pointer. ret = zisofs_uncompress_block(inode, block_start, block_end, pcount, pages, poffset, &err); poffset += ret; pages += poffset >> PAGE_SHIFT; ... poffset &= ~PAGE_MASK; ret is supposed to be 65366. PAGE_SHIFT is 16. PAGE_MASK is 65365. So "pages" gets altered. Later comes: if (poffset && *pages) { memset(page_address(*pages) + poffset, 0, PAGE_SIZE - poffset); flush_dcache_page(*pages); SetPageUptodate(*pages); } I could not imagine how poffset would be non-0 here. But if it is, and if the "pages" array has only one member, then memset() is the first to read the bytes after the kmalloc'ed "pages" and to perform a write operation to a location that depends on their value. Now the question is how poffset became unaligned to 64 KiB. The best chance for that is at the very end of the file. Does dd, after umount and mount, yield bytes before the memory fault happens ? If so, how many. Have a nice day :) Thomas