Snapshot delete happens in 2 passes: shrink and merge. Shrink pass may have read all snapshot metadata to page cache causing the merge pass to run for a long time with no I/O. We need to add mode cond_resched() points during merge, to prevent system freeze on single CPU machine.
ext4_snapshot_count_branches() was copied from ext4_free_branches(). The latter drops bh refcount in ext4_forget(), but the former didn't drop the refcount.
The 2 implementations of ext4_group_used_meta_blocks() were conflicting so I imlemented a 3rd version of the func, using an helper variable to make the final result more easy on the eye.
ext4dev/Kconfig is not included in fs/Kconfig on purpose. Configurations options are defined in ext4dev.h. clone_ext4dev.sh prepares a patch for adding ext4dev fs to kernel build.
If the exclude bitmap block is not in the group, we should not count it.
ext4_group_used_meta_blocks() counts metadata blocks in the group. it always counted 1 exclude bitmap, even if exclude bitmap was not in the group, in the case of flex_bg. Note that this function doesn't count the number of metadata blocks in the first flex_bg group correctly, which is why mkfs always initializes the block bitmap of the first flex_bg group.
since we cannot allocate direct blocks in snapshot files using ext4_getblk() anymore, we allocate the DIND branches at offset 0 and move it to the TIND branch we want to pre-allocate.
Snapshot image addresses should need to cover a 16TB filesystem (2^32-1 blocks). Snapshot image logical address 0 was the first doubly indirect mapped block at offset 1036 in the snapshot inode. This caused a 32bit overflow when calling ext4_blk_to_path for the last blocks in a 16TB snapshot file (2^32+1035). We change the code to always use logical addresses 0..2^32-1 when accessing snapshot files and only deal with the 1036 offset inside ext4_blk_to_path, where the overflow can be noticed and handled properly. ext4_snapblk_t has be depraced and ext4_lblk_t is used instead. SNAPSHOT_BLOCK() and SNAPSHOT_IBLOCK() macros now don't change the offset, only cast from ext4_lblk_t to ext4_fsblk_t and back. Also changed some XXX_cow function names to remove the _cow suffix, changed ext4_free_data_cow to ext4_free_data_bitmap and documented the new arguments to those function.
1] Let ext4_mb_mark_space_used() use ext4_snapshot_exclude_blocks instead of handling exclude bimap itself. 2] Clear EXCLUDE_UNINIT if exclude bitmap is modified first time.
Reproduced on x86_64 machines by myself and Sergey with stand alone ext4dev module. xfstest 251 hangs for the same reason.
1. Remove unnecessary args of ext4_move_to_snapshot(). 2. Correct comment for ext4_snapshot_test_and_move().
The function moves old blocks to the snapshot and splices new blocks to the file.
snapshot file size is limited by 32bit logical block address the same as extent mapped file, so there is no need to change s_bitmap_maxbytes which also affects other indirect mapped files. Instead, use s_maxbytes to limit snapshot files seek and don't allow snapshot files size change by truncate syscall.