aboutsummaryrefslogtreecommitdiff
path: root/hw/9pfs/9p.h
diff options
context:
space:
mode:
authorChristian Schoenebeck <qemu_oss@crudebyte.com>2019-10-07 17:02:45 +0200
committerGreg Kurz <groug@kaod.org>2019-10-10 11:36:23 +0200
commit6b6aa8285d7ecc172ed59903bb61f26c19ba2538 (patch)
treed4705bbc262e7c218c60b13fef30361fd07ae776 /hw/9pfs/9p.h
parentf3fe4a2d92bb4ee5b599b8b1eb781b2ae68af36c (diff)
9p: Use variable length suffixes for inode remapping
Use variable length suffixes for inode remapping instead of the fixed 16 bit size prefixes before. With this change the inode numbers on guest will typically be much smaller (e.g. around >2^1 .. >2^7 instead of >2^48 with the previous fixed size inode remapping. Additionally this solution is more efficient, since inode numbers in practice can take almost their entire 64 bit range on guest as well, so there is less likely a need for generating and tracking additional suffixes, which might also be beneficial for nested virtualization where each level of virtualization would shift up the inode bits and increase the chance of expensive remapping actions. The "Exponential Golomb" algorithm is used as basis for generating the variable length suffixes. The algorithm has a parameter k which controls the distribution of bits on increasing indeces (minimum bits at low index vs. maximum bits at high index). With k=0 the generated suffixes look like: Index Dec/Bin -> Generated Suffix Bin 1 [1] -> [1] (1 bits) 2 [10] -> [010] (3 bits) 3 [11] -> [110] (3 bits) 4 [100] -> [00100] (5 bits) 5 [101] -> [10100] (5 bits) 6 [110] -> [01100] (5 bits) 7 [111] -> [11100] (5 bits) 8 [1000] -> [0001000] (7 bits) 9 [1001] -> [1001000] (7 bits) 10 [1010] -> [0101000] (7 bits) 11 [1011] -> [1101000] (7 bits) 12 [1100] -> [0011000] (7 bits) ... 65533 [1111111111111101] -> [1011111111111111000000000000000] (31 bits) 65534 [1111111111111110] -> [0111111111111111000000000000000] (31 bits) 65535 [1111111111111111] -> [1111111111111111000000000000000] (31 bits) Hence minBits=1 maxBits=31 And with k=5 they would look like: Index Dec/Bin -> Generated Suffix Bin 1 [1] -> [000001] (6 bits) 2 [10] -> [100001] (6 bits) 3 [11] -> [010001] (6 bits) 4 [100] -> [110001] (6 bits) 5 [101] -> [001001] (6 bits) 6 [110] -> [101001] (6 bits) 7 [111] -> [011001] (6 bits) 8 [1000] -> [111001] (6 bits) 9 [1001] -> [000101] (6 bits) 10 [1010] -> [100101] (6 bits) 11 [1011] -> [010101] (6 bits) 12 [1100] -> [110101] (6 bits) ... 65533 [1111111111111101] -> [0011100000000000100000000000] (28 bits) 65534 [1111111111111110] -> [1011100000000000100000000000] (28 bits) 65535 [1111111111111111] -> [0111100000000000100000000000] (28 bits) Hence minBits=6 maxBits=28 Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com> Signed-off-by: Greg Kurz <groug@kaod.org>
Diffstat (limited to 'hw/9pfs/9p.h')
-rw-r--r--hw/9pfs/9p.h44
1 files changed, 41 insertions, 3 deletions
diff --git a/hw/9pfs/9p.h b/hw/9pfs/9p.h
index 35a362c0d7..3904f82901 100644
--- a/hw/9pfs/9p.h
+++ b/hw/9pfs/9p.h
@@ -236,13 +236,49 @@ struct V9fsFidState
V9fsFidState *rclm_lst;
};
-#define QPATH_INO_MASK ((1ULL << 48) - 1)
+typedef enum AffixType_t {
+ AffixType_Prefix,
+ AffixType_Suffix, /* A.k.a. postfix. */
+} AffixType_t;
+
+/**
+ * @brief Unique affix of variable length.
+ *
+ * An affix is (currently) either a suffix or a prefix, which is either
+ * going to be prepended (prefix) or appended (suffix) with some other
+ * number for the goal to generate unique numbers. Accordingly the
+ * suffixes (or prefixes) we generate @b must all have the mathematical
+ * property of being suffix-free (or prefix-free in case of prefixes)
+ * so that no matter what number we concatenate the affix with, that we
+ * always reliably get unique numbers as result after concatenation.
+ */
+typedef struct VariLenAffix {
+ AffixType_t type; /* Whether this affix is a suffix or a prefix. */
+ uint64_t value; /* Actual numerical value of this affix. */
+ /*
+ * Lenght of the affix, that is how many (of the lowest) bits of @c value
+ * must be used for appending/prepending this affix to its final resulting,
+ * unique number.
+ */
+ int bits;
+} VariLenAffix;
+
+/* See qid_inode_prefix_hash_bits(). */
+typedef struct {
+ dev_t dev; /* FS device on host. */
+ /*
+ * How many (high) bits of the original inode number shall be used for
+ * hashing.
+ */
+ int prefix_bits;
+} QpdEntry;
/* QID path prefix entry, see stat_to_qid */
typedef struct {
dev_t dev;
uint16_t ino_prefix;
- uint16_t qp_prefix;
+ uint32_t qp_affix_index;
+ VariLenAffix qp_affix;
} QppEntry;
/* QID path full entry, as above */
@@ -274,9 +310,11 @@ struct V9fsState
V9fsConf fsconf;
V9fsQID root_qid;
dev_t dev_id;
+ struct qht qpd_table;
struct qht qpp_table;
struct qht qpf_table;
- uint16_t qp_prefix_next;
+ uint64_t qp_ndevices; /* Amount of entries in qpd_table. */
+ uint16_t qp_affix_next;
uint64_t qp_fullpath_next;
};