From bf41326ac68cbb191e92170d5dbbcdad57503992 Mon Sep 17 00:00:00 2001 From: Christian Kellner Date: Fri, 13 Dec 2019 13:54:37 +0100 Subject: [PATCH] remoteloop: don't use O_DIRECT on s390x Using O_DIRECT to open the image partition and then using that fd for the backing of the loopback device will break the mounting of the formatted partition, i.e mount will fail with: mount: /tmp/looptest-6qrtkp5e/mountpoint-root: wrong fs type, bad option, bad superblock on /dev/loop0, missing codepage or helper program, or other error. Reproducible with the follow small-ish python script, executed via 'env PYTHONPATH=$(pwd) python3 looptest.py': ---- 8< ---- 8< ---- [ looptest.py ] ---- 8< ---- 8< ---- import contextlib import json import os import subprocess import stat import tempfile from osbuild import loop @contextlib.contextmanager def mount(source, dest): subprocess.run(["mount", source, dest], check=True) try: yield dest finally: subprocess.run(["umount", "-R", dest], check=True) @contextlib.contextmanager def os_open(path, flags): fd = os.open(path, flags) try: yield fd finally: os.close(fd) def main(): size = 512 * 1024 * 1024 ptuuid = "0x14fc63d2" with contextlib.ExitStack() as cm: tmpdir = cm.enter_context(tempfile.TemporaryDirectory(prefix="looptest-")) print(f"Temporary directory at {tmpdir}") devdir = os.path.join(tmpdir, "dev") os.makedirs(devdir, exist_ok=True) dir_fd = cm.enter_context(os_open(devdir, os.O_DIRECTORY)) image = os.path.join(tmpdir, "image") subprocess.run(["truncate", "--size", str(size), image], check=True) table = f"label: mbr\nlabel-id: {ptuuid}\nbootable, type=83" subprocess.run(["sfdisk", image], input=table, encoding='utf-8', check=True) # read it back r = subprocess.run(["sfdisk", "--json", image], stdout=subprocess.PIPE, encoding='utf-8', check=True) table = json.loads(r.stdout)["partitiontable"] partitions = table["partitions"] start = partitions[0]["start"] * 512 size = partitions[0]["size"] * 512 # fails here with os.O_DIRECT image_fd = cm.enter_context(os_open(image, os.O_RDWR | os.O_DIRECT)) control = loop.LoopControl() minor = control.get_unbound() lo = loop.Loop(minor) lo.set_fd(image_fd) lo.set_status(offset=start, sizelimit=size, autoclear=True) lo.mknod(dir_fd) loopdev = f"/dev/loop{minor}" # loopdev = os.path.join(devdir, lo.devname) # os.chmod(loopdev, os.stat(loopdev).st_mode | stat.S_IRGRP) subprocess.run(["ls", "-la", f"{devdir}"], check=True) subprocess.run(["mkfs.ext4", loopdev], input="y", encoding='utf-8', check=True) subprocess.run(["blkid", loopdev], check=True) mountpoint = os.path.join(tmpdir, "mountpoint-root") os.makedirs(mountpoint, exist_ok=True) cm.enter_context(mount(loopdev, mountpoint)) subprocess.run(["ls", "-la", tmpdir], check=True) subprocess.run(["ls", "-la", mountpoint], check=True) subprocess.run(["mount"], check=True) if __name__ == '__main__': main() --- osbuild/remoteloop.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/osbuild/remoteloop.py b/osbuild/remoteloop.py index c37a1d1b..424bc060 100644 --- a/osbuild/remoteloop.py +++ b/osbuild/remoteloop.py @@ -4,6 +4,7 @@ import contextlib import errno import json import os +import platform import socket import threading from . import loop @@ -117,7 +118,13 @@ class LoopClient: def device(self, filename, offset=None, sizelimit=None): req = {} fds = array.array("i") - fd = os.open(filename, os.O_RDWR | os.O_DIRECT) + oflags = os.O_RDWR + + if platform.machine() != "s390x": + # O_DIRECT will break s390x currently + oflags |= os.O_DIRECT + + fd = os.open(filename, oflags) dir_fd = os.open("/dev", os.O_DIRECTORY) fds.append(fd)