Obvious leak, which cannot detected unless you try to unload
fuse module. Found accidentally searching for reasons why
fuse_dev_find_request take 7% of cpu in profiles.

Also, make it in more optimal way, fget() is too expensive and
well seen on profiles, there is lighter way relying on rcu protection.

Signed-off-by: Alexey Kuznetsov <kuz...@virtuozzo.com>
Acked-by:: Liu Kui <kui....@virtuozzo.com>
---
 fs/fuse/dev.c | 20 +++++++++++++++++---
 1 file changed, 17 insertions(+), 3 deletions(-)

diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index f5594e4..1db40f0 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -19,6 +19,7 @@
 #include <linux/slab.h>
 #include <linux/pipe_fs_i.h>
 #include <linux/swap.h>
+#include <linux/fdtable.h>
 #include <linux/splice.h>
 #include <linux/sched.h>
 
@@ -2678,16 +2679,29 @@ int fuse_dev_release(struct inode *inode, struct file 
*file)
 
 struct fuse_req *fuse_dev_find_request(int fd, u64 unique)
 {
-       struct file *f = fget(fd);
-       struct fuse_dev *fud = fuse_get_dev(f);
-       struct fuse_pqueue *fpq = &fud->pq;
+       struct file * file;
+       struct fuse_dev *fud;
+       struct fuse_pqueue *fpq;
        struct fuse_req *req = NULL;
 
+       rcu_read_lock();
+       file = files_lookup_fd_rcu(current->files, fd);
+       if (!file)
+               goto out;
+
+       if (file->f_op != &fuse_dev_operations)
+               goto out;
+
+       fud = fuse_get_dev(file);
+       fpq = &fud->pq;
+
        spin_lock(&fpq->lock);
        if (fpq->connected)
                req = request_find(&fud->pq, unique);
        spin_unlock(&fpq->lock);
 
+out:
+       rcu_read_unlock();
        return req;
 }
 EXPORT_SYMBOL_GPL(fuse_dev_find_request);
-- 
1.8.3.1

_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to