Merge remote-tracking branch 'origin/pr/384'

* origin/pr/384:
  storage/file: fix is_dirty() false positive
  storage/file: refactor is_dirty()
This commit is contained in:
Marek Marczykowski-Górecki 2021-02-11 11:26:53 +01:00
commit df7cd63bd1
No known key found for this signature in database
GPG Key ID: 063938BA42CFA724
2 changed files with 16 additions and 6 deletions

View File

@ -4,6 +4,8 @@
# #
# This creates dm-snapshot device on given arguments # This creates dm-snapshot device on given arguments
SNAPSHOT_CHUNKSIZE=256 # same as in file.py
dir=$(dirname "$0") dir=$(dirname "$0")
if [ "$1" = "prepare" ] || [ "$1" = "cleanup" ]; then if [ "$1" = "prepare" ] || [ "$1" = "cleanup" ]; then
# shellcheck disable=SC1090,SC1091 # shellcheck disable=SC1090,SC1091
@ -80,7 +82,7 @@ create_dm_snapshot() {
base_dev=$(get_dev "$base") base_dev=$(get_dev "$base")
cow_dev=$(get_dev "$cow") cow_dev=$(get_dev "$cow")
base_sz=$(blockdev --getsz "$base_dev") base_sz=$(blockdev --getsz "$base_dev")
do_or_die dmsetup create "$dm_devname" --table "0 $base_sz snapshot $base_dev $cow_dev P 256" do_or_die dmsetup create "$dm_devname" --table "0 $base_sz snapshot $base_dev $cow_dev P $SNAPSHOT_CHUNKSIZE"
fi fi
} }

View File

@ -33,6 +33,12 @@ import qubes.utils
BLKSIZE = 512 BLKSIZE = 512
# 256 KiB chunk, same as in block-snapshot script. Header created by
# struct.pack('<4I', 0x70416e53, 1, 1, 256) mimicking write_header()
# in linux/drivers/md/dm-snap-persistent.c
EMPTY_SNAPSHOT = b'SnAp\x01\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00' \
+ bytes(262128)
class FilePool(qubes.storage.Pool): class FilePool(qubes.storage.Pool):
''' File based 'original' disk implementation ''' File based 'original' disk implementation
@ -214,11 +220,13 @@ class FileVolume(qubes.storage.Volume):
_remove_if_exists(self.path_cow) _remove_if_exists(self.path_cow)
def is_dirty(self): def is_dirty(self):
if not self.save_on_stop: if self.save_on_stop:
return False with suppress(FileNotFoundError), open(self.path_cow, 'rb') as cow:
if os.path.exists(self.path_cow): cow_used = os.fstat(cow.fileno()).st_blocks * BLKSIZE
stat = os.stat(self.path_cow) return (cow_used > 0 and
return stat.st_blocks > 0 (cow_used > len(EMPTY_SNAPSHOT) or
cow.read(len(EMPTY_SNAPSHOT)) != EMPTY_SNAPSHOT or
cow_used > cow.seek(0, os.SEEK_HOLE)))
return False return False
def resize(self, size): def resize(self, size):