storage/reflink: _update_loopdev_sizes() without losetup

Factor out a function, and use the LOOP_SET_CAPACITY ioctl instead of
going through losetup.
This commit is contained in:
Rusty Bird 2018-09-11 23:50:10 +00:00
parent 385ba91772
commit fb06a8089a
No known key found for this signature in database
GPG Key ID: 469D78F47AAF2ADF

View File

@ -28,7 +28,6 @@ import fcntl
import glob
import logging
import os
import re
import subprocess
import tempfile
from contextlib import contextmanager, suppress
@ -36,7 +35,8 @@ from contextlib import contextmanager, suppress
import qubes.storage
BLKSIZE = 512
FICLONE = 1074041865 # see ioctl_ficlone manpage
FICLONE = 1074041865 # defined in <linux/fs.h>
LOOP_SET_CAPACITY = 0x4C07 # defined in <linux/loop.h>
LOGGER = logging.getLogger('qubes.storage.reflink')
@ -246,12 +246,7 @@ class ReflinkVolume(qubes.storage.Volume):
self.size = size
return self
# resize any corresponding loop devices
out = _cmd('losetup', '--associated', self._path_dirty)
for match in re.finditer(br'^(/dev/loop[0-9]+): ', out, re.MULTILINE):
loop_dev = match.group(1).decode('ascii')
_cmd('losetup', '--set-capacity', loop_dev)
_update_loopdev_sizes(self._path_dirty)
return self
def export(self):
@ -395,6 +390,19 @@ def _create_sparse_file(path, size):
tmp.truncate(size)
LOGGER.info('Created sparse file: %s', tmp.name)
def _update_loopdev_sizes(img):
''' Resolve img; update the size of loop devices backed by it. '''
needle = os.fsencode(os.path.realpath(img)) + b'\n'
for sys_path in glob.iglob('/sys/block/loop[0-9]*/loop/backing_file'):
try:
with open(sys_path, 'rb') as sys_io:
if sys_io.read() != needle:
continue
except FileNotFoundError:
continue
with open('/dev/' + sys_path.split('/')[3]) as dev_io:
fcntl.ioctl(dev_io.fileno(), LOOP_SET_CAPACITY)
def _copy_file(src, dst):
''' Copy src to dst as a reflink if possible, sparse if not. '''
if not os.path.exists(src):