9pfs changes:

* Add FreeBSD host support.
 
 * Fix glib header inclusion.
 -----BEGIN PGP SIGNATURE-----
 
 iQJLBAABCgA1FiEEltjREM96+AhPiFkBNMK1h2Wkc5UFAmjMYKMXHHFlbXVfb3Nz
 QGNydWRlYnl0ZS5jb20ACgkQNMK1h2Wkc5VUGBAAiRVM6vTErPwccp+w8UrpAVo5
 oXdN2TIpQoILGg2vSuHc4mGUXjMmqnihCbNP9p3ZUVSYQwSwpXa2i47GSe100Mzi
 kiv2/SROopohE6ZiDok65GCj2hXShF0tZGauTBoE0WTZP9LG+rvftMeupbgrEKll
 To5hOdsQbPw2HtATpTjRufvVTtaeu8oGeh+BPmtiyu7Aiea4xht9YCAMa8AVG44P
 97ZmnqYAq/5bolE6fTuVEWj484cPjMPC/sMBddhNV57HwzYdqGdOinR3GqRHspvN
 B0oCq07HXeAV55APGQtPWOWq1SonGqIhHj0Hdnugl3DWUWiQs0CVSMPlE7Aag7at
 /8JbGS2j7RuM5N9Zdf8Wlq78jgvRmbpYZunD0RLd8O+jESaHAoNpjrNHm4v92WLa
 bUePytsxCK9ozStPqRVB9zGOYyx36LKG/8E5J4t00GX2F0FRB9OxgSPFWCWFnqM5
 R4IvR2huW8/DvplgvVpPc0SM+lMV7GZhAC92z7KkQYBE85s09EdAobIIHguK3B0l
 5hy9w6tZ6nnFloaL0fWccE3XU+X56KrDkX0G/AEdppsxYBYYhs1XNhR5AYuQCEd5
 gdKtLrEOr1F2snb8aLfS8MDwTUCkU1lfbipyzDaX3sr4Gg+7L/vV3OxQoGmwMjOe
 xnI3cMzk0j7prHT1oSc=
 =3YK2
 -----END PGP SIGNATURE-----

Merge tag 'pull-9p-20250918' of https://github.com/cschoenebeck/qemu into staging

9pfs changes:

* Add FreeBSD host support.

* Fix glib header inclusion.

# -----BEGIN PGP SIGNATURE-----
#
# iQJLBAABCgA1FiEEltjREM96+AhPiFkBNMK1h2Wkc5UFAmjMYKMXHHFlbXVfb3Nz
# QGNydWRlYnl0ZS5jb20ACgkQNMK1h2Wkc5VUGBAAiRVM6vTErPwccp+w8UrpAVo5
# oXdN2TIpQoILGg2vSuHc4mGUXjMmqnihCbNP9p3ZUVSYQwSwpXa2i47GSe100Mzi
# kiv2/SROopohE6ZiDok65GCj2hXShF0tZGauTBoE0WTZP9LG+rvftMeupbgrEKll
# To5hOdsQbPw2HtATpTjRufvVTtaeu8oGeh+BPmtiyu7Aiea4xht9YCAMa8AVG44P
# 97ZmnqYAq/5bolE6fTuVEWj484cPjMPC/sMBddhNV57HwzYdqGdOinR3GqRHspvN
# B0oCq07HXeAV55APGQtPWOWq1SonGqIhHj0Hdnugl3DWUWiQs0CVSMPlE7Aag7at
# /8JbGS2j7RuM5N9Zdf8Wlq78jgvRmbpYZunD0RLd8O+jESaHAoNpjrNHm4v92WLa
# bUePytsxCK9ozStPqRVB9zGOYyx36LKG/8E5J4t00GX2F0FRB9OxgSPFWCWFnqM5
# R4IvR2huW8/DvplgvVpPc0SM+lMV7GZhAC92z7KkQYBE85s09EdAobIIHguK3B0l
# 5hy9w6tZ6nnFloaL0fWccE3XU+X56KrDkX0G/AEdppsxYBYYhs1XNhR5AYuQCEd5
# gdKtLrEOr1F2snb8aLfS8MDwTUCkU1lfbipyzDaX3sr4Gg+7L/vV3OxQoGmwMjOe
# xnI3cMzk0j7prHT1oSc=
# =3YK2
# -----END PGP SIGNATURE-----
# gpg: Signature made Thu 18 Sep 2025 12:42:27 PM PDT
# gpg:                using RSA key 96D8D110CF7AF8084F88590134C2B58765A47395
# gpg:                issuer "qemu_oss@crudebyte.com"
# gpg: Good signature from "Christian Schoenebeck <qemu_oss@crudebyte.com>" [unknown]
# gpg: WARNING: The key's User ID is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: ECAB 1A45 4014 1413 BA38  4926 30DB 47C3 A012 D5F4
#      Subkey fingerprint: 96D8 D110 CF7A F808 4F88  5901 34C2 B587 65A4 7395

* tag 'pull-9p-20250918' of https://github.com/cschoenebeck/qemu:
  9pfs: Stop including gstrfuncs.h
  9pfs: Add FreeBSD support

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2025-09-19 12:21:35 -07:00
commit ab8008b231
10 changed files with 179 additions and 16 deletions

View file

@ -21,9 +21,11 @@
#ifdef CONFIG_LINUX
# include <sys/vfs.h>
#endif
#ifdef CONFIG_DARWIN
#elif defined(CONFIG_DARWIN) || defined(CONFIG_FREEBSD)
# include <sys/param.h>
# ifdef CONFIG_FREEBSD
# undef MACHINE /* work around some unfortunate namespace pollution */
# endif
# include <sys/mount.h>
#endif

View file

@ -5,6 +5,6 @@ fsdev_ss.add(when: ['CONFIG_FSDEV_9P'], if_true: files(
'9p-marshal.c',
'qemu-fsdev.c',
), if_false: files('qemu-fsdev-dummy.c'))
if host_os in ['linux', 'darwin']
if host_os in ['linux', 'darwin', 'freebsd']
system_ss.add_all(fsdev_ss)
endif

View file

@ -451,7 +451,7 @@ static int synth_statfs(FsContext *s, V9fsPath *fs_path,
stbuf->f_bsize = 512;
stbuf->f_blocks = 0;
stbuf->f_files = synth_node_count;
#ifndef CONFIG_DARWIN
#if !defined(CONFIG_DARWIN) && !defined(CONFIG_FREEBSD)
stbuf->f_namelen = NAME_MAX;
#endif
return 0;

132
hw/9pfs/9p-util-freebsd.c Normal file
View file

@ -0,0 +1,132 @@
/*
* 9p utilities (FreeBSD Implementation)
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*/
/*
* Not so fast! You might want to read the 9p developer docs first:
* https://wiki.qemu.org/Documentation/9p
*/
#include "qemu/osdep.h"
#include "qemu/xattr.h"
#include "9p-util.h"
static int mangle_xattr_name(const char **namep)
{
const char *name = *namep;
/*
* ZFS forbids attributes in starting with "user." or "system.".
*/
if (strncmp(name, "system.", 7) == 0) {
*namep = name + 7;
return EXTATTR_NAMESPACE_SYSTEM;
}
if (strncmp(name, "user.", 5) == 0) {
*namep = name + 5;
}
return EXTATTR_NAMESPACE_USER;
}
ssize_t fgetxattr(int fd, const char *name, void *value, size_t size)
{
int namespace;
namespace = mangle_xattr_name(&name);
return extattr_get_fd(fd, namespace, name, value, size);
}
ssize_t fgetxattrat_nofollow(int dirfd, const char *filename, const char *name,
void *value, size_t size)
{
ssize_t ret;
int fd, namespace;
fd = openat_file(dirfd, filename,
O_RDONLY | O_PATH_9P_UTIL | O_NOFOLLOW, 0);
if (fd == -1) {
return -1;
}
namespace = mangle_xattr_name(&name);
ret = extattr_get_fd(fd, namespace, name, value, size);
close_preserve_errno(fd);
return ret;
}
ssize_t flistxattrat_nofollow(int dirfd, const char *filename,
char *list, size_t size)
{
ssize_t ret;
int fd;
fd = openat_file(dirfd, filename,
O_RDONLY | O_PATH_9P_UTIL | O_NOFOLLOW, 0);
if (fd == -1) {
return -1;
}
ret = extattr_list_fd(fd, EXTATTR_NAMESPACE_USER, list, size);
close_preserve_errno(fd);
return ret;
}
ssize_t fremovexattrat_nofollow(int dirfd, const char *filename,
const char *name)
{
int fd, namespace, ret;
fd = openat_file(dirfd, filename,
O_RDONLY | O_PATH_9P_UTIL | O_NOFOLLOW, 0);
if (fd == -1) {
return -1;
}
namespace = mangle_xattr_name(&name);
ret = extattr_delete_fd(fd, namespace, name);
close_preserve_errno(fd);
return ret;
}
int fsetxattrat_nofollow(int dirfd, const char *filename, const char *name,
void *value, size_t size, int flags)
{
ssize_t ret;
int fd, namespace;
namespace = mangle_xattr_name(&name);
if (flags == (XATTR_CREATE | XATTR_REPLACE)) {
errno = EINVAL;
return -1;
}
fd = openat_file(dirfd, filename,
O_RDONLY | O_PATH_9P_UTIL | O_NOFOLLOW, 0);
if (fd == -1) {
return -1;
}
if (flags & (XATTR_CREATE | XATTR_REPLACE)) {
ret = extattr_get_fd(fd, namespace, name, NULL, 0);
if (ret == -1 && errno != ENOATTR) {
close_preserve_errno(fd);
return -1;
}
if (ret >= 0 && (flags & XATTR_CREATE)) {
errno = EEXIST;
close_preserve_errno(fd);
return -1;
}
if (ret == -1 && (flags & XATTR_REPLACE)) {
errno = ENOATTR;
close_preserve_errno(fd);
return -1;
}
}
ret = extattr_set_fd(fd, namespace, name, value, size);
close_preserve_errno(fd);
return ret;
}
int qemu_mknodat(int dirfd, const char *filename, mode_t mode, dev_t dev)
{
return mknodat(dirfd, filename, mode, dev);
}

View file

@ -2,7 +2,6 @@
#include "qemu/osdep.h"
#include "9p-util.h"
#include <glib/gstrfuncs.h>
char *qemu_open_flags_tostr(int flags)
{

View file

@ -21,6 +21,15 @@
#define O_PATH_9P_UTIL 0
#endif
#ifdef CONFIG_FREEBSD
/*
* FreeBSD does not have these flags, so we can only emulate their intended
* behaviour (racily).
*/
#define XATTR_CREATE 0x1
#define XATTR_REPLACE 0x2
#endif
#if !defined(CONFIG_LINUX)
/*
@ -64,9 +73,9 @@ static inline uint64_t host_dev_to_dotl_dev(dev_t dev)
static inline int errno_to_dotl(int err) {
#if defined(CONFIG_LINUX)
/* nothing to translate (Linux -> Linux) */
#elif defined(CONFIG_DARWIN)
#elif defined(CONFIG_DARWIN) || defined(CONFIG_FREEBSD)
/*
* translation mandatory for macOS hosts
* translation mandatory for non-Linux hosts
*
* FIXME: Only most important errnos translated here yet, this should be
* extended to as many errnos being translated as possible in future.
@ -155,13 +164,13 @@ static inline int openat_file(int dirfd, const char *name, int flags,
{
int fd, serrno, ret;
#ifndef CONFIG_DARWIN
#if !defined(CONFIG_DARWIN) && !defined(CONFIG_FREEBSD)
again:
#endif
fd = qemu_openat(dirfd, name, flags | O_NOFOLLOW | O_NOCTTY | O_NONBLOCK,
mode);
if (fd == -1) {
#ifndef CONFIG_DARWIN
#if !defined(CONFIG_DARWIN) && !defined(CONFIG_FREEBSD)
if (errno == EPERM && (flags & O_NOATIME)) {
/*
* The client passed O_NOATIME but we lack permissions to honor it.
@ -202,6 +211,9 @@ again:
return fd;
}
#ifdef CONFIG_FREEBSD
ssize_t fgetxattr(int dirfd, const char *name, void *value, size_t size);
#endif
ssize_t fgetxattrat_nofollow(int dirfd, const char *path, const char *name,
void *value, size_t size);
int fsetxattrat_nofollow(int dirfd, const char *path, const char *name,

View file

@ -136,8 +136,10 @@ static int dotl_to_open_flags(int flags)
{ P9_DOTL_NONBLOCK, O_NONBLOCK } ,
{ P9_DOTL_DSYNC, O_DSYNC },
{ P9_DOTL_FASYNC, FASYNC },
#ifndef CONFIG_DARWIN
#if !defined(CONFIG_DARWIN) && !defined(CONFIG_FREEBSD)
{ P9_DOTL_NOATIME, O_NOATIME },
#endif
#ifndef CONFIG_DARWIN
/*
* On Darwin, we could map to F_NOCACHE, which is
* similar, but doesn't quite have the same
@ -3658,7 +3660,7 @@ static int v9fs_fill_statfs(V9fsState *s, V9fsPDU *pdu, struct statfs *stbuf)
f_bavail = stbuf->f_bavail / bsize_factor;
f_files = stbuf->f_files;
f_ffree = stbuf->f_ffree;
#ifdef CONFIG_DARWIN
#if defined(CONFIG_DARWIN) || defined(CONFIG_FREEBSD)
fsid_val = (unsigned int)stbuf->f_fsid.val[0] |
(unsigned long long)stbuf->f_fsid.val[1] << 32;
f_namelen = NAME_MAX;
@ -4050,6 +4052,16 @@ out_nofid:
* Linux guests.
*/
#define P9_XATTR_SIZE_MAX 65536
#elif defined(CONFIG_FREEBSD)
/*
* FreeBSD similarly doesn't define a maximum xattr size, the limit is
* filesystem dependent. On UFS filesystems it's 2 times the filesystem block
* size, typically 32KB. On ZFS it depends on the value of the xattr property;
* with the default value there is no limit, and with xattr=sa it is 64KB.
*
* So, a limit of 64k seems reasonable here too.
*/
#define P9_XATTR_SIZE_MAX 65536
#else
#error Missing definition for P9_XATTR_SIZE_MAX for this host system
#endif

View file

@ -15,6 +15,8 @@ fs_ss.add(files(
))
if host_os == 'darwin'
fs_ss.add(files('9p-util-darwin.c'))
elif host_os == 'freebsd'
fs_ss.add(files('9p-util-freebsd.c'))
elif host_os == 'linux'
fs_ss.add(files('9p-util-linux.c'))
endif

View file

@ -26,7 +26,11 @@
# define ENOATTR ENODATA
# endif
# ifndef CONFIG_WIN32
# include <sys/xattr.h>
# ifdef CONFIG_FREEBSD
# include <sys/extattr.h>
# else
# include <sys/xattr.h>
# endif
# endif
#endif

View file

@ -2384,11 +2384,11 @@ dbus_display = get_option('dbus_display') \
.allowed()
have_virtfs = get_option('virtfs') \
.require(host_os == 'linux' or host_os == 'darwin',
error_message: 'virtio-9p (virtfs) requires Linux or macOS') \
.require(host_os == 'linux' or cc.has_function('pthread_fchdir_np'),
.require(host_os == 'linux' or host_os == 'darwin' or host_os == 'freebsd',
error_message: 'virtio-9p (virtfs) requires Linux or macOS or FreeBSD') \
.require(host_os != 'darwin' or cc.has_function('pthread_fchdir_np'),
error_message: 'virtio-9p (virtfs) on macOS requires the presence of pthread_fchdir_np') \
.require(host_os == 'darwin' or libattr.found(),
.require(host_os != 'linux' or libattr.found(),
error_message: 'virtio-9p (virtfs) on Linux requires libattr-devel') \
.disable_auto_if(not have_tools and not have_system) \
.allowed()