go-debos / fakemachine

fake a machine
Apache License 2.0
34 stars 37 forks source link

bmaptool doesn't work in fakemachine #179

Open eds-collabora opened 9 months ago

eds-collabora commented 9 months ago

The failing stacktrace in bmaptool create starts with os.ftruncate which fails with "No such file or directory".

Here's a python script which reproduces the issue:

"""Save me as repro.py"""
import tempfile
import os
directory=os.getcwd()
tmp_obj = tempfile.TemporaryFile("w+", dir=directory)
os.ftruncate(tmp_obj.fileno(), 1024)
tmp_obj.close()

Put this script somewhere (mine is in my home directory). From there, to reproduce:

docker run -it --rm --device=/dev/kvm -v $PWD:/build debian:bookworm /bin/bash
apt-get update
apt-get install golang git qemu-system-x86 busybox systemd-resolved linux-image-amd64 linux-headers-amd64
git clone https://github.com/go-debos/fakemachine.git
cd fakemachine
go build cmd/fakemachine/main.go
./main -v /build:/build
python repro.py

The output I see in fakemachine:

bash-5.2# python3 repro.py
Traceback (most recent call last):
File "/build/repro.py", line 7, in <module>
os.ftruncate(tmp_obj.fileno(), 1024)
FileNotFoundError: [Errno 2] No such file or directory

In the docker container I get no output:

root@7432ceebb7a7:/fakemachine# python3 repro.py

Nor on the actual bare metal machine:

# python repro.py
obbardc commented 9 months ago

if it's any help, your example script works fine for me when run from /scratch (default working directory) but breaks when ran from /build (mounted directory):

$ fakemachine -v $(pwd):/build
Running /bin/bash using kvm backend
bash-5.2# pwd
/scratch
bash-5.2# python3 /build/test.py 
bash-5.2# cd /build/
bash-5.2# python3 test.py 
Traceback (most recent call last):
  File "/build/test.py", line 6, in <module>
    os.ftruncate(tmp_obj.fileno(), 1024)
FileNotFoundError: [Errno 2] No such file or directory
sjoerdsimons commented 8 months ago

Yeah the problem seems to be that the 9pfs doesn't seem to support truncating an unlinked file; from strace:

openat(AT_FDCWD, "/t/tmpty_rb8zv", O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW|O_CLOEXEC, 0600) = 3
unlink("/t/tmpty_rb8zv")                = 0
ioctl(3, FIOCLEX)                       = 0
newfstatat(3, "", {st_mode=S_IFREG|0600, st_size=0, ...}, AT_EMPTY_PATH) = 0
ioctl(3, TCGETS, 0x7ffd6d4abfd0)        = -1 ENOTTY (Inappropriate ioctl for device)
lseek(3, 0, SEEK_CUR)                   = 0
lseek(3, 0, SEEK_CUR)                   = 0
lseek(3, 0, SEEK_CUR)                   = 0
ftruncate(3, 1024)                      = -1 ENOENT (No such file or directory)

Which is annoying but not much fakemaching can do about it; Which is why it fails in the mounted directory (9pfs) but works on e.g. /scratch

sjoerdsimons commented 8 months ago

fwiw doing a ugly hacky test with virtiofs shows some performance improvements and does fix this issue (see an ugly first hack in e74e487ab2e7f91cfcb066817c9afc8ed85b9a5c )