On Thu, Mar 26, 2020 at 01:35:56PM +0800, Qu Wenruo wrote: > For certain btrfs files with compressed file extent, uboot will fail to > load it: > > btrfs_read_extent_reg: disk_bytenr=14229504 disk_len=73728 offset=0 nr_bytes=131 > 072 > decompress_lzo: tot_len=70770 > decompress_lzo: in_len=1389 > decompress_lzo: in_len=2400 > decompress_lzo: in_len=3002 > decompress_lzo: in_len=1379 > decompress_lzo: in_len=88539136 > decompress_lzo: header error, in_len=88539136 clen=65534 tot_len=62580 > > NOTE: except the last line, all other lines are debug output. > > Btrfs lzo compression uses its own format to record compressed size > (segment header, LE32). > > However to make decompression easier, we never put such segment header > across page boundary. > > In above case, the xxd dump of the lzo compressed data looks like this: > > 00001fe0: 4cdc 02fc 0bfd 02c0 dc02 0d13 0100 0001 L............... > 00001ff0: 0000 0008 0300 0000 0000 0011 0000|0000 ................ > 00002000: 4705 0000 0001 cc02 0000 0000 0000 1e01 G............... > > '|' is the "expected" segment header start position. > > But in that page, there are only 2 bytes left, can't contain the 4 bytes > segment header. > > So btrfs compression will skip that 2 bytes, put the segment header in > next page directly. > > Uboot doesn't have such check, and read the header with 2 bytes offset, > result 0x05470000 (88539136), other than the expected result > 0x00000547 (1351), resulting above error. > > Follow the btrfs-progs restore implementation, by introducing tot_in to > record total processed bytes (including headers), and do proper page > boundary skip to fix it. > > Please note that, current code base doesn't parse fs_info thus we can't > grab sector size easily, so it uses PAGE_SIZE, and relying on fs open > time check to exclude unsupported sector size. > > Signed-off-by: Qu Wenruo > Cc: Marek Behun > Reviewed-by: Marek Behún Applied to u-boot/master, thanks! -- Tom