Merge remote-tracking branch 'qubesos/pr/201'
* qubesos/pr/201: storage/reflink: reorder start() to be more readable storage/reflink: simplify storage/reflink: let _remove_empty_dir() ignore ENOTEMPTY storage/reflink: show size in refused volume shrink message storage/reflink: fsync() after resizing existing file
This commit is contained in:
commit
a3a6a462f3
@ -117,8 +117,7 @@ class ReflinkVolume(qubes.storage.Volume):
|
|||||||
|
|
||||||
def verify(self):
|
def verify(self):
|
||||||
if self.snap_on_start:
|
if self.snap_on_start:
|
||||||
# pylint: disable=protected-access
|
img = self.source._path_clean # pylint: disable=protected-access
|
||||||
img = self.source._path_clean
|
|
||||||
elif self.save_on_stop:
|
elif self.save_on_stop:
|
||||||
img = self._path_clean
|
img = self._path_clean
|
||||||
else:
|
else:
|
||||||
@ -133,20 +132,11 @@ class ReflinkVolume(qubes.storage.Volume):
|
|||||||
''' Drop volume object from pool; remove volume images from
|
''' Drop volume object from pool; remove volume images from
|
||||||
oldest to newest; remove empty VM directory.
|
oldest to newest; remove empty VM directory.
|
||||||
'''
|
'''
|
||||||
with suppress(KeyError):
|
self.pool._volumes.pop(self, None) # pylint: disable=protected-access
|
||||||
# pylint: disable=protected-access
|
|
||||||
del self.pool._volumes[self]
|
|
||||||
|
|
||||||
self._prune_revisions(keep=0)
|
self._prune_revisions(keep=0)
|
||||||
_remove_file(self._path_clean)
|
_remove_file(self._path_clean)
|
||||||
_remove_file(self._path_dirty)
|
_remove_file(self._path_dirty)
|
||||||
|
_remove_empty_dir(os.path.dirname(self._path_dirty))
|
||||||
try:
|
|
||||||
_remove_empty_dir(os.path.dirname(self._path_dirty))
|
|
||||||
except OSError as ex:
|
|
||||||
if ex.errno is not errno.ENOTEMPTY:
|
|
||||||
raise
|
|
||||||
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def is_outdated(self):
|
def is_outdated(self):
|
||||||
@ -161,12 +151,12 @@ class ReflinkVolume(qubes.storage.Volume):
|
|||||||
return self.save_on_stop and os.path.exists(self._path_dirty)
|
return self.save_on_stop and os.path.exists(self._path_dirty)
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
|
if self.is_dirty(): # implies self.save_on_stop
|
||||||
|
return self
|
||||||
if self.snap_on_start:
|
if self.snap_on_start:
|
||||||
# pylint: disable=protected-access
|
# pylint: disable=protected-access
|
||||||
_copy_file(self.source._path_clean, self._path_clean)
|
_copy_file(self.source._path_clean, self._path_clean)
|
||||||
if self.is_dirty(): # implies self.save_on_stop
|
if self.snap_on_start or self.save_on_stop:
|
||||||
return self
|
|
||||||
if self.save_on_stop or self.snap_on_start:
|
|
||||||
_copy_file(self._path_clean, self._path_dirty)
|
_copy_file(self._path_clean, self._path_dirty)
|
||||||
else:
|
else:
|
||||||
_create_sparse_file(self._path_dirty, self.size)
|
_create_sparse_file(self._path_dirty, self.size)
|
||||||
@ -177,8 +167,7 @@ class ReflinkVolume(qubes.storage.Volume):
|
|||||||
self._commit()
|
self._commit()
|
||||||
else:
|
else:
|
||||||
_remove_file(self._path_dirty)
|
_remove_file(self._path_dirty)
|
||||||
if self.snap_on_start:
|
_remove_file(self._path_clean)
|
||||||
_remove_file(self._path_clean)
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def _commit(self):
|
def _commit(self):
|
||||||
@ -223,9 +212,9 @@ class ReflinkVolume(qubes.storage.Volume):
|
|||||||
|
|
||||||
if size < self.size:
|
if size < self.size:
|
||||||
raise qubes.storage.StoragePoolException(
|
raise qubes.storage.StoragePoolException(
|
||||||
'For your own safety, shrinking of {!s} is disabled.'
|
'For your own safety, shrinking of {!s} is disabled'
|
||||||
' If you really know what you are doing,'
|
' ({:d} < {:d}). If you really know what you are doing,'
|
||||||
' use "truncate" manually.'.format(self.vid))
|
' use "truncate" manually.'.format(self.vid, size, self.size))
|
||||||
|
|
||||||
try: # assume volume is not (cleanly) stopped ...
|
try: # assume volume is not (cleanly) stopped ...
|
||||||
_resize_file(self._path_dirty, size)
|
_resize_file(self._path_dirty, size)
|
||||||
@ -360,10 +349,13 @@ def _remove_file(path):
|
|||||||
LOGGER.info('Removed file: %s', path)
|
LOGGER.info('Removed file: %s', path)
|
||||||
|
|
||||||
def _remove_empty_dir(path):
|
def _remove_empty_dir(path):
|
||||||
with suppress(FileNotFoundError):
|
try:
|
||||||
os.rmdir(path)
|
os.rmdir(path)
|
||||||
_fsync_dir(os.path.dirname(path))
|
_fsync_dir(os.path.dirname(path))
|
||||||
LOGGER.info('Removed empty directory: %s', path)
|
LOGGER.info('Removed empty directory: %s', path)
|
||||||
|
except OSError as ex:
|
||||||
|
if ex.errno not in (errno.ENOENT, errno.ENOTEMPTY):
|
||||||
|
raise
|
||||||
|
|
||||||
def _rename_file(src, dst):
|
def _rename_file(src, dst):
|
||||||
os.rename(src, dst)
|
os.rename(src, dst)
|
||||||
@ -378,6 +370,7 @@ def _resize_file(path, size):
|
|||||||
''' Resize an existing file. '''
|
''' Resize an existing file. '''
|
||||||
with open(path, 'rb+') as file:
|
with open(path, 'rb+') as file:
|
||||||
file.truncate(size)
|
file.truncate(size)
|
||||||
|
os.fsync(file.fileno())
|
||||||
|
|
||||||
def _create_sparse_file(path, size):
|
def _create_sparse_file(path, size):
|
||||||
''' Create an empty sparse file. '''
|
''' Create an empty sparse file. '''
|
||||||
|
Loading…
Reference in New Issue
Block a user