dcavalca / rpms / qemu

Forked from rpms/qemu a year ago
Clone

Blame 0083-virtiofsd-passthrough_ll-use-hashtable.patch

1d442b
From: Miklos Szeredi <mszeredi@redhat.com>
1d442b
Date: Mon, 27 Jan 2020 19:01:52 +0000
1d442b
Subject: [PATCH] virtiofsd: passthrough_ll: use hashtable
1d442b
MIME-Version: 1.0
1d442b
Content-Type: text/plain; charset=UTF-8
1d442b
Content-Transfer-Encoding: 8bit
1d442b
1d442b
Improve performance of inode lookup by using a hash table.
1d442b
1d442b
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
1d442b
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
1d442b
Signed-off-by: Liu Bo <bo.liu@linux.alibaba.com>
1d442b
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
1d442b
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
1d442b
(cherry picked from commit bfc50a6e06b10b2f9dbaf6c1a89dd523322e016f)
1d442b
---
1d442b
 tools/virtiofsd/passthrough_ll.c | 81 ++++++++++++++++++--------------
1d442b
 1 file changed, 45 insertions(+), 36 deletions(-)
1d442b
1d442b
diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c
1d442b
index b40f2874a7..b176a314d6 100644
1d442b
--- a/tools/virtiofsd/passthrough_ll.c
1d442b
+++ b/tools/virtiofsd/passthrough_ll.c
1d442b
@@ -84,13 +84,15 @@ struct lo_map {
1d442b
     ssize_t freelist;
1d442b
 };
1d442b
 
1d442b
+struct lo_key {
1d442b
+    ino_t ino;
1d442b
+    dev_t dev;
1d442b
+};
1d442b
+
1d442b
 struct lo_inode {
1d442b
-    struct lo_inode *next; /* protected by lo->mutex */
1d442b
-    struct lo_inode *prev; /* protected by lo->mutex */
1d442b
     int fd;
1d442b
     bool is_symlink;
1d442b
-    ino_t ino;
1d442b
-    dev_t dev;
1d442b
+    struct lo_key key;
1d442b
     uint64_t refcount; /* protected by lo->mutex */
1d442b
     fuse_ino_t fuse_ino;
1d442b
 };
1d442b
@@ -119,7 +121,8 @@ struct lo_data {
1d442b
     int timeout_set;
1d442b
     int readdirplus_set;
1d442b
     int readdirplus_clear;
1d442b
-    struct lo_inode root; /* protected by lo->mutex */
1d442b
+    struct lo_inode root;
1d442b
+    GHashTable *inodes; /* protected by lo->mutex */
1d442b
     struct lo_map ino_map; /* protected by lo->mutex */
1d442b
     struct lo_map dirp_map; /* protected by lo->mutex */
1d442b
     struct lo_map fd_map; /* protected by lo->mutex */
1d442b
@@ -573,7 +576,7 @@ retry:
1d442b
         }
1d442b
         goto fail_unref;
1d442b
     }
1d442b
-    if (stat.st_dev != inode->dev || stat.st_ino != inode->ino) {
1d442b
+    if (stat.st_dev != inode->key.dev || stat.st_ino != inode->key.ino) {
1d442b
         if (!retries) {
1d442b
             fuse_log(FUSE_LOG_WARNING,
1d442b
                      "%s: failed to match last\n", __func__);
1d442b
@@ -753,19 +756,20 @@ out_err:
1d442b
 static struct lo_inode *lo_find(struct lo_data *lo, struct stat *st)
1d442b
 {
1d442b
     struct lo_inode *p;
1d442b
-    struct lo_inode *ret = NULL;
1d442b
+    struct lo_key key = {
1d442b
+        .ino = st->st_ino,
1d442b
+        .dev = st->st_dev,
1d442b
+    };
1d442b
 
1d442b
     pthread_mutex_lock(&lo->mutex);
1d442b
-    for (p = lo->root.next; p != &lo->root; p = p->next) {
1d442b
-        if (p->ino == st->st_ino && p->dev == st->st_dev) {
1d442b
-            assert(p->refcount > 0);
1d442b
-            ret = p;
1d442b
-            ret->refcount++;
1d442b
-            break;
1d442b
-        }
1d442b
+    p = g_hash_table_lookup(lo->inodes, &key);
1d442b
+    if (p) {
1d442b
+        assert(p->refcount > 0);
1d442b
+        p->refcount++;
1d442b
     }
1d442b
     pthread_mutex_unlock(&lo->mutex);
1d442b
-    return ret;
1d442b
+
1d442b
+    return p;
1d442b
 }
1d442b
 
1d442b
 static int lo_do_lookup(fuse_req_t req, fuse_ino_t parent, const char *name,
1d442b
@@ -810,8 +814,6 @@ static int lo_do_lookup(fuse_req_t req, fuse_ino_t parent, const char *name,
1d442b
         close(newfd);
1d442b
         newfd = -1;
1d442b
     } else {
1d442b
-        struct lo_inode *prev, *next;
1d442b
-
1d442b
         saverr = ENOMEM;
1d442b
         inode = calloc(1, sizeof(struct lo_inode));
1d442b
         if (!inode) {
1d442b
@@ -822,17 +824,12 @@ static int lo_do_lookup(fuse_req_t req, fuse_ino_t parent, const char *name,
1d442b
         inode->refcount = 1;
1d442b
         inode->fd = newfd;
1d442b
         newfd = -1;
1d442b
-        inode->ino = e->attr.st_ino;
1d442b
-        inode->dev = e->attr.st_dev;
1d442b
+        inode->key.ino = e->attr.st_ino;
1d442b
+        inode->key.dev = e->attr.st_dev;
1d442b
 
1d442b
         pthread_mutex_lock(&lo->mutex);
1d442b
         inode->fuse_ino = lo_add_inode_mapping(req, inode);
1d442b
-        prev = &lo->root;
1d442b
-        next = prev->next;
1d442b
-        next->prev = inode;
1d442b
-        inode->next = next;
1d442b
-        inode->prev = prev;
1d442b
-        prev->next = inode;
1d442b
+        g_hash_table_insert(lo->inodes, &inode->key, inode);
1d442b
         pthread_mutex_unlock(&lo->mutex);
1d442b
     }
1d442b
     e->ino = inode->fuse_ino;
1d442b
@@ -1162,14 +1159,8 @@ static void unref_inode_lolocked(struct lo_data *lo, struct lo_inode *inode,
1d442b
     assert(inode->refcount >= n);
1d442b
     inode->refcount -= n;
1d442b
     if (!inode->refcount) {
1d442b
-        struct lo_inode *prev, *next;
1d442b
-
1d442b
-        prev = inode->prev;
1d442b
-        next = inode->next;
1d442b
-        next->prev = prev;
1d442b
-        prev->next = next;
1d442b
-
1d442b
         lo_map_remove(&lo->ino_map, inode->fuse_ino);
1d442b
+        g_hash_table_remove(lo->inodes, &inode->key);
1d442b
         pthread_mutex_unlock(&lo->mutex);
1d442b
         close(inode->fd);
1d442b
         free(inode);
1d442b
@@ -1369,7 +1360,7 @@ static void lo_do_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
1d442b
 
1d442b
         /* Hide root's parent directory */
1d442b
         if (dinode == &lo->root && strcmp(name, "..") == 0) {
1d442b
-            e.attr.st_ino = lo->root.ino;
1d442b
+            e.attr.st_ino = lo->root.key.ino;
1d442b
             e.attr.st_mode = DT_DIR << 12;
1d442b
         }
1d442b
 
1d442b
@@ -2370,11 +2361,26 @@ static void setup_root(struct lo_data *lo, struct lo_inode *root)
1d442b
 
1d442b
     root->is_symlink = false;
1d442b
     root->fd = fd;
1d442b
-    root->ino = stat.st_ino;
1d442b
-    root->dev = stat.st_dev;
1d442b
+    root->key.ino = stat.st_ino;
1d442b
+    root->key.dev = stat.st_dev;
1d442b
     root->refcount = 2;
1d442b
 }
1d442b
 
1d442b
+static guint lo_key_hash(gconstpointer key)
1d442b
+{
1d442b
+    const struct lo_key *lkey = key;
1d442b
+
1d442b
+    return (guint)lkey->ino + (guint)lkey->dev;
1d442b
+}
1d442b
+
1d442b
+static gboolean lo_key_equal(gconstpointer a, gconstpointer b)
1d442b
+{
1d442b
+    const struct lo_key *la = a;
1d442b
+    const struct lo_key *lb = b;
1d442b
+
1d442b
+    return la->ino == lb->ino && la->dev == lb->dev;
1d442b
+}
1d442b
+
1d442b
 int main(int argc, char *argv[])
1d442b
 {
1d442b
     struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
1d442b
@@ -2392,7 +2398,7 @@ int main(int argc, char *argv[])
1d442b
     umask(0);
1d442b
 
1d442b
     pthread_mutex_init(&lo.mutex, NULL);
1d442b
-    lo.root.next = lo.root.prev = &lo.root;
1d442b
+    lo.inodes = g_hash_table_new(lo_key_hash, lo_key_equal);
1d442b
     lo.root.fd = -1;
1d442b
     lo.root.fuse_ino = FUSE_ROOT_ID;
1d442b
     lo.cache = CACHE_AUTO;
1d442b
@@ -2522,6 +2528,9 @@ err_out2:
1d442b
 err_out1:
1d442b
     fuse_opt_free_args(&args);
1d442b
 
1d442b
+    if (lo.inodes) {
1d442b
+        g_hash_table_destroy(lo.inodes);
1d442b
+    }
1d442b
     lo_map_destroy(&lo.fd_map);
1d442b
     lo_map_destroy(&lo.dirp_map);
1d442b
     lo_map_destroy(&lo.ino_map);