diff --git a/fs/fuse/virtio_fs.c b/fs/fuse/virtio_fs.c index 4f334766b8c3..674fd784cdb8 100644 --- a/fs/fuse/virtio_fs.c +++ b/fs/fuse/virtio_fs.c @@ -455,26 +455,23 @@ static int virtio_fs_add_instance(struct virtio_device *vdev, return ret; } -/* Return the virtio_fs with a given tag, or NULL */ +/* Return the virtio_fs with a given tag, or NULL. + * Callers hold virtio_fs_mutex, which also keeps the virtqueues alive. + */ static struct virtio_fs *virtio_fs_find_instance(const char *tag) { struct virtio_fs *fs; - mutex_lock(&virtio_fs_mutex); + lockdep_assert_held(&virtio_fs_mutex); list_for_each_entry(fs, &virtio_fs_instances, list) { if (strcmp(fs->tag, tag) == 0) { kobject_get(&fs->kobj); - goto found; + return fs; } } - fs = NULL; /* not found */ - -found: - mutex_unlock(&virtio_fs_mutex); - - return fs; + return NULL; /* not found */ } static void virtio_fs_free_devs(struct virtio_fs *fs) @@ -1700,13 +1697,17 @@ static int virtio_fs_get_tree(struct fs_context *fsc) * in chan->iq->priv. Once fuse_conn is going away, it calls ->put() * to drop the reference to this object. */ + mutex_lock(&virtio_fs_mutex); fs = virtio_fs_find_instance(fsc->source); + if (fs) + virtqueue_size = virtqueue_get_vring_size(fs->vqs[VQ_REQUEST].vq); + mutex_unlock(&virtio_fs_mutex); + if (!fs) { pr_info("virtio-fs: tag <%s> not found\n", fsc->source); return -EINVAL; } - virtqueue_size = virtqueue_get_vring_size(fs->vqs[VQ_REQUEST].vq); if (WARN_ON(virtqueue_size <= FUSE_HEADER_OVERHEAD)) goto out_err;