Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions fsdev/file-op-9p.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,11 @@

#ifdef CONFIG_LINUX
# include <sys/vfs.h>
#endif
#ifdef CONFIG_DARWIN
#elif defined(CONFIG_DARWIN) || defined(CONFIG_BSD)
# include <sys/param.h>
# ifdef CONFIG_BSD
# undef MACHINE /* work around some unfortunate namespace pollution */
# endif
# include <sys/mount.h>
#endif

Expand Down
1 change: 1 addition & 0 deletions fsdev/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ fsdev_ss.add(when: ['CONFIG_FSDEV_9P'], if_true: files(
), if_false: files('qemu-fsdev-dummy.c'))
softmmu_ss.add_all(when: 'CONFIG_LINUX', if_true: fsdev_ss)
softmmu_ss.add_all(when: 'CONFIG_DARWIN', if_true: fsdev_ss)
softmmu_ss.add_all(when: 'CONFIG_BSD', if_true: fsdev_ss)

if have_virtfs_proxy_helper
executable('virtfs-proxy-helper',
Expand Down
11 changes: 0 additions & 11 deletions fsdev/qemu-fsdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,17 +89,6 @@ static FsDriverTable FsDrivers[] = {
NULL
},
},
{
.name = "proxy",
.ops = &proxy_ops,
.opts = (const char * []) {
COMMON_FS_DRIVER_OPTIONS,
"socket",
"sock_fd",
"writeout",
NULL
},
},
};

static int validate_opt(void *opaque, const char *name, const char *value,
Expand Down
12 changes: 10 additions & 2 deletions hw/9pfs/9p-posix-acl.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,11 @@ static int mp_pacl_removexattr(FsContext *ctx,
int ret;

ret = local_removexattr_nofollow(ctx, path, MAP_ACL_ACCESS);
if (ret == -1 && errno == ENODATA) {
/*
* macOS returns ENOATTR (!=ENODATA on macOS), whereas Linux returns
* ENODATA (==ENOATTR on Linux), so checking for ENOATTR is fine
*/
if (ret == -1 && errno == ENOATTR) {
/*
* We don't get ENODATA error when trying to remove a
* posix acl that is not present. So don't throw the error
Expand Down Expand Up @@ -115,7 +119,11 @@ static int mp_dacl_removexattr(FsContext *ctx,
int ret;

ret = local_removexattr_nofollow(ctx, path, MAP_ACL_DEFAULT);
if (ret == -1 && errno == ENODATA) {
/*
* macOS returns ENOATTR (!=ENODATA on macOS), whereas Linux returns
* ENODATA (==ENOATTR on Linux), so checking for ENOATTR is fine
*/
if (ret == -1 && errno == ENOATTR) {
/*
* We don't get ENODATA error when trying to remove a
* posix acl that is not present. So don't throw the error
Expand Down
2 changes: 1 addition & 1 deletion hw/9pfs/9p-synth.c
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,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_BSD)
stbuf->f_namelen = NAME_MAX;
#endif
return 0;
Expand Down
132 changes: 132 additions & 0 deletions hw/9pfs/9p-util-freebsd.c
Original file line number Diff line number Diff line change
@@ -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);
}
16 changes: 14 additions & 2 deletions hw/9pfs/9p-util.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,15 @@
#define O_PATH_9P_UTIL 0
#endif

#ifdef CONFIG_BSD
/*
* FreeBSD does not have these flags, so we can only emulate their intended
* behaviour (racily).
*/
#define XATTR_CREATE 0x1
#define XATTR_REPLACE 0x2
#endif

#ifdef CONFIG_DARWIN
#define qemu_fgetxattr(...) fgetxattr(__VA_ARGS__, 0, 0)
#define qemu_lgetxattr(...) getxattr(__VA_ARGS__, 0, XATTR_NOFOLLOW)
Expand Down Expand Up @@ -54,13 +63,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_BSD)
again:
#endif
fd = openat(dirfd, name, flags | O_NOFOLLOW | O_NOCTTY | O_NONBLOCK,
mode);
if (fd == -1) {
#ifndef CONFIG_DARWIN
#if !defined(CONFIG_DARWIN) && !defined(CONFIG_BSD)
if (errno == EPERM && (flags & O_NOATIME)) {
/*
* The client passed O_NOATIME but we lack permissions to honor it.
Expand Down Expand Up @@ -90,6 +99,9 @@ static inline int openat_file(int dirfd, const char *name, int flags,
return fd;
}

#ifdef CONFIG_BSD
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,
Expand Down
16 changes: 14 additions & 2 deletions hw/9pfs/9p.c
Original file line number Diff line number Diff line change
Expand Up @@ -138,8 +138,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_BSD)
{ 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
Expand Down Expand Up @@ -3547,7 +3549,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_BSD)
fsid_val = (unsigned int)stbuf->f_fsid.val[0] |
(unsigned long long)stbuf->f_fsid.val[1] << 32;
f_namelen = NAME_MAX;
Expand Down Expand Up @@ -3939,6 +3941,16 @@ static void coroutine_fn v9fs_xattrwalk(void *opaque)
* Linux guests.
*/
#define P9_XATTR_SIZE_MAX 65536
#elif defined(CONFIG_BSD)
/*
* 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
Expand Down
2 changes: 1 addition & 1 deletion hw/9pfs/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ fs_ss = ss.source_set()
fs_ss.add(files(
'9p-local.c',
'9p-posix-acl.c',
'9p-proxy.c',
'9p-synth.c',
'9p-xattr-user.c',
'9p-xattr.c',
Expand All @@ -15,6 +14,7 @@ fs_ss.add(files(
))
fs_ss.add(when: 'CONFIG_LINUX', if_true: files('9p-util-linux.c'))
fs_ss.add(when: 'CONFIG_DARWIN', if_true: files('9p-util-darwin.c'))
fs_ss.add(when: 'CONFIG_BSD', if_true: files('9p-util-freebsd.c'))
fs_ss.add(when: 'CONFIG_XEN', if_true: files('xen-9p-backend.c'))
softmmu_ss.add_all(when: 'CONFIG_FSDEV_9P', if_true: fs_ss)

Expand Down
6 changes: 5 additions & 1 deletion include/qemu/xattr.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,11 @@
# if !defined(ENOATTR)
# define ENOATTR ENODATA
# endif
# include <sys/xattr.h>
# ifdef CONFIG_BSD
# include <sys/extattr.h>
# else
# include <sys/xattr.h>
# endif
#endif

#endif
10 changes: 5 additions & 5 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -1465,16 +1465,16 @@ dbus_display = get_option('dbus_display') \
.allowed()

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

have_virtfs_proxy_helper = targetos != 'darwin' and have_virtfs and have_tools
have_virtfs_proxy_helper = targetos != 'darwin' and targetos != 'freebsd' and have_virtfs and have_tools

foreach k : get_option('trace_backends')
config_host_data.set('CONFIG_TRACE_' + k.to_upper(), true)
Expand Down
Loading