9pfs: various fixes

* macOS: Fix recently (in QEMU 7.0) added 9p support for macOS hosts.
 
 * Tests: Fix inode sequencing in 'synth' driver.
 -----BEGIN PGP SIGNATURE-----
 
 iQJLBAABCgA1FiEEltjREM96+AhPiFkBNMK1h2Wkc5UFAmJuhqEXHHFlbXVfb3Nz
 QGNydWRlYnl0ZS5jb20ACgkQNMK1h2Wkc5U4fBAAofSRlDuxC0h2irHy0tRRGv+W
 rH1gDVm0jzFChUumarUOs5/hZjG5C4H9nFA0g/6di9bSoiubtA839w/dDmUYV7Xn
 S/8Jvauk/zZley1R1AKK5BEtOjJTlEYkbLqR1i9JPUrUk3Q9A+/f0FhgnW8NU2zu
 KhqbzYZnUXb3P1RyRm4cTh9UCr904OI30mdqiM9U+oJag1Zd3us/Q9sPdqDCYs8e
 vD4UXqG8c5UYpEN6C/ag2p3oJpAzpRa3CLkT5U59j/LhNgVtBPG/Pm5Q9qKHrxiN
 3p/+36NWLNXMtCKsU4Tf9TsA+tEB1G+QfObC5g8yM0e12dInW7K8KKUIOO7lE5Eq
 a8aXZZC4yjW6y9vml0tC2E8p3n7n3r4MdLIrdY5VoOk72QLLBORq547DN/c5vt8A
 Qsj2eZTvkrZNVmpQKpanwc8nsavslenFmQVVo+E6kuEOhTJpBeahsEx/ReH4D9rg
 Hmq9O+xnPXodrj4DI1uqdwxN37A6bAn/4UAnQiPosnbzn+a6rZ3TZZ7x6ZZVwVub
 MyPdWSwu0JujcD8Goina7f12tDOt2GaYrbegH4AG3B6kpMUQD6vwzcAFwZMP/0zZ
 XMQnhR/lrvpsuBymuNA8cHRjccK6uGHxCEbstSsvKJCw0GqSonvTzMKY43HtgWmz
 XjQe3jVk2+U5Aw8umTU=
 =KBDF
 -----END PGP SIGNATURE-----

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

9pfs: various fixes

* macOS: Fix recently (in QEMU 7.0) added 9p support for macOS hosts.

* Tests: Fix inode sequencing in 'synth' driver.

# -----BEGIN PGP SIGNATURE-----
#
# iQJLBAABCgA1FiEEltjREM96+AhPiFkBNMK1h2Wkc5UFAmJuhqEXHHFlbXVfb3Nz
# QGNydWRlYnl0ZS5jb20ACgkQNMK1h2Wkc5U4fBAAofSRlDuxC0h2irHy0tRRGv+W
# rH1gDVm0jzFChUumarUOs5/hZjG5C4H9nFA0g/6di9bSoiubtA839w/dDmUYV7Xn
# S/8Jvauk/zZley1R1AKK5BEtOjJTlEYkbLqR1i9JPUrUk3Q9A+/f0FhgnW8NU2zu
# KhqbzYZnUXb3P1RyRm4cTh9UCr904OI30mdqiM9U+oJag1Zd3us/Q9sPdqDCYs8e
# vD4UXqG8c5UYpEN6C/ag2p3oJpAzpRa3CLkT5U59j/LhNgVtBPG/Pm5Q9qKHrxiN
# 3p/+36NWLNXMtCKsU4Tf9TsA+tEB1G+QfObC5g8yM0e12dInW7K8KKUIOO7lE5Eq
# a8aXZZC4yjW6y9vml0tC2E8p3n7n3r4MdLIrdY5VoOk72QLLBORq547DN/c5vt8A
# Qsj2eZTvkrZNVmpQKpanwc8nsavslenFmQVVo+E6kuEOhTJpBeahsEx/ReH4D9rg
# Hmq9O+xnPXodrj4DI1uqdwxN37A6bAn/4UAnQiPosnbzn+a6rZ3TZZ7x6ZZVwVub
# MyPdWSwu0JujcD8Goina7f12tDOt2GaYrbegH4AG3B6kpMUQD6vwzcAFwZMP/0zZ
# XMQnhR/lrvpsuBymuNA8cHRjccK6uGHxCEbstSsvKJCw0GqSonvTzMKY43HtgWmz
# XjQe3jVk2+U5Aw8umTU=
# =KBDF
# -----END PGP SIGNATURE-----
# gpg: Signature made Sun 01 May 2022 06:09:53 AM 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: This key 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-20220501' of https://github.com/cschoenebeck/qemu:
  9pfs: fix qemu_mknodat() to always return -1 on error on macOS host
  9pfs: fix removing non-existent POSIX ACL xattr on macOS host
  9pfs: fix wrong errno being sent to Linux client on macOS host
  9pfs: fix wrong encoding of rdev field in Rgetattr on macOS
  9pfs: fix qemu_mknodat(S_IFSOCK) on macOS
  9pfs: fix qemu_mknodat(S_IFREG) on macOS
  9pfs: fix inode sequencing in 'synth' driver

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2022-05-01 07:48:11 -07:00
commit f5643914a9
5 changed files with 136 additions and 7 deletions

View File

@ -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
@ -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

View File

@ -92,7 +92,7 @@ int qemu_v9fs_synth_mkdir(V9fsSynthNode *parent, int mode,
}
}
/* Add the name */
node = v9fs_add_dir_node(parent, mode, name, NULL, synth_node_count++);
node = v9fs_add_dir_node(parent, mode, name, NULL, ++synth_node_count);
v9fs_add_dir_node(node, parent->attr->mode, "..",
parent->attr, parent->attr->inode);
v9fs_add_dir_node(node, node->attr->mode, ".",
@ -130,7 +130,7 @@ int qemu_v9fs_synth_add_file(V9fsSynthNode *parent, int mode,
mode = ((mode & 0777) | S_IFREG);
node = g_new0(V9fsSynthNode, 1);
node->attr = &node->actual_attr;
node->attr->inode = synth_node_count++;
node->attr->inode = ++synth_node_count;
node->attr->nlink = 1;
node->attr->read = read;
node->attr->write = write;

View File

@ -74,17 +74,67 @@ int fsetxattrat_nofollow(int dirfd, const char *filename, const char *name,
*/
#if defined CONFIG_PTHREAD_FCHDIR_NP
static int create_socket_file_at_cwd(const char *filename, mode_t mode) {
int fd, err;
struct sockaddr_un addr = {
.sun_family = AF_UNIX
};
err = snprintf(addr.sun_path, sizeof(addr.sun_path), "./%s", filename);
if (err < 0 || err >= sizeof(addr.sun_path)) {
errno = ENAMETOOLONG;
return -1;
}
fd = socket(PF_UNIX, SOCK_DGRAM, 0);
if (fd == -1) {
return fd;
}
err = bind(fd, (struct sockaddr *) &addr, sizeof(addr));
if (err == -1) {
goto out;
}
/*
* FIXME: Should rather be using descriptor-based fchmod() on the
* socket file descriptor above (preferably before bind() call),
* instead of path-based fchmodat(), to prevent concurrent transient
* state issues between creating the named FIFO file at bind() and
* delayed adjustment of permissions at fchmodat(). However currently
* macOS (12.x) does not support such operations on socket file
* descriptors yet.
*
* Filed report with Apple: FB9997731
*/
err = fchmodat(AT_FDCWD, filename, mode, AT_SYMLINK_NOFOLLOW);
out:
close_preserve_errno(fd);
return err;
}
int qemu_mknodat(int dirfd, const char *filename, mode_t mode, dev_t dev)
{
int preserved_errno, err;
if (S_ISREG(mode) || !(mode & S_IFMT)) {
int fd = openat_file(dirfd, filename, O_CREAT, mode);
if (fd == -1) {
return fd;
}
close(fd);
return 0;
}
if (!pthread_fchdir_np) {
error_report_once("pthread_fchdir_np() not available on this version of macOS");
return -ENOTSUP;
errno = ENOTSUP;
return -1;
}
if (pthread_fchdir_np(dirfd) < 0) {
return -1;
}
err = mknod(filename, mode, dev);
if (S_ISSOCK(mode)) {
err = create_socket_file_at_cwd(filename, mode);
} else {
err = mknod(filename, mode, dev);
}
preserved_errno = errno;
/* Stop using the thread-local cwd */
pthread_fchdir_np(-1);

View File

@ -19,6 +19,75 @@
#define O_PATH_9P_UTIL 0
#endif
#if !defined(CONFIG_LINUX)
/*
* Generates a Linux device number (a.k.a. dev_t) for given device major
* and minor numbers.
*
* To be more precise: it generates a device number in glibc's format
* (MMMM_Mmmm_mmmM_MMmm, 64 bits) actually, which is compatible with
* Linux's format (mmmM_MMmm, 32 bits), as described in <bits/sysmacros.h>.
*/
static inline uint64_t makedev_dotl(uint32_t dev_major, uint32_t dev_minor)
{
uint64_t dev;
// from glibc sysmacros.h:
dev = (((uint64_t) (dev_major & 0x00000fffu)) << 8);
dev |= (((uint64_t) (dev_major & 0xfffff000u)) << 32);
dev |= (((uint64_t) (dev_minor & 0x000000ffu)) << 0);
dev |= (((uint64_t) (dev_minor & 0xffffff00u)) << 12);
return dev;
}
#endif
/*
* Converts given device number from host's device number format to Linux
* device number format. As both the size of type dev_t and encoding of
* dev_t is system dependant, we have to convert them for Linux guests if
* host is not running Linux.
*/
static inline uint64_t host_dev_to_dotl_dev(dev_t dev)
{
#ifdef CONFIG_LINUX
return dev;
#else
return makedev_dotl(major(dev), minor(dev));
#endif
}
/* Translates errno from host -> Linux if needed */
static inline int errno_to_dotl(int err) {
#if defined(CONFIG_LINUX)
/* nothing to translate (Linux -> Linux) */
#elif defined(CONFIG_DARWIN)
/*
* translation mandatory for macOS hosts
*
* FIXME: Only most important errnos translated here yet, this should be
* extended to as many errnos being translated as possible in future.
*/
if (err == ENAMETOOLONG) {
err = 36; /* ==ENAMETOOLONG on Linux */
} else if (err == ENOTEMPTY) {
err = 39; /* ==ENOTEMPTY on Linux */
} else if (err == ELOOP) {
err = 40; /* ==ELOOP on Linux */
} else if (err == ENOATTR) {
err = 61; /* ==ENODATA on Linux */
} else if (err == ENOTSUP) {
err = 95; /* ==EOPNOTSUPP on Linux */
} else if (err == EOPNOTSUPP) {
err = 95; /* ==EOPNOTSUPP on Linux */
}
#else
#error Missing errno translation to Linux for this host system
#endif
return err;
}
#ifdef CONFIG_DARWIN
#define qemu_fgetxattr(...) fgetxattr(__VA_ARGS__, 0, 0)
#define qemu_lgetxattr(...) getxattr(__VA_ARGS__, 0, XATTR_NOFOLLOW)

View File

@ -1054,6 +1054,8 @@ static void coroutine_fn pdu_complete(V9fsPDU *pdu, ssize_t len)
}
len += ret;
id = P9_RERROR;
} else {
err = errno_to_dotl(err);
}
ret = pdu_marshal(pdu, len, "d", err);
@ -1327,7 +1329,7 @@ static int stat_to_v9stat_dotl(V9fsPDU *pdu, const struct stat *stbuf,
v9lstat->st_nlink = stbuf->st_nlink;
v9lstat->st_uid = stbuf->st_uid;
v9lstat->st_gid = stbuf->st_gid;
v9lstat->st_rdev = stbuf->st_rdev;
v9lstat->st_rdev = host_dev_to_dotl_dev(stbuf->st_rdev);
v9lstat->st_size = stbuf->st_size;
v9lstat->st_blksize = stat_to_iounit(pdu, stbuf);
v9lstat->st_blocks = stbuf->st_blocks;