From nobody Tue Feb 10 01:33:06 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1518113566901889.3693246235903; Thu, 8 Feb 2018 10:12:46 -0800 (PST) Received: from localhost ([::1]:58861 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ejqgd-0005j8-Kl for importer@patchew.org; Thu, 08 Feb 2018 13:12:43 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:35538) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ejqU0-0002Sm-CM for qemu-devel@nongnu.org; Thu, 08 Feb 2018 12:59:41 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ejqTw-0006sd-8x for qemu-devel@nongnu.org; Thu, 08 Feb 2018 12:59:40 -0500 Received: from lhrrgout.huawei.com ([194.213.3.17]:43313 helo=huawei.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ejqTw-0006rC-01 for qemu-devel@nongnu.org; Thu, 08 Feb 2018 12:59:36 -0500 Received: from lhreml704-cah.china.huawei.com (unknown [172.18.7.107]) by Forcepoint Email with ESMTP id 8E3072CBA0887; Thu, 8 Feb 2018 17:59:30 +0000 (GMT) Received: from localhost.localdomain (10.204.62.86) by lhreml704-cah.china.huawei.com (10.201.108.45) with Microsoft SMTP Server id 14.3.361.1; Thu, 8 Feb 2018 17:59:23 +0000 From: To: , Date: Thu, 8 Feb 2018 19:00:18 +0100 Message-ID: <20180208180019.13683-4-antonios.motakis@huawei.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20180208180019.13683-1-antonios.motakis@huawei.com> References: <20180208180019.13683-1-antonios.motakis@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.204.62.86] X-CFilter-Loop: Reflected X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 194.213.3.17 Subject: [Qemu-devel] [PATCH 3/4] 9pfs: stat_to_qid: use device as input to qid.path X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: veaceslav.falico@huawei.com, Eduard.Shishkin@huawei.com, andy.wangguoli@huawei.com, cota@braap.org, Antonios Motakis , Jani.Kokkonen@huawei.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Antonios Motakis To support multiple devices on the 9p share, and avoid qid path collisions we take the device id as input to generate a unique QID path. The lowest 48 bits of the path will be set equal to the file inode, and the top bits will be uniquely assigned based on the top 16 bits of the inode and the device id. Signed-off-by: Antonios Motakis --- hw/9pfs/9p.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++---= ---- hw/9pfs/9p.h | 13 ++++++++- 2 files changed, 90 insertions(+), 11 deletions(-) diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c index 4da858f..f434f05 100644 --- a/hw/9pfs/9p.c +++ b/hw/9pfs/9p.c @@ -25,6 +25,8 @@ #include "trace.h" #include "migration/blocker.h" #include "sysemu/qtest.h" +#include "exec/tb-hash-xx.h" +#include "qemu/qht.h" =20 int open_fd_hw; int total_open_fd; @@ -572,20 +574,82 @@ static void coroutine_fn virtfs_reset(V9fsPDU *pdu) P9_STAT_MODE_NAMED_PIPE | \ P9_STAT_MODE_SOCKET) =20 -/* This is the algorithm from ufs in spfs */ + +/* creative abuse of tb_hash_func7, which is based on xxhash */ +static uint32_t qpp_hash(QppEntry e) +{ + return tb_hash_func7(e.ino_prefix, e.dev, 0, 0, 0); +} + +static bool qpp_lookup_func(const void *obj, const void *userp) +{ + const QppEntry *e1 =3D obj, *e2 =3D userp; + return (e1->dev =3D=3D e2->dev) && (e1->ino_prefix =3D=3D e2->ino_pref= ix); +} + +static void qpp_table_remove(struct qht *ht, void *p, uint32_t h, void *up) +{ + g_free(p); +} + +static void qpp_table_destroy(struct qht *ht) +{ + qht_iter(ht, qpp_table_remove, NULL); + qht_destroy(ht); +} + +/* stat_to_qid needs to map inode number (64 bits) and device id (32 bits) + * to a unique QID path (64 bits). To avoid having to map and keep track + * of up to 2^64 objects, we map only the 16 highest bits of the inode plus + * the device id to the 16 highest bits of the QID path. The 48 lowest bits + * of the QID path equal to the lowest bits of the inode number. + * + * This takes advantage of the fact that inode number are usually not + * random but allocated sequentially, so we have fewer items to keep + * track of. + */ +static int qid_path_prefixmap(V9fsPDU *pdu, const struct stat *stbuf, + uint64_t *path) +{ + QppEntry lookup =3D { + .dev =3D stbuf->st_dev, + .ino_prefix =3D (uint16_t) (stbuf->st_ino >> 48) + }, *val; + uint32_t hash =3D qpp_hash(lookup); + + val =3D qht_lookup(&pdu->s->qpp_table, qpp_lookup_func, &lookup, hash); + + if (!val) { + if (pdu->s->qp_prefix_next =3D=3D 0) { + /* we ran out of prefixes */ + return -ENFILE; + } + + val =3D g_malloc0(sizeof(QppEntry)); + if (!val) { + return -ENOMEM; + } + *val =3D lookup; + + /* new unique inode prefix and device combo */ + val->qp_prefix =3D pdu->s->qp_prefix_next++; + qht_insert(&pdu->s->qpp_table, val, hash); + } + + *path =3D ((uint64_t)val->qp_prefix << 48) | (stbuf->st_ino & QPATH_IN= O_MASK); + return 0; +} + static int stat_to_qid(V9fsPDU *pdu, const struct stat *stbuf, V9fsQID *qi= dp) { - size_t size; + int err; =20 - if (pdu->s->dev_id =3D=3D 0) { - pdu->s->dev_id =3D stbuf->st_dev; - } else if (pdu->s->dev_id !=3D stbuf->st_dev) { - return -ENOSYS; + /* map inode+device to qid path (fast path) */ + err =3D qid_path_prefixmap(pdu, stbuf, &qidp->path); + if (err) { + return err; } =20 - memset(&qidp->path, 0, sizeof(qidp->path)); - size =3D MIN(sizeof(stbuf->st_ino), sizeof(qidp->path)); - memcpy(&qidp->path, &stbuf->st_ino, size); qidp->version =3D stbuf->st_mtime ^ (stbuf->st_size << 8); qidp->type =3D 0; if (S_ISDIR(stbuf->st_mode)) { @@ -3626,7 +3690,9 @@ int v9fs_device_realize_common(V9fsState *s, const V9= fsTransport *t, goto out; } =20 - s->dev_id =3D 0; + /* QID path hash table. 1 entry ought to be enough for anybody ;) */ + qht_init(&s->qpp_table, 1, QHT_MODE_AUTO_RESIZE); + s->qp_prefix_next =3D 1; /* reserve 0 to detect overflow */ =20 s->ctx.fst =3D &fse->fst; fsdev_throttle_init(s->ctx.fst); @@ -3641,6 +3707,7 @@ out: } g_free(s->tag); g_free(s->ctx.fs_root); + qpp_table_destroy(&s->qpp_table); v9fs_path_free(&path); } return rc; @@ -3653,6 +3720,7 @@ void v9fs_device_unrealize_common(V9fsState *s, Error= **errp) } fsdev_throttle_cleanup(s->ctx.fst); g_free(s->tag); + qpp_table_destroy(&s->qpp_table); g_free(s->ctx.fs_root); } =20 diff --git a/hw/9pfs/9p.h b/hw/9pfs/9p.h index afb4ebd..80428f7 100644 --- a/hw/9pfs/9p.h +++ b/hw/9pfs/9p.h @@ -8,6 +8,7 @@ #include "fsdev/9p-iov-marshal.h" #include "qemu/thread.h" #include "qemu/coroutine.h" +#include "qemu/qht.h" =20 enum { P9_TLERROR =3D 6, @@ -231,6 +232,15 @@ struct V9fsFidState V9fsFidState *rclm_lst; }; =20 +#define QPATH_INO_MASK (((unsigned long)1 << 48) - 1) + +/* QID path prefix entry, see stat_to_qid */ +typedef struct { + dev_t dev; + uint16_t ino_prefix; + uint16_t qp_prefix; +} QppEntry; + struct V9fsState { QLIST_HEAD(, V9fsPDU) free_list; @@ -252,7 +262,8 @@ struct V9fsState Error *migration_blocker; V9fsConf fsconf; V9fsQID root_qid; - dev_t dev_id; + struct qht qpp_table; + uint16_t qp_prefix_next; }; =20 /* 9p2000.L open flags */ --=20 1.8.3.1