nanovms / nanos

A kernel designed to run one and only one application in a virtualized environment
https://nanos.org
Apache License 2.0
2.59k stars 133 forks source link

Create unnamed O_TMPFILE fails in VirtFS (`error 22(EINVAL): Invalid argument`) #2051

Open aleasims opened 1 month ago

aleasims commented 1 month ago

Description

When I'm trying to create unnamed temporary file O_TMPFILE in directory mounted with VirtFS, it fails with error 22: invalid argument.

Reproduce

Consider following C code :

main.c:

#define _GNU_SOURCE

#include <fcntl.h>
#include <stdio.h>

int main()
{
    int fd = open("/tmp", O_TMPFILE | O_RDWR);
    printf("fd = %d\n", fd);
    return 0;
}

Compile code and run with ops, mounting directory through VirtFS:

gcc -o main main.c && ops run --mounts /tmp:/tmp ./main

Expected result

Program works successfully, just like on native Linux platform: unnamed tmp file is created and removed at the end of execution. Printed fd is positive:

running local instance
booting /home/alea/.ops/images/main ...
FS: filesystem_read_entire: t 0x7fc601c4, bufheap 0x00017054, buffer_handler 0x7fbdd000, status_handler 0x7fc609b4
FS: read_entire_complete: status [invalid format %v], addr 0x00000000
en1: assigned 10.0.2.15
fd = 3

Actual result

Returned fd is -1:

running local instance
booting /home/alea/.ops/images/main ...
FS: filesystem_read_entire: t 0x7fc601c4, bufheap 0x00017054, buffer_handler 0x7fbdd000, status_handler 0x7fc609b4
FS: read_entire_complete: status [invalid format %v], addr 0x00000000
en1: assigned 10.0.2.15
fd = -1

Setup

$ ops profile
Ops version: 0.1.41
Nanos version: 0.1.51
Qemu version: 6.2.0
OS: linux
Arch: amd64
Virtualized: false

I tested the same with --nightly and with local build of master branch and the same error occurs.

What I found

It looks like to me that open() syscall results in calling filesystem_creat_unnamed function, and 9pfs implementation fails immediately if asked to create unnamed file.

But I'm not sure, if 9pfs supports unnamed files at all. In that case this behavior is different from Unix-like, where creating such unnamed tmp files is a normal thing.

francescolavra commented 1 month ago

Creation of unnamed temporary files in a 9P filesystem is indeed not supported. As far as I'm aware, this is not supported on Linux either, and when looking at the 9P protocol I couldn't see a way for a 9P client to send commands to the server to create temporary files, so I doubt O_TMPFILE will ever be supported on VirtFS-mounted directories.

aleasims commented 1 month ago

@francescolavra thanks for the answer!

As far as I see from Linux man, O_TMPFILE in Linux is unnamed by default and can be linked with linkat() if needed.

In that case, probably it is possible to change the error code? From that man page (ERRORS section) I can see these three codes which are treated as "O_TMPFILE files are not supported on the filesystem":

Some libraries which work with temp files check for these error codes to decide if they need to fallback to normal named files. So it would be very helpful, if nanos open() could return one of these error codes.

francescolavra commented 4 weeks ago

To be clear, when I said that creation of unnamed temporary files is not supported on Linux, I meant that it's not supported in a 9P filesystem, i.e. a filesystem mounted with the -t 9p option. As for the error code, EINVAL is indeed not appropriate, I will change it to EOPNOTSUPP.

francescolavra commented 3 weeks ago

As part of a larger refactoring, #2054 changes the error code returned by open(O_TMPFILE) from EINVAL to EOPNOTSUPP.