storage/reflink: add _path_import (don't reuse _path_dirty)
Import volume data to a new _path_import (instead of _path_dirty) before committing to _path_clean. In case the computer crashes while an import operation is running, the partially written file should not be attached to Xen on the next volume startup. Use <name>-import.img as the filename like 'file' does, to be compatible with qubes.tests.api_admin/TC_00_VMs/test_510_vm_volume_import.
This commit is contained in:
parent
d301aa2e50
commit
60bf68a748
@ -121,6 +121,7 @@ class ReflinkVolume(qubes.storage.Volume):
|
||||
self._path_vid = os.path.join(self.pool.dir_path, self.vid)
|
||||
self._path_clean = self._path_vid + '.img'
|
||||
self._path_dirty = self._path_vid + '-dirty.img'
|
||||
self._path_import = self._path_vid + '-import.img'
|
||||
self.path = self._path_dirty
|
||||
|
||||
def create(self):
|
||||
@ -156,6 +157,7 @@ class ReflinkVolume(qubes.storage.Volume):
|
||||
def _cleanup(self):
|
||||
for tmp in glob.iglob(glob.escape(self._path_vid) + '*.img*~*'):
|
||||
_remove_file(tmp)
|
||||
_remove_file(self._path_import)
|
||||
|
||||
def is_outdated(self):
|
||||
if self.snap_on_start:
|
||||
@ -183,16 +185,16 @@ class ReflinkVolume(qubes.storage.Volume):
|
||||
|
||||
def stop(self):
|
||||
if self.save_on_stop:
|
||||
self._commit()
|
||||
self._commit(self._path_dirty)
|
||||
else:
|
||||
_remove_file(self._path_dirty)
|
||||
_remove_file(self._path_clean)
|
||||
return self
|
||||
|
||||
def _commit(self):
|
||||
def _commit(self, path_from):
|
||||
self._add_revision()
|
||||
self._prune_revisions()
|
||||
_rename_file(self._path_dirty, self._path_clean)
|
||||
_rename_file(path_from, self._path_clean)
|
||||
|
||||
def _add_revision(self):
|
||||
if self.revisions_to_keep == 0:
|
||||
@ -263,20 +265,20 @@ class ReflinkVolume(qubes.storage.Volume):
|
||||
|
||||
def import_data(self):
|
||||
self._require_save_on_stop('import_data')
|
||||
_create_sparse_file(self._path_dirty, self.size)
|
||||
return self._path_dirty
|
||||
_create_sparse_file(self._path_import, self.size)
|
||||
return self._path_import
|
||||
|
||||
def import_data_end(self, success):
|
||||
if success:
|
||||
self._commit()
|
||||
self._commit(self._path_import)
|
||||
else:
|
||||
_remove_file(self._path_dirty)
|
||||
_remove_file(self._path_import)
|
||||
return self
|
||||
|
||||
def import_volume(self, src_volume):
|
||||
self._require_save_on_stop('import_volume')
|
||||
try:
|
||||
_copy_file(src_volume.export(), self._path_dirty)
|
||||
_copy_file(src_volume.export(), self._path_import)
|
||||
except:
|
||||
self.import_data_end(False)
|
||||
raise
|
||||
|
Loading…
Reference in New Issue
Block a user