aboutsummaryrefslogtreecommitdiff
path: root/hw/9pfs/9p.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/9pfs/9p.c')
-rw-r--r--hw/9pfs/9p.c104
1 files changed, 71 insertions, 33 deletions
diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
index 15b3f4d385..a6d6b3f835 100644
--- a/hw/9pfs/9p.c
+++ b/hw/9pfs/9p.c
@@ -27,12 +27,17 @@
#include "virtio-9p.h"
#include "fsdev/qemu-fsdev.h"
#include "9p-xattr.h"
+#include "9p-util.h"
#include "coth.h"
#include "trace.h"
#include "migration/blocker.h"
#include "qemu/xxhash.h"
#include <math.h>
+#ifdef CONFIG_LINUX
#include <linux/limits.h>
+#else
+#include <limits.h>
+#endif
int open_fd_hw;
int total_open_fd;
@@ -133,11 +138,20 @@ 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
+ { P9_DOTL_NOATIME, O_NOATIME },
+ /*
+ * On Darwin, we could map to F_NOCACHE, which is
+ * similar, but doesn't quite have the same
+ * semantics. However, we don't support O_DIRECT
+ * even on linux at the moment, so we just ignore
+ * it here.
+ */
{ P9_DOTL_DIRECT, O_DIRECT },
+#endif
{ P9_DOTL_LARGEFILE, O_LARGEFILE },
{ P9_DOTL_DIRECTORY, O_DIRECTORY },
{ P9_DOTL_NOFOLLOW, O_NOFOLLOW },
- { P9_DOTL_NOATIME, O_NOATIME },
{ P9_DOTL_SYNC, O_SYNC },
};
@@ -166,10 +180,12 @@ static int get_dotl_openflags(V9fsState *s, int oflags)
*/
flags = dotl_to_open_flags(oflags);
flags &= ~(O_NOCTTY | O_ASYNC | O_CREAT);
+#ifndef CONFIG_DARWIN
/*
* Ignore direct disk access hint until the server supports it.
*/
flags &= ~O_DIRECT;
+#endif
return flags;
}
@@ -612,8 +628,8 @@ static inline uint64_t mirror64bit(uint64_t value)
((uint64_t)mirror8bit((value >> 56) & 0xff));
}
-/**
- * @brief Parameter k for the Exponential Golomb algorihm to be used.
+/*
+ * Parameter k for the Exponential Golomb algorihm to be used.
*
* The smaller this value, the smaller the minimum bit count for the Exp.
* Golomb generated affixes will be (at lowest index) however for the
@@ -626,28 +642,30 @@ static inline uint64_t mirror64bit(uint64_t value)
* should be small, for a large amount of devices k might be increased
* instead. The default of k=0 should be fine for most users though.
*
- * @b IMPORTANT: In case this ever becomes a runtime parameter; the value of
+ * IMPORTANT: In case this ever becomes a runtime parameter; the value of
* k should not change as long as guest is still running! Because that would
* cause completely different inode numbers to be generated on guest.
*/
#define EXP_GOLOMB_K 0
/**
- * @brief Exponential Golomb algorithm for arbitrary k (including k=0).
+ * expGolombEncode() - Exponential Golomb algorithm for arbitrary k
+ * (including k=0).
+ *
+ * @n: natural number (or index) of the prefix to be generated
+ * (1, 2, 3, ...)
+ * @k: parameter k of Exp. Golomb algorithm to be used
+ * (see comment on EXP_GOLOMB_K macro for details about k)
+ * Return: prefix for given @n and @k
*
- * The Exponential Golomb algorithm generates @b prefixes (@b not suffixes!)
+ * The Exponential Golomb algorithm generates prefixes (NOT suffixes!)
* with growing length and with the mathematical property of being
* "prefix-free". The latter means the generated prefixes can be prepended
* in front of arbitrary numbers and the resulting concatenated numbers are
* guaranteed to be always unique.
*
* This is a minor adjustment to the original Exp. Golomb algorithm in the
- * sense that lowest allowed index (@param n) starts with 1, not with zero.
- *
- * @param n - natural number (or index) of the prefix to be generated
- * (1, 2, 3, ...)
- * @param k - parameter k of Exp. Golomb algorithm to be used
- * (see comment on EXP_GOLOMB_K macro for details about k)
+ * sense that lowest allowed index (@n) starts with 1, not with zero.
*/
static VariLenAffix expGolombEncode(uint64_t n, int k)
{
@@ -661,7 +679,9 @@ static VariLenAffix expGolombEncode(uint64_t n, int k)
}
/**
- * @brief Converts a suffix into a prefix, or a prefix into a suffix.
+ * invertAffix() - Converts a suffix into a prefix, or a prefix into a suffix.
+ * @affix: either suffix or prefix to be inverted
+ * Return: inversion of passed @affix
*
* Simply mirror all bits of the affix value, for the purpose to preserve
* respectively the mathematical "prefix-free" or "suffix-free" property
@@ -685,16 +705,16 @@ static VariLenAffix invertAffix(const VariLenAffix *affix)
}
/**
- * @brief Generates suffix numbers with "suffix-free" property.
+ * affixForIndex() - Generates suffix numbers with "suffix-free" property.
+ * @index: natural number (or index) of the suffix to be generated
+ * (1, 2, 3, ...)
+ * Return: Suffix suitable to assemble unique number.
*
* This is just a wrapper function on top of the Exp. Golomb algorithm.
*
* Since the Exp. Golomb algorithm generates prefixes, but we need suffixes,
* this function converts the Exp. Golomb prefixes into appropriate suffixes
* which are still suitable for generating unique numbers.
- *
- * @param n - natural number (or index) of the suffix to be generated
- * (1, 2, 3, ...)
*/
static VariLenAffix affixForIndex(uint64_t index)
{
@@ -794,8 +814,8 @@ static int qid_inode_prefix_hash_bits(V9fsPDU *pdu, dev_t dev)
return val->prefix_bits;
}
-/**
- * @brief Slow / full mapping host inode nr -> guest inode nr.
+/*
+ * Slow / full mapping host inode nr -> guest inode nr.
*
* This function performs a slower and much more costly remapping of an
* original file inode number on host to an appropriate different inode
@@ -807,7 +827,7 @@ static int qid_inode_prefix_hash_bits(V9fsPDU *pdu, dev_t dev)
* qid_path_suffixmap() failed. In practice this slow / full mapping is not
* expected ever to be used at all though.
*
- * @see qid_path_suffixmap() for details
+ * See qid_path_suffixmap() for details
*
*/
static int qid_path_fullmap(V9fsPDU *pdu, const struct stat *stbuf,
@@ -848,8 +868,8 @@ static int qid_path_fullmap(V9fsPDU *pdu, const struct stat *stbuf,
return 0;
}
-/**
- * @brief Quick mapping host inode nr -> guest inode nr.
+/*
+ * Quick mapping host inode nr -> guest inode nr.
*
* This function performs quick remapping of an original file inode number
* on host to an appropriate different inode number on guest. This remapping
@@ -1265,12 +1285,15 @@ static int coroutine_fn stat_to_v9stat(V9fsPDU *pdu, V9fsPath *path,
/**
- * Convert host filesystem's block size into an appropriate block size for
- * 9p client (guest OS side). The value returned suggests an "optimum" block
- * size for 9p I/O, i.e. to maximize performance.
+ * blksize_to_iounit() - Block size exposed to 9p client.
+ * Return: block size
*
* @pdu: 9p client request
* @blksize: host filesystem's block size
+ *
+ * Convert host filesystem's block size into an appropriate block size for
+ * 9p client (guest OS side). The value returned suggests an "optimum" block
+ * size for 9p I/O, i.e. to maximize performance.
*/
static int32_t blksize_to_iounit(const V9fsPDU *pdu, int32_t blksize)
{
@@ -1309,11 +1332,17 @@ static int stat_to_v9stat_dotl(V9fsPDU *pdu, const struct stat *stbuf,
v9lstat->st_blksize = stat_to_iounit(pdu, stbuf);
v9lstat->st_blocks = stbuf->st_blocks;
v9lstat->st_atime_sec = stbuf->st_atime;
- v9lstat->st_atime_nsec = stbuf->st_atim.tv_nsec;
v9lstat->st_mtime_sec = stbuf->st_mtime;
- v9lstat->st_mtime_nsec = stbuf->st_mtim.tv_nsec;
v9lstat->st_ctime_sec = stbuf->st_ctime;
+#ifdef CONFIG_DARWIN
+ v9lstat->st_atime_nsec = stbuf->st_atimespec.tv_nsec;
+ v9lstat->st_mtime_nsec = stbuf->st_mtimespec.tv_nsec;
+ v9lstat->st_ctime_nsec = stbuf->st_ctimespec.tv_nsec;
+#else
+ v9lstat->st_atime_nsec = stbuf->st_atim.tv_nsec;
+ v9lstat->st_mtime_nsec = stbuf->st_mtim.tv_nsec;
v9lstat->st_ctime_nsec = stbuf->st_ctim.tv_nsec;
+#endif
/* Currently we only support BASIC fields in stat */
v9lstat->st_result_mask = P9_STATS_BASIC;
@@ -2271,7 +2300,7 @@ static int coroutine_fn v9fs_do_readdir_with_stat(V9fsPDU *pdu,
count += len;
v9fs_stat_free(&v9stat);
v9fs_path_free(&path);
- saved_dir_pos = dent->d_off;
+ saved_dir_pos = qemu_dirent_off(dent);
}
v9fs_readdir_unlock(&fidp->fs.dir);
@@ -2376,10 +2405,11 @@ out_nofid:
}
/**
- * Returns size required in Rreaddir response for the passed dirent @p name.
+ * v9fs_readdir_response_size() - Returns size required in Rreaddir response
+ * for the passed dirent @name.
*
- * @param name - directory entry's name (i.e. file name, directory name)
- * @returns required size in bytes
+ * @name: directory entry's name (i.e. file name, directory name)
+ * Return: required size in bytes
*/
size_t v9fs_readdir_response_size(V9fsString *name)
{
@@ -2410,6 +2440,7 @@ static int coroutine_fn v9fs_do_readdir(V9fsPDU *pdu, V9fsFidState *fidp,
V9fsString name;
int len, err = 0;
int32_t count = 0;
+ off_t off;
struct dirent *dent;
struct stat *st;
struct V9fsDirEnt *entries = NULL;
@@ -2470,12 +2501,13 @@ static int coroutine_fn v9fs_do_readdir(V9fsPDU *pdu, V9fsFidState *fidp,
qid.version = 0;
}
+ off = qemu_dirent_off(dent);
v9fs_string_init(&name);
v9fs_string_sprintf(&name, "%s", dent->d_name);
/* 11 = 7 + 4 (7 = start offset, 4 = space for storing count) */
len = pdu_marshal(pdu, 11 + count, "Qqbs",
- &qid, dent->d_off,
+ &qid, off,
dent->d_type, &name);
v9fs_string_free(&name);
@@ -3515,9 +3547,15 @@ 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
+ fsid_val = (unsigned int)stbuf->f_fsid.val[0] |
+ (unsigned long long)stbuf->f_fsid.val[1] << 32;
+ f_namelen = NAME_MAX;
+#else
fsid_val = (unsigned int) stbuf->f_fsid.__val[0] |
(unsigned long long)stbuf->f_fsid.__val[1] << 32;
f_namelen = stbuf->f_namelen;
+#endif
return pdu_marshal(pdu, offset, "ddqqqqqqd",
f_type, f_bsize, f_blocks, f_bfree,
@@ -3919,7 +3957,7 @@ static void coroutine_fn v9fs_xattrcreate(void *opaque)
rflags |= XATTR_REPLACE;
}
- if (size > XATTR_SIZE_MAX) {
+ if (size > P9_XATTR_SIZE_MAX) {
err = -E2BIG;
goto out_nofid;
}