diff --git a/.github/wordlist.txt b/.github/wordlist.txt index 2f620740..dab0863d 100644 --- a/.github/wordlist.txt +++ b/.github/wordlist.txt @@ -62,6 +62,7 @@ JQC keyrings kvm LEDs +loopback LTS maxdepth microSD diff --git a/docs/config.rst b/docs/config.rst index 08671e43..b435ed77 100644 --- a/docs/config.rst +++ b/docs/config.rst @@ -396,13 +396,15 @@ configuration to expose either a file or a physical device or partition to the DUT as a Mass Storage device. The following settings are supported: * ``device``: string [optional] - Block device for the shared storage as seen on the host. This is the - same as ``file`` but a warning will be issued if the specified file - is not a block device. When both ``device`` and ``file`` are set, - ``file`` will be used. + Block device for the shared storage as seen on the host. A systemd + dependency is added to ensure the service is started only after the + specified block device was found. A warning is issued if the input + is not a block device. * ``file``: string [optional] - File or block device for the shared storage as seen on the host. + File for the shared storage: a loopback device will be created to make + sure that writes to the shared storage do not cause this file to + expand and leave the host without free space. Timeout settings ---------------- diff --git a/mtda/storage/usbf.py b/mtda/storage/usbf.py index 7b283db4..a0611936 100644 --- a/mtda/storage/usbf.py +++ b/mtda/storage/usbf.py @@ -12,6 +12,7 @@ # System imports import os import stat +import subprocess # Local imports import mtda.constants as CONSTS @@ -26,9 +27,23 @@ def __init__(self, mtda): super().__init__(mtda) self.device = None self.file = None + self.loop = None self.mode = CONSTS.STORAGE.ON_HOST Composite.mtda = mtda + def cleanup(self): + self.mtda.debug(3, "storage.usbf.cleanup()") + + result = None + if self.loop is not None: + self.mtda.debug(2, "storage.usbf.cleanup(): " + "removing {}".format(self.loop)) + cmd = ['/usr/sbin/losetup', '-d', self.loop] + self.loop = subprocess.check_call(cmd) + + self.mtda.debug(3, "storage.usbf.cleanup(): {}".format(result)) + return result + """ Configure this storage controller from the provided configuration""" def configure(self, conf): self.mtda.debug(3, "storage.usbf.configure()") @@ -44,8 +59,14 @@ def configure(self, conf): "both 'file' ({}) and 'device' ({}) are set, " "using 'file'".format(self.file, self.device)) self.device = None - - if self.file is None and self.device is not None: + elif self.device is None: + import atexit + cmd = ['/usr/sbin/losetup', '-f', '--show', self.file] + self.loop = subprocess.check_output(cmd).decode("utf-8").strip() + atexit.register(self.cleanup) + self.mtda.debug(2, "storage.usbf.configure(): created loopback " + "device {} for {}".format(self.loop, self.file)) + else: self.file = self.device if self.file is not None: